Replaced the regex gunk in the composer with something more readable and more reliable.
Also, put in a fix for a crash related to failing while loading the vector image for the media picker button.
This commit is contained in:
parent
22a2a31afe
commit
f14973a6d4
6 changed files with 54 additions and 46 deletions
|
@ -87,7 +87,6 @@ public class ComposeActivity extends AppCompatActivity {
|
||||||
private static final int STATUS_MEDIA_SIZE_LIMIT = 4000000; // 4MB
|
private static final int STATUS_MEDIA_SIZE_LIMIT = 4000000; // 4MB
|
||||||
private static final int MEDIA_PICK_RESULT = 1;
|
private static final int MEDIA_PICK_RESULT = 1;
|
||||||
private static final int PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 1;
|
private static final int PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 1;
|
||||||
private static final Pattern mentionPattern = Pattern.compile("\\B@[^\\s@]+@?[^\\s@]+");
|
|
||||||
|
|
||||||
private String inReplyToId;
|
private String inReplyToId;
|
||||||
private String domain;
|
private String domain;
|
||||||
|
@ -175,9 +174,37 @@ public class ComposeActivity extends AppCompatActivity {
|
||||||
Snackbar.make(findViewById(R.id.activity_compose), stringId, Snackbar.LENGTH_LONG).show();
|
Snackbar.make(findViewById(R.id.activity_compose), stringId, Snackbar.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Interval {
|
private static int findStartOfMention(String string, int fromIndex) {
|
||||||
public int start;
|
final int length = string.length();
|
||||||
public int end;
|
while (fromIndex < length) {
|
||||||
|
int at = string.indexOf('@', fromIndex);
|
||||||
|
if (at < 0) {
|
||||||
|
break;
|
||||||
|
} else if (at == 0 || at >= 1 && Character.isWhitespace(string.codePointBefore(at))) {
|
||||||
|
return at;
|
||||||
|
} else {
|
||||||
|
fromIndex = at + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int findEndOfMention(String string, int fromIndex) {
|
||||||
|
int atCount = 0;
|
||||||
|
final int length = string.length();
|
||||||
|
for (int i = fromIndex; i < length; ) {
|
||||||
|
int codepoint = string.codePointAt(i);
|
||||||
|
if (Character.isWhitespace(codepoint)) {
|
||||||
|
return i;
|
||||||
|
} else if (codepoint == '@') {
|
||||||
|
atCount += 1;
|
||||||
|
if (atCount > 2) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i += Character.charCount(codepoint);
|
||||||
|
}
|
||||||
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void colourMentions(Spannable text, int colour) {
|
private static void colourMentions(Spannable text, int colour) {
|
||||||
|
@ -187,44 +214,20 @@ public class ComposeActivity extends AppCompatActivity {
|
||||||
for (int i = oldSpans.length - 1; i >= 0; i--) {
|
for (int i = oldSpans.length - 1; i >= 0; i--) {
|
||||||
text.removeSpan(oldSpans[i]);
|
text.removeSpan(oldSpans[i]);
|
||||||
}
|
}
|
||||||
// Match a list of new colour spans.
|
// Colour the mentions.
|
||||||
List<Interval> intervals = new ArrayList<>();
|
String string = text.toString();
|
||||||
Matcher matcher = mentionPattern.matcher(text);
|
int start;
|
||||||
while (matcher.find()) {
|
int end = 0;
|
||||||
Interval interval = new Interval();
|
while (end < n) {
|
||||||
interval.start = matcher.start();
|
start = findStartOfMention(string, end);
|
||||||
interval.end = matcher.end();
|
if (start < 0 || start >= n) {
|
||||||
intervals.add(interval);
|
break;
|
||||||
}
|
|
||||||
// Make sure intervals don't overlap.
|
|
||||||
Collections.sort(intervals, new Comparator<Interval>() {
|
|
||||||
@Override
|
|
||||||
public int compare(Interval a, Interval b) {
|
|
||||||
return a.start - b.start;
|
|
||||||
}
|
}
|
||||||
});
|
end = findEndOfMention(string, start);
|
||||||
for (int i = 0, j = 0; i < intervals.size() - 1; i++, j++) {
|
if (end < 0) {
|
||||||
if (j != 0) {
|
break;
|
||||||
Interval a = intervals.get(j - 1);
|
|
||||||
Interval b = intervals.get(i);
|
|
||||||
if (a.start <= b.end) {
|
|
||||||
while (j != 0 && a.start <= b.end) {
|
|
||||||
a = intervals.get(j - 1);
|
|
||||||
b = intervals.get(i);
|
|
||||||
a.end = Math.max(a.end, b.end);
|
|
||||||
a.start = Math.min(a.start, b.start);
|
|
||||||
j--;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
intervals.set(j, b);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
intervals.set(j, intervals.get(i));
|
|
||||||
}
|
}
|
||||||
}
|
text.setSpan(new ForegroundColorSpan(colour), start, end,
|
||||||
// Finally, set the spans.
|
|
||||||
for (Interval interval : intervals) {
|
|
||||||
text.setSpan(new ForegroundColorSpan(colour), interval.start, interval.end,
|
|
||||||
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -508,10 +511,12 @@ public class ComposeActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private void enableMediaPicking() {
|
private void enableMediaPicking() {
|
||||||
mediaPick.setEnabled(true);
|
mediaPick.setEnabled(true);
|
||||||
|
mediaPick.setImageResource(R.drawable.ic_media);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void disableMediaPicking() {
|
private void disableMediaPicking() {
|
||||||
mediaPick.setEnabled(false);
|
mediaPick.setEnabled(false);
|
||||||
|
mediaPick.setImageResource(R.drawable.ic_media_disabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addMediaToQueue(QueuedMedia.Type type, Bitmap preview, Uri uri, long mediaSize) {
|
private void addMediaToQueue(QueuedMedia.Type type, Bitmap preview, Uri uri, long mediaSize) {
|
||||||
|
|
5
app/src/main/res/color/media_button_dark.xml
Normal file
5
app/src/main/res/color/media_button_dark.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:color="#8F8F8F" android:state_enabled="false" />
|
||||||
|
<item android:color="#FFFFFF" />
|
||||||
|
</selector>
|
|
@ -1,5 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:state_enabled="true" android:drawable="@drawable/ic_media" />
|
|
||||||
<item android:state_enabled="false" android:drawable="@drawable/ic_media_disabled" />
|
|
||||||
</selector>
|
|
|
@ -14,8 +14,9 @@
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
app:srcCompat="@drawable/media_selector"
|
app:srcCompat="@drawable/ic_media"
|
||||||
style="?attr/image_button_style"
|
style="?attr/image_button_style"
|
||||||
|
android:tint="?attr/compose_media_button_tint"
|
||||||
android:id="@+id/compose_photo_pick"
|
android:id="@+id/compose_photo_pick"
|
||||||
android:layout_marginLeft="8dp" />
|
android:layout_marginLeft="8dp" />
|
||||||
|
|
||||||
|
|
|
@ -21,5 +21,6 @@
|
||||||
<attr name="status_divider_color" format="reference|color" />
|
<attr name="status_divider_color" format="reference|color" />
|
||||||
<attr name="tab_page_margin_color" format="reference|color" />
|
<attr name="tab_page_margin_color" format="reference|color" />
|
||||||
<attr name="account_header_background_color" format="reference|color" />
|
<attr name="account_header_background_color" format="reference|color" />
|
||||||
|
<attr name="compose_media_button_tint" format="reference|color" />
|
||||||
|
|
||||||
</resources>
|
</resources>
|
|
@ -29,6 +29,7 @@
|
||||||
<item name="status_divider_color">@color/status_divider_dark</item>
|
<item name="status_divider_color">@color/status_divider_dark</item>
|
||||||
<item name="tab_page_margin_color">@color/tab_page_margin_dark</item>
|
<item name="tab_page_margin_color">@color/tab_page_margin_dark</item>
|
||||||
<item name="account_header_background_color">@color/account_header_background_dark</item>
|
<item name="account_header_background_color">@color/account_header_background_dark</item>
|
||||||
|
<item name="compose_media_button_tint">@color/media_button_dark</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppTheme.ImageButton.Dark" parent="@style/Widget.AppCompat.Button.Borderless.Colored">
|
<style name="AppTheme.ImageButton.Dark" parent="@style/Widget.AppCompat.Button.Borderless.Colored">
|
||||||
|
|
Loading…
Add table
Reference in a new issue