diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/UserKey.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/UserKey.java index 1c31834f7..35ca8567e 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/UserKey.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/UserKey.java @@ -119,7 +119,8 @@ public class UserKey implements Comparable, Parcelable { public static UserKey valueOf(@Nullable String str) { if (str == null) return null; boolean escaping = false, idFinished = false; - StringBuilder idBuilder = new StringBuilder(), hostBuilder = new StringBuilder(); + StringBuilder idBuilder = new StringBuilder(str.length()), + hostBuilder = new StringBuilder(str.length()); for (int i = 0, j = str.length(); i < j; i++) { final char ch = str.charAt(i); boolean append = false; diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/ComposeActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/ComposeActivity.java index 6a92f33dc..845eebd4c 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/ComposeActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/ComposeActivity.java @@ -71,6 +71,7 @@ import android.text.TextUtils; import android.text.TextWatcher; import android.text.style.ImageSpan; import android.text.style.SuggestionSpan; +import android.text.style.URLSpan; import android.text.style.UpdateAppearance; import android.util.Log; import android.view.ActionMode; @@ -119,6 +120,7 @@ import org.mariotaku.twidere.model.ParcelableMediaUpdate; import org.mariotaku.twidere.model.ParcelableStatus; import org.mariotaku.twidere.model.ParcelableStatusUpdate; import org.mariotaku.twidere.model.ParcelableUser; +import org.mariotaku.twidere.model.ParcelableUserMention; import org.mariotaku.twidere.model.UserKey; import org.mariotaku.twidere.model.draft.UpdateStatusActionExtra; import org.mariotaku.twidere.model.util.ParcelableAccountUtils; @@ -132,6 +134,7 @@ import org.mariotaku.twidere.util.AsyncTaskUtils; import org.mariotaku.twidere.util.DataStoreUtils; import org.mariotaku.twidere.util.EditTextEnterHandler; import org.mariotaku.twidere.util.EditTextEnterHandler.EnterListener; +import org.mariotaku.twidere.util.HtmlSpanBuilder; import org.mariotaku.twidere.util.IntentUtils; import org.mariotaku.twidere.util.KeyboardShortcutsHandler; import org.mariotaku.twidere.util.MediaLoaderWrapper; @@ -1075,20 +1078,34 @@ public class ComposeActivity extends BaseActivity implements OnMenuItemClickList final String myScreenName = DataStoreUtils.getAccountScreenName(this, status.account_key); if (TextUtils.isEmpty(myScreenName)) return false; int selectionStart = 0; + final Collection mentions = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); mEditText.append("@" + status.user_screen_name + " "); // If replying status from current user, just exclude it's screen name from selection. if (!status.account_key.equals(status.user_key)) { selectionStart = mEditText.length(); } if (status.is_retweet) { - mEditText.append("@" + status.retweeted_by_user_screen_name + " "); + mentions.add(status.retweeted_by_user_screen_name); } if (status.is_quote) { - mEditText.append("@" + status.quoted_user_screen_name + " "); + mentions.add(status.quoted_user_screen_name); + } + if (!ArrayUtils.isEmpty(status.mentions)) { + for (ParcelableUserMention mention : status.mentions) { + mentions.add(mention.screen_name); + } + mentions.addAll(mExtractor.extractMentionedScreennames(status.quoted_text_plain)); + } else if (USER_TYPE_FANFOU_COM.equals(status.account_key.getHost())) { + addFanfouHtmlToMentions(status.text_html, mentions); + if (status.is_quote) { + addFanfouHtmlToMentions(status.quoted_text_html, mentions); + } + } else { + mentions.addAll(mExtractor.extractMentionedScreennames(status.text_plain)); + if (status.is_quote) { + mentions.addAll(mExtractor.extractMentionedScreennames(status.quoted_text_plain)); + } } - final Collection mentions = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); - mentions.addAll(mExtractor.extractMentionedScreennames(status.text_plain)); - mentions.addAll(mExtractor.extractMentionedScreennames(status.quoted_text_plain)); for (final String mention : mentions) { if (mention.equalsIgnoreCase(status.user_screen_name) || mention.equalsIgnoreCase(myScreenName) @@ -1104,6 +1121,21 @@ public class ComposeActivity extends BaseActivity implements OnMenuItemClickList return true; } + private void addFanfouHtmlToMentions(String textHtml, Collection mentions) { + final CharSequence text = HtmlSpanBuilder.fromHtml(textHtml, null); + if (text instanceof Spannable) { + Spannable html = ((Spannable) text); + for (URLSpan span : html.getSpans(0, html.length(), URLSpan.class)) { + int start = html.getSpanStart(span), end = html.getSpanEnd(span); + if (start <= 0 || end > html.length() || start > end) continue; + final char ch = html.charAt(start - 1); + if (ch == '@' || ch == '\uff20') { + mentions.add(html.subSequence(start, end).toString()); + } + } + } + } + private boolean handleReplyMultipleIntent(final String[] screenNames, final UserKey accountId, final ParcelableStatus inReplyToStatus) { if (screenNames == null || screenNames.length == 0 || accountId == null) return false; diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/MediaViewerActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/MediaViewerActivity.java index 7c5f96be0..e7231b273 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/MediaViewerActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/MediaViewerActivity.java @@ -138,7 +138,7 @@ public final class MediaViewerActivity extends AbsMediaViewerActivity implements getDelegate().onCreate(savedInstanceState); GeneralComponentHelper.build(this).inject(this); super.onCreate(savedInstanceState); - this.updateTime = System.currentTimeMillis(); + updateTime = System.currentTimeMillis(); ActionBar actionBar = getSupportActionBar(); assert actionBar != null; actionBar.setDisplayHomeAsUpEnabled(true); @@ -160,7 +160,7 @@ public final class MediaViewerActivity extends AbsMediaViewerActivity implements protected void onPause() { mActionHelper.dispatchOnPause(); super.onPause(); - if (this.isFinishing()) { + if (isFinishing()) { ATE.cleanup(); } @@ -169,7 +169,7 @@ public final class MediaViewerActivity extends AbsMediaViewerActivity implements @Override protected void onResume() { super.onResume(); - ATE.invalidateActivity(this, this.updateTime, getATEKey()); + ATE.invalidateActivity(this, updateTime, getATEKey()); } @Override @@ -330,7 +330,7 @@ public final class MediaViewerActivity extends AbsMediaViewerActivity implements @Override public boolean onCreateOptionsMenu(Menu menu) { - ATE.themeOverflow(this, this.getATEKey()); + ATE.themeOverflow(this, getATEKey()); getMenuInflater().inflate(R.menu.menu_media_viewer, menu); return true; }