mirror of https://github.com/oxen-io/session-ios
				
				
				
			
			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.
		
		
		
		
		
			
		
			
				
	
	
		
			123 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Swift
		
	
			
		
		
	
	
			123 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Swift
		
	
| //
 | |
| //  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
 | |
|         }
 | |
|     }
 | |
| }
 |