Changes mention and tag highlighting in the composer to use Mastodon's regex. Closes #145 Also, does some haphazard cleanup.

This commit is contained in:
Vavassor 2017-07-01 20:32:35 -04:00
parent 6b0ae5be95
commit 5d621cecda
7 changed files with 83 additions and 60 deletions

View file

@ -244,7 +244,6 @@ public class AccountActivity extends BaseActivity {
String subtitle = String.format(getString(R.string.status_username_format),
account.username);
getSupportActionBar().setSubtitle(subtitle);
}
boolean useCustomTabs = PreferenceManager.getDefaultSharedPreferences(this)

View file

@ -170,7 +170,8 @@ public class EditProfileActivity extends BaseActivity {
Account me = response.body();
priorDisplayName = me.getDisplayName();
priorNote = me.note.toString();
CircularImageView avatar = (CircularImageView) findViewById(R.id.edit_profile_avatar_preview);
CircularImageView avatar =
(CircularImageView) findViewById(R.id.edit_profile_avatar_preview);
ImageView header = (ImageView) findViewById(R.id.edit_profile_header_preview);
displayNameEditText.setText(priorDisplayName);

View file

@ -16,6 +16,7 @@
package com.keylesspalace.tusky.json;
import android.text.Spanned;
import android.text.SpannedString;
import com.emojione.Emojione;
import com.google.gson.JsonDeserializationContext;
@ -28,7 +29,13 @@ import java.lang.reflect.Type;
public class SpannedTypeAdapter implements JsonDeserializer<Spanned> {
@Override
public Spanned deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return HtmlUtils.fromHtml(Emojione.shortnameToUnicode(json.getAsString(), false));
public Spanned deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
String string = json.getAsString();
if (string != null) {
return HtmlUtils.fromHtml(Emojione.shortnameToUnicode(string, false));
} else {
return new SpannedString("");
}
}
}

View file

