| Index: ios/chrome/browser/ui/settings/voicesearch_collection_view_controller.mm
|
| diff --git a/ios/chrome/browser/ui/settings/voicesearch_collection_view_controller.mm b/ios/chrome/browser/ui/settings/voicesearch_collection_view_controller.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..5298b8fb6e4a519d0c03548bf6eb5649b6f1a837
|
| --- /dev/null
|
| +++ b/ios/chrome/browser/ui/settings/voicesearch_collection_view_controller.mm
|
| @@ -0,0 +1,254 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// 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/settings/voicesearch_collection_view_controller.h"
|
| +
|
| +#include "base/ios/weak_nsobject.h"
|
| +#include "base/logging.h"
|
| +#include "base/mac/foundation_util.h"
|
| +#include "base/mac/scoped_nsobject.h"
|
| +#include "base/strings/sys_string_conversions.h"
|
| +#include "components/prefs/pref_member.h"
|
| +#include "components/prefs/pref_service.h"
|
| +#import "ios/chrome/browser/ui/collection_view/cells/collection_view_switch_item.h"
|
| +#import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h"
|
| +#import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
|
| +#include "ios/chrome/browser/voice/speech_input_locale_config.h"
|
| +#include "ios/chrome/grit/ios_strings.h"
|
| +#include "ios/public/provider/chrome/browser/voice/voice_search_prefs.h"
|
| +#import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h"
|
| +#include "ui/base/l10n/l10n_util.h"
|
| +#include "ui/base/l10n/l10n_util_mac.h"
|
| +
|
| +namespace {
|
| +
|
| +typedef NS_ENUM(NSInteger, SectionIdentifier) {
|
| + SectionIdentifierTTS = kSectionIdentifierEnumZero,
|
| + SectionIdentifierLanguages,
|
| +};
|
| +
|
| +typedef NS_ENUM(NSInteger, ItemType) {
|
| + ItemTypeTTSEnabled = kItemTypeEnumZero,
|
| + ItemTypeLanguagesLanguageOption,
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +@interface VoicesearchCollectionViewController () {
|
| + PrefService* _prefs; // weak
|
| + StringPrefMember _selectedLanguage;
|
| + BooleanPrefMember _ttsEnabled;
|
| +}
|
| +// Updates all cells to check the selected language and uncheck all the other.
|
| +- (void)markAsCheckedLanguageAtIndex:(NSUInteger)index;
|
| +
|
| +// Returns YES if the current language supports TTS.
|
| +- (BOOL)currentLanguageSupportsTTS;
|
| +@end
|
| +
|
| +@implementation VoicesearchCollectionViewController
|
| +
|
| +#pragma mark - Initialization
|
| +
|
| +- (instancetype)initWithPrefs:(PrefService*)prefs {
|
| + self = [super initWithStyle:CollectionViewControllerStyleAppBar];
|
| + if (self) {
|
| + self.title = l10n_util::GetNSString(IDS_IOS_VOICE_SEARCH_SETTING_TITLE);
|
| + _prefs = prefs;
|
| + _selectedLanguage.Init(prefs::kVoiceSearchLocale, _prefs);
|
| + _ttsEnabled.Init(prefs::kVoiceSearchTTS, _prefs);
|
| + [self loadModel];
|
| + }
|
| + return self;
|
| +}
|
| +
|
| +- (void)loadModel {
|
| + [super loadModel];
|
| + CollectionViewModel* model = self.collectionViewModel;
|
| +
|
| + // TTS section.
|
| + [model addSectionWithIdentifier:SectionIdentifierTTS];
|
| + CollectionViewSwitchItem* tts = [[[CollectionViewSwitchItem alloc]
|
| + initWithType:ItemTypeTTSEnabled] autorelease];
|
| + tts.text = l10n_util::GetNSString(IDS_IOS_VOICE_SEARCH_SETTING_TTS);
|
| + tts.on = _ttsEnabled.GetValue();
|
| + tts.enabled = [self currentLanguageSupportsTTS];
|
| + [model addItem:tts toSectionWithIdentifier:SectionIdentifierTTS];
|
| +
|
| + // Variables used to populate the languages section.
|
| + voice::SpeechInputLocaleConfig* localeConfig =
|
| + voice::SpeechInputLocaleConfig::GetInstance();
|
| + const std::vector<voice::SpeechInputLocale>& locales =
|
| + localeConfig->GetAvailableLocales();
|
| + std::string selectedLocaleCode = _selectedLanguage.GetValue();
|
| +
|
| + // Section with the list of voice search languages.
|
| + [model addSectionWithIdentifier:SectionIdentifierLanguages];
|
| + // Add default locale option. Using an empty string for the voice search
|
| + // locale pref indicates using the default locale.
|
| + CollectionViewTextItem* defaultItem = [[[CollectionViewTextItem alloc]
|
| + initWithType:ItemTypeLanguagesLanguageOption] autorelease];
|
| + defaultItem.text =
|
| + l10n_util::GetNSStringF(IDS_IOS_VOICE_SEARCH_SETTINGS_DEFAULT_LOCALE,
|
| + localeConfig->GetDefaultLocale().display_name);
|
| + defaultItem.accessoryType = selectedLocaleCode.empty()
|
| + ? MDCCollectionViewCellAccessoryCheckmark
|
| + : MDCCollectionViewCellAccessoryNone;
|
| + [model addItem:defaultItem
|
| + toSectionWithIdentifier:SectionIdentifierLanguages];
|
| + // Add locale list.
|
| + for (NSUInteger ii = 0; ii < locales.size(); ii++) {
|
| + voice::SpeechInputLocale locale = locales[ii];
|
| + NSString* languageName = base::SysUTF16ToNSString(locale.display_name);
|
| + BOOL checked = (locale.code == selectedLocaleCode);
|
| +
|
| + CollectionViewTextItem* languageItem = [[[CollectionViewTextItem alloc]
|
| + initWithType:ItemTypeLanguagesLanguageOption] autorelease];
|
| + languageItem.text = languageName;
|
| + languageItem.accessoryType = checked
|
| + ? MDCCollectionViewCellAccessoryCheckmark
|
| + : MDCCollectionViewCellAccessoryNone;
|
| + [model addItem:languageItem
|
| + toSectionWithIdentifier:SectionIdentifierLanguages];
|
| + }
|
| +}
|
| +
|
| +#pragma mark - UICollectionViewDelegate
|
| +
|
| +- (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView
|
| + cellForItemAtIndexPath:(NSIndexPath*)indexPath {
|
| + UICollectionViewCell* cell =
|
| + [super collectionView:collectionView cellForItemAtIndexPath:indexPath];
|
| + NSInteger itemType =
|
| + [self.collectionViewModel itemTypeForIndexPath:indexPath];
|
| +
|
| + if (itemType == ItemTypeTTSEnabled) {
|
| + // Have the switch send a message on UIControlEventValueChanged.
|
| + CollectionViewSwitchCell* switchCell =
|
| + base::mac::ObjCCastStrict<CollectionViewSwitchCell>(cell);
|
| + [switchCell.switchView addTarget:self
|
| + action:@selector(ttsToggled:)
|
| + forControlEvents:UIControlEventValueChanged];
|
| + }
|
| +
|
| + return cell;
|
| +}
|
| +
|
| +- (void)collectionView:(UICollectionView*)collectionView
|
| + didSelectItemAtIndexPath:(NSIndexPath*)indexPath {
|
| + [super collectionView:collectionView didSelectItemAtIndexPath:indexPath];
|
| +
|
| + CollectionViewModel* model = self.collectionViewModel;
|
| + CollectionViewItem* item = [model itemAtIndexPath:indexPath];
|
| +
|
| + // Language options.
|
| + if (item.type == ItemTypeLanguagesLanguageOption) {
|
| + NSInteger index = [model indexInItemTypeForIndexPath:indexPath];
|
| + std::string selectedLocaleCode;
|
| + if (index > 0) {
|
| + // Fetch selected locale code from locale list if non-default option was
|
| + // selected. Setting the preference to the empty string denotes using the
|
| + // default locale.
|
| + voice::SpeechInputLocaleConfig* localeConfig =
|
| + voice::SpeechInputLocaleConfig::GetInstance();
|
| + DCHECK_LT(static_cast<size_t>(index - 1),
|
| + localeConfig->GetAvailableLocales().size());
|
| + selectedLocaleCode = localeConfig->GetAvailableLocales()[index - 1].code;
|
| + }
|
| + _selectedLanguage.SetValue(selectedLocaleCode);
|
| +
|
| + // Update the UI.
|
| + [self markAsCheckedLanguageAtIndex:index];
|
| + }
|
| +}
|
| +
|
| +#pragma mark MDCCollectionViewStylingDelegate
|
| +
|
| +- (BOOL)collectionView:(UICollectionView*)collectionView
|
| + hidesInkViewAtIndexPath:(NSIndexPath*)indexPath {
|
| + NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath];
|
| + switch (type) {
|
| + case ItemTypeTTSEnabled:
|
| + return YES;
|
| + default:
|
| + return NO;
|
| + }
|
| +}
|
| +
|
| +#pragma mark - Actions
|
| +
|
| +- (void)ttsToggled:(id)sender {
|
| + NSIndexPath* switchPath =
|
| + [self.collectionViewModel indexPathForItemType:ItemTypeTTSEnabled
|
| + sectionIdentifier:SectionIdentifierTTS];
|
| +
|
| + CollectionViewSwitchItem* switchItem =
|
| + base::mac::ObjCCastStrict<CollectionViewSwitchItem>(
|
| + [self.collectionViewModel itemAtIndexPath:switchPath]);
|
| + CollectionViewSwitchCell* switchCell =
|
| + base::mac::ObjCCastStrict<CollectionViewSwitchCell>(
|
| + [self.collectionView cellForItemAtIndexPath:switchPath]);
|
| +
|
| + // Update the model and the preference with the current value of the switch.
|
| + DCHECK_EQ(switchCell.switchView, sender);
|
| + BOOL isOn = switchCell.switchView.isOn;
|
| + switchItem.on = isOn;
|
| + _ttsEnabled.SetValue(isOn);
|
| +}
|
| +
|
| +#pragma mark - Private methods
|
| +
|
| +- (void)markAsCheckedLanguageAtIndex:(NSUInteger)index {
|
| + // Update the collection view model with the new selected language.
|
| + NSArray* languageItems = [self.collectionViewModel
|
| + itemsInSectionWithIdentifier:SectionIdentifierLanguages];
|
| + NSMutableArray* modifiedItems = [NSMutableArray array];
|
| + for (NSUInteger ii = 0; ii < [languageItems count]; ++ii) {
|
| + MDCCollectionViewCellAccessoryType type =
|
| + (ii == index) ? MDCCollectionViewCellAccessoryCheckmark
|
| + : MDCCollectionViewCellAccessoryNone;
|
| +
|
| + CollectionViewTextItem* textItem =
|
| + base::mac::ObjCCastStrict<CollectionViewTextItem>(
|
| + [languageItems objectAtIndex:ii]);
|
| + if (textItem.accessoryType != type) {
|
| + textItem.accessoryType = type;
|
| + [modifiedItems addObject:textItem];
|
| + }
|
| + }
|
| +
|
| + // Some languages do not support TTS. Disable the switch for those
|
| + // languages.
|
| + NSIndexPath* switchPath =
|
| + [self.collectionViewModel indexPathForItemType:ItemTypeTTSEnabled
|
| + sectionIdentifier:SectionIdentifierTTS];
|
| + CollectionViewSwitchCell* switchCell =
|
| + base::mac::ObjCCastStrict<CollectionViewSwitchCell>(
|
| + [self.collectionView cellForItemAtIndexPath:switchPath]);
|
| +
|
| + BOOL enabled = [self currentLanguageSupportsTTS];
|
| + BOOL on = enabled && _ttsEnabled.GetValue();
|
| +
|
| + UISwitch* switchView = switchCell.switchView;
|
| + switchView.enabled = enabled;
|
| + switchCell.textLabel.textColor =
|
| + [CollectionViewSwitchCell defaultTextColorForState:switchView.state];
|
| + if (on != switchView.isOn) {
|
| + [switchView setOn:on animated:YES];
|
| + }
|
| +
|
| + [self reconfigureCellsForItems:modifiedItems
|
| + inSectionWithIdentifier:SectionIdentifierLanguages];
|
| +}
|
| +
|
| +- (BOOL)currentLanguageSupportsTTS {
|
| + voice::SpeechInputLocaleConfig* localeConfig =
|
| + voice::SpeechInputLocaleConfig::GetInstance();
|
| + std::string localeCode = _selectedLanguage.GetValue().empty()
|
| + ? localeConfig->GetDefaultLocale().code
|
| + : _selectedLanguage.GetValue();
|
| + return localeConfig->IsTextToSpeechEnabledForCode(localeCode);
|
| +}
|
| +
|
| +@end
|
|
|