Signal-iOS/SignalServiceKit/Contacts/DisappearingMessagesConfigurationStore.swift
2024-03-27 12:22:52 -05:00

116 lines
4.1 KiB
Swift

//
// Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import Foundation
public protocol DisappearingMessagesConfigurationStore {
func fetch(for scope: DisappearingMessagesConfigurationScope, tx: DBReadTransaction) -> OWSDisappearingMessagesConfiguration?
func remove(for thread: TSThread, tx: DBWriteTransaction)
@discardableResult
func set(
token: DisappearingMessageToken,
for scope: DisappearingMessagesConfigurationScope,
tx: DBWriteTransaction
) -> (oldConfiguration: OWSDisappearingMessagesConfiguration, newConfiguration: OWSDisappearingMessagesConfiguration)
}
public enum DisappearingMessagesConfigurationScope {
case universal
case thread(TSThread)
private enum Constants {
/// The persistence key for the global setting for new chats.
static let universalThreadId = "kUniversalTimerThreadId"
}
fileprivate var persistenceKey: String {
switch self {
case .universal:
return Constants.universalThreadId
case .thread(let thread):
return thread.uniqueId
}
}
}
extension DisappearingMessagesConfigurationStore {
public func fetchOrBuildDefault(
for scope: DisappearingMessagesConfigurationScope,
tx: DBReadTransaction
) -> OWSDisappearingMessagesConfiguration {
fetch(for: scope, tx: tx) ?? OWSDisappearingMessagesConfiguration(
threadId: scope.persistenceKey,
enabled: false,
durationSeconds: 0
)
}
public func durationSeconds(for thread: TSThread, tx: DBReadTransaction) -> UInt32 {
fetchOrBuildDefault(for: .thread(thread), tx: tx).asToken.durationSeconds
}
}
class DisappearingMessagesConfigurationStoreImpl: DisappearingMessagesConfigurationStore {
func fetch(for scope: DisappearingMessagesConfigurationScope, tx: DBReadTransaction) -> OWSDisappearingMessagesConfiguration? {
OWSDisappearingMessagesConfiguration.anyFetch(uniqueId: scope.persistenceKey, transaction: SDSDB.shimOnlyBridge(tx))
}
@discardableResult
func set(
token: DisappearingMessageToken,
for scope: DisappearingMessagesConfigurationScope,
tx: DBWriteTransaction
) -> (oldConfiguration: OWSDisappearingMessagesConfiguration, newConfiguration: OWSDisappearingMessagesConfiguration) {
let oldConfiguration = fetchOrBuildDefault(for: scope, tx: tx)
let newConfiguration = (
token.isEnabled
? oldConfiguration.copyAsEnabled(withDurationSeconds: token.durationSeconds)
: oldConfiguration.copy(withIsEnabled: false)
)
if newConfiguration.grdbId == nil || newConfiguration != oldConfiguration {
newConfiguration.anyUpsert(transaction: SDSDB.shimOnlyBridge(tx))
}
return (oldConfiguration, newConfiguration)
}
func remove(for thread: TSThread, tx: DBWriteTransaction) {
fetch(for: .thread(thread), tx: tx)?.anyRemove(transaction: SDSDB.shimOnlyBridge(tx))
}
}
#if TESTABLE_BUILD
class MockDisappearingMessagesConfigurationStore: DisappearingMessagesConfigurationStore {
var values = [String: OWSDisappearingMessagesConfiguration]()
func fetch(for scope: DisappearingMessagesConfigurationScope, tx: DBReadTransaction) -> OWSDisappearingMessagesConfiguration? {
values[scope.persistenceKey]
}
@discardableResult
func set(
token: DisappearingMessageToken,
for scope: DisappearingMessagesConfigurationScope,
tx: DBWriteTransaction
) -> (oldConfiguration: OWSDisappearingMessagesConfiguration, newConfiguration: OWSDisappearingMessagesConfiguration) {
let oldConfiguration = fetchOrBuildDefault(for: scope, tx: tx)
let newConfiguration = OWSDisappearingMessagesConfiguration(
threadId: scope.persistenceKey,
enabled: token.isEnabled,
durationSeconds: token.durationSeconds
)
values[scope.persistenceKey] = newConfiguration
return (oldConfiguration, newConfiguration)
}
func remove(for thread: TSThread, tx: DBWriteTransaction) {
values[thread.uniqueId] = nil
}
}
#endif