BlockListCache
block manager synchronizes on self for coherent read/writes to blocking state across threads, but we want to be able to have performant reads on the main thread.
This commit is contained in:
parent
28d28cf2b6
commit
448936d156
|
@ -442,6 +442,7 @@
|
|||
4C63CC00210A620B003AE45C /* SignalTSan.supp in Resources */ = {isa = PBXBuildFile; fileRef = 4C63CBFF210A620B003AE45C /* SignalTSan.supp */; };
|
||||
4C6F527C20FFE8400097DEEE /* SignalUBSan.supp in Resources */ = {isa = PBXBuildFile; fileRef = 4C6F527B20FFE8400097DEEE /* SignalUBSan.supp */; };
|
||||
4C858A52212DC5E1001B45D3 /* UIImage+OWS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C858A51212DC5E1001B45D3 /* UIImage+OWS.swift */; };
|
||||
4C948FF72146EB4800349F0D /* BlockListCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C948FF62146EB4800349F0D /* BlockListCache.swift */; };
|
||||
4CA5F793211E1F06008C2708 /* Toast.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CA5F792211E1F06008C2708 /* Toast.swift */; };
|
||||
4CB5F26720F6E1E2004D1B42 /* MenuActionsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CFF4C0920F55BBA005DA313 /* MenuActionsViewController.swift */; };
|
||||
4CB5F26920F7D060004D1B42 /* MessageActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB5F26820F7D060004D1B42 /* MessageActions.swift */; };
|
||||
|
@ -1131,6 +1132,7 @@
|
|||
4C63CBFF210A620B003AE45C /* SignalTSan.supp */ = {isa = PBXFileReference; lastKnownFileType = text; path = SignalTSan.supp; sourceTree = "<group>"; };
|
||||
4C6F527B20FFE8400097DEEE /* SignalUBSan.supp */ = {isa = PBXFileReference; lastKnownFileType = text; path = SignalUBSan.supp; sourceTree = "<group>"; };
|
||||
4C858A51212DC5E1001B45D3 /* UIImage+OWS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+OWS.swift"; sourceTree = "<group>"; };
|
||||
4C948FF62146EB4800349F0D /* BlockListCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockListCache.swift; sourceTree = "<group>"; };
|
||||
4CA5F792211E1F06008C2708 /* Toast.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toast.swift; sourceTree = "<group>"; };
|
||||
4CB5F26820F7D060004D1B42 /* MessageActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageActions.swift; sourceTree = "<group>"; };
|
||||
4CC0B59B20EC5F2E00CF6EE0 /* ConversationConfigurationSyncOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationConfigurationSyncOperation.swift; sourceTree = "<group>"; };
|
||||
|
@ -1563,6 +1565,7 @@
|
|||
B97940261832BD2400BD66CB /* UIUtil.m */,
|
||||
45F170D51E315310003FC1F2 /* Weak.swift */,
|
||||
4C858A51212DC5E1001B45D3 /* UIImage+OWS.swift */,
|
||||
4C948FF62146EB4800349F0D /* BlockListCache.swift */,
|
||||
);
|
||||
path = utils;
|
||||
sourceTree = "<group>";
|
||||
|
@ -3269,6 +3272,7 @@
|
|||
34480B561FD0A7A400BC14EF /* DebugLogger.m in Sources */,
|
||||
459B775C207BA46C0071D0AB /* OWSQuotedReplyModel.m in Sources */,
|
||||
34ABB2C42090C59700C727A6 /* OWSResaveCollectionDBMigration.m in Sources */,
|
||||
4C948FF72146EB4800349F0D /* BlockListCache.swift in Sources */,
|
||||
4551DB5A205C562300C8AE75 /* Collection+OWS.swift in Sources */,
|
||||
34AC09ED211B39B100997B47 /* ContactFieldView.swift in Sources */,
|
||||
346129AF1FD1F5D900532771 /* SystemContactsFetcher.swift in Sources */,
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
#import <PromiseKit/AnyPromise.h>
|
||||
#import <SignalMessaging/OWSContactsManager.h>
|
||||
#import <SignalMessaging/OWSFormat.h>
|
||||
#import <SignalMessaging/SignalMessaging-Swift.h>
|
||||
#import <SignalMessaging/UIUtil.h>
|
||||
#import <SignalServiceKit/NSDate+OWS.h>
|
||||
#import <SignalServiceKit/OWSBlockingManager.h>
|
||||
#import <SignalServiceKit/OWSMessageSender.h>
|
||||
#import <SignalServiceKit/OWSMessageUtils.h>
|
||||
#import <SignalServiceKit/TSAccountManager.h>
|
||||
|
@ -64,7 +64,8 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations
|
|||
UITableViewDataSource,
|
||||
UIViewControllerPreviewingDelegate,
|
||||
UISearchBarDelegate,
|
||||
ConversationSearchViewDelegate>
|
||||
ConversationSearchViewDelegate,
|
||||
OWSBlockListCacheDelegate>
|
||||
|
||||
@property (nonatomic) UITableView *tableView;
|
||||
@property (nonatomic) UILabel *emptyBoxLabel;
|
||||
|
@ -89,7 +90,7 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations
|
|||
@property (nonatomic, readonly) AccountManager *accountManager;
|
||||
@property (nonatomic, readonly) OWSContactsManager *contactsManager;
|
||||
@property (nonatomic, readonly) OWSMessageSender *messageSender;
|
||||
@property (nonatomic, readonly) OWSBlockingManager *blockingManager;
|
||||
@property (nonatomic, readonly) OWSBlockListCache *blocklistCache;
|
||||
|
||||
// Views
|
||||
|
||||
|
@ -147,7 +148,8 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations
|
|||
_accountManager = SignalApp.sharedApp.accountManager;
|
||||
_contactsManager = [Environment current].contactsManager;
|
||||
_messageSender = [Environment current].messageSender;
|
||||
_blockingManager = [OWSBlockingManager sharedManager];
|
||||
_blocklistCache = [OWSBlockListCache new];
|
||||
[_blocklistCache startObservingAndSyncStateWithDelegate:self];
|
||||
_threadViewModelCache = [NSCache new];
|
||||
|
||||
// Ensure ExperienceUpgradeFinder has been initialized.
|
||||
|
@ -835,7 +837,7 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations
|
|||
|
||||
ThreadViewModel *thread = [self threadViewModelForIndexPath:indexPath];
|
||||
|
||||
BOOL isBlocked = [self.blockingManager isThreadBlocked:thread.threadRecord];
|
||||
BOOL isBlocked = [self.blocklistCache isThreadBlocked:thread.threadRecord];
|
||||
[cell configureWithThread:thread contactsManager:self.contactsManager isBlocked:isBlocked];
|
||||
|
||||
return cell;
|
||||
|
@ -1544,6 +1546,14 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations
|
|||
}
|
||||
}
|
||||
|
||||
#pragma mark - OWSBlockListCacheDelegate
|
||||
|
||||
- (void)blockListCacheDidUpdate:(OWSBlockListCache *_Nonnull)blocklistCache
|
||||
{
|
||||
DDLogVerbose(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__);
|
||||
[self reloadTableViewData];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
//
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc(OWSBlockListCacheDelegate)
|
||||
public protocol BlockListCacheDelegate: class {
|
||||
func blockListCacheDidUpdate(_ blocklistCache: BlockListCache)
|
||||
}
|
||||
|
||||
@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
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue