WIP: group blocking
-[ ] UI -[ ] Conversation Settings -[x] Show switch for group -[ ] localize -[ ] migrate existing localizations? (nice to have) -[ ] can view conversation settings (but not edit them) in left group -[ ] special block copy for groups -[ ] special unblock copy for groups -[ ] Block List -[ ] Group Section -[ ] Unblock group -[ ] Interstitial interacting with blocked threads (e.g. thread picker) -[ ] BlockListUIUtils w/ thread -[x] Block -[x] Unblock -[ ] Replace usages where possible -[x] block manager -[ ] Sync -[x] tentative protos -[ ] confirm protos w/ team -[ ] send new protos -[ ] Message Processing -[ ] Drop messages from blocked groups
This commit is contained in:
parent
bfe1f38c75
commit
236c17f65e
|
@ -617,35 +617,48 @@ const CGFloat kIconViewLength = 24;
|
|||
= NSLocalizedString(@"MUTE_BEHAVIOR_EXPLANATION", @"An explanation of the consequences of muting a thread.");
|
||||
[contents addSection:notificationsSection];
|
||||
|
||||
// Block user section.
|
||||
// Block Conversation section.
|
||||
|
||||
if (!self.isGroupThread) {
|
||||
BOOL isBlocked = [[_blockingManager blockedPhoneNumbers] containsObject:self.thread.contactIdentifier];
|
||||
|
||||
OWSTableSection *section = [OWSTableSection new];
|
||||
OWSTableSection *section = [OWSTableSection new];
|
||||
if (self.thread.isGroupThread) {
|
||||
section.footerTitle = NSLocalizedString(
|
||||
@"BLOCK_BEHAVIOR_EXPLANATION", @"An explanation of the consequences of blocking another user.");
|
||||
[section addItem:[OWSTableItem itemWithCustomCellBlock:^{
|
||||
UITableViewCell *cell =
|
||||
[weakSelf disclosureCellWithName:NSLocalizedString(@"CONVERSATION_SETTINGS_BLOCK_THIS_USER",
|
||||
@"table cell label in conversation settings")
|
||||
iconName:@"table_ic_block"];
|
||||
OWSConversationSettingsViewController *strongSelf = weakSelf;
|
||||
OWSCAssert(strongSelf);
|
||||
cell.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||
|
||||
UISwitch *blockUserSwitch = [UISwitch new];
|
||||
blockUserSwitch.on = isBlocked;
|
||||
[blockUserSwitch addTarget:strongSelf
|
||||
action:@selector(blockUserSwitchDidChange:)
|
||||
forControlEvents:UIControlEventValueChanged];
|
||||
cell.accessoryView = blockUserSwitch;
|
||||
return cell;
|
||||
}
|
||||
actionBlock:nil]];
|
||||
[contents addSection:section];
|
||||
@"BLOCK_GROUP_BEHAVIOR_EXPLANATION", @"An explanation of the consequences of blocking another user.");
|
||||
} else {
|
||||
section.footerTitle = NSLocalizedString(
|
||||
@"BLOCK_USER_BEHAVIOR_EXPLANATION", @"An explanation of the consequences of blocking a group.");
|
||||
}
|
||||
|
||||
[section addItem:[OWSTableItem
|
||||
itemWithCustomCellBlock:^{
|
||||
OWSConversationSettingsViewController *strongSelf = weakSelf;
|
||||
if (!strongSelf) {
|
||||
return [UITableViewCell new];
|
||||
}
|
||||
|
||||
NSString *cellTitle;
|
||||
if (self.thread.isGroupThread) {
|
||||
cellTitle = NSLocalizedString(@"CONVERSATION_SETTINGS_BLOCK_THIS_GROUP",
|
||||
@"table cell label in conversation settings");
|
||||
} else {
|
||||
cellTitle = NSLocalizedString(@"CONVERSATION_SETTINGS_BLOCK_THIS_USER",
|
||||
@"table cell label in conversation settings");
|
||||
}
|
||||
UITableViewCell *cell =
|
||||
[strongSelf disclosureCellWithName:cellTitle iconName:@"table_ic_block"];
|
||||
|
||||
cell.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||
|
||||
UISwitch *blockConversationSwitch = [UISwitch new];
|
||||
blockConversationSwitch.on = [strongSelf.blockingManager isThreadBlocked:self.thread];
|
||||
[blockConversationSwitch addTarget:strongSelf
|
||||
action:@selector(blockConversationSwitchDidChange:)
|
||||
forControlEvents:UIControlEventValueChanged];
|
||||
cell.accessoryView = blockConversationSwitch;
|
||||
return cell;
|
||||
}
|
||||
actionBlock:nil]];
|
||||
[contents addSection:section];
|
||||
|
||||
self.contents = contents;
|
||||
}
|
||||
|
||||
|
@ -1013,43 +1026,41 @@ const CGFloat kIconViewLength = 24;
|
|||
[self updateTableContents];
|
||||
}
|
||||
|
||||
- (void)blockUserSwitchDidChange:(id)sender
|
||||
- (void)blockConversationSwitchDidChange:(id)sender
|
||||
{
|
||||
OWSAssert(!self.isGroupThread);
|
||||
|
||||
if (![sender isKindOfClass:[UISwitch class]]) {
|
||||
OWSFail(@"%@ Unexpected sender for block user switch: %@", self.logTag, sender);
|
||||
}
|
||||
UISwitch *blockUserSwitch = (UISwitch *)sender;
|
||||
UISwitch *blockConversationSwitch = (UISwitch *)sender;
|
||||
|
||||
BOOL isCurrentlyBlocked = [[_blockingManager blockedPhoneNumbers] containsObject:self.thread.contactIdentifier];
|
||||
BOOL isCurrentlyBlocked = [self.blockingManager isThreadBlocked:self.thread];
|
||||
|
||||
if (blockUserSwitch.isOn) {
|
||||
if (blockConversationSwitch.isOn) {
|
||||
OWSAssert(!isCurrentlyBlocked);
|
||||
if (isCurrentlyBlocked) {
|
||||
return;
|
||||
}
|
||||
[BlockListUIUtils showBlockPhoneNumberActionSheet:self.thread.contactIdentifier
|
||||
fromViewController:self
|
||||
blockingManager:_blockingManager
|
||||
contactsManager:_contactsManager
|
||||
completionBlock:^(BOOL isBlocked) {
|
||||
// Update switch state if user cancels action.
|
||||
blockUserSwitch.on = isBlocked;
|
||||
}];
|
||||
[BlockListUIUtils showBlockThreadActionSheet:self.thread
|
||||
fromViewController:self
|
||||
blockingManager:_blockingManager
|
||||
contactsManager:_contactsManager
|
||||
completionBlock:^(BOOL isBlocked) {
|
||||
// Update switch state if user cancels action.
|
||||
blockConversationSwitch.on = isBlocked;
|
||||
}];
|
||||
} else {
|
||||
OWSAssert(isCurrentlyBlocked);
|
||||
if (!isCurrentlyBlocked) {
|
||||
return;
|
||||
}
|
||||
[BlockListUIUtils showUnblockPhoneNumberActionSheet:self.thread.contactIdentifier
|
||||
fromViewController:self
|
||||
blockingManager:_blockingManager
|
||||
contactsManager:_contactsManager
|
||||
completionBlock:^(BOOL isBlocked) {
|
||||
// Update switch state if user cancels action.
|
||||
blockUserSwitch.on = isBlocked;
|
||||
}];
|
||||
[BlockListUIUtils showUnblockThreadActionSheet:self.thread
|
||||
fromViewController:self
|
||||
blockingManager:_blockingManager
|
||||
contactsManager:_contactsManager
|
||||
completionBlock:^(BOOL isBlocked) {
|
||||
// Update switch state if user cancels action.
|
||||
blockConversationSwitch.on = isBlocked;
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -227,6 +227,9 @@
|
|||
/* An explanation of the consequences of blocking another user. */
|
||||
"BLOCK_BEHAVIOR_EXPLANATION" = "Blocked users will not be able to call you or send you messages.";
|
||||
|
||||
/* An explanation of the consequences of blocking another user. */
|
||||
"BLOCK_GROUP_BEHAVIOR_EXPLANATION" = "BLOCK_GROUP_BEHAVIOR_EXPLANATION";
|
||||
|
||||
/* Button label for the 'block' button */
|
||||
"BLOCK_LIST_BLOCK_BUTTON" = "Block";
|
||||
|
||||
|
@ -278,6 +281,9 @@
|
|||
/* Title format for action sheet that offers to block an unknown user.Embeds {{the unknown user's name or phone number}}. */
|
||||
"BLOCK_OFFER_ACTIONSHEET_TITLE_FORMAT" = "Block %@?";
|
||||
|
||||
/* An explanation of the consequences of blocking a group. */
|
||||
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "BLOCK_USER_BEHAVIOR_EXPLANATION";
|
||||
|
||||
/* Label for 'continue' button. */
|
||||
"BUTTON_CONTINUE" = "Continue";
|
||||
|
||||
|
@ -512,6 +518,9 @@
|
|||
/* Label for 'new contact' button in conversation settings view. */
|
||||
"CONVERSATION_SETTINGS_ADD_TO_EXISTING_CONTACT" = "Add to Existing Contact";
|
||||
|
||||
/* table cell label in conversation settings */
|
||||
"CONVERSATION_SETTINGS_BLOCK_THIS_GROUP" = "CONVERSATION_SETTINGS_BLOCK_THIS_GROUP";
|
||||
|
||||
/* table cell label in conversation settings */
|
||||
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "Block this user";
|
||||
|
||||
|
|
|
@ -238,21 +238,19 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
return;
|
||||
}
|
||||
|
||||
if ([thread isKindOfClass:[TSContactThread class]]) {
|
||||
BOOL isBlocked = [helper isRecipientIdBlocked:thread.contactIdentifier];
|
||||
if (isBlocked && ![strongSelf.selectThreadViewDelegate canSelectBlockedContact]) {
|
||||
[BlockListUIUtils showUnblockPhoneNumberActionSheet:thread.contactIdentifier
|
||||
fromViewController:strongSelf
|
||||
blockingManager:helper.blockingManager
|
||||
contactsManager:helper.contactsManager
|
||||
completionBlock:^(BOOL isStillBlocked) {
|
||||
if (!isStillBlocked) {
|
||||
[strongSelf.selectThreadViewDelegate
|
||||
threadWasSelected:thread];
|
||||
}
|
||||
}];
|
||||
return;
|
||||
}
|
||||
BOOL isBlocked = [helper isThreadBlocked:thread];
|
||||
if (isBlocked && ![strongSelf.selectThreadViewDelegate canSelectBlockedContact]) {
|
||||
[BlockListUIUtils
|
||||
showUnblockThreadActionSheet:thread
|
||||
fromViewController:strongSelf
|
||||
blockingManager:helper.blockingManager
|
||||
contactsManager:helper.contactsManager
|
||||
completionBlock:^(BOOL isStillBlocked) {
|
||||
if (!isStillBlocked) {
|
||||
[strongSelf.selectThreadViewDelegate threadWasSelected:thread];
|
||||
}
|
||||
}];
|
||||
return;
|
||||
}
|
||||
|
||||
[strongSelf.selectThreadViewDelegate threadWasSelected:thread];
|
||||
|
|
|
@ -7,6 +7,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@class Contact;
|
||||
@class ContactsViewHelper;
|
||||
@class SignalAccount;
|
||||
@class TSThread;
|
||||
|
||||
@protocol CNContactViewControllerDelegate;
|
||||
|
||||
|
@ -58,10 +59,13 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
- (nullable SignalAccount *)fetchSignalAccountForRecipientId:(NSString *)recipientId;
|
||||
- (SignalAccount *)fetchOrBuildSignalAccountForRecipientId:(NSString *)recipientId;
|
||||
|
||||
// MJK TODO Can we remove?
|
||||
// This method is faster than OWSBlockingManager but
|
||||
// is only safe to be called on the main thread.
|
||||
- (BOOL)isRecipientIdBlocked:(NSString *)recipientId;
|
||||
|
||||
- (BOOL)isThreadBlocked:(TSThread *)thread;
|
||||
|
||||
// NOTE: This method uses a transaction.
|
||||
- (NSString *)localNumber;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
@ -7,9 +7,10 @@
|
|||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class Contact;
|
||||
@class SignalAccount;
|
||||
@class OWSBlockingManager;
|
||||
@class OWSContactsManager;
|
||||
@class SignalAccount;
|
||||
@class TSThread;
|
||||
|
||||
typedef void (^BlockActionCompletionBlock)(BOOL isBlocked);
|
||||
|
||||
|
@ -19,6 +20,12 @@ typedef void (^BlockActionCompletionBlock)(BOOL isBlocked);
|
|||
|
||||
#pragma mark - Block
|
||||
|
||||
+ (void)showBlockThreadActionSheet:(TSThread *)thread
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
blockingManager:(OWSBlockingManager *)blockingManager
|
||||
contactsManager:(OWSContactsManager *)contactsManager
|
||||
completionBlock:(nullable BlockActionCompletionBlock)completionBlock;
|
||||
|
||||
+ (void)showBlockPhoneNumberActionSheet:(NSString *)phoneNumber
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
blockingManager:(OWSBlockingManager *)blockingManager
|
||||
|
@ -33,6 +40,12 @@ typedef void (^BlockActionCompletionBlock)(BOOL isBlocked);
|
|||
|
||||
#pragma mark - Unblock
|
||||
|
||||
+ (void)showUnblockThreadActionSheet:(TSThread *)thread
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
blockingManager:(OWSBlockingManager *)blockingManager
|
||||
contactsManager:(OWSContactsManager *)contactsManager
|
||||
completionBlock:(nullable BlockActionCompletionBlock)completionBlock;
|
||||
|
||||
+ (void)showUnblockPhoneNumberActionSheet:(NSString *)phoneNumber
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
blockingManager:(OWSBlockingManager *)blockingManager
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "BlockListUIUtils.h"
|
||||
|
@ -19,6 +19,31 @@ typedef void (^BlockAlertCompletionBlock)(UIAlertAction *action);
|
|||
|
||||
#pragma mark - Block
|
||||
|
||||
+ (void)showBlockThreadActionSheet:(TSThread *)thread
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
blockingManager:(OWSBlockingManager *)blockingManager
|
||||
contactsManager:(OWSContactsManager *)contactsManager
|
||||
completionBlock:(nullable BlockActionCompletionBlock)completionBlock
|
||||
{
|
||||
if ([thread isKindOfClass:[TSContactThread class]]) {
|
||||
TSContactThread *contactThread = (TSContactThread *)thread;
|
||||
[self showBlockPhoneNumberActionSheet:contactThread.contactIdentifier
|
||||
fromViewController:fromViewController
|
||||
blockingManager:blockingManager
|
||||
contactsManager:contactsManager
|
||||
completionBlock:completionBlock];
|
||||
} else if ([thread isKindOfClass:[TSGroupThread class]]) {
|
||||
TSGroupThread *groupThread = (TSGroupThread *)thread;
|
||||
[self showBlockGroupActionSheet:groupThread.groupModel
|
||||
displayName:groupThread.name
|
||||
fromViewController:fromViewController
|
||||
blockingManager:blockingManager
|
||||
completionBlock:completionBlock];
|
||||
} else {
|
||||
OWSFail(@"unexpected thread type: %@", thread.class);
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)showBlockPhoneNumberActionSheet:(NSString *)phoneNumber
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
blockingManager:(OWSBlockingManager *)blockingManager
|
||||
|
@ -89,7 +114,7 @@ typedef void (^BlockAlertCompletionBlock)(UIAlertAction *action);
|
|||
@"An explanation of the consequences of blocking another user.")
|
||||
preferredStyle:UIAlertControllerStyleActionSheet];
|
||||
|
||||
UIAlertAction *unblockAction = [UIAlertAction
|
||||
UIAlertAction *blockAction = [UIAlertAction
|
||||
actionWithTitle:NSLocalizedString(@"BLOCK_LIST_BLOCK_BUTTON", @"Button label for the 'block' button")
|
||||
style:UIAlertActionStyleDestructive
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
|
@ -103,7 +128,56 @@ typedef void (^BlockAlertCompletionBlock)(UIAlertAction *action);
|
|||
}
|
||||
}];
|
||||
}];
|
||||
[actionSheetController addAction:unblockAction];
|
||||
[actionSheetController addAction:blockAction];
|
||||
|
||||
UIAlertAction *dismissAction = [UIAlertAction actionWithTitle:CommonStrings.cancelButton
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
if (completionBlock) {
|
||||
completionBlock(NO);
|
||||
}
|
||||
}];
|
||||
[actionSheetController addAction:dismissAction];
|
||||
|
||||
[fromViewController presentViewController:actionSheetController animated:YES completion:nil];
|
||||
}
|
||||
|
||||
+ (void)showBlockGroupActionSheet:(TSGroupModel *)groupModel
|
||||
displayName:(NSString *)displayName
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
blockingManager:(OWSBlockingManager *)blockingManager
|
||||
completionBlock:(nullable BlockActionCompletionBlock)completionBlock
|
||||
{
|
||||
OWSAssert(displayName.length > 0);
|
||||
OWSAssert(fromViewController);
|
||||
OWSAssert(blockingManager);
|
||||
|
||||
NSString *title = [NSString stringWithFormat:NSLocalizedString(@"BLOCK_LIST_BLOCK_GROUP_TITLE_FORMAT",
|
||||
@"A format for the 'block group' action sheet title. Embeds {{the "
|
||||
@"blocked group's name}}."),
|
||||
[self formatDisplayNameForAlertTitle:displayName]];
|
||||
|
||||
UIAlertController *actionSheetController =
|
||||
[UIAlertController alertControllerWithTitle:title
|
||||
message:NSLocalizedString(@"BLOCK_GROUP_BEHAVIOR_EXPLANATION",
|
||||
@"An explanation of the consequences of blocking a group.")
|
||||
preferredStyle:UIAlertControllerStyleActionSheet];
|
||||
|
||||
UIAlertAction *blockAction = [UIAlertAction
|
||||
actionWithTitle:NSLocalizedString(@"BLOCK_LIST_BLOCK_BUTTON", @"Button label for the 'block' button")
|
||||
style:UIAlertActionStyleDestructive
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
[self blockGroup:groupModel
|
||||
displayName:displayName
|
||||
fromViewController:fromViewController
|
||||
blockingManager:blockingManager
|
||||
completionBlock:^(UIAlertAction *ignore) {
|
||||
if (completionBlock) {
|
||||
completionBlock(YES);
|
||||
}
|
||||
}];
|
||||
}];
|
||||
[actionSheetController addAction:blockAction];
|
||||
|
||||
UIAlertAction *dismissAction = [UIAlertAction actionWithTitle:CommonStrings.cancelButton
|
||||
style:UIAlertActionStyleCancel
|
||||
|
@ -144,8 +218,56 @@ typedef void (^BlockAlertCompletionBlock)(UIAlertAction *action);
|
|||
completionBlock:completionBlock];
|
||||
}
|
||||
|
||||
+ (void)blockGroup:(TSGroupModel *)groupModel
|
||||
displayName:(NSString *)displayName
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
blockingManager:(OWSBlockingManager *)blockingManager
|
||||
completionBlock:(BlockAlertCompletionBlock)completionBlock
|
||||
{
|
||||
OWSAssert(displayName.length > 0);
|
||||
OWSAssert(fromViewController);
|
||||
OWSAssert(blockingManager);
|
||||
|
||||
[blockingManager addBlockedGroupId:groupModel.groupId];
|
||||
|
||||
[self showOkAlertWithTitle:NSLocalizedString(@"BLOCK_LIST_VIEW_BLOCKED_GROUP_ALERT_TITLE",
|
||||
@"The title of the 'group blocked' alert.")
|
||||
message:[NSString
|
||||
stringWithFormat:NSLocalizedString(@"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT",
|
||||
@"The message format of the 'user blocked' "
|
||||
@"alert. Embeds {{the blocked group's name}}."),
|
||||
[self formatDisplayNameForAlertMessage:displayName]]
|
||||
fromViewController:fromViewController
|
||||
completionBlock:completionBlock];
|
||||
}
|
||||
|
||||
#pragma mark - Unblock
|
||||
|
||||
+ (void)showUnblockThreadActionSheet:(TSThread *)thread
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
blockingManager:(OWSBlockingManager *)blockingManager
|
||||
contactsManager:(OWSContactsManager *)contactsManager
|
||||
completionBlock:(nullable BlockActionCompletionBlock)completionBlock
|
||||
{
|
||||
if ([thread isKindOfClass:[TSContactThread class]]) {
|
||||
TSContactThread *contactThread = (TSContactThread *)thread;
|
||||
[self showUnblockPhoneNumberActionSheet:contactThread.contactIdentifier
|
||||
fromViewController:fromViewController
|
||||
blockingManager:blockingManager
|
||||
contactsManager:contactsManager
|
||||
completionBlock:completionBlock];
|
||||
} else if ([thread isKindOfClass:[TSGroupThread class]]) {
|
||||
TSGroupThread *groupThread = (TSGroupThread *)thread;
|
||||
[self showUnblockGroupActionSheet:groupThread.groupModel
|
||||
displayName:groupThread.name
|
||||
fromViewController:fromViewController
|
||||
blockingManager:blockingManager
|
||||
completionBlock:completionBlock];
|
||||
} else {
|
||||
OWSFail(@"unexpected thread type: %@", thread.class);
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)showUnblockPhoneNumberActionSheet:(NSString *)phoneNumber
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
blockingManager:(OWSBlockingManager *)blockingManager
|
||||
|
@ -248,28 +370,71 @@ typedef void (^BlockAlertCompletionBlock)(UIAlertAction *action);
|
|||
completionBlock:completionBlock];
|
||||
}
|
||||
|
||||
+ (void)showBlockFailedAlert:(UIViewController *)fromViewController
|
||||
completionBlock:(BlockAlertCompletionBlock)completionBlock
|
||||
+ (void)showUnblockGroupActionSheet:(TSGroupModel *)groupModel
|
||||
displayName:(NSString *)displayName
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
blockingManager:(OWSBlockingManager *)blockingManager
|
||||
completionBlock:(nullable BlockActionCompletionBlock)completionBlock
|
||||
{
|
||||
OWSAssert(displayName.length > 0);
|
||||
OWSAssert(fromViewController);
|
||||
OWSAssert(blockingManager);
|
||||
|
||||
[self showOkAlertWithTitle:NSLocalizedString(@"BLOCK_LIST_VIEW_BLOCK_FAILED_ALERT_TITLE",
|
||||
@"The title of the 'block user failed' alert.")
|
||||
message:NSLocalizedString(@"BLOCK_LIST_VIEW_BLOCK_FAILED_ALERT_MESSAGE",
|
||||
@"The title of the 'block user failed' alert.")
|
||||
fromViewController:fromViewController
|
||||
completionBlock:completionBlock];
|
||||
NSString *title = [NSString stringWithFormat:NSLocalizedString(@"BLOCK_LIST_UNBLOCK_GROUP_TITLE_FORMAT",
|
||||
@"A format for the 'unblock group' action sheet title. Embeds "
|
||||
@"{{the blocked groups's name}}."),
|
||||
[self formatDisplayNameForAlertTitle:displayName]];
|
||||
|
||||
UIAlertController *actionSheetController =
|
||||
[UIAlertController alertControllerWithTitle:title message:nil preferredStyle:UIAlertControllerStyleActionSheet];
|
||||
|
||||
UIAlertAction *unblockAction = [UIAlertAction
|
||||
actionWithTitle:NSLocalizedString(@"BLOCK_LIST_UNBLOCK_BUTTON", @"Button label for the 'unblock' button")
|
||||
style:UIAlertActionStyleDestructive
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
[BlockListUIUtils unblockGroup:groupModel
|
||||
displayName:displayName
|
||||
fromViewController:fromViewController
|
||||
blockingManager:blockingManager
|
||||
completionBlock:^(UIAlertAction *ignore) {
|
||||
if (completionBlock) {
|
||||
completionBlock(NO);
|
||||
}
|
||||
}];
|
||||
}];
|
||||
[actionSheetController addAction:unblockAction];
|
||||
|
||||
UIAlertAction *dismissAction = [UIAlertAction actionWithTitle:CommonStrings.cancelButton
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
if (completionBlock) {
|
||||
completionBlock(YES);
|
||||
}
|
||||
}];
|
||||
[actionSheetController addAction:dismissAction];
|
||||
|
||||
[fromViewController presentViewController:actionSheetController animated:YES completion:nil];
|
||||
}
|
||||
|
||||
+ (void)showUnblockFailedAlert:(UIViewController *)fromViewController
|
||||
completionBlock:(BlockAlertCompletionBlock)completionBlock
|
||||
+ (void)unblockGroup:(TSGroupModel *)groupModel
|
||||
displayName:(NSString *)displayName
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
blockingManager:(OWSBlockingManager *)blockingManager
|
||||
completionBlock:(BlockAlertCompletionBlock)completionBlock
|
||||
{
|
||||
OWSAssert(displayName.length > 0);
|
||||
OWSAssert(fromViewController);
|
||||
OWSAssert(blockingManager);
|
||||
|
||||
[self showOkAlertWithTitle:NSLocalizedString(@"BLOCK_LIST_VIEW_UNBLOCK_FAILED_ALERT_TITLE",
|
||||
@"The title of the 'unblock user failed' alert.")
|
||||
message:NSLocalizedString(@"BLOCK_LIST_VIEW_UNBLOCK_FAILED_ALERT_MESSAGE",
|
||||
@"The title of the 'unblock user failed' alert.")
|
||||
[blockingManager removeBlockedGroupId:groupModel.groupId];
|
||||
|
||||
[self showOkAlertWithTitle:NSLocalizedString(@"BLOCK_LIST_VIEW_UNBLOCKED_USER_ALERT_TITLE",
|
||||
@"The title of the 'group unblocked' alert.")
|
||||
message:[NSString stringWithFormat:NSLocalizedString(
|
||||
@"BLOCK_LIST_VIEW_UNBLOCKED_USER_ALERT_MESSAGE_FORMAT",
|
||||
@"The message format of the 'group unblocked' "
|
||||
@"alert. Embeds {{the blocked group's name}}."),
|
||||
[self formatDisplayNameForAlertMessage:displayName]]
|
||||
fromViewController:fromViewController
|
||||
completionBlock:completionBlock];
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class TSThread;
|
||||
|
||||
extern NSString *const kNSNotificationName_BlockedPhoneNumbersDidChange;
|
||||
|
||||
// This class can be safely accessed and used from any thread.
|
||||
|
@ -21,9 +23,15 @@ extern NSString *const kNSNotificationName_BlockedPhoneNumbersDidChange;
|
|||
// want to fire a sync message.
|
||||
- (void)setBlockedPhoneNumbers:(NSArray<NSString *> *)blockedPhoneNumbers sendSyncMessage:(BOOL)sendSyncMessage;
|
||||
|
||||
// TODO convert to property
|
||||
- (NSArray<NSString *> *)blockedPhoneNumbers;
|
||||
|
||||
@property (readonly) NSArray<NSData *> *blockedGroupIds;
|
||||
- (void)addBlockedGroupId:(NSData *)groupId;
|
||||
- (void)removeBlockedGroupId:(NSData *)groupId;
|
||||
|
||||
- (BOOL)isRecipientIdBlocked:(NSString *)recipientId;
|
||||
- (BOOL)isThreadBlocked:(TSThread *)thread;
|
||||
|
||||
- (void)syncBlockedPhoneNumbers;
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#import "OWSBlockedPhoneNumbersMessage.h"
|
||||
#import "OWSMessageSender.h"
|
||||
#import "OWSPrimaryStorage.h"
|
||||
#import "TSContactThread.h"
|
||||
#import "TSGroupThread.h"
|
||||
#import "TextSecureKitEnv.h"
|
||||
#import "YapDatabaseConnection+OWS.h"
|
||||
|
||||
|
@ -16,9 +18,13 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
NSString *const kNSNotificationName_BlockedPhoneNumbersDidChange = @"kNSNotificationName_BlockedPhoneNumbersDidChange";
|
||||
|
||||
NSString *const kOWSBlockingManager_BlockedPhoneNumbersCollection = @"kOWSBlockingManager_BlockedPhoneNumbersCollection";
|
||||
NSString *const kOWSBlockingManager_BlockListCollection = @"kOWSBlockingManager_BlockedPhoneNumbersCollection";
|
||||
|
||||
// This key is used to persist the current "blocked phone numbers" state.
|
||||
NSString *const kOWSBlockingManager_BlockedPhoneNumbersKey = @"kOWSBlockingManager_BlockedPhoneNumbersKey";
|
||||
|
||||
NSString *const kOWSBlockingManager_BlockedGroupIdsKey = @"kOWSBlockingManager_BlockedGroupIdsKey";
|
||||
|
||||
// This key is used to persist the most recently synced "blocked phone numbers" state.
|
||||
NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockingManager_SyncedBlockedPhoneNumbersKey";
|
||||
|
||||
|
@ -31,6 +37,7 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin
|
|||
// consistency issues between clients, but these should all be valid e164
|
||||
// phone numbers.
|
||||
@property (atomic, readonly) NSMutableSet<NSString *> *blockedPhoneNumberSet;
|
||||
@property (atomic, readonly) NSMutableSet<NSData *> *blockedGroupIdSet;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -93,6 +100,25 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin
|
|||
object:nil];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
|
||||
- (BOOL)isThreadBlocked:(TSThread *)thread
|
||||
{
|
||||
if ([thread isKindOfClass:[TSContactThread class]]) {
|
||||
TSContactThread *contactThread = (TSContactThread *)thread;
|
||||
return [self isRecipientIdBlocked:contactThread.contactIdentifier];
|
||||
} else if ([thread isKindOfClass:[TSGroupThread class]]) {
|
||||
TSGroupThread *groupThread = (TSGroupThread *)thread;
|
||||
return [self isGroupIdBlocked:groupThread.groupModel.groupId];
|
||||
} else {
|
||||
OWSFail(@"%@ failure unexpected thread type", self.logTag);
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Contact Blocking
|
||||
|
||||
- (void)addBlockedPhoneNumber:(NSString *)phoneNumber
|
||||
{
|
||||
OWSAssert(phoneNumber.length > 0);
|
||||
|
@ -171,6 +197,65 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin
|
|||
return [self.blockedPhoneNumbers containsObject:recipientId];
|
||||
}
|
||||
|
||||
#pragma mark - Group Blocking
|
||||
|
||||
- (NSArray<NSData *> *)blockedGroupIds
|
||||
{
|
||||
@synchronized(self) {
|
||||
[self ensureLazyInitialization];
|
||||
|
||||
return _blockedGroupIdSet.allObjects;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isGroupIdBlocked:(NSData *)groupId
|
||||
{
|
||||
return [self.blockedGroupIds containsObject:groupId];
|
||||
}
|
||||
|
||||
- (void)addBlockedGroupId:(NSData *)groupId
|
||||
{
|
||||
OWSAssert(groupId.length > 0);
|
||||
|
||||
DDLogInfo(@"%@ addBlockedGroupId: %@", self.logTag, groupId);
|
||||
|
||||
@synchronized(self) {
|
||||
[self ensureLazyInitialization];
|
||||
|
||||
if ([_blockedGroupIdSet containsObject:groupId]) {
|
||||
// Ignore redundant changes.
|
||||
return;
|
||||
}
|
||||
|
||||
[_blockedGroupIdSet addObject:groupId];
|
||||
}
|
||||
|
||||
[self handleUpdate];
|
||||
}
|
||||
|
||||
- (void)removeBlockedGroupId:(NSData *)groupId
|
||||
{
|
||||
OWSAssert(groupId.length > 0);
|
||||
|
||||
DDLogInfo(@"%@ removeBlockedGroupId: %@", self.logTag, groupId);
|
||||
|
||||
@synchronized(self) {
|
||||
[self ensureLazyInitialization];
|
||||
|
||||
if (![_blockedGroupIdSet containsObject:groupId]) {
|
||||
// Ignore redundant changes.
|
||||
return;
|
||||
}
|
||||
|
||||
[_blockedGroupIdSet removeObject:groupId];
|
||||
}
|
||||
|
||||
[self handleUpdate];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Updates
|
||||
|
||||
// This should be called every time the block list changes.
|
||||
|
||||
- (void)handleUpdate
|
||||
|
@ -185,7 +270,7 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin
|
|||
|
||||
[self.dbConnection setObject:blockedPhoneNumbers
|
||||
forKey:kOWSBlockingManager_BlockedPhoneNumbersKey
|
||||
inCollection:kOWSBlockingManager_BlockedPhoneNumbersCollection];
|
||||
inCollection:kOWSBlockingManager_BlockListCollection];
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
if (sendSyncMessage) {
|
||||
|
@ -216,15 +301,21 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin
|
|||
- (void)ensureLazyInitialization
|
||||
{
|
||||
if (_blockedPhoneNumberSet) {
|
||||
// _blockedPhoneNumberSet has already been loaded, abort.
|
||||
OWSAssert(_blockedGroupIdSet);
|
||||
|
||||
// already loaded
|
||||
return;
|
||||
}
|
||||
|
||||
NSArray<NSString *> *blockedPhoneNumbers =
|
||||
[self.dbConnection objectForKey:kOWSBlockingManager_BlockedPhoneNumbersKey
|
||||
inCollection:kOWSBlockingManager_BlockedPhoneNumbersCollection];
|
||||
inCollection:kOWSBlockingManager_BlockListCollection];
|
||||
_blockedPhoneNumberSet = [[NSMutableSet alloc] initWithArray:(blockedPhoneNumbers ?: [NSArray new])];
|
||||
|
||||
NSArray<NSData *> *blockedGroupIds = [self.dbConnection objectForKey:kOWSBlockingManager_BlockedGroupIdsKey
|
||||
inCollection:kOWSBlockingManager_BlockListCollection];
|
||||
_blockedGroupIdSet = [[NSMutableSet alloc] initWithArray:(blockedGroupIds ?: [NSArray new])];
|
||||
|
||||
[self syncBlockedPhoneNumbersIfNecessary];
|
||||
[self observeNotifications];
|
||||
}
|
||||
|
@ -247,7 +338,7 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin
|
|||
// try again to sync now.
|
||||
NSArray<NSString *> *syncedBlockedPhoneNumbers =
|
||||
[self.dbConnection objectForKey:kOWSBlockingManager_SyncedBlockedPhoneNumbersKey
|
||||
inCollection:kOWSBlockingManager_BlockedPhoneNumbersCollection];
|
||||
inCollection:kOWSBlockingManager_BlockListCollection];
|
||||
NSSet *syncedBlockedPhoneNumberSet = [[NSSet alloc] initWithArray:(syncedBlockedPhoneNumbers ?: [NSArray new])];
|
||||
if (![_blockedPhoneNumberSet isEqualToSet:syncedBlockedPhoneNumberSet]) {
|
||||
DDLogInfo(@"%@ retrying sync of blocked phone numbers", self.logTag);
|
||||
|
@ -258,6 +349,7 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin
|
|||
- (void)sendBlockedPhoneNumbersMessage:(NSArray<NSString *> *)blockedPhoneNumbers
|
||||
{
|
||||
OWSAssert(blockedPhoneNumbers);
|
||||
OWSAssert(blockedGroupIds);
|
||||
|
||||
OWSBlockedPhoneNumbersMessage *message =
|
||||
[[OWSBlockedPhoneNumbersMessage alloc] initWithPhoneNumbers:blockedPhoneNumbers];
|
||||
|
@ -281,7 +373,7 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin
|
|||
// Record the last set of "blocked phone numbers" which we successfully synced.
|
||||
[self.dbConnection setObject:blockedPhoneNumbers
|
||||
forKey:kOWSBlockingManager_SyncedBlockedPhoneNumbersKey
|
||||
inCollection:kOWSBlockingManager_BlockedPhoneNumbersCollection];
|
||||
inCollection:kOWSBlockingManager_BlockListCollection];
|
||||
}
|
||||
|
||||
#pragma mark - Notifications
|
||||
|
|
Loading…
Reference in New Issue