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 |