Merge branch 'charlesmchen/blocking5'
This commit is contained in:
commit
d640aaa9d7
@ -13,6 +13,7 @@
|
||||
34330A5E1E787BD800DF2FB9 /* ElegantIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 34330A5D1E787BD800DF2FB9 /* ElegantIcons.ttf */; };
|
||||
34330A611E788EA900DF2FB9 /* AttachmentUploadView.m in Sources */ = {isa = PBXBuildFile; fileRef = 34330A601E788EA900DF2FB9 /* AttachmentUploadView.m */; };
|
||||
34330AA31E79686200DF2FB9 /* OWSProgressView.m in Sources */ = {isa = PBXBuildFile; fileRef = 34330AA21E79686200DF2FB9 /* OWSProgressView.m */; };
|
||||
343D3D9B1E9283F100165CA4 /* BlockListUIUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 343D3D9A1E9283F100165CA4 /* BlockListUIUtils.m */; };
|
||||
344F2F671E57A932000D9322 /* UIViewController+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = 344F2F661E57A932000D9322 /* UIViewController+OWS.m */; };
|
||||
34535D821E256BE9008A4747 /* UIView+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = 34535D811E256BE9008A4747 /* UIView+OWS.m */; };
|
||||
345671011E89A5F1006EE662 /* ThreadUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 345671001E89A5F1006EE662 /* ThreadUtil.m */; };
|
||||
@ -347,6 +348,8 @@
|
||||
34330A601E788EA900DF2FB9 /* AttachmentUploadView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AttachmentUploadView.m; sourceTree = "<group>"; };
|
||||
34330AA11E79686200DF2FB9 /* OWSProgressView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSProgressView.h; sourceTree = "<group>"; };
|
||||
34330AA21E79686200DF2FB9 /* OWSProgressView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSProgressView.m; sourceTree = "<group>"; };
|
||||
343D3D991E9283F100165CA4 /* BlockListUIUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockListUIUtils.h; sourceTree = "<group>"; };
|
||||
343D3D9A1E9283F100165CA4 /* BlockListUIUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BlockListUIUtils.m; sourceTree = "<group>"; };
|
||||
344F2F651E57A932000D9322 /* UIViewController+OWS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIViewController+OWS.h"; path = "util/UIViewController+OWS.h"; sourceTree = "<group>"; };
|
||||
344F2F661E57A932000D9322 /* UIViewController+OWS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIViewController+OWS.m"; path = "util/UIViewController+OWS.m"; sourceTree = "<group>"; };
|
||||
34535D801E256BE9008A4747 /* UIView+OWS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+OWS.h"; sourceTree = "<group>"; };
|
||||
@ -823,6 +826,8 @@
|
||||
34B3F8381E8DF1700035BE1A /* AttachmentApprovalViewController.swift */,
|
||||
34B3F8391E8DF1700035BE1A /* AttachmentSharing.h */,
|
||||
34B3F83A1E8DF1700035BE1A /* AttachmentSharing.m */,
|
||||
343D3D991E9283F100165CA4 /* BlockListUIUtils.h */,
|
||||
343D3D9A1E9283F100165CA4 /* BlockListUIUtils.m */,
|
||||
34B3F89A1E8DF3270035BE1A /* BlockListViewController.h */,
|
||||
34B3F89B1E8DF3270035BE1A /* BlockListViewController.m */,
|
||||
34B3F83B1E8DF1700035BE1A /* CallViewController.swift */,
|
||||
@ -1958,6 +1963,7 @@
|
||||
34B3F88F1E8DF1710035BE1A /* RegistrationViewController.m in Sources */,
|
||||
34B3F8901E8DF1710035BE1A /* SettingsTableViewController.m in Sources */,
|
||||
34FD93701E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m in Sources */,
|
||||
343D3D9B1E9283F100165CA4 /* BlockListUIUtils.m in Sources */,
|
||||
34B3F8931E8DF1710035BE1A /* SignalsNavigationController.m in Sources */,
|
||||
76EB063A18170B33006006FC /* FunctionalUtil.m in Sources */,
|
||||
76EB058A18170B33006006FC /* Release.m in Sources */,
|
||||
|
||||
23
Signal/Images.xcassets/ic_block.imageset/Contents.json
vendored
Normal file
23
Signal/Images.xcassets/ic_block.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_block@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_block@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_block@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
Signal/Images.xcassets/ic_block.imageset/ic_block@1x.png
vendored
Normal file
BIN
Signal/Images.xcassets/ic_block.imageset/ic_block@1x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
BIN
Signal/Images.xcassets/ic_block.imageset/ic_block@2x.png
vendored
Normal file
BIN
Signal/Images.xcassets/ic_block.imageset/ic_block@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
BIN
Signal/Images.xcassets/ic_block.imageset/ic_block@3x.png
vendored
Normal file
BIN
Signal/Images.xcassets/ic_block.imageset/ic_block@3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
23
Signal/Images.xcassets/table_ic_block.imageset/Contents.json
vendored
Normal file
23
Signal/Images.xcassets/table_ic_block.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "table_ic_block@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "table_ic_block@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "table_ic_block@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
Signal/Images.xcassets/table_ic_block.imageset/table_ic_block@1x.png
vendored
Normal file
BIN
Signal/Images.xcassets/table_ic_block.imageset/table_ic_block@1x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
BIN
Signal/Images.xcassets/table_ic_block.imageset/table_ic_block@2x.png
vendored
Normal file
BIN
Signal/Images.xcassets/table_ic_block.imageset/table_ic_block@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
BIN
Signal/Images.xcassets/table_ic_block.imageset/table_ic_block@3x.png
vendored
Normal file
BIN
Signal/Images.xcassets/table_ic_block.imageset/table_ic_block@3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
@ -446,11 +446,33 @@
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<segue destination="urv-62-RsD" kind="modal" id="wgA-Oo-kKq"/>
|
||||
<segue destination="urv-62-RsD" kind="modal" identifier="OWSConversationSettingsTableViewControllerSegueSafetyNumbers" id="wgA-Oo-kKq"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="checkmark" indentationWidth="10" textLabel="NTW-lE-H66" imageView="cpX-fS-xEX" style="IBUITableViewCellStyleDefault" id="Lpy-OD-yA9">
|
||||
<rect key="frame" x="0.0" y="144" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Lpy-OD-yA9" id="NhR-r7-vVa">
|
||||
<rect key="frame" x="0.0" y="0.0" width="336" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Blocklist State" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="NTW-lE-H66">
|
||||
<rect key="frame" x="62" y="0.0" width="274" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" image="ic_lock_outline" id="cpX-fS-xEX">
|
||||
<rect key="frame" x="15" y="5" width="32" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<color key="tintColor" red="0.054901960780000002" green="0.054901960780000002" blue="0.054901960780000002" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="108" id="U6h-Xo-HEv">
|
||||
<rect key="frame" x="0.0" y="144" width="375" height="108"/>
|
||||
<rect key="frame" x="0.0" y="188" width="375" height="108"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="U6h-Xo-HEv" id="Nmz-2u-fOY">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="107"/>
|
||||
@ -506,7 +528,7 @@
|
||||
<inset key="separatorInset" minX="63" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="76" id="3dL-aW-P1A">
|
||||
<rect key="frame" x="0.0" y="252" width="375" height="76"/>
|
||||
<rect key="frame" x="0.0" y="296" width="375" height="76"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="3dL-aW-P1A" id="2a2-Po-p8O">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="75"/>
|
||||
@ -555,7 +577,7 @@
|
||||
<tableViewSection headerTitle="Group Management" id="z5m-Fe-GK8">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="NxZ-wa-xV9" style="IBUITableViewCellStyleDefault" id="XHr-b6-Gvn" userLabel="Update Group">
|
||||
<rect key="frame" x="0.0" y="385" width="375" height="44"/>
|
||||
<rect key="frame" x="0.0" y="429" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="XHr-b6-Gvn" id="Epj-vT-UYL">
|
||||
<rect key="frame" x="0.0" y="0.0" width="342" height="43"/>
|
||||
@ -575,7 +597,7 @@
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="geN-YN-TQg" style="IBUITableViewCellStyleDefault" id="w57-rz-BWN" userLabel="Leave Group">
|
||||
<rect key="frame" x="0.0" y="429" width="375" height="44"/>
|
||||
<rect key="frame" x="0.0" y="473" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="w57-rz-BWN" id="Pgy-Fc-U25">
|
||||
<rect key="frame" x="0.0" y="0.0" width="342" height="43"/>
|
||||
@ -592,7 +614,7 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="Zml-Zn-2fd" style="IBUITableViewCellStyleDefault" id="Dnq-Ko-46l" userLabel="Group Members">
|
||||
<rect key="frame" x="0.0" y="473" width="375" height="44"/>
|
||||
<rect key="frame" x="0.0" y="517" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Dnq-Ko-46l" id="VRQ-31-E5Y">
|
||||
<rect key="frame" x="0.0" y="0.0" width="342" height="43"/>
|
||||
@ -622,22 +644,21 @@
|
||||
<navigationItem key="navigationItem" title="Conversation Settings" id="3Gh-BY-xJE"/>
|
||||
<connections>
|
||||
<outlet property="avatar" destination="7IV-AJ-aCS" id="9LA-fh-tIF"/>
|
||||
<outlet property="blocklistStateCell" destination="Lpy-OD-yA9" id="GZW-j4-F2n"/>
|
||||
<outlet property="disappearingMessagesDurationCell" destination="3dL-aW-P1A" id="fZT-hN-ZNB"/>
|
||||
<outlet property="disappearingMessagesDurationLabel" destination="c6Q-rV-1LO" id="dEt-U7-kFm"/>
|
||||
<outlet property="disappearingMessagesDurationSlider" destination="4Hn-9p-qsR" id="nMT-B6-hzM"/>
|
||||
<outlet property="disappearingMessagesSwitch" destination="0dO-mx-W3I" id="bBm-Lk-kgv"/>
|
||||
<outlet property="leaveGroupCell" destination="w57-rz-BWN" id="NhL-3S-t9C"/>
|
||||
<outlet property="listGroupMembersCell" destination="Dnq-Ko-46l" id="FF2-Vv-UPN"/>
|
||||
<outlet property="nameLabel" destination="qCt-Cp-bFX" id="7yI-kh-cN6"/>
|
||||
<outlet property="signalIdLabel" destination="tmV-r0-09O" id="jFP-hM-j3f"/>
|
||||
<outlet property="toggleDisappearingMessagesCell" destination="U6h-Xo-HEv" id="a3T-jn-u7Z"/>
|
||||
<outlet property="toggleDisappearingMessagesDescriptionLabel" destination="zIg-K4-8lV" id="bbK-a4-b6t"/>
|
||||
<outlet property="toggleDisappearingMessagesTitleLabel" destination="qbY-qJ-enK" id="gMK-F9-7Ss"/>
|
||||
<outlet property="updateGroupCell" destination="XHr-b6-Gvn" id="JMz-e5-FNh"/>
|
||||
<outlet property="verifyPrivacyCell" destination="Dzg-XO-ciX" id="kKQ-3F-uIp"/>
|
||||
<outletCollection property="cellIcons" destination="eGH-Vc-aKx" id="QW6-1W-hpg"/>
|
||||
<outletCollection property="cellIcons" destination="iRL-ZI-kXA" id="kct-Ug-2zB"/>
|
||||
<outletCollection property="cellIcons" destination="X7n-1t-1Q7" id="sc6-6u-NOR"/>
|
||||
<outletCollection property="cellIcons" destination="cpX-fS-xEX" id="BZI-wV-O2B"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Ftx-dN-loa" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
//
|
||||
|
||||
#import "AddToBlockListViewController.h"
|
||||
#import "BlockListUIUtils.h"
|
||||
#import "ContactTableViewCell.h"
|
||||
#import "CountryCodeViewController.h"
|
||||
#import "Environment.h"
|
||||
@ -13,8 +14,8 @@
|
||||
#import "UIUtil.h"
|
||||
#import "UIView+OWS.h"
|
||||
#import "ViewControllerUtils.h"
|
||||
#import <SignalServiceKit/PhoneNumberUtil.h>
|
||||
#import <SignalServiceKit/OWSBlockingManager.h>
|
||||
#import <SignalServiceKit/PhoneNumberUtil.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@ -273,25 +274,18 @@ NSString *const kContactsTable_CellReuseIdentifier = @"kContactsTable_CellReuseI
|
||||
PhoneNumber *parsedPhoneNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:possiblePhoneNumber];
|
||||
OWSAssert(parsedPhoneNumber);
|
||||
|
||||
[_blockingManager addBlockedPhoneNumber:[parsedPhoneNumber toE164]];
|
||||
|
||||
UIAlertController *controller = [UIAlertController
|
||||
alertControllerWithTitle:NSLocalizedString(@"BLOCK_LIST_VIEW_PHONE_NUMBER_BLOCKED_ALERT_TITLE",
|
||||
@"The title of the 'phone number blocked' alert in the block view.")
|
||||
message:[NSString
|
||||
stringWithFormat:NSLocalizedString(
|
||||
@"BLOCK_LIST_VIEW_PHONE_NUMBER_BLOCKED_ALERT_MESSAGE_FORMAT",
|
||||
@"The message format of the 'phone number blocked' alert in "
|
||||
@"the block view. Embeds {{the blocked phone number}}."),
|
||||
[parsedPhoneNumber toE164]]
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
[controller addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil)
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:nil]];
|
||||
[self presentViewController:controller animated:YES completion:nil];
|
||||
|
||||
_phoneNumberTextField.text = nil;
|
||||
__weak AddToBlockListViewController *weakSelf = self;
|
||||
[BlockListUIUtils showBlockPhoneNumberActionSheet:[parsedPhoneNumber toE164]
|
||||
fromViewController:self
|
||||
blockingManager:_blockingManager
|
||||
contactsManager:_contactsManager
|
||||
completionBlock:^(BOOL isBlocked) {
|
||||
if (isBlocked) {
|
||||
// Clear phone number text field if block succeeds.
|
||||
weakSelf.phoneNumberTextField.text = nil;
|
||||
[weakSelf.navigationController popViewControllerAnimated:YES];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)textFieldDidChange:(id)sender
|
||||
@ -416,63 +410,17 @@ NSString *const kContactsTable_CellReuseIdentifier = @"kContactsTable_CellReuseI
|
||||
{
|
||||
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
||||
|
||||
Contact *contact = self.contacts[(NSUInteger)indexPath.item];
|
||||
[self showBlockActionSheet:contact];
|
||||
}
|
||||
|
||||
- (void)showBlockActionSheet:(Contact *)contact
|
||||
{
|
||||
OWSAssert(contact);
|
||||
|
||||
NSString *displayName = contact.fullName;
|
||||
|
||||
NSString *title = [NSString stringWithFormat:NSLocalizedString(@"BLOCK_LIST_BLOCK_TITLE_FORMAT",
|
||||
@"A format for the 'block phone number' action sheet title."),
|
||||
displayName];
|
||||
|
||||
UIAlertController *actionSheetController =
|
||||
[UIAlertController alertControllerWithTitle:title message:nil preferredStyle:UIAlertControllerStyleActionSheet];
|
||||
|
||||
__weak AddToBlockListViewController *weakSelf = self;
|
||||
UIAlertAction *unblockAction = [UIAlertAction
|
||||
actionWithTitle:NSLocalizedString(@"BLOCK_LIST_BLOCK_BUTTON", @"Button label for the 'block' button")
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
[weakSelf blockContact:contact displayName:displayName];
|
||||
}];
|
||||
[actionSheetController addAction:unblockAction];
|
||||
|
||||
UIAlertAction *dismissAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"")
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:nil];
|
||||
[actionSheetController addAction:dismissAction];
|
||||
|
||||
[self presentViewController:actionSheetController animated:YES completion:nil];
|
||||
}
|
||||
|
||||
- (void)blockContact:(Contact *)contact displayName:(NSString *)displayName
|
||||
{
|
||||
for (PhoneNumber *phoneNumber in contact.parsedPhoneNumbers) {
|
||||
if (phoneNumber.toE164.length > 0) {
|
||||
[_blockingManager addBlockedPhoneNumber:phoneNumber.toE164];
|
||||
}
|
||||
}
|
||||
|
||||
UIAlertController *controller = [UIAlertController
|
||||
alertControllerWithTitle:NSLocalizedString(@"BLOCK_LIST_VIEW_CONTACT_BLOCKED_ALERT_TITLE",
|
||||
@"The title of the 'contact blocked' alert in the block view.")
|
||||
message:[NSString stringWithFormat:NSLocalizedString(
|
||||
@"BLOCK_LIST_VIEW_CONTACT_BLOCKED_ALERT_MESSAGE_FORMAT",
|
||||
@"The message format of the 'contact blocked' "
|
||||
@"alert in the block view. It is populated with the "
|
||||
@"blocked contact's name."),
|
||||
displayName]
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
[controller addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil)
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:nil]];
|
||||
[self presentViewController:controller animated:YES completion:nil];
|
||||
Contact *contact = self.contacts[(NSUInteger)indexPath.item];
|
||||
[BlockListUIUtils showBlockContactActionSheet:contact
|
||||
fromViewController:self
|
||||
blockingManager:_blockingManager
|
||||
contactsManager:_contactsManager
|
||||
completionBlock:^(BOOL isBlocked) {
|
||||
if (isBlocked) {
|
||||
[weakSelf.navigationController popViewControllerAnimated:YES];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - UIScrollViewDelegate
|
||||
|
||||
39
Signal/src/ViewControllers/BlockListUIUtils.h
Normal file
39
Signal/src/ViewControllers/BlockListUIUtils.h
Normal file
@ -0,0 +1,39 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class Contact;
|
||||
@class OWSBlockingManager;
|
||||
@class OWSContactsManager;
|
||||
|
||||
typedef void (^BlockActionCompletionBlock)(BOOL isBlocked);
|
||||
|
||||
@interface BlockListUIUtils : NSObject
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
+ (void)showBlockContactActionSheet:(Contact *)contact
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
blockingManager:(OWSBlockingManager *)blockingManager
|
||||
contactsManager:(OWSContactsManager *)contactsManager
|
||||
completionBlock:(nullable BlockActionCompletionBlock)completionBlock;
|
||||
|
||||
+ (void)showBlockPhoneNumberActionSheet:(NSString *)phoneNumber
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
blockingManager:(OWSBlockingManager *)blockingManager
|
||||
contactsManager:(OWSContactsManager *)contactsManager
|
||||
completionBlock:(nullable BlockActionCompletionBlock)completionBlock;
|
||||
|
||||
+ (void)showUnblockPhoneNumberActionSheet:(NSString *)phoneNumber
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
blockingManager:(OWSBlockingManager *)blockingManager
|
||||
contactsManager:(OWSContactsManager *)contactsManager
|
||||
completionBlock:(nullable BlockActionCompletionBlock)completionBlock;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
271
Signal/src/ViewControllers/BlockListUIUtils.m
Normal file
271
Signal/src/ViewControllers/BlockListUIUtils.m
Normal file
@ -0,0 +1,271 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "BlockListUIUtils.h"
|
||||
#import "OWSContactsManager.h"
|
||||
#import "PhoneNumber.h"
|
||||
#import <SignalServiceKit/Contact.h>
|
||||
#import <SignalServiceKit/OWSBlockingManager.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@implementation BlockListUIUtils
|
||||
|
||||
+ (void)showBlockContactActionSheet:(Contact *)contact
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
blockingManager:(OWSBlockingManager *)blockingManager
|
||||
contactsManager:(OWSContactsManager *)contactsManager
|
||||
completionBlock:(nullable BlockActionCompletionBlock)completionBlock
|
||||
{
|
||||
NSMutableArray<NSString *> *phoneNumbers = [NSMutableArray new];
|
||||
for (PhoneNumber *phoneNumber in contact.parsedPhoneNumbers) {
|
||||
if (phoneNumber.toE164.length > 0) {
|
||||
[phoneNumbers addObject:phoneNumber.toE164];
|
||||
}
|
||||
}
|
||||
if (phoneNumbers.count < 1) {
|
||||
DDLogError(@"%@ Contact has no phone numbers", self.tag);
|
||||
OWSAssert(0);
|
||||
[self showBlockFailedAlert:fromViewController];
|
||||
if (completionBlock) {
|
||||
completionBlock(NO);
|
||||
}
|
||||
return;
|
||||
}
|
||||
NSString *displayName = [contactsManager displayNameForContact:contact];
|
||||
[self showBlockPhoneNumbersActionSheet:phoneNumbers
|
||||
displayName:displayName
|
||||
fromViewController:fromViewController
|
||||
blockingManager:blockingManager
|
||||
completionBlock:completionBlock];
|
||||
}
|
||||
|
||||
+ (void)showBlockPhoneNumberActionSheet:(NSString *)phoneNumber
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
blockingManager:(OWSBlockingManager *)blockingManager
|
||||
contactsManager:(OWSContactsManager *)contactsManager
|
||||
completionBlock:(nullable BlockActionCompletionBlock)completionBlock
|
||||
{
|
||||
NSString *displayName = [contactsManager displayNameForPhoneIdentifier:phoneNumber];
|
||||
[self showBlockPhoneNumbersActionSheet:@[ phoneNumber ]
|
||||
displayName:displayName
|
||||
fromViewController:fromViewController
|
||||
blockingManager:blockingManager
|
||||
completionBlock:completionBlock];
|
||||
}
|
||||
|
||||
+ (void)showBlockPhoneNumbersActionSheet:(NSArray<NSString *> *)phoneNumbers
|
||||
displayName:(NSString *)displayName
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
blockingManager:(OWSBlockingManager *)blockingManager
|
||||
completionBlock:(nullable BlockActionCompletionBlock)completionBlock
|
||||
{
|
||||
OWSAssert(phoneNumbers.count > 0);
|
||||
OWSAssert(displayName.length > 0);
|
||||
OWSAssert(fromViewController);
|
||||
OWSAssert(blockingManager);
|
||||
|
||||
NSString *title = [NSString stringWithFormat:NSLocalizedString(@"BLOCK_LIST_BLOCK_TITLE_FORMAT",
|
||||
@"A format for the 'block user' action sheet title. Embeds {{the "
|
||||
@"blocked user's name or phone number}}."),
|
||||
[self formatDisplayNameForAlertTitle:displayName]];
|
||||
|
||||
UIAlertController *actionSheetController =
|
||||
[UIAlertController alertControllerWithTitle:title message:nil preferredStyle:UIAlertControllerStyleActionSheet];
|
||||
|
||||
UIAlertAction *unblockAction = [UIAlertAction
|
||||
actionWithTitle:NSLocalizedString(@"BLOCK_LIST_BLOCK_BUTTON", @"Button label for the 'block' button")
|
||||
style:UIAlertActionStyleDestructive
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
[self blockPhoneNumbers:phoneNumbers
|
||||
displayName:displayName
|
||||
fromViewController:fromViewController
|
||||
blockingManager:blockingManager];
|
||||
if (completionBlock) {
|
||||
completionBlock(YES);
|
||||
}
|
||||
}];
|
||||
[actionSheetController addAction:unblockAction];
|
||||
|
||||
UIAlertAction *dismissAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"")
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
if (completionBlock) {
|
||||
completionBlock(NO);
|
||||
}
|
||||
}];
|
||||
[actionSheetController addAction:dismissAction];
|
||||
|
||||
[fromViewController presentViewController:actionSheetController animated:YES completion:nil];
|
||||
}
|
||||
|
||||
+ (void)blockPhoneNumbers:(NSArray<NSString *> *)phoneNumbers
|
||||
displayName:(NSString *)displayName
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
blockingManager:(OWSBlockingManager *)blockingManager
|
||||
{
|
||||
OWSAssert(phoneNumbers.count > 0);
|
||||
OWSAssert(displayName.length > 0);
|
||||
OWSAssert(fromViewController);
|
||||
OWSAssert(blockingManager);
|
||||
|
||||
for (NSString *phoneNumber in phoneNumbers) {
|
||||
OWSAssert(phoneNumber.length > 0);
|
||||
[blockingManager addBlockedPhoneNumber:phoneNumber];
|
||||
}
|
||||
|
||||
[self showOkAlertWithTitle:NSLocalizedString(
|
||||
@"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE", @"The title of the 'user blocked' alert.")
|
||||
message:[NSString
|
||||
stringWithFormat:NSLocalizedString(@"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT",
|
||||
@"The message format of the 'user blocked' "
|
||||
@"alert. Embeds {{the blocked user's name or phone number}}."),
|
||||
[self formatDisplayNameForAlertMessage:displayName]]
|
||||
fromViewController:fromViewController];
|
||||
}
|
||||
|
||||
+ (void)showUnblockPhoneNumberActionSheet:(NSString *)phoneNumber
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
blockingManager:(OWSBlockingManager *)blockingManager
|
||||
contactsManager:(OWSContactsManager *)contactsManager
|
||||
completionBlock:(nullable BlockActionCompletionBlock)completionBlock
|
||||
{
|
||||
OWSAssert(phoneNumber.length > 0);
|
||||
OWSAssert(fromViewController);
|
||||
OWSAssert(blockingManager);
|
||||
OWSAssert(contactsManager);
|
||||
|
||||
NSString *displayName = [contactsManager displayNameForPhoneIdentifier:phoneNumber];
|
||||
|
||||
NSString *title = [NSString stringWithFormat:NSLocalizedString(@"BLOCK_LIST_UNBLOCK_TITLE_FORMAT",
|
||||
@"A format for the 'unblock user' action sheet title. Embeds "
|
||||
@"{{the blocked user's name or phone number}}."),
|
||||
[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 unblockPhoneNumber:phoneNumber
|
||||
displayName:displayName
|
||||
fromViewController:fromViewController
|
||||
blockingManager:blockingManager];
|
||||
if (completionBlock) {
|
||||
completionBlock(NO);
|
||||
}
|
||||
}];
|
||||
[actionSheetController addAction:unblockAction];
|
||||
|
||||
UIAlertAction *dismissAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"")
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
if (completionBlock) {
|
||||
completionBlock(YES);
|
||||
}
|
||||
}];
|
||||
[actionSheetController addAction:dismissAction];
|
||||
|
||||
[fromViewController presentViewController:actionSheetController animated:YES completion:nil];
|
||||
}
|
||||
|
||||
+ (void)unblockPhoneNumber:(NSString *)phoneNumber
|
||||
displayName:(NSString *)displayName
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
blockingManager:(OWSBlockingManager *)blockingManager
|
||||
{
|
||||
OWSAssert(phoneNumber.length > 0);
|
||||
OWSAssert(displayName.length > 0);
|
||||
OWSAssert(fromViewController);
|
||||
OWSAssert(blockingManager);
|
||||
|
||||
[blockingManager removeBlockedPhoneNumber:phoneNumber];
|
||||
|
||||
[self showOkAlertWithTitle:NSLocalizedString(@"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE",
|
||||
@"The title of the 'user unblocked' alert.")
|
||||
message:[NSString
|
||||
stringWithFormat:NSLocalizedString(@"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_MESSAGE_FORMAT",
|
||||
@"The message format of the 'user unblocked' "
|
||||
@"alert. Embeds {{the blocked user's name or phone number}}."),
|
||||
[self formatDisplayNameForAlertMessage:displayName]]
|
||||
fromViewController:fromViewController];
|
||||
}
|
||||
|
||||
+ (void)showBlockFailedAlert:(UIViewController *)fromViewController
|
||||
{
|
||||
OWSAssert(fromViewController);
|
||||
|
||||
[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];
|
||||
}
|
||||
|
||||
+ (void)showUnblockFailedAlert:(UIViewController *)fromViewController
|
||||
{
|
||||
OWSAssert(fromViewController);
|
||||
|
||||
[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.")
|
||||
fromViewController:fromViewController];
|
||||
}
|
||||
|
||||
+ (void)showOkAlertWithTitle:(NSString *)title
|
||||
message:(NSString *)message
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
{
|
||||
OWSAssert(title.length > 0);
|
||||
OWSAssert(message.length > 0);
|
||||
OWSAssert(fromViewController);
|
||||
|
||||
UIAlertController *controller =
|
||||
[UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
[controller addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil)
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:nil]];
|
||||
[fromViewController presentViewController:controller animated:YES completion:nil];
|
||||
}
|
||||
|
||||
+ (NSString *)formatDisplayNameForAlertTitle:(NSString *)displayName
|
||||
{
|
||||
return [self formatDisplayName:displayName withMaxLength:20];
|
||||
}
|
||||
|
||||
+ (NSString *)formatDisplayNameForAlertMessage:(NSString *)displayName
|
||||
{
|
||||
return [self formatDisplayName:displayName withMaxLength:127];
|
||||
}
|
||||
|
||||
+ (NSString *)formatDisplayName:(NSString *)displayName withMaxLength:(NSUInteger)maxLength
|
||||
{
|
||||
OWSAssert(displayName.length > 0);
|
||||
|
||||
if (displayName.length > maxLength) {
|
||||
return [[displayName substringToIndex:maxLength] stringByAppendingString:@"…"];
|
||||
}
|
||||
|
||||
return displayName;
|
||||
}
|
||||
|
||||
#pragma mark - Logging
|
||||
|
||||
+ (NSString *)tag
|
||||
{
|
||||
return [NSString stringWithFormat:@"[%@]", self.class];
|
||||
}
|
||||
|
||||
- (NSString *)tag
|
||||
{
|
||||
return self.class.tag;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -4,6 +4,7 @@
|
||||
|
||||
#import "BlockListViewController.h"
|
||||
#import "AddToBlockListViewController.h"
|
||||
#import "BlockListUIUtils.h"
|
||||
#import "Environment.h"
|
||||
#import "OWSContactsManager.h"
|
||||
#import "PhoneNumber.h"
|
||||
@ -19,7 +20,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@property (nonatomic, readonly) OWSContactsManager *contactsManager;
|
||||
@property (nonatomic) NSArray<Contact *> *contacts;
|
||||
@property (nonatomic) NSDictionary<NSString *, Contact *> *contactMap;
|
||||
|
||||
@end
|
||||
|
||||
@ -137,18 +137,7 @@ typedef NS_ENUM(NSInteger, BlockListViewControllerSection) {
|
||||
- (NSString *)displayNameForIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
NSString *phoneNumber = _blockedPhoneNumbers[(NSUInteger)indexPath.item];
|
||||
PhoneNumber *parsedPhoneNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:phoneNumber];
|
||||
|
||||
// Try to parse and present the phone number in E164.
|
||||
// It should already be in E164, so this should always work.
|
||||
// If an invalid or unparsable phone number is already in the block list,
|
||||
// present it as-is.
|
||||
NSString *displayName = (parsedPhoneNumber ? parsedPhoneNumber.toE164 : phoneNumber);
|
||||
Contact *contact = self.contactMap[displayName];
|
||||
if (contact && [contact fullName].length > 0) {
|
||||
displayName = [contact fullName];
|
||||
}
|
||||
|
||||
NSString *displayName = [_contactsManager displayNameForPhoneIdentifier:phoneNumber];
|
||||
return displayName;
|
||||
}
|
||||
|
||||
@ -167,8 +156,11 @@ typedef NS_ENUM(NSInteger, BlockListViewControllerSection) {
|
||||
}
|
||||
case BlockListViewControllerSection_BlockList: {
|
||||
NSString *phoneNumber = _blockedPhoneNumbers[(NSUInteger)indexPath.item];
|
||||
NSString *displayName = [self displayNameForIndexPath:indexPath];
|
||||
[self showUnblockActionSheet:phoneNumber displayName:displayName];
|
||||
[BlockListUIUtils showUnblockPhoneNumberActionSheet:phoneNumber
|
||||
fromViewController:self
|
||||
blockingManager:_blockingManager
|
||||
contactsManager:_contactsManager
|
||||
completionBlock:nil];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -176,56 +168,6 @@ typedef NS_ENUM(NSInteger, BlockListViewControllerSection) {
|
||||
}
|
||||
}
|
||||
|
||||
- (void)showUnblockActionSheet:(NSString *)phoneNumber displayName:(NSString *)displayName
|
||||
{
|
||||
OWSAssert(phoneNumber.length > 0);
|
||||
OWSAssert(displayName.length > 0);
|
||||
|
||||
NSString *title = [NSString stringWithFormat:NSLocalizedString(@"BLOCK_LIST_UNBLOCK_TITLE_FORMAT",
|
||||
@"A format for the 'unblock phone number' action sheet title."),
|
||||
displayName];
|
||||
|
||||
UIAlertController *actionSheetController =
|
||||
[UIAlertController alertControllerWithTitle:title message:nil preferredStyle:UIAlertControllerStyleActionSheet];
|
||||
|
||||
__weak BlockListViewController *weakSelf = self;
|
||||
UIAlertAction *unblockAction = [UIAlertAction
|
||||
actionWithTitle:NSLocalizedString(@"BLOCK_LIST_UNBLOCK_BUTTON", @"Button label for the 'unblock' button")
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
[weakSelf unblockPhoneNumber:phoneNumber displayName:displayName];
|
||||
}];
|
||||
[actionSheetController addAction:unblockAction];
|
||||
|
||||
UIAlertAction *dismissAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"")
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:nil];
|
||||
[actionSheetController addAction:dismissAction];
|
||||
|
||||
[self presentViewController:actionSheetController animated:YES completion:nil];
|
||||
}
|
||||
|
||||
- (void)unblockPhoneNumber:(NSString *)phoneNumber displayName:(NSString *)displayName
|
||||
{
|
||||
[_blockingManager removeBlockedPhoneNumber:phoneNumber];
|
||||
|
||||
UIAlertController *controller = [UIAlertController
|
||||
alertControllerWithTitle:NSLocalizedString(@"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE",
|
||||
@"The title of the 'phone number unblocked' alert in the block view.")
|
||||
message:[NSString stringWithFormat:NSLocalizedString(
|
||||
@"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_MESSAGE_FORMAT",
|
||||
@"The message format of the 'phone number unblocked' "
|
||||
@"alert in the block view. It is populated with the "
|
||||
@"blocked phone number."),
|
||||
displayName]
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
[controller addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil)
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:nil]];
|
||||
[self presentViewController:controller animated:YES completion:nil];
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
- (void)blockedPhoneNumbersDidChange:(id)notification
|
||||
@ -248,22 +190,6 @@ typedef NS_ENUM(NSInteger, BlockListViewControllerSection) {
|
||||
});
|
||||
}
|
||||
|
||||
- (void)setContacts:(NSArray<Contact *> *)contacts
|
||||
{
|
||||
_contacts = contacts;
|
||||
|
||||
NSMutableDictionary<NSString *, Contact *> *contactMap = [NSMutableDictionary new];
|
||||
for (Contact *contact in contacts) {
|
||||
for (PhoneNumber *phoneNumber in contact.parsedPhoneNumbers) {
|
||||
NSString *phoneNumberE164 = phoneNumber.toE164;
|
||||
if (phoneNumberE164.length > 0) {
|
||||
contactMap[phoneNumberE164] = contact;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.contactMap = contactMap;
|
||||
}
|
||||
|
||||
#pragma mark - Logging
|
||||
|
||||
+ (NSString *)tag
|
||||
|
||||
@ -34,41 +34,45 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
OWSTableContents *contents = [OWSTableContents new];
|
||||
contents.title = @"Debug: Conversation";
|
||||
|
||||
[contents addSection:[OWSTableSection sectionWithTitle:@"Messages View"
|
||||
items:@[
|
||||
[OWSTableItem actionWithTitle:@"Send 10 messages (1/sec.)"
|
||||
actionBlock:^{
|
||||
[DebugUITableViewController sendTextMessage:10
|
||||
thread:thread];
|
||||
}],
|
||||
[OWSTableItem actionWithTitle:@"Send 100 messages (1/sec.)"
|
||||
actionBlock:^{
|
||||
[DebugUITableViewController sendTextMessage:100
|
||||
thread:thread];
|
||||
}],
|
||||
[OWSTableItem actionWithTitle:@"Send text/x-signal-plain"
|
||||
actionBlock:^{
|
||||
[DebugUITableViewController sendOversizeTextMessage:thread];
|
||||
}],
|
||||
[OWSTableItem actionWithTitle:@"Send unknown mimetype"
|
||||
actionBlock:^{
|
||||
[DebugUITableViewController sendRandomAttachment:thread
|
||||
uti:SignalAttachment.kUnknownTestAttachmentUTI];
|
||||
}],
|
||||
[OWSTableItem actionWithTitle:@"Send pdf"
|
||||
actionBlock:^{
|
||||
[DebugUITableViewController sendRandomAttachment:thread
|
||||
uti:(NSString *) kUTTypePDF];
|
||||
}],
|
||||
]]];
|
||||
|
||||
[contents
|
||||
addSection:[OWSTableSection
|
||||
sectionWithTitle:@"Messages View"
|
||||
items:@[
|
||||
[OWSTableItem itemWithTitle:@"Send 10 messages (1/sec.)"
|
||||
actionBlock:^{
|
||||
[DebugUITableViewController sendTextMessage:10 thread:thread];
|
||||
}],
|
||||
[OWSTableItem itemWithTitle:@"Send 100 messages (1/sec.)"
|
||||
actionBlock:^{
|
||||
[DebugUITableViewController sendTextMessage:100
|
||||
thread:thread];
|
||||
}],
|
||||
[OWSTableItem itemWithTitle:@"Send text/x-signal-plain"
|
||||
actionBlock:^{
|
||||
[DebugUITableViewController sendOversizeTextMessage:thread];
|
||||
}],
|
||||
[OWSTableItem
|
||||
itemWithTitle:@"Send unknown mimetype"
|
||||
actionBlock:^{
|
||||
[DebugUITableViewController
|
||||
sendRandomAttachment:thread
|
||||
uti:SignalAttachment.kUnknownTestAttachmentUTI];
|
||||
}],
|
||||
[OWSTableItem itemWithTitle:@"Send pdf"
|
||||
actionBlock:^{
|
||||
[DebugUITableViewController
|
||||
sendRandomAttachment:thread
|
||||
uti:(NSString *)kUTTypePDF];
|
||||
}],
|
||||
]]];
|
||||
|
||||
[contents addSection:[OWSTableSection sectionWithTitle:@"Print to Debug Log"
|
||||
items:@[ [OWSTableItem actionWithTitle:@"Print all sessions"
|
||||
actionBlock:^{
|
||||
[[TSStorageManager sharedManager]
|
||||
printAllSessions];
|
||||
}] ]]];
|
||||
items:@[ [OWSTableItem itemWithTitle:@"Print all sessions"
|
||||
actionBlock:^{
|
||||
[[TSStorageManager sharedManager]
|
||||
printAllSessions];
|
||||
}] ]]];
|
||||
|
||||
DebugUITableViewController *viewController = [DebugUITableViewController new];
|
||||
viewController.contents = contents;
|
||||
|
||||
@ -1,13 +1,15 @@
|
||||
// Created by Michael Kirk on 9/21/16.
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSTableViewController.h"
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class TSThread;
|
||||
|
||||
@interface OWSConversationSettingsTableViewController : UITableViewController
|
||||
@interface OWSConversationSettingsTableViewController : OWSTableViewController
|
||||
|
||||
- (void)configureWithThread:(TSThread *)thread;
|
||||
- (void)presentedModalWasDismissed;
|
||||
|
||||
@ -3,10 +3,12 @@
|
||||
//
|
||||
|
||||
#import "OWSConversationSettingsTableViewController.h"
|
||||
#import "BlockListUIUtils.h"
|
||||
#import "Environment.h"
|
||||
#import "FingerprintViewController.h"
|
||||
#import "NewGroupViewController.h"
|
||||
#import "OWSAvatarBuilder.h"
|
||||
#import "OWSBlockingManager.h"
|
||||
#import "OWSContactsManager.h"
|
||||
#import "PhoneNumber.h"
|
||||
#import "ShowGroupMembersViewController.h"
|
||||
@ -27,23 +29,6 @@
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef NS_ENUM(NSUInteger, OWSConversationSettingsTableViewControllerSection) {
|
||||
OWSConversationSettingsTableViewControllerSectionContact,
|
||||
OWSConversationSettingsTableViewControllerSectionGroup
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSUInteger, OWSConversationSettingsTableViewControllerContactCellIndex) {
|
||||
OWSConversationSettingsTableViewControllerCellIndexShowFingerprint,
|
||||
OWSConversationSettingsTableViewControllerCellIndexToggleDisappearingMessages,
|
||||
OWSConversationSettingsTableViewControllerCellIndexSetDisappearingMessagesDuration
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSUInteger, OWSConversationSettingsTableViewControllerGroupCellIndex) {
|
||||
OWSConversationSettingsTableViewControllerCellIndexUpdateGroup,
|
||||
OWSConversationSettingsTableViewControllerCellIndexLeaveGroup,
|
||||
OWSConversationSettingsTableViewControllerCellIndexSeeGroupMembers
|
||||
};
|
||||
|
||||
static NSString *const OWSConversationSettingsTableViewControllerSegueUpdateGroup =
|
||||
@"OWSConversationSettingsTableViewControllerSegueUpdateGroup";
|
||||
static NSString *const OWSConversationSettingsTableViewControllerSegueShowGroupMembers =
|
||||
@ -51,22 +36,20 @@ static NSString *const OWSConversationSettingsTableViewControllerSegueShowGroupM
|
||||
|
||||
@interface OWSConversationSettingsTableViewController ()
|
||||
|
||||
@property (strong, nonatomic) IBOutlet UITableViewCell *verifyPrivacyCell;
|
||||
@property (strong, nonatomic) IBOutlet UITableViewCell *toggleDisappearingMessagesCell;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *toggleDisappearingMessagesTitleLabel;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *toggleDisappearingMessagesDescriptionLabel;
|
||||
@property (strong, nonatomic) IBOutlet UISwitch *disappearingMessagesSwitch;
|
||||
@property (strong, nonatomic) IBOutlet UITableViewCell *disappearingMessagesDurationCell;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *disappearingMessagesDurationLabel;
|
||||
@property (strong, nonatomic) IBOutlet UISlider *disappearingMessagesDurationSlider;
|
||||
@property (nonatomic) IBOutlet UITableViewCell *verifyPrivacyCell;
|
||||
@property (nonatomic) IBOutlet UITableViewCell *blocklistStateCell;
|
||||
@property (nonatomic) IBOutlet UITableViewCell *toggleDisappearingMessagesCell;
|
||||
@property (nonatomic) IBOutlet UILabel *toggleDisappearingMessagesTitleLabel;
|
||||
@property (nonatomic) IBOutlet UILabel *toggleDisappearingMessagesDescriptionLabel;
|
||||
@property (nonatomic) IBOutlet UISwitch *disappearingMessagesSwitch;
|
||||
@property (nonatomic) IBOutlet UITableViewCell *disappearingMessagesDurationCell;
|
||||
@property (nonatomic) IBOutlet UILabel *disappearingMessagesDurationLabel;
|
||||
@property (nonatomic) IBOutlet UISlider *disappearingMessagesDurationSlider;
|
||||
|
||||
@property (strong, nonatomic) IBOutlet UITableViewCell *updateGroupCell;
|
||||
@property (strong, nonatomic) IBOutlet UITableViewCell *leaveGroupCell;
|
||||
@property (strong, nonatomic) IBOutlet UITableViewCell *listGroupMembersCell;
|
||||
@property (strong, nonatomic) IBOutlet UIImageView *avatar;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *nameLabel;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *signalIdLabel;
|
||||
@property (strong, nonatomic) IBOutletCollection(UIImageView) NSArray *cellIcons;
|
||||
@property (nonatomic) IBOutlet UIImageView *avatar;
|
||||
@property (nonatomic) IBOutlet UILabel *nameLabel;
|
||||
@property (nonatomic) IBOutlet UILabel *signalIdLabel;
|
||||
@property (nonatomic) IBOutletCollection(UIImageView) NSArray *cellIcons;
|
||||
|
||||
@property (nonatomic) TSThread *thread;
|
||||
@property (nonatomic) NSString *contactName;
|
||||
@ -80,6 +63,7 @@ static NSString *const OWSConversationSettingsTableViewControllerSegueShowGroupM
|
||||
@property (nonatomic, readonly) TSStorageManager *storageManager;
|
||||
@property (nonatomic, readonly) OWSContactsManager *contactsManager;
|
||||
@property (nonatomic, readonly) OWSMessageSender *messageSender;
|
||||
@property (nonatomic, readonly) OWSBlockingManager *blockingManager;
|
||||
|
||||
@end
|
||||
|
||||
@ -125,6 +109,7 @@ static NSString *const OWSConversationSettingsTableViewControllerSegueShowGroupM
|
||||
_storageManager = [TSStorageManager sharedManager];
|
||||
_contactsManager = [Environment getCurrent].contactsManager;
|
||||
_messageSender = [Environment getCurrent].messageSender;
|
||||
_blockingManager = [OWSBlockingManager sharedManager];
|
||||
}
|
||||
|
||||
- (void)configureWithThread:(TSThread *)thread
|
||||
@ -145,6 +130,15 @@ static NSString *const OWSConversationSettingsTableViewControllerSegueShowGroupM
|
||||
|
||||
#pragma mark - View Lifecycle
|
||||
|
||||
- (void)loadView
|
||||
{
|
||||
// Initialize with empty contents. We'll populate the
|
||||
// contents later.
|
||||
self.contents = [OWSTableContents new];
|
||||
|
||||
[super loadView];
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
@ -162,21 +156,10 @@ static NSString *const OWSConversationSettingsTableViewControllerSegueShowGroupM
|
||||
|
||||
// Translations
|
||||
self.title = NSLocalizedString(@"CONVERSATION_SETTINGS", @"title for conversation settings screen");
|
||||
self.verifyPrivacyCell.textLabel.text
|
||||
= NSLocalizedString(@"VERIFY_PRIVACY", @"table cell label in conversation settings");
|
||||
self.toggleDisappearingMessagesTitleLabel.text
|
||||
= NSLocalizedString(@"DISAPPEARING_MESSAGES", @"table cell label in conversation settings");
|
||||
self.toggleDisappearingMessagesDescriptionLabel.text
|
||||
= NSLocalizedString(@"DISAPPEARING_MESSAGES_DESCRIPTION", @"subheading in conversation settings");
|
||||
self.updateGroupCell.textLabel.text
|
||||
= NSLocalizedString(@"EDIT_GROUP_ACTION", @"table cell label in conversation settings");
|
||||
self.leaveGroupCell.textLabel.text
|
||||
= NSLocalizedString(@"LEAVE_GROUP_ACTION", @"table cell label in conversation settings");
|
||||
self.listGroupMembersCell.textLabel.text
|
||||
= NSLocalizedString(@"LIST_GROUP_MEMBERS_ACTION", @"table cell label in conversation settings");
|
||||
|
||||
self.toggleDisappearingMessagesCell.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||
self.disappearingMessagesDurationCell.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||
|
||||
self.disappearingMessagesDurations = [OWSDisappearingMessagesConfiguration validDurationsSeconds];
|
||||
self.disappearingMessagesDurationSlider.maximumValue = (float)(self.disappearingMessagesDurations.count - 1);
|
||||
@ -200,6 +183,131 @@ static NSString *const OWSConversationSettingsTableViewControllerSegueShowGroupM
|
||||
for (UIImageView *cellIcon in self.cellIcons) {
|
||||
[cellIcon tintColorDidChange];
|
||||
}
|
||||
|
||||
[self updateTableContents];
|
||||
}
|
||||
|
||||
- (void)updateTableContents
|
||||
{
|
||||
OWSTableContents *contents = [OWSTableContents new];
|
||||
contents.title = NSLocalizedString(@"CONVERSATION_SETTINGS", @"title for conversation settings screen");
|
||||
|
||||
__weak OWSConversationSettingsTableViewController *weakSelf = self;
|
||||
|
||||
NSMutableArray *firstSectionItems = [NSMutableArray new];
|
||||
if (!self.isGroupThread && self.thread.hasSafetyNumbers) {
|
||||
[firstSectionItems addObject:[OWSTableItem itemWithCustomCellBlock:^{
|
||||
weakSelf.verifyPrivacyCell.textLabel.text
|
||||
= NSLocalizedString(@"VERIFY_PRIVACY", @"table cell label in conversation settings");
|
||||
return weakSelf.verifyPrivacyCell;
|
||||
}
|
||||
actionBlock:^{
|
||||
[weakSelf
|
||||
performSegueWithIdentifier:
|
||||
@"OWSConversationSettingsTableViewControllerSegueSafetyNumbers"
|
||||
sender:weakSelf];
|
||||
}]];
|
||||
}
|
||||
|
||||
if (!self.isGroupThread) {
|
||||
BOOL isBlocked = [[_blockingManager blockedPhoneNumbers] containsObject:self.signalId];
|
||||
|
||||
[firstSectionItems addObject:[OWSTableItem itemWithCustomCellBlock:^{
|
||||
UITableViewCell *cell = [UITableViewCell new];
|
||||
cell.textLabel.text = NSLocalizedString(
|
||||
@"CONVERSATION_SETTINGS_BLOCK_THIS_USER", @"table cell label in conversation settings");
|
||||
cell.textLabel.textColor = [UIColor blackColor];
|
||||
cell.textLabel.font = [UIFont ows_regularFontWithSize:17.f];
|
||||
cell.textLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
||||
UIImage *icon = [UIImage imageNamed:@"ic_block"];
|
||||
OWSAssert(icon);
|
||||
cell.imageView.image = [icon imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
|
||||
cell.imageView.contentMode = UIViewContentModeScaleToFill;
|
||||
cell.imageView.tintColor = [UIColor blackColor];
|
||||
cell.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||
|
||||
UISwitch *blockUserSwitch = [UISwitch new];
|
||||
blockUserSwitch.on = isBlocked;
|
||||
[blockUserSwitch addTarget:self
|
||||
action:@selector(blockUserSwitchDidChange:)
|
||||
forControlEvents:UIControlEventValueChanged];
|
||||
cell.accessoryView = blockUserSwitch;
|
||||
return cell;
|
||||
}
|
||||
actionBlock:nil]];
|
||||
}
|
||||
|
||||
[firstSectionItems addObject:[OWSTableItem itemWithCustomCellBlock:^{
|
||||
weakSelf.toggleDisappearingMessagesCell.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||
return weakSelf.toggleDisappearingMessagesCell;
|
||||
}
|
||||
customRowHeight:108.f
|
||||
actionBlock:nil]];
|
||||
|
||||
if (self.disappearingMessagesSwitch.isOn) {
|
||||
[firstSectionItems addObject:[OWSTableItem itemWithCustomCellBlock:^{
|
||||
weakSelf.disappearingMessagesDurationCell.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||
return weakSelf.disappearingMessagesDurationCell;
|
||||
}
|
||||
customRowHeight:76.f
|
||||
actionBlock:nil]];
|
||||
}
|
||||
|
||||
[contents addSection:[OWSTableSection sectionWithTitle:nil items:firstSectionItems]];
|
||||
|
||||
if (self.isGroupThread) {
|
||||
NSArray *groupItems = @[
|
||||
[OWSTableItem itemWithCustomCellBlock:^{
|
||||
UITableViewCell *cell = [UITableViewCell new];
|
||||
cell.textLabel.text
|
||||
= NSLocalizedString(@"EDIT_GROUP_ACTION", @"table cell label in conversation settings");
|
||||
cell.textLabel.textColor = [UIColor blackColor];
|
||||
cell.textLabel.font = [UIFont ows_regularFontWithSize:17.f];
|
||||
cell.textLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
||||
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
|
||||
return cell;
|
||||
}
|
||||
actionBlock:^{
|
||||
[weakSelf performSegueWithIdentifier:@"OWSConversationSettingsTableViewControllerSegueUpdateGroup"
|
||||
sender:weakSelf];
|
||||
}],
|
||||
[OWSTableItem itemWithCustomCellBlock:^{
|
||||
UITableViewCell *cell = [UITableViewCell new];
|
||||
cell.textLabel.text
|
||||
= NSLocalizedString(@"LEAVE_GROUP_ACTION", @"table cell label in conversation settings");
|
||||
cell.textLabel.textColor = [UIColor blackColor];
|
||||
cell.textLabel.font = [UIFont ows_regularFontWithSize:17.f];
|
||||
cell.textLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
||||
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
|
||||
return cell;
|
||||
}
|
||||
actionBlock:^{
|
||||
[weakSelf didTapLeaveGroup];
|
||||
}],
|
||||
[OWSTableItem itemWithCustomCellBlock:^{
|
||||
UITableViewCell *cell = [UITableViewCell new];
|
||||
cell.textLabel.text
|
||||
= NSLocalizedString(@"LIST_GROUP_MEMBERS_ACTION", @"table cell label in conversation settings");
|
||||
cell.textLabel.textColor = [UIColor blackColor];
|
||||
cell.textLabel.font = [UIFont ows_regularFontWithSize:17.f];
|
||||
cell.textLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
||||
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
|
||||
return cell;
|
||||
}
|
||||
actionBlock:^{
|
||||
[weakSelf
|
||||
performSegueWithIdentifier:@"OWSConversationSettingsTableViewControllerSegueShowGroupMembers"
|
||||
sender:weakSelf];
|
||||
}],
|
||||
];
|
||||
|
||||
[contents addSection:[OWSTableSection sectionWithTitle:NSLocalizedString(@"GROUP_MANAGEMENT_SECTION",
|
||||
@"Conversation settings table section title")
|
||||
items:groupItems]];
|
||||
}
|
||||
|
||||
self.contents = contents;
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
@ -244,105 +352,6 @@ static NSString *const OWSConversationSettingsTableViewControllerSegueShowGroupM
|
||||
self.avatar.layer.cornerRadius = self.avatar.frame.size.height / 2.0f;
|
||||
}
|
||||
|
||||
#pragma mark - UITableViewDelegate
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
NSInteger baseCount = [super tableView:tableView numberOfRowsInSection:section];
|
||||
|
||||
if (section == OWSConversationSettingsTableViewControllerSectionGroup) {
|
||||
if (self.isGroupThread) {
|
||||
return baseCount;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (section == OWSConversationSettingsTableViewControllerSectionContact) {
|
||||
if (!self.thread.hasSafetyNumbers) {
|
||||
baseCount -= 1;
|
||||
}
|
||||
|
||||
if (!self.disappearingMessagesSwitch.isOn) {
|
||||
// hide duration slider when disappearing messages is off.
|
||||
baseCount -= 1;
|
||||
}
|
||||
}
|
||||
return baseCount;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath
|
||||
{
|
||||
if (indexPath.section == OWSConversationSettingsTableViewControllerSectionContact
|
||||
&& !self.thread.hasSafetyNumbers) {
|
||||
|
||||
// Since fingerprint cell is hidden for some threads we offset our index path
|
||||
NSIndexPath *offsetIndexPath = [NSIndexPath indexPathForRow:indexPath.row + 1 inSection:indexPath.section];
|
||||
return [super tableView:tableView cellForRowAtIndexPath:offsetIndexPath];
|
||||
}
|
||||
|
||||
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
|
||||
}
|
||||
|
||||
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
|
||||
|
||||
// group vs. contact thread have some cells slider at different index.
|
||||
if (cell == self.disappearingMessagesDurationCell) {
|
||||
NSIndexPath *originalIndexPath = [NSIndexPath
|
||||
indexPathForRow:OWSConversationSettingsTableViewControllerCellIndexSetDisappearingMessagesDuration
|
||||
inSection:OWSConversationSettingsTableViewControllerSectionContact];
|
||||
|
||||
return [super tableView:tableView heightForRowAtIndexPath:originalIndexPath];
|
||||
}
|
||||
if (cell == self.toggleDisappearingMessagesCell) {
|
||||
NSIndexPath *originalIndexPath =
|
||||
[NSIndexPath indexPathForRow:OWSConversationSettingsTableViewControllerCellIndexToggleDisappearingMessages
|
||||
inSection:OWSConversationSettingsTableViewControllerSectionContact];
|
||||
|
||||
return [super tableView:tableView heightForRowAtIndexPath:originalIndexPath];
|
||||
} else {
|
||||
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
|
||||
}
|
||||
}
|
||||
|
||||
// Called before the user changes the selection. Return a new indexPath, or nil, to change the proposed selection.
|
||||
- (nullable NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
|
||||
|
||||
// Don't highlight rows that have no selection style.
|
||||
if (cell.selectionStyle == UITableViewCellSelectionStyleNone) {
|
||||
return nil;
|
||||
}
|
||||
return indexPath;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
DDLogDebug(@"%@ tapped indexPath:%@", self.tag, indexPath);
|
||||
|
||||
if (indexPath.section == OWSConversationSettingsTableViewControllerSectionGroup
|
||||
&& indexPath.row == OWSConversationSettingsTableViewControllerCellIndexLeaveGroup) {
|
||||
|
||||
[self didTapLeaveGroup];
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
|
||||
{
|
||||
if (section == OWSConversationSettingsTableViewControllerSectionGroup) {
|
||||
if (self.isGroupThread) {
|
||||
return NSLocalizedString(@"GROUP_MANAGEMENT_SECTION", @"Conversation settings table section title");
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
} else {
|
||||
return [super tableView:tableView titleForHeaderInSection:section];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
- (void)didTapLeaveGroup
|
||||
@ -407,6 +416,49 @@ static NSString *const OWSConversationSettingsTableViewControllerSegueShowGroupM
|
||||
}
|
||||
UISwitch *disappearingMessagesSwitch = (UISwitch *)sender;
|
||||
[self toggleDisappearingMessages:disappearingMessagesSwitch.isOn];
|
||||
|
||||
[self updateTableContents];
|
||||
}
|
||||
|
||||
- (void)blockUserSwitchDidChange:(id)sender
|
||||
{
|
||||
OWSAssert(!self.isGroupThread);
|
||||
|
||||
if (![sender isKindOfClass:[UISwitch class]]) {
|
||||
DDLogError(@"%@ Unexpected sender for block user switch: %@", self.tag, sender);
|
||||
OWSAssert(0);
|
||||
}
|
||||
UISwitch *blockUserSwitch = (UISwitch *)sender;
|
||||
|
||||
BOOL isCurrentlyBlocked = [[_blockingManager blockedPhoneNumbers] containsObject:self.signalId];
|
||||
|
||||
if (blockUserSwitch.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;
|
||||
}];
|
||||
} 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;
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)toggleDisappearingMessages:(BOOL)flag
|
||||
@ -417,28 +469,6 @@ static NSString *const OWSConversationSettingsTableViewControllerSegueShowGroupM
|
||||
// but it allows us to resuse the method to set the switch programmatically in view setup.
|
||||
self.disappearingMessagesSwitch.on = flag;
|
||||
[self durationSliderDidChange:self.disappearingMessagesDurationSlider];
|
||||
|
||||
// Animate show/hide of duration settings.
|
||||
if (flag) {
|
||||
[self.tableView insertRowsAtIndexPaths:@[ self.indexPathForDurationSlider ]
|
||||
withRowAnimation:UITableViewRowAnimationFade];
|
||||
} else {
|
||||
[self.tableView deleteRowsAtIndexPaths:@[ self.indexPathForDurationSlider ]
|
||||
withRowAnimation:UITableViewRowAnimationFade];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSIndexPath *)indexPathForDurationSlider
|
||||
{
|
||||
if (!self.thread.hasSafetyNumbers) {
|
||||
return [NSIndexPath
|
||||
indexPathForRow:OWSConversationSettingsTableViewControllerCellIndexSetDisappearingMessagesDuration - 1
|
||||
inSection:OWSConversationSettingsTableViewControllerSectionContact];
|
||||
} else {
|
||||
return [NSIndexPath
|
||||
indexPathForRow:OWSConversationSettingsTableViewControllerCellIndexSetDisappearingMessagesDuration
|
||||
inSection:OWSConversationSettingsTableViewControllerSectionContact];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)durationSliderDidChange:(UISlider *)slider
|
||||
|
||||
@ -32,15 +32,30 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
#pragma mark -
|
||||
|
||||
typedef NS_ENUM(NSInteger, OWSTableItemType) {
|
||||
OWSTableItemTypeDefault,
|
||||
OWSTableItemTypeAction,
|
||||
};
|
||||
|
||||
typedef void (^OWSTableActionBlock)();
|
||||
typedef UITableViewCell * (^OWSTableCustomCellBlock)();
|
||||
|
||||
@interface OWSTableItem : NSObject
|
||||
|
||||
+ (OWSTableItem *)actionWithTitle:(NSString *)title
|
||||
actionBlock:(OWSTableActionBlock)actionBlock;
|
||||
+ (OWSTableItem *)itemWithTitle:(NSString *)title actionBlock:(nullable OWSTableActionBlock)actionBlock;
|
||||
|
||||
+ (OWSTableItem *)itemWithCustomCell:(UITableViewCell *)customCell
|
||||
customRowHeight:(CGFloat)customRowHeight
|
||||
actionBlock:(nullable OWSTableActionBlock)actionBlock;
|
||||
|
||||
+ (OWSTableItem *)itemWithCustomCellBlock:(OWSTableCustomCellBlock)customCellBlock
|
||||
customRowHeight:(CGFloat)customRowHeight
|
||||
actionBlock:(nullable OWSTableActionBlock)actionBlock;
|
||||
|
||||
+ (OWSTableItem *)itemWithCustomCellBlock:(OWSTableCustomCellBlock)customCellBlock
|
||||
actionBlock:(nullable OWSTableActionBlock)actionBlock;
|
||||
|
||||
- (UITableViewCell *)customCell;
|
||||
- (NSNumber *)customRowHeight;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@ -78,13 +78,17 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property (nonatomic, nullable) NSString *title;
|
||||
@property (nonatomic, nullable) OWSTableActionBlock actionBlock;
|
||||
|
||||
@property (nonatomic) OWSTableCustomCellBlock customCellBlock;
|
||||
@property (nonatomic) UITableViewCell *customCell;
|
||||
@property (nonatomic) NSNumber *customRowHeight;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation OWSTableItem
|
||||
|
||||
+ (OWSTableItem *)actionWithTitle:(NSString *)title actionBlock:(OWSTableActionBlock)actionBlock
|
||||
+ (OWSTableItem *)itemWithTitle:(NSString *)title actionBlock:(nullable OWSTableActionBlock)actionBlock
|
||||
{
|
||||
OWSAssert(title.length > 0);
|
||||
|
||||
@ -95,6 +99,60 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return item;
|
||||
}
|
||||
|
||||
+ (OWSTableItem *)itemWithCustomCell:(UITableViewCell *)customCell
|
||||
customRowHeight:(CGFloat)customRowHeight
|
||||
actionBlock:(nullable OWSTableActionBlock)actionBlock
|
||||
{
|
||||
OWSAssert(customCell);
|
||||
OWSAssert(customRowHeight > 0);
|
||||
|
||||
OWSTableItem *item = [OWSTableItem new];
|
||||
item.itemType = (actionBlock != nil ? OWSTableItemTypeAction : OWSTableItemTypeDefault);
|
||||
item.actionBlock = actionBlock;
|
||||
item.customCell = customCell;
|
||||
item.customRowHeight = @(customRowHeight);
|
||||
return item;
|
||||
}
|
||||
|
||||
+ (OWSTableItem *)itemWithCustomCellBlock:(OWSTableCustomCellBlock)customCellBlock
|
||||
customRowHeight:(CGFloat)customRowHeight
|
||||
actionBlock:(nullable OWSTableActionBlock)actionBlock
|
||||
{
|
||||
OWSAssert(customCellBlock);
|
||||
OWSAssert(customRowHeight > 0);
|
||||
|
||||
OWSTableItem *item = [OWSTableItem new];
|
||||
item.itemType = (actionBlock != nil ? OWSTableItemTypeAction : OWSTableItemTypeDefault);
|
||||
item.actionBlock = actionBlock;
|
||||
item.customCellBlock = customCellBlock;
|
||||
item.customRowHeight = @(customRowHeight);
|
||||
return item;
|
||||
}
|
||||
|
||||
+ (OWSTableItem *)itemWithCustomCellBlock:(OWSTableCustomCellBlock)customCellBlock
|
||||
actionBlock:(nullable OWSTableActionBlock)actionBlock
|
||||
{
|
||||
OWSAssert(customCellBlock);
|
||||
|
||||
OWSTableItem *item = [OWSTableItem new];
|
||||
item.itemType = (actionBlock != nil ? OWSTableItemTypeAction : OWSTableItemTypeDefault);
|
||||
item.actionBlock = actionBlock;
|
||||
item.customCellBlock = customCellBlock;
|
||||
return item;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)customCell
|
||||
{
|
||||
if (_customCell) {
|
||||
return _customCell;
|
||||
}
|
||||
if (_customCellBlock) {
|
||||
return _customCellBlock();
|
||||
}
|
||||
OWSAssert(0);
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
@ -173,6 +231,12 @@ NSString * const kOWSTableCellIdentifier = @"kOWSTableCellIdentifier";
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
OWSTableItem *item = [self itemForIndexPath:indexPath];
|
||||
|
||||
UITableViewCell *customCell = [item customCell];
|
||||
if (customCell) {
|
||||
return customCell;
|
||||
}
|
||||
|
||||
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kOWSTableCellIdentifier];
|
||||
OWSAssert(cell);
|
||||
|
||||
@ -181,13 +245,32 @@ NSString * const kOWSTableCellIdentifier = @"kOWSTableCellIdentifier";
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
OWSTableItem *item = [self itemForIndexPath:indexPath];
|
||||
if (item.customRowHeight) {
|
||||
return [item.customRowHeight floatValue];
|
||||
}
|
||||
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
|
||||
}
|
||||
|
||||
// Called before the user changes the selection. Return a new indexPath, or nil, to change the proposed selection.
|
||||
- (nullable NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
OWSTableItem *item = [self itemForIndexPath:indexPath];
|
||||
if (!item.actionBlock) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return indexPath;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
||||
|
||||
OWSTableItem *item = [self itemForIndexPath:indexPath];
|
||||
if (item.itemType == OWSTableItemTypeAction) {
|
||||
OWSAssert(item.actionBlock);
|
||||
if (item.actionBlock) {
|
||||
item.actionBlock();
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,6 +39,7 @@ extern NSString *const OWSContactsManagerSignalRecipientsDidChangeNotification;
|
||||
- (void)doAfterEnvironmentInitSetup;
|
||||
|
||||
- (NSString *)displayNameForPhoneIdentifier:(nullable NSString *)identifier;
|
||||
- (NSString *)displayNameForContact:(Contact *)contact;
|
||||
- (nullable UIImage *)imageForPhoneIdentifier:(nullable NSString *)identifier;
|
||||
- (NSAttributedString *)formattedFullNameForContact:(Contact *)contact font:(UIFont *)font;
|
||||
|
||||
|
||||
@ -20,12 +20,15 @@ NSString *const OWSContactsManagerSignalRecipientsDidChangeNotification =
|
||||
@property TOCFuture *futureAddressBook;
|
||||
@property ObservableValueController *observableContactsController;
|
||||
@property TOCCancelTokenSource *life;
|
||||
@property(atomic, copy) NSDictionary *latestContactsById;
|
||||
@property (atomic) NSDictionary *latestContactsById;
|
||||
@property (atomic) NSDictionary<NSString *, Contact *> *contactMap;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OWSContactsManager
|
||||
|
||||
@synthesize latestContactsById = _latestContactsById;
|
||||
|
||||
- (void)dealloc {
|
||||
[_life cancel];
|
||||
}
|
||||
@ -46,6 +49,41 @@ NSString *const OWSContactsManagerSignalRecipientsDidChangeNotification =
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSDictionary *)latestContactsById
|
||||
{
|
||||
@synchronized(self)
|
||||
{
|
||||
return _latestContactsById;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setLatestContactsById:(NSDictionary *)latestContactsById
|
||||
{
|
||||
@synchronized(self)
|
||||
{
|
||||
_latestContactsById = [latestContactsById copy];
|
||||
|
||||
NSMutableDictionary<NSString *, Contact *> *contactMap = [NSMutableDictionary new];
|
||||
for (Contact *contact in _latestContactsById.allValues) {
|
||||
// The allContacts method seems to protect against non-contact instances
|
||||
// in latestContactsById, so I've done the same here. I'm not sure if
|
||||
// this is a real issue.
|
||||
OWSAssert([contact isKindOfClass:[Contact class]]);
|
||||
if (![contact isKindOfClass:[Contact class]]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (PhoneNumber *phoneNumber in contact.parsedPhoneNumbers) {
|
||||
NSString *phoneNumberE164 = phoneNumber.toE164;
|
||||
if (phoneNumberE164.length > 0) {
|
||||
contactMap[phoneNumberE164] = contact;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.contactMap = contactMap;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)doAfterEnvironmentInitSetup {
|
||||
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(9, 0)) {
|
||||
self.contactStore = [[CNContactStore alloc] init];
|
||||
@ -419,6 +457,15 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in
|
||||
return displayName;
|
||||
}
|
||||
|
||||
- (NSString *_Nonnull)displayNameForContact:(Contact *)contact
|
||||
{
|
||||
OWSAssert(contact);
|
||||
|
||||
NSString *displayName = (contact.fullName.length > 0) ? contact.fullName : self.unknownContactName;
|
||||
|
||||
return displayName;
|
||||
}
|
||||
|
||||
- (NSAttributedString *_Nonnull)formattedFullNameForContact:(Contact *)contact font:(UIFont *_Nonnull)font
|
||||
{
|
||||
UIFont *boldFont = [UIFont ows_mediumFontWithSize:font.pointSize];
|
||||
@ -473,14 +520,7 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in
|
||||
if (!identifier) {
|
||||
return nil;
|
||||
}
|
||||
for (Contact *contact in self.allContacts) {
|
||||
for (PhoneNumber *phoneNumber in contact.parsedPhoneNumbers) {
|
||||
if ([phoneNumber.toE164 isEqualToString:identifier]) {
|
||||
return contact;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
return self.contactMap[identifier];
|
||||
}
|
||||
|
||||
- (Contact *)getOrBuildContactForPhoneIdentifier:(NSString *)identifier
|
||||
|
||||
@ -100,38 +100,44 @@
|
||||
/* Button label for the 'block' button */
|
||||
"BLOCK_LIST_BLOCK_BUTTON" = "Block";
|
||||
|
||||
/* A format for the 'block phone number' action sheet title. */
|
||||
/* A format for the 'block user' action sheet title. Embeds {{the blocked user's name or phone number}}. */
|
||||
"BLOCK_LIST_BLOCK_TITLE_FORMAT" = "Block %@?";
|
||||
|
||||
/* Button label for the 'unblock' button */
|
||||
"BLOCK_LIST_UNBLOCK_BUTTON" = "Unblock";
|
||||
|
||||
/* A format for the 'unblock phone number' action sheet title. */
|
||||
/* A format for the 'unblock user' action sheet title. Embeds {{the blocked user's name or phone number}}. */
|
||||
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "Unblock %@?";
|
||||
|
||||
/* A label for the block button in the block list view */
|
||||
"BLOCK_LIST_VIEW_BLOCK_BUTTON" = "Block";
|
||||
|
||||
/* The message format of the 'contact blocked' alert in the block view. It is populated with the blocked contact's name. */
|
||||
"BLOCK_LIST_VIEW_CONTACT_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ has been blocked";
|
||||
/* The title of the 'block user failed' alert. */
|
||||
"BLOCK_LIST_VIEW_BLOCK_FAILED_ALERT_MESSAGE" = "Block user failed.";
|
||||
|
||||
/* The title of the 'contact blocked' alert in the block view. */
|
||||
"BLOCK_LIST_VIEW_CONTACT_BLOCKED_ALERT_TITLE" = "Contact Blocked";
|
||||
/* The title of the 'block user failed' alert. */
|
||||
"BLOCK_LIST_VIEW_BLOCK_FAILED_ALERT_TITLE" = "Error";
|
||||
|
||||
/* The message format of the 'user blocked' alert. Embeds {{the blocked user's name or phone number}}. */
|
||||
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ has been blocked";
|
||||
|
||||
/* The title of the 'user blocked' alert. */
|
||||
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "User Blocked";
|
||||
|
||||
/* A title for the contacts section of the blocklist view. */
|
||||
"BLOCK_LIST_VIEW_CONTACTS_SECTION_TITLE" = "Contacts";
|
||||
|
||||
/* The message format of the 'phone number blocked' alert in the block view. It is populated with the blocked phone number. */
|
||||
"BLOCK_LIST_VIEW_PHONE_NUMBER_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ has been blocked";
|
||||
/* The title of the 'unblock user failed' alert. */
|
||||
"BLOCK_LIST_VIEW_UNBLOCK_FAILED_ALERT_MESSAGE" = "Unblock user failed.";
|
||||
|
||||
/* The title of the 'phone number blocked' alert in the block view. */
|
||||
"BLOCK_LIST_VIEW_PHONE_NUMBER_BLOCKED_ALERT_TITLE" = "Phone Number Blocked";
|
||||
/* The title of the 'unblock user failed' alert. */
|
||||
"BLOCK_LIST_VIEW_UNBLOCK_FAILED_ALERT_TITLE" = "Error";
|
||||
|
||||
/* The message format of the 'phone number unblocked' alert in the block view. It is populated with the blocked phone number. */
|
||||
/* The message format of the 'user unblocked' alert. Embeds {{the blocked user's name or phone number}}. */
|
||||
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_MESSAGE_FORMAT" = "%@ has been unblocked.";
|
||||
|
||||
/* The title of the 'phone number unblocked' alert in the block view. */
|
||||
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE" = "Phone Number Unblocked";
|
||||
/* The title of the 'user unblocked' alert. */
|
||||
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE" = "User Unblocked";
|
||||
|
||||
/* Accessibilty label for placing call button */
|
||||
"CALL_LABEL" = "Call";
|
||||
@ -193,6 +199,9 @@
|
||||
/* title for conversation settings screen */
|
||||
"CONVERSATION_SETTINGS" = "Conversation Settings";
|
||||
|
||||
/* table cell label in conversation settings */
|
||||
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "Block this user";
|
||||
|
||||
/* The message of the 'text message too large' alert. */
|
||||
"CONVERSATION_VIEW_TEXT_MESSAGE_TOO_LARGE_ALERT_MESSAGE" = "This message is too long to send.";
|
||||
|
||||
@ -733,10 +742,10 @@
|
||||
/* Alert title */
|
||||
"REGISTRATION_BODY" = "Failed to re-register for push notifications.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
/* Label for the country code field */
|
||||
"REGISTRATION_DEFAULT_COUNTRY_NAME" = "Country Code";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
/* Placeholder text for the phone number textfield */
|
||||
"REGISTRATION_ENTERNUMBER_DEFAULT_TEXT" = "Enter Number";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
@ -748,7 +757,7 @@
|
||||
/* No comment provided by engineer. */
|
||||
"REGISTRATION_NON_VALID_NUMBER" = "This phone number format is not supported, please contact support.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
/* Label for the phone number textfield */
|
||||
"REGISTRATION_PHONENUMBER_BUTTON" = "Phone Number";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
@ -841,7 +850,7 @@
|
||||
/* A header title for the block list table. */
|
||||
"SETTINGS_BLOCK_LIST_HEADER_TITLE" = "Blocked Phone Numbers";
|
||||
|
||||
/* Label for the block list row of the settings view */
|
||||
/* Label for the block list section of the settings view */
|
||||
"SETTINGS_BLOCK_LIST_TITLE" = "Blocked";
|
||||
|
||||
/* User settings section footer, a detailed explanation */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user