Index: chrome/android/java/src/org/chromium/chrome/browser/firstrun/AccountFirstRunView.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/AccountFirstRunView.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/AccountFirstRunView.java |
index 002cd2eb946942ef81e43055575cba6d9ebd08e5..856c7d2bc0fc791d629afc0c546085aad5b44c80 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/AccountFirstRunView.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/AccountFirstRunView.java |
@@ -6,11 +6,13 @@ package org.chromium.chrome.browser.firstrun; |
import android.content.Context; |
import android.graphics.Bitmap; |
-import android.graphics.Color; |
+import android.graphics.drawable.Drawable; |
import android.os.Bundle; |
+import android.text.TextPaint; |
import android.text.TextUtils; |
+import android.text.method.LinkMovementMethod; |
+import android.text.style.ClickableSpan; |
import android.util.AttributeSet; |
-import android.view.Gravity; |
import android.view.View; |
import android.widget.AdapterView; |
import android.widget.ArrayAdapter; |
@@ -27,7 +29,8 @@ import org.chromium.chrome.browser.firstrun.ImageCarousel.ImageCarouselPositionC |
import org.chromium.chrome.browser.profiles.ProfileDownloader; |
import org.chromium.chrome.browser.signin.SigninManager; |
import org.chromium.sync.signin.AccountManagerHelper; |
-import org.chromium.ui.widget.ButtonCompat; |
+import org.chromium.ui.text.SpanApplier; |
+import org.chromium.ui.text.SpanApplier.SpanInfo; |
import java.util.List; |
@@ -45,12 +48,6 @@ public class AccountFirstRunView extends FrameLayout |
*/ |
public interface Listener { |
/** |
- * The user selected an account. |
- * @param accountName The name of the account |
- */ |
- public void onAccountSelectionConfirmed(String accountName); |
- |
- /** |
* The user canceled account selection. |
*/ |
public void onAccountSelectionCanceled(); |
@@ -61,16 +58,24 @@ public class AccountFirstRunView extends FrameLayout |
public void onNewAccount(); |
/** |
- * The user has been signed in and pressed 'Done' button. |
+ * The user selected an account. |
+ * This call will be followed by either {@link #onSettingsClicked} or |
+ * {@link #onDoneClicked}. |
* @param accountName The name of the account |
*/ |
- public void onSigningInCompleted(String accountName); |
+ public void onAccountSelected(String accountName); |
/** |
- * The user has signed in and pressed 'Settings' button. |
- * @param accountName The name of the account |
+ * The user has completed the dialog flow. |
+ * This will only be called after {@link #onAccountSelected} and should exit the View. |
*/ |
- public void onSettingsButtonClicked(String accountName); |
+ public void onDoneClicked(); |
+ |
+ /** |
+ * The user has selected to view sync settings. |
+ * This will only be called after {@link #onAccountSelected} and should exit the View. |
+ */ |
+ public void onSettingsClicked(); |
/** |
* Failed to set the forced account because it wasn't found. |
@@ -102,20 +107,27 @@ public class AccountFirstRunView extends FrameLayout |
} |
} |
+ private static final String TAG = "AccountFirstRunView"; |
+ |
private static final int EXPERIMENT_TITLE_VARIANT_MASK = 1; |
private static final int EXPERIMENT_SUMMARY_VARIANT_MASK = 2; |
private static final int EXPERIMENT_LAYOUT_VARIANT_MASK = 4; |
private static final int EXPERIMENT_MAX_VALUE = 7; |
+ private static final String SETTINGS_LINK_OPEN = "<LINK1>"; |
+ private static final String SETTINGS_LINK_CLOSE = "</LINK1>"; |
+ |
private AccountManagerHelper mAccountManagerHelper; |
private List<String> mAccountNames; |
private ArrayAdapter<CharSequence> mArrayAdapter; |
private ImageCarousel mImageCarousel; |
private Button mPositiveButton; |
private Button mNegativeButton; |
+ private TextView mTitle; |
private TextView mDescriptionText; |
private Listener mListener; |
private Spinner mSpinner; |
+ private Drawable mSpinnerBackground; |
private String mForcedAccountName; |
private String mAccountName; |
private String mAddAnotherAccount; |
@@ -123,11 +135,14 @@ public class AccountFirstRunView extends FrameLayout |
private boolean mSignedIn; |
private boolean mPositionSetProgrammatically; |
private int mDescriptionTextId; |
+ private int mCancelButtonTextId; |
private boolean mIsChildAccount; |
private boolean mHorizontalModeEnabled = true; |
+ private boolean mShowSettingsSpan = true; |
public AccountFirstRunView(Context context, AttributeSet attrs) { |
super(context, attrs); |
+ mAccountManagerHelper = AccountManagerHelper.get(getContext().getApplicationContext()); |
} |
/** |
@@ -157,30 +172,32 @@ public class AccountFirstRunView extends FrameLayout |
mPositiveButton = (Button) findViewById(R.id.positive_button); |
mNegativeButton = (Button) findViewById(R.id.negative_button); |
- mNegativeButton.setOnClickListener(new OnClickListener() { |
- @Override |
- public void onClick(View v) { |
- setButtonsEnabled(false); |
- mListener.onAccountSelectionCanceled(); |
- } |
- }); |
// A workaround for Android support library ignoring padding set in XML. b/20307607 |
int padding = getResources().getDimensionPixelSize(R.dimen.fre_button_padding); |
ApiCompatibilityUtils.setPaddingRelative(mPositiveButton, padding, 0, padding, 0); |
ApiCompatibilityUtils.setPaddingRelative(mNegativeButton, padding, 0, padding, 0); |
+ mTitle = (TextView) findViewById(R.id.title); |
mDescriptionText = (TextView) findViewById(R.id.description); |
+ // For the spans to be clickable. |
+ mDescriptionText.setMovementMethod(LinkMovementMethod.getInstance()); |
mDescriptionTextId = R.string.fre_account_choice_description; |
+ // TODO(peconn): Ensure this is changed to R.string.cancel when used in Settings > Sign In. |
+ mCancelButtonTextId = R.string.fre_skip_text; |
+ |
+ // Set the invisible TextView to contain the longest text the visible TextView can hold. |
+ // It assumes that the signed in description for child accounts is the longest text. |
+ ((TextView) findViewById(R.id.longest_description)).setText(getSignedInDescription(true)); |
+ |
mAddAnotherAccount = getResources().getString(R.string.fre_add_account); |
mSpinner = (Spinner) findViewById(R.id.google_accounts_spinner); |
+ mSpinnerBackground = mSpinner.getBackground(); |
mArrayAdapter = new ArrayAdapter<CharSequence>( |
getContext().getApplicationContext(), R.layout.fre_spinner_text); |
- updateAccounts(); |
- |
mArrayAdapter.setDropDownViewResource(R.layout.fre_spinner_dropdown); |
mSpinner.setAdapter(mArrayAdapter); |
mSpinner.setOnItemSelectedListener(new SpinnerOnItemSelectedListener()); |
@@ -201,6 +218,8 @@ public class AccountFirstRunView extends FrameLayout |
return super.performAccessibilityAction(host, action, args); |
} |
}); |
+ |
+ showSignInPage(); |
} |
@Override |
@@ -213,7 +232,12 @@ public class AccountFirstRunView extends FrameLayout |
public void onWindowVisibilityChanged(int visibility) { |
super.onWindowVisibilityChanged(visibility); |
if (visibility == View.VISIBLE) { |
- updateAccounts(); |
+ if (updateAccounts()) { |
+ // A new account has been added and the visibility has returned to us. |
+ // The updateAccounts function will have selected the new account. |
+ // Shortcut to confirm sign in page. |
+ showConfirmSignInPage(); |
+ } |
} |
} |
@@ -244,33 +268,20 @@ public class AccountFirstRunView extends FrameLayout |
/** |
* Changes the visuals slightly for when this view appears in the recent tabs page instead of |
* in first run. For example, the title text is changed as well as the button style. |
+ * This is currently used in the Recent Tabs Promo and the Enhanced Bookmark page. |
*/ |
- public void configureForRecentTabsPage() { |
+ public void configureForRecentTabsOrBookmarksPage() { |
mHorizontalModeEnabled = false; |
+ mShowSettingsSpan = false; |
setBackgroundResource(R.color.ntp_bg); |
- TextView title = (TextView) findViewById(R.id.title); |
- title.setText(R.string.sign_in_to_chrome); |
+ mTitle.setText(R.string.sign_in_to_chrome); |
- // Remove the border above the button, swap in a new button with a blue material background, |
- // and center the button. |
- View buttonBarSeparator = findViewById(R.id.button_bar_separator); |
- buttonBarSeparator.setVisibility(View.GONE); |
+ mCancelButtonTextId = R.string.cancel; |
+ setUpCancelButton(); |
- LinearLayout buttonContainer = (LinearLayout) findViewById(R.id.button_bar); |
- buttonContainer.setGravity(Gravity.CENTER_HORIZONTAL); |
- setPadding(0, 0, 0, getResources().getDimensionPixelOffset( |
- R.dimen.sign_in_promo_padding_bottom)); |
- |
- ButtonCompat positiveButton = new ButtonCompat(getContext(), |
- ApiCompatibilityUtils.getColor(getResources(), R.color.light_active_color)); |
- positiveButton.setTextColor(Color.WHITE); |
- positiveButton.setLayoutParams(new LinearLayout.LayoutParams( |
- LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); |
- |
- buttonContainer.removeView(mPositiveButton); |
- buttonContainer.addView(positiveButton); |
- mPositiveButton = positiveButton; |
+ setPadding(0, 0, 0, |
+ getResources().getDimensionPixelOffset(R.dimen.sign_in_promo_padding_bottom)); |
} |
/** |
@@ -281,9 +292,8 @@ public class AccountFirstRunView extends FrameLayout |
int experimentGroup = SigninManager.getAndroidSigninPromoExperimentGroup(); |
assert experimentGroup >= 0 && experimentGroup <= EXPERIMENT_MAX_VALUE; |
- TextView title = (TextView) findViewById(R.id.title); |
if ((experimentGroup & EXPERIMENT_TITLE_VARIANT_MASK) != 0) { |
- title.setText(R.string.make_chrome_yours); |
+ mTitle.setText(R.string.make_chrome_yours); |
} |
mDescriptionTextId = (experimentGroup & EXPERIMENT_SUMMARY_VARIANT_MASK) != 0 |
@@ -322,36 +332,21 @@ public class AccountFirstRunView extends FrameLayout |
} |
/** |
- * Tell the view whether or not the user can cancel account selection. In |
- * wizards, it makes sense to allow the user to skip account selection. |
- * However, in other settings-type contexts it does not make sense to allow |
- * this. |
- * |
- * @param canCancel Whether or not account selection can be canceled. |
- */ |
- public void setCanCancel(boolean canCancel) { |
- mNegativeButton.setVisibility(canCancel ? View.VISIBLE : View.GONE); |
- mPositiveButton.setGravity( |
- canCancel ? Gravity.END | Gravity.CENTER_VERTICAL : Gravity.CENTER); |
- } |
- |
- /** |
* Refresh the list of available system account. |
+ * @return Whether any new accounts were added (the first newly added account will now be |
+ * selected). |
*/ |
- private void updateAccounts() { |
- if (mSignedIn) return; |
- setButtonsEnabled(true); |
- |
- mAccountManagerHelper = AccountManagerHelper.get(getContext().getApplicationContext()); |
+ private boolean updateAccounts() { |
+ if (mSignedIn) return false; |
List<String> oldAccountNames = mAccountNames; |
mAccountNames = mAccountManagerHelper.getGoogleAccountNames(); |
int accountToSelect = 0; |
- if (mForcedAccountName != null) { |
+ if (isInForcedAccountMode()) { |
accountToSelect = mAccountNames.indexOf(mForcedAccountName); |
if (accountToSelect < 0) { |
mListener.onFailedToSetForcedAccount(mForcedAccountName); |
- return; |
+ return false; |
} |
} else { |
accountToSelect = getIndexOfNewElement( |
@@ -363,24 +358,14 @@ public class AccountFirstRunView extends FrameLayout |
mSpinner.setVisibility(View.VISIBLE); |
mArrayAdapter.addAll(mAccountNames); |
mArrayAdapter.add(mAddAnotherAccount); |
- mPositiveButton.setText(R.string.choose_account_sign_in); |
- mPositiveButton.setOnClickListener(new OnClickListener() { |
- @Override |
- public void onClick(View v) { |
- mListener.onAccountSelectionConfirmed(mAccountName); |
- } |
- }); |
+ |
+ setUpSignInButton(true); |
mDescriptionText.setText(mDescriptionTextId); |
+ |
} else { |
mSpinner.setVisibility(View.GONE); |
mArrayAdapter.add(mAddAnotherAccount); |
- mPositiveButton.setText(R.string.fre_no_accounts); |
- mPositiveButton.setOnClickListener(new OnClickListener() { |
- @Override |
- public void onClick(View v) { |
- mListener.onNewAccount(); |
- } |
- }); |
+ setUpSignInButton(false); |
mDescriptionText.setText(R.string.fre_no_account_choice_description); |
} |
@@ -390,6 +375,10 @@ public class AccountFirstRunView extends FrameLayout |
mSpinner.setSelection(accountToSelect); |
mAccountName = mArrayAdapter.getItem(accountToSelect).toString(); |
mImageCarousel.scrollTo(accountToSelect, false, false); |
+ |
+ return oldAccountNames != null |
+ && !(oldAccountNames.size() == mAccountNames.size() |
+ && oldAccountNames.containsAll(mAccountNames)); |
} |
/** |
@@ -444,45 +433,146 @@ public class AccountFirstRunView extends FrameLayout |
if (!mSignedIn) return; |
String name = null; |
- if (mIsChildAccount) name = mProfileData.getGivenName(mAccountName); |
- if (name == null) name = mProfileData.getFullName(mAccountName); |
+ if (mProfileData != null) { |
+ if (mIsChildAccount) name = mProfileData.getGivenName(mAccountName); |
+ if (name == null) name = mProfileData.getFullName(mAccountName); |
+ } |
if (name == null) name = mAccountName; |
String text = String.format(getResources().getString(R.string.fre_hi_name), name); |
- ((TextView) findViewById(R.id.title)).setText(text); |
+ mTitle.setText(text); |
} |
/** |
* Updates the view to show that sign in has completed. |
*/ |
public void switchToSignedMode() { |
+ showConfirmSignInPage(); |
+ } |
+ |
+ private void showSignInPage() { |
+ mSignedIn = false; |
+ mTitle.setText(R.string.sign_in_to_chrome); |
+ |
+ mSpinner.setEnabled(true); |
+ mSpinner.setBackground(mSpinnerBackground); |
+ mImageCarousel.setVisibility(VISIBLE); |
+ |
+ setUpCancelButton(); |
+ updateAccounts(); |
+ |
+ mImageCarousel.setSignedInMode(false); |
+ } |
+ |
+ private void showConfirmSignInPage() { |
mSignedIn = true; |
updateProfileName(); |
mSpinner.setEnabled(false); |
mSpinner.setBackground(null); |
- mPositiveButton.setText(getResources().getText(R.string.fre_done)); |
- mPositiveButton.setOnClickListener(new OnClickListener() { |
+ setUpConfirmButton(); |
+ setUpUndoButton(); |
+ |
+ if (mShowSettingsSpan) { |
+ ClickableSpan settingsSpan = new ClickableSpan() { |
+ @Override |
+ public void onClick(View widget) { |
+ mListener.onAccountSelected(mAccountName); |
+ mListener.onSettingsClicked(); |
+ } |
+ |
+ @Override |
+ public void updateDrawState(TextPaint textPaint) { |
+ textPaint.setColor(textPaint.linkColor); |
+ textPaint.setUnderlineText(false); |
+ } |
+ }; |
+ mDescriptionText.setText(SpanApplier.applySpans(getSignedInDescription(mIsChildAccount), |
+ new SpanInfo(SETTINGS_LINK_OPEN, SETTINGS_LINK_CLOSE, settingsSpan))); |
+ } else { |
+ // If we aren't showing the span, get rid of the LINK1 annotations. |
+ mDescriptionText.setText(getSignedInDescription(mIsChildAccount) |
+ .replace(SETTINGS_LINK_OPEN, "") |
+ .replace(SETTINGS_LINK_CLOSE, "")); |
+ } |
+ |
+ mImageCarousel.setVisibility(VISIBLE); |
+ mImageCarousel.setSignedInMode(true); |
+ } |
+ |
+ private void setUpCancelButton() { |
+ setNegativeButtonVisible(true); |
+ |
+ mNegativeButton.setText(getResources().getText(mCancelButtonTextId)); |
+ mNegativeButton.setOnClickListener(new OnClickListener() { |
@Override |
public void onClick(View v) { |
- mListener.onSigningInCompleted(mAccountName); |
+ setButtonsEnabled(false); |
+ mListener.onAccountSelectionCanceled(); |
} |
}); |
- mNegativeButton.setText(getResources().getText(R.string.fre_settings)); |
+ } |
+ |
+ private void setUpSignInButton(boolean hasAccounts) { |
+ if (hasAccounts) { |
+ mPositiveButton.setText(R.string.choose_account_sign_in); |
+ mPositiveButton.setOnClickListener(new OnClickListener() { |
+ @Override |
+ public void onClick(View v) { |
+ showConfirmSignInPage(); |
+ } |
+ }); |
+ } else { |
+ mPositiveButton.setText(R.string.fre_no_accounts); |
+ mPositiveButton.setOnClickListener(new OnClickListener() { |
+ @Override |
+ public void onClick(View v) { |
+ mListener.onNewAccount(); |
+ } |
+ }); |
+ } |
+ } |
+ |
+ private void setUpUndoButton() { |
+ setNegativeButtonVisible(!isInForcedAccountMode()); |
+ if (isInForcedAccountMode()) return; |
+ |
+ mNegativeButton.setText(getResources().getText(R.string.undo)); |
mNegativeButton.setOnClickListener(new OnClickListener() { |
@Override |
public void onClick(View v) { |
- mListener.onSettingsButtonClicked(mAccountName); |
+ showSignInPage(); |
+ } |
+ }); |
+ } |
+ |
+ private void setUpConfirmButton() { |
+ mPositiveButton.setText(getResources().getText(R.string.fre_accept)); |
+ mPositiveButton.setOnClickListener(new OnClickListener() { |
+ @Override |
+ public void onClick(View v) { |
+ mListener.onAccountSelected(mAccountName); |
+ mListener.onDoneClicked(); |
} |
}); |
- setButtonsEnabled(true); |
- String text = getResources().getString(R.string.fre_signed_in_description); |
- if (mIsChildAccount) { |
- text += "\n" + getResources().getString( |
- R.string.fre_signed_in_description_uca_addendum); |
+ } |
+ |
+ private void setNegativeButtonVisible(boolean enabled) { |
+ if (enabled) { |
+ mNegativeButton.setVisibility(View.VISIBLE); |
+ findViewById(R.id.positive_button_end_padding).setVisibility(View.GONE); |
+ } else { |
+ mNegativeButton.setVisibility(View.GONE); |
+ findViewById(R.id.positive_button_end_padding).setVisibility(View.INVISIBLE); |
+ } |
+ } |
+ |
+ private String getSignedInDescription(boolean childAccount) { |
+ if (childAccount) { |
+ return getResources().getString(R.string.fre_signed_in_description) + '\n' |
+ + getResources().getString(R.string.fre_signed_in_description_uca_addendum); |
+ } else { |
+ return getResources().getString(R.string.fre_signed_in_description); |
} |
- mDescriptionText.setText(text); |
- mImageCarousel.setVisibility(VISIBLE); |
- mImageCarousel.setSignedInMode(); |
} |
/** |