Add new delete account flow

This commit is contained in:
Nora Trapp 2021-03-08 16:11:08 -08:00
parent 0ec429ed3a
commit 49c17f2af8
33 changed files with 514 additions and 103 deletions

View File

@ -751,6 +751,7 @@
887B380F25F056FD00685845 /* NotificationSettingsSoundViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 887B380E25F056FD00685845 /* NotificationSettingsSoundViewController.swift */; };
887B381125F05F3100685845 /* PrivacySettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 887B381025F05F3100685845 /* PrivacySettingsViewController.swift */; };
887B381325F0681400685845 /* AdvancedPrivacySettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 887B381225F0681400685845 /* AdvancedPrivacySettingsViewController.swift */; };
887B6DC925F6C3E900E677D4 /* DeleteAccountConfirmationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 887B6DC825F6C3E900E677D4 /* DeleteAccountConfirmationViewController.swift */; };
887C6A7824DBB16E00141B64 /* ResizingScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 887C6A7724DBB16E00141B64 /* ResizingScrollView.swift */; };
887CD4772472FEA500FDD265 /* DeviceTransferOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 887CD4762472FEA500FDD265 /* DeviceTransferOperation.swift */; };
887CD47B247304B600FDD265 /* DeviceTransferService+URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 887CD47A247304B600FDD265 /* DeviceTransferService+URL.swift */; };
@ -1827,6 +1828,7 @@
887B381025F05F3100685845 /* PrivacySettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacySettingsViewController.swift; sourceTree = "<group>"; };
887B381225F0681400685845 /* AdvancedPrivacySettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedPrivacySettingsViewController.swift; sourceTree = "<group>"; };
887B6B2324895F1F0075EBC7 /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = translations/eu.lproj/Localizable.strings; sourceTree = "<group>"; };
887B6DC825F6C3E900E677D4 /* DeleteAccountConfirmationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteAccountConfirmationViewController.swift; sourceTree = "<group>"; };
887C6A7724DBB16E00141B64 /* ResizingScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResizingScrollView.swift; sourceTree = "<group>"; };
887CD4762472FEA500FDD265 /* DeviceTransferOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceTransferOperation.swift; sourceTree = "<group>"; };
887CD47A247304B600FDD265 /* DeviceTransferService+URL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DeviceTransferService+URL.swift"; sourceTree = "<group>"; };
@ -2277,34 +2279,18 @@
isa = PBXGroup;
children = (
88F58A1625EEE5B9008CDA24 /* AppSettingsViewController.swift */,
88E728FE25F0241100A2E4A4 /* AccountSettingsViewController.swift */,
88C7597224B7EAA600DB03EA /* AdvancedPinSettingsTableViewController.swift */,
8827004D23208A1900F01C46 /* AppearanceSettingsTableViewController.swift */,
8829883825B979F900DEE1E3 /* ThemeSettingsTableViewController.swift */,
340FC890204DAC8C007AEB0F /* BlockListViewController.h */,
340FC887204DAC8C007AEB0F /* BlockListViewController.m */,
887B6DCA25F6C3F500E677D4 /* Account */,
887B6DCB25F6C40500E677D4 /* Appearance */,
887B380725F0355700685845 /* ChatsSettingsViewController.swift */,
329D42A625AE673400DCB449 /* NetworkInterfacePreferenceViewController.swift */,
346C19DE25ACDF0B00061D3A /* DataSettingsTableViewController.swift */,
340FC889204DAC8C007AEB0F /* DomainFrontingCountryViewController.h */,
340FC87D204DAC8C007AEB0F /* DomainFrontingCountryViewController.m */,
344A761024B366F4009D69A5 /* FlagsViewController.swift */,
887B6DCC25F6C41500E677D4 /* Data Usage */,
32ECD08624BFBF5C00EDDED0 /* Help */,
8862A55825F090C5005D65DB /* InternalSettingsViewController.swift */,
3437F6392512835200AC1767 /* LinkedDevicesTableViewController.swift */,
346C19E025ACE9AE00061D3A /* MediaDownloadSettingsViewController.swift */,
887B6DCE25F6C45B00E677D4 /* Internal */,
887B6DCD25F6C44800E677D4 /* Linked Devices */,
887B380B25F042A300685845 /* Notifications */,
340FC87F204DAC8C007AEB0F /* OWSBackupSettingsViewController.h */,
340FC88E204DAC8C007AEB0F /* OWSBackupSettingsViewController.m */,
340FC891204DAC8C007AEB0F /* OWSLinkDeviceViewController.h */,
340FC885204DAC8C007AEB0F /* OWSLinkDeviceViewController.m */,
340FC888204DAC8C007AEB0F /* OWSQRCodeScanningViewController.h */,
340FC896204DAC8C007AEB0F /* OWSQRCodeScanningViewController.m */,
88D1BCBA24F73C15009A1738 /* PhoneNumberDiscoverabilitySettingsTableViewController.swift */,
88D1BCB824F73C04009A1738 /* PhoneNumberSharingSettingsTableViewController.swift */,
887B381425F0681B00685845 /* Privacy */,
8871B16D25F007CE00D4E070 /* Profile */,
344A761224B36C8C009D69A5 /* TestingViewController.swift */,
);
path = AppSettings;
sourceTree = "<group>";
@ -3564,10 +3550,67 @@
children = (
887B381025F05F3100685845 /* PrivacySettingsViewController.swift */,
887B381225F0681400685845 /* AdvancedPrivacySettingsViewController.swift */,
340FC890204DAC8C007AEB0F /* BlockListViewController.h */,
340FC887204DAC8C007AEB0F /* BlockListViewController.m */,
340FC889204DAC8C007AEB0F /* DomainFrontingCountryViewController.h */,
340FC87D204DAC8C007AEB0F /* DomainFrontingCountryViewController.m */,
88D1BCBA24F73C15009A1738 /* PhoneNumberDiscoverabilitySettingsTableViewController.swift */,
88D1BCB824F73C04009A1738 /* PhoneNumberSharingSettingsTableViewController.swift */,
);
path = Privacy;
sourceTree = "<group>";
};
887B6DCA25F6C3F500E677D4 /* Account */ = {
isa = PBXGroup;
children = (
88E728FE25F0241100A2E4A4 /* AccountSettingsViewController.swift */,
88C7597224B7EAA600DB03EA /* AdvancedPinSettingsTableViewController.swift */,
887B6DC825F6C3E900E677D4 /* DeleteAccountConfirmationViewController.swift */,
);
path = Account;
sourceTree = "<group>";
};
887B6DCB25F6C40500E677D4 /* Appearance */ = {
isa = PBXGroup;
children = (
8827004D23208A1900F01C46 /* AppearanceSettingsTableViewController.swift */,
8829883825B979F900DEE1E3 /* ThemeSettingsTableViewController.swift */,
);
path = Appearance;
sourceTree = "<group>";
};
887B6DCC25F6C41500E677D4 /* Data Usage */ = {
isa = PBXGroup;
children = (
329D42A625AE673400DCB449 /* NetworkInterfacePreferenceViewController.swift */,
346C19DE25ACDF0B00061D3A /* DataSettingsTableViewController.swift */,
346C19E025ACE9AE00061D3A /* MediaDownloadSettingsViewController.swift */,
);
path = "Data Usage";
sourceTree = "<group>";
};
887B6DCD25F6C44800E677D4 /* Linked Devices */ = {
isa = PBXGroup;
children = (
3437F6392512835200AC1767 /* LinkedDevicesTableViewController.swift */,
340FC891204DAC8C007AEB0F /* OWSLinkDeviceViewController.h */,
340FC885204DAC8C007AEB0F /* OWSLinkDeviceViewController.m */,
340FC888204DAC8C007AEB0F /* OWSQRCodeScanningViewController.h */,
340FC896204DAC8C007AEB0F /* OWSQRCodeScanningViewController.m */,
);
path = "Linked Devices";
sourceTree = "<group>";
};
887B6DCE25F6C45B00E677D4 /* Internal */ = {
isa = PBXGroup;
children = (
344A761024B366F4009D69A5 /* FlagsViewController.swift */,
8862A55825F090C5005D65DB /* InternalSettingsViewController.swift */,
344A761224B36C8C009D69A5 /* TestingViewController.swift */,
);
path = Internal;
sourceTree = "<group>";
};
888B6D4325B2223200E2A662 /* Wallpapers */ = {
isa = PBXGroup;
children = (
@ -5325,6 +5368,7 @@
34995F1B2411838D00C70546 /* NewGroupMembersViewController.swift in Sources */,
340FC8BC204DAC8D007AEB0F /* FingerprintViewController.m in Sources */,
34A4C61E221613D00042EF2E /* OnboardingVerificationViewController.swift in Sources */,
887B6DC925F6C3E900E677D4 /* DeleteAccountConfirmationViewController.swift in Sources */,
884EFBAC251478D0006B9457 /* ResearchMegaphone.swift in Sources */,
4CC613362227A00400E21A3A /* ConversationSearch.swift in Sources */,
88A505FA23DBA1360005C012 /* IntroducingPINs.swift in Sources */,

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "delete-account-dark.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "delete-account.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -179,37 +179,18 @@ class AccountSettingsViewController: OWSTableViewController2 {
}
private func unregisterUser() {
showDeleteAccountUI(isRegistered: true)
let vc = DeleteAccountConfirmationViewController()
presentFormSheet(OWSNavigationController(rootViewController: vc), animated: true)
}
private func deleteUnregisterUserData() {
showDeleteAccountUI(isRegistered: false)
}
private func showDeleteAccountUI(isRegistered: Bool) {
OWSActionSheets.showConfirmationAlert(
title: NSLocalizedString("CONFIRM_ACCOUNT_DESTRUCTION_TITLE", comment: ""),
message: NSLocalizedString("CONFIRM_ACCOUNT_DESTRUCTION_TEXT", comment: ""),
title: NSLocalizedString("CONFIRM_DELETE_DATA_TITLE", comment: ""),
message: NSLocalizedString("CONFIRM_DELETE_DATA_TEXT", comment: ""),
proceedTitle: NSLocalizedString("PROCEED_BUTTON", comment: ""),
proceedStyle: .destructive
) { [weak self] _ in
self?.deleteAccount(isRegistered: isRegistered)
}
}
private func deleteAccount(isRegistered: Bool) {
guard isRegistered else { return SignalApp.resetAppData() }
ModalActivityIndicatorViewController.present(fromViewController: self, canCancel: false) { modal in
TSAccountManager.unregisterTextSecure {
SignalApp.resetAppData()
} failure: { error in
owsFailDebug("Faild to unregister \(error)")
modal.dismiss {
OWSActionSheets.showActionSheet(title: NSLocalizedString("UNREGISTER_SIGNAL_FAIL", comment: ""))
}
}
SignalApp.resetAppData()
}
}

View File

@ -0,0 +1,326 @@
//
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
//
import Foundation
class DeleteAccountConfirmationViewController: OWSTableViewController2 {
private var callingCode = "+1"
private var countryCode = "US"
private let phoneNumberTextField = UITextField()
// Don't allow swipe to dismiss
override var isModalInPresentation: Bool {
get { true }
set {}
}
override func loadView() {
view = UIView()
phoneNumberTextField.returnKeyType = .done
phoneNumberTextField.autocorrectionType = .no
phoneNumberTextField.spellCheckingType = .no
phoneNumberTextField.placeholder = ViewControllerUtils.examplePhoneNumber(
forCountryCode: countryCode,
callingCode: callingCode,
includeExampleLabel: false
)
phoneNumberTextField.delegate = self
phoneNumberTextField.accessibilityIdentifier = "phone_number_textfield"
}
override func viewDidLoad() {
shouldAvoidKeyboard = true
super.viewDidLoad()
navigationItem.leftBarButtonItem = .init(barButtonSystemItem: .cancel, target: self, action: #selector(didTapCancel))
navigationItem.rightBarButtonItem = .init(title: CommonStrings.deleteButton, style: .done, target: self, action: #selector(didTapDelete))
navigationItem.rightBarButtonItem?.setTitleTextAttributes([.foregroundColor: UIColor.ows_accentRed], for: .normal)
populateDefaultCountryCode()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
phoneNumberTextField.becomeFirstResponder()
}
override func themeDidChange() {
super.themeDidChange()
updateTableContents()
}
func updateTableContents() {
let contents = OWSTableContents()
let headerSection = OWSTableSection()
headerSection.hasBackground = false
headerSection.add(.init(customCell: buildHeaderCell()))
contents.addSection(headerSection)
let confirmSection = OWSTableSection()
confirmSection.headerTitle = NSLocalizedString(
"DELETE_ACCOUNT_CONFIRMATION_SECTION_TITLE",
comment: "Section header"
)
confirmSection.add(.disclosureItem(
withText: NSLocalizedString(
"DELETE_ACCOUNT_CONFIRMATION_COUNTRY_CODE_TITLE",
comment: "Title for the 'country code' row of the 'delete account confirmation' view controller."
),
detailText: "\(callingCode) (\(countryCode))",
actionBlock: { [weak self] in
guard let self = self else { return }
let countryCodeController = CountryCodeViewController()
countryCodeController.countryCodeDelegate = self
self.present(OWSNavigationController(rootViewController: countryCodeController), animated: true)
}
))
confirmSection.add(.init(
customCellBlock: {
self.buildPhoneNumberCell()
}, actionBlock: { [weak self] in
self?.phoneNumberTextField.becomeFirstResponder()
}
))
contents.addSection(confirmSection)
self.contents = contents
}
func buildHeaderCell() -> UITableViewCell {
let imageView = UIImageView(image: Theme.isDarkThemeEnabled ? #imageLiteral(resourceName: "delete-account-dark") : #imageLiteral(resourceName: "delete-account-light"))
imageView.autoSetDimensions(to: CGSize(square: 112))
let imageContainer = UIView()
imageContainer.addSubview(imageView)
imageView.autoPinEdge(toSuperviewEdge: .top)
imageView.autoPinEdge(toSuperviewEdge: .bottom, withInset: 12)
imageView.autoHCenterInSuperview()
let titleLabel = UILabel()
titleLabel.font = UIFont.ows_dynamicTypeTitle2.ows_semibold
titleLabel.textColor = Theme.primaryTextColor
titleLabel.textAlignment = .center
titleLabel.text = NSLocalizedString(
"DELETE_ACCOUNT_CONFIRMATION_TITLE",
comment: "Title for the 'delete account' confirmation view."
)
let descriptionLabel = UILabel()
descriptionLabel.numberOfLines = 0
descriptionLabel.lineBreakMode = .byWordWrapping
descriptionLabel.font = .ows_dynamicTypeSubheadline
descriptionLabel.textColor = Theme.secondaryTextAndIconColor
descriptionLabel.textAlignment = .center
descriptionLabel.text = NSLocalizedString(
"DELETE_ACCOUNT_CONFIRMATION_DESCRIPTION",
comment: "Description for the 'delete account' confirmation view."
)
let headerView = UIStackView(arrangedSubviews: [
imageContainer,
titleLabel,
descriptionLabel
])
headerView.axis = .vertical
headerView.spacing = 12
let cell = OWSTableItem.newCell()
cell.contentView.addSubview(headerView)
headerView.autoPinEdgesToSuperviewMargins()
return cell
}
func buildPhoneNumberCell() -> UITableViewCell {
let cell = OWSTableItem.newCell()
cell.preservesSuperviewLayoutMargins = true
cell.contentView.preservesSuperviewLayoutMargins = true
let nameLabel = UILabel()
nameLabel.text = NSLocalizedString(
"DELETE_ACCOUNT_CONFIRMATION_PHONE_NUMBER_TITLE",
comment: "Title for the 'phone number' row of the 'delete account confirmation' view controller."
)
nameLabel.textColor = Theme.primaryTextColor
nameLabel.font = OWSTableItem.primaryLabelFont
nameLabel.adjustsFontForContentSizeCategory = true
nameLabel.lineBreakMode = .byTruncatingTail
nameLabel.setCompressionResistanceHorizontalHigh()
nameLabel.setContentHuggingHorizontalHigh()
nameLabel.autoSetDimension(.height, toSize: 24, relation: .greaterThanOrEqual)
phoneNumberTextField.textColor = Theme.primaryTextColor
phoneNumberTextField.font = OWSTableItem.accessoryLabelFont
phoneNumberTextField.setCompressionResistanceHorizontalHigh()
phoneNumberTextField.setContentHuggingHorizontalHigh()
let contentRow = UIStackView(arrangedSubviews: [
nameLabel, .hStretchingSpacer(), phoneNumberTextField
])
contentRow.spacing = OWSTableItem.iconSpacing
contentRow.alignment = .center
cell.contentView.addSubview(contentRow)
contentRow.autoPinEdgesToSuperviewMargins()
return cell
}
@objc
func didTapDelete() {
guard hasEnteredLocalNumber else {
OWSActionSheets.showActionSheet(
title: NSLocalizedString(
"DELETE_ACCOUNT_CONFIRMATION_WRONG_NUMBER",
comment: "Title for the action sheet when you enter the wrong number on the 'delete account confirmation' view controller."
)
)
return
}
guard reachabilityManager.isReachable else {
OWSActionSheets.showActionSheet(
title: NSLocalizedString(
"DELETE_ACCOUNT_CONFIRMATION_NO_INTERNET",
comment: "Title for the action sheet when you have no internet on the 'delete account confirmation' view controller."
)
)
return
}
phoneNumberTextField.resignFirstResponder()
OWSActionSheets.showConfirmationAlert(
title: NSLocalizedString(
"DELETE_ACCOUNT_CONFIRMATION_ACTION_SHEEET_TITLE",
comment: "Title for the action sheet confirmation title of the 'delete account confirmation' view controller."
),
message: NSLocalizedString(
"DELETE_ACCOUNT_CONFIRMATION_ACTION_SHEEET_MESSAGE",
comment: "Title for the action sheet message of the 'delete account confirmation' view controller."
),
proceedTitle: NSLocalizedString(
"DELETE_ACCOUNT_CONFIRMATION_ACTION_SHEEET_ACTION",
comment: "Title for the action sheet 'delete' action of the 'delete account confirmation' view controller."
),
proceedStyle: .destructive
) { _ in
let overlayView = UIView()
overlayView.backgroundColor = self.tableBackgroundColor.withAlphaComponent(0.9)
overlayView.alpha = 0
self.navigationController?.view.addSubview(overlayView)
overlayView.autoPinEdgesToSuperviewEdges()
let progressView = AnimatedProgressView(
loadingText: NSLocalizedString(
"DELETE_ACCOUNT_CONFIRMATION_IN_PROGRESS",
comment: "Indicates the work we are doing while deleting the account"
)
)
self.navigationController?.view.addSubview(progressView)
progressView.autoCenterInSuperview()
progressView.startAnimating { overlayView.alpha = 1 }
TSAccountManager.unregisterTextSecure {
// We don't need to stop animating here because "resetAppData" exits the app.
SignalApp.resetAppData()
} failure: { error in
owsFailDebug("Failed to unregister \(error)")
progressView.stopAnimating(success: false) {
overlayView.alpha = 0
} completion: {
overlayView.removeFromSuperview()
progressView.removeFromSuperview()
OWSActionSheets.showActionSheet(
title: NSLocalizedString(
"DELETE_ACCOUNT_CONFIRMATION_DELETE_FAILED",
comment: "Title for the action sheet when delete failed on the 'delete account confirmation' view controller."
)
)
}
}
}
}
var hasEnteredLocalNumber: Bool {
guard let localNumber = TSAccountManager.localNumber else {
owsFailDebug("local number unexpectedly nil")
return false
}
guard let phoneNumberText = phoneNumberTextField.text else { return false }
let possiblePhoneNumber = callingCode + phoneNumberText
let possibleNumbers = PhoneNumber.tryParsePhoneNumbers(
fromUserSpecifiedText: possiblePhoneNumber,
clientPhoneNumber: localNumber
).map { $0.toE164() }
return possibleNumbers.contains(localNumber)
}
@objc
func didTapCancel() {
dismiss(animated: true)
}
}
extension DeleteAccountConfirmationViewController: CountryCodeViewControllerDelegate {
func countryCodeViewController(_ vc: CountryCodeViewController, didSelectCountryCode countryCode: String, countryName: String, callingCode: String) {
updateCountry(callingCode: callingCode, countryCode: countryCode)
}
func populateDefaultCountryCode() {
guard let localNumber = TSAccountManager.localNumber else {
return owsFailDebug("Local number unexpectedly nil")
}
var callingCodeInt: Int?
var countryCode: String?
if let localE164 = PhoneNumber(fromE164: localNumber), let localCountryCode = localE164.getCountryCode()?.intValue {
callingCodeInt = localCountryCode
} else {
callingCodeInt = PhoneNumberUtil.sharedThreadLocal().nbPhoneNumberUtil.getCountryCode(
forRegion: PhoneNumber.defaultCountryCode()
)?.intValue
}
var callingCode: String?
if let callingCodeInt = callingCodeInt {
callingCode = COUNTRY_CODE_PREFIX + "\(callingCodeInt)"
countryCode = PhoneNumberUtil.sharedThreadLocal().probableCountryCode(forCallingCode: callingCode!)
}
updateCountry(callingCode: callingCode, countryCode: countryCode)
}
func updateCountry(callingCode: String?, countryCode: String?) {
guard let callingCode = callingCode, !callingCode.isEmpty, let countryCode = countryCode, !countryCode.isEmpty else {
return owsFailDebug("missing calling code for selected country")
}
self.callingCode = callingCode
self.countryCode = countryCode
updateTableContents()
}
}
extension DeleteAccountConfirmationViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
didTapDelete()
return false
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
ViewControllerUtils.phoneNumber(textField, changeCharactersIn: range, replacementString: string, callingCode: callingCode)
return false
}
}

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
//
#import "OWSQRCodeScanningViewController.h"

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
//
#import "OWSLinkDeviceViewController.h"

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
//
#import <AVFoundation/AVFoundation.h>

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
//
#import "OWSQRCodeScanningViewController.h"

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
//
#import <SignalMessaging/OWSViewController.h>

View File

@ -106,22 +106,21 @@ NS_ASSUME_NONNULL_BEGIN
@"BLOCK_LIST_BLOCKED_USERS_SECTION", @"Section header for users that have been blocked");
for (SignalServiceAddress *address in blockedAddresses) {
[blockedContactsSection
addItem:[OWSTableItem
itemWithCustomCellBlock:^{
ContactTableViewCell *cell = [ContactTableViewCell new];
[cell configureWithRecipientAddressWithSneakyTransaction:address];
cell.accessibilityIdentifier
= ACCESSIBILITY_IDENTIFIER_WITH_NAME(BlockListViewController, @"user");
return cell;
}
actionBlock:^{
[BlockListUIUtils showUnblockAddressActionSheet:address
fromViewController:weakSelf
completionBlock:^(BOOL isBlocked) {
[weakSelf updateTableContents];
}];
}]];
[blockedContactsSection addItem:[OWSTableItem
itemWithCustomCellBlock:^{
ContactTableViewCell *cell = [ContactTableViewCell new];
[cell configureWithRecipientAddressWithSneakyTransaction:address];
cell.accessibilityIdentifier = ACCESSIBILITY_IDENTIFIER_WITH_NAME(
BlockListViewController, @"user");
return cell;
}
actionBlock:^{
[BlockListUIUtils showUnblockAddressActionSheet:address
fromViewController:weakSelf
completionBlock:^(BOOL isBlocked) {
[weakSelf updateTableContents];
}];
}]];
}
[contents addSection:blockedContactsSection];
}
@ -141,21 +140,19 @@ NS_ASSUME_NONNULL_BEGIN
conversationColorName:conversationColorName
diameter:kStandardAvatarSize];
}
[blockedGroupsSection addItem:[OWSTableItem
itemWithCustomCellBlock:^{
OWSAvatarTableViewCell *cell = [OWSAvatarTableViewCell new];
[cell configureWithImage:image
text:blockedGroup.groupNameOrDefault
detailText:nil];
return cell;
}
actionBlock:^{
[BlockListUIUtils showUnblockGroupActionSheet:blockedGroup
fromViewController:weakSelf
completionBlock:^(BOOL isBlocked) {
[weakSelf updateTableContents];
}];
}]];
[blockedGroupsSection
addItem:[OWSTableItem
itemWithCustomCellBlock:^{
OWSAvatarTableViewCell *cell = [OWSAvatarTableViewCell new];
[cell configureWithImage:image text:blockedGroup.groupNameOrDefault detailText:nil];
return cell;
}
actionBlock:^{
[BlockListUIUtils
showUnblockGroupActionSheet:blockedGroup
fromViewController:weakSelf
completionBlock:^(BOOL isBlocked) { [weakSelf updateTableContents]; }];
}]];
}
[contents addSection:blockedGroupsSection];
}

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
//
#import <SignalMessaging/OWSViewController.h>

