Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(322)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/locale/DefaultSearchEnginePromoDialog.java

Issue 2838833002: 🔍 Introduce default search engine dialog (Closed)
Patch Set: Redo how the dialog is created Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.chrome.browser.locale;
6
7 import android.content.Context;
8 import android.content.DialogInterface;
9 import android.os.Bundle;
10 import android.support.annotation.Nullable;
11 import android.view.View;
12 import android.widget.RadioButton;
13 import android.widget.RadioGroup;
14 import android.widget.RadioGroup.OnCheckedChangeListener;
15
16 import org.chromium.base.library_loader.LibraryLoader;
17 import org.chromium.chrome.R;
18 import org.chromium.chrome.browser.infobar.InfoBarControlLayout;
19 import org.chromium.chrome.browser.search_engines.TemplateUrlService;
20 import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl ;
21 import org.chromium.chrome.browser.widget.PromoDialog;
22
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.Random;
26
27 /** A dialog that forces the user to choose a default search engine. */
28 public class DefaultSearchEnginePromoDialog extends PromoDialog implements OnChe ckedChangeListener {
29 /** Used to determine the promo dialog contents. */
30 private final int mDialogType;
31
32 /** Run when the dialog is dismissed after the user has chosen a search engi ne. */
33 private final Runnable mOnDismissed;
34
35 private RadioGroup mRadioGroup;
36 private String mSelectedKeyword;
37
38 /**
39 * Construct and show the dialog. Will be asynchronous if the TemplateUrlSe rvice has not yet
40 * been loaded.
41 */
42 public static void create(
Ted C 2017/04/26 20:21:52 maybe this should be called show?
gone 2017/04/26 21:45:15 Done.
43 final Context context, final int dialogType, @Nullable final Runnabl e onDismissed) {
Ted C 2017/04/26 20:21:52 Should/can dialogType have an associated IntDef?
gone 2017/04/26 21:45:15 Seems like it'd be fine to move it to always be ca
44 assert LibraryLoader.isInitialized();
45
46 // Load up the search engines.
47 final TemplateUrlService instance = TemplateUrlService.getInstance();
48 instance.registerLoadListener(new TemplateUrlService.LoadListener() {
49 @Override
50 public void onTemplateUrlServiceLoaded() {
51 instance.unregisterLoadListener(this);
52 new DefaultSearchEnginePromoDialog(context, dialogType, onDismis sed).show();
53 }
54 });
55 instance.load();
56 }
57
58 private DefaultSearchEnginePromoDialog(
59 Context context, int dialogType, @Nullable Runnable onDismissed) {
60 super(context);
61 mDialogType = dialogType;
62 mOnDismissed = onDismissed;
63 setOnDismissListener(this);
64
65 // No one should be able to bypass this dialog by clicking outside or by hitting back.
66 setCancelable(false);
67 setCanceledOnTouchOutside(false);
68 }
69
70 @Override
71 protected DialogParams getDialogParams() {
72 PromoDialog.DialogParams params = new PromoDialog.DialogParams();
73 params.headerStringResource = R.string.search_engine_dialog_title;
74 params.footerStringResource = R.string.search_engine_dialog_footer;
75 params.primaryButtonStringResource = R.string.ok;
76 return params;
77 }
78
79 @Override
80 protected void onCreate(Bundle savedInstanceState) {
81 super.onCreate(savedInstanceState);
82 assert LibraryLoader.isInitialized();
Ted C 2017/04/26 20:21:52 Since this happens in the one place you create it
gone 2017/04/26 21:45:15 Done.
83
84 // Set up the general UI.
85 InfoBarControlLayout controls = addControlLayout();
86 updateButtonState();
87
88 // Load up the search engines.
89 TemplateUrlService instance = TemplateUrlService.getInstance();
90 assert instance.isLoaded();
91 List<TemplateUrl> engines = null;
92 if (mDialogType == LocaleManager.SEARCH_ENGINE_PROMO_SHOW_EXISTING) {
93 engines = instance.getSearchEngines();
94 } else {
95 // TODO(dfalcantara): Handle the new user case.
96 assert false;
97 }
98
99 List<CharSequence> engineNames = new ArrayList<>();
100 List<String> engineKeywords = new ArrayList<>();
101 shuffleEngines(engines, engineNames, engineKeywords);
102
103 // Add the search engines to the dialog.
104 mRadioGroup = controls.addRadioButtons(
105 engineNames, engineKeywords, InfoBarControlLayout.INVALID_INDEX) ;
106 mRadioGroup.setOnCheckedChangeListener(this);
107 }
108
109 @Override
110 public void onCheckedChanged(RadioGroup group, int checkedId) {
111 mSelectedKeyword = null;
112
113 // Run through the RadioGroup to figure out which one was checked.
114 for (int i = 0; i < group.getChildCount(); i++) {
115 View child = group.getChildAt(i);
116 assert child instanceof RadioButton;
117
118 RadioButton button = (RadioButton) child;
119 if (button.isChecked()) {
120 assert mSelectedKeyword == null;
121 mSelectedKeyword = (String) button.getTag();
122 }
123 }
124
125 updateButtonState();
126 }
127
128 @Override
129 public void onClick(View view) {
130 if (view.getId() == R.id.button_primary) {
131 if (mSelectedKeyword == null) {
132 updateButtonState();
133 return;
134 }
135
136 dismiss();
137 } else {
138 assert false : "Unhandled click.";
139 }
140
141 // Don't propagate the click to the parent to prevent circumventing the dialog.
142 }
143
144 @Override
145 public void onDismiss(DialogInterface dialog) {
146 if (mSelectedKeyword == null) {
147 // This shouldn't happen, but in case it does, finish the Activity s o that the user has
148 // to respond to the dialog next time.
149 if (getOwnerActivity() != null) getOwnerActivity().finish();
Ted C 2017/04/26 20:21:52 should this be finish and remove task?
gone 2017/04/26 21:45:15 I'd argue for a regular finish() so that the activ
150 } else {
151 TemplateUrlService.getInstance().setSearchEngine(mSelectedKeyword.to String());
152 if (mOnDismissed != null) mOnDismissed.run();
153 // TODO(dfalcantara): Prevent the dialog from appearing again.
154 }
155 }
156
157 private void updateButtonState() {
158 findViewById(R.id.button_primary).setEnabled(mSelectedKeyword != null);
159 }
160
161 private void shuffleEngines(
162 List<TemplateUrl> engines, List<CharSequence> names, List<String> ke ywords) {
163 ArrayList<Integer> indices = new ArrayList<>();
Ted C 2017/04/26 20:21:52 Could we use: https://developer.android.com/refere
gone 2017/04/26 21:45:15 Works for me.
164 for (int i = 0; i < engines.size(); i++) indices.add(i);
165
166 Random generator = new Random();
167 for (int i = 0; i < indices.size(); i++) {
168 int remaining = indices.size() - i;
169 int shuffleIndex = i + generator.nextInt(remaining);
170
171 if (shuffleIndex != i) {
172 int temp = indices.get(i);
173 indices.set(i, indices.get(shuffleIndex));
174 indices.set(shuffleIndex, temp);
175 }
176 }
177
178 for (Integer index : indices) {
179 TemplateUrl engine = engines.get(index);
180 names.add(engine.getShortName());
181 keywords.add(engine.getKeyword());
182 }
183 }
184 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698