michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: package org.mozilla.gecko.sync.setup.activities; michael@0: michael@0: import java.util.Locale; michael@0: michael@0: import org.mozilla.gecko.background.common.GlobalConstants; michael@0: import org.mozilla.gecko.background.common.log.Logger; michael@0: import org.mozilla.gecko.sync.SyncConstants; michael@0: import org.mozilla.gecko.sync.setup.InvalidSyncKeyException; michael@0: michael@0: import android.content.Context; michael@0: import android.content.Intent; michael@0: import android.net.Uri; michael@0: import android.text.Html; michael@0: import android.text.SpannableString; michael@0: import android.text.Spanned; michael@0: import android.text.TextPaint; michael@0: import android.text.method.LinkMovementMethod; michael@0: import android.text.style.ClickableSpan; michael@0: import android.text.style.URLSpan; michael@0: import android.view.View; michael@0: import android.widget.TextView; michael@0: michael@0: public class ActivityUtils { michael@0: private static final String LOG_TAG = "ActivityUtils"; michael@0: michael@0: public static void prepareLogging() { michael@0: Logger.setThreadLogTag(SyncConstants.GLOBAL_LOG_TAG); michael@0: } michael@0: michael@0: /** michael@0: * Sync key should be a 26-character string, and can include arbitrary michael@0: * capitalization and hyphenation. michael@0: * michael@0: * @param key michael@0: * Sync key entered by user in account setup. michael@0: * @return Sync key in correct format (lower-case, no hyphens). michael@0: * @throws InvalidSyncKeyException michael@0: */ michael@0: public static String validateSyncKey(String key) throws InvalidSyncKeyException { michael@0: String charKey = key.trim().replace("-", "").toLowerCase(Locale.US); michael@0: if (!charKey.matches("^[abcdefghijkmnpqrstuvwxyz23456789]{26}$")) { michael@0: throw new InvalidSyncKeyException(); michael@0: } michael@0: return charKey; michael@0: } michael@0: michael@0: /** michael@0: * Open a URL in Fennec, if one is provided; or just open Fennec. michael@0: * michael@0: * @param context Android context. michael@0: * @param url to visit, or null to just open Fennec. michael@0: */ michael@0: public static void openURLInFennec(final Context context, final String url) { michael@0: Intent intent; michael@0: if (url != null) { michael@0: intent = new Intent(Intent.ACTION_VIEW); michael@0: intent.setData(Uri.parse(url)); michael@0: } else { michael@0: intent = new Intent(Intent.ACTION_MAIN); michael@0: } michael@0: intent.setClassName(GlobalConstants.BROWSER_INTENT_PACKAGE, GlobalConstants.BROWSER_INTENT_CLASS); michael@0: intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); michael@0: context.startActivity(intent); michael@0: } michael@0: michael@0: /** michael@0: * Open a clicked span in Fennec with the provided URL. michael@0: */ michael@0: public static class FennecClickableSpan extends ClickableSpan { michael@0: private final String url; michael@0: private final boolean underlining; michael@0: michael@0: public FennecClickableSpan(final String url, boolean underlining) { michael@0: this.url = url; michael@0: this.underlining = underlining; michael@0: } michael@0: michael@0: @Override michael@0: public void updateDrawState(TextPaint ds) { michael@0: super.updateDrawState(ds); michael@0: if (!this.underlining) { michael@0: ds.setUnderlineText(false); michael@0: } michael@0: } michael@0: michael@0: @Override michael@0: public void onClick(View widget) { michael@0: openURLInFennec(widget.getContext(), this.url); michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * Replace the contents of a plain text view with the provided text wrapped in a link. michael@0: * TODO: escape the URL! michael@0: */ michael@0: public static void linkTextView(TextView view, int text, int link) { michael@0: final Context context = view.getContext(); michael@0: linkTextView(view, context.getString(text), context.getString(link)); michael@0: } michael@0: michael@0: /** michael@0: * Replace the contents of a plain text view with the provided text wrapped in a link. michael@0: * TODO: escape the URL! michael@0: */ michael@0: public static void linkTextView(TextView view, String text, String url) { michael@0: view.setText("" + text + ""); michael@0: linkifyTextView(view, false); michael@0: } michael@0: michael@0: public static void linkifyTextView(TextView textView, boolean underlining) { michael@0: if (textView == null) { michael@0: Logger.warn(LOG_TAG, "Could not process links for view."); michael@0: return; michael@0: } michael@0: michael@0: textView.setMovementMethod(LinkMovementMethod.getInstance()); michael@0: michael@0: // Create spans. michael@0: final Spanned spanned = Html.fromHtml(textView.getText().toString()); michael@0: michael@0: // Replace the spans with Fennec-launching links. michael@0: SpannableString replaced = new SpannableString(spanned); michael@0: URLSpan[] spans = replaced.getSpans(0, replaced.length(), URLSpan.class); michael@0: for (URLSpan span : spans) { michael@0: final int start = replaced.getSpanStart(span); michael@0: final int end = replaced.getSpanEnd(span); michael@0: final int flags = replaced.getSpanFlags(span); michael@0: michael@0: replaced.removeSpan(span); michael@0: replaced.setSpan(new FennecClickableSpan(span.getURL(), underlining), start, end, flags); michael@0: } michael@0: michael@0: textView.setText(replaced); michael@0: } michael@0: }