View File

@ -76,9 +76,7 @@ NS_ASSUME_NONNULL_BEGIN
return cell;
}
actionBlock:^{
[weakSelf selectCountry:countryMetadata];
}]];
actionBlock:^{ [weakSelf selectCountry:countryMetadata]; }]];
}
[contents addSection:section];

View File

@ -87,7 +87,7 @@ class ProfileSettingsViewController: OWSTableViewController2 {
actionBlock: { [weak self] in
guard let self = self else { return }
let vc = ProfileNameViewController(givenName: self.givenName, familyName: self.familyName, profileDelegate: self)
self.present(OWSNavigationController(rootViewController: vc), animated: true)
self.presentFormSheet(OWSNavigationController(rootViewController: vc), animated: true)
}
))
if RemoteConfig.usernames {
@ -100,7 +100,7 @@ class ProfileSettingsViewController: OWSTableViewController2 {
accessibilityIdentifier: UIView.accessibilityIdentifier(in: self, name: "username"),
actionBlock: { [weak self] in
let vc = UsernameViewController(username: self?.username)
self?.present(OWSNavigationController(rootViewController: vc), animated: true)
self?.presentFormSheet(OWSNavigationController(rootViewController: vc), animated: true)
}
))
}
@ -114,7 +114,7 @@ class ProfileSettingsViewController: OWSTableViewController2 {
actionBlock: { [weak self] in
guard let self = self else { return }
let vc = ProfileBioViewController(bio: self.bio, bioEmoji: self.bioEmoji, profileDelegate: self)
self.present(OWSNavigationController(rootViewController: vc), animated: true)
self.presentFormSheet(OWSNavigationController(rootViewController: vc), animated: true)
}
))
contents.addSection(mainSection)

