From 79b3d83368fafa2192444022128d29c8e810cff2 Mon Sep 17 00:00:00 2001 From: Vavassor Date: Mon, 13 Feb 2017 22:39:48 -0500 Subject: [PATCH] Hashtags are now also highlighted in the composer, similar to mentions. --- .../keylesspalace/tusky/ComposeActivity.java | 79 +++++++++++++++---- 1 file changed, 64 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java b/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java index 87acc21d..6c6d5ae4 100644 --- a/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java @@ -174,31 +174,72 @@ public class ComposeActivity extends AppCompatActivity { Snackbar.make(findViewById(R.id.activity_compose), stringId, Snackbar.LENGTH_LONG).show(); } - private static int findStartOfMention(String string, int fromIndex) { + private static class FindCharsResult { + public int charIndex; + public int stringIndex; + + public FindCharsResult() { + charIndex = -1; + stringIndex = -1; + } + } + + private static FindCharsResult findChars(String string, int fromIndex, char[] chars) { + FindCharsResult result = new FindCharsResult(); + final int length = string.length(); + for (int i = fromIndex; i < length; i++) { + char c = string.charAt(i); + for (int j = 0; j < chars.length; j++) { + if (chars[j] == c) { + result.charIndex = j; + result.stringIndex = i; + return result; + } + } + } + return result; + } + + private static FindCharsResult findStart(String string, int fromIndex, char[] chars) { final int length = string.length(); while (fromIndex < length) { - int at = string.indexOf('@', fromIndex); - if (at < 0) { + FindCharsResult found = findChars(string, fromIndex, chars); + int i = found.stringIndex; + if (i < 0) { break; - } else if (at == 0 || at >= 1 && Character.isWhitespace(string.codePointBefore(at))) { - return at; + } else if (i == 0 || i >= 1 && Character.isWhitespace(string.codePointBefore(i))) { + return found; } else { - fromIndex = at + 1; + fromIndex = i + 1; } } - return -1; + return new FindCharsResult(); + } + + private static int findEndOfHashtag(String string, int fromIndex) { + final int length = string.length(); + for (int i = fromIndex + 1; i < length;) { + int codepoint = string.codePointAt(i); + if (Character.isWhitespace(codepoint)) { + return i; + } else if (codepoint == '#') { + return -1; + } + i += Character.charCount(codepoint); + } + return length; } private static int findEndOfMention(String string, int fromIndex) { int atCount = 0; final int length = string.length(); - for (int i = fromIndex; i < length; ) { + for (int i = fromIndex + 1; i < length;) { int codepoint = string.codePointAt(i); if (Character.isWhitespace(codepoint)) { return i; } else if (codepoint == '@') { atCount += 1; - if (atCount > 2) { + if (atCount >= 2) { return -1; } } @@ -207,23 +248,31 @@ public class ComposeActivity extends AppCompatActivity { return length; } - private static void colourMentions(Spannable text, int colour) { + private static void highlightSpans(Spannable text, int colour) { // Strip all existing colour spans. int n = text.length(); ForegroundColorSpan[] oldSpans = text.getSpans(0, n, ForegroundColorSpan.class); for (int i = oldSpans.length - 1; i >= 0; i--) { text.removeSpan(oldSpans[i]); } - // Colour the mentions. + // Colour the mentions and hashtags. String string = text.toString(); int start; int end = 0; while (end < n) { - start = findStartOfMention(string, end); - if (start < 0 || start >= n) { + char[] chars = { '#', '@' }; + FindCharsResult found = findStart(string, end, chars); + start = found.stringIndex; + if (start < 0) { + break; + } + if (found.charIndex == 0) { + end = findEndOfHashtag(string, start); + } else if (found.charIndex == 1) { + end = findEndOfMention(string, start); + } else { break; } - end = findEndOfMention(string, start); if (end < 0) { break; } @@ -264,7 +313,7 @@ public class ComposeActivity extends AppCompatActivity { @Override public void afterTextChanged(Editable editable) { - colourMentions(editable, mentionColour); + highlightSpans(editable, mentionColour); } }; textEditor.addTextChangedListener(textEditorWatcher);