fixing leaks
This commit is contained in:
parent
1c5dfb86a9
commit
6f6dec7bb6
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.api.twitter.model;
|
||||
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/12/25.
|
||||
*/
|
||||
@JsonObject
|
||||
public class Contributor {
|
||||
@JsonField(name = "id")
|
||||
long id;
|
||||
@JsonField(name = "screen_name")
|
||||
String screenName;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getScreenName() {
|
||||
return screenName;
|
||||
}
|
||||
}
|
|
@ -20,12 +20,12 @@
|
|||
package org.mariotaku.twidere.api.twitter.model;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
import com.bluelinelabs.logansquare.annotation.OnJsonParseComplete;
|
||||
|
||||
import org.apache.commons.lang3.builder.CompareToBuilder;
|
||||
import org.mariotaku.twidere.api.twitter.util.TwitterDateConverter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -81,8 +81,9 @@ public class Status extends TwitterResponseObject implements Comparable<Status>,
|
|||
@JsonField(name = "current_user_retweet")
|
||||
CurrentUserRetweet currentUserRetweet;
|
||||
|
||||
@Nullable
|
||||
@JsonField(name = "contributors")
|
||||
long[] contributors;
|
||||
Contributor[] contributors;
|
||||
|
||||
@JsonField(name = "retweet_count")
|
||||
long retweetCount;
|
||||
|
@ -127,25 +128,21 @@ public class Status extends TwitterResponseObject implements Comparable<Status>,
|
|||
|
||||
|
||||
public String getInReplyToScreenName() {
|
||||
|
||||
return inReplyToScreenName;
|
||||
}
|
||||
|
||||
|
||||
public long getInReplyToUserId() {
|
||||
|
||||
return inReplyToUserId;
|
||||
}
|
||||
|
||||
|
||||
public long getInReplyToStatusId() {
|
||||
|
||||
return inReplyToStatusId;
|
||||
}
|
||||
|
||||
|
||||
public boolean isTruncated() {
|
||||
|
||||
return truncated;
|
||||
}
|
||||
|
||||
|
@ -157,11 +154,12 @@ public class Status extends TwitterResponseObject implements Comparable<Status>,
|
|||
|
||||
|
||||
public String getSource() {
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* UTC time when this Tweet was created.
|
||||
*/
|
||||
public Date getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
@ -201,6 +199,10 @@ public class Status extends TwitterResponseObject implements Comparable<Status>,
|
|||
return currentUserRetweet != null;
|
||||
}
|
||||
|
||||
public boolean wasRetweeted() {
|
||||
return retweeted;
|
||||
}
|
||||
|
||||
|
||||
public long getFavoriteCount() {
|
||||
return favoriteCount;
|
||||
|
@ -213,6 +215,10 @@ public class Status extends TwitterResponseObject implements Comparable<Status>,
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* <i>Perspectival</i>. Only surfaces on methods supporting the <code>include_my_retweet</code> parameter,
|
||||
* when set to true. Details the Tweet ID of the user’s own retweet (if existent) of this Tweet.
|
||||
*/
|
||||
public long getCurrentUserRetweet() {
|
||||
if (currentUserRetweet == null) return -1;
|
||||
return currentUserRetweet.id;
|
||||
|
@ -279,7 +285,12 @@ public class Status extends TwitterResponseObject implements Comparable<Status>,
|
|||
}
|
||||
|
||||
|
||||
public long[] getContributors() {
|
||||
/**
|
||||
* An collection of brief user objects (usually only one) indicating users who contributed to
|
||||
* the authorship of the tweet, on behalf of the official tweet author.
|
||||
*/
|
||||
@Nullable
|
||||
public Contributor[] getContributors() {
|
||||
return contributors;
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,244 @@ import java.util.Map.Entry;
|
|||
@JsonObject
|
||||
@ParcelablePlease
|
||||
public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus>, Cloneable {
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "id")
|
||||
@CursorField(Statuses.STATUS_ID)
|
||||
public long id;
|
||||
public static final Comparator<ParcelableStatus> REVERSE_ID_COMPARATOR = new Comparator<ParcelableStatus>() {
|
||||
|
||||
@Override
|
||||
public int compare(final ParcelableStatus object1, final ParcelableStatus object2) {
|
||||
final long diff = object1.id - object2.id;
|
||||
if (diff > Integer.MAX_VALUE) return Integer.MAX_VALUE;
|
||||
if (diff < Integer.MIN_VALUE) return Integer.MIN_VALUE;
|
||||
return (int) diff;
|
||||
}
|
||||
};
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "account_id")
|
||||
@CursorField(Statuses.ACCOUNT_ID)
|
||||
public long account_id;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "timestamp")
|
||||
@CursorField(Statuses.STATUS_TIMESTAMP)
|
||||
public long timestamp;
|
||||
public static final Comparator<ParcelableStatus> TIMESTAMP_COMPARATOR = new Comparator<ParcelableStatus>() {
|
||||
|
||||
@Override
|
||||
public int compare(final ParcelableStatus object1, final ParcelableStatus object2) {
|
||||
final long diff = object2.timestamp - object1.timestamp;
|
||||
if (diff > Integer.MAX_VALUE) return Integer.MAX_VALUE;
|
||||
if (diff < Integer.MIN_VALUE) return Integer.MIN_VALUE;
|
||||
return (int) diff;
|
||||
}
|
||||
};
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_id")
|
||||
@CursorField(Statuses.USER_ID)
|
||||
public long user_id;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweet_id")
|
||||
@CursorField(Statuses.RETWEET_ID)
|
||||
public long retweet_id;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweeted_by_user_id")
|
||||
@CursorField(Statuses.RETWEETED_BY_USER_ID)
|
||||
public long retweeted_by_user_id;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweet_timestamp")
|
||||
@CursorField(Statuses.RETWEET_TIMESTAMP)
|
||||
public long retweet_timestamp;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweet_count")
|
||||
@CursorField(Statuses.RETWEET_COUNT)
|
||||
public long retweet_count;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "favorite_count")
|
||||
@CursorField(Statuses.FAVORITE_COUNT)
|
||||
public long favorite_count;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "reply_count")
|
||||
@CursorField(Statuses.REPLY_COUNT)
|
||||
public long reply_count;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "in_reply_to_status_id")
|
||||
@CursorField(Statuses.IN_REPLY_TO_STATUS_ID)
|
||||
public long in_reply_to_status_id;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "in_reply_to_user_id")
|
||||
@CursorField(Statuses.IN_REPLY_TO_USER_ID)
|
||||
public long in_reply_to_user_id;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "my_retweet_id")
|
||||
@CursorField(Statuses.MY_RETWEET_ID)
|
||||
public long my_retweet_id;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_id")
|
||||
@CursorField(Statuses.QUOTED_ID)
|
||||
public long quoted_id;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_timestamp")
|
||||
@CursorField(Statuses.QUOTED_TIMESTAMP)
|
||||
public long quoted_timestamp;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_user_id")
|
||||
@CursorField(Statuses.QUOTED_USER_ID)
|
||||
public long quoted_user_id;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "is_gap")
|
||||
@CursorField(Statuses.IS_GAP)
|
||||
public boolean is_gap;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "is_retweet")
|
||||
@CursorField(Statuses.IS_RETWEET)
|
||||
public boolean is_retweet;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweeted")
|
||||
@CursorField(Statuses.RETWEETED)
|
||||
public boolean retweeted;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "is_favorite")
|
||||
@CursorField(Statuses.IS_FAVORITE)
|
||||
public boolean is_favorite;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "is_possibly_sensitive")
|
||||
@CursorField(Statuses.IS_POSSIBLY_SENSITIVE)
|
||||
public boolean is_possibly_sensitive;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_is_following")
|
||||
@CursorField(Statuses.IS_FOLLOWING)
|
||||
public boolean user_is_following;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_is_protected")
|
||||
@CursorField(Statuses.IS_PROTECTED)
|
||||
public boolean user_is_protected;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_is_verified")
|
||||
@CursorField(Statuses.IS_VERIFIED)
|
||||
public boolean user_is_verified;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "is_quote")
|
||||
@CursorField(Statuses.IS_QUOTE)
|
||||
public boolean is_quote;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_user_is_protected")
|
||||
@CursorField(Statuses.QUOTED_USER_IS_PROTECTED)
|
||||
public boolean quoted_user_is_protected;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_user_is_verified")
|
||||
@CursorField(Statuses.QUOTED_USER_IS_VERIFIED)
|
||||
public boolean quoted_user_is_verified;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweeted_by_user_name")
|
||||
@CursorField(Statuses.RETWEETED_BY_USER_NAME)
|
||||
public String retweeted_by_user_name;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweeted_by_user_screen_name")
|
||||
@CursorField(Statuses.RETWEETED_BY_USER_SCREEN_NAME)
|
||||
public String retweeted_by_user_screen_name;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweeted_by_user_profile_image")
|
||||
@CursorField(Statuses.RETWEETED_BY_USER_PROFILE_IMAGE)
|
||||
public String retweeted_by_user_profile_image;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "text_html")
|
||||
@CursorField(Statuses.TEXT_HTML)
|
||||
public String text_html;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "text_plain")
|
||||
@CursorField(Statuses.TEXT_PLAIN)
|
||||
public String text_plain;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "lang")
|
||||
@CursorField(Statuses.LANG)
|
||||
public String lang;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_name")
|
||||
@CursorField(Statuses.USER_NAME)
|
||||
public String user_name;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_screen_name")
|
||||
@CursorField(Statuses.USER_SCREEN_NAME)
|
||||
public String user_screen_name;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "in_reply_to_name")
|
||||
@CursorField(Statuses.IN_REPLY_TO_USER_NAME)
|
||||
public String in_reply_to_name;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "in_reply_to_screen_name")
|
||||
@CursorField(Statuses.IN_REPLY_TO_USER_SCREEN_NAME)
|
||||
public String in_reply_to_screen_name;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "source")
|
||||
@CursorField(Statuses.SOURCE)
|
||||
public String source;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_profile_image_url")
|
||||
@CursorField(Statuses.USER_PROFILE_IMAGE_URL)
|
||||
public String user_profile_image_url;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "text_unescaped")
|
||||
@CursorField(Statuses.TEXT_UNESCAPED)
|
||||
public String text_unescaped;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "card_name")
|
||||
@CursorField(Statuses.CARD_NAME)
|
||||
public String card_name;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_text_html")
|
||||
@CursorField(Statuses.QUOTED_TEXT_HTML)
|
||||
public String quoted_text_html;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_text_plain")
|
||||
@CursorField(Statuses.QUOTED_TEXT_PLAIN)
|
||||
public String quoted_text_plain;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_text_unescaped")
|
||||
@CursorField(Statuses.QUOTED_TEXT_UNESCAPED)
|
||||
public String quoted_text_unescaped;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_source")
|
||||
@CursorField(Statuses.QUOTED_SOURCE)
|
||||
public String quoted_source;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_user_name")
|
||||
@CursorField(Statuses.QUOTED_USER_NAME)
|
||||
public String quoted_user_name;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_user_screen_name")
|
||||
@CursorField(Statuses.QUOTED_USER_SCREEN_NAME)
|
||||
public String quoted_user_screen_name;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_user_profile_image")
|
||||
@CursorField(Statuses.QUOTED_USER_PROFILE_IMAGE)
|
||||
public String quoted_user_profile_image;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "location")
|
||||
@CursorField(value = Statuses.LOCATION, converter = ParcelableLocation.Converter.class)
|
||||
public ParcelableLocation location;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "place_full_name")
|
||||
@CursorField(value = Statuses.PLACE_FULL_NAME, converter = LoganSquareCursorFieldConverter.class)
|
||||
public String place_full_name;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "mentions")
|
||||
@CursorField(value = Statuses.MENTIONS_JSON, converter = LoganSquareCursorFieldConverter.class)
|
||||
public ParcelableUserMention[] mentions;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "media")
|
||||
@CursorField(value = Statuses.MEDIA_JSON, converter = LoganSquareCursorFieldConverter.class)
|
||||
public ParcelableMedia[] media;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_media")
|
||||
@CursorField(value = Statuses.QUOTED_MEDIA_JSON, converter = LoganSquareCursorFieldConverter.class)
|
||||
public ParcelableMedia[] quoted_media;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "card")
|
||||
@CursorField(value = Statuses.CARD, converter = LoganSquareCursorFieldConverter.class)
|
||||
public ParcelableCardEntity card;
|
||||
@CursorField(value = Statuses._ID, excludeWrite = true)
|
||||
long _id;
|
||||
public static final Creator<ParcelableStatus> CREATOR = new Creator<ParcelableStatus>() {
|
||||
public ParcelableStatus createFromParcel(Parcel source) {
|
||||
ParcelableStatus target = new ParcelableStatus();
|
||||
|
@ -74,296 +312,6 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
|
|||
}
|
||||
};
|
||||
|
||||
public static final Comparator<ParcelableStatus> REVERSE_ID_COMPARATOR = new Comparator<ParcelableStatus>() {
|
||||
|
||||
@Override
|
||||
public int compare(final ParcelableStatus object1, final ParcelableStatus object2) {
|
||||
final long diff = object1.id - object2.id;
|
||||
if (diff > Integer.MAX_VALUE) return Integer.MAX_VALUE;
|
||||
if (diff < Integer.MIN_VALUE) return Integer.MIN_VALUE;
|
||||
return (int) diff;
|
||||
}
|
||||
};
|
||||
|
||||
public static final Comparator<ParcelableStatus> TIMESTAMP_COMPARATOR = new Comparator<ParcelableStatus>() {
|
||||
|
||||
@Override
|
||||
public int compare(final ParcelableStatus object1, final ParcelableStatus object2) {
|
||||
final long diff = object2.timestamp - object1.timestamp;
|
||||
if (diff > Integer.MAX_VALUE) return Integer.MAX_VALUE;
|
||||
if (diff < Integer.MIN_VALUE) return Integer.MIN_VALUE;
|
||||
return (int) diff;
|
||||
}
|
||||
};
|
||||
|
||||
@CursorField(value = Statuses._ID, excludeWrite = true)
|
||||
long _id;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "id")
|
||||
@CursorField(Statuses.STATUS_ID)
|
||||
public long id;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "account_id")
|
||||
@CursorField(Statuses.ACCOUNT_ID)
|
||||
public long account_id;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "timestamp")
|
||||
@CursorField(Statuses.STATUS_TIMESTAMP)
|
||||
public long timestamp;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_id")
|
||||
@CursorField(Statuses.USER_ID)
|
||||
public long user_id;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweet_id")
|
||||
@CursorField(Statuses.RETWEET_ID)
|
||||
public long retweet_id;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweeted_by_user_id")
|
||||
@CursorField(Statuses.RETWEETED_BY_USER_ID)
|
||||
public long retweeted_by_user_id;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweet_timestamp")
|
||||
@CursorField(Statuses.RETWEET_TIMESTAMP)
|
||||
public long retweet_timestamp;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweet_count")
|
||||
@CursorField(Statuses.RETWEET_COUNT)
|
||||
public long retweet_count;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "favorite_count")
|
||||
@CursorField(Statuses.FAVORITE_COUNT)
|
||||
public long favorite_count;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "reply_count")
|
||||
@CursorField(Statuses.REPLY_COUNT)
|
||||
public long reply_count;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "in_reply_to_status_id")
|
||||
@CursorField(Statuses.IN_REPLY_TO_STATUS_ID)
|
||||
public long in_reply_to_status_id;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "in_reply_to_user_id")
|
||||
@CursorField(Statuses.IN_REPLY_TO_USER_ID)
|
||||
public long in_reply_to_user_id;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "my_retweet_id")
|
||||
@CursorField(Statuses.MY_RETWEET_ID)
|
||||
public long my_retweet_id;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_id")
|
||||
@CursorField(Statuses.QUOTED_ID)
|
||||
public long quoted_id;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_timestamp")
|
||||
@CursorField(Statuses.QUOTED_TIMESTAMP)
|
||||
public long quoted_timestamp;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_user_id")
|
||||
@CursorField(Statuses.QUOTED_USER_ID)
|
||||
public long quoted_user_id;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "is_gap")
|
||||
@CursorField(Statuses.IS_GAP)
|
||||
public boolean is_gap;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "is_retweet")
|
||||
@CursorField(Statuses.IS_RETWEET)
|
||||
public boolean is_retweet;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "is_favorite")
|
||||
@CursorField(Statuses.IS_FAVORITE)
|
||||
public boolean is_favorite;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "is_possibly_sensitive")
|
||||
@CursorField(Statuses.IS_POSSIBLY_SENSITIVE)
|
||||
public boolean is_possibly_sensitive;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_is_following")
|
||||
@CursorField(Statuses.IS_FOLLOWING)
|
||||
public boolean user_is_following;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_is_protected")
|
||||
@CursorField(Statuses.IS_PROTECTED)
|
||||
public boolean user_is_protected;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_is_verified")
|
||||
@CursorField(Statuses.IS_VERIFIED)
|
||||
public boolean user_is_verified;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "is_quote")
|
||||
@CursorField(Statuses.IS_QUOTE)
|
||||
public boolean is_quote;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_user_is_protected")
|
||||
@CursorField(Statuses.QUOTED_USER_IS_PROTECTED)
|
||||
public boolean quoted_user_is_protected;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_user_is_verified")
|
||||
@CursorField(Statuses.QUOTED_USER_IS_VERIFIED)
|
||||
public boolean quoted_user_is_verified;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweeted_by_user_name")
|
||||
@CursorField(Statuses.RETWEETED_BY_USER_NAME)
|
||||
public String retweeted_by_user_name;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweeted_by_user_screen_name")
|
||||
@CursorField(Statuses.RETWEETED_BY_USER_SCREEN_NAME)
|
||||
public String retweeted_by_user_screen_name;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweeted_by_user_profile_image")
|
||||
@CursorField(Statuses.RETWEETED_BY_USER_PROFILE_IMAGE)
|
||||
public String retweeted_by_user_profile_image;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "text_html")
|
||||
@CursorField(Statuses.TEXT_HTML)
|
||||
public String text_html;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "text_plain")
|
||||
@CursorField(Statuses.TEXT_PLAIN)
|
||||
public String text_plain;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "lang")
|
||||
@CursorField(Statuses.LANG)
|
||||
public String lang;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_name")
|
||||
@CursorField(Statuses.USER_NAME)
|
||||
public String user_name;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_screen_name")
|
||||
@CursorField(Statuses.USER_SCREEN_NAME)
|
||||
public String user_screen_name;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "in_reply_to_name")
|
||||
@CursorField(Statuses.IN_REPLY_TO_USER_NAME)
|
||||
public String in_reply_to_name;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "in_reply_to_screen_name")
|
||||
@CursorField(Statuses.IN_REPLY_TO_USER_SCREEN_NAME)
|
||||
public String in_reply_to_screen_name;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "source")
|
||||
@CursorField(Statuses.SOURCE)
|
||||
public String source;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_profile_image_url")
|
||||
@CursorField(Statuses.USER_PROFILE_IMAGE_URL)
|
||||
public String user_profile_image_url;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "text_unescaped")
|
||||
@CursorField(Statuses.TEXT_UNESCAPED)
|
||||
public String text_unescaped;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "card_name")
|
||||
@CursorField(Statuses.CARD_NAME)
|
||||
public String card_name;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_text_html")
|
||||
@CursorField(Statuses.QUOTED_TEXT_HTML)
|
||||
public String quoted_text_html;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_text_plain")
|
||||
@CursorField(Statuses.QUOTED_TEXT_PLAIN)
|
||||
public String quoted_text_plain;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_text_unescaped")
|
||||
@CursorField(Statuses.QUOTED_TEXT_UNESCAPED)
|
||||
public String quoted_text_unescaped;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_source")
|
||||
@CursorField(Statuses.QUOTED_SOURCE)
|
||||
public String quoted_source;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_user_name")
|
||||
@CursorField(Statuses.QUOTED_USER_NAME)
|
||||
public String quoted_user_name;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_user_screen_name")
|
||||
@CursorField(Statuses.QUOTED_USER_SCREEN_NAME)
|
||||
public String quoted_user_screen_name;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_user_profile_image")
|
||||
@CursorField(Statuses.QUOTED_USER_PROFILE_IMAGE)
|
||||
public String quoted_user_profile_image;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "location")
|
||||
@CursorField(value = Statuses.LOCATION, converter = ParcelableLocation.Converter.class)
|
||||
public ParcelableLocation location;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "place_full_name")
|
||||
@CursorField(value = Statuses.PLACE_FULL_NAME, converter = LoganSquareCursorFieldConverter.class)
|
||||
public String place_full_name;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "mentions")
|
||||
@CursorField(value = Statuses.MENTIONS_JSON, converter = LoganSquareCursorFieldConverter.class)
|
||||
public ParcelableUserMention[] mentions;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "media")
|
||||
@CursorField(value = Statuses.MEDIA_JSON, converter = LoganSquareCursorFieldConverter.class)
|
||||
public ParcelableMedia[] media;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_media")
|
||||
@CursorField(value = Statuses.QUOTED_MEDIA_JSON, converter = LoganSquareCursorFieldConverter.class)
|
||||
public ParcelableMedia[] quoted_media;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "card")
|
||||
@CursorField(value = Statuses.CARD, converter = LoganSquareCursorFieldConverter.class)
|
||||
public ParcelableCardEntity card;
|
||||
|
||||
|
||||
ParcelableStatus() {
|
||||
}
|
||||
|
@ -374,15 +322,18 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
|
|||
id = orig.getId();
|
||||
timestamp = getTime(orig.getCreatedAt());
|
||||
|
||||
final Status retweeted = orig.getRetweetedStatus();
|
||||
final User retweet_user = retweeted != null ? orig.getUser() : null;
|
||||
final Status retweetedStatus = orig.getRetweetedStatus();
|
||||
final User retweetUser = retweetedStatus != null ? orig.getUser() : null;
|
||||
is_retweet = orig.isRetweet();
|
||||
retweet_id = retweeted != null ? retweeted.getId() : -1;
|
||||
retweet_timestamp = retweeted != null ? getTime(retweeted.getCreatedAt()) : -1;
|
||||
retweeted_by_user_id = retweet_user != null ? retweet_user.getId() : -1;
|
||||
retweeted_by_user_name = retweet_user != null ? retweet_user.getName() : null;
|
||||
retweeted_by_user_screen_name = retweet_user != null ? retweet_user.getScreenName() : null;
|
||||
retweeted_by_user_profile_image = TwitterContentUtils.getProfileImageUrl(retweet_user);
|
||||
retweeted = orig.wasRetweeted();
|
||||
if (retweetedStatus != null) {
|
||||
retweet_id = retweetedStatus.getId();
|
||||
retweet_timestamp = getTime(retweetedStatus.getCreatedAt());
|
||||
retweeted_by_user_id = retweetUser.getId();
|
||||
retweeted_by_user_name = retweetUser.getName();
|
||||
retweeted_by_user_screen_name = retweetUser.getScreenName();
|
||||
retweeted_by_user_profile_image = TwitterContentUtils.getProfileImageUrl(retweetUser);
|
||||
}
|
||||
|
||||
final Status quoted = orig.getQuotedStatus();
|
||||
is_quote = orig.isQuote();
|
||||
|
@ -405,15 +356,28 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
|
|||
}
|
||||
|
||||
final Status status;
|
||||
if (retweeted != null) {
|
||||
status = retweeted;
|
||||
if (retweetedStatus != null) {
|
||||
status = retweetedStatus;
|
||||
reply_count = retweetedStatus.getReplyCount();
|
||||
retweet_count = retweetedStatus.getRetweetCount();
|
||||
favorite_count = retweetedStatus.getFavoriteCount();
|
||||
|
||||
|
||||
in_reply_to_name = TwitterContentUtils.getInReplyToName(retweetedStatus);
|
||||
in_reply_to_screen_name = retweetedStatus.getInReplyToScreenName();
|
||||
in_reply_to_status_id = retweetedStatus.getInReplyToStatusId();
|
||||
in_reply_to_user_id = retweetedStatus.getInReplyToUserId();
|
||||
} else {
|
||||
status = orig;
|
||||
}
|
||||
reply_count = orig.getReplyCount();
|
||||
retweet_count = orig.getRetweetCount();
|
||||
favorite_count = orig.getFavoriteCount();
|
||||
|
||||
retweet_count = (retweeted != null ? retweeted : orig).getRetweetCount();
|
||||
favorite_count = (retweeted != null ? retweeted : orig).getFavoriteCount();
|
||||
reply_count = (retweeted != null ? retweeted : orig).getReplyCount();
|
||||
in_reply_to_name = TwitterContentUtils.getInReplyToName(orig);
|
||||
in_reply_to_screen_name = orig.getInReplyToScreenName();
|
||||
in_reply_to_status_id = orig.getInReplyToStatusId();
|
||||
in_reply_to_user_id = orig.getInReplyToUserId();
|
||||
}
|
||||
|
||||
final User user = status.getUser();
|
||||
user_id = user.getId();
|
||||
|
@ -426,10 +390,6 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
|
|||
text_html = TwitterContentUtils.formatStatusText(status);
|
||||
media = ParcelableMedia.fromStatus(status);
|
||||
text_plain = TwitterContentUtils.unescapeTwitterStatusText(status.getText());
|
||||
in_reply_to_name = TwitterContentUtils.getInReplyToName(retweeted != null ? retweeted : orig);
|
||||
in_reply_to_screen_name = (retweeted != null ? retweeted : orig).getInReplyToScreenName();
|
||||
in_reply_to_status_id = (retweeted != null ? retweeted : orig).getInReplyToStatusId();
|
||||
in_reply_to_user_id = (retweeted != null ? retweeted : orig).getInReplyToUserId();
|
||||
source = status.getSource();
|
||||
location = ParcelableLocation.fromGeoLocation(status.getGeoLocation());
|
||||
is_favorite = status.isFavorited();
|
||||
|
@ -632,18 +592,18 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
|
|||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ParcelableBindingValue getValue(@Nullable String key) {
|
||||
if (key == null || values == null) return null;
|
||||
return values.get(key);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ParcelableBindingValue getValue(@Nullable ParcelableCardEntity entity, @Nullable String key) {
|
||||
if (entity == null) return null;
|
||||
return entity.getValue(key);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ParcelableBindingValue getValue(@Nullable String key) {
|
||||
if (key == null || values == null) return null;
|
||||
return values.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ParcelableCardEntity{" +
|
||||
|
|
|
@ -855,6 +855,8 @@ public interface TwidereDataStore {
|
|||
String QUOTED_USER_IS_VERIFIED = "quoted_user_is_verified";
|
||||
String QUOTED_USER_IS_PROTECTED = "quoted_user_is_protected";
|
||||
|
||||
String RETWEETED = "retweeted";
|
||||
|
||||
String[] COLUMNS = {_ID, ACCOUNT_ID, STATUS_ID, USER_ID,
|
||||
STATUS_TIMESTAMP, TEXT_HTML, TEXT_PLAIN, TEXT_UNESCAPED, USER_NAME, USER_SCREEN_NAME,
|
||||
USER_PROFILE_IMAGE_URL, IN_REPLY_TO_STATUS_ID, IN_REPLY_TO_USER_ID, IN_REPLY_TO_USER_NAME,
|
||||
|
@ -866,7 +868,7 @@ public interface TwidereDataStore {
|
|||
QUOTED_USER_IS_VERIFIED, QUOTED_USER_IS_PROTECTED, MY_RETWEET_ID, IS_RETWEET,
|
||||
IS_QUOTE, IS_FAVORITE, IS_PROTECTED, IS_VERIFIED, IS_FOLLOWING, IS_GAP,
|
||||
IS_POSSIBLY_SENSITIVE, MEDIA_JSON, MENTIONS_JSON, QUOTED_MEDIA_JSON, CARD_NAME, CARD,
|
||||
PLACE_FULL_NAME, LANG};
|
||||
PLACE_FULL_NAME, LANG, RETWEETED};
|
||||
|
||||
String[] TYPES = {TYPE_PRIMARY_KEY, TYPE_INT, TYPE_INT,
|
||||
TYPE_INT, TYPE_INT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT,
|
||||
|
@ -876,7 +878,7 @@ public interface TwidereDataStore {
|
|||
TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_INT, TYPE_BOOLEAN,
|
||||
TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_BOOLEAN,
|
||||
TYPE_BOOLEAN, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT,
|
||||
TYPE_TEXT, TYPE_TEXT, TYPE_TEXT};
|
||||
TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_BOOLEAN};
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -181,22 +181,35 @@ public class HotMobiLogger {
|
|||
record.setState(intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1));
|
||||
record.setTimestamp(System.currentTimeMillis());
|
||||
record.setTimeOffset(TimeZone.getDefault().getRawOffset());
|
||||
getInstance(context).log(record);
|
||||
getInstance(context).log(record, null);
|
||||
}
|
||||
|
||||
public void log(long accountId, final Object event) {
|
||||
mExecutor.execute(new WriteLogTask(mApplication, accountId, event));
|
||||
public <T> void log(long accountId, final T event, final PreProcessing<T> preProcessing) {
|
||||
mExecutor.execute(new WriteLogTask<>(mApplication, accountId, event, preProcessing));
|
||||
}
|
||||
|
||||
public void log(Object event) {
|
||||
log(ACCOUNT_ID_NOT_NEEDED, event);
|
||||
public <T> void log(long accountId, final T event) {
|
||||
log(accountId, event, null);
|
||||
}
|
||||
|
||||
public void logList(List<?> events, long accountId, String type) {
|
||||
mExecutor.execute(new WriteLogTask(mApplication, accountId, type, events));
|
||||
public <T> void log(final T event) {
|
||||
log(event, null);
|
||||
}
|
||||
|
||||
public void log(final Object event, final PreProcessing preProcessing) {
|
||||
log(ACCOUNT_ID_NOT_NEEDED, event, preProcessing);
|
||||
}
|
||||
|
||||
public <T> void logList(List<T> events, long accountId, String type) {
|
||||
logList(events, accountId, type, null);
|
||||
}
|
||||
|
||||
public <T> void logList(List<T> events, long accountId, String type, final PreProcessing<T> preProcessing) {
|
||||
mExecutor.execute(new WriteLogTask<>(mApplication, accountId, type, events, preProcessing));
|
||||
}
|
||||
|
||||
public static void logScreenEvent(Context context, ScreenEvent.Action action, long presentDuration) {
|
||||
getInstance(context).log(ScreenEvent.create(context, action, presentDuration));
|
||||
getInstance(context).log(ScreenEvent.create(context, action, presentDuration), null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package edu.tsinghua.hotmobi;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/12/24.
|
||||
*/
|
||||
public interface PreProcessing<T> {
|
||||
void process(T event, Context appContext);
|
||||
}
|
|
@ -110,7 +110,6 @@ public class UploadLogsTask implements Runnable {
|
|||
if (response.isSuccessful()) {
|
||||
succeeded &= logFile.delete();
|
||||
}
|
||||
response.close();
|
||||
} catch (IOException e) {
|
||||
Log.w(HotMobiLogger.LOGTAG, e);
|
||||
succeeded = false;
|
||||
|
|
|
@ -21,6 +21,7 @@ package edu.tsinghua.hotmobi;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import com.bluelinelabs.logansquare.LoganSquare;
|
||||
|
@ -40,24 +41,28 @@ import java.util.List;
|
|||
/**
|
||||
* Created by mariotaku on 15/8/23.
|
||||
*/
|
||||
public class WriteLogTask implements Runnable, Constants {
|
||||
public class WriteLogTask<T> implements Runnable, Constants {
|
||||
|
||||
private static final byte[] LF = {'\n'};
|
||||
|
||||
private final Context context;
|
||||
private final long accountId;
|
||||
private final String type;
|
||||
private final List<?> events;
|
||||
private final List<T> events;
|
||||
@Nullable
|
||||
private final PreProcessing<T> preProcessing;
|
||||
|
||||
public WriteLogTask(Context context, long accountId, Object event) {
|
||||
this(context, accountId, HotMobiLogger.getLogFilename(event), Collections.singletonList(event));
|
||||
public WriteLogTask(Context context, long accountId, T event, @Nullable PreProcessing<T> preProcessing) {
|
||||
this(context, accountId, HotMobiLogger.getLogFilename(event), Collections.singletonList(event), preProcessing);
|
||||
}
|
||||
|
||||
public WriteLogTask(Context context, long accountId, String type, List<?> events) {
|
||||
public WriteLogTask(Context context, long accountId, String type, List<T> events,
|
||||
@Nullable PreProcessing<T> preProcessing) {
|
||||
this.context = context;
|
||||
this.accountId = accountId;
|
||||
this.type = type;
|
||||
this.events = events;
|
||||
this.preProcessing = preProcessing;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -71,7 +76,10 @@ public class WriteLogTask implements Runnable, Constants {
|
|||
raf = new RandomAccessFile(HotMobiLogger.getLogFile(context, accountId, type), "rw");
|
||||
fc = raf.getChannel();
|
||||
final FileLock lock = fc.lock();
|
||||
for (Object event : events) {
|
||||
for (T event : events) {
|
||||
if (preProcessing != null) {
|
||||
preProcessing.process(event, context);
|
||||
}
|
||||
if (BuildConfig.DEBUG) {
|
||||
if (accountId > 0) {
|
||||
Log.v(HotMobiLogger.LOGTAG, "Log " + type + " for account " + accountId + ": " + event);
|
||||
|
|
|
@ -33,7 +33,7 @@ import static org.mariotaku.twidere.annotation.Preference.Type.STRING;
|
|||
public interface Constants extends TwidereConstants {
|
||||
|
||||
String DATABASES_NAME = "twidere.sqlite";
|
||||
int DATABASES_VERSION = 114;
|
||||
int DATABASES_VERSION = 115;
|
||||
|
||||
int MENU_GROUP_STATUS_EXTENSION = 10;
|
||||
int MENU_GROUP_COMPOSE_EXTENSION = 11;
|
||||
|
|
|
@ -85,6 +85,7 @@ import org.mariotaku.twidere.util.Utils;
|
|||
import org.mariotaku.twidere.util.VideoLoader.VideoLoadingListener;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import pl.droidsonroids.gif.GifSupportChecker;
|
||||
|
@ -402,7 +403,8 @@ public final class MediaViewerActivity extends BaseAppCompatActivity implements
|
|||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
final boolean isLoading = getLoaderManager().hasRunningLoaders();
|
||||
final TaskRunnable<File, Pair<Boolean, Intent>, Pair<Fragment, Menu>> checkState = new TaskRunnable<File, Pair<Boolean, Intent>, Pair<Fragment, Menu>>() {
|
||||
final TaskRunnable<File, Pair<Boolean, Intent>, Pair<Fragment, Menu>> checkState
|
||||
= new TaskRunnable<File, Pair<Boolean, Intent>, Pair<Fragment, Menu>>() {
|
||||
@Override
|
||||
public Pair<Boolean, Intent> doLongOperation(File file) throws InterruptedException {
|
||||
final boolean hasImage = file != null && file.exists();
|
||||
|
@ -411,7 +413,8 @@ public final class MediaViewerActivity extends BaseAppCompatActivity implements
|
|||
}
|
||||
final Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
final Uri fileUri = Uri.fromFile(file);
|
||||
intent.setDataAndType(fileUri, Utils.getImageMimeType(file));
|
||||
final String imageMimeType = Utils.getImageMimeType(file);
|
||||
intent.setDataAndType(fileUri, imageMimeType);
|
||||
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
|
||||
final MediaViewerActivity activity = (MediaViewerActivity) getActivity();
|
||||
if (activity.hasStatus()) {
|
||||
|
|
|
@ -102,6 +102,8 @@ import org.mariotaku.twidere.util.view.ConsumerKeySecretValidator;
|
|||
import org.mariotaku.twidere.view.TintedStatusNativeActionModeAwareLayout;
|
||||
import org.mariotaku.twidere.view.iface.TintedStatusLayout;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.createAccount;
|
||||
import static org.mariotaku.twidere.util.DataStoreUtils.getActivatedAccountIds;
|
||||
|
@ -577,14 +579,15 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
|
|||
|
||||
public static abstract class AbstractSignInTask extends AsyncTask<Object, Runnable, SignInResponse> {
|
||||
|
||||
protected final SignInActivity activity;
|
||||
protected final WeakReference<SignInActivity> activityRef;
|
||||
|
||||
public AbstractSignInTask(final SignInActivity activity) {
|
||||
this.activity = activity;
|
||||
this.activityRef = new WeakReference<>(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final SignInResponse result) {
|
||||
final SignInActivity activity = activityRef.get();
|
||||
if (activity != null) {
|
||||
activity.onSignInResult(result);
|
||||
}
|
||||
|
@ -592,6 +595,7 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
|
|||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
final SignInActivity activity = activityRef.get();
|
||||
if (activity != null) {
|
||||
activity.onSignInStart();
|
||||
}
|
||||
|
@ -730,6 +734,8 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
|
|||
}
|
||||
|
||||
private SignInResponse authBasic() throws TwitterException {
|
||||
final SignInActivity activity = activityRef.get();
|
||||
if (activity == null) return new SignInResponse(false, false, null);
|
||||
final String versionSuffix = noVersionSuffix ? null : "1.1";
|
||||
final Endpoint endpoint = new Endpoint(TwitterAPIFactory.getApiUrl(apiUrlFormat, "api", versionSuffix));
|
||||
final Authorization auth = new BasicAuthorization(username, password);
|
||||
|
@ -744,6 +750,8 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
|
|||
}
|
||||
|
||||
private SignInResponse authOAuth() throws AuthenticationException, TwitterException {
|
||||
final SignInActivity activity = activityRef.get();
|
||||
if (activity == null) return new SignInResponse(false, false, null);
|
||||
Endpoint endpoint = TwitterAPIFactory.getOAuthEndpoint(apiUrlFormat, "api", null, sameOAuthSigningUrl);
|
||||
OAuthAuthorization auth = new OAuthAuthorization(consumerKey.getOauthToken(), consumerKey.getOauthTokenSecret());
|
||||
final TwitterOAuth oauth = TwitterAPIFactory.getInstance(activity, endpoint, auth, TwitterOAuth.class);
|
||||
|
@ -762,6 +770,8 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
|
|||
}
|
||||
|
||||
private SignInResponse authTwipOMode() throws TwitterException {
|
||||
final SignInActivity activity = activityRef.get();
|
||||
if (activity == null) return new SignInResponse(false, false, null);
|
||||
final String versionSuffix = noVersionSuffix ? null : "1.1";
|
||||
final Endpoint endpoint = new Endpoint(TwitterAPIFactory.getApiUrl(apiUrlFormat, "api", versionSuffix));
|
||||
final Authorization auth = new EmptyAuthorization();
|
||||
|
@ -774,6 +784,8 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
|
|||
}
|
||||
|
||||
private SignInResponse authxAuth() throws TwitterException {
|
||||
final SignInActivity activity = activityRef.get();
|
||||
if (activity == null) return new SignInResponse(false, false, null);
|
||||
Endpoint endpoint = TwitterAPIFactory.getOAuthEndpoint(apiUrlFormat, "api", null, sameOAuthSigningUrl);
|
||||
OAuthAuthorization auth = new OAuthAuthorization(consumerKey.getOauthToken(), consumerKey.getOauthTokenSecret());
|
||||
final TwitterOAuth oauth = TwitterAPIFactory.getInstance(activity, endpoint, auth, TwitterOAuth.class);
|
||||
|
@ -800,6 +812,8 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
|
|||
publishProgress(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final SignInActivity activity = activityRef.get();
|
||||
if (activity == null) return;
|
||||
activity.dismissDialogFragment(FRAGMENT_TAG_SIGN_IN_PROGRESS);
|
||||
}
|
||||
});
|
||||
|
@ -807,6 +821,8 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
|
|||
publishProgress(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final SignInActivity activity = activityRef.get();
|
||||
if (activity == null) return;
|
||||
activity.postAfterFragmentResumed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -830,6 +846,8 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
|
|||
publishProgress(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final SignInActivity activity = activityRef.get();
|
||||
if (activity == null) return;
|
||||
activity.showSignInProgressDialog();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -72,7 +72,6 @@ public abstract class AbsActivitiesAdapter<Data> extends LoadMoreSupportAdapter<
|
|||
private final MediaLoadingHandler mLoadingHandler;
|
||||
private final int mCardBackgroundColor;
|
||||
private final boolean mCompactCards;
|
||||
private final TwidereLinkify mLinkify;
|
||||
private final DummyStatusHolderAdapter mStatusAdapterDelegate;
|
||||
private ActivityAdapterListener mActivityAdapterListener;
|
||||
|
||||
|
@ -80,14 +79,13 @@ public abstract class AbsActivitiesAdapter<Data> extends LoadMoreSupportAdapter<
|
|||
|
||||
protected AbsActivitiesAdapter(final Context context, boolean compact) {
|
||||
super(context);
|
||||
mStatusAdapterDelegate = new DummyStatusHolderAdapter(context);
|
||||
mStatusAdapterDelegate = new DummyStatusHolderAdapter(context, new TwidereLinkify(new OnLinkClickHandler(context, null)));
|
||||
mCardBackgroundColor = ThemeUtils.getCardBackgroundColor(context,
|
||||
ThemeUtils.getThemeBackgroundOption(context),
|
||||
ThemeUtils.getUserThemeBackgroundAlpha(context));
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mLoadingHandler = new MediaLoadingHandler(R.id.media_preview_progress);
|
||||
mCompactCards = compact;
|
||||
mLinkify = new TwidereLinkify(new OnLinkClickHandler(context, null));
|
||||
mStatusAdapterDelegate.updateOptions();
|
||||
}
|
||||
|
||||
|
@ -133,10 +131,6 @@ public abstract class AbsActivitiesAdapter<Data> extends LoadMoreSupportAdapter<
|
|||
return mStatusAdapterDelegate.getLinkHighlightingStyle();
|
||||
}
|
||||
|
||||
public TwidereLinkify getLinkify() {
|
||||
return mLinkify;
|
||||
}
|
||||
|
||||
public boolean isNameFirst() {
|
||||
return mStatusAdapterDelegate.isNameFirst();
|
||||
}
|
||||
|
|
|
@ -1263,7 +1263,8 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
|||
private static final int VIEW_TYPE_CONVERSATION_LOAD_INDICATOR = 2;
|
||||
private static final int VIEW_TYPE_REPLIES_LOAD_INDICATOR = 3;
|
||||
private static final int VIEW_TYPE_REPLY_ERROR = 4;
|
||||
private static final int VIEW_TYPE_SPACE = 5;
|
||||
private static final int VIEW_TYPE_CONVERSATION_ERROR = 5;
|
||||
private static final int VIEW_TYPE_SPACE = 6;
|
||||
private static final int ITEM_IDX_CONVERSATION_ERROR = 0;
|
||||
private static final int ITEM_IDX_CONVERSATION_LOAD_MORE = 1;
|
||||
private static final int ITEM_IDX_CONVERSATION = 2;
|
||||
|
@ -1300,7 +1301,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
|||
private List<ParcelableStatus> mConversation, mReplies;
|
||||
private StatusAdapterListener mStatusAdapterListener;
|
||||
private RecyclerView mRecyclerView;
|
||||
private CharSequence mReplyError;
|
||||
private CharSequence mReplyError, mConversationError;
|
||||
private boolean mRepliesLoading, mConversationsLoading;
|
||||
private TranslationResult mTranslationResult;
|
||||
|
||||
|
@ -1615,6 +1616,11 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
|||
errorHolder.showError(mReplyError);
|
||||
break;
|
||||
}
|
||||
case VIEW_TYPE_CONVERSATION_ERROR: {
|
||||
final StatusErrorItemViewHolder errorHolder = (StatusErrorItemViewHolder) holder;
|
||||
errorHolder.showError(mReplyError);
|
||||
break;
|
||||
}
|
||||
case VIEW_TYPE_CONVERSATION_LOAD_INDICATOR: {
|
||||
LoadIndicatorViewHolder indicatorHolder = ((LoadIndicatorViewHolder) holder);
|
||||
indicatorHolder.setLoadProgressVisible(mConversationsLoading);
|
||||
|
@ -1660,6 +1666,8 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
|||
return VIEW_TYPE_SPACE;
|
||||
case ITEM_IDX_REPLY_ERROR:
|
||||
return VIEW_TYPE_REPLY_ERROR;
|
||||
case ITEM_IDX_CONVERSATION_ERROR:
|
||||
return VIEW_TYPE_CONVERSATION_ERROR;
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
@ -1781,6 +1789,12 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
|||
updateItemDecoration();
|
||||
}
|
||||
|
||||
public void setConversationError(CharSequence error) {
|
||||
mConversationError = error;
|
||||
setCount(ITEM_IDX_CONVERSATION_ERROR, error != null ? 1 : 0);
|
||||
updateItemDecoration();
|
||||
}
|
||||
|
||||
public void setReplies(List<ParcelableStatus> replies) {
|
||||
mReplies = replies;
|
||||
setCount(ITEM_IDX_REPLY, replies != null ? replies.size() : 0);
|
||||
|
@ -1857,7 +1871,6 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
|||
|
||||
@Override
|
||||
public int getDecoratedMeasuredHeight(View child) {
|
||||
final int height = super.getDecoratedMeasuredHeight(child);
|
||||
int heightBeforeSpace = 0;
|
||||
if (getItemViewType(child) == StatusAdapter.VIEW_TYPE_SPACE) {
|
||||
for (int i = 0, j = getChildCount(); i < j; i++) {
|
||||
|
@ -1877,7 +1890,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
|||
return Math.max(0, spaceHeight);
|
||||
}
|
||||
}
|
||||
return height;
|
||||
return super.getDecoratedMeasuredHeight(child);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -22,12 +22,14 @@ package org.mariotaku.twidere.util;
|
|||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
|
||||
import org.apache.commons.collections.primitives.ArrayIntList;
|
||||
import org.apache.commons.collections.primitives.IntList;
|
||||
|
||||
import edu.tsinghua.hotmobi.HotMobiLogger;
|
||||
import edu.tsinghua.hotmobi.PreProcessing;
|
||||
import edu.tsinghua.hotmobi.model.SessionEvent;
|
||||
|
||||
/**
|
||||
|
@ -56,7 +58,7 @@ public class ActivityTracker implements Application.ActivityLifecycleCallbacks {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStarted(Activity activity) {
|
||||
public void onActivityStarted(final Activity activity) {
|
||||
mInternalStack.add(System.identityHashCode(activity));
|
||||
// BEGIN HotMobi
|
||||
if (mSessionEvent == null) {
|
||||
|
@ -82,9 +84,13 @@ public class ActivityTracker implements Application.ActivityLifecycleCallbacks {
|
|||
// BEGIN HotMobi
|
||||
final SessionEvent event = mSessionEvent;
|
||||
if (event != null && !isSwitchingInSameTask(hashCode)) {
|
||||
event.dumpPreferences(activity);
|
||||
event.markEnd();
|
||||
HotMobiLogger.getInstance(activity).log(event);
|
||||
HotMobiLogger.getInstance(activity).log(event, new PreProcessing<SessionEvent>() {
|
||||
@Override
|
||||
public void process(SessionEvent event, Context appContext) {
|
||||
event.dumpPreferences(appContext);
|
||||
}
|
||||
});
|
||||
mSessionEvent = null;
|
||||
}
|
||||
// END HotMobi
|
||||
|
|
|
@ -42,8 +42,9 @@ public class EmojiSupportUtils {
|
|||
for (int i = array.length() - 1; i >= 0; i--) {
|
||||
final int codePoint = array.get(i);
|
||||
if (isEmoji(codePoint)) {
|
||||
int arrayIdx = i, arrayEnd = i + 1;
|
||||
int textIdx = array.indexOfText(codePoint, i);
|
||||
int arrayIdx = i, arrayEnd = i + 1, arrayIdxOffset = 0;
|
||||
int textIdx = array.indexOfText(codePoint, i), textIdxOffset = 0;
|
||||
int indexOffset = 0;
|
||||
if (textIdx == -1 || textIdx < textStart) {
|
||||
continue;
|
||||
}
|
||||
|
@ -52,29 +53,58 @@ public class EmojiSupportUtils {
|
|||
if (i > 0) {
|
||||
int prev = array.get(i - 1);
|
||||
if (isRegionalIndicatorSymbol(prev)) {
|
||||
textIdx -= Character.charCount(prev);
|
||||
arrayIdx--;
|
||||
i--;
|
||||
arrayIdxOffset = -1;
|
||||
textIdxOffset = -Character.charCount(prev);
|
||||
indexOffset = -1;
|
||||
}
|
||||
}
|
||||
} else if (isModifier(codePoint)) {
|
||||
if (i > 0) {
|
||||
int prev = array.get(i - 1);
|
||||
if (isEmoji(prev)) {
|
||||
textIdx -= Character.charCount(prev);
|
||||
arrayIdx--;
|
||||
i--;
|
||||
arrayIdxOffset = -1;
|
||||
textIdxOffset = -Character.charCount(prev);
|
||||
indexOffset = -1;
|
||||
}
|
||||
}
|
||||
} else if (isKeyCap(codePoint)) {
|
||||
if (i > 0) {
|
||||
int prev = array.get(i - 1);
|
||||
if (isPhoneNumberSymbol(prev)) {
|
||||
arrayIdxOffset = -1;
|
||||
textIdxOffset = -Character.charCount(prev);
|
||||
indexOffset = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (textEnd > textStart + textLength) continue;
|
||||
final EmojiSpan[] spans = text.getSpans(textIdx, textEnd, EmojiSpan.class);
|
||||
if (spans.length > 0) continue;
|
||||
final Drawable drawable = emoji.getEmojiDrawableFor(array.subarray(arrayIdx, arrayEnd));
|
||||
if (drawable == null) continue;
|
||||
text.setSpan(new EmojiSpan(drawable), textIdx, textEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
EmojiSpan[] spans = text.getSpans(textIdx + textIdxOffset, textEnd, EmojiSpan.class);
|
||||
if (spans.length == 0) {
|
||||
Drawable drawable = emoji.getEmojiDrawableFor(array.subarray(arrayIdx + arrayIdxOffset,
|
||||
arrayEnd));
|
||||
if (drawable == null) {
|
||||
// Not emoji combination, just use fallback
|
||||
textIdxOffset = 0;
|
||||
arrayIdxOffset = 0;
|
||||
indexOffset = 0;
|
||||
spans = text.getSpans(textIdx + textIdxOffset, textEnd, EmojiSpan.class);
|
||||
if (spans.length == 0) {
|
||||
drawable = emoji.getEmojiDrawableFor(array.subarray(arrayIdx + arrayIdxOffset,
|
||||
arrayEnd));
|
||||
}
|
||||
}
|
||||
if (drawable != null) {
|
||||
text.setSpan(new EmojiSpan(drawable), textIdx + textIdxOffset, textEnd,
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
}
|
||||
i += indexOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isPhoneNumberSymbol(int codePoint) {
|
||||
return codePoint == 0x0023 || codePoint == 0x002a || inRange(codePoint, 0x0030, 0x0039);
|
||||
}
|
||||
|
||||
private static boolean isModifier(int codePoint) {
|
||||
|
@ -93,4 +123,8 @@ public class EmojiSupportUtils {
|
|||
return inRange(codePoint, 0x1f1e6, 0x1f1ff);
|
||||
}
|
||||
|
||||
private static boolean isKeyCap(int codePoint) {
|
||||
return codePoint == 0x20e3;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,8 +11,11 @@ import android.support.annotation.Nullable;
|
|||
import android.text.TextUtils;
|
||||
import android.webkit.URLUtil;
|
||||
|
||||
import com.squareup.okhttp.Authenticator;
|
||||
import com.squareup.okhttp.Dns;
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
import com.squareup.okhttp.Request;
|
||||
import com.squareup.okhttp.Response;
|
||||
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
import org.mariotaku.restfu.ExceptionFactory;
|
||||
|
@ -51,6 +54,7 @@ import org.mariotaku.twidere.model.RequestType;
|
|||
import org.mariotaku.twidere.util.dagger.ApplicationModule;
|
||||
import org.mariotaku.twidere.util.net.NetworkUsageUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.SocketAddress;
|
||||
|
@ -118,6 +122,7 @@ public class TwitterAPIFactory implements TwidereConstants {
|
|||
final OkHttpClient client = new OkHttpClient();
|
||||
updateHttpClientConfiguration(prefs, client);
|
||||
client.setDns(dns);
|
||||
DebugModeUtils.initForHttpClient(client);
|
||||
NetworkUsageUtils.initForHttpClient(context, client);
|
||||
return new OkHttpRestClient(client);
|
||||
}
|
||||
|
@ -386,8 +391,8 @@ public class TwitterAPIFactory implements TwidereConstants {
|
|||
sExtraParams.put("include_cards", "true");
|
||||
sExtraParams.put("cards_platform", "Android-12");
|
||||
sExtraParams.put("include_entities", "true");
|
||||
sExtraParams.put("include_my_retweet", "1");
|
||||
sExtraParams.put("include_rts", "1");
|
||||
sExtraParams.put("include_my_retweet", "true");
|
||||
sExtraParams.put("include_rts", "true");
|
||||
sExtraParams.put("include_reply_count", "true");
|
||||
sExtraParams.put("include_descendent_reply_count", "true");
|
||||
sExtraParams.put("full_text", "true");
|
||||
|
|
|
@ -38,11 +38,16 @@ import org.mariotaku.twidere.util.ConnectivityUtils;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/6/24.
|
||||
*/
|
||||
public class NetworkUsageUtils implements Constants {
|
||||
|
||||
private static final Executor sNetworkUsageExecutor = Executors.newSingleThreadExecutor();
|
||||
|
||||
public static void initForHttpClient(Context context, OkHttpClient client) {
|
||||
final List<Interceptor> interceptors = client.networkInterceptors();
|
||||
interceptors.add(new NetworkUsageInterceptor(context));
|
||||
|
@ -74,12 +79,17 @@ public class NetworkUsageUtils implements Constants {
|
|||
values.put(NetworkUsages.REQUEST_NETWORK, sNetworkType);
|
||||
final Response response = chain.proceed(request);
|
||||
values.put(NetworkUsages.KILOBYTES_RECEIVED, getBodyLength(response.body()) / 1024.0);
|
||||
sNetworkUsageExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final ContentResolver cr = context.getContentResolver();
|
||||
try {
|
||||
cr.insert(NetworkUsages.CONTENT_URI, values);
|
||||
} catch (IllegalStateException e) {
|
||||
Log.e(LOGTAG, "Unable to log network usage", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
return response;
|
||||
}
|
||||
|
||||
|
|
|
@ -87,8 +87,8 @@ public class TwidereDns implements Constants, Dns {
|
|||
// First, I'll try to load address cached.
|
||||
final InetAddress[] cachedHostAddr = mHostCache.get(host);
|
||||
if (cachedHostAddr != null) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.d(RESOLVER_LOGTAG, "Got cached " + Arrays.toString(cachedHostAddr));
|
||||
if (BuildConfig.DEBUG && Log.isLoggable(RESOLVER_LOGTAG, Log.VERBOSE)) {
|
||||
Log.v(RESOLVER_LOGTAG, "Got cached " + Arrays.toString(cachedHostAddr));
|
||||
return cachedHostAddr;
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ public class TwidereDns implements Constants, Dns {
|
|||
final InetAddress[] hostAddr = fromAddressString(originalHost, mappedAddr);
|
||||
putCache(originalHost, hostAddr);
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.d(RESOLVER_LOGTAG, "Got mapped " + Arrays.toString(hostAddr));
|
||||
Log.v(RESOLVER_LOGTAG, "Got mapped " + Arrays.toString(hostAddr));
|
||||
}
|
||||
if (hostAddr != null) {
|
||||
return hostAddr;
|
||||
|
@ -110,8 +110,8 @@ public class TwidereDns implements Constants, Dns {
|
|||
try {
|
||||
final InetAddress[] hostAddr = mResolver.resolve(host);
|
||||
putCache(originalHost, hostAddr);
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.d(RESOLVER_LOGTAG, "Got hosts " + Arrays.toString(hostAddr));
|
||||
if (BuildConfig.DEBUG && Log.isLoggable(RESOLVER_LOGTAG, Log.VERBOSE)) {
|
||||
Log.v(RESOLVER_LOGTAG, "Got hosts " + Arrays.toString(hostAddr));
|
||||
}
|
||||
return hostAddr;
|
||||
} catch (UnknownHostException e) {
|
||||
|
@ -121,8 +121,8 @@ public class TwidereDns implements Constants, Dns {
|
|||
if (customMappedHost != null) {
|
||||
final InetAddress[] hostAddr = fromAddressString(originalHost, customMappedHost);
|
||||
putCache(originalHost, hostAddr);
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.d(RESOLVER_LOGTAG, "Got mapped address " + customMappedHost + " for host " + host);
|
||||
if (BuildConfig.DEBUG && Log.isLoggable(RESOLVER_LOGTAG, Log.VERBOSE)) {
|
||||
Log.v(RESOLVER_LOGTAG, "Got mapped address " + customMappedHost + " for host " + host);
|
||||
}
|
||||
if (hostAddr != null) {
|
||||
return hostAddr;
|
||||
|
@ -154,8 +154,8 @@ public class TwidereDns implements Constants, Dns {
|
|||
if (!resolvedAddresses.isEmpty()) {
|
||||
final InetAddress[] hostAddr = resolvedAddresses.toArray(new InetAddress[resolvedAddresses.size()]);
|
||||
putCache(originalHost, hostAddr);
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.d(RESOLVER_LOGTAG, "Resolved " + Arrays.toString(hostAddr));
|
||||
if (BuildConfig.DEBUG && Log.isLoggable(RESOLVER_LOGTAG, Log.VERBOSE)) {
|
||||
Log.v(RESOLVER_LOGTAG, "Resolved " + Arrays.toString(hostAddr));
|
||||
}
|
||||
return hostAddr;
|
||||
}
|
||||
|
@ -166,8 +166,8 @@ public class TwidereDns implements Constants, Dns {
|
|||
return resolveInternal(originalHost, ((CNAMERecord) record).getTarget().toString());
|
||||
}
|
||||
}
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.w(RESOLVER_LOGTAG, "Resolve address " + host + " failed, using original host");
|
||||
if (BuildConfig.DEBUG && Log.isLoggable(RESOLVER_LOGTAG, Log.VERBOSE)) {
|
||||
Log.v(RESOLVER_LOGTAG, "Resolve address " + host + " failed, using original host");
|
||||
}
|
||||
final InetAddress[] defaultAddresses = InetAddress.getAllByName(host);
|
||||
putCache(host, defaultAddresses);
|
||||
|
|
|
@ -31,6 +31,8 @@ import org.mariotaku.twidere.Constants;
|
|||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.view.themed.ThemedTextView;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import static android.text.format.DateUtils.getRelativeTimeSpanString;
|
||||
import static org.mariotaku.twidere.util.Utils.formatSameDayTime;
|
||||
|
||||
|
@ -111,17 +113,19 @@ public class ShortTimeView extends ThemedTextView implements Constants, OnShared
|
|||
|
||||
private static class TickerRunnable implements Runnable {
|
||||
|
||||
private final ShortTimeView mTextView;
|
||||
private final WeakReference<ShortTimeView> mViewRef;
|
||||
|
||||
private TickerRunnable(final ShortTimeView view) {
|
||||
mTextView = view;
|
||||
mViewRef = new WeakReference<>(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
final Handler handler = mTextView.getHandler();
|
||||
final ShortTimeView view = mViewRef.get();
|
||||
if (view == null) return;
|
||||
final Handler handler = view.getHandler();
|
||||
if (handler == null) return;
|
||||
mTextView.invalidateTime();
|
||||
view.invalidateTime();
|
||||
final long now = SystemClock.uptimeMillis();
|
||||
final long next = now + TICKER_DURATION - now % TICKER_DURATION;
|
||||
handler.postAtTime(this, next);
|
||||
|
|
|
@ -26,7 +26,6 @@ import android.database.Cursor;
|
|||
import android.os.Bundle;
|
||||
import android.support.v7.widget.RecyclerView.ViewHolder;
|
||||
import android.text.Spanned;
|
||||
import android.text.method.ArrowKeyMovementMethod;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
@ -38,7 +37,6 @@ import org.mariotaku.twidere.model.ParcelableMedia;
|
|||
import org.mariotaku.twidere.util.HtmlSpanBuilder;
|
||||
import org.mariotaku.twidere.util.JsonSerializer;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.StatusActionModeCallback;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
import org.mariotaku.twidere.util.TwidereColorUtils;
|
||||
import org.mariotaku.twidere.util.TwidereLinkify;
|
||||
|
@ -55,7 +53,6 @@ public class MessageViewHolder extends ViewHolder implements OnMediaClickListene
|
|||
protected final MessageConversationAdapter adapter;
|
||||
|
||||
private final int textColorPrimary, textColorPrimaryInverse, textColorSecondary, textColorSecondaryInverse;
|
||||
private final StatusActionModeCallback callback;
|
||||
|
||||
|
||||
public MessageViewHolder(final MessageConversationAdapter adapter, final View itemView) {
|
||||
|
@ -75,7 +72,6 @@ public class MessageViewHolder extends ViewHolder implements OnMediaClickListene
|
|||
time = (TextView) itemView.findViewById(R.id.time);
|
||||
mediaContainer = (CardMediaContainer) itemView.findViewById(R.id.media_preview_container);
|
||||
mediaContainer.setStyle(adapter.getMediaPreviewStyle());
|
||||
callback = new StatusActionModeCallback(textView, adapter.getContext());
|
||||
}
|
||||
|
||||
public void displayMessage(Cursor cursor, ParcelableDirectMessageCursorIndices indices) {
|
||||
|
@ -92,10 +88,6 @@ public class MessageViewHolder extends ViewHolder implements OnMediaClickListene
|
|||
time.setText(Utils.formatToLongTimeString(context, timestamp));
|
||||
mediaContainer.setVisibility(media != null && media.length > 0 ? View.VISIBLE : View.GONE);
|
||||
mediaContainer.displayMedia(media, loader, accountId, true, this, adapter.getMediaLoadingHandler());
|
||||
|
||||
textView.setTextIsSelectable(true);
|
||||
textView.setMovementMethod(ArrowKeyMovementMethod.getInstance());
|
||||
textView.setCustomSelectionActionModeCallback(callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -471,11 +471,15 @@ public class StatusViewHolder extends ViewHolder implements Constants, OnClickLi
|
|||
private boolean useStarsForLikes;
|
||||
|
||||
public DummyStatusHolderAdapter(Context context) {
|
||||
this(context, new TwidereLinkify(null));
|
||||
}
|
||||
|
||||
public DummyStatusHolderAdapter(Context context, TwidereLinkify linkify) {
|
||||
DaggerGeneralComponent.builder().applicationModule(ApplicationModule.get(context)).build().inject(this);
|
||||
this.context = context;
|
||||
preferences = SharedPreferencesWrapper.getInstance(context, SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
handler = new MediaLoadingHandler(R.id.media_preview_progress);
|
||||
linkify = new TwidereLinkify(null);
|
||||
this.linkify = linkify;
|
||||
updateOptions();
|
||||
}
|
||||
|
||||
|
|
|
@ -17,10 +17,11 @@
|
|||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<org.mariotaku.twidere.view.ExtendedRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<org.mariotaku.twidere.view.ExtendedRelativeLayout
|
||||
android:id="@+id/main_content"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="@dimen/element_spacing_normal">
|
||||
|
@ -53,7 +54,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="0"
|
||||
tools:listitem="@layout/spinner_item_account_icon" />
|
||||
tools:listitem="@layout/spinner_item_account_icon"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/search_query"
|
||||
|
@ -65,7 +66,7 @@
|
|||
android:hint="@string/search_hint"
|
||||
android:inputType="text|textMultiLine">
|
||||
|
||||
<requestFocus />
|
||||
<requestFocus/>
|
||||
</EditText>
|
||||
|
||||
<org.mariotaku.twidere.view.ActionIconButton
|
||||
|
@ -75,14 +76,14 @@
|
|||
android:layout_weight="0"
|
||||
android:background="?actionBarItemBackground"
|
||||
android:color="?menuIconColor"
|
||||
android:src="@drawable/ic_action_search" />
|
||||
android:src="@drawable/ic_action_search"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="2dp"
|
||||
android:background="#20808080" />
|
||||
android:background="#20808080"/>
|
||||
|
||||
<ListView
|
||||
android:id="@+id/suggestions_list"
|
||||
|
@ -90,7 +91,7 @@
|
|||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:listSelector="?selectableItemBackground"
|
||||
tools:listitem="@layout/list_item_user" />
|
||||
tools:listitem="@layout/list_item_user"/>
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<include layout="@layout/layout_card_media_preview" />
|
||||
<include layout="@layout/layout_card_media_preview"/>
|
||||
|
||||
</org.mariotaku.twidere.view.CardMediaContainer>
|
||||
|
||||
|
@ -45,8 +45,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textIsSelectable="true"
|
||||
tools:text="@string/sample_status_text" />
|
||||
tools:text="@string/sample_status_text"/>
|
||||
|
||||
<org.mariotaku.twidere.view.themed.ThemedTextView
|
||||
android:id="@+id/time"
|
||||
|
@ -54,6 +53,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/element_spacing_small"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
tools:text="12:00" />
|
||||
tools:text="12:00"/>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
|
@ -16,10 +16,10 @@
|
|||
~ You should have received a copy of the GNU General Public License
|
||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<org.mariotaku.twidere.view.ColorLabelFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<org.mariotaku.twidere.view.ColorLabelFrameLayout android:id="@+id/item_content"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/item_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:background="?cardItemBackgroundColor">
|
||||
|
@ -47,7 +47,7 @@
|
|||
android:scaleType="centerInside"
|
||||
android:visibility="gone"
|
||||
tools:src="@drawable/ic_activity_action_retweet"
|
||||
tools:visibility="visible" />
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<org.mariotaku.twidere.view.ActionIconThemedTextView
|
||||
android:id="@+id/reply_retweet_status"
|
||||
|
@ -66,7 +66,7 @@
|
|||
android:visibility="gone"
|
||||
tools:text="Retweeted by Mariotaku"
|
||||
tools:textSize="@dimen/text_size_extra_small"
|
||||
tools:visibility="visible" />
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<org.mariotaku.twidere.view.ProfileImageView
|
||||
android:id="@+id/profile_image"
|
||||
|
@ -83,7 +83,7 @@
|
|||
android:layout_marginRight="@dimen/element_spacing_small"
|
||||
android:contentDescription="@string/profile_image"
|
||||
android:scaleType="centerCrop"
|
||||
tools:visibility="visible" />
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<org.mariotaku.twidere.view.BoundsImageView
|
||||
android:id="@+id/profile_type"
|
||||
|
@ -96,7 +96,7 @@
|
|||
android:layout_marginEnd="@dimen/element_spacing_minus_small"
|
||||
android:layout_marginRight="@dimen/element_spacing_minus_small"
|
||||
android:scaleType="fitCenter"
|
||||
tools:visibility="gone" />
|
||||
tools:visibility="gone"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/status_content"
|
||||
|
@ -123,7 +123,7 @@
|
|||
android:layout_weight="1"
|
||||
app:nv_primaryTextColor="?android:textColorPrimary"
|
||||
app:nv_primaryTextStyle="bold"
|
||||
app:nv_secondaryTextColor="?android:textColorSecondary" />
|
||||
app:nv_secondaryTextColor="?android:textColorSecondary"/>
|
||||
|
||||
<org.mariotaku.twidere.view.ShortTimeView
|
||||
android:id="@+id/time"
|
||||
|
@ -132,7 +132,7 @@
|
|||
android:layout_weight="0"
|
||||
android:textAppearance="?android:textAppearanceSmall"
|
||||
tools:text="42 mins ago"
|
||||
tools:textSize="@dimen/text_size_extra_small" />
|
||||
tools:textSize="@dimen/text_size_extra_small"/>
|
||||
|
||||
<org.mariotaku.twidere.view.ActionIconView
|
||||
android:id="@+id/extra_type"
|
||||
|
@ -140,7 +140,7 @@
|
|||
android:layout_height="@dimen/element_size_small"
|
||||
android:layout_weight="0"
|
||||
android:color="?android:textColorSecondary"
|
||||
tools:src="@drawable/ic_action_gallery" />
|
||||
tools:src="@drawable/ic_action_gallery"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
@ -156,9 +156,8 @@
|
|||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:visibility="visible"
|
||||
app:nv_primaryTextStyle="bold"
|
||||
tools:text="@string/sample_status_text"
|
||||
tools:visibility="visible" />
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<org.mariotaku.twidere.view.ForegroundColorView
|
||||
android:id="@+id/quote_indicator"
|
||||
|
@ -171,7 +170,7 @@
|
|||
android:layout_marginRight="@dimen/element_spacing_normal"
|
||||
android:background="?quoteIndicatorBackgroundColor"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<org.mariotaku.twidere.view.NameView
|
||||
android:id="@+id/quoted_name"
|
||||
|
@ -185,7 +184,7 @@
|
|||
android:visibility="gone"
|
||||
app:nv_primaryTextColor="?android:textColorPrimary"
|
||||
app:nv_secondaryTextColor="?android:textColorSecondary"
|
||||
tools:visibility="visible" />
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<org.mariotaku.twidere.view.TimelineContentTextView
|
||||
android:id="@+id/quoted_text"
|
||||
|
@ -200,7 +199,7 @@
|
|||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:visibility="gone"
|
||||
tools:text="@string/sample_status_text"
|
||||
tools:visibility="visible" />
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<org.mariotaku.twidere.view.CardMediaContainer
|
||||
android:id="@+id/media_preview"
|
||||
|
@ -248,7 +247,7 @@
|
|||
android:paddingRight="@dimen/element_spacing_normal"
|
||||
android:textAppearance="?android:textAppearanceSmall"
|
||||
app:iabActivatedColor="@color/highlight_reply"
|
||||
app:iabColor="?android:textColorTertiary" />
|
||||
app:iabColor="?android:textColorTertiary"/>
|
||||
|
||||
<org.mariotaku.twidere.view.ActionIconThemedTextView
|
||||
android:id="@+id/retweet_count"
|
||||
|
@ -264,7 +263,7 @@
|
|||
android:paddingRight="@dimen/element_spacing_normal"
|
||||
android:textAppearance="?android:textAppearanceSmall"
|
||||
app:iabActivatedColor="@color/highlight_retweet"
|
||||
app:iabColor="?android:textColorTertiary" />
|
||||
app:iabColor="?android:textColorTertiary"/>
|
||||
|
||||
<org.mariotaku.twidere.view.ActionIconThemedTextView
|
||||
android:id="@+id/favorite_count"
|
||||
|
@ -280,7 +279,7 @@
|
|||
android:paddingRight="@dimen/element_spacing_normal"
|
||||
android:textAppearance="?android:textAppearanceSmall"
|
||||
app:iabActivatedColor="@color/highlight_like"
|
||||
app:iabColor="?android:textColorTertiary" />
|
||||
app:iabColor="?android:textColorTertiary"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
@ -296,7 +295,7 @@
|
|||
android:color="?android:textColorTertiary"
|
||||
android:focusable="false"
|
||||
android:src="@drawable/ic_action_more_horizontal"
|
||||
tools:visibility="visible" />
|
||||
tools:visibility="visible"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</org.mariotaku.twidere.view.ColorLabelFrameLayout>
|
|
@ -17,10 +17,13 @@
|
|||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<org.mariotaku.twidere.view.SquareFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<org.mariotaku.twidere.view.SquareFrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="@dimen/element_spacing_small">
|
||||
android:padding="@dimen/element_spacing_small"
|
||||
tools:layout_width="48dp">
|
||||
|
||||
<org.mariotaku.twidere.view.ProfileImageView
|
||||
android:id="@android:id/icon"
|
||||
|
@ -29,6 +32,6 @@
|
|||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:contentDescription="@string/profile_image"
|
||||
android:scaleType="centerCrop" />
|
||||
android:scaleType="centerCrop"/>
|
||||
|
||||
</org.mariotaku.twidere.view.SquareFrameLayout>
|
Loading…
Reference in New Issue