View File

@ -623,10 +623,10 @@
"COMPOSE_SCREEN_MISSING_CONTACTS_PERMISSION" = "You can enable contacts access in the iOS Settings app to see which of your contacts are Signal users.";
/* No comment provided by engineer. */
"CONFIRM_ACCOUNT_DESTRUCTION_TEXT" = "This will reset the application by deleting your messages and unregistering you with the server. The app will close after this process is complete.";
"CONFIRM_DELETE_DATA_TEXT" = "This will reset the application by deleting your messages. The app will close after this process is complete.";
/* No comment provided by engineer. */
"CONFIRM_ACCOUNT_DESTRUCTION_TITLE" = "Are you sure you want to delete your account?";
"CONFIRM_DELETE_DATA_TITLE" = "Are you sure you want to delete all data?";
/* No comment provided by engineer. */
"CONFIRM_DELETE_LINKED_DATA_TEXT" = "This will reset the application by deleting all of your messages from this device. You can always link with your phone again, but that will not restore deleted messages. The app will close after this process is complete.";
@ -1075,6 +1075,42 @@
/* Accessibility label for the ? vector asset used to get info about debug logs */
"DEBUG_LOG_INFO_BUTTON" = "Info about debug logs";
/* Title for the action sheet 'delete' action of the 'delete account confirmation' view controller. */
"DELETE_ACCOUNT_CONFIRMATION_ACTION_SHEEET_ACTION" = "Delete Account";
/* Title for the action sheet message of the 'delete account confirmation' view controller. */
"DELETE_ACCOUNT_CONFIRMATION_ACTION_SHEEET_MESSAGE" = "This will delete your Signal account and reset the application. The app will close after this process is complete.";
/* Title for the action sheet confirmation title of the 'delete account confirmation' view controller. */
"DELETE_ACCOUNT_CONFIRMATION_ACTION_SHEEET_TITLE" = "Are you sure you want to delete your account?";
/* Title for the 'country code' row of the 'delete account confirmation' view controller. */
"DELETE_ACCOUNT_CONFIRMATION_COUNTRY_CODE_TITLE" = "Country Code";
/* Title for the action sheet when delete failed on the 'delete account confirmation' view controller. */
"DELETE_ACCOUNT_CONFIRMATION_DELETE_FAILED" = "Failed to delete account. Make sure that Wi-Fi or mobile data is turned on, then try again.";
/* Description for the 'delete account' confirmation view. */
"DELETE_ACCOUNT_CONFIRMATION_DESCRIPTION" = "This will delete your account info, profile, and all of your messages. You will also be deleted from all Signal groups.";
/* Indicates the work we are doing while deleting the account */
"DELETE_ACCOUNT_CONFIRMATION_IN_PROGRESS" = "Deleting Account...";
/* Title for the action sheet when you have no internet on the 'delete account confirmation' view controller. */
"DELETE_ACCOUNT_CONFIRMATION_NO_INTERNET" = "No internet connection. Make sure that Wi-Fi or mobile data is turned on, then try again.";
/* Title for the 'phone number' row of the 'delete account confirmation' view controller. */
"DELETE_ACCOUNT_CONFIRMATION_PHONE_NUMBER_TITLE" = "Phone Number";
/* Section header */
"DELETE_ACCOUNT_CONFIRMATION_SECTION_TITLE" = "Enter Your Phone Number";
/* Title for the 'delete account' confirmation view. */
"DELETE_ACCOUNT_CONFIRMATION_TITLE" = "Delete Account";
/* Title for the action sheet when you enter the wrong number on the 'delete account confirmation' view controller. */
"DELETE_ACCOUNT_CONFIRMATION_WRONG_NUMBER" = "The phone number you entered doesnt match your accounts.";
/* action sheet body */
"DELETE_ALL_MESSAGES_IN_CONVERSATION_ALERT_BODY" = "Delete all messages in the chat?";
@ -5083,9 +5119,6 @@
/* Pressing this button marks a thread as unread */
"UNREAD_ACTION" = "Unread";
/* No comment provided by engineer. */
"UNREGISTER_SIGNAL_FAIL" = "Failed to unregister from Signal.";
/* No comment provided by engineer. */
"UNSUPPORTED_ATTACHMENT" = "Received unsupported attachment type.";

