diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index ed66f5b89..67d390007 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -1039,6 +1039,12 @@ Tap the + to start adding people."; "service_terms_modal_description_identity_server" = "This will allow someone to find you if they have your phone number or email saved in their phone contacts."; "service_terms_modal_description_integration_manager" = "This will allow you to use bots, bridges, widgets and sticker packs."; +// Alert explaining what an identity server / integration manager is. +"service_terms_modal_information_title_identity_server" = "Identity Server"; +"service_terms_modal_information_title_integration_manager" = "Integration Manager"; +"service_terms_modal_information_description_identity_server" = "An identity server allows %@ to find users on Matrix by looking up their phone number or email address."; +"service_terms_modal_information_description_integration_manager" = "An integration manager allows %@ to ..."; + "service_terms_modal_policy_checkbox_accessibility_hint" = "Check to accept %@"; // Deactivate account diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 6891446ae..cf7f1b935 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -559,6 +559,14 @@ public class VectorL10n: NSObject { public static func contactsAddressBookPermissionDenied(_ p1: String) -> String { return VectorL10n.tr("Vector", "contacts_address_book_permission_denied", p1) } + /// To enable contacts, go to your device settings. + public static var contactsAddressBookPermissionDeniedAlertMessage: String { + return VectorL10n.tr("Vector", "contacts_address_book_permission_denied_alert_message") + } + /// Contacts disabled + public static var contactsAddressBookPermissionDeniedAlertTitle: String { + return VectorL10n.tr("Vector", "contacts_address_book_permission_denied_alert_title") + } /// Permission required to access local contacts public static var contactsAddressBookPermissionRequired: String { return VectorL10n.tr("Vector", "contacts_address_book_permission_required") @@ -1403,6 +1411,26 @@ public class VectorL10n: NSObject { public static var fileUploadErrorUnsupportedFileTypeMessage: String { return VectorL10n.tr("Vector", "file_upload_error_unsupported_file_type_message") } + /// Find your contacts + public static var findYourContactsButtonTitle: String { + return VectorL10n.tr("Vector", "find_your_contacts_button_title") + } + /// This can be disabled anytime from settings. + public static var findYourContactsFooter: String { + return VectorL10n.tr("Vector", "find_your_contacts_footer") + } + /// Unable to connect to the identity server. + public static var findYourContactsIdentityServiceError: String { + return VectorL10n.tr("Vector", "find_your_contacts_identity_service_error") + } + /// Let %@ show your contacts so you can quickly start chatting with those you know best. + public static func findYourContactsMessage(_ p1: String) -> String { + return VectorL10n.tr("Vector", "find_your_contacts_message", p1) + } + /// Start by listing your contacts + public static var findYourContactsTitle: String { + return VectorL10n.tr("Vector", "find_your_contacts_title") + } /// To continue using the %@ homeserver you must review and agree to the terms and conditions. public static func gdprConsentNotGivenAlertMessage(_ p1: String) -> String { return VectorL10n.tr("Vector", "gdpr_consent_not_given_alert_message", p1) @@ -2463,7 +2491,7 @@ public class VectorL10n: NSObject { public static var roomCreationErrorInviteUserByEmailWithoutIdentityServer: String { return VectorL10n.tr("Vector", "room_creation_error_invite_user_by_email_without_identity_server") } - /// Search / invite by User ID, Name or email + /// User ID, name or email public static var roomCreationInviteAnotherUser: String { return VectorL10n.tr("Vector", "room_creation_invite_another_user") } @@ -4011,37 +4039,49 @@ public class VectorL10n: NSObject { public static var serviceTermsModalDeclineButton: String { return VectorL10n.tr("Vector", "service_terms_modal_decline_button") } - /// Find others by phone or email - public static var serviceTermsModalDescriptionForIdentityServer1: String { - return VectorL10n.tr("Vector", "service_terms_modal_description_for_identity_server_1") + /// This will allow someone to find you if they have your phone number or email saved in their phone contacts. + public static var serviceTermsModalDescriptionIdentityServer: String { + return VectorL10n.tr("Vector", "service_terms_modal_description_identity_server") } - /// Be found by phone or email - public static var serviceTermsModalDescriptionForIdentityServer2: String { - return VectorL10n.tr("Vector", "service_terms_modal_description_for_identity_server_2") + /// This will allow you to use bots, bridges, widgets and sticker packs. + public static var serviceTermsModalDescriptionIntegrationManager: String { + return VectorL10n.tr("Vector", "service_terms_modal_description_integration_manager") } - /// Use Bots, bridges, widgets and sticker packs - public static var serviceTermsModalDescriptionForIntegrationManager: String { - return VectorL10n.tr("Vector", "service_terms_modal_description_for_integration_manager") + /// This can be disabled anytime in settings. + public static var serviceTermsModalFooter: String { + return VectorL10n.tr("Vector", "service_terms_modal_footer") } - /// To continue you need to accept the terms of this service (%@). - public static func serviceTermsModalMessage(_ p1: String) -> String { - return VectorL10n.tr("Vector", "service_terms_modal_message", p1) + /// An identity server allows %@ to find users on Matrix by looking up their phone number or email address. + public static func serviceTermsModalInformationDescriptionIdentityServer(_ p1: String) -> String { + return VectorL10n.tr("Vector", "service_terms_modal_information_description_identity_server", p1) } - /// Accept the terms of the identity server (%@) to discover contacts. - public static func serviceTermsModalMessageIdentityServer(_ p1: String) -> String { - return VectorL10n.tr("Vector", "service_terms_modal_message_identity_server", p1) + /// An integration manager allows %@ to ... + public static func serviceTermsModalInformationDescriptionIntegrationManager(_ p1: String) -> String { + return VectorL10n.tr("Vector", "service_terms_modal_information_description_integration_manager", p1) + } + /// Identity Server + public static var serviceTermsModalInformationTitleIdentityServer: String { + return VectorL10n.tr("Vector", "service_terms_modal_information_title_identity_server") + } + /// Integration Manager + public static var serviceTermsModalInformationTitleIntegrationManager: String { + return VectorL10n.tr("Vector", "service_terms_modal_information_title_integration_manager") } /// Check to accept %@ public static func serviceTermsModalPolicyCheckboxAccessibilityHint(_ p1: String) -> String { return VectorL10n.tr("Vector", "service_terms_modal_policy_checkbox_accessibility_hint", p1) } - /// Terms Of Service - public static var serviceTermsModalTitle: String { - return VectorL10n.tr("Vector", "service_terms_modal_title") + /// IDENTITY SERVER TERMS + public static var serviceTermsModalTableHeaderIdentityServer: String { + return VectorL10n.tr("Vector", "service_terms_modal_table_header_identity_server") } - /// Contact discovery - public static var serviceTermsModalTitleIdentityServer: String { - return VectorL10n.tr("Vector", "service_terms_modal_title_identity_server") + /// INTEGRATION MANAGER TERMS + public static var serviceTermsModalTableHeaderIntegrationManager: String { + return VectorL10n.tr("Vector", "service_terms_modal_table_header_integration_manager") + } + /// To continue, accept the below terms and conditions + public static var serviceTermsModalTitleMessage: String { + return VectorL10n.tr("Vector", "service_terms_modal_title_message") } /// Invalid credentials public static var settingsAdd3pidInvalidPasswordMessage: String { @@ -4127,13 +4167,17 @@ public class VectorL10n: NSObject { public static var settingsConfirmPassword: String { return VectorL10n.tr("Vector", "settings_confirm_password") } - /// LOCAL CONTACTS + /// DEVICE CONTACTS public static var settingsContacts: String { return VectorL10n.tr("Vector", "settings_contacts") } - /// Use emails and phone numbers to discover users - public static var settingsContactsDiscoverMatrixUsers: String { - return VectorL10n.tr("Vector", "settings_contacts_discover_matrix_users") + /// Find your contacts + public static var settingsContactsEnableSync: String { + return VectorL10n.tr("Vector", "settings_contacts_enable_sync") + } + /// This will use your identity server to connect you with your contacts, and help them find you. + public static var settingsContactsEnableSyncDescription: String { + return VectorL10n.tr("Vector", "settings_contacts_enable_sync_description") } /// Phonebook country public static var settingsContactsPhonebookCountry: String { @@ -4543,6 +4587,10 @@ public class VectorL10n: NSObject { public static var settingsPasswordUpdated: String { return VectorL10n.tr("Vector", "settings_password_updated") } + /// PHONE CONTACTS + public static var settingsPhoneContacts: String { + return VectorL10n.tr("Vector", "settings_phone_contacts") + } /// Phone public static var settingsPhoneNumber: String { return VectorL10n.tr("Vector", "settings_phone_number") diff --git a/Riot/Modules/Contacts/ContactsTableViewController.h b/Riot/Modules/Contacts/ContactsTableViewController.h index 707070e1d..8b535495b 100644 --- a/Riot/Modules/Contacts/ContactsTableViewController.h +++ b/Riot/Modules/Contacts/ContactsTableViewController.h @@ -74,9 +74,8 @@ @property (nonatomic) BOOL disableFindYourContactsFooter; /** - Indicates when there's an active search. This is used to indicate that the contacts - access footer should be hidden as even without local contacts, there will still be - results to be shown from the server. + Indicates when there's an active search. This is used to determine when the contacts + access footer should be hidden in order to list the results from the server. */ @property (nonatomic) BOOL contactsAreFilteredWithSearch; diff --git a/Riot/Modules/Contacts/ContactsTableViewController.m b/Riot/Modules/Contacts/ContactsTableViewController.m index 5043d28cc..49342c959 100644 --- a/Riot/Modules/Contacts/ContactsTableViewController.m +++ b/Riot/Modules/Contacts/ContactsTableViewController.m @@ -200,6 +200,10 @@ #pragma mark - +/** + Creates a new `FindYourContactsFooterView` and caches it in + the `findYourContactsFooterView` property before returning it for use. + */ - (FindYourContactsFooterView*)makeFooterView { FindYourContactsFooterView *footerView = [FindYourContactsFooterView instantiate]; @@ -210,6 +214,11 @@ return footerView; } +/** + Checks whether local contacts sync is ready to use or if there are any search results + in the table, hiding the find your contacts footer if so. Otherwise the footer is shown + so long as it hasn't been disabled. + */ - (void)updateFooterViewVisibility { if (!BuildSettings.allowLocalContactsAccess || self.disableFindYourContactsFooter) @@ -238,6 +247,9 @@ [self updateFooterViewHeight]; } +/** + Updates the height of the find your contacts footer to fill all available space. + */ - (void)updateFooterViewHeight { if (self.findYourContactsFooterView && self.findYourContactsFooterView == self.contactsTableView.tableFooterView) @@ -504,7 +516,7 @@ #pragma mark - FindYourContactsFooterViewDelegate -- (void)didTapEnableContactsSync +- (void)contactsFooterViewDidRequestFindContacts:(FindYourContactsFooterView *)footerView { // First check the identity if service terms have already been accepted if (self->contactsDataSource.mxSession.identityService.areAllTermsAgreed) @@ -518,12 +530,14 @@ // The preparation can take some time so indicate this to the user [self startActivityIndicator]; + footerView.isActionEnabled = NO; [self->contactsDataSource.mxSession prepareIdentityServiceForTermsWithDefault:RiotSettings.shared.identityServerUrlString success:^(MXSession *session, NSString *baseURL, NSString *accessToken) { MXStrongifyAndReturnIfNil(self); [self stopActivityIndicator]; + footerView.isActionEnabled = YES; // Present the terms of the identity server. [self presentIdentityServerTermsWithSession:session baseURL:baseURL andAccessToken:accessToken]; @@ -532,12 +546,14 @@ MXStrongifyAndReturnIfNil(self); [self stopActivityIndicator]; + footerView.isActionEnabled = YES; - UIAlertController *alertController = [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"find_your_contacts_identity_service_error", @"Vector", nil) + // Alert the user that something went wrong. + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:VectorL10n.findYourContactsIdentityServiceError message:nil preferredStyle:UIAlertControllerStyleAlert]; - [alertController addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"ok"] + [alertController addAction:[UIAlertAction actionWithTitle:MatrixKitL10n.ok style:UIAlertActionStyleDefault handler:nil]]; @@ -551,8 +567,8 @@ MXWeakify(self); // Check for contacts access, showing a pop-up if necessary. - [MXKTools checkAccessForContacts:NSLocalizedStringFromTable(@"contacts_address_book_permission_denied_alert_title", @"Vector", nil) - withManualChangeMessage:NSLocalizedStringFromTable(@"contacts_address_book_permission_denied_alert_message", @"Vector", nil) + [MXKTools checkAccessForContacts:VectorL10n.contactsAddressBookPermissionDeniedAlertTitle + withManualChangeMessage:VectorL10n.contactsAddressBookPermissionDeniedAlertMessage showPopUpInViewController:self completionHandler:^(BOOL granted) { @@ -611,9 +627,7 @@ - (void)serviceTermsModalCoordinatorBridgePresenterDelegateDidDecline:(ServiceTermsModalCoordinatorBridgePresenter *)coordinatorBridgePresenter session:(MXSession *)session { - [coordinatorBridgePresenter dismissWithAnimated:YES completion:^{ - - }]; + [coordinatorBridgePresenter dismissWithAnimated:YES completion:nil]; self.serviceTermsModalCoordinatorBridgePresenter = nil; } diff --git a/Riot/Modules/Contacts/Views/FindYourContactsFooterView.swift b/Riot/Modules/Contacts/Views/FindYourContactsFooterView.swift index edaf04468..ba0e9cf8a 100644 --- a/Riot/Modules/Contacts/Views/FindYourContactsFooterView.swift +++ b/Riot/Modules/Contacts/Views/FindYourContactsFooterView.swift @@ -18,7 +18,7 @@ import UIKit import Reusable @objc protocol FindYourContactsFooterViewDelegate { - func didTapEnableContactsSync() + func contactsFooterViewDidRequestFindContacts(_ footerView: FindYourContactsFooterView) } @objcMembers @@ -28,11 +28,17 @@ class FindYourContactsFooterView: UIView, NibLoadable, Themable { weak var delegate: FindYourContactsFooterViewDelegate? - @IBOutlet weak var containerView: UIView! - @IBOutlet weak var titleLabel: UILabel! - @IBOutlet weak var messageLabel: UILabel! - @IBOutlet weak var button: CustomRoundedButton! - @IBOutlet weak var footerLabel: UILabel! + /// Whether or not the view's button responds to taps. + var isActionEnabled: Bool { + get { button.isEnabled } + set { button.isEnabled = newValue } + } + + @IBOutlet weak private var containerView: UIView! + @IBOutlet weak private var titleLabel: UILabel! + @IBOutlet weak private var messageLabel: UILabel! + @IBOutlet weak private var button: CustomRoundedButton! + @IBOutlet weak private var footerLabel: UILabel! // MARK: - Setup @@ -75,7 +81,7 @@ class FindYourContactsFooterView: UIView, NibLoadable, Themable { // MARK: - Action - @IBAction private func enableContactsSync(_ sender: Any) { - delegate?.didTapEnableContactsSync() + @IBAction private func buttonAction(_ sender: Any) { + delegate?.contactsFooterViewDidRequestFindContacts(self) } } diff --git a/Riot/Modules/Contacts/Views/FindYourContactsFooterView.xib b/Riot/Modules/Contacts/Views/FindYourContactsFooterView.xib index eb5faea58..86cc2734b 100644 --- a/Riot/Modules/Contacts/Views/FindYourContactsFooterView.xib +++ b/Riot/Modules/Contacts/Views/FindYourContactsFooterView.xib @@ -1,8 +1,6 @@ - - @@ -40,7 +38,7 @@ - +