Add blacklist controls to 1:1 conversation view.

// FREEBIE
This commit is contained in:
Matthew Chen 2017-04-03 10:29:11 -04:00
parent 80ddc1a2c3
commit 54cd8cfa3c
20 changed files with 749 additions and 358 deletions

View File

@ -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 */,

View 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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View 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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -446,18 +446,40 @@
</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"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Disappearing Messages" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="qbY-qJ-enK" userLabel="Disappearing Messages">
<rect key="frame" x="64" y="0.0" width="238" height="44"/>
<rect key="frame" x="68" y="0.0" width="234" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="dT5-gx-pqJ"/>
</constraints>
@ -475,7 +497,7 @@
</connections>
</switch>
<imageView opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="table_ic_timer" translatesAutoresizingMaskIntoConstraints="NO" id="iRL-ZI-kXA">
<rect key="frame" x="16" y="6" width="32" height="32"/>
<rect key="frame" x="20" y="6" width="32" height="32"/>
<color key="tintColor" red="0.054901960780000002" green="0.054901960780000002" blue="0.054901960780000002" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" secondItem="iRL-ZI-kXA" secondAttribute="height" multiplier="1:1" id="QMF-qg-bIc"/>
@ -483,14 +505,14 @@
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="When enabled, messages sent and received in this conversation will disappear after they have been seen." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="zIg-K4-8lV">
<rect key="frame" x="64" y="40" width="287" height="59"/>
<rect key="frame" x="68" y="40" width="283" height="59"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleFootnote"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstItem="iRL-ZI-kXA" firstAttribute="leading" secondItem="Nmz-2u-fOY" secondAttribute="leading" constant="16" id="FsM-rL-dWt"/>
<constraint firstItem="iRL-ZI-kXA" firstAttribute="leading" secondItem="Nmz-2u-fOY" secondAttribute="leading" constant="20" id="FsM-rL-dWt"/>
<constraint firstItem="qbY-qJ-enK" firstAttribute="top" secondItem="Nmz-2u-fOY" secondAttribute="top" id="Hzt-Rw-yQA"/>
<constraint firstItem="zIg-K4-8lV" firstAttribute="top" secondItem="qbY-qJ-enK" secondAttribute="bottom" constant="-4" id="NGz-Yy-9uN"/>
<constraint firstItem="zIg-K4-8lV" firstAttribute="leading" secondItem="qbY-qJ-enK" secondAttribute="leading" id="PYG-46-cLa"/>
@ -506,20 +528,20 @@
<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"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Messages disappear after 8 hours." lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="c6Q-rV-1LO" userLabel="Keep messages for 8 hours.">
<rect key="frame" x="64" y="6" width="303" height="32"/>
<rect key="frame" x="68" y="6" width="299" height="32"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleFootnote"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="4Hn-9p-qsR">
<rect key="frame" x="62" y="38" width="295" height="31"/>
<rect key="frame" x="66" y="38" width="291" height="31"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="D1q-zH-wtT"/>
</constraints>
@ -528,7 +550,7 @@
</connections>
</slider>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="table_ic_hourglass_empty" translatesAutoresizingMaskIntoConstraints="NO" id="X7n-1t-1Q7">
<rect key="frame" x="16" y="6" width="32" height="32"/>
<rect key="frame" x="20" y="6" width="32" height="32"/>
<color key="tintColor" red="0.054901960784313725" green="0.054901960784313725" blue="0.054901960784313725" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" constant="32" id="Pmb-2B-dEA"/>
@ -544,7 +566,7 @@
<constraint firstItem="c6Q-rV-1LO" firstAttribute="bottom" secondItem="X7n-1t-1Q7" secondAttribute="bottom" id="WOE-pQ-2zh"/>
<constraint firstItem="c6Q-rV-1LO" firstAttribute="leading" secondItem="X7n-1t-1Q7" secondAttribute="trailing" constant="16" id="itv-VA-m3d"/>
<constraint firstItem="c6Q-rV-1LO" firstAttribute="top" secondItem="X7n-1t-1Q7" secondAttribute="top" id="oa2-QP-Lhu"/>
<constraint firstItem="X7n-1t-1Q7" firstAttribute="leading" secondItem="2a2-Po-p8O" secondAttribute="leading" constant="16" id="qNh-GB-pE2"/>
<constraint firstItem="X7n-1t-1Q7" firstAttribute="leading" secondItem="2a2-Po-p8O" secondAttribute="leading" constant="20" id="qNh-GB-pE2"/>
<constraint firstItem="4Hn-9p-qsR" firstAttribute="top" secondItem="c6Q-rV-1LO" secondAttribute="bottom" id="ssH-ql-B0K"/>
</constraints>
</tableViewCellContentView>
@ -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"/>

