Merge branch 'charlesmchen/cvcLongPressBodyLinks'
This commit is contained in:
commit
3f91e966e3
@ -502,7 +502,7 @@ import SignalMessaging
|
||||
|
||||
var isUnknownCaller = false
|
||||
if call.individualCall.direction == .incoming {
|
||||
isUnknownCaller = !self.contactsManagerImpl.hasSignalAccount(for: call.individualCall.thread.contactAddress)
|
||||
isUnknownCaller = !self.contactsManagerImpl.isSystemContactWithSignalAccount(call.individualCall.thread.contactAddress)
|
||||
if isUnknownCaller {
|
||||
Logger.warn("Using relay server because remote user is an unknown caller")
|
||||
}
|
||||
@ -763,7 +763,7 @@ import SignalMessaging
|
||||
return
|
||||
}
|
||||
call.individualCall.isRemoteSharingScreen = false
|
||||
|
||||
|
||||
case .reconnecting:
|
||||
self.handleReconnecting(call: call)
|
||||
|
||||
|
||||
@ -68,8 +68,7 @@ extension ConversationViewController {
|
||||
case .dataItem(let dataItem):
|
||||
switch dataItem.dataType {
|
||||
case .link:
|
||||
// TODO: Show action sheet with options for links.
|
||||
didTapLink(dataItem: dataItem)
|
||||
didLongPressLink(dataItem: dataItem)
|
||||
case .address:
|
||||
// Open in iOS Maps app using URL.
|
||||
//
|
||||
@ -78,14 +77,7 @@ extension ConversationViewController {
|
||||
// TODO: Show action sheet with options for addresses.
|
||||
UIApplication.shared.open(dataItem.url, options: [:], completionHandler: nil)
|
||||
case .phoneNumber:
|
||||
// Initiate PSTN call using URL.
|
||||
//
|
||||
// https://developer.apple.com/library/archive/featuredarticles/iPhoneURLScheme_Reference/PhoneLinks/PhoneLinks.html
|
||||
// https://developer.apple.com/library/archive/featuredarticles/iPhoneURLScheme_Reference/SMSLinks/SMSLinks.html
|
||||
// https://developer.apple.com/library/archive/featuredarticles/iPhoneURLScheme_Reference/FacetimeLinks/FacetimeLinks.html
|
||||
//
|
||||
// TODO: Show action sheet with options for phone numbers.
|
||||
UIApplication.shared.open(dataItem.url, options: [:], completionHandler: nil)
|
||||
didLongPressPhoneNumber(dataItem: dataItem)
|
||||
case .date:
|
||||
// Open in iOS Calendar app using default URL.
|
||||
//
|
||||
@ -106,6 +98,141 @@ extension ConversationViewController {
|
||||
}
|
||||
}
|
||||
|
||||
// * URL
|
||||
// * tap - open URL in safari
|
||||
// * long press - preview + open link in safari / add to reading list / copy link / share
|
||||
private func didLongPressLink(dataItem: CVBodyTextLabel.DataItem) {
|
||||
let actionSheet = ActionSheetController(title: dataItem.snippet.strippedOrNil)
|
||||
|
||||
actionSheet.addAction(ActionSheetAction(title: NSLocalizedString("MESSAGE_ACTION_LINK_OPEN_LINK",
|
||||
comment: "Label for button to open a link."),
|
||||
accessibilityIdentifier: "link_open_link",
|
||||
style: .default) { [weak self] _ in
|
||||
self?.openLink(dataItem: dataItem)
|
||||
})
|
||||
actionSheet.addAction(ActionSheetAction(title: CommonStrings.copyButton,
|
||||
accessibilityIdentifier: "link_copy",
|
||||
style: .default) { _ in
|
||||
UIPasteboard.general.string = dataItem.snippet
|
||||
// TODO: Show toast?
|
||||
})
|
||||
actionSheet.addAction(ActionSheetAction(title: CommonStrings.shareButton,
|
||||
accessibilityIdentifier: "link_share",
|
||||
style: .default) { _ in
|
||||
AttachmentSharing.showShareUI(for: dataItem.url, sender: self)
|
||||
})
|
||||
actionSheet.addAction(OWSActionSheets.cancelAction)
|
||||
|
||||
presentActionSheet(actionSheet)
|
||||
}
|
||||
|
||||
// * phone number
|
||||
// * tap - action sheet with call.
|
||||
// * long press - show phone number + call PSTN / facetime audio / facetime video / send messages / add to contacts / copy
|
||||
private func didLongPressPhoneNumber(dataItem: CVBodyTextLabel.DataItem) {
|
||||
guard let snippet = dataItem.snippet.strippedOrNil,
|
||||
let phoneNumber = PhoneNumber.tryParsePhoneNumber(fromUserSpecifiedText: snippet),
|
||||
let e164 = phoneNumber.toE164().strippedOrNil else {
|
||||
owsFailDebug("Invalid phone number.")
|
||||
UIApplication.shared.open(dataItem.url, options: [:], completionHandler: nil)
|
||||
return
|
||||
}
|
||||
let address = SignalServiceAddress(phoneNumber: e164)
|
||||
|
||||
if address.isLocalAddress ||
|
||||
Self.contactsManagerImpl.isKnownRegisteredUserWithSneakyTransaction(address: address) {
|
||||
let groupViewHelper: GroupViewHelper? = {
|
||||
guard threadViewModel.isGroupThread else {
|
||||
return nil
|
||||
}
|
||||
let groupViewHelper = GroupViewHelper(threadViewModel: threadViewModel)
|
||||
groupViewHelper.delegate = self
|
||||
return groupViewHelper
|
||||
}()
|
||||
let actionSheet = MemberActionSheet(address: address, groupViewHelper: groupViewHelper)
|
||||
actionSheet.present(from: self)
|
||||
return
|
||||
}
|
||||
|
||||
let actionSheet = ActionSheetController(title: e164)
|
||||
|
||||
if address.isLocalAddress {
|
||||
// Show no options.
|
||||
} else if blockingManager.isAddressBlocked(address) {
|
||||
actionSheet.addAction(ActionSheetAction(title: NSLocalizedString(
|
||||
"BLOCK_LIST_UNBLOCK_BUTTON",
|
||||
comment: "Button label for the 'unblock' button"
|
||||
),
|
||||
accessibilityIdentifier: "phone_number_unblock",
|
||||
style: .default) { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
BlockListUIUtils.showUnblockAddressActionSheet(
|
||||
address,
|
||||
from: self,
|
||||
completionBlock: nil
|
||||
)
|
||||
})
|
||||
} else {
|
||||
// https://developer.apple.com/library/archive/featuredarticles/iPhoneURLScheme_Reference/PhoneLinks/PhoneLinks.html
|
||||
actionSheet.addAction(ActionSheetAction(title: NSLocalizedString("MESSAGE_ACTION_PHONE_NUMBER_CALL",
|
||||
comment: "Label for button to call a phone number."),
|
||||
accessibilityIdentifier: "phone_number_call",
|
||||
style: .default) { _ in
|
||||
guard let url = URL(string: "tel:" + e164) else {
|
||||
owsFailDebug("Invalid phone number.")
|
||||
return
|
||||
}
|
||||
UIApplication.shared.open(url, options: [:], completionHandler: nil)
|
||||
})
|
||||
// https://developer.apple.com/library/archive/featuredarticles/iPhoneURLScheme_Reference/SMSLinks/SMSLinks.html
|
||||
actionSheet.addAction(ActionSheetAction(title: NSLocalizedString("MESSAGE_ACTION_PHONE_NUMBER_SMS",
|
||||
comment: "Label for button to send a text message a phone number."),
|
||||
accessibilityIdentifier: "phone_number_text_message",
|
||||
style: .default) { _ in
|
||||
guard let url = URL(string: "sms:" + e164) else {
|
||||
owsFailDebug("Invalid phone number.")
|
||||
return
|
||||
}
|
||||
UIApplication.shared.open(url, options: [:], completionHandler: nil)
|
||||
})
|
||||
// https://developer.apple.com/library/archive/featuredarticles/iPhoneURLScheme_Reference/FacetimeLinks/FacetimeLinks.html
|
||||
actionSheet.addAction(ActionSheetAction(title: NSLocalizedString("MESSAGE_ACTION_PHONE_NUMBER_FACETIME_VIDEO",
|
||||
comment: "Label for button to make a Facetime video call to a phone number."),
|
||||
accessibilityIdentifier: "phone_number_facetime_video",
|
||||
style: .default) { _ in
|
||||
guard let url = URL(string: "facetime:" + e164) else {
|
||||
owsFailDebug("Invalid phone number.")
|
||||
return
|
||||
}
|
||||
UIApplication.shared.open(url, options: [:], completionHandler: nil)
|
||||
})
|
||||
actionSheet.addAction(ActionSheetAction(title: NSLocalizedString("MESSAGE_ACTION_PHONE_NUMBER_FACETIME_AUDIO",
|
||||
comment: "Label for button to make a Facetime audio call to a phone number."),
|
||||
accessibilityIdentifier: "phone_number_facetime_audio",
|
||||
style: .default) { _ in
|
||||
guard let url = URL(string: "facetime-audio:" + e164) else {
|
||||
owsFailDebug("Invalid phone number.")
|
||||
return
|
||||
}
|
||||
UIApplication.shared.open(url, options: [:], completionHandler: nil)
|
||||
})
|
||||
// TODO: We could show an "add to contact" action for this phone number.
|
||||
// Ideally we could detect whether this phone number is already in a system contact.
|
||||
// TODO: We could show an "share" action for this phone number.
|
||||
}
|
||||
|
||||
actionSheet.addAction(ActionSheetAction(title: CommonStrings.copyButton,
|
||||
accessibilityIdentifier: "phone_number_copy",
|
||||
style: .default) { _ in
|
||||
UIPasteboard.general.string = dataItem.snippet
|
||||
// TODO: Show toast?
|
||||
})
|
||||
|
||||
actionSheet.addAction(OWSActionSheets.cancelAction)
|
||||
|
||||
presentActionSheet(actionSheet)
|
||||
}
|
||||
|
||||
private func didLongPressEmail(dataItem: CVBodyTextLabel.DataItem) {
|
||||
let actionSheet = ActionSheetController(title: dataItem.snippet.strippedOrNil)
|
||||
|
||||
@ -129,6 +256,7 @@ extension ConversationViewController {
|
||||
// TODO: We could show (Send Signal Message/Signal call) actions for this email address.
|
||||
// Ideally we could detect whether this email address corresponds to a system contact
|
||||
// which is a registered Signal user.
|
||||
// TODO: We could show an "share" action for this email address.
|
||||
|
||||
actionSheet.addAction(OWSActionSheets.cancelAction)
|
||||
|
||||
@ -138,6 +266,12 @@ extension ConversationViewController {
|
||||
private func didTapLink(dataItem: CVBodyTextLabel.DataItem) {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
openLink(dataItem: dataItem)
|
||||
}
|
||||
|
||||
private func openLink(dataItem: CVBodyTextLabel.DataItem) {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
if isMailtoUrl(dataItem.url) {
|
||||
didTapEmail(dataItem: dataItem)
|
||||
} else {
|
||||
|
||||
@ -1116,7 +1116,7 @@ typedef enum : NSUInteger {
|
||||
}
|
||||
|
||||
// If the user is in the system contacts, show a badge
|
||||
if ([self.contactsManagerImpl hasSignalAccountForAddress:thread.contactAddress]) {
|
||||
if ([self.contactsManagerImpl isSystemContactWithAddress:thread.contactAddress]) {
|
||||
icon =
|
||||
[[UIImage imageNamed:@"contact-outline-16"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
|
||||
}
|
||||
|
||||
@ -21,12 +21,12 @@ extension ConversationSettingsViewController {
|
||||
return !thread.isGroupThread
|
||||
}
|
||||
|
||||
private var hasExistingContact: Bool {
|
||||
private var hasExistingSystemContact: Bool {
|
||||
guard let contactThread = thread as? TSContactThread else {
|
||||
owsFailDebug("Invalid thread.")
|
||||
return false
|
||||
}
|
||||
return contactsManagerImpl.hasSignalAccount(for: contactThread.contactAddress)
|
||||
return contactsManagerImpl.isSystemContact(address: contactThread.contactAddress)
|
||||
}
|
||||
|
||||
// MARK: - Table
|
||||
@ -175,7 +175,7 @@ extension ConversationSettingsViewController {
|
||||
let contactThread = thread as? TSContactThread,
|
||||
contactsManagerImpl.supportsContactEditing else { return }
|
||||
|
||||
if hasExistingContact {
|
||||
if hasExistingSystemContact {
|
||||
section.add(OWSTableItem(customCellBlock: { [weak self] in
|
||||
guard let self = self else {
|
||||
owsFailDebug("Missing self")
|
||||
|
||||
@ -439,6 +439,9 @@
|
||||
/* Label for the 'set' button. */
|
||||
"BUTTON_SET" = "Set";
|
||||
|
||||
/* Label for the 'share' button. */
|
||||
"BUTTON_SHARE" = "Share";
|
||||
|
||||
/* Label for the 'start' button. */
|
||||
"BUTTON_START" = "Start";
|
||||
|
||||
@ -2974,6 +2977,21 @@
|
||||
/* Action sheet button title */
|
||||
"MESSAGE_ACTION_FORWARD_MESSAGE" = "Forward This Message";
|
||||
|
||||
/* Label for button to open a link. */
|
||||
"MESSAGE_ACTION_LINK_OPEN_LINK" = "Open Link";
|
||||
|
||||
/* Label for button to call a phone number. */
|
||||
"MESSAGE_ACTION_PHONE_NUMBER_CALL" = "Call";
|
||||
|
||||
/* Label for button to make a Facetime audio call to a phone number. */
|
||||
"MESSAGE_ACTION_PHONE_NUMBER_FACETIME_AUDIO" = "Facetime Audio";
|
||||
|
||||
/* Label for button to make a Facetime video call to a phone number. */
|
||||
"MESSAGE_ACTION_PHONE_NUMBER_FACETIME_VIDEO" = "Facetime Video";
|
||||
|
||||
/* Label for button to send a text message a phone number. */
|
||||
"MESSAGE_ACTION_PHONE_NUMBER_SMS" = "Send Text Message";
|
||||
|
||||
/* Action sheet button title */
|
||||
"MESSAGE_ACTION_REPLY" = "Reply to This Message";
|
||||
|
||||
|
||||
@ -68,6 +68,9 @@ import Foundation
|
||||
static public let saveButton = NSLocalizedString("ALERT_SAVE",
|
||||
comment: "The label for the 'save' button in action sheets.")
|
||||
|
||||
@objc
|
||||
static public let shareButton = NSLocalizedString("BUTTON_SHARE", comment: "Label for the 'share' button.")
|
||||
|
||||
@objc
|
||||
static public let help = NSLocalizedString("SETTINGS_HELP", comment: "Title for help button and help pages in app settings.")
|
||||
|
||||
|
||||
@ -48,8 +48,6 @@ extern NSString *const OWSContactsManagerSignalAccountsDidChangeNotification;
|
||||
|
||||
// This will always return an instance of SignalAccount.
|
||||
- (SignalAccount *)fetchOrBuildSignalAccountForAddress:(SignalServiceAddress *)address;
|
||||
- (BOOL)hasSignalAccountForAddress:(SignalServiceAddress *)address;
|
||||
- (BOOL)hasSignalAccountForAddress:(SignalServiceAddress *)address transaction:(SDSAnyReadTransaction *)transaction;
|
||||
|
||||
#pragma mark - System Contact Fetching
|
||||
|
||||
@ -100,6 +98,10 @@ extern NSString *const OWSContactsManagerSignalAccountsDidChangeNotification;
|
||||
transaction:(SDSAnyReadTransaction *)transaction;
|
||||
- (nullable UIImage *)imageForAddressWithSneakyTransaction:(nullable SignalServiceAddress *)address;
|
||||
|
||||
- (BOOL)isKnownRegisteredUserWithSneakyTransaction:(SignalServiceAddress *)address
|
||||
NS_SWIFT_NAME(isKnownRegisteredUserWithSneakyTransaction(address:));
|
||||
- (BOOL)isKnownRegisteredUser:(SignalServiceAddress *)address transaction:(SDSAnyReadTransaction *)transaction;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@ -922,19 +922,19 @@ NSString *const OWSContactsManagerKeyNextFullIntersectionDate = @"OWSContactsMan
|
||||
return [self isSystemContactWithPhoneNumber:phoneNumber];
|
||||
}
|
||||
|
||||
- (BOOL)isSystemContactWithSignalAccount:(NSString *)phoneNumber
|
||||
- (BOOL)isSystemContactWithSignalAccount:(SignalServiceAddress *)address
|
||||
{
|
||||
OWSAssertDebug(phoneNumber.length > 0);
|
||||
OWSAssertDebug(address.isValid);
|
||||
|
||||
return [self hasSignalAccountForAddress:[[SignalServiceAddress alloc] initWithPhoneNumber:phoneNumber]];
|
||||
return [self hasSignalAccountForAddress:address];
|
||||
}
|
||||
|
||||
- (BOOL)isSystemContactWithSignalAccount:(NSString *)phoneNumber transaction:(SDSAnyReadTransaction *)transaction
|
||||
- (BOOL)isSystemContactWithSignalAccount:(SignalServiceAddress *)address
|
||||
transaction:(SDSAnyReadTransaction *)transaction
|
||||
{
|
||||
OWSAssertDebug(phoneNumber.length > 0);
|
||||
OWSAssertDebug(address.isValid);
|
||||
|
||||
return [self hasSignalAccountForAddress:[[SignalServiceAddress alloc] initWithPhoneNumber:phoneNumber]
|
||||
transaction:transaction];
|
||||
return [self hasSignalAccountForAddress:address transaction:transaction];
|
||||
}
|
||||
|
||||
- (BOOL)hasNameInSystemContactsForAddress:(SignalServiceAddress *)address
|
||||
@ -1358,6 +1358,19 @@ NSString *const OWSContactsManagerKeyNextFullIntersectionDate = @"OWSContactsMan
|
||||
return [self displayNameForAddress:signalAccount.recipientAddress transaction:transaction];
|
||||
}
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
- (BOOL)isKnownRegisteredUserWithSneakyTransaction:(SignalServiceAddress *)address
|
||||
{
|
||||
__block BOOL result;
|
||||
[self.databaseStorage readWithBlock:^(
|
||||
SDSAnyReadTransaction *transaction) { result = [self isKnownRegisteredUser:address transaction:transaction]; }];
|
||||
return result;
|
||||
}
|
||||
|
||||
- (BOOL)isKnownRegisteredUser:(SignalServiceAddress *)address transaction:(SDSAnyReadTransaction *)transaction
|
||||
{
|
||||
return [SignalRecipient isRegisteredRecipient:address transaction:transaction];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@ -544,18 +544,20 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value)
|
||||
- (NSArray<NSString *> *)systemContactsWithSignalAccountPhoneNumbers
|
||||
{
|
||||
return [self.e164PhoneNumbers
|
||||
filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSString *_Nullable recipientId,
|
||||
filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSString *_Nullable phoneNumber,
|
||||
NSDictionary<NSString *, id> *_Nullable bindings) {
|
||||
return [OWSContact.contactsManager isSystemContactWithSignalAccount:recipientId];
|
||||
SignalServiceAddress *address = [[SignalServiceAddress alloc] initWithPhoneNumber:phoneNumber];
|
||||
return [OWSContact.contactsManager isSystemContactWithSignalAccount:address];
|
||||
}]];
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)systemContactsWithSignalAccountPhoneNumbersWithTransaction:(SDSAnyReadTransaction *)transaction
|
||||
{
|
||||
return [self.e164PhoneNumbers
|
||||
filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSString *_Nullable recipientId,
|
||||
filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSString *_Nullable phoneNumber,
|
||||
NSDictionary<NSString *, id> *_Nullable bindings) {
|
||||
return [OWSContact.contactsManager isSystemContactWithSignalAccount:recipientId transaction:transaction];
|
||||
SignalServiceAddress *address = [[SignalServiceAddress alloc] initWithPhoneNumber:phoneNumber];
|
||||
return [OWSContact.contactsManager isSystemContactWithSignalAccount:address transaction:transaction];
|
||||
}]];
|
||||
}
|
||||
|
||||
|
||||
@ -53,8 +53,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (BOOL)isSystemContactWithPhoneNumber:(NSString *)phoneNumber NS_SWIFT_NAME(isSystemContact(phoneNumber:));
|
||||
- (BOOL)isSystemContactWithAddress:(SignalServiceAddress *)address NS_SWIFT_NAME(isSystemContact(address:));
|
||||
- (BOOL)isSystemContactWithSignalAccount:(NSString *)phoneNumber;
|
||||
- (BOOL)isSystemContactWithSignalAccount:(NSString *)phoneNumber transaction:(SDSAnyReadTransaction *)transaction;
|
||||
- (BOOL)isSystemContactWithSignalAccount:(SignalServiceAddress *)address
|
||||
NS_SWIFT_NAME(isSystemContactWithSignalAccount(_:));
|
||||
- (BOOL)isSystemContactWithSignalAccount:(SignalServiceAddress *)address
|
||||
transaction:(SDSAnyReadTransaction *)transaction
|
||||
NS_SWIFT_NAME(isSystemContactWithSignalAccount(_:transaction:));
|
||||
- (BOOL)hasNameInSystemContactsForAddress:(SignalServiceAddress *)address;
|
||||
- (BOOL)hasNameInSystemContactsForAddress:(SignalServiceAddress *)address
|
||||
transaction:(SDSAnyReadTransaction *)transaction;
|
||||
|
||||
@ -66,6 +66,15 @@ public class FakeContactsManager: NSObject, ContactsManagerProtocol {
|
||||
return true
|
||||
}
|
||||
|
||||
public func isSystemContactWithSignalAccount(_ address: SignalServiceAddress) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
public func isSystemContactWithSignalAccount(_ address: SignalServiceAddress,
|
||||
transaction: SDSAnyReadTransaction) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
public func sortSignalServiceAddresses(_ addresses: [SignalServiceAddress],
|
||||
transaction: SDSAnyReadTransaction) -> [SignalServiceAddress] {
|
||||
return addresses
|
||||
|
||||
Loading…
Reference in New Issue
Block a user