mirror of https://github.com/oxen-io/session-ios
mirror of https://github.com/oxen-io/session-ios
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
4.1 KiB
122 lines
4.1 KiB
// |
|
// Copyright (c) 2018 Open Whisper Systems. All rights reserved. |
|
// |
|
|
|
import Foundation |
|
|
|
@objc(OWSBlockListCacheDelegate) |
|
public protocol BlockListCacheDelegate: class { |
|
func blockListCacheDidUpdate(_ blocklistCache: BlockListCache) |
|
} |
|
|
|
/// A performant cache for which contacts/groups are blocked. |
|
/// |
|
/// The source of truth for which contacts and groups are blocked is the `blockingManager`, but because |
|
/// those accessors are made to be thread safe, they can be slow in tight loops, e.g. when rendering table |
|
/// view cells. |
|
/// |
|
/// Typically you'll want to create a Cache, update it to the latest state while simultaneously being informed |
|
/// of any future changes to block list state. |
|
/// |
|
/// class SomeViewController: BlockListCacheDelegate { |
|
/// let blockListCache = BlockListCache() |
|
/// func viewDidLoad() { |
|
/// super.viewDidLoad() |
|
/// blockListCache.startObservingAndSyncState(delegate: self) |
|
/// self.updateAnyViewsWhichDepondOnBlockListCache() |
|
/// } |
|
/// |
|
/// func blockListCacheDidUpdate(_ blocklistCache: BlockListCache) { |
|
/// self.updateAnyViewsWhichDepondOnBlockListCache() |
|
/// } |
|
/// |
|
/// ... |
|
/// } |
|
/// |
|
@objc(OWSBlockListCache) |
|
public class BlockListCache: NSObject { |
|
|
|
private var blockedRecipientIds: Set<String> = Set() |
|
private var blockedGroupIds: Set<Data> = Set() |
|
private let serialQueue: DispatchQueue = DispatchQueue(label: "BlockListCache") |
|
weak var delegate: BlockListCacheDelegate? |
|
|
|
private var blockingManager: OWSBlockingManager { |
|
return OWSBlockingManager.shared() |
|
} |
|
|
|
/// Generally something which wants to use this cache wants to do 3 things |
|
/// 1. get the cache on the latest state |
|
/// 2. update the cache whenever the blockingManager's state changes |
|
/// 3. be notified when the cache updates |
|
/// This method does all three. |
|
@objc |
|
public func startObservingAndSyncState(delegate: BlockListCacheDelegate) { |
|
self.delegate = delegate |
|
NotificationCenter.default.addObserver(self, |
|
selector: #selector(blockListDidChange), |
|
name: NSNotification.Name(rawValue: kNSNotificationName_BlockListDidChange), |
|
object: nil) |
|
updateWithoutNotifyingDelegate() |
|
} |
|
|
|
// MARK: - |
|
|
|
@objc |
|
func blockListDidChange() { |
|
self.update() |
|
} |
|
|
|
@objc(isRecipientIdBlocked:) |
|
public func isBlocked(recipientId: String) -> Bool { |
|
return serialQueue.sync { |
|
blockedRecipientIds.contains(recipientId) |
|
} |
|
} |
|
|
|
@objc(isGroupIdBlocked:) |
|
public func isBlocked(groupId: Data) -> Bool { |
|
return serialQueue.sync { |
|
blockedGroupIds.contains(groupId) |
|
} |
|
} |
|
|
|
@objc(isThreadBlocked:) |
|
public func isBlocked(thread: TSThread) -> Bool { |
|
switch thread { |
|
case let contactThread as TSContactThread: |
|
return serialQueue.sync { |
|
blockedRecipientIds.contains(contactThread.contactIdentifier()) |
|
} |
|
case let groupThread as TSGroupThread: |
|
return serialQueue.sync { |
|
blockedGroupIds.contains(groupThread.groupModel.groupId) |
|
} |
|
default: |
|
owsFailDebug("\(self.logTag) in \(#function) unexpected thread type: \(type(of: thread))") |
|
return false |
|
} |
|
} |
|
|
|
// MARK: - |
|
|
|
public func update() { |
|
updateWithoutNotifyingDelegate() |
|
DispatchQueue.main.async { |
|
self.delegate?.blockListCacheDidUpdate(self) |
|
} |
|
} |
|
|
|
private func updateWithoutNotifyingDelegate() { |
|
let blockedRecipientIds = Set(blockingManager.blockedPhoneNumbers()) |
|
let blockedGroupIds = Set(blockingManager.blockedGroupIds) |
|
update(blockedRecipientIds: blockedRecipientIds, blockedGroupIds: blockedGroupIds) |
|
} |
|
|
|
private func update(blockedRecipientIds: Set<String>, blockedGroupIds: Set<Data>) { |
|
serialQueue.sync { |
|
self.blockedRecipientIds = blockedRecipientIds |
|
self.blockedGroupIds = blockedGroupIds |
|
} |
|
} |
|
}
|
|
|