View File

@ -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,17 @@ 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]
displayName:[parsedPhoneNumber toE164]
fromViewController:self
blockingManager:_blockingManager
completionBlock:^(BOOL isBlocked) {
if (isBlocked) {
// Clear phone number text field is block succeeds.
weakSelf.phoneNumberTextField.text = nil;
}
}];
}
- (void)textFieldDidChange:(id)sender
@ -417,62 +410,10 @@ 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];
[BlockListUIUtils showBlockContactActionSheet:contact
fromViewController:self
blockingManager:_blockingManager
completionBlock:nil];
}
#pragma mark - UIScrollViewDelegate

View File

@ -0,0 +1,33 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import <UIKit/UIKit.h>
@class Contact;
@class OWSBlockingManager;
typedef void (^BlockActionCompletionBlock)(BOOL isBlocked);
@interface BlockListUIUtils : NSObject
- (instancetype)init NS_UNAVAILABLE;
+ (void)showBlockContactActionSheet:(Contact *)contact
fromViewController:(UIViewController *)fromViewController
blockingManager:(OWSBlockingManager *)blockingManager
completionBlock:(BlockActionCompletionBlock)completionBlock;
+ (void)showBlockPhoneNumberActionSheet:(NSString *)phoneNumber
displayName:(NSString *)displayName
fromViewController:(UIViewController *)fromViewController
blockingManager:(OWSBlockingManager *)blockingManager
completionBlock:(BlockActionCompletionBlock)completionBlock;
+ (void)showUnblockPhoneNumberActionSheet:(NSString *)phoneNumber
displayName:(NSString *)displayName
fromViewController:(UIViewController *)fromViewController
blockingManager:(OWSBlockingManager *)blockingManager
completionBlock:(BlockActionCompletionBlock)completionBlock;
@end

View File

@ -0,0 +1,241 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "BlockListUIUtils.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
completionBlock:(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) {
[self showBlockFailedAlert:fromViewController];
if (completionBlock) {
completionBlock(NO);
}
return;
}
[self showBlockPhoneNumbersActionSheet:phoneNumbers
displayName:contact.fullName
fromViewController:fromViewController
blockingManager:blockingManager
completionBlock:completionBlock];
}
+ (void)showBlockPhoneNumberActionSheet:(NSString *)phoneNumber
displayName:(NSString *)displayName
fromViewController:(UIViewController *)fromViewController
blockingManager:(OWSBlockingManager *)blockingManager
completionBlock:(BlockActionCompletionBlock)completionBlock
{
[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:(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."),
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:UIAlertActionStyleDefault
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}}."),
displayName]
fromViewController:fromViewController];
}
+ (void)showUnblockPhoneNumberActionSheet:(NSString *)phoneNumber
displayName:(NSString *)displayName
fromViewController:(UIViewController *)fromViewController
blockingManager:(OWSBlockingManager *)blockingManager
completionBlock:(BlockActionCompletionBlock)completionBlock
{
OWSAssert(phoneNumber.length > 0);
OWSAssert(displayName.length > 0);
OWSAssert(fromViewController);
OWSAssert(blockingManager);
NSString *title = [NSString stringWithFormat:NSLocalizedString(@"BLOCK_LIST_UNBLOCK_TITLE_FORMAT",
@"A format for the 'unblock user' action sheet title."),
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:UIAlertActionStyleDefault
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. It is populated with the "
@"blocked phone number."),
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];
}
#pragma mark - Logging
+ (NSString *)tag
{
return [NSString stringWithFormat:@"[%@]", self.class];
}
- (NSString *)tag
{
return self.class.tag;
}
@end
NS_ASSUME_NONNULL_END

