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:
 | 
						|
            owsFail("\(self.logTag) in \(#function) unexepected 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
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |