Bug 959774 - Linkifying FxA setup elements. r=nalexander

This commit is contained in:
Richard Newman 2014-01-28 15:27:26 -08:00
parent 99693917c0
commit 9fcdad0a9d
7 changed files with 106 additions and 11 deletions

View File

@ -7,13 +7,12 @@ package org.mozilla.gecko.fxa.activities;
import org.mozilla.gecko.background.common.log.Logger;
import org.mozilla.gecko.background.fxa.FxAccountAgeLockoutHelper;
import org.mozilla.gecko.fxa.authenticator.FxAccountAuthenticator;
import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
import android.accounts.Account;
import android.app.Activity;
import android.content.Intent;
import android.os.SystemClock;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
@ -113,12 +112,13 @@ public abstract class FxAccountAbstractActivity extends Activity {
} else {
textView = (TextView) findViewById(id);
}
if (textView == null) {
Logger.warn(LOG_TAG, "Could not process links for view with id " + id + ".");
continue;
}
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setText(Html.fromHtml(textView.getText().toString()));
ActivityUtils.linkifyTextView(textView);
}
}

View File

@ -19,6 +19,7 @@ import org.mozilla.gecko.background.fxa.PasswordStretcher;
import org.mozilla.gecko.background.fxa.QuickPasswordStretcher;
import org.mozilla.gecko.fxa.FxAccountConstants;
import org.mozilla.gecko.fxa.activities.FxAccountSetupTask.FxAccountCreateAccountTask;
import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
import android.app.AlertDialog;
import android.app.Dialog;
@ -54,7 +55,13 @@ public class FxAccountCreateAccountActivity extends FxAccountAbstractSetupActivi
super.onCreate(icicle);
setContentView(R.layout.fxaccount_create_account);
linkifyTextViews(null, new int[] { R.id.policy });
TextView policyView = (TextView) ensureFindViewById(null, R.id.policy, "policy links");
final String linkTerms = getString(R.string.fxaccount_link_tos);
final String linkPrivacy = getString(R.string.fxaccount_link_pn);
final String linkedTOS = "<a href=\"" + linkTerms + "\">" + getString(R.string.fxaccount_policy_linktos) + "</a>";
final String linkedPN = "<a href=\"" + linkPrivacy + "\">" + getString(R.string.fxaccount_policy_linkprivacy) + "</a>";
policyView.setText(getString(R.string.fxaccount_policy_text, linkedTOS, linkedPN));
ActivityUtils.linkifyTextView(policyView);
emailEdit = (EditText) ensureFindViewById(null, R.id.email, "email edit");
passwordEdit = (EditText) ensureFindViewById(null, R.id.password, "password edit");

View File

@ -110,9 +110,13 @@
<!-- Firefox Account strings -->
<!ENTITY firefox.accounts 'Firefox Accounts'>
<!ENTITY fxaccount.label '&fxaccountBrand.fullName.label;'>
<!ENTITY fxaccount.policy 'By proceeding you agree with the &lt;a
href="http://mozilla.com"&gt;Terms of Service&lt;/a&gt; and &lt;a
href="http://mozilla.com"&gt;Privacy Policy&lt;/a&gt;.'>
<!ENTITY fxaccount.link.tos 'https://accounts.firefox.com/legal/terms'>
<!ENTITY fxaccount.link.pn 'https://accounts.firefox.com/legal/privacy'>
<!ENTITY fxaccount.policy.linktos 'Terms of Service'>
<!ENTITY fxaccount.policy.linkprivacy 'Privacy Notice'>
<!-- Localization note: &formatS1; is fxaccount.policy.linktos, &formatS2; is fxaccount.policy.linkprivacy, both hyperlinked. -->
<!ENTITY fxaccount.policy.text 'By proceeding you agree with the &formatS1; and &formatS2;.'>
<!ENTITY fxaccount.forgot.password 'Forgot password?'>
<!ENTITY fxaccount.create.account.button.label 'Create Account'>
<!ENTITY fxaccount.sign.in.button.label 'Sign In'>

View File

@ -74,7 +74,7 @@
<TextView
android:id="@+id/policy"
style="@style/FxAccountLinkifiedItem"
android:text="@string/fxaccount_policy" />
android:text="@string/fxaccount_policy_text" />
<LinearLayout style="@style/FxAccountSpacer" />

View File

