You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
session-ios/SessionUtilitiesKit/General/Dependencies.swift

150 lines
4.9 KiB
Swift

// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import GRDB
public class Dependencies {
private var _storage: Atomic<Storage?>
public var storage: Storage {
get { Dependencies.getValueSettingIfNull(&_storage) { Storage.shared } }
set { _storage.mutate { $0 = newValue } }
Fixed a number of issues found during internal testing Added copy for an unrecoverable startup case Added some additional logs to better debug ValueObservation query errors Increased the pageSize to 20 on iPad devices (to prevent it immediately loading a second page) Cleaned up a bunch of threading logic (try to avoid overriding subscribe/receive threads specified at subscription) Consolidated the 'sendMessage' and 'sendAttachments' functions Updated the various frameworks to use 'DAWRF with DSYM' to allow for better debugging during debug mode (at the cost of a longer build time) Updated the logic to optimistically insert messages when sending to avoid any database write delays Updated the logic to avoid sending notifications for messages which are already marked as read by the config Fixed an issue where multiple paths could incorrectly get built at the same time in some cases Fixed an issue where other job queues could be started before the blockingQueue finishes Fixed a potential bug with the snode version comparison (was just a string comparison which would fail when getting to double-digit values) Fixed a bug where you couldn't remove the last reaction on a message Fixed the broken media message zoom animations Fixed a bug where the last message read in a conversation wouldn't be correctly detected as already read Fixed a bug where the QuoteView had no line limits (resulting in the '@You' mention background highlight being incorrectly positioned in the quote preview) Fixed a bug where a large number of configSyncJobs could be scheduled (only one would run at a time but this could result in performance impacts)
1 year ago
}
private var _network: Atomic<NetworkType?>
public var network: NetworkType {
get { Dependencies.getValueSettingIfNull(&_network) { Network() } }
set { _network.mutate { $0 = newValue } }
}
private var _crypto: Atomic<CryptoType?>
public var crypto: CryptoType {
get { Dependencies.getValueSettingIfNull(&_crypto) { Crypto() } }
set { _crypto.mutate { $0 = newValue } }
}
private var _standardUserDefaults: Atomic<UserDefaultsType?>
public var standardUserDefaults: UserDefaultsType {
get { Dependencies.getValueSettingIfNull(&_standardUserDefaults) { UserDefaults.standard } }
set { _standardUserDefaults.mutate { $0 = newValue } }
}
private var _caches: CachesType
public var caches: CachesType {
get { _caches }
set { _caches = newValue }
}
private var _jobRunner: Atomic<JobRunnerType?>
public var jobRunner: JobRunnerType {
get { Dependencies.getValueSettingIfNull(&_jobRunner) { JobRunner.instance } }
set { _jobRunner.mutate { $0 = newValue } }
}
private var _scheduler: Atomic<ValueObservationScheduler?>
public var scheduler: ValueObservationScheduler {
get { Dependencies.getValueSettingIfNull(&_scheduler) { Storage.defaultPublisherScheduler } }
set { _scheduler.mutate { $0 = newValue } }
}
private var _dateNow: Atomic<Date?>
public var dateNow: Date {
get { (_dateNow.wrappedValue ?? Date()) }
set { _dateNow.mutate { $0 = newValue } }
}
private var _fixedTime: Atomic<Int?>
public var fixedTime: Int {
get { Dependencies.getValueSettingIfNull(&_fixedTime) { 0 } }
set { _fixedTime.mutate { $0 = newValue } }
}
private var _forceSynchronous: Bool
public var forceSynchronous: Bool {
get { _forceSynchronous }
set { _forceSynchronous = newValue }
}
public var asyncExecutions: [Int: [() -> Void]] = [:]
// MARK: - Initialization
public init(
storage: Storage? = nil,
network: NetworkType? = nil,
crypto: CryptoType? = nil,
standardUserDefaults: UserDefaultsType? = nil,
caches: CachesType = Caches(),
jobRunner: JobRunnerType? = nil,
scheduler: ValueObservationScheduler? = nil,
dateNow: Date? = nil,
fixedTime: Int? = nil,
forceSynchronous: Bool = false
) {
_storage = Atomic(storage)
_network = Atomic(network)
_crypto = Atomic(crypto)
_standardUserDefaults = Atomic(standardUserDefaults)
_caches = caches
_jobRunner = Atomic(jobRunner)
_scheduler = Atomic(scheduler)
_dateNow = Atomic(dateNow)
_fixedTime = Atomic(fixedTime)
_forceSynchronous = forceSynchronous
}
// MARK: - Convenience
private static func getValueSettingIfNull<T>(_ maybeValue: inout Atomic<T?>, _ valueGenerator: () -> T) -> T {
guard let value: T = maybeValue.wrappedValue else {
let value: T = valueGenerator()
maybeValue.mutate { $0 = value }
return value
}
return value
}
private static func getMutableValueSettingIfNull<T>(_ maybeValue: inout Atomic<T?>, _ valueGenerator: () -> T) -> Atomic<T> {
guard let value: T = maybeValue.wrappedValue else {
let value: T = valueGenerator()
maybeValue.mutate { $0 = value }
return Atomic(value)
}
return Atomic(value)
}
#if DEBUG
public func stepForwardInTime() {
let targetTime: Int = ((_fixedTime.wrappedValue ?? 0) + 1)
_fixedTime.mutate { $0 = targetTime }
if let currentDate: Date = _dateNow.wrappedValue {
_dateNow.mutate { $0 = Date(timeIntervalSince1970: currentDate.timeIntervalSince1970 + 1) }
}
// Run and clear any executions which should run at the target time
let targetKeys: [Int] = asyncExecutions.keys
.filter { $0 <= targetTime }
targetKeys.forEach { key in
asyncExecutions[key]?.forEach { $0() }
asyncExecutions[key] = nil
}
}
#endif
// MARK: - Random Access Functions
public func randomElement<T: Collection>(_ collection: T) -> T.Element? {
return collection.randomElement()
}
public func randomElement<T>(_ elements: Set<T>) -> T? {
return elements.randomElement()
}
public func popRandomElement<T>(_ elements: inout Set<T>) -> T? {
return elements.popRandomElement()
}
}