Uncodegen OWSDisappearingMessagesConfiguration
This commit is contained in:
parent
10185bd436
commit
7d25c4ec12
@ -17,8 +17,6 @@
|
||||
"properties_to_ignore": [
|
||||
"TSYapDatabaseObject.grdbId",
|
||||
"OWSDynamicOutgoingMessage.block",
|
||||
"OWSDisappearingMessagesConfiguration.originalDictionaryValue",
|
||||
"OWSDisappearingMessagesConfiguration.newRecord",
|
||||
"TSThread.isArchivedByLegacyTimestampForSorting",
|
||||
"TSContactThread.contactThreadSchemaVersion",
|
||||
"TSCall.callSchemaVersion",
|
||||
@ -113,9 +111,7 @@
|
||||
"TSIncomingMessage.read": "wasRead",
|
||||
"TSCall.read": "wasRead",
|
||||
"OWSGroupCallMessage.read": "wasRead",
|
||||
"TSIncomingMessage.viewed": "wasViewed",
|
||||
"OWSDisappearingMessagesConfiguration.enabled": "isEnabled",
|
||||
"OWSDisappearingMessagesConfiguration.newRecord": "isNewRecord"
|
||||
"TSIncomingMessage.viewed": "wasViewed"
|
||||
},
|
||||
"custom_column_names": {
|
||||
"TSInteraction.uniqueThreadId": "threadUniqueId",
|
||||
|
||||
@ -30,9 +30,6 @@
|
||||
"AttachmentRecord.uploadTimestamp": 23,
|
||||
"AttachmentRecord.videoDuration": 28,
|
||||
"BaseModel": 56,
|
||||
"DisappearingMessagesConfigurationRecord.durationSeconds": 1,
|
||||
"DisappearingMessagesConfigurationRecord.enabled": 2,
|
||||
"DisappearingMessagesConfigurationRecord.timerVersion": 3,
|
||||
"InstalledStickerRecord.contentType": 3,
|
||||
"InstalledStickerRecord.emojiString": 1,
|
||||
"InstalledStickerRecord.info": 2,
|
||||
|
||||
@ -3688,11 +3688,9 @@
|
||||
F9C5CCA4289453B300548EEE /* SSKProto+OWS.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9B9289453B100548EEE /* SSKProto+OWS.swift */; };
|
||||
F9C5CCAC289453B300548EEE /* PreKeyManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9C2289453B100548EEE /* PreKeyManager.swift */; };
|
||||
F9C5CCB0289453B300548EEE /* RemoteAttestation.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9C7289453B100548EEE /* RemoteAttestation.swift */; };
|
||||
F9C5CCB9289453B300548EEE /* OWSDisappearingMessagesConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = F9C5C9D1289453B100548EEE /* OWSDisappearingMessagesConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
F9C5CCBA289453B300548EEE /* TSThread.h in Headers */ = {isa = PBXBuildFile; fileRef = F9C5C9D2289453B100548EEE /* TSThread.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
F9C5CCC0289453B300548EEE /* ContactDiscoveryTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9D9289453B100548EEE /* ContactDiscoveryTask.swift */; };
|
||||
F9C5CCC3289453B300548EEE /* ContactDiscoveryError.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9DC289453B100548EEE /* ContactDiscoveryError.swift */; };
|
||||
F9C5CCC4289453B300548EEE /* OWSDisappearingMessagesConfiguration+SDS.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9DD289453B100548EEE /* OWSDisappearingMessagesConfiguration+SDS.swift */; };
|
||||
F9C5CCC5289453B300548EEE /* SignalAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9DE289453B100548EEE /* SignalAccount.swift */; };
|
||||
F9C5CCC8289453B300548EEE /* SignalRecipient.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9E1289453B100548EEE /* SignalRecipient.swift */; };
|
||||
F9C5CCCA289453B300548EEE /* TSPrivateStoryThread+SDS.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9E4289453B100548EEE /* TSPrivateStoryThread+SDS.swift */; };
|
||||
@ -3708,9 +3706,8 @@
|
||||
F9C5CCD4289453B300548EEE /* TSContactThread.m in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9EE289453B100548EEE /* TSContactThread.m */; };
|
||||
F9C5CCD5289453B300548EEE /* TSGroupThread+OWS.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9EF289453B100548EEE /* TSGroupThread+OWS.swift */; };
|
||||
F9C5CCD6289453B300548EEE /* PhoneNumberUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9F0289453B100548EEE /* PhoneNumberUtil.swift */; };
|
||||
F9C5CCD7289453B300548EEE /* OWSDisappearingMessagesConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9F1289453B100548EEE /* OWSDisappearingMessagesConfiguration.m */; };
|
||||
F9C5CCD8289453B300548EEE /* ThreadAssociatedData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9F2289453B100548EEE /* ThreadAssociatedData.swift */; };
|
||||
F9C5CCDA289453B300548EEE /* OWSDisappearingMessagesConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9F4289453B100548EEE /* OWSDisappearingMessagesConfiguration.swift */; };
|
||||
F9C5CCDA289453B300548EEE /* DisappearingMessagesConfigurationRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9F4289453B100548EEE /* DisappearingMessagesConfigurationRecord.swift */; };
|
||||
F9C5CCDD289453B300548EEE /* SignalAccountFinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9F7289453B100548EEE /* SignalAccountFinder.swift */; };
|
||||
F9C5CCDE289453B300548EEE /* TSThread.m in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9F8289453B100548EEE /* TSThread.m */; };
|
||||
F9C5CCDF289453B300548EEE /* TSThread+SDS.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9F9289453B100548EEE /* TSThread+SDS.swift */; };
|
||||
@ -7888,11 +7885,9 @@
|
||||
F9C5C9B9289453B100548EEE /* SSKProto+OWS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SSKProto+OWS.swift"; sourceTree = "<group>"; };
|
||||
F9C5C9C2289453B100548EEE /* PreKeyManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreKeyManager.swift; sourceTree = "<group>"; };
|
||||
F9C5C9C7289453B100548EEE /* RemoteAttestation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RemoteAttestation.swift; sourceTree = "<group>"; };
|
||||
F9C5C9D1289453B100548EEE /* OWSDisappearingMessagesConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSDisappearingMessagesConfiguration.h; sourceTree = "<group>"; };
|
||||
F9C5C9D2289453B100548EEE /* TSThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSThread.h; sourceTree = "<group>"; };
|
||||
F9C5C9D9289453B100548EEE /* ContactDiscoveryTask.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactDiscoveryTask.swift; sourceTree = "<group>"; };
|
||||
F9C5C9DC289453B100548EEE /* ContactDiscoveryError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactDiscoveryError.swift; sourceTree = "<group>"; };
|
||||
F9C5C9DD289453B100548EEE /* OWSDisappearingMessagesConfiguration+SDS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "OWSDisappearingMessagesConfiguration+SDS.swift"; sourceTree = "<group>"; };
|
||||
F9C5C9DE289453B100548EEE /* SignalAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignalAccount.swift; sourceTree = "<group>"; };
|
||||
F9C5C9E1289453B100548EEE /* SignalRecipient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignalRecipient.swift; sourceTree = "<group>"; };
|
||||
F9C5C9E4289453B100548EEE /* TSPrivateStoryThread+SDS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "TSPrivateStoryThread+SDS.swift"; sourceTree = "<group>"; };
|
||||
@ -7908,9 +7903,8 @@
|
||||
F9C5C9EE289453B100548EEE /* TSContactThread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSContactThread.m; sourceTree = "<group>"; };
|
||||
F9C5C9EF289453B100548EEE /* TSGroupThread+OWS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "TSGroupThread+OWS.swift"; sourceTree = "<group>"; };
|
||||
F9C5C9F0289453B100548EEE /* PhoneNumberUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhoneNumberUtil.swift; sourceTree = "<group>"; };
|
||||
F9C5C9F1289453B100548EEE /* OWSDisappearingMessagesConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSDisappearingMessagesConfiguration.m; sourceTree = "<group>"; };
|
||||
F9C5C9F2289453B100548EEE /* ThreadAssociatedData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThreadAssociatedData.swift; sourceTree = "<group>"; };
|
||||
F9C5C9F4289453B100548EEE /* OWSDisappearingMessagesConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSDisappearingMessagesConfiguration.swift; sourceTree = "<group>"; };
|
||||
F9C5C9F4289453B100548EEE /* DisappearingMessagesConfigurationRecord.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DisappearingMessagesConfigurationRecord.swift; sourceTree = "<group>"; };
|
||||
F9C5C9F7289453B100548EEE /* SignalAccountFinder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignalAccountFinder.swift; sourceTree = "<group>"; };
|
||||
F9C5C9F8289453B100548EEE /* TSThread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSThread.m; sourceTree = "<group>"; };
|
||||
F9C5C9F9289453B100548EEE /* TSThread+SDS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "TSThread+SDS.swift"; sourceTree = "<group>"; };
|
||||
@ -14693,6 +14687,7 @@
|
||||
5096BE642AF3514800668F9F /* ContactSyncAttachmentBuilder.swift */,
|
||||
5077B5B72BBC7FE600EF399E /* ContactTest.swift */,
|
||||
F9C5C9FB289453B100548EEE /* ContactThreadFinder.swift */,
|
||||
F9C5C9F4289453B100548EEE /* DisappearingMessagesConfigurationRecord.swift */,
|
||||
50A40ED22B88005A0060C5A5 /* DisplayName.swift */,
|
||||
5003BB42299F034D0037159B /* E164.swift */,
|
||||
342FFE822721D4B6000AC89F /* FetchedSystemContacts.swift */,
|
||||
@ -14700,10 +14695,6 @@
|
||||
50086B9B29DF5CB100F9C072 /* NameResolver.swift */,
|
||||
4C6E446822AEDDEE007982E6 /* NewAccountDiscovery.swift */,
|
||||
3498A0A524DC81E100CA492C /* OWSContactsManager.swift */,
|
||||
F9C5C9DD289453B100548EEE /* OWSDisappearingMessagesConfiguration+SDS.swift */,
|
||||
F9C5C9D1289453B100548EEE /* OWSDisappearingMessagesConfiguration.h */,
|
||||
F9C5C9F1289453B100548EEE /* OWSDisappearingMessagesConfiguration.m */,
|
||||
F9C5C9F4289453B100548EEE /* OWSDisappearingMessagesConfiguration.swift */,
|
||||
885C354F2370DFD50004BA35 /* OWSSyncManager.swift */,
|
||||
726E0F0B2C626978000BC973 /* PhoneNumber.swift */,
|
||||
5033D46229D64ADF007FEADA /* PhoneNumberChangedMessageInserter.swift */,
|
||||
@ -15281,7 +15272,6 @@
|
||||
C190F8F72C1B48BE00D1EAC9 /* OWSArchivedPaymentMessage.h in Headers */,
|
||||
668A01012C2B5FC8007B8808 /* OWSAsserts.h in Headers */,
|
||||
F9C5CBE5289453B300548EEE /* OWSDisappearingConfigurationUpdateInfoMessage.h in Headers */,
|
||||
F9C5CCB9289453B300548EEE /* OWSDisappearingMessagesConfiguration.h in Headers */,
|
||||
F9C5CC36289453B300548EEE /* OWSGroupCallMessage.h in Headers */,
|
||||
C190F8F12C1B431900D1EAC9 /* OWSIncomingArchivedPaymentMessage.h in Headers */,
|
||||
6605D4FC2A85AD0B004DC345 /* OWSIncomingPaymentMessage.h in Headers */,
|
||||
@ -18747,6 +18737,7 @@
|
||||
F9C5CCA0289453B300548EEE /* DeviceTransferProto.swift in Sources */,
|
||||
502D69322A7AC07C0085B656 /* Dictionary+SSK.swift in Sources */,
|
||||
50DCCBFA2F1817280024D124 /* DisappearingMessagesConfigurationMessage.swift in Sources */,
|
||||
F9C5CCDA289453B300548EEE /* DisappearingMessagesConfigurationRecord.swift in Sources */,
|
||||
502D45462A09C2EE00B8BCE0 /* DisappearingMessagesConfigurationStore.swift in Sources */,
|
||||
D98BC53A2EE49EF30052A81F /* DisappearingMessagesExpirationJob.swift in Sources */,
|
||||
F9C5CDE8289453B400548EEE /* DispatchQueue+OWS.swift in Sources */,
|
||||
@ -19089,9 +19080,6 @@
|
||||
F9C5CBFC289453B300548EEE /* OWSDisappearingConfigurationUpdateInfoMessage+SDS.swift in Sources */,
|
||||
F9C5CC02289453B300548EEE /* OWSDisappearingConfigurationUpdateInfoMessage.m in Sources */,
|
||||
D95787832C6D2FBA0051AC74 /* OWSDisappearingConfigurationUpdateInfoMessage.swift in Sources */,
|
||||
F9C5CCC4289453B300548EEE /* OWSDisappearingMessagesConfiguration+SDS.swift in Sources */,
|
||||
F9C5CCD7289453B300548EEE /* OWSDisappearingMessagesConfiguration.m in Sources */,
|
||||
F9C5CCDA289453B300548EEE /* OWSDisappearingMessagesConfiguration.swift in Sources */,
|
||||
F9C5CE49289453B400548EEE /* OWSError.swift in Sources */,
|
||||
F937EDA429746DA20003AF3F /* OWSFail.swift in Sources */,
|
||||
503BD28B2B44DA64009624FC /* OWSFakeProfileManager.swift in Sources */,
|
||||
|
||||
@ -177,7 +177,7 @@ extension ConversationViewController {
|
||||
|
||||
var thread: TSThread { threadViewModel.threadRecord }
|
||||
|
||||
var disappearingMessagesConfiguration: OWSDisappearingMessagesConfiguration { threadViewModel.disappearingMessagesConfiguration }
|
||||
var disappearingMessagesConfiguration: DisappearingMessagesConfigurationRecord { threadViewModel.disappearingMessagesConfiguration }
|
||||
|
||||
var conversationStyle: ConversationStyle {
|
||||
get { viewState.conversationStyle }
|
||||
|
||||
@ -1152,7 +1152,7 @@ extension CVComponentSystemMessage {
|
||||
"SYSTEM_MESSAGE_DEFAULT_DISAPPEARING_MESSAGE_TIMER_FORMAT",
|
||||
comment: "Indicator that the default disappearing message timer will be applied when you send a message. Embeds {default disappearing message time}",
|
||||
)
|
||||
labelText.append(String(format: titleFormat, configuration.durationString))
|
||||
labelText.append(String(format: titleFormat, configuration.durationString()))
|
||||
|
||||
return buildComponentState(title: labelText, action: nil, expiration: nil)
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ class CVRenderState {
|
||||
|
||||
// TODO: We might want to precompute: interactionIndexMap, focusItemIndex, unreadIndicatorIndex
|
||||
|
||||
var disappearingMessagesConfiguration: OWSDisappearingMessagesConfiguration {
|
||||
var disappearingMessagesConfiguration: DisappearingMessagesConfigurationRecord {
|
||||
threadViewModel.disappearingMessagesConfiguration
|
||||
}
|
||||
|
||||
|
||||
@ -50,7 +50,7 @@ class ConversationSettingsViewController: OWSTableViewController2, BadgeCollecti
|
||||
|
||||
var showVerificationOnAppear = false
|
||||
|
||||
var disappearingMessagesConfiguration: OWSDisappearingMessagesConfiguration
|
||||
var disappearingMessagesConfiguration: DisappearingMessagesConfigurationRecord
|
||||
var avatarView: ConversationAvatarView?
|
||||
|
||||
var isShowingAllGroupMembers = false
|
||||
|
||||
@ -14,10 +14,10 @@ class DisappearingMessagesTimerSettingsViewController: HostingController<Disappe
|
||||
case universal
|
||||
}
|
||||
|
||||
private let initialConfiguration: OWSDisappearingMessagesConfiguration
|
||||
private var selectedConfiguration: OWSDisappearingMessagesConfiguration
|
||||
private let initialConfiguration: DisappearingMessagesConfigurationRecord
|
||||
private var selectedConfiguration: DisappearingMessagesConfigurationRecord
|
||||
private let settingsMode: SettingsMode
|
||||
private let completion: (OWSDisappearingMessagesConfiguration) -> Void
|
||||
private let completion: (DisappearingMessagesConfigurationRecord) -> Void
|
||||
|
||||
private let viewModel: DisappearingMessagesTimerSettingsViewModel
|
||||
|
||||
@ -26,9 +26,9 @@ class DisappearingMessagesTimerSettingsViewController: HostingController<Disappe
|
||||
}
|
||||
|
||||
init(
|
||||
initialConfiguration: OWSDisappearingMessagesConfiguration,
|
||||
initialConfiguration: DisappearingMessagesConfigurationRecord,
|
||||
settingsMode: SettingsMode,
|
||||
completion: @escaping (OWSDisappearingMessagesConfiguration) -> Void,
|
||||
completion: @escaping (DisappearingMessagesConfigurationRecord) -> Void,
|
||||
) {
|
||||
self.initialConfiguration = initialConfiguration
|
||||
self.selectedConfiguration = initialConfiguration
|
||||
@ -148,13 +148,13 @@ class DisappearingMessagesTimerSettingsViewController: HostingController<Disappe
|
||||
extension DisappearingMessagesTimerSettingsViewController: DisappearingMessagesTimerSettingsViewModel.ActionsDelegate {
|
||||
fileprivate func updateForSelection(_ durationSeconds: UInt32) {
|
||||
if durationSeconds == 0 {
|
||||
selectedConfiguration = initialConfiguration.copy(
|
||||
withIsEnabled: false,
|
||||
selectedConfiguration = initialConfiguration.copyWith(
|
||||
isEnabled: false,
|
||||
timerVersion: initialConfiguration.timerVersion + 1,
|
||||
)
|
||||
} else {
|
||||
selectedConfiguration = initialConfiguration.copyAsEnabled(
|
||||
withDurationSeconds: durationSeconds,
|
||||
selectedConfiguration = initialConfiguration.copyAsEnabledWith(
|
||||
durationSeconds: durationSeconds,
|
||||
timerVersion: initialConfiguration.timerVersion + 1,
|
||||
)
|
||||
}
|
||||
@ -228,10 +228,9 @@ private class DisappearingMessagesTimerSettingsViewModel: ObservableObject {
|
||||
localizedDescription: CommonStrings.switchOff,
|
||||
durationSeconds: 0,
|
||||
)
|
||||
let enabledPresets = OWSDisappearingMessagesConfiguration
|
||||
let enabledPresets = DisappearingMessagesConfigurationRecord
|
||||
.presetDurationsSeconds()
|
||||
.reversed()
|
||||
.map { $0.uint32Value }
|
||||
.map { durationSeconds in
|
||||
Preset(
|
||||
localizedDescription: DateUtil.formatDuration(seconds: durationSeconds, useShortFormat: false),
|
||||
|
||||
@ -18,7 +18,7 @@ final class ContactOutputStream {
|
||||
aci: Aci?,
|
||||
phoneNumber: E164?,
|
||||
signalAccount: SignalAccount?,
|
||||
disappearingMessagesConfiguration: OWSDisappearingMessagesConfiguration?,
|
||||
disappearingMessagesConfiguration: DisappearingMessagesConfigurationRecord?,
|
||||
inboxPosition: Int?,
|
||||
) throws {
|
||||
let contactBuilder = SSKProtoContactDetails.builder()
|
||||
|
||||
@ -0,0 +1,251 @@
|
||||
//
|
||||
// Copyright 2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
import Foundation
|
||||
public import GRDB
|
||||
|
||||
/// A convenience wrapper around a disappearing message timer duration value that
|
||||
/// 1) handles seconds/millis conversion
|
||||
/// 2) deals internally with the fact that `0` means "not enabled".
|
||||
///
|
||||
/// See also ``VersionedDisappearingMessageToken``, which is the same thing but
|
||||
/// with an attached version that, at time of writing, used by 1:1 conversations (TSContactThread)
|
||||
/// which are subject to races in setting their DM timer config.
|
||||
@objc
|
||||
public final class DisappearingMessageToken: NSObject, NSSecureCoding, NSCopying {
|
||||
public static var supportsSecureCoding: Bool { true }
|
||||
|
||||
public init?(coder: NSCoder) {
|
||||
self.durationSeconds = coder.decodeObject(of: NSNumber.self, forKey: "durationSeconds")?.uint32Value ?? 0
|
||||
}
|
||||
|
||||
public func encode(with coder: NSCoder) {
|
||||
coder.encode(NSNumber(value: self.durationSeconds), forKey: "durationSeconds")
|
||||
}
|
||||
|
||||
override public var hash: Int {
|
||||
var hasher = Hasher()
|
||||
hasher.combine(durationSeconds)
|
||||
return hasher.finalize()
|
||||
}
|
||||
|
||||
override public func isEqual(_ object: Any?) -> Bool {
|
||||
guard let object = object as? Self else { return false }
|
||||
guard type(of: self) == type(of: object) else { return false }
|
||||
guard self.durationSeconds == object.durationSeconds else { return false }
|
||||
return true
|
||||
}
|
||||
|
||||
public func copy(with zone: NSZone? = nil) -> Any {
|
||||
return self
|
||||
}
|
||||
|
||||
@objc
|
||||
public var isEnabled: Bool {
|
||||
return durationSeconds > 0
|
||||
}
|
||||
|
||||
public let durationSeconds: UInt32
|
||||
|
||||
@objc
|
||||
public init(isEnabled: Bool, durationSeconds: UInt32) {
|
||||
// Consider disabled if duration is zero.
|
||||
// Use zero duration if not enabled.
|
||||
self.durationSeconds = isEnabled ? durationSeconds : 0
|
||||
|
||||
super.init()
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
public static var disabledToken: DisappearingMessageToken {
|
||||
return DisappearingMessageToken(isEnabled: false, durationSeconds: 0)
|
||||
}
|
||||
|
||||
public class func token(forProtoExpireTimerSeconds expireTimerSeconds: UInt32?) -> DisappearingMessageToken {
|
||||
if let expireTimerSeconds, expireTimerSeconds > 0 {
|
||||
return DisappearingMessageToken(isEnabled: true, durationSeconds: expireTimerSeconds)
|
||||
} else {
|
||||
return .disabledToken
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
@objc(OWSDisappearingMessagesConfiguration)
|
||||
public final class DisappearingMessagesConfigurationRecord: NSObject, SDSCodableModel, Decodable, NSSecureCoding, NSCopying {
|
||||
public static var databaseTableName: String = "model_OWSDisappearingMessagesConfiguration"
|
||||
public static var recordType: UInt = SDSRecordType.disappearingMessagesConfiguration.rawValue
|
||||
|
||||
public var id: Int64?
|
||||
public let threadUniqueId: String
|
||||
public var uniqueId: String { threadUniqueId }
|
||||
public let durationSeconds: UInt32
|
||||
public let isEnabled: Bool
|
||||
public let timerVersion: UInt32
|
||||
|
||||
public enum CodingKeys: String, CodingKey, ColumnExpression, CaseIterable {
|
||||
case id
|
||||
case recordType
|
||||
case threadUniqueId = "uniqueId"
|
||||
case durationSeconds
|
||||
case isEnabled = "enabled"
|
||||
case timerVersion
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.id = try container.decodeIfPresent(Int64.self, forKey: .id)
|
||||
self.threadUniqueId = try container.decode(String.self, forKey: .threadUniqueId)
|
||||
self.durationSeconds = try container.decode(UInt32.self, forKey: .durationSeconds)
|
||||
self.isEnabled = try container.decode(Bool.self, forKey: .isEnabled)
|
||||
self.timerVersion = try container.decode(UInt32.self, forKey: .timerVersion)
|
||||
}
|
||||
|
||||
public func encode(to encoder: any Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encodeIfPresent(self.id, forKey: .id)
|
||||
try container.encode(Self.recordType, forKey: .recordType)
|
||||
try container.encode(self.threadUniqueId, forKey: .threadUniqueId)
|
||||
try container.encode(self.durationSeconds, forKey: .durationSeconds)
|
||||
try container.encode(self.isEnabled, forKey: .isEnabled)
|
||||
try container.encode(self.timerVersion, forKey: .timerVersion)
|
||||
}
|
||||
|
||||
public static var supportsSecureCoding: Bool { true }
|
||||
|
||||
public func encode(with coder: NSCoder) {
|
||||
if let id {
|
||||
coder.encode(NSNumber(value: id), forKey: "grdbId")
|
||||
}
|
||||
coder.encode(self.threadUniqueId, forKey: "uniqueId")
|
||||
coder.encode(NSNumber(value: self.durationSeconds), forKey: "durationSeconds")
|
||||
coder.encode(NSNumber(value: self.isEnabled), forKey: "enabled")
|
||||
coder.encode(NSNumber(value: self.timerVersion), forKey: "timerVersion")
|
||||
}
|
||||
|
||||
public init?(coder: NSCoder) {
|
||||
self.id = coder.decodeObject(of: NSNumber.self, forKey: "grdbId")?.int64Value ?? 0
|
||||
guard let threadUniqueId = coder.decodeObject(of: NSString.self, forKey: "uniqueId") as String? else {
|
||||
return nil
|
||||
}
|
||||
self.threadUniqueId = threadUniqueId
|
||||
self.durationSeconds = coder.decodeObject(of: NSNumber.self, forKey: "durationSeconds")?.uint32Value ?? 0
|
||||
self.isEnabled = coder.decodeObject(of: NSNumber.self, forKey: "enabled")?.boolValue ?? false
|
||||
self.timerVersion = coder.decodeObject(of: NSNumber.self, forKey: "timerVersion")?.uint32Value ?? 0
|
||||
}
|
||||
|
||||
override public var hash: Int {
|
||||
var hasher = Hasher()
|
||||
hasher.combine(self.id)
|
||||
hasher.combine(self.threadUniqueId)
|
||||
hasher.combine(self.durationSeconds)
|
||||
hasher.combine(self.isEnabled)
|
||||
// [Mantle] TODO: It's wrong to include this based on isEqual:'s implementation.
|
||||
hasher.combine(self.timerVersion)
|
||||
return hasher.finalize()
|
||||
}
|
||||
|
||||
override public func isEqual(_ object: Any?) -> Bool {
|
||||
guard let object = object as? Self else { return false }
|
||||
// [Mantle] TODO: This is wrong because it ignores id & uniqueId.
|
||||
guard self.isEnabled == object.isEnabled else { return false }
|
||||
// Don't bother comparing durationSeconds if not enabled.
|
||||
// [Mantle] TODO: This is wrong because it violates the requirements for hash.
|
||||
guard self.isEnabled else { return true }
|
||||
guard self.durationSeconds == object.durationSeconds else { return false }
|
||||
guard self.timerVersion == object.timerVersion else { return false }
|
||||
return true
|
||||
}
|
||||
|
||||
public func copy(with zone: NSZone? = nil) -> Any {
|
||||
return Self(
|
||||
id: self.id,
|
||||
threadUniqueId: self.threadUniqueId,
|
||||
isEnabled: self.isEnabled,
|
||||
durationSeconds: self.durationSeconds,
|
||||
timerVersion: self.timerVersion,
|
||||
)
|
||||
}
|
||||
|
||||
init(
|
||||
id: Int64? = nil,
|
||||
threadUniqueId: String,
|
||||
isEnabled: Bool,
|
||||
durationSeconds: UInt32,
|
||||
timerVersion: UInt32,
|
||||
) {
|
||||
owsAssertDebug(!threadUniqueId.isEmpty)
|
||||
self.id = id
|
||||
self.threadUniqueId = threadUniqueId
|
||||
self.isEnabled = isEnabled
|
||||
self.durationSeconds = durationSeconds
|
||||
self.timerVersion = timerVersion
|
||||
}
|
||||
|
||||
public static func presetDurationsSeconds() -> [UInt32] {
|
||||
return [
|
||||
UInt32(30 * .second),
|
||||
UInt32(5 * .minute),
|
||||
UInt32(1 * .hour),
|
||||
UInt32(8 * .hour),
|
||||
UInt32(24 * .hour),
|
||||
UInt32(1 * .week),
|
||||
UInt32(4 * .week),
|
||||
]
|
||||
}
|
||||
|
||||
public func durationString() -> String {
|
||||
return String.formatDurationLossless(durationSeconds: self.durationSeconds)
|
||||
}
|
||||
|
||||
public func copyWith(isEnabled: Bool, timerVersion: UInt32) -> Self {
|
||||
return Self(
|
||||
id: self.id,
|
||||
threadUniqueId: self.threadUniqueId,
|
||||
isEnabled: isEnabled,
|
||||
durationSeconds: isEnabled ? self.durationSeconds : 0,
|
||||
timerVersion: timerVersion,
|
||||
)
|
||||
}
|
||||
|
||||
func copyWith(durationSeconds: UInt32, timerVersion: UInt32) -> Self {
|
||||
return Self(
|
||||
id: self.id,
|
||||
threadUniqueId: self.threadUniqueId,
|
||||
isEnabled: self.isEnabled,
|
||||
durationSeconds: durationSeconds,
|
||||
timerVersion: timerVersion,
|
||||
)
|
||||
}
|
||||
|
||||
public func copyAsEnabledWith(durationSeconds: UInt32, timerVersion: UInt32) -> Self {
|
||||
return Self(
|
||||
id: self.id,
|
||||
threadUniqueId: self.threadUniqueId,
|
||||
isEnabled: true,
|
||||
durationSeconds: durationSeconds,
|
||||
timerVersion: timerVersion,
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns true if two configs have the same duration and enabled state, regardless of timer version.
|
||||
func hasSameDurationAs(_ other: DisappearingMessagesConfigurationRecord) -> Bool {
|
||||
return self.isEnabled == other.isEnabled && self.durationSeconds == other.durationSeconds
|
||||
}
|
||||
|
||||
public var asToken: DisappearingMessageToken {
|
||||
return DisappearingMessageToken(isEnabled: isEnabled, durationSeconds: durationSeconds)
|
||||
}
|
||||
|
||||
public var asVersionedToken: VersionedDisappearingMessageToken {
|
||||
return VersionedDisappearingMessageToken(
|
||||
isEnabled: isEnabled,
|
||||
durationSeconds: durationSeconds,
|
||||
version: timerVersion,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,465 +0,0 @@
|
||||
//
|
||||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
import Foundation
|
||||
public import GRDB
|
||||
|
||||
// NOTE: This file is generated by /Scripts/sds_codegen/sds_generate.py.
|
||||
// Do not manually edit it, instead run `sds_codegen.sh`.
|
||||
|
||||
// MARK: - Record
|
||||
|
||||
public struct DisappearingMessagesConfigurationRecord: SDSRecord {
|
||||
public weak var delegate: SDSRecordDelegate?
|
||||
|
||||
public var tableMetadata: SDSTableMetadata {
|
||||
OWSDisappearingMessagesConfigurationSerializer.table
|
||||
}
|
||||
|
||||
public static var databaseTableName: String {
|
||||
OWSDisappearingMessagesConfigurationSerializer.table.tableName
|
||||
}
|
||||
|
||||
public var id: Int64?
|
||||
|
||||
// This defines all of the columns used in the table
|
||||
// where this model (and any subclasses) are persisted.
|
||||
public let recordType: SDSRecordType?
|
||||
public let uniqueId: String
|
||||
|
||||
// Properties
|
||||
public let durationSeconds: UInt32
|
||||
public let enabled: Bool
|
||||
public let timerVersion: UInt32
|
||||
|
||||
public enum CodingKeys: String, CodingKey, ColumnExpression, CaseIterable {
|
||||
case id
|
||||
case recordType
|
||||
case uniqueId
|
||||
case durationSeconds
|
||||
case enabled
|
||||
case timerVersion
|
||||
}
|
||||
|
||||
public static func columnName(_ column: DisappearingMessagesConfigurationRecord.CodingKeys, fullyQualified: Bool = false) -> String {
|
||||
fullyQualified ? "\(databaseTableName).\(column.rawValue)" : column.rawValue
|
||||
}
|
||||
|
||||
public func didInsert(with rowID: Int64, for column: String?) {
|
||||
guard let delegate = delegate else {
|
||||
owsFailDebug("Missing delegate.")
|
||||
return
|
||||
}
|
||||
delegate.updateRowId(rowID)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Row Initializer
|
||||
|
||||
public extension DisappearingMessagesConfigurationRecord {
|
||||
static var databaseSelection: [SQLSelectable] {
|
||||
CodingKeys.allCases
|
||||
}
|
||||
|
||||
init(row: Row) {
|
||||
id = row[0]
|
||||
recordType = row[1].flatMap { SDSRecordType(rawValue: $0) }
|
||||
uniqueId = row[2]
|
||||
durationSeconds = row[3]
|
||||
enabled = row[4]
|
||||
timerVersion = row[5]
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - StringInterpolation
|
||||
|
||||
public extension String.StringInterpolation {
|
||||
mutating func appendInterpolation(disappearingMessagesConfigurationColumn column: DisappearingMessagesConfigurationRecord.CodingKeys) {
|
||||
appendLiteral(DisappearingMessagesConfigurationRecord.columnName(column))
|
||||
}
|
||||
mutating func appendInterpolation(disappearingMessagesConfigurationColumnFullyQualified column: DisappearingMessagesConfigurationRecord.CodingKeys) {
|
||||
appendLiteral(DisappearingMessagesConfigurationRecord.columnName(column, fullyQualified: true))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Deserialization
|
||||
|
||||
extension OWSDisappearingMessagesConfiguration {
|
||||
// This method defines how to deserialize a model, given a
|
||||
// database row. The recordType column is used to determine
|
||||
// the corresponding model class.
|
||||
class func fromRecord(_ record: DisappearingMessagesConfigurationRecord) throws -> OWSDisappearingMessagesConfiguration {
|
||||
|
||||
guard let recordId = record.id else { throw SDSError.missingRequiredField(fieldName: "id") }
|
||||
guard let recordType = record.recordType else { throw SDSError.missingRequiredField(fieldName: "recordType") }
|
||||
|
||||
switch recordType {
|
||||
case .disappearingMessagesConfiguration:
|
||||
|
||||
let uniqueId: String = record.uniqueId
|
||||
let durationSeconds: UInt32 = record.durationSeconds
|
||||
let enabled: Bool = record.enabled
|
||||
let timerVersion: UInt32 = record.timerVersion
|
||||
|
||||
return OWSDisappearingMessagesConfiguration(grdbId: recordId,
|
||||
uniqueId: uniqueId,
|
||||
durationSeconds: durationSeconds,
|
||||
enabled: enabled,
|
||||
timerVersion: timerVersion)
|
||||
|
||||
default:
|
||||
owsFailDebug("Unexpected record type: \(recordType)")
|
||||
throw SDSError.invalidValue()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - SDSModel
|
||||
|
||||
extension OWSDisappearingMessagesConfiguration: SDSModel {
|
||||
public var serializer: SDSSerializer {
|
||||
// Any subclass can be cast to it's superclass,
|
||||
// so the order of this switch statement matters.
|
||||
// We need to do a "depth first" search by type.
|
||||
switch self {
|
||||
default:
|
||||
return OWSDisappearingMessagesConfigurationSerializer(model: self)
|
||||
}
|
||||
}
|
||||
|
||||
public func asRecord() -> SDSRecord {
|
||||
serializer.asRecord()
|
||||
}
|
||||
|
||||
public var sdsTableName: String {
|
||||
DisappearingMessagesConfigurationRecord.databaseTableName
|
||||
}
|
||||
|
||||
public static var table: SDSTableMetadata {
|
||||
OWSDisappearingMessagesConfigurationSerializer.table
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - DeepCopyable
|
||||
|
||||
extension OWSDisappearingMessagesConfiguration: DeepCopyable {
|
||||
|
||||
public func deepCopy() throws -> AnyObject {
|
||||
guard let id = self.grdbId?.int64Value else {
|
||||
throw OWSAssertionError("Model missing grdbId.")
|
||||
}
|
||||
|
||||
// Any subclass can be cast to its superclass, so the order of these if
|
||||
// statements matters. We need to do a "depth first" search by type.
|
||||
|
||||
do {
|
||||
let modelToCopy = self
|
||||
assert(type(of: modelToCopy) == OWSDisappearingMessagesConfiguration.self)
|
||||
let uniqueId: String = modelToCopy.uniqueId
|
||||
let durationSeconds: UInt32 = modelToCopy.durationSeconds
|
||||
let enabled: Bool = modelToCopy.isEnabled
|
||||
let timerVersion: UInt32 = modelToCopy.timerVersion
|
||||
|
||||
return OWSDisappearingMessagesConfiguration(grdbId: id,
|
||||
uniqueId: uniqueId,
|
||||
durationSeconds: durationSeconds,
|
||||
enabled: enabled,
|
||||
timerVersion: timerVersion)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Table Metadata
|
||||
|
||||
extension OWSDisappearingMessagesConfigurationSerializer {
|
||||
|
||||
// This defines all of the columns used in the table
|
||||
// where this model (and any subclasses) are persisted.
|
||||
static var idColumn: SDSColumnMetadata { SDSColumnMetadata(columnName: "id", columnType: .primaryKey) }
|
||||
static var recordTypeColumn: SDSColumnMetadata { SDSColumnMetadata(columnName: "recordType", columnType: .int64) }
|
||||
static var uniqueIdColumn: SDSColumnMetadata { SDSColumnMetadata(columnName: "uniqueId", columnType: .unicodeString, isUnique: true) }
|
||||
// Properties
|
||||
static var durationSecondsColumn: SDSColumnMetadata { SDSColumnMetadata(columnName: "durationSeconds", columnType: .int64) }
|
||||
static var enabledColumn: SDSColumnMetadata { SDSColumnMetadata(columnName: "enabled", columnType: .int) }
|
||||
static var timerVersionColumn: SDSColumnMetadata { SDSColumnMetadata(columnName: "timerVersion", columnType: .int64) }
|
||||
|
||||
public static var table: SDSTableMetadata {
|
||||
SDSTableMetadata(
|
||||
tableName: "model_OWSDisappearingMessagesConfiguration",
|
||||
columns: [
|
||||
idColumn,
|
||||
recordTypeColumn,
|
||||
uniqueIdColumn,
|
||||
durationSecondsColumn,
|
||||
enabledColumn,
|
||||
timerVersionColumn,
|
||||
]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Save/Remove/Update
|
||||
|
||||
@objc
|
||||
public extension OWSDisappearingMessagesConfiguration {
|
||||
func anyInsert(transaction: DBWriteTransaction) {
|
||||
sdsSave(saveMode: .insert, transaction: transaction)
|
||||
}
|
||||
|
||||
// Avoid this method whenever feasible.
|
||||
//
|
||||
// If the record has previously been saved, this method does an overwriting
|
||||
// update of the corresponding row, otherwise if it's a new record, this
|
||||
// method inserts a new row.
|
||||
//
|
||||
// For performance, when possible, you should explicitly specify whether
|
||||
// you are inserting or updating rather than calling this method.
|
||||
func anyUpsert(transaction: DBWriteTransaction) {
|
||||
let isInserting: Bool
|
||||
if OWSDisappearingMessagesConfiguration.anyFetch(uniqueId: uniqueId, transaction: transaction) != nil {
|
||||
isInserting = false
|
||||
} else {
|
||||
isInserting = true
|
||||
}
|
||||
sdsSave(saveMode: isInserting ? .insert : .update, transaction: transaction)
|
||||
}
|
||||
|
||||
// This method is used by "updateWith..." methods.
|
||||
//
|
||||
// This model may be updated from many threads. We don't want to save
|
||||
// our local copy (this instance) since it may be out of date. We also
|
||||
// want to avoid re-saving a model that has been deleted. Therefore, we
|
||||
// use "updateWith..." methods to:
|
||||
//
|
||||
// a) Update a property of this instance.
|
||||
// b) If a copy of this model exists in the database, load an up-to-date copy,
|
||||
// and update and save that copy.
|
||||
// b) If a copy of this model _DOES NOT_ exist in the database, do _NOT_ save
|
||||
// this local instance.
|
||||
//
|
||||
// After "updateWith...":
|
||||
//
|
||||
// a) Any copy of this model in the database will have been updated.
|
||||
// b) The local property on this instance will always have been updated.
|
||||
// c) Other properties on this instance may be out of date.
|
||||
//
|
||||
// All mutable properties of this class have been made read-only to
|
||||
// prevent accidentally modifying them directly.
|
||||
//
|
||||
// This isn't a perfect arrangement, but in practice this will prevent
|
||||
// data loss and will resolve all known issues.
|
||||
func anyUpdate(transaction: DBWriteTransaction, block: (OWSDisappearingMessagesConfiguration) -> Void) {
|
||||
|
||||
block(self)
|
||||
|
||||
// If it's not saved, we don't expect to find it in the database, and we
|
||||
// won't save any changes we make back into the database.
|
||||
guard shouldBeSaved else {
|
||||
return
|
||||
}
|
||||
|
||||
guard let dbCopy = type(of: self).anyFetch(uniqueId: uniqueId, transaction: transaction) else {
|
||||
return
|
||||
}
|
||||
|
||||
// Don't apply the block twice to the same instance.
|
||||
// It's at least unnecessary and actually wrong for some blocks.
|
||||
// e.g. `block: { $0 in $0.someField++ }`
|
||||
if dbCopy !== self {
|
||||
block(dbCopy)
|
||||
}
|
||||
|
||||
dbCopy.sdsSave(saveMode: .update, transaction: transaction)
|
||||
}
|
||||
|
||||
// This method is an alternative to `anyUpdate(transaction:block:)` methods.
|
||||
//
|
||||
// We should generally use `anyUpdate` to ensure we're not unintentionally
|
||||
// clobbering other columns in the database when another concurrent update
|
||||
// has occurred.
|
||||
//
|
||||
// There are cases when this doesn't make sense, e.g. when we know we've
|
||||
// just loaded the model in the same transaction. In those cases it is
|
||||
// safe and faster to do a "overwriting" update
|
||||
func anyOverwritingUpdate(transaction: DBWriteTransaction) {
|
||||
sdsSave(saveMode: .update, transaction: transaction)
|
||||
}
|
||||
|
||||
func anyRemove(transaction: DBWriteTransaction) {
|
||||
sdsRemove(transaction: transaction)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - OWSDisappearingMessagesConfigurationCursor
|
||||
|
||||
@objc
|
||||
public class OWSDisappearingMessagesConfigurationCursor: NSObject, SDSCursor {
|
||||
private let transaction: DBReadTransaction
|
||||
private let cursor: RecordCursor<DisappearingMessagesConfigurationRecord>
|
||||
|
||||
init(transaction: DBReadTransaction, cursor: RecordCursor<DisappearingMessagesConfigurationRecord>) {
|
||||
self.transaction = transaction
|
||||
self.cursor = cursor
|
||||
}
|
||||
|
||||
public func next() throws -> OWSDisappearingMessagesConfiguration? {
|
||||
guard let record = try cursor.next() else {
|
||||
return nil
|
||||
}
|
||||
return try OWSDisappearingMessagesConfiguration.fromRecord(record)
|
||||
}
|
||||
|
||||
public func all() throws -> [OWSDisappearingMessagesConfiguration] {
|
||||
var result = [OWSDisappearingMessagesConfiguration]()
|
||||
while true {
|
||||
guard let model = try next() else {
|
||||
break
|
||||
}
|
||||
result.append(model)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Obj-C Fetch
|
||||
|
||||
@objc
|
||||
public extension OWSDisappearingMessagesConfiguration {
|
||||
@nonobjc
|
||||
class func grdbFetchCursor(transaction: DBReadTransaction) -> OWSDisappearingMessagesConfigurationCursor {
|
||||
let database = transaction.database
|
||||
return failIfThrows {
|
||||
let cursor = try DisappearingMessagesConfigurationRecord.fetchCursor(database)
|
||||
return OWSDisappearingMessagesConfigurationCursor(transaction: transaction, cursor: cursor)
|
||||
}
|
||||
}
|
||||
|
||||
// Fetches a single model by "unique id".
|
||||
class func anyFetch(uniqueId: String,
|
||||
transaction: DBReadTransaction) -> OWSDisappearingMessagesConfiguration? {
|
||||
assert(!uniqueId.isEmpty)
|
||||
|
||||
let sql = "SELECT * FROM \(DisappearingMessagesConfigurationRecord.databaseTableName) WHERE \(disappearingMessagesConfigurationColumn: .uniqueId) = ?"
|
||||
return grdbFetchOne(sql: sql, arguments: [uniqueId], transaction: transaction)
|
||||
}
|
||||
|
||||
// Traverses all records.
|
||||
// Records are not visited in any particular order.
|
||||
class func anyEnumerate(
|
||||
transaction: DBReadTransaction,
|
||||
block: (OWSDisappearingMessagesConfiguration, UnsafeMutablePointer<ObjCBool>) -> Void
|
||||
) {
|
||||
anyEnumerate(transaction: transaction, batched: false, block: block)
|
||||
}
|
||||
|
||||
// Traverses all records.
|
||||
// Records are not visited in any particular order.
|
||||
class func anyEnumerate(
|
||||
transaction: DBReadTransaction,
|
||||
batched: Bool = false,
|
||||
block: (OWSDisappearingMessagesConfiguration, UnsafeMutablePointer<ObjCBool>) -> Void
|
||||
) {
|
||||
let batchSize = batched ? Batching.kDefaultBatchSize : 0
|
||||
anyEnumerate(transaction: transaction, batchSize: batchSize, block: block)
|
||||
}
|
||||
|
||||
// Traverses all records.
|
||||
// Records are not visited in any particular order.
|
||||
//
|
||||
// If batchSize > 0, the enumeration is performed in autoreleased batches.
|
||||
class func anyEnumerate(
|
||||
transaction: DBReadTransaction,
|
||||
batchSize: UInt,
|
||||
block: (OWSDisappearingMessagesConfiguration, UnsafeMutablePointer<ObjCBool>) -> Void
|
||||
) {
|
||||
let cursor = OWSDisappearingMessagesConfiguration.grdbFetchCursor(transaction: transaction)
|
||||
Batching.loop(batchSize: batchSize,
|
||||
loopBlock: { stop in
|
||||
do {
|
||||
guard let value = try cursor.next() else {
|
||||
stop.pointee = true
|
||||
return
|
||||
}
|
||||
block(value, stop)
|
||||
} catch let error {
|
||||
owsFailDebug("Couldn't fetch model: \(error)")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Does not order the results.
|
||||
class func anyFetchAll(transaction: DBReadTransaction) -> [OWSDisappearingMessagesConfiguration] {
|
||||
var result = [OWSDisappearingMessagesConfiguration]()
|
||||
anyEnumerate(transaction: transaction) { (model, _) in
|
||||
result.append(model)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
class func anyCount(transaction: DBReadTransaction) -> UInt {
|
||||
return DisappearingMessagesConfigurationRecord.ows_fetchCount(transaction.database)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Swift Fetch
|
||||
|
||||
public extension OWSDisappearingMessagesConfiguration {
|
||||
class func grdbFetchCursor(sql: String,
|
||||
arguments: StatementArguments = StatementArguments(),
|
||||
transaction: DBReadTransaction) -> OWSDisappearingMessagesConfigurationCursor {
|
||||
return failIfThrows {
|
||||
let sqlRequest = SQLRequest<Void>(sql: sql, arguments: arguments, cached: true)
|
||||
let cursor = try DisappearingMessagesConfigurationRecord.fetchCursor(transaction.database, sqlRequest)
|
||||
return OWSDisappearingMessagesConfigurationCursor(transaction: transaction, cursor: cursor)
|
||||
}
|
||||
}
|
||||
|
||||
class func grdbFetchOne(sql: String,
|
||||
arguments: StatementArguments = StatementArguments(),
|
||||
transaction: DBReadTransaction) -> OWSDisappearingMessagesConfiguration? {
|
||||
assert(!sql.isEmpty)
|
||||
|
||||
do {
|
||||
let sqlRequest = SQLRequest<Void>(sql: sql, arguments: arguments, cached: true)
|
||||
guard let record = try DisappearingMessagesConfigurationRecord.fetchOne(transaction.database, sqlRequest) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return try OWSDisappearingMessagesConfiguration.fromRecord(record)
|
||||
} catch {
|
||||
owsFailDebug("error: \(error)")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - SDSSerializer
|
||||
|
||||
// The SDSSerializer protocol specifies how to insert and update the
|
||||
// row that corresponds to this model.
|
||||
class OWSDisappearingMessagesConfigurationSerializer: SDSSerializer {
|
||||
|
||||
private let model: OWSDisappearingMessagesConfiguration
|
||||
public init(model: OWSDisappearingMessagesConfiguration) {
|
||||
self.model = model
|
||||
}
|
||||
|
||||
// MARK: - Record
|
||||
|
||||
func asRecord() -> SDSRecord {
|
||||
let id: Int64? = model.grdbId?.int64Value
|
||||
|
||||
let recordType: SDSRecordType = .disappearingMessagesConfiguration
|
||||
let uniqueId: String = model.uniqueId
|
||||
|
||||
// Properties
|
||||
let durationSeconds: UInt32 = model.durationSeconds
|
||||
let enabled: Bool = model.isEnabled
|
||||
let timerVersion: UInt32 = model.timerVersion
|
||||
|
||||
return DisappearingMessagesConfigurationRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, durationSeconds: durationSeconds, enabled: enabled, timerVersion: timerVersion)
|
||||
}
|
||||
}
|
||||
@ -1,66 +0,0 @@
|
||||
//
|
||||
// Copyright 2018 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
#import <SignalServiceKit/BaseModel.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class DBReadTransaction;
|
||||
@class TSThread;
|
||||
|
||||
@interface OWSDisappearingMessagesConfiguration : BaseModel <NSSecureCoding, NSCopying>
|
||||
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
- (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
|
||||
- (instancetype)initWithUniqueId:(NSString *)uniqueId NS_UNAVAILABLE;
|
||||
- (instancetype)initWithGrdbId:(int64_t)grdbId uniqueId:(NSString *)uniqueId NS_UNAVAILABLE;
|
||||
|
||||
// This initializer should only be used internally.
|
||||
- (instancetype)initWithThreadId:(NSString *)threadId
|
||||
enabled:(BOOL)isEnabled
|
||||
durationSeconds:(uint32_t)seconds
|
||||
timerVersion:(uint32_t)timerVersion NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
// --- CODE GENERATION MARKER
|
||||
|
||||
// This snippet is generated by /Scripts/sds_codegen/sds_generate.py. Do not manually edit it, instead run
|
||||
// `sds_codegen.sh`.
|
||||
|
||||
// clang-format off
|
||||
|
||||
- (instancetype)initWithGrdbId:(int64_t)grdbId
|
||||
uniqueId:(NSString *)uniqueId
|
||||
durationSeconds:(unsigned int)durationSeconds
|
||||
enabled:(BOOL)enabled
|
||||
timerVersion:(unsigned int)timerVersion
|
||||
NS_DESIGNATED_INITIALIZER NS_SWIFT_NAME(init(grdbId:uniqueId:durationSeconds:enabled:timerVersion:));
|
||||
|
||||
// clang-format on
|
||||
|
||||
// --- CODE GENERATION MARKER
|
||||
|
||||
@property (nonatomic, readonly, getter=isEnabled) BOOL enabled;
|
||||
@property (nonatomic, readonly) uint32_t durationSeconds;
|
||||
@property (nonatomic, readonly) NSString *durationString;
|
||||
@property (nonatomic, readonly) uint32_t timerVersion;
|
||||
|
||||
+ (NSArray<NSNumber *> *)presetDurationsSeconds;
|
||||
+ (uint32_t)maxDurationSeconds;
|
||||
|
||||
/// Returns true if two configs have the same duration and enabled state, regardless of timer version.
|
||||
- (BOOL)hasSameDurationAs:(OWSDisappearingMessagesConfiguration *)other;
|
||||
|
||||
// It's critical that we only modify copies.
|
||||
// Otherwise any modifications will be made to the
|
||||
// instance in the YDB object cache and hasChangedForThread:
|
||||
// won't be able to detect changes.
|
||||
- (instancetype)copyWithIsEnabled:(BOOL)isEnabled timerVersion:(uint32_t)timerVersion;
|
||||
- (instancetype)copyWithDurationSeconds:(uint32_t)durationSeconds timerVersion:(uint32_t)timerVersion;
|
||||
- (instancetype)copyAsEnabledWithDurationSeconds:(uint32_t)durationSeconds timerVersion:(uint32_t)timerVersion;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,210 +0,0 @@
|
||||
//
|
||||
// Copyright 2017 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
#import "OWSDisappearingMessagesConfiguration.h"
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWSDisappearingMessagesConfiguration ()
|
||||
|
||||
@property (nonatomic, getter=isEnabled) BOOL enabled;
|
||||
@property (nonatomic) uint32_t durationSeconds;
|
||||
@property (nonatomic) uint32_t timerVersion;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation OWSDisappearingMessagesConfiguration
|
||||
|
||||
+ (BOOL)supportsSecureCoding
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)coder
|
||||
{
|
||||
[self encodeIdsWithCoder:coder];
|
||||
[coder encodeObject:[self valueForKey:@"durationSeconds"] forKey:@"durationSeconds"];
|
||||
[coder encodeObject:[self valueForKey:@"enabled"] forKey:@"enabled"];
|
||||
[coder encodeObject:[self valueForKey:@"timerVersion"] forKey:@"timerVersion"];
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithCoder:(NSCoder *)coder
|
||||
{
|
||||
self = [super initWithCoder:coder];
|
||||
if (!self) {
|
||||
return self;
|
||||
}
|
||||
self->_durationSeconds = [(NSNumber *)[coder decodeObjectOfClass:[NSNumber class]
|
||||
forKey:@"durationSeconds"] unsignedIntValue];
|
||||
self->_enabled = [(NSNumber *)[coder decodeObjectOfClass:[NSNumber class] forKey:@"enabled"] boolValue];
|
||||
self->_timerVersion = [(NSNumber *)[coder decodeObjectOfClass:[NSNumber class]
|
||||
forKey:@"timerVersion"] unsignedIntValue];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSUInteger)hash
|
||||
{
|
||||
NSUInteger result = [super hash];
|
||||
result ^= self.durationSeconds;
|
||||
result ^= self.enabled;
|
||||
// [Mantle] TODO: It's wrong to include this based on isEqual:'s implementation.
|
||||
result ^= self.timerVersion;
|
||||
return result;
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(nullable NSZone *)zone
|
||||
{
|
||||
OWSDisappearingMessagesConfiguration *result = [self copyAndAssignIdsWithZone:zone];
|
||||
result->_durationSeconds = self.durationSeconds;
|
||||
result->_enabled = self.enabled;
|
||||
result->_timerVersion = self.timerVersion;
|
||||
return result;
|
||||
}
|
||||
|
||||
- (instancetype)initWithThreadId:(NSString *)threadId
|
||||
enabled:(BOOL)isEnabled
|
||||
durationSeconds:(uint32_t)seconds
|
||||
timerVersion:(uint32_t)timerVersion
|
||||
{
|
||||
OWSAssertDebug(threadId.length > 0);
|
||||
|
||||
// Thread id == configuration id.
|
||||
self = [super initWithUniqueId:threadId];
|
||||
if (!self) {
|
||||
return self;
|
||||
}
|
||||
|
||||
_enabled = isEnabled;
|
||||
_durationSeconds = seconds;
|
||||
_timerVersion = timerVersion;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
// --- CODE GENERATION MARKER
|
||||
|
||||
// This snippet is generated by /Scripts/sds_codegen/sds_generate.py. Do not manually edit it, instead run
|
||||
// `sds_codegen.sh`.
|
||||
|
||||
// clang-format off
|
||||
|
||||
- (instancetype)initWithGrdbId:(int64_t)grdbId
|
||||
uniqueId:(NSString *)uniqueId
|
||||
durationSeconds:(unsigned int)durationSeconds
|
||||
enabled:(BOOL)enabled
|
||||
timerVersion:(unsigned int)timerVersion
|
||||
{
|
||||
self = [super initWithGrdbId:grdbId
|
||||
uniqueId:uniqueId];
|
||||
|
||||
if (!self) {
|
||||
return self;
|
||||
}
|
||||
|
||||
_durationSeconds = durationSeconds;
|
||||
_enabled = enabled;
|
||||
_timerVersion = timerVersion;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
|
||||
// --- CODE GENERATION MARKER
|
||||
|
||||
+ (NSArray<NSNumber *> *)presetDurationsSeconds
|
||||
{
|
||||
return @[
|
||||
@(30 * NSTimeIntervalConstants.second),
|
||||
@(5 * NSTimeIntervalConstants.minute),
|
||||
@(1 * NSTimeIntervalConstants.hour),
|
||||
@(8 * NSTimeIntervalConstants.hour),
|
||||
@(24 * NSTimeIntervalConstants.hour),
|
||||
@(1 * NSTimeIntervalConstants.week),
|
||||
@(4 * NSTimeIntervalConstants.week)
|
||||
];
|
||||
}
|
||||
|
||||
+ (uint32_t)maxDurationSeconds
|
||||
{
|
||||
return (uint32_t)NSTimeIntervalConstants.year;
|
||||
}
|
||||
|
||||
- (NSString *)durationString
|
||||
{
|
||||
return [NSString formatDurationLosslessWithDurationSeconds:self.durationSeconds];
|
||||
}
|
||||
|
||||
- (instancetype)copyWithIsEnabled:(BOOL)isEnabled timerVersion:(uint32_t)timerVersion
|
||||
{
|
||||
// for compiler enforcement
|
||||
id<NSCopying> selfToCopy = self;
|
||||
(void)selfToCopy;
|
||||
OWSDisappearingMessagesConfiguration *newInstance = [self copy];
|
||||
newInstance.enabled = isEnabled;
|
||||
newInstance.timerVersion = timerVersion;
|
||||
if (!isEnabled) {
|
||||
newInstance.durationSeconds = 0;
|
||||
}
|
||||
return newInstance;
|
||||
}
|
||||
|
||||
- (instancetype)copyWithDurationSeconds:(uint32_t)durationSeconds timerVersion:(uint32_t)timerVersion
|
||||
{
|
||||
// for compiler enforcement
|
||||
id<NSCopying> selfToCopy = self;
|
||||
(void)selfToCopy;
|
||||
OWSDisappearingMessagesConfiguration *newInstance = [self copy];
|
||||
newInstance.durationSeconds = durationSeconds;
|
||||
newInstance.timerVersion = timerVersion;
|
||||
return newInstance;
|
||||
}
|
||||
|
||||
- (instancetype)copyAsEnabledWithDurationSeconds:(uint32_t)durationSeconds timerVersion:(uint32_t)timerVersion
|
||||
{
|
||||
// for compiler enforcement
|
||||
id<NSCopying> selfToCopy = self;
|
||||
(void)selfToCopy;
|
||||
OWSDisappearingMessagesConfiguration *newInstance = [self copy];
|
||||
newInstance.enabled = YES;
|
||||
newInstance.durationSeconds = durationSeconds;
|
||||
newInstance.timerVersion = timerVersion;
|
||||
return newInstance;
|
||||
}
|
||||
|
||||
- (BOOL)hasSameDurationAs:(OWSDisappearingMessagesConfiguration *)other
|
||||
{
|
||||
if (other.isEnabled != self.isEnabled) {
|
||||
return NO;
|
||||
}
|
||||
return other.durationSeconds == self.durationSeconds;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)other
|
||||
{
|
||||
if (![other isKindOfClass:[OWSDisappearingMessagesConfiguration class]]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
// [Mantle] TODO: This is wrong because it ignores uniqueId.
|
||||
|
||||
OWSDisappearingMessagesConfiguration *otherConfiguration = (OWSDisappearingMessagesConfiguration *)other;
|
||||
if (otherConfiguration.isEnabled != self.isEnabled) {
|
||||
return NO;
|
||||
}
|
||||
if (!self.isEnabled) {
|
||||
// Don't bother comparing durationSeconds if not enabled.
|
||||
return YES;
|
||||
}
|
||||
return otherConfiguration.durationSeconds == self.durationSeconds
|
||||
&& otherConfiguration.timerVersion == self.timerVersion;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,90 +0,0 @@
|
||||
//
|
||||
// Copyright 2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// A convenience wrapper around a disappearing message timer duration value that
|
||||
/// 1) handles seconds/millis conversion
|
||||
/// 2) deals internally with the fact that `0` means "not enabled".
|
||||
///
|
||||
/// See also ``VersionedDisappearingMessageToken``, which is the same thing but
|
||||
/// with an attached version that, at time of writing, used by 1:1 conversations (TSContactThread)
|
||||
/// which are subject to races in setting their DM timer config.
|
||||
@objc
|
||||
public final class DisappearingMessageToken: NSObject, NSSecureCoding, NSCopying {
|
||||
public static var supportsSecureCoding: Bool { true }
|
||||
|
||||
public init?(coder: NSCoder) {
|
||||
self.durationSeconds = coder.decodeObject(of: NSNumber.self, forKey: "durationSeconds")?.uint32Value ?? 0
|
||||
}
|
||||
|
||||
public func encode(with coder: NSCoder) {
|
||||
coder.encode(NSNumber(value: self.durationSeconds), forKey: "durationSeconds")
|
||||
}
|
||||
|
||||
override public var hash: Int {
|
||||
var hasher = Hasher()
|
||||
hasher.combine(durationSeconds)
|
||||
return hasher.finalize()
|
||||
}
|
||||
|
||||
override public func isEqual(_ object: Any?) -> Bool {
|
||||
guard let object = object as? Self else { return false }
|
||||
guard type(of: self) == type(of: object) else { return false }
|
||||
guard self.durationSeconds == object.durationSeconds else { return false }
|
||||
return true
|
||||
}
|
||||
|
||||
public func copy(with zone: NSZone? = nil) -> Any {
|
||||
return self
|
||||
}
|
||||
|
||||
@objc
|
||||
public var isEnabled: Bool {
|
||||
return durationSeconds > 0
|
||||
}
|
||||
|
||||
public let durationSeconds: UInt32
|
||||
|
||||
@objc
|
||||
public init(isEnabled: Bool, durationSeconds: UInt32) {
|
||||
// Consider disabled if duration is zero.
|
||||
// Use zero duration if not enabled.
|
||||
self.durationSeconds = isEnabled ? durationSeconds : 0
|
||||
|
||||
super.init()
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
public static var disabledToken: DisappearingMessageToken {
|
||||
return DisappearingMessageToken(isEnabled: false, durationSeconds: 0)
|
||||
}
|
||||
|
||||
public class func token(forProtoExpireTimerSeconds expireTimerSeconds: UInt32?) -> DisappearingMessageToken {
|
||||
if let expireTimerSeconds, expireTimerSeconds > 0 {
|
||||
return DisappearingMessageToken(isEnabled: true, durationSeconds: expireTimerSeconds)
|
||||
} else {
|
||||
return .disabledToken
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
public extension OWSDisappearingMessagesConfiguration {
|
||||
@objc
|
||||
var asToken: DisappearingMessageToken {
|
||||
return DisappearingMessageToken(isEnabled: isEnabled, durationSeconds: durationSeconds)
|
||||
}
|
||||
|
||||
var asVersionedToken: VersionedDisappearingMessageToken {
|
||||
return VersionedDisappearingMessageToken(
|
||||
isEnabled: isEnabled,
|
||||
durationSeconds: durationSeconds,
|
||||
version: timerVersion,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -11,7 +11,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@class DBWriteTransaction;
|
||||
@class MessageBody;
|
||||
@class MessageBodyRanges;
|
||||
@class OWSDisappearingMessagesConfiguration;
|
||||
@class SignalServiceAddress;
|
||||
@class TSInteraction;
|
||||
@class TSInvalidIdentityKeyReceivingErrorMessage;
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
//
|
||||
|
||||
#import "TSThread.h"
|
||||
#import "OWSDisappearingMessagesConfiguration.h"
|
||||
#import "OWSReadTracking.h"
|
||||
#import "TSIncomingMessage.h"
|
||||
#import "TSInfoMessage.h"
|
||||
|
||||
@ -145,7 +145,7 @@ final class ThreadMerger {
|
||||
}
|
||||
|
||||
let oldConfig = configPair.intoValue
|
||||
let newConfig = oldConfig.copyAsEnabled(withDurationSeconds: resolvedValue, timerVersion: resolvedVersion)
|
||||
let newConfig = oldConfig.copyAsEnabledWith(durationSeconds: resolvedValue, timerVersion: resolvedVersion)
|
||||
|
||||
if newConfig == oldConfig {
|
||||
return
|
||||
|
||||
@ -7,11 +7,11 @@ import Foundation
|
||||
|
||||
public protocol DisappearingMessagesConfigurationStore {
|
||||
typealias SetTokenResult = (
|
||||
oldConfiguration: OWSDisappearingMessagesConfiguration,
|
||||
newConfiguration: OWSDisappearingMessagesConfiguration,
|
||||
oldConfiguration: DisappearingMessagesConfigurationRecord,
|
||||
newConfiguration: DisappearingMessagesConfigurationRecord,
|
||||
)
|
||||
|
||||
func fetch(for scope: DisappearingMessagesConfigurationScope, tx: DBReadTransaction) -> OWSDisappearingMessagesConfiguration?
|
||||
func fetch(for scope: DisappearingMessagesConfigurationScope, tx: DBReadTransaction) -> DisappearingMessagesConfigurationRecord?
|
||||
|
||||
func remove(for thread: TSThread, tx: DBWriteTransaction)
|
||||
|
||||
@ -90,10 +90,10 @@ extension DisappearingMessagesConfigurationStore {
|
||||
public func fetchOrBuildDefault(
|
||||
for scope: DisappearingMessagesConfigurationScope,
|
||||
tx: DBReadTransaction,
|
||||
) -> OWSDisappearingMessagesConfiguration {
|
||||
fetch(for: scope, tx: tx) ?? OWSDisappearingMessagesConfiguration(
|
||||
threadId: scope.persistenceKey,
|
||||
enabled: false,
|
||||
) -> DisappearingMessagesConfigurationRecord {
|
||||
fetch(for: scope, tx: tx) ?? DisappearingMessagesConfigurationRecord(
|
||||
threadUniqueId: scope.persistenceKey,
|
||||
isEnabled: false,
|
||||
durationSeconds: 0,
|
||||
timerVersion: 1,
|
||||
)
|
||||
@ -105,9 +105,9 @@ extension DisappearingMessagesConfigurationStore {
|
||||
}
|
||||
|
||||
class DisappearingMessagesConfigurationStoreImpl: DisappearingMessagesConfigurationStore {
|
||||
func fetch(for scope: DisappearingMessagesConfigurationScope, tx: DBReadTransaction) -> OWSDisappearingMessagesConfiguration? {
|
||||
func fetch(for scope: DisappearingMessagesConfigurationScope, tx: DBReadTransaction) -> DisappearingMessagesConfigurationRecord? {
|
||||
guard
|
||||
let config = OWSDisappearingMessagesConfiguration.anyFetch(
|
||||
let config = DisappearingMessagesConfigurationRecord.anyFetch(
|
||||
uniqueId: scope.persistenceKey,
|
||||
transaction: tx,
|
||||
)
|
||||
@ -117,7 +117,7 @@ class DisappearingMessagesConfigurationStoreImpl: DisappearingMessagesConfigurat
|
||||
// What's in the database may have a nonzero duration but isEnabled=false.
|
||||
// Normalize so if isEnabled is false, duration is 0.
|
||||
if !config.isEnabled, config.durationSeconds != 0 {
|
||||
return config.copy(withDurationSeconds: 0, timerVersion: config.timerVersion)
|
||||
return config.copyWith(durationSeconds: 0, timerVersion: config.timerVersion)
|
||||
}
|
||||
return config
|
||||
}
|
||||
@ -143,8 +143,8 @@ class DisappearingMessagesConfigurationStoreImpl: DisappearingMessagesConfigurat
|
||||
let newVersion = token.version == 0 ? oldConfiguration.timerVersion : token.version
|
||||
let newConfiguration = (
|
||||
token.isEnabled
|
||||
? oldConfiguration.copyAsEnabled(withDurationSeconds: token.durationSeconds, timerVersion: newVersion)
|
||||
: oldConfiguration.copy(withIsEnabled: false, timerVersion: newVersion),
|
||||
? oldConfiguration.copyAsEnabledWith(durationSeconds: token.durationSeconds, timerVersion: newVersion)
|
||||
: oldConfiguration.copyWith(isEnabled: false, timerVersion: newVersion),
|
||||
)
|
||||
if newConfiguration.grdbId == nil || newConfiguration != oldConfiguration {
|
||||
newConfiguration.anyUpsert(transaction: tx)
|
||||
@ -158,8 +158,8 @@ class DisappearingMessagesConfigurationStoreImpl: DisappearingMessagesConfigurat
|
||||
|
||||
func resetAllDMTimerVersions(tx: DBWriteTransaction) throws {
|
||||
try tx.database.execute(sql: """
|
||||
UPDATE \(OWSDisappearingMessagesConfigurationSerializer.table.tableName)
|
||||
SET \(OWSDisappearingMessagesConfigurationSerializer.timerVersionColumn.columnName) = 1;
|
||||
UPDATE \(DisappearingMessagesConfigurationRecord.databaseTableName)
|
||||
SET \(DisappearingMessagesConfigurationRecord.CodingKeys.timerVersion.rawValue) = 1
|
||||
""")
|
||||
}
|
||||
}
|
||||
@ -167,9 +167,9 @@ class DisappearingMessagesConfigurationStoreImpl: DisappearingMessagesConfigurat
|
||||
#if TESTABLE_BUILD
|
||||
|
||||
class MockDisappearingMessagesConfigurationStore: DisappearingMessagesConfigurationStore {
|
||||
var values = [String: OWSDisappearingMessagesConfiguration]()
|
||||
var values = [String: DisappearingMessagesConfigurationRecord]()
|
||||
|
||||
func fetch(for scope: DisappearingMessagesConfigurationScope, tx: DBReadTransaction) -> OWSDisappearingMessagesConfiguration? {
|
||||
func fetch(for scope: DisappearingMessagesConfigurationScope, tx: DBReadTransaction) -> DisappearingMessagesConfigurationRecord? {
|
||||
values[scope.persistenceKey]
|
||||
}
|
||||
|
||||
@ -181,9 +181,9 @@ class MockDisappearingMessagesConfigurationStore: DisappearingMessagesConfigurat
|
||||
) -> SetTokenResult {
|
||||
let oldConfiguration = fetchOrBuildDefault(for: scope, tx: tx)
|
||||
let newVersion = oldConfiguration.timerVersion
|
||||
let newConfiguration = OWSDisappearingMessagesConfiguration(
|
||||
threadId: scope.persistenceKey,
|
||||
enabled: token.isEnabled,
|
||||
let newConfiguration = DisappearingMessagesConfigurationRecord(
|
||||
threadUniqueId: scope.persistenceKey,
|
||||
isEnabled: token.isEnabled,
|
||||
durationSeconds: token.durationSeconds,
|
||||
timerVersion: newVersion,
|
||||
)
|
||||
@ -197,9 +197,9 @@ class MockDisappearingMessagesConfigurationStore: DisappearingMessagesConfigurat
|
||||
|
||||
func resetAllDMTimerVersions(tx: DBWriteTransaction) throws {
|
||||
values.forEach { key, value in
|
||||
values[key] = OWSDisappearingMessagesConfiguration(
|
||||
threadId: value.uniqueId,
|
||||
enabled: value.isEnabled,
|
||||
values[key] = DisappearingMessagesConfigurationRecord(
|
||||
threadUniqueId: value.uniqueId,
|
||||
isEnabled: value.isEnabled,
|
||||
durationSeconds: value.durationSeconds,
|
||||
timerVersion: 1,
|
||||
)
|
||||
|
||||
@ -348,7 +348,7 @@ public class GroupManager: NSObject {
|
||||
)
|
||||
|
||||
// Skip redundant updates.
|
||||
if !result.newConfiguration.hasSameDuration(as: result.oldConfiguration) {
|
||||
if !result.newConfiguration.hasSameDurationAs(result.oldConfiguration) {
|
||||
let remoteContactName: String? = {
|
||||
if
|
||||
let changeAuthor,
|
||||
|
||||
@ -8,12 +8,12 @@ import Foundation
|
||||
@objc(OWSDisappearingMessagesConfigurationMessage)
|
||||
final class DisappearingMessagesConfigurationMessage: TransientOutgoingMessage {
|
||||
|
||||
private let configuration: OWSDisappearingMessagesConfiguration
|
||||
private let configuration: DisappearingMessagesConfigurationRecord
|
||||
|
||||
override var isUrgent: Bool { false }
|
||||
|
||||
init(
|
||||
configuration: OWSDisappearingMessagesConfiguration,
|
||||
configuration: DisappearingMessagesConfigurationRecord,
|
||||
thread: TSThread,
|
||||
tx: DBReadTransaction,
|
||||
) {
|
||||
@ -35,7 +35,7 @@ final class DisappearingMessagesConfigurationMessage: TransientOutgoingMessage {
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
guard let configuration = coder.decodeObject(of: OWSDisappearingMessagesConfiguration.self, forKey: "configuration") else {
|
||||
guard let configuration = coder.decodeObject(of: DisappearingMessagesConfigurationRecord.self, forKey: "configuration") else {
|
||||
return nil
|
||||
}
|
||||
self.configuration = configuration
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class OWSDisappearingMessagesConfiguration;
|
||||
@class TSContactThread;
|
||||
|
||||
@interface OWSDisappearingConfigurationUpdateInfoMessage : TSInfoMessage
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
//
|
||||
|
||||
#import "OWSDisappearingConfigurationUpdateInfoMessage.h"
|
||||
#import "OWSDisappearingMessagesConfiguration.h"
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
//
|
||||
|
||||
#import "OWSVerificationStateChangeMessage.h"
|
||||
#import "OWSDisappearingMessagesConfiguration.h"
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
//
|
||||
|
||||
#import "TSIncomingMessage.h"
|
||||
#import "OWSDisappearingMessagesConfiguration.h"
|
||||
#import "TSContactThread.h"
|
||||
#import "TSGroupThread.h"
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
//
|
||||
|
||||
#import "TSMessage.h"
|
||||
#import "OWSDisappearingMessagesConfiguration.h"
|
||||
#import "TSQuotedMessage.h"
|
||||
#import "TSThread.h"
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
|
||||
@ -19,7 +19,6 @@ FOUNDATION_EXPORT const unsigned char SignalServiceKitVersionString[];
|
||||
#import <SignalServiceKit/OWSArchivedPaymentMessage.h>
|
||||
#import <SignalServiceKit/OWSAsserts.h>
|
||||
#import <SignalServiceKit/OWSDisappearingConfigurationUpdateInfoMessage.h>
|
||||
#import <SignalServiceKit/OWSDisappearingMessagesConfiguration.h>
|
||||
#import <SignalServiceKit/OWSGroupCallMessage.h>
|
||||
#import <SignalServiceKit/OWSIncomingArchivedPaymentMessage.h>
|
||||
#import <SignalServiceKit/OWSIncomingPaymentMessage.h>
|
||||
|
||||
@ -795,15 +795,6 @@ public extension String {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
@objc
|
||||
public extension NSString {
|
||||
static func formatDurationLossless(durationSeconds: UInt32) -> String {
|
||||
String.formatDurationLossless(durationSeconds: durationSeconds)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Filename
|
||||
|
||||
public extension String {
|
||||
|
||||
@ -53,15 +53,3 @@ extension TimeInterval {
|
||||
return min(actualValue, UInt64(Int64.max))
|
||||
}
|
||||
}
|
||||
|
||||
@objcMembers
|
||||
@available(swift, obsoleted: 1)
|
||||
public class NSTimeIntervalConstants: NSObject {
|
||||
public static let second: TimeInterval = .second
|
||||
public static let minute: TimeInterval = .minute
|
||||
public static let hour: TimeInterval = .hour
|
||||
public static let day: TimeInterval = .day
|
||||
public static let week: TimeInterval = .week
|
||||
public static let month: TimeInterval = .month
|
||||
public static let year: TimeInterval = .year
|
||||
}
|
||||
|
||||
@ -21,8 +21,8 @@ class OWSDisappearingMessagesConfigurationTest: XCTestCase {
|
||||
func testEquality() {
|
||||
mockDB.read { tx in
|
||||
let value1 = store.fetchOrBuildDefault(for: .universal, tx: tx)
|
||||
let value2 = value1.copyAsEnabled(withDurationSeconds: 10, timerVersion: 1)
|
||||
let value3 = value2.copy(withIsEnabled: false, timerVersion: 1)
|
||||
let value2 = value1.copyAsEnabledWith(durationSeconds: 10, timerVersion: 1)
|
||||
let value3 = value2.copyWith(isEnabled: false, timerVersion: 1)
|
||||
XCTAssertNotEqual(value1, value2)
|
||||
XCTAssertNotEqual(value2, value3)
|
||||
XCTAssertEqual(value1, value3)
|
||||
|
||||
@ -140,15 +140,15 @@ final class ThreadMergerTest: XCTestCase {
|
||||
|
||||
private func setDisappearingMessageIntervals(serviceIdValue: UInt32?, phoneNumberValue: UInt32?) {
|
||||
disappearingMessagesConfigurationStore.values = [
|
||||
serviceIdThread.uniqueId: OWSDisappearingMessagesConfiguration(
|
||||
threadId: serviceIdThread.uniqueId,
|
||||
enabled: serviceIdValue != nil,
|
||||
serviceIdThread.uniqueId: DisappearingMessagesConfigurationRecord(
|
||||
threadUniqueId: serviceIdThread.uniqueId,
|
||||
isEnabled: serviceIdValue != nil,
|
||||
durationSeconds: serviceIdValue ?? 0,
|
||||
timerVersion: 1,
|
||||
),
|
||||
phoneNumberThread.uniqueId: OWSDisappearingMessagesConfiguration(
|
||||
threadId: phoneNumberThread.uniqueId,
|
||||
enabled: phoneNumberValue != nil,
|
||||
phoneNumberThread.uniqueId: DisappearingMessagesConfigurationRecord(
|
||||
threadUniqueId: phoneNumberThread.uniqueId,
|
||||
isEnabled: phoneNumberValue != nil,
|
||||
durationSeconds: phoneNumberValue ?? 0,
|
||||
timerVersion: 1,
|
||||
),
|
||||
|
||||
@ -29,7 +29,7 @@ public protocol ConversationItem {
|
||||
var image: UIImage? { get }
|
||||
var isBlocked: Bool { get }
|
||||
var isStory: Bool { get }
|
||||
var disappearingMessagesConfig: OWSDisappearingMessagesConfiguration? { get }
|
||||
var disappearingMessagesConfig: DisappearingMessagesConfigurationRecord? { get }
|
||||
|
||||
func getExistingThread(transaction: DBReadTransaction) -> TSThread?
|
||||
func getOrCreateThread(transaction: DBWriteTransaction) -> TSThread?
|
||||
@ -103,7 +103,7 @@ extension RecentConversationItem: ConversationItem {
|
||||
|
||||
var isStory: Bool { return false }
|
||||
|
||||
var disappearingMessagesConfig: OWSDisappearingMessagesConfiguration? {
|
||||
var disappearingMessagesConfig: DisappearingMessagesConfigurationRecord? {
|
||||
return unwrapped.disappearingMessagesConfig
|
||||
}
|
||||
|
||||
@ -121,13 +121,13 @@ extension RecentConversationItem: ConversationItem {
|
||||
struct ContactConversationItem {
|
||||
let address: SignalServiceAddress
|
||||
let isBlocked: Bool
|
||||
let disappearingMessagesConfig: OWSDisappearingMessagesConfiguration?
|
||||
let disappearingMessagesConfig: DisappearingMessagesConfigurationRecord?
|
||||
let comparableName: ComparableDisplayName
|
||||
|
||||
init(
|
||||
address: SignalServiceAddress,
|
||||
isBlocked: Bool,
|
||||
disappearingMessagesConfig: OWSDisappearingMessagesConfiguration?,
|
||||
disappearingMessagesConfig: DisappearingMessagesConfigurationRecord?,
|
||||
comparableName: ComparableDisplayName,
|
||||
) {
|
||||
owsAssertBeta(
|
||||
@ -189,12 +189,12 @@ extension ContactConversationItem: ConversationItem {
|
||||
public struct GroupConversationItem {
|
||||
public let groupThreadId: String
|
||||
public let isBlocked: Bool
|
||||
public let disappearingMessagesConfig: OWSDisappearingMessagesConfiguration?
|
||||
public let disappearingMessagesConfig: DisappearingMessagesConfigurationRecord?
|
||||
|
||||
init(
|
||||
groupThreadId: String,
|
||||
isBlocked: Bool,
|
||||
disappearingMessagesConfig: OWSDisappearingMessagesConfiguration?,
|
||||
disappearingMessagesConfig: DisappearingMessagesConfigurationRecord?,
|
||||
) {
|
||||
owsAssertBeta(
|
||||
!isBlocked,
|
||||
@ -571,7 +571,7 @@ extension StoryConversationItem: ConversationItem {
|
||||
|
||||
public var isStory: Bool { return true }
|
||||
|
||||
public var disappearingMessagesConfig: OWSDisappearingMessagesConfiguration? {
|
||||
public var disappearingMessagesConfig: DisappearingMessagesConfigurationRecord? {
|
||||
unwrapped.disappearingMessagesConfig
|
||||
}
|
||||
|
||||
@ -610,7 +610,7 @@ extension PrivateStoryConversationItem: ConversationItem {
|
||||
|
||||
public var isStory: Bool { return true }
|
||||
|
||||
public var disappearingMessagesConfig: OWSDisappearingMessagesConfiguration? { nil }
|
||||
public var disappearingMessagesConfig: DisappearingMessagesConfigurationRecord? { nil }
|
||||
|
||||
public var messageRecipient: MessageRecipient { .privateStory(storyThreadId, isMyStory: isMyStory) }
|
||||
|
||||
|
||||
@ -1369,7 +1369,7 @@ class ConversationPickerCell: ContactTableViewCell {
|
||||
return container
|
||||
}()
|
||||
|
||||
func buildAccessoryView(disappearingMessagesConfig: OWSDisappearingMessagesConfiguration?) -> ContactCellAccessoryView {
|
||||
func buildAccessoryView(disappearingMessagesConfig: DisappearingMessagesConfigurationRecord?) -> ContactCellAccessoryView {
|
||||
|
||||
selectionView.removeFromSuperview()
|
||||
let selectionWrapper = ManualLayoutView.wrapSubviewUsingIOSAutoLayout(selectionView)
|
||||
|
||||
@ -16,7 +16,7 @@ public class ThreadViewModel: NSObject {
|
||||
public let shortName: String?
|
||||
public let associatedData: ThreadAssociatedData
|
||||
public let hasPendingMessageRequest: Bool
|
||||
public let disappearingMessagesConfiguration: OWSDisappearingMessagesConfiguration
|
||||
public let disappearingMessagesConfiguration: DisappearingMessagesConfigurationRecord
|
||||
public let isBlocked: Bool
|
||||
public let isPinned: Bool
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user