quote is also available for users not using official keys!
fixed black background issue
This commit is contained in:
parent
a6dd10a3f9
commit
64b7692391
|
@ -39,6 +39,7 @@ android {
|
|||
dependencies {
|
||||
apt 'com.bluelinelabs:logansquare-compiler:1.0.6'
|
||||
compile 'com.android.support:support-annotations:22.1.1'
|
||||
compile 'com.android.support:support-v4:22.1.1'
|
||||
compile 'com.bluelinelabs:logansquare:1.0.6'
|
||||
compile 'org.apache.commons:commons-lang3:3.4'
|
||||
compile project(':twidere.component.querybuilder')
|
||||
|
|
|
@ -56,4 +56,8 @@ public interface TweetResources {
|
|||
@Body(BodyType.FORM)
|
||||
Status updateStatus(@Form StatusUpdate latestStatus) throws TwitterException;
|
||||
|
||||
@POST("/statuses/lookup.json")
|
||||
@Body(BodyType.FORM)
|
||||
ResponseList<Status> lookupStatuses(@Form("id") long[] ids) throws TwitterException;
|
||||
|
||||
}
|
||||
|
|
|
@ -24,11 +24,6 @@ import android.support.annotation.NonNull;
|
|||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
|
||||
import org.mariotaku.twidere.api.twitter.util.TwitterDateConverter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
|
||||
import org.mariotaku.twidere.api.twitter.model.CardEntity;
|
||||
import org.mariotaku.twidere.api.twitter.model.GeoLocation;
|
||||
import org.mariotaku.twidere.api.twitter.model.HashtagEntity;
|
||||
|
@ -38,6 +33,10 @@ import org.mariotaku.twidere.api.twitter.model.Status;
|
|||
import org.mariotaku.twidere.api.twitter.model.UrlEntity;
|
||||
import org.mariotaku.twidere.api.twitter.model.User;
|
||||
import org.mariotaku.twidere.api.twitter.model.UserMentionEntity;
|
||||
import org.mariotaku.twidere.api.twitter.util.TwitterDateConverter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/5/5.
|
||||
|
@ -326,6 +325,11 @@ public class StatusImpl extends TwitterResponseImpl implements Status {
|
|||
'}';
|
||||
}
|
||||
|
||||
public static void setQuotedStatus(Status status, Status quoted) {
|
||||
if (!(status instanceof StatusImpl)) return;
|
||||
((StatusImpl) status).quotedStatus = quoted;
|
||||
}
|
||||
|
||||
@JsonObject
|
||||
static class CurrentUserRetweet {
|
||||
@JsonField(name = "id")
|
||||
|
|
|
@ -22,12 +22,8 @@ package org.mariotaku.twidere.util;
|
|||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.mariotaku.twidere.common.R;
|
||||
import org.mariotaku.twidere.model.ConsumerKeyType;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
import org.mariotaku.twidere.api.twitter.Twitter;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.DirectMessage;
|
||||
import org.mariotaku.twidere.api.twitter.model.EntitySupport;
|
||||
import org.mariotaku.twidere.api.twitter.model.MediaEntity;
|
||||
|
@ -35,6 +31,17 @@ import org.mariotaku.twidere.api.twitter.model.Status;
|
|||
import org.mariotaku.twidere.api.twitter.model.UrlEntity;
|
||||
import org.mariotaku.twidere.api.twitter.model.User;
|
||||
import org.mariotaku.twidere.api.twitter.model.UserMentionEntity;
|
||||
import org.mariotaku.twidere.api.twitter.model.impl.StatusImpl;
|
||||
import org.mariotaku.twidere.common.R;
|
||||
import org.mariotaku.twidere.model.ConsumerKeyType;
|
||||
import org.mariotaku.twidere.util.collection.LongSparseMap;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
import static org.mariotaku.twidere.util.HtmlEscapeHelper.toPlainText;
|
||||
|
||||
|
@ -42,6 +49,9 @@ import static org.mariotaku.twidere.util.HtmlEscapeHelper.toPlainText;
|
|||
* Created by mariotaku on 15/1/11.
|
||||
*/
|
||||
public class TwitterContentUtils {
|
||||
|
||||
public static final int TWITTER_BULK_QUERY_COUNT = 100;
|
||||
|
||||
public static String formatDirectMessageText(final DirectMessage message) {
|
||||
if (message == null) return null;
|
||||
final HtmlBuilder builder = new HtmlBuilder(message.getText(), false, true, true);
|
||||
|
@ -159,6 +169,43 @@ public class TwitterContentUtils {
|
|||
return str.replace("&", "&").replace("<", "<").replace(">", ">");
|
||||
}
|
||||
|
||||
private static final Pattern PATTERN_TWITTER_STATUS_LINK = Pattern.compile("https?://twitter\\.com/(?:#!/)?(\\w+)/status(es)?/(\\d+)");
|
||||
|
||||
public static <T extends List<Status>> T getStatusesWithQuoteData(Twitter twitter, @NonNull T list) throws TwitterException {
|
||||
LongSparseMap<Status> quotes = new LongSparseMap<>();
|
||||
// Phase 1: collect all statuses contains a status link, and put it in the map
|
||||
for (Status status : list) {
|
||||
if (status.isQuote()) continue;
|
||||
final UrlEntity[] entities = status.getUrlEntities();
|
||||
if (entities == null || entities.length <= 0) continue;
|
||||
// Seems Twitter will find last status link for quote target, so we search backward
|
||||
for (int i = entities.length - 1; i >= 0; i--) {
|
||||
final Matcher m = PATTERN_TWITTER_STATUS_LINK.matcher(entities[i].getExpandedUrl());
|
||||
if (!m.matches()) continue;
|
||||
quotes.put(Long.parseLong(m.group(3)), status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Phase 2: look up quoted tweets. Each lookup can fetch up to 100 tweets, so we split quote
|
||||
// ids into batches
|
||||
final long[] quoteIds = quotes.keys();
|
||||
for (int currentBulkIdx = 0, totalLength = quoteIds.length; currentBulkIdx < totalLength; currentBulkIdx += TWITTER_BULK_QUERY_COUNT) {
|
||||
final int currentBulkCount = Math.min(totalLength, currentBulkIdx + TWITTER_BULK_QUERY_COUNT);
|
||||
final long[] ids = new long[currentBulkCount];
|
||||
System.arraycopy(quoteIds, currentBulkIdx, ids, 0, currentBulkCount);
|
||||
// Lookup quoted statuses, then set each status into original status
|
||||
for (Status quoted : twitter.lookupStatuses(ids)) {
|
||||
final Set<Status> orig = quotes.get(quoted.getId());
|
||||
// This set shouldn't be null here, add null check to make inspector happy.
|
||||
if (orig == null) continue;
|
||||
for (Status status : orig) {
|
||||
StatusImpl.setQuotedStatus(status, quoted);
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private static void parseEntities(final HtmlBuilder builder, final EntitySupport entities) {
|
||||
// Format media.
|
||||
final MediaEntity[] mediaEntities = entities.getMediaEntities();
|
||||
|
|
|
@ -19,16 +19,17 @@
|
|||
|
||||
package org.mariotaku.twidere.util.collection;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.util.LongSparseArray;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 14/12/12.
|
||||
*/
|
||||
public class LongSparseMap<T> {
|
||||
|
||||
private final LongSparseArray<HashSet<T>> internalArray;
|
||||
private final LongSparseArray<CompactHashSet<T>> internalArray;
|
||||
|
||||
public LongSparseMap() {
|
||||
internalArray = new LongSparseArray<>();
|
||||
|
@ -36,9 +37,9 @@ public class LongSparseMap<T> {
|
|||
|
||||
public boolean put(long key, T value) {
|
||||
final int idx = internalArray.indexOfKey(key);
|
||||
final HashSet<T> set;
|
||||
final CompactHashSet<T> set;
|
||||
if (idx < 0) {
|
||||
set = new HashSet<>();
|
||||
set = new CompactHashSet<>();
|
||||
internalArray.put(key, set);
|
||||
} else {
|
||||
set = internalArray.valueAt(idx);
|
||||
|
@ -46,6 +47,11 @@ public class LongSparseMap<T> {
|
|||
return set.add(value);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Set<T> get(long key) {
|
||||
return internalArray.get(key);
|
||||
}
|
||||
|
||||
public boolean clear(long key) {
|
||||
final int idx = internalArray.indexOfKey(key);
|
||||
if (idx < 0) return false;
|
||||
|
@ -63,4 +69,12 @@ public class LongSparseMap<T> {
|
|||
return idx >= 0 && internalArray.valueAt(idx).contains(value);
|
||||
}
|
||||
|
||||
public long[] keys() {
|
||||
final long[] keys = new long[internalArray.size()];
|
||||
for (int i = 0, j = internalArray.size(); i < j; i++) {
|
||||
keys[i] = internalArray.keyAt(i);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
}
|
|
@ -42,6 +42,7 @@ import android.widget.Toast;
|
|||
import org.mariotaku.simplerestapi.http.Authorization;
|
||||
import org.mariotaku.simplerestapi.http.Endpoint;
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterOAuth;
|
||||
import org.mariotaku.twidere.api.twitter.auth.OAuthAuthorization;
|
||||
import org.mariotaku.twidere.api.twitter.auth.OAuthToken;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
|
@ -55,9 +56,6 @@ import org.xmlpull.v1.XmlPullParserException;
|
|||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
|
||||
import org.mariotaku.twidere.api.twitter.TwitterConstants;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterOAuth;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
import static org.mariotaku.twidere.util.Utils.getNonEmptyString;
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ public abstract class ThemedAppCompatActivity extends AppCompatActivity implemen
|
|||
public void setTheme(int resid) {
|
||||
super.setTheme(mCurrentThemeResource = getThemeResourceId());
|
||||
if (shouldApplyWindowBackground()) {
|
||||
ThemeUtils.applyWindowBackground(this, getWindow(), resid, mCurrentThemeBackgroundOption,
|
||||
ThemeUtils.applyWindowBackground(this, getWindow(), mCurrentThemeResource, mCurrentThemeBackgroundOption,
|
||||
mCurrentThemeBackgroundAlpha);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import android.view.MenuItem;
|
|||
import android.view.View;
|
||||
|
||||
import com.rengwuxian.materialedittext.MaterialEditText;
|
||||
import com.rengwuxian.materialedittext.validation.METLengthChecker;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
|
@ -44,6 +45,7 @@ import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
|||
import org.mariotaku.twidere.util.LinkCreator;
|
||||
import org.mariotaku.twidere.util.MenuUtils;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
import org.mariotaku.twidere.util.TwidereValidator;
|
||||
import org.mariotaku.twidere.view.holder.StatusViewHolder;
|
||||
import org.mariotaku.twidere.view.holder.StatusViewHolder.DummyStatusHolderAdapter;
|
||||
|
||||
|
@ -56,6 +58,7 @@ public class RetweetQuoteDialogFragment extends BaseSupportDialogFragment implem
|
|||
private MaterialEditText mEditComment;
|
||||
private PopupMenu mPopupMenu;
|
||||
private View mCommentMenu;
|
||||
private TwidereValidator mValidator;
|
||||
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
|
@ -108,6 +111,7 @@ public class RetweetQuoteDialogFragment extends BaseSupportDialogFragment implem
|
|||
final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity());
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped);
|
||||
final Context context = builder.getContext();
|
||||
mValidator = new TwidereValidator(context);
|
||||
final LayoutInflater inflater = LayoutInflater.from(context);
|
||||
@SuppressLint("InflateParams") final View view = inflater.inflate(R.layout.dialog_status_quote_retweet, null);
|
||||
final StatusViewHolder holder = new StatusViewHolder(new DummyStatusHolderAdapter(context), view.findViewById(R.id.item_content));
|
||||
|
@ -127,6 +131,16 @@ public class RetweetQuoteDialogFragment extends BaseSupportDialogFragment implem
|
|||
view.findViewById(R.id.action_buttons).setVisibility(View.GONE);
|
||||
view.findViewById(R.id.item_content).setFocusable(false);
|
||||
mEditComment = (MaterialEditText) view.findViewById(R.id.edit_comment);
|
||||
mEditComment.setLengthChecker(new METLengthChecker() {
|
||||
|
||||
final String statusLink = LinkCreator.getTwitterStatusLink(status.user_screen_name, status.quote_id).toString();
|
||||
|
||||
@Override
|
||||
public int getLength(CharSequence text) {
|
||||
return mValidator.getTweetLength(text + " " + statusLink);
|
||||
}
|
||||
});
|
||||
mEditComment.setMaxCharacters(mValidator.getMaxTweetLength());
|
||||
mCommentMenu = view.findViewById(R.id.comment_menu);
|
||||
|
||||
mPopupMenu = new PopupMenu(context, mCommentMenu, Gravity.NO_GRAVITY,
|
||||
|
|
|
@ -37,6 +37,8 @@ import org.mariotaku.twidere.app.TwidereApplication;
|
|||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.util.LoganSquareWrapper;
|
||||
import org.mariotaku.twidere.util.TwitterAPIUtils;
|
||||
import org.mariotaku.twidere.util.TwitterContentUtils;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
@ -108,6 +110,9 @@ public abstract class TwitterAPIStatusesLoader extends ParcelableStatusesLoader
|
|||
}
|
||||
statuses = new ArrayList<>();
|
||||
truncated = truncateStatuses(getStatuses(twitter, paging), statuses, mSinceId);
|
||||
if (!Utils.isOfficialTwitterInstance(context, twitter)) {
|
||||
TwitterContentUtils.getStatusesWithQuoteData(twitter, statuses);
|
||||
}
|
||||
} catch (final TwitterException e) {
|
||||
// mHandler.post(new ShowErrorRunnable(e));
|
||||
Log.w(LOGTAG, e);
|
||||
|
|
|
@ -141,7 +141,6 @@ import org.mariotaku.twidere.activity.support.MediaViewerActivity;
|
|||
import org.mariotaku.twidere.adapter.iface.IBaseAdapter;
|
||||
import org.mariotaku.twidere.adapter.iface.IBaseCardAdapter;
|
||||
import org.mariotaku.twidere.api.twitter.Twitter;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterConstants;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.auth.OAuthSupport;
|
||||
import org.mariotaku.twidere.api.twitter.model.DirectMessage;
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
package org.mariotaku.twidere.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v7.widget.AppCompatMultiAutoCompleteTextView;
|
||||
import android.text.InputType;
|
||||
import android.text.SpannableString;
|
||||
import android.text.Spanned;
|
||||
|
@ -28,10 +27,12 @@ import android.text.TextUtils;
|
|||
import android.text.method.ArrowKeyMovementMethod;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import com.rengwuxian.materialedittext.MaterialMultiAutoCompleteTextView;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.adapter.UserHashtagAutoCompleteAdapter;
|
||||
|
||||
public class StatusComposeEditText extends AppCompatMultiAutoCompleteTextView {
|
||||
public class StatusComposeEditText extends MaterialMultiAutoCompleteTextView {
|
||||
|
||||
private UserHashtagAutoCompleteAdapter mAdapter;
|
||||
private long mAccountId;
|
||||
|
|
|
@ -126,7 +126,10 @@
|
|||
android:maxHeight="140dp"
|
||||
android:singleLine="false"
|
||||
android:textAppearance="?android:textAppearanceMedium"
|
||||
android:textColor="?android:textColorPrimary">
|
||||
app:met_baseColor="?android:textColorSecondary"
|
||||
app:met_helperTextColor="?android:textColorSecondary"
|
||||
app:met_textColor="?android:textColorPrimary"
|
||||
app:met_textColorHint="?android:textColorSecondary">
|
||||
|
||||
<requestFocus />
|
||||
</org.mariotaku.twidere.view.StatusComposeEditText>
|
||||
|
|
Loading…
Reference in New Issue