summaryrefslogtreecommitdiffstats
path: root/src/com/android/calendar/EventInfoFragment.java
diff options
context:
space:
mode:
authorSam Blitzstein <sblitz@google.com>2012-11-13 10:02:41 -0800
committerSam Blitzstein <sblitz@google.com>2012-11-15 14:30:10 -0800
commit7e19bf984bc280c0cc034adf1dfa8840c75a698d (patch)
treec3dc355674a9bc86629961f2025ac0bd5a416aee /src/com/android/calendar/EventInfoFragment.java
parentad83b9aa618d52952f98bf8d7ec876140e7fb404 (diff)
downloadandroid_packages_apps_Calendar-7e19bf984bc280c0cc034adf1dfa8840c75a698d.tar.gz
android_packages_apps_Calendar-7e19bf984bc280c0cc034adf1dfa8840c75a698d.tar.bz2
android_packages_apps_Calendar-7e19bf984bc280c0cc034adf1dfa8840c75a698d.zip
Added new notification actions for map and call.
Bug: 7525552 Change-Id: I6a175a270f4049897ee73c005f4f73420fc635d9
Diffstat (limited to 'src/com/android/calendar/EventInfoFragment.java')
-rw-r--r--src/com/android/calendar/EventInfoFragment.java328
1 files changed, 1 insertions, 327 deletions
diff --git a/src/com/android/calendar/EventInfoFragment.java b/src/com/android/calendar/EventInfoFragment.java
index 88e58355..d3caae0b 100644
--- a/src/com/android/calendar/EventInfoFragment.java
+++ b/src/com/android/calendar/EventInfoFragment.java
@@ -254,10 +254,6 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange
static final String CALENDARS_DUPLICATE_NAME_WHERE = Calendars.CALENDAR_DISPLAY_NAME + "=?";
static final String CALENDARS_VISIBLE_WHERE = Calendars.VISIBLE + "=?";
- private static final String NANP_ALLOWED_SYMBOLS = "()+-*#.";
- private static final int NANP_MIN_DIGITS = 7;
- private static final int NANP_MAX_DIGITS = 11;
-
private View mView;
@@ -320,8 +316,6 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange
private boolean mNoCrossFade = false; // Used to prevent repeated cross-fade
- private static final Pattern mWildcardPattern = Pattern.compile("^.*$");
-
ArrayList<Attendee> mAcceptedAttendees = new ArrayList<Attendee>();
ArrayList<Attendee> mDeclinedAttendees = new ArrayList<Attendee>();
ArrayList<Attendee> mTentativeAttendees = new ArrayList<Attendee>();
@@ -1233,7 +1227,7 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange
textView.setAutoLinkMask(0);
textView.setText(location.trim());
try {
- linkifyTextView(textView);
+ Utils.linkifyTextView(textView, true);
} catch (Exception ex) {
// unexpected
Log.e(TAG, "Linkification failed", ex);
@@ -1337,326 +1331,6 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange
return;
}
- /**
- * Finds North American Numbering Plan (NANP) phone numbers in the input text.
- *
- * @param text The text to scan.
- * @return A list of [start, end) pairs indicating the positions of phone numbers in the input.
- */
- // @VisibleForTesting
- static int[] findNanpPhoneNumbers(CharSequence text) {
- ArrayList<Integer> list = new ArrayList<Integer>();
-
- int startPos = 0;
- int endPos = text.length() - NANP_MIN_DIGITS + 1;
- if (endPos < 0) {
- return new int[] {};
- }
-
- /*
- * We can't just strip the whitespace out and crunch it down, because the whitespace
- * is significant. March through, trying to figure out where numbers start and end.
- */
- while (startPos < endPos) {
- // skip whitespace
- while (Character.isWhitespace(text.charAt(startPos)) && startPos < endPos) {
- startPos++;
- }
- if (startPos == endPos) {
- break;
- }
-
- // check for a match at this position
- int matchEnd = findNanpMatchEnd(text, startPos);
- if (matchEnd > startPos) {
- list.add(startPos);
- list.add(matchEnd);
- startPos = matchEnd; // skip past match
- } else {
- // skip to next whitespace char
- while (!Character.isWhitespace(text.charAt(startPos)) && startPos < endPos) {
- startPos++;
- }
- }
- }
-
- int[] result = new int[list.size()];
- for (int i = list.size() - 1; i >= 0; i--) {
- result[i] = list.get(i);
- }
- return result;
- }
-
- /**
- * Checks to see if there is a valid phone number in the input, starting at the specified
- * offset. If so, the index of the last character + 1 is returned. The input is assumed
- * to begin with a non-whitespace character.
- *
- * @return Exclusive end position, or -1 if not a match.
- */
- private static int findNanpMatchEnd(CharSequence text, int startPos) {
- /*
- * A few interesting cases:
- * 94043 # too short, ignore
- * 123456789012 # too long, ignore
- * +1 (650) 555-1212 # 11 digits, spaces
- * (650) 555 5555 # Second space, only when first is present.
- * (650) 555-1212, (650) 555-1213 # two numbers, return first
- * 1-650-555-1212 # 11 digits with leading '1'
- * *#650.555.1212#*! # 10 digits, include #*, ignore trailing '!'
- * 555.1212 # 7 digits
- *
- * For the most part we want to break on whitespace, but it's common to leave a space
- * between the initial '1' and/or after the area code.
- */
-
- // Check for "tel:" URI prefix.
- if (text.length() > startPos+4
- && text.subSequence(startPos, startPos+4).toString().equalsIgnoreCase("tel:")) {
- startPos += 4;
- }
-
- int endPos = text.length();
- int curPos = startPos;
- int foundDigits = 0;
- char firstDigit = 'x';
- boolean foundWhiteSpaceAfterAreaCode = false;
-
- while (curPos <= endPos) {
- char ch;
- if (curPos < endPos) {
- ch = text.charAt(curPos);
- } else {
- ch = 27; // fake invalid symbol at end to trigger loop break
- }
-
- if (Character.isDigit(ch)) {
- if (foundDigits == 0) {
- firstDigit = ch;
- }
- foundDigits++;
- if (foundDigits > NANP_MAX_DIGITS) {
- // too many digits, stop early
- return -1;
- }
- } else if (Character.isWhitespace(ch)) {
- if ( (firstDigit == '1' && foundDigits == 4) ||
- (foundDigits == 3)) {
- foundWhiteSpaceAfterAreaCode = true;
- } else if (firstDigit == '1' && foundDigits == 1) {
- } else if (foundWhiteSpaceAfterAreaCode
- && ( (firstDigit == '1' && (foundDigits == 7)) || (foundDigits == 6))) {
- } else {
- break;
- }
- } else if (NANP_ALLOWED_SYMBOLS.indexOf(ch) == -1) {
- break;
- }
- // else it's an allowed symbol
-
- curPos++;
- }
-
- if ((firstDigit != '1' && (foundDigits == 7 || foundDigits == 10)) ||
- (firstDigit == '1' && foundDigits == 11)) {
- // match
- return curPos;
- }
-
- return -1;
- }
-
- private static int indexFirstNonWhitespaceChar(CharSequence str) {
- for (int i = 0; i < str.length(); i++) {
- if (!Character.isWhitespace(str.charAt(i))) {
- return i;
- }
- }
- return -1;
- }
-
- private static int indexLastNonWhitespaceChar(CharSequence str) {
- for (int i = str.length() - 1; i >= 0; i--) {
- if (!Character.isWhitespace(str.charAt(i))) {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * Replaces stretches of text that look like addresses and phone numbers with clickable
- * links.
- * <p>
- * This is really just an enhanced version of Linkify.addLinks().
- */
- private static void linkifyTextView(TextView textView) {
- /*
- * If the text includes a street address like "1600 Amphitheater Parkway, 94043",
- * the current Linkify code will identify "94043" as a phone number and invite
- * you to dial it (and not provide a map link for the address). For outside US,
- * use Linkify result iff it spans the entire text. Otherwise send the user to maps.
- */
- String defaultPhoneRegion = System.getProperty("user.region", "US");
- if (!defaultPhoneRegion.equals("US")) {
- CharSequence origText = textView.getText();
- Linkify.addLinks(textView, Linkify.ALL);
-
- // If Linkify links the entire text, use that result.
- if (textView.getText() instanceof Spannable) {
- Spannable spanText = (Spannable) textView.getText();
- URLSpan[] spans = spanText.getSpans(0, spanText.length(), URLSpan.class);
- if (spans.length == 1) {
- int linkStart = spanText.getSpanStart(spans[0]);
- int linkEnd = spanText.getSpanEnd(spans[0]);
- if (linkStart <= indexFirstNonWhitespaceChar(origText) &&
- linkEnd >= indexLastNonWhitespaceChar(origText) + 1) {
- return;
- }
- }
- }
-
- // Otherwise default to geo.
- textView.setText(origText);
- Linkify.addLinks(textView, mWildcardPattern, "geo:0,0?q=");
- return;
- }
-
- /*
- * For within US, we want to have better recognition of phone numbers without losing
- * any of the existing annotations. Ideally this would be addressed by improving Linkify.
- * For now we manage it as a second pass over the text.
- *
- * URIs and e-mail addresses are pretty easy to pick out of text. Phone numbers
- * are a bit tricky because they have radically different formats in different
- * countries, in terms of both the digits and the way in which they are commonly
- * written or presented (e.g. the punctuation and spaces in "(650) 555-1212").
- * The expected format of a street address is defined in WebView.findAddress(). It's
- * pretty narrowly defined, so it won't often match.
- *
- * The RFC 3966 specification defines the format of a "tel:" URI.
- *
- * Start by letting Linkify find anything that isn't a phone number. We have to let it
- * run first because every invocation removes all previous URLSpan annotations.
- *
- * Ideally we'd use the external/libphonenumber routines, but those aren't available
- * to unbundled applications.
- */
- boolean linkifyFoundLinks = Linkify.addLinks(textView,
- Linkify.ALL & ~(Linkify.PHONE_NUMBERS));
-
- /*
- * Search for phone numbers.
- *
- * Some URIs contain strings of digits that look like phone numbers. If both the URI
- * scanner and the phone number scanner find them, we want the URI link to win. Since
- * the URI scanner runs first, we just need to avoid creating overlapping spans.
- */
- CharSequence text = textView.getText();
- int[] phoneSequences = findNanpPhoneNumbers(text);
-
- /*
- * If the contents of the TextView are already Spannable (which will be the case if
- * Linkify found stuff, but might not be otherwise), we can just add annotations
- * to what's there. If it's not, and we find phone numbers, we need to convert it to
- * a Spannable form. (This mimics the behavior of Linkable.addLinks().)
- */
- Spannable spanText;
- if (text instanceof SpannableString) {
- spanText = (SpannableString) text;
- } else {
- spanText = SpannableString.valueOf(text);
- }
-
- /*
- * Get a list of any spans created by Linkify, for the overlapping span check.
- */
- URLSpan[] existingSpans = spanText.getSpans(0, spanText.length(), URLSpan.class);
-
- /*
- * Insert spans for the numbers we found. We generate "tel:" URIs.
- */
- int phoneCount = 0;
- for (int match = 0; match < phoneSequences.length / 2; match++) {
- int start = phoneSequences[match*2];
- int end = phoneSequences[match*2 + 1];
-
- if (spanWillOverlap(spanText, existingSpans, start, end)) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- CharSequence seq = text.subSequence(start, end);
- Log.v(TAG, "Not linkifying " + seq + " as phone number due to overlap");
- }
- continue;
- }
-
- /*
- * The Linkify code takes the matching span and strips out everything that isn't a
- * digit or '+' sign. We do the same here. Extension numbers will get appended
- * without a separator, but the dialer wasn't doing anything useful with ";ext="
- * anyway.
- */
-
- //String dialStr = phoneUtil.format(match.number(),
- // PhoneNumberUtil.PhoneNumberFormat.RFC3966);
- StringBuilder dialBuilder = new StringBuilder();
- for (int i = start; i < end; i++) {
- char ch = spanText.charAt(i);
- if (ch == '+' || Character.isDigit(ch)) {
- dialBuilder.append(ch);
- }
- }
- URLSpan span = new URLSpan("tel:" + dialBuilder.toString());
-
- spanText.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- phoneCount++;
- }
-
- if (phoneCount != 0) {
- // If we had to "upgrade" to Spannable, store the object into the TextView.
- if (spanText != text) {
- textView.setText(spanText);
- }
-
- // Linkify.addLinks() sets the TextView movement method if it finds any links. We
- // want to do the same here. (This is cloned from Linkify.addLinkMovementMethod().)
- MovementMethod mm = textView.getMovementMethod();
-
- if ((mm == null) || !(mm instanceof LinkMovementMethod)) {
- if (textView.getLinksClickable()) {
- textView.setMovementMethod(LinkMovementMethod.getInstance());
- }
- }
- }
-
- if (!linkifyFoundLinks && phoneCount == 0) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "No linkification matches, using geo default");
- }
- Linkify.addLinks(textView, mWildcardPattern, "geo:0,0?q=");
- }
- }
-
- /**
- * Determines whether a new span at [start,end) will overlap with any existing span.
- */
- private static boolean spanWillOverlap(Spannable spanText, URLSpan[] spanList, int start,
- int end) {
- if (start == end) {
- // empty span, ignore
- return false;
- }
- for (URLSpan span : spanList) {
- int existingStart = spanText.getSpanStart(span);
- int existingEnd = spanText.getSpanEnd(span);
- if ((start >= existingStart && start < existingEnd) ||
- end > existingStart && end <= existingEnd) {
- return true;
- }
- }
-
- return false;
- }
-
private void sendAccessibilityEvent() {
AccessibilityManager am =
(AccessibilityManager) getActivity().getSystemService(Service.ACCESSIBILITY_SERVICE);