View File

@ -4,6 +4,7 @@
#import "BlockListViewController.h"
#import "AddToBlockListViewController.h"
#import "BlockListUIUtils.h"
#import "Environment.h"
#import "OWSContactsManager.h"
#import "PhoneNumber.h"
@ -168,7 +169,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
displayName:displayName
fromViewController:self
blockingManager:_blockingManager
completionBlock:nil];
break;
}
default:
@ -176,56 +181,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

View File

@ -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;

View File

@ -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;

View File

@ -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,48 @@ 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);
}
UISwitch *blockUserSwitch = (UISwitch *)sender;
BOOL isCurrentlyBlocked = [[_blockingManager blockedPhoneNumbers] containsObject:self.signalId];
if (blockUserSwitch.isOn) {
OWSAssert(!isCurrentlyBlocked);
if (isCurrentlyBlocked) {
return;
}
[BlockListUIUtils showBlockPhoneNumberActionSheet:self.thread.contactIdentifier
displayName:self.thread.name
fromViewController:self
blockingManager:_blockingManager
completionBlock:^(BOOL isBlocked) {
// Update switch state if user cancels action.
blockUserSwitch.on = isBlocked;
}];
} else {
OWSAssert(isCurrentlyBlocked);
if (!isCurrentlyBlocked) {
return;
}
[BlockListUIUtils showUnblockPhoneNumberActionSheet:self.thread.contactIdentifier
displayName:self.thread.name
fromViewController:self
blockingManager:_blockingManager
completionBlock:^(BOOL isBlocked) {
// Update switch state if user cancels action.
blockUserSwitch.on = isBlocked;
}];
}
}
- (void)toggleDisappearingMessages:(BOOL)flag
@ -417,28 +468,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

View File

@ -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:(OWSTableActionBlock)actionBlock;
+ (OWSTableItem *)itemWithCustomCell:(UITableViewCell *)customCell
customRowHeight:(CGFloat)customRowHeight
actionBlock:(OWSTableActionBlock)actionBlock;
+ (OWSTableItem *)itemWithCustomCellBlock:(OWSTableCustomCellBlock)customCellBlock
customRowHeight:(CGFloat)customRowHeight
actionBlock:(OWSTableActionBlock)actionBlock;
+ (OWSTableItem *)itemWithCustomCellBlock:(OWSTableCustomCellBlock)customCellBlock
actionBlock:(OWSTableActionBlock)actionBlock;
- (UITableViewCell *)customCell;
- (NSNumber *)customRowHeight;
@end

View File

@ -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:(OWSTableActionBlock)actionBlock
{
OWSAssert(title.length > 0);
@ -95,6 +99,60 @@ NS_ASSUME_NONNULL_BEGIN
return item;
}
+ (OWSTableItem *)itemWithCustomCell:(UITableViewCell *)customCell
customRowHeight:(CGFloat)customRowHeight
actionBlock:(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:(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:(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();
}
}

View File

@ -100,23 +100,29 @@
/* 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. */
"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. */
"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. It is populated with the blocked contact's name. */
"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";
@ -127,11 +133,17 @@
/* The title of the 'phone number blocked' alert in the block view. */
"BLOCK_LIST_VIEW_PHONE_NUMBER_BLOCKED_ALERT_TITLE" = "Phone Number Blocked";
/* The message format of the 'phone number unblocked' alert in the block view. It is populated with the blocked phone number. */
/* The title of the 'unblock user failed' alert. */
"BLOCK_LIST_VIEW_UNBLOCK_FAILED_ALERT_MESSAGE" = "Unblock user failed.";
/* The title of the 'unblock user failed' alert. */
"BLOCK_LIST_VIEW_UNBLOCK_FAILED_ALERT_TITLE" = "Error";
/* The message format of the 'user unblocked' alert. It is populated with the blocked 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 +205,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.";