@ -190,7 +190,10 @@ public interface MastodonApi {
@FormUrlEncoded
@POST("api/v1/reports")
Call<ResponseBody> report(@Field("account_id") String accountId, @Field("status_ids[]") List<String> statusIds, @Field("comment") String comment);
Call<ResponseBody> report(
@Field("account_id") String accountId,
@Field("status_ids[]") List<String> statusIds,
@Field("comment") String comment);
@GET("api/v1/search")
Call<SearchResults> search(@Query("q") String q, @Query("resolve") Boolean resolve);

View file

@ -47,8 +47,8 @@ public class LinkHelper {
}
public static void setClickableText(TextView view, Spanned content,
@Nullable Status.Mention[] mentions, boolean useCustomTabs,
final LinkListener listener) {
@Nullable Status.Mention[] mentions, boolean useCustomTabs,
final LinkListener listener) {
SpannableStringBuilder builder = new SpannableStringBuilder(content);
URLSpan[] urlSpans = content.getSpans(0, content.length(), URLSpan.class);
for (URLSpan span : urlSpans) {

View file

@ -41,7 +41,7 @@ import com.squareup.picasso.Target;
import org.json.JSONArray;
import org.json.JSONException;
public class NotificationMaker {
class NotificationMaker {
public static final String TAG = "NotificationMaker";
@ -89,10 +89,12 @@ public class NotificationMaker {
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT);
Intent deleteIntent = new Intent(context, NotificationClearBroadcastReceiver.class);
PendingIntent deletePendingIntent = PendingIntent.getBroadcast(context, 0, deleteIntent, PendingIntent.FLAG_CANCEL_CURRENT);
PendingIntent deletePendingIntent = PendingIntent.getBroadcast(context, 0, deleteIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_notify)
@ -104,15 +106,16 @@ public class NotificationMaker {
builder.setContentTitle(titleForType(context, body))
.setContentText(truncateWithEllipses(bodyForType(body), 40));
Target mTarget = new Target() {
Target target = new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
builder.setLargeIcon(bitmap);
setupPreferences(preferences, builder);
((NotificationManager) (context.getSystemService(Context.NOTIFICATION_SERVICE)))
.notify(notifyId, builder.build());
NotificationManager notificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notifyId, builder.build());
}
@Override
@ -126,12 +129,15 @@ public class NotificationMaker {
.load(body.account.avatar)
.placeholder(R.drawable.avatar_default)
.transform(new RoundedTransformation(7, 0))
.into(mTarget);
.into(target);
} else {
setupPreferences(preferences, builder);
try {
builder.setContentTitle(String.format(context.getString(R.string.notification_title_summary), currentNotifications.length()))
.setContentText(truncateWithEllipses(joinNames(context, currentNotifications), 40));
String format = context.getString(R.string.notification_title_summary);
String title = String.format(format, currentNotifications.length());
String text = truncateWithEllipses(joinNames(context, currentNotifications), 40);
builder.setContentTitle(title)
.setContentText(text);
} catch (JSONException e) {
Log.d(TAG, Log.getStackTraceString(e));
}
@ -142,26 +148,23 @@ public class NotificationMaker {
builder.setCategory(android.app.Notification.CATEGORY_SOCIAL);
}
((NotificationManager) (context.getSystemService(Context.NOTIFICATION_SERVICE)))
.notify(notifyId, builder.build());
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notifyId, builder.build());
}
private static boolean filterNotification(SharedPreferences preferences,
Notification notification) {
Notification notification) {
switch (notification.type) {
default:
case MENTION: {
case MENTION:
return preferences.getBoolean("notificationFilterMentions", true);
}
case FOLLOW: {
case FOLLOW:
return preferences.getBoolean("notificationFilterFollows", true);
}
case REBLOG: {
case REBLOG:
return preferences.getBoolean("notificationFilterReblogs", true);
}
case FAVOURITE: {
case FAVOURITE:
return preferences.getBoolean("notificationFilterFavourites", true);
}
}
}
@ -174,7 +177,7 @@ public class NotificationMaker {
}
private static void setupPreferences(SharedPreferences preferences,
NotificationCompat.Builder builder) {
NotificationCompat.Builder builder) {
if (preferences.getBoolean("notificationAlertSound", true)) {
builder.setSound(Settings.System.DEFAULT_NOTIFICATION_URI);
}
@ -191,11 +194,14 @@ public class NotificationMaker {
@Nullable
private static String joinNames(Context context, JSONArray array) throws JSONException {
if (array.length() > 3) {
return String.format(context.getString(R.string.notification_summary_large), array.get(0), array.get(1), array.get(2), array.length() - 3);
return String.format(context.getString(R.string.notification_summary_large),
array.get(0), array.get(1), array.get(2), array.length() - 3);
} else if (array.length() == 3) {
return String.format(context.getString(R.string.notification_summary_medium), array.get(0), array.get(1), array.get(2));
return String.format(context.getString(R.string.notification_summary_medium),
array.get(0), array.get(1), array.get(2));
} else if (array.length() == 2) {
return String.format(context.getString(R.string.notification_summary_small), array.get(0), array.get(1));
return String.format(context.getString(R.string.notification_summary_small),
array.get(0), array.get(1));
}
return null;
@ -205,13 +211,17 @@ public class NotificationMaker {
private static String titleForType(Context context, Notification notification) {
switch (notification.type) {
case MENTION:
return String.format(context.getString(R.string.notification_mention_format), notification.account.getDisplayName());
return String.format(context.getString(R.string.notification_mention_format),
notification.account.getDisplayName());
case FOLLOW:
return String.format(context.getString(R.string.notification_follow_format), notification.account.getDisplayName());
return String.format(context.getString(R.string.notification_follow_format),
notification.account.getDisplayName());
case FAVOURITE:
return String.format(context.getString(R.string.notification_favourite_format), notification.account.getDisplayName());
return String.format(context.getString(R.string.notification_favourite_format),
notification.account.getDisplayName());
case REBLOG:
return String.format(context.getString(R.string.notification_reblog_format), notification.account.getDisplayName());
return String.format(context.getString(R.string.notification_reblog_format),
notification.account.getDisplayName());
}
return null;
}
@ -226,7 +236,6 @@ public class NotificationMaker {
case REBLOG:
return notification.status.content.toString();
}
return null;
}
}

View file

@ -19,7 +19,17 @@ import android.text.Spannable;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SpanUtils {
private static final String TAG_REGEX = "(?:^|[^/)\\w])#([\\w_]*[\\p{Alpha}_][\\w_]*)";
private static Pattern TAG_PATTERN = Pattern.compile(TAG_REGEX, Pattern.CASE_INSENSITIVE);
private static final String MENTION_REGEX =
"(?:^|[^/[:word:]])@([a-z0-9_]+(?:@[a-z0-9\\.\\-]+[a-z0-9]+)?)";
private static Pattern MENTION_PATTERN =
Pattern.compile(MENTION_REGEX, Pattern.CASE_INSENSITIVE);
private static class FindCharsResult {
int charIndex;
int stringIndex;
@ -63,35 +73,29 @@ public class SpanUtils {
}
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);
Matcher matcher = TAG_PATTERN.matcher(string);
if (fromIndex >= 1) {
fromIndex--;
}
boolean found = matcher.find(fromIndex);
if (found) {
return matcher.end();
} else {
return -1;
}
return length;
}
private static int findEndOfMention(String string, int fromIndex) {
int atCount = 0;
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 == '@') {
atCount += 1;
if (atCount >= 2) {
return -1;
}
}
i += Character.charCount(codepoint);
Matcher matcher = MENTION_PATTERN.matcher(string);
if (fromIndex >= 1) {
fromIndex--;
}
boolean found = matcher.find(fromIndex);
if (found) {
return matcher.end();
} else {
return -1;
}
return length;
}
public static void highlightSpans(Spannable text, int colour) {