View File

@ -270,7 +270,7 @@ extension FindByPhoneNumberViewController: CountryCodeViewControllerDelegate {
self.callingCode = callingCode
let labelFormat = CurrentAppContext().isRTL ? "(%2$@) %1$@" : "%1$@ (%2$@)"
countryCodeLabel.text = String(format: labelFormat, callingCode, countryCode.localizedUppercase)
exampleLabel.text = ViewControllerUtils.examplePhoneNumber(forCountryCode: countryCode, callingCode: callingCode)
exampleLabel.text = ViewControllerUtils.examplePhoneNumber(forCountryCode: countryCode, callingCode: callingCode, includeExampleLabel: true)
}
}

View File

@ -41,7 +41,9 @@ extern NSString *const TappedStatusBarNotification;
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)insertionText;
+ (NSString *)examplePhoneNumberForCountryCode:(NSString *)countryCode callingCode:(NSString *)callingCode;
+ (nullable NSString *)examplePhoneNumberForCountryCode:(NSString *)countryCode
callingCode:(NSString *)callingCode
includeExampleLabel:(BOOL)includeExampleLabel;
@end

View File

@ -176,7 +176,9 @@ NSString *const TappedStatusBarNotification = @"TappedStatusBarNotification";
[textField setSelectedTextRange:[textField textRangeFromPosition:pos toPosition:pos]];
}
+ (NSString *)examplePhoneNumberForCountryCode:(NSString *)countryCode callingCode:(NSString *)callingCode
+ (nullable NSString *)examplePhoneNumberForCountryCode:(NSString *)countryCode
callingCode:(NSString *)callingCode
includeExampleLabel:(BOOL)includeExampleLabel
{
OWSAssertDebug(countryCode.length > 0);
OWSAssertDebug(callingCode.length > 0);
@ -191,13 +193,17 @@ NSString *const TappedStatusBarNotification = @"TappedStatusBarNotification";
examplePhoneNumber = formattedPhoneNumber;
}
return [NSString
stringWithFormat:
NSLocalizedString(@"PHONE_NUMBER_EXAMPLE_FORMAT",
@"A format for a label showing an example phone number. Embeds {{the example phone number}}."),
[examplePhoneNumber substringFromIndex:callingCode.length]];
if (includeExampleLabel) {
return [NSString
stringWithFormat:
NSLocalizedString(@"PHONE_NUMBER_EXAMPLE_FORMAT",
@"A format for a label showing an example phone number. Embeds {{the example phone number}}."),
[examplePhoneNumber substringFromIndex:callingCode.length]];
} else {
return [examplePhoneNumber substringFromIndex:callingCode.length];
}
} else {
return @"";
return nil;
}
}

View File

@ -294,7 +294,7 @@ NSString *const OWSRequestKey_AuthKey = @"AuthKey";
+ (TSRequest *)unregisterAccountRequest
{
NSString *path = [NSString stringWithFormat:@"%@/%@", textSecureAccountsAPI, @"apn"];
NSString *path = [NSString stringWithFormat:@"%@/%@", textSecureAccountsAPI, @"me"];
return [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"DELETE" parameters:@{}];
}