[go: nahoru, domu]

blob: 756b4c54e39c40f2fd12f6ba72217bb5d0504702 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/ui/autofill/autofill_country_selection_table_view_controller.h"
#import "base/apple/foundation_util.h"
#import "base/strings/sys_string_conversions.h"
#import "ios/chrome/browser/shared/public/features/features.h"
#import "ios/chrome/browser/shared/ui/table_view/table_view_navigation_controller_constants.h"
#import "ios/chrome/browser/shared/ui/table_view/table_view_utils.h"
#import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h"
#import "ios/chrome/browser/ui/autofill/cells/country_item.h"
#import "ios/chrome/browser/ui/settings/autofill/autofill_constants.h"
#import "ios/chrome/common/ui/colors/semantic_color_names.h"
#import "ios/chrome/common/ui/table_view/table_view_cells_constants.h"
#import "ios/chrome/common/ui/util/constraints_ui_util.h"
#import "ios/chrome/grit/ios_strings.h"
#import "ui/base/l10n/l10n_util_mac.h"
namespace {
typedef NS_ENUM(NSInteger, SectionIdentifier) {
SectionIdentifierCountries = kSectionIdentifierEnumZero,
};
} // namespace
@interface AutofillCountrySelectionTableViewController () <
UISearchControllerDelegate,
UISearchResultsUpdating> {
}
// The delegate passed to this instance.
@property(nonatomic, weak)
id<AutofillCountrySelectionTableViewControllerDelegate>
delegate;
// This ViewController's search controller.
@property(nonatomic, strong) UISearchController* searchController;
// Denotes the currently selected country.
@property(nonatomic, strong) NSString* currentlySelectedCountry;
// The current search filter. May be nil.
@property(nonatomic, strong) NSPredicate* searchPredicate;
// Scrim overlay covering the entire tableView when the search bar is focused.
@property(nonatomic, strong) UIControl* scrimView;
// The fetched country list.
@property(nonatomic, weak) NSArray<CountryItem*>* allCountries;
// If YES, denotes that the view is shown in the settings.
@property(nonatomic, assign) BOOL settingsView;
@end
@implementation AutofillCountrySelectionTableViewController
- (instancetype)initWithDelegate:
(id<AutofillCountrySelectionTableViewControllerDelegate>)
delegate
selectedCountry:(NSString*)selectedCountry
allCountries:(NSArray<CountryItem*>*)allCountries
settingsView:(BOOL)settingsView {
DCHECK(delegate);
self = [super initWithStyle:(settingsView ? ChromeTableViewStyle()
: UITableViewStylePlain)];
if (self) {
_delegate = delegate;
_currentlySelectedCountry = selectedCountry;
_allCountries = allCountries;
_settingsView = settingsView;
}
return self;
}
#pragma mark - UIViewController
- (void)viewDidLoad {
[super viewDidLoad];
if (!self.settingsView) {
self.title = l10n_util::GetNSString(IDS_IOS_AUTOFILL_SELECT_COUNTRY);
self.view.backgroundColor = [UIColor colorNamed:kBackgroundColor];
self.tableView.sectionHeaderHeight = 0;
self.tableView.sectionFooterHeight = 0;
} else {
self.title = l10n_util::GetNSString(IDS_IOS_AUTOFILL_EDIT_ADDRESS);
}
[self.tableView
setSeparatorInset:UIEdgeInsetsMake(0, kTableViewHorizontalSpacing, 0, 0)];
// Search controller.
self.searchController =
[[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.obscuresBackgroundDuringPresentation = NO;
self.searchController.searchResultsUpdater = self;
self.searchController.searchBar.accessibilityIdentifier =
kAutofillCountrySelectionTableViewId;
// Presentation of searchController will walk up the view controller hierarchy
// until it finds the root view controller or one that defines a presentation
// context. Make this view controller the presentation context so that the
// searchController does not present on top of the navigation controller.
self.definesPresentationContext = YES;
// Place the search bar in the navigation bar.
self.navigationItem.searchController = self.searchController;
self.navigationItem.hidesSearchBarWhenScrolling = NO;
self.navigationItem.largeTitleDisplayMode =
UINavigationItemLargeTitleDisplayModeAutomatic;
// Scrim.
self.scrimView = [[UIControl alloc] init];
self.scrimView.alpha = 0.0f;
self.scrimView.backgroundColor = UIColor.clearColor;
self.scrimView.translatesAutoresizingMaskIntoConstraints = NO;
self.scrimView.accessibilityIdentifier =
kAutofillCountrySelectionSearchScrimId;
[self.scrimView addTarget:self
action:@selector(dismissSearchController:)
forControlEvents:UIControlEventTouchUpInside];
[self loadModel];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// Autoscroll to the selected country.
for (CountryItem* item in [self.tableViewModel
itemsInSectionWithIdentifier:SectionIdentifierCountries]) {
if (item.accessoryType == UITableViewCellAccessoryCheckmark) {
NSIndexPath* indexPath = [self.tableViewModel indexPathForItem:item];
[self.tableView scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionMiddle
animated:NO];
}
}
}
#pragma mark - ChromeTableViewController
- (void)loadModel {
[super loadModel];
[self.tableViewModel addSectionWithIdentifier:SectionIdentifierCountries];
[self populateCountriesSection];
}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView*)tableView
didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
if (@available(iOS 16.0, *)) {
return;
}
CountryItem* item = base::apple::ObjCCastStrict<CountryItem>(
[self.tableViewModel itemAtIndexPath:indexPath]);
[self.delegate didSelectCountry:item];
}
- (void)tableView:(UITableView*)tableView
performPrimaryActionForRowAtIndexPath:(NSIndexPath*)indexPath {
CountryItem* item = base::apple::ObjCCastStrict<CountryItem>(
[self.tableViewModel itemAtIndexPath:indexPath]);
[self.delegate didSelectCountry:item];
}
#pragma mark - UISearchResultsUpdating
- (void)updateSearchResultsForSearchController:
(UISearchController*)searchController {
NSString* searchText = searchController.searchBar.text;
// Set the current search filter to filter the languages based on the display
// name of the language in the current locale and the language locale. The
// search is case insensitive and diacritic insensitive. If the search text is
// empty all languages will be displayed.
self.searchPredicate = [[NSPredicate
predicateWithFormat:@"$searchText.length == 0 OR text CONTAINS[cd] "
@"$searchText"]
predicateWithSubstitutionVariables:@{@"searchText" : searchText}];
// Show the scrim overlay only if the search text is empty and the search
// controller is active (it is not being dismissed); Otherwise hide it.
if (searchText.length == 0 && self.searchController.active) {
[self showScrim];
} else {
[self hideScrim];
}
[self updateCountriesSection];
}
#pragma mark - Helper methods
// Populates the country items in the section.
- (void)populateCountriesSection {
TableViewModel* model = self.tableViewModel;
// Filter the countries items based on the current search text, if applicable.
NSArray<CountryItem*>* filteredSupportedCountries = self.allCountries;
if (self.searchPredicate) {
filteredSupportedCountries = [filteredSupportedCountries
filteredArrayUsingPredicate:self.searchPredicate];
}
for (CountryItem* item in filteredSupportedCountries) {
[model addItem:item toSectionWithIdentifier:SectionIdentifierCountries];
}
}
// Shows scrim overlay and hide toolbar.
- (void)showScrim {
if (self.scrimView.alpha < 1.0f) {
self.scrimView.alpha = 0.0f;
[self.tableView addSubview:self.scrimView];
// We attach our constraints to the superview because the tableView is
// a scrollView and it seems that we get an empty frame when attaching to
// it.
AddSameConstraints(self.scrimView, self.view.superview);
self.tableView.accessibilityElementsHidden = YES;
self.tableView.scrollEnabled = NO;
__weak __typeof(self) weakSelf = self;
[UIView animateWithDuration:kTableViewNavigationScrimFadeDuration
animations:^{
weakSelf.scrimView.alpha = 1.0f;
[weakSelf.view layoutIfNeeded];
}];
}
}
// Hides scrim and restore toolbar.
- (void)hideScrim {
if (self.scrimView.alpha > 0.0f) {
__weak __typeof(self) weakSelf = self;
[UIView animateWithDuration:kTableViewNavigationScrimFadeDuration
animations:^{
weakSelf.scrimView.alpha = 0.0f;
}
completion:^(BOOL finished) {
[weakSelf.scrimView removeFromSuperview];
weakSelf.tableView.accessibilityElementsHidden = NO;
weakSelf.tableView.scrollEnabled = YES;
}];
}
}
// Dismisses the search controller when the scrim overlay is tapped.
- (void)dismissSearchController:(UIControl*)sender {
self.searchController.active = NO;
}
// Reloads the countries items in thes ection.
- (void)updateCountriesSection {
// Update the model.
[self.tableViewModel
deleteAllItemsFromSectionWithIdentifier:SectionIdentifierCountries];
[self populateCountriesSection];
// Update the table view.
NSUInteger index = [self.tableViewModel
sectionForSectionIdentifier:SectionIdentifierCountries];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:index]
withRowAnimation:UITableViewRowAnimationNone];
}
#pragma mark - SettingsControllerProtocol
- (void)reportDismissalUserAction {
// TODO(crbug.com/1407666): Record for this VC.
}
- (void)reportBackUserAction {
// TODO(crbug.com/1407666): Record for this VC.
}
@end