@ -4,11 +4,28 @@
package org.mozilla.gecko.sync.setup.activities;
import java.util.Locale;
import org.mozilla.gecko.background.common.GlobalConstants;
import org.mozilla.gecko.background.common.log.Logger;
import org.mozilla.gecko.sync.SyncConstants;
import org.mozilla.gecko.sync.setup.InvalidSyncKeyException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.text.Html;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.URLSpan;
import android.view.View;
import android.widget.TextView;
public class ActivityUtils {
private static final String LOG_TAG = "ActivityUtils";
public static void prepareLogging() {
Logger.setThreadLogTag(SyncConstants.GLOBAL_LOG_TAG);
}
@ -23,10 +40,71 @@ public class ActivityUtils {
* @throws InvalidSyncKeyException
*/
public static String validateSyncKey(String key) throws InvalidSyncKeyException {
String charKey = key.trim().replace("-", "").toLowerCase();
String charKey = key.trim().replace("-", "").toLowerCase(Locale.US);
if (!charKey.matches("^[abcdefghijkmnpqrstuvwxyz23456789]{26}$")) {
throw new InvalidSyncKeyException();
}
return charKey;
}
public static void openURLInFennec(final Context context, final String url) {
final Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setClassName(GlobalConstants.BROWSER_INTENT_PACKAGE, GlobalConstants.BROWSER_INTENT_CLASS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setData(Uri.parse(url));
context.startActivity(intent);
}
/**
* Open a clicked span in Fennec with the provided URL.
*/
public static class FennecClickableSpan extends ClickableSpan {
private final String url;
public FennecClickableSpan(final String url) {
this.url = url;
}
@Override
public void onClick(View widget) {
openURLInFennec(widget.getContext(), this.url);
}
}
/**
* Replace the contents of a plain text view with the provided text wrapped in a link.
* TODO: escape the URL!
*/
public static void linkTextView(TextView view, int text, int link) {
final Context context = view.getContext();
final String url = context.getString(link);
view.setText("<a href=\"" + url + "\">" + context.getString(text) + "</a>");
ActivityUtils.linkifyTextView(view);
}
public static void linkifyTextView(TextView textView) {
if (textView == null) {
Logger.warn(LOG_TAG, "Could not process links for view.");
return;
}
textView.setMovementMethod(LinkMovementMethod.getInstance());
// Create spans.
final Spanned spanned = Html.fromHtml(textView.getText().toString());
// Replace the spans with Fennec-launching links.
SpannableString replaced = new SpannableString(spanned);
URLSpan[] spans = replaced.getSpans(0, replaced.length(), URLSpan.class);
for (URLSpan span : spans) {
final int start = replaced.getSpanStart(span);
final int end = replaced.getSpanEnd(span);
final int flags = replaced.getSpanFlags(span);
replaced.removeSpan(span);
replaced.setSpan(new FennecClickableSpan(span.getURL()), start, end, flags);
}
textView.setText(replaced);
}
}

View File

@ -3,6 +3,7 @@
android:icon="@drawable/fxaccount_icon"
android:label="Status"
android:clearTaskOnLaunch="true"
android:taskAffinity="@ANDROID_PACKAGE_NAME@.FXA"
android:name="org.mozilla.gecko.fxa.activities.FxAccountStatusActivity"
android:windowSoftInputMode="adjustResize">
<!-- Adding a launcher will make this activity appear on the
@ -18,6 +19,7 @@
android:icon="@drawable/fxaccount_icon"
android:label="Setup"
android:clearTaskOnLaunch="true"
android:taskAffinity="@ANDROID_PACKAGE_NAME@.FXA"
android:name="org.mozilla.gecko.fxa.activities.FxAccountGetStartedActivity"
android:windowSoftInputMode="adjustResize">
<!-- Adding a launcher will make this activity appear on the

View File

@ -102,7 +102,11 @@
<string name="firefox_accounts">&firefox.accounts;</string>
<string name="fxaccount_label">&fxaccount.label;</string>
<string name="fxaccount_policy">&fxaccount.policy;</string>
<string name="fxaccount_link_tos">&fxaccount.link.tos;</string>
<string name="fxaccount_link_pn">&fxaccount.link.pn;</string>
<string name="fxaccount_policy_text">&fxaccount.policy.text;</string>
<string name="fxaccount_policy_linktos">&fxaccount.policy.linktos;</string>
<string name="fxaccount_policy_linkprivacy">&fxaccount.policy.linkprivacy;</string>
<string name="fxaccount_forgot_password">&fxaccount.forgot.password;</string>
<string name="fxaccount_create_account_button_label">&fxaccount.create.account.button.label;</string>
<string name="fxaccount_sign_in_button_label">&fxaccount.sign.in.button.label;</string>