1
0
mirror of https://github.com/TwidereProject/Twidere-Android synced 2025-02-17 04:00:48 +01:00

removed some library dependencies from extensions library

This commit is contained in:
Mariotaku Lee 2016-02-24 13:07:24 +08:00
parent dbca8e96c5
commit f4bab1c81a
60 changed files with 902 additions and 762 deletions

View File

@ -40,9 +40,7 @@ dependencies {
apt 'com.hannesdorfmann.parcelableplease:processor:1.0.2'
apt 'com.github.mariotaku.ObjectCursor:processor:0.9.4'
compile 'com.android.support:support-annotations:23.1.1'
compile 'com.android.support:support-v4:23.1.1'
compile 'com.bluelinelabs:logansquare:1.3.4'
compile 'org.apache.commons:commons-lang3:3.4'
compile 'com.github.mariotaku.RestFu:library:0.9.21'
compile 'com.hannesdorfmann.parcelableplease:annotation:1.0.2'
compile 'com.github.mariotaku.ObjectCursor:core:0.9.4'

View File

@ -19,12 +19,11 @@
package org.mariotaku.twidere.api.twitter.model;
import android.support.v4.util.ArrayMap;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
import com.bluelinelabs.logansquare.annotation.OnJsonParseComplete;
import java.util.HashMap;
import java.util.Map;
/**
@ -66,7 +65,7 @@ public class CardEntity {
@OnJsonParseComplete
void onParseComplete() {
if (rawBindingValues != null) {
bindingValues = new ArrayMap<>();
bindingValues = new HashMap<>();
for (Map.Entry<String, RawBindingValue> entry : rawBindingValues.entrySet()) {
bindingValues.put(entry.getKey(), entry.getValue().getBindingValue());
}

View File

@ -23,15 +23,14 @@ import android.util.Log;
import com.bluelinelabs.logansquare.typeconverters.StringBasedTypeConverter;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;
import java.util.SimpleTimeZone;
import java.util.TimeZone;
@ -75,40 +74,35 @@ public class TwitterDateConverter extends StringBasedTypeConverter<Date> {
}
private Date parseTwitterDate(String string) {
final String[] segs = StringUtils.split(string, ' ');
if (segs.length != 6) {
final List<String> segs = split(string, " ");
if (segs.size() != 6) {
return null;
}
final String[] timeSegs = StringUtils.split(segs[3], ':');
if (timeSegs.length != 3) {
final List<String> timeSegs = split(segs.get(3), ":");
if (timeSegs.size() != 3) {
return null;
}
final GregorianCalendar calendar = new GregorianCalendar(TIME_ZONE, LOCALE);
calendar.clear();
final int monthIdx = ArrayUtils.indexOf(MONTH_NAMES, segs[1]);
final int monthIdx = indexOf(MONTH_NAMES, segs.get(1));
if (monthIdx < 0) {
return null;
}
calendar.set(Calendar.YEAR, Integer.parseInt(segs[5]));
calendar.set(Calendar.YEAR, Integer.parseInt(segs.get(5)));
calendar.set(Calendar.MONTH, monthIdx);
calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(segs[2]));
calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(timeSegs[0]));
calendar.set(Calendar.MINUTE, Integer.parseInt(timeSegs[1]));
calendar.set(Calendar.SECOND, Integer.parseInt(timeSegs[2]));
calendar.setTimeZone(SimpleTimeZone.getTimeZone(getTimezoneText(segs[4])));
calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(segs.get(2)));
calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(timeSegs.get(0)));
calendar.set(Calendar.MINUTE, Integer.parseInt(timeSegs.get(1)));
calendar.set(Calendar.SECOND, Integer.parseInt(timeSegs.get(2)));
calendar.setTimeZone(SimpleTimeZone.getTimeZone(getTimezoneText(segs.get(4))));
final Date date = calendar.getTime();
if (!WEEK_NAMES[calendar.get(Calendar.DAY_OF_WEEK) - 1].equals(segs[0])) {
if (!WEEK_NAMES[calendar.get(Calendar.DAY_OF_WEEK) - 1].equals(segs.get(0))) {
return null;
}
return date;
}
private String getTimezoneText(String seg) {
if (seg.startsWith("GMT") || seg.startsWith("UTC")) return seg;
return "GMT" + seg;
}
@Override
public String convertToString(Date date) {
final Calendar calendar = Calendar.getInstance();
@ -134,4 +128,34 @@ public class TwitterDateConverter extends StringBasedTypeConverter<Date> {
return sb.toString();
}
private String getTimezoneText(String seg) {
if (seg.startsWith("GMT") || seg.startsWith("UTC")) return seg;
return "GMT" + seg;
}
private static List<String> split(String input, String delim) {
List<String> l = new ArrayList<>();
int offset = 0;
while (true) {
int index = input.indexOf(delim, offset);
if (index == -1) {
l.add(input.substring(offset));
return l;
} else {
l.add(input.substring(offset, index));
offset = (index + delim.length());
}
}
}
private static int indexOf(String[] input, String find) {
for (int i = 0, inputLength = input.length; i < inputLength; i++) {
if (find == null) {
if (input[i] == null) return i;
} else if (find.equals(input[i])) return i;
}
return -1;
}
}

View File

@ -22,8 +22,8 @@ package org.mariotaku.twidere.model;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.util.ArrayMap;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
@ -32,13 +32,10 @@ import com.hannesdorfmann.parcelableplease.annotation.Bagger;
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
import com.hannesdorfmann.parcelableplease.annotation.ParcelableThisPlease;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.mariotaku.twidere.api.twitter.model.CardEntity;
import java.text.ParseException;
import java.util.Date;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
@ -81,74 +78,21 @@ public final class ParcelableCardEntity implements Parcelable {
}
public ParcelableCardEntity(CardEntity card, long accountId) {
name = card.getName();
url = card.getUrl();
users = ParcelableUser.fromUsersArray(card.getUsers(), accountId);
account_id = accountId;
values = ParcelableBindingValue.from(card.getBindingValues());
}
public static ParcelableCardEntity fromCardEntity(CardEntity card, long accountId) {
if (card == null) return null;
return new ParcelableCardEntity(card, accountId);
}
@Nullable
public ParcelableBindingValue getValue(@Nullable String key) {
if (key == null || values == null) return null;
public ParcelableBindingValue getValue(@NonNull String key) {
if (values == null) return null;
return values.get(key);
}
public boolean getAsBoolean(@Nullable String key, boolean def) {
final ParcelableBindingValue value = getValue(key);
if (value == null) return def;
return Boolean.parseBoolean(value.value);
}
public String getAsString(@Nullable String key, String def) {
final ParcelableBindingValue value = getValue(key);
if (value == null) return def;
return value.value;
}
public String getString(@Nullable String key) {
final ParcelableBindingValue value = getValue(key);
if (value == null || !CardEntity.BindingValue.TYPE_STRING.equals(value.type)) return null;
return value.value;
}
public int getAsInteger(@Nullable String key, int def) {
final ParcelableBindingValue value = getValue(key);
if (value == null) return def;
return NumberUtils.toInt(value.value, def);
}
public long getAsLong(@Nullable String key, long def) {
final ParcelableBindingValue value = getValue(key);
if (value == null) return def;
return NumberUtils.toLong(value.value, def);
}
public Date getAsDate(String key, Date def) {
final ParcelableBindingValue value = getValue(key);
if (value == null) return def;
try {
return DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.parse(value.value);
} catch (ParseException e) {
return def;
}
}
@Override
public String toString() {
return new ToStringBuilder(this)
.append("account_id", account_id)
.append("name", name)
.append("url", url)
.append("users", users)
.append("values", values)
.toString();
return "ParcelableCardEntity{" +
"account_id=" + account_id +
", name='" + name + '\'' +
", url='" + url + '\'' +
", users=" + Arrays.toString(users) +
", values=" + values +
'}';
}
@Override
@ -181,7 +125,7 @@ public final class ParcelableCardEntity implements Parcelable {
public Map<String, ParcelableBindingValue> read(Parcel in) {
final int size = in.readInt();
if (size == -1) return null;
final Map<String, ParcelableBindingValue> map = new ArrayMap<>(size);
final Map<String, ParcelableBindingValue> map = new HashMap<>(size);
for (int i = 0; i < size; i++) {
final String key = in.readString();
final ParcelableBindingValue value = in.readParcelable(ParcelableBindingValue.class.getClassLoader());
@ -236,15 +180,6 @@ public final class ParcelableCardEntity implements Parcelable {
}
}
public static Map<String, ParcelableBindingValue> from(Map<String, CardEntity.BindingValue> bindingValues) {
if (bindingValues == null) return null;
final ArrayMap<String, ParcelableBindingValue> map = new ArrayMap<>();
for (Map.Entry<String, CardEntity.BindingValue> entry : bindingValues.entrySet()) {
map.put(entry.getKey(), new ParcelableBindingValue(entry.getValue()));
}
return map;
}
@Override
public String toString() {
return value + " (" + type + ")";

View File

@ -29,7 +29,6 @@ import android.support.annotation.Nullable;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
import org.apache.commons.lang3.math.NumberUtils;
import org.mariotaku.library.objectcursor.converter.CursorFieldConverter;
import org.mariotaku.twidere.api.twitter.model.GeoLocation;
import org.mariotaku.twidere.util.ParseUtils;
@ -79,20 +78,32 @@ public class ParcelableLocation implements Parcelable {
longitude = in.readDouble();
}
public ParcelableLocation(final String locationString) {
if (locationString == null) {
latitude = Double.NaN;
longitude = Double.NaN;
return;
}
@Nullable
public static ParcelableLocation fromString(@Nullable final String locationString) {
if (locationString == null) return null;
final String[] longlat = locationString.split(",");
if (longlat.length != 2) {
latitude = Double.NaN;
longitude = Double.NaN;
} else {
latitude = NumberUtils.toDouble(longlat[0], Double.NaN);
longitude = NumberUtils.toDouble(longlat[1], Double.NaN);
return null;
}
ParcelableLocation obj = new ParcelableLocation();
try {
obj.latitude = Double.parseDouble(longlat[0]);
obj.longitude = Double.parseDouble(longlat[1]);
} catch (NumberFormatException e) {
return null;
}
if (isValidLocation(obj)) return obj;
return null;
}
public static String toString(final ParcelableLocation location) {
if (!isValidLocation(location)) return null;
return toString(location.latitude, location.longitude);
}
public static String toString(double latitude, double longitude) {
return latitude + "," + longitude;
}
@Override
@ -166,12 +177,6 @@ public class ParcelableLocation implements Parcelable {
out.writeDouble(longitude);
}
public static ParcelableLocation fromString(final String string) {
final ParcelableLocation location = new ParcelableLocation(string);
if (ParcelableLocation.isValidLocation(location)) return location;
return null;
}
public static boolean isValidLocation(final ParcelableLocation location) {
return location != null && location.isValid();
}
@ -180,15 +185,6 @@ public class ParcelableLocation implements Parcelable {
return isValidLocation(location) ? location.toGeoLocation() : null;
}
public static String toString(final ParcelableLocation location) {
if (!isValidLocation(location)) return null;
return toString(location.latitude, location.longitude);
}
public static String toString(double latitude, double longitude) {
return latitude + "," + longitude;
}
public static class Converter implements CursorFieldConverter<ParcelableLocation> {
@Override
public ParcelableLocation parseField(Cursor cursor, int columnIndex, ParameterizedType fieldType) {

View File

@ -31,18 +31,15 @@ import com.bluelinelabs.logansquare.annotation.OnJsonParseComplete;
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
import com.hannesdorfmann.parcelableplease.annotation.ParcelableThisPlease;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.mariotaku.library.objectcursor.annotation.AfterCursorObjectCreated;
import org.mariotaku.library.objectcursor.annotation.CursorField;
import org.mariotaku.library.objectcursor.annotation.CursorObject;
import org.mariotaku.twidere.api.twitter.model.Place;
import org.mariotaku.twidere.api.twitter.model.Status;
import org.mariotaku.twidere.model.util.LoganSquareCursorFieldConverter;
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
@CursorObject(valuesCreator = true)
@JsonObject
@ -351,65 +348,65 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
@Override
public String toString() {
return new ToStringBuilder(this)
.append("id", id)
.append("account_id", account_id)
.append("timestamp", timestamp)
.append("user_id", user_id)
.append("retweet_id", retweet_id)
.append("retweeted_by_user_id", retweeted_by_user_id)
.append("retweet_timestamp", retweet_timestamp)
.append("retweet_count", retweet_count)
.append("favorite_count", favorite_count)
.append("reply_count", reply_count)
.append("in_reply_to_status_id", in_reply_to_status_id)
.append("in_reply_to_user_id", in_reply_to_user_id)
.append("my_retweet_id", my_retweet_id)
.append("quoted_id", quoted_id)
.append("quoted_timestamp", quoted_timestamp)
.append("quoted_user_id", quoted_user_id)
.append("is_gap", is_gap)
.append("is_retweet", is_retweet)
.append("retweeted", retweeted)
.append("is_favorite", is_favorite)
.append("is_possibly_sensitive", is_possibly_sensitive)
.append("user_is_following", user_is_following)
.append("user_is_protected", user_is_protected)
.append("user_is_verified", user_is_verified)
.append("is_quote", is_quote)
.append("quoted_user_is_protected", quoted_user_is_protected)
.append("quoted_user_is_verified", quoted_user_is_verified)
.append("retweeted_by_user_name", retweeted_by_user_name)
.append("retweeted_by_user_screen_name", retweeted_by_user_screen_name)
.append("retweeted_by_user_profile_image", retweeted_by_user_profile_image)
.append("text_html", text_html)
.append("text_plain", text_plain)
.append("lang", lang)
.append("user_name", user_name)
.append("user_screen_name", user_screen_name)
.append("in_reply_to_name", in_reply_to_name)
.append("in_reply_to_screen_name", in_reply_to_screen_name)
.append("source", source)
.append("user_profile_image_url", user_profile_image_url)
.append("text_unescaped", text_unescaped)
.append("card_name", card_name)
.append("quoted_text_html", quoted_text_html)
.append("quoted_text_plain", quoted_text_plain)
.append("quoted_text_unescaped", quoted_text_unescaped)
.append("quoted_source", quoted_source)
.append("quoted_user_name", quoted_user_name)
.append("quoted_user_screen_name", quoted_user_screen_name)
.append("quoted_user_profile_image", quoted_user_profile_image)
.append("quoted_location", quoted_location)
.append("quoted_place_full_name", quoted_place_full_name)
.append("location", location)
.append("place_full_name", place_full_name)
.append("mentions", mentions)
.append("media", media)
.append("quoted_media", quoted_media)
.append("card", card)
.append("_id", _id)
.toString();
return "ParcelableStatus{" +
"id=" + id +
", account_id=" + account_id +
", timestamp=" + timestamp +
", user_id=" + user_id +
", retweet_id=" + retweet_id +
", retweeted_by_user_id=" + retweeted_by_user_id +
", retweet_timestamp=" + retweet_timestamp +
", retweet_count=" + retweet_count +
", favorite_count=" + favorite_count +
", reply_count=" + reply_count +
", in_reply_to_status_id=" + in_reply_to_status_id +
", in_reply_to_user_id=" + in_reply_to_user_id +
", my_retweet_id=" + my_retweet_id +
", quoted_id=" + quoted_id +
", quoted_timestamp=" + quoted_timestamp +
", quoted_user_id=" + quoted_user_id +
", is_gap=" + is_gap +
", is_retweet=" + is_retweet +
", retweeted=" + retweeted +
", is_favorite=" + is_favorite +
", is_possibly_sensitive=" + is_possibly_sensitive +
", user_is_following=" + user_is_following +
", user_is_protected=" + user_is_protected +
", user_is_verified=" + user_is_verified +
", is_quote=" + is_quote +
", quoted_user_is_protected=" + quoted_user_is_protected +
", quoted_user_is_verified=" + quoted_user_is_verified +
", retweeted_by_user_name='" + retweeted_by_user_name + '\'' +
", retweeted_by_user_screen_name='" + retweeted_by_user_screen_name + '\'' +
", retweeted_by_user_profile_image='" + retweeted_by_user_profile_image + '\'' +
", text_html='" + text_html + '\'' +
", text_plain='" + text_plain + '\'' +
", lang='" + lang + '\'' +
", user_name='" + user_name + '\'' +
", user_screen_name='" + user_screen_name + '\'' +
", in_reply_to_name='" + in_reply_to_name + '\'' +
", in_reply_to_screen_name='" + in_reply_to_screen_name + '\'' +
", source='" + source + '\'' +
", user_profile_image_url='" + user_profile_image_url + '\'' +
", text_unescaped='" + text_unescaped + '\'' +
", card_name='" + card_name + '\'' +
", quoted_text_html='" + quoted_text_html + '\'' +
", quoted_text_plain='" + quoted_text_plain + '\'' +
", quoted_text_unescaped='" + quoted_text_unescaped + '\'' +
", quoted_source='" + quoted_source + '\'' +
", quoted_user_name='" + quoted_user_name + '\'' +
", quoted_user_screen_name='" + quoted_user_screen_name + '\'' +
", quoted_user_profile_image='" + quoted_user_profile_image + '\'' +
", quoted_location=" + quoted_location +
", quoted_place_full_name='" + quoted_place_full_name + '\'' +
", location=" + location +
", place_full_name='" + place_full_name + '\'' +
", mentions=" + Arrays.toString(mentions) +
", media=" + Arrays.toString(media) +
", quoted_media=" + Arrays.toString(quoted_media) +
", card=" + card +
", _id=" + _id +
'}';
}
@OnJsonParseComplete

View File

@ -19,11 +19,9 @@
package org.mariotaku.twidere.model;
import android.database.Cursor;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
@ -33,13 +31,7 @@ import com.hannesdorfmann.parcelableplease.annotation.ParcelableThisPlease;
import org.mariotaku.library.objectcursor.annotation.AfterCursorObjectCreated;
import org.mariotaku.library.objectcursor.annotation.CursorField;
import org.mariotaku.library.objectcursor.annotation.CursorObject;
import org.mariotaku.twidere.api.twitter.model.UrlEntity;
import org.mariotaku.twidere.api.twitter.model.User;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers;
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.ConversationEntries;
import org.mariotaku.twidere.util.HtmlEscapeHelper;
import org.mariotaku.twidere.util.ParseUtils;
import org.mariotaku.twidere.util.TwitterContentUtils;
@ParcelablePlease(allFields = false)
@ -120,6 +112,7 @@ public class ParcelableUser implements Parcelable, Comparable<ParcelableUser> {
public String description_html;
@ParcelableThisPlease
@JsonField(name = "description_unescaped")
@CursorField(CachedUsers.DESCRIPTION_UNESCAPED)
public String description_unescaped;
@ParcelableThisPlease
@JsonField(name = "description_expanded")
@ -219,43 +212,6 @@ public class ParcelableUser implements Parcelable, Comparable<ParcelableUser> {
is_basic = true;
}
public ParcelableUser(final User user, final long account_id) {
this(user, account_id, 0);
}
public ParcelableUser(final User user, final long account_id, final long position) {
this.position = position;
this.account_id = account_id;
final UrlEntity[] urls_url_entities = user.getUrlEntities();
id = user.getId();
created_at = user.getCreatedAt().getTime();
is_protected = user.isProtected();
is_verified = user.isVerified();
name = user.getName();
screen_name = user.getScreenName();
description_plain = user.getDescription();
description_html = TwitterContentUtils.formatUserDescription(user);
description_expanded = TwitterContentUtils.formatExpandedUserDescription(user);
description_unescaped = HtmlEscapeHelper.toPlainText(description_html);
location = user.getLocation();
profile_image_url = TwitterContentUtils.getProfileImageUrl(user);
profile_banner_url = user.getProfileBannerImageUrl();
url = user.getUrl();
url_expanded = url != null && urls_url_entities != null && urls_url_entities.length > 0 ? urls_url_entities[0].getExpandedUrl() : null;
is_follow_request_sent = user.isFollowRequestSent();
followers_count = user.getFollowersCount();
friends_count = user.getFriendsCount();
statuses_count = user.getStatusesCount();
favorites_count = user.getFavouritesCount();
listed_count = user.getListedCount();
media_count = user.getMediaCount();
is_following = user.isFollowing();
background_color = ParseUtils.parseColor("#" + user.getProfileBackgroundColor(), 0);
link_color = ParseUtils.parseColor("#" + user.getProfileLinkColor(), 0);
text_color = ParseUtils.parseColor("#" + user.getProfileTextColor(), 0);
is_cache = false;
is_basic = false;
}
public static int calculateHashCode(long accountId, long userId) {
final int prime = 31;
@ -265,38 +221,12 @@ public class ParcelableUser implements Parcelable, Comparable<ParcelableUser> {
return result;
}
public static ParcelableUser[] fromUsersArray(@Nullable final User[] users, long account_id) {
if (users == null) return null;
final ParcelableUser[] result = new ParcelableUser[users.length];
for (int i = 0, j = users.length; i < j; i++) {
result[i] = new ParcelableUser(users[i], account_id);
}
return result;
}
public static ParcelableUser fromDirectMessageConversationEntry(final Cursor cursor) {
final long account_id = cursor.getLong(ConversationEntries.IDX_ACCOUNT_ID);
final long id = cursor.getLong(ConversationEntries.IDX_CONVERSATION_ID);
final String name = cursor.getString(ConversationEntries.IDX_NAME);
final String screen_name = cursor.getString(ConversationEntries.IDX_SCREEN_NAME);
final String profile_image_url = cursor.getString(ConversationEntries.IDX_PROFILE_IMAGE_URL);
return new ParcelableUser(account_id, id, name, screen_name, profile_image_url);
}
public static ParcelableUser[] fromUsers(final User[] users, long accountId) {
if (users == null) return null;
int size = users.length;
final ParcelableUser[] result = new ParcelableUser[size];
for (int i = 0; i < size; i++) {
result[i] = new ParcelableUser(users[i], accountId);
}
return result;
}
@AfterCursorObjectCreated
void afterCursorObjectCreated() {
is_cache = true;
description_unescaped = HtmlEscapeHelper.toPlainText(description_html);
if (description_unescaped == null) {
description_unescaped = description_plain;
}
is_basic = description_plain == null || url == null || location == null;
}
@ -326,16 +256,39 @@ public class ParcelableUser implements Parcelable, Comparable<ParcelableUser> {
@Override
public String toString() {
return "ParcelableUser{account_id=" + account_id + ", id=" + id + ", created_at=" + created_at + ", position="
+ position + ", is_protected=" + is_protected + ", is_verified=" + is_verified
+ ", is_follow_request_sent=" + is_follow_request_sent + ", is_following=" + is_following
+ ", description_plain=" + description_plain + ", name=" + name + ", screen_name=" + screen_name
+ ", location=" + location + ", profile_image_url=" + profile_image_url + ", profile_banner_url="
+ profile_banner_url + ", url=" + url + ", url_expanded=" + url_expanded + ", description_html="
+ description_html + ", description_unescaped=" + description_unescaped + ", description_expanded="
+ description_expanded + ", followers_count=" + followers_count + ", friends_count=" + friends_count
+ ", statuses_count=" + statuses_count + ", favorites_count=" + favorites_count + ", is_cache="
+ is_cache + "}";
return "ParcelableUser{" +
"account_id=" + account_id +
", account_color=" + account_color +
", id=" + id +
", created_at=" + created_at +
", position=" + position +
", is_protected=" + is_protected +
", is_verified=" + is_verified +
", is_follow_request_sent=" + is_follow_request_sent +
", is_following=" + is_following +
", description_plain='" + description_plain + '\'' +
", name='" + name + '\'' +
", screen_name='" + screen_name + '\'' +
", location='" + location + '\'' +
", profile_image_url='" + profile_image_url + '\'' +
", profile_banner_url='" + profile_banner_url + '\'' +
", url='" + url + '\'' +
", url_expanded='" + url_expanded + '\'' +
", description_html='" + description_html + '\'' +
", description_unescaped='" + description_unescaped + '\'' +
", description_expanded='" + description_expanded + '\'' +
", followers_count=" + followers_count +
", friends_count=" + friends_count +
", statuses_count=" + statuses_count +
", favorites_count=" + favorites_count +
", listed_count=" + listed_count +
", media_count=" + media_count +
", background_color=" + background_color +
", link_color=" + link_color +
", text_color=" + text_color +
", is_cache=" + is_cache +
", is_basic=" + is_basic +
'}';
}
@Override

View File

@ -21,9 +21,9 @@ package org.mariotaku.twidere.model.util;
import android.content.ContentValues;
import android.database.Cursor;
import android.text.TextUtils;
import org.mariotaku.library.objectcursor.converter.CursorFieldConverter;
import org.mariotaku.twidere.util.TwidereArrayUtils;
import java.lang.reflect.ParameterizedType;
@ -33,11 +33,52 @@ import java.lang.reflect.ParameterizedType;
public class LongArrayConverter implements CursorFieldConverter<long[]> {
@Override
public long[] parseField(Cursor cursor, int columnIndex, ParameterizedType fieldType) {
return TwidereArrayUtils.parseLongArray(cursor.getString(columnIndex), ',');
final String string = cursor.getString(columnIndex);
if (TextUtils.isEmpty(string)) return null;
long[] temp = new long[0];
int len = 0;
int offset = 0;
try {
while (true) {
int index = string.indexOf(',', offset);
if (index == -1) {
temp = putElement(temp, Long.parseLong(string.substring(offset)), len++);
long[] out = new long[len];
System.arraycopy(temp, 0, out, 0, len);
return out;
} else {
temp = putElement(temp, Long.parseLong(string.substring(offset, index)), len++);
offset = (index + 1);
}
}
} catch (NumberFormatException e) {
return null;
}
}
@Override
public void writeField(ContentValues values, long[] object, String columnName, ParameterizedType fieldType) {
values.put(columnName, TwidereArrayUtils.toString(object, ',', false));
if (object == null) return;
final StringBuilder sb = new StringBuilder();
for (int i = 0, j = object.length; i < j; i++) {
if (i > 0) {
sb.append(',');
}
sb.append(object[i]);
}
values.put(columnName, sb.toString());
}
private static long[] putElement(long[] array, long element, int index) {
long[] out;
if (index < array.length) {
out = array;
} else {
out = new long[Math.max(1, array.length) * 2];
System.arraycopy(array, 0, out, 0, array.length);
}
out[index] = element;
return out;
}
}

View File

@ -242,6 +242,8 @@ public interface TwidereDataStore {
String DESCRIPTION_HTML = "description_html";
String DESCRIPTION_UNESCAPED = "description_unescaped";
String DESCRIPTION_EXPANDED = "description_expanded";
String LOCATION = "location";

View File

@ -20,99 +20,25 @@
package org.mariotaku.twidere.util;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.text.translate.CharSequenceTranslator;
import org.apache.commons.lang3.text.translate.EntityArrays;
import org.apache.commons.lang3.text.translate.LookupTranslator;
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;
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.common.R;
import org.mariotaku.twidere.model.ConsumerKeyType;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.provider.TwidereDataStore.Filters;
import org.mariotaku.twidere.util.collection.LongSparseMap;
import org.mariotaku.twidere.util.media.preview.PreviewMediaExtractor;
import java.nio.charset.Charset;
import java.util.ArrayList;
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;
/**
* Created by mariotaku on 15/1/11.
*/
public class TwitterContentUtils {
public static final int TWITTER_BULK_QUERY_COUNT = 100;
private static final Pattern PATTERN_TWITTER_STATUS_LINK = Pattern.compile("https?://twitter\\.com/(?:#!/)?(\\w+)/status(es)?/(\\d+)");
private static final CharSequenceTranslator UNESCAPE_TWITTER_RAW_TEXT = new LookupTranslator(EntityArrays.BASIC_UNESCAPE());
private static final CharSequenceTranslator ESCAPE_TWITTER_RAW_TEXT = new LookupTranslator(EntityArrays.BASIC_ESCAPE());
public static String formatDirectMessageText(final DirectMessage message) {
if (message == null) return null;
final HtmlBuilder builder = new HtmlBuilder(message.getText(), false, true, true);
TwitterContentUtils.parseEntities(builder, message);
return builder.build();
}
public static String formatExpandedUserDescription(final User user) {
if (user == null) return null;
final String text = user.getDescription();
if (text == null) return null;
final HtmlBuilder builder = new HtmlBuilder(text, false, true, true);
final UrlEntity[] urls = user.getDescriptionEntities();
if (urls != null) {
for (final UrlEntity url : urls) {
final String expanded_url = url.getExpandedUrl();
if (expanded_url != null) {
builder.addLink(expanded_url, expanded_url, url.getStart(), url.getEnd());
}
}
}
return toPlainText(builder.build());
}
public static String formatStatusText(final Status status) {
if (status == null) return null;
final HtmlBuilder builder = new HtmlBuilder(status.getText(), false, true, true);
TwitterContentUtils.parseEntities(builder, status);
return builder.build();
}
public static String formatUserDescription(final User user) {
if (user == null) return null;
final String text = user.getDescription();
if (text == null) return null;
final HtmlBuilder builder = new HtmlBuilder(text, false, true, true);
final UrlEntity[] urls = user.getDescriptionEntities();
if (urls != null) {
for (final UrlEntity url : urls) {
final String expanded_url = url.getExpandedUrl();
if (expanded_url != null) {
builder.addLink(expanded_url, url.getDisplayUrl(), url.getStart(), url.getEnd());
}
}
}
return builder.build();
}
@NonNull
public static String getInReplyToName(@NonNull final Status status) {
@ -178,181 +104,9 @@ public class TwitterContentUtils {
return ConsumerKeyType.UNKNOWN;
}
public static String unescapeTwitterStatusText(final CharSequence text) {
if (text == null) return null;
return UNESCAPE_TWITTER_RAW_TEXT.translate(text);
}
public static String escapeTwitterStatusText(final CharSequence text) {
if (text == null) return null;
return ESCAPE_TWITTER_RAW_TEXT.translate(text);
}
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;
final long def = -1;
final long quoteId = NumberUtils.toLong(m.group(3), def);
if (quoteId > 0) {
quotes.put(quoteId, 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) - currentBulkIdx;
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) {
Status.setQuotedStatus(status, quoted);
}
}
}
return list;
}
public static String getMediaUrl(MediaEntity entity) {
return TextUtils.isEmpty(entity.getMediaUrlHttps()) ? entity.getMediaUrl() : entity.getMediaUrlHttps();
}
public static String getProfileImageUrl(@Nullable User user) {
if (user == null) return null;
return TextUtils.isEmpty(user.getProfileImageUrlHttps()) ? user.getProfileImageUrl() : user.getProfileImageUrlHttps();
}
private static void parseEntities(final HtmlBuilder builder, final EntitySupport entities) {
// Format media.
final MediaEntity[] mediaEntities = entities.getMediaEntities();
if (mediaEntities != null) {
for (final MediaEntity mediaEntity : mediaEntities) {
final int start = mediaEntity.getStart(), end = mediaEntity.getEnd();
final String mediaUrl = TwitterContentUtils.getMediaUrl(mediaEntity);
if (mediaUrl != null && start >= 0 && end >= 0) {
builder.addLink(mediaUrl, mediaEntity.getDisplayUrl(), start, end);
}
}
}
final UrlEntity[] urlEntities = entities.getUrlEntities();
if (urlEntities != null) {
for (final UrlEntity urlEntity : urlEntities) {
final int start = urlEntity.getStart(), end = urlEntity.getEnd();
final String expandedUrl = urlEntity.getExpandedUrl();
if (expandedUrl != null && start >= 0 && end >= 0) {
builder.addLink(expandedUrl, urlEntity.getDisplayUrl(), start, end);
}
}
}
}
public static boolean isFiltered(final SQLiteDatabase database, final long user_id, final String text_plain,
final String text_html, final String source, final long retweeted_by_id, final long quotedUserId) {
return isFiltered(database, user_id, text_plain, text_html, source, retweeted_by_id, quotedUserId, true);
}
public static boolean isFiltered(final SQLiteDatabase database, final long userId,
final String textPlain, final String textHtml, final String source,
final long retweetedById, final long quotedUserId, final boolean filterRts) {
if (database == null) return false;
if (textPlain == null && textHtml == null && userId <= 0 && source == null) return false;
final StringBuilder builder = new StringBuilder();
final List<String> selection_args = new ArrayList<>();
builder.append("SELECT NULL WHERE");
if (textPlain != null) {
selection_args.add(textPlain);
builder.append("(SELECT 1 IN (SELECT ? LIKE '%'||" + Filters.Keywords.TABLE_NAME + "." + Filters.VALUE
+ "||'%' FROM " + Filters.Keywords.TABLE_NAME + "))");
}
if (textHtml != null) {
if (!selection_args.isEmpty()) {
builder.append(" OR ");
}
selection_args.add(textHtml);
builder.append("(SELECT 1 IN (SELECT ? LIKE '%<a href=\"%'||" + Filters.Links.TABLE_NAME + "."
+ Filters.VALUE + "||'%\">%' FROM " + Filters.Links.TABLE_NAME + "))");
}
if (userId > 0) {
if (!selection_args.isEmpty()) {
builder.append(" OR ");
}
builder.append("(SELECT ").append(userId).append(" IN (SELECT ").append(Filters.Users.USER_ID).append(" FROM ").append(Filters.Users.TABLE_NAME).append("))");
}
if (retweetedById > 0) {
if (!selection_args.isEmpty()) {
builder.append(" OR ");
}
builder.append("(SELECT ").append(retweetedById).append(" IN (SELECT ").append(Filters.Users.USER_ID).append(" FROM ").append(Filters.Users.TABLE_NAME).append("))");
}
if (quotedUserId > 0) {
if (!selection_args.isEmpty()) {
builder.append(" OR ");
}
builder.append("(SELECT ").append(quotedUserId).append(" IN (SELECT ").append(Filters.Users.USER_ID).append(" FROM ").append(Filters.Users.TABLE_NAME).append("))");
}
if (source != null) {
if (!selection_args.isEmpty()) {
builder.append(" OR ");
}
selection_args.add(source);
builder.append("(SELECT 1 IN (SELECT ? LIKE '%>'||" + Filters.Sources.TABLE_NAME + "." + Filters.VALUE
+ "||'</a>%' FROM " + Filters.Sources.TABLE_NAME + "))");
}
final Cursor cur = database.rawQuery(builder.toString(),
selection_args.toArray(new String[selection_args.size()]));
if (cur == null) return false;
try {
return cur.getCount() > 0;
} finally {
cur.close();
}
}
public static boolean isFiltered(final SQLiteDatabase database, final ParcelableStatus status,
final boolean filter_rts) {
if (database == null || status == null) return false;
return isFiltered(database, status.user_id, status.text_plain, status.text_html, status.source,
status.retweeted_by_user_id, status.quoted_user_id, filter_rts);
}
@Nullable
public static String getBestBannerUrl(@Nullable final String baseUrl, final int width) {
if (baseUrl == null) return null;
final String type = getBestBannerType(width);
final String authority = PreviewMediaExtractor.getAuthority(baseUrl);
return authority != null && authority.endsWith(".twimg.com") ? baseUrl + "/" + type : baseUrl;
}
public static String getBestBannerType(final int width) {
if (width <= 320)
return "mobile";
else if (width <= 520)
return "web";
else if (width <= 626)
return "ipad";
else if (width <= 640)
return "mobile_retina";
else if (width <= 1040)
return "web_retina";
else
return "ipad_retina";
}
public static long getOriginalId(@NonNull ParcelableStatus status) {
return status.is_retweet ? status.retweet_id : status.id;
}
}

View File

@ -20,7 +20,6 @@
package org.mariotaku.twidere.extension.shortener.gist;
import android.support.annotation.NonNull;
import android.support.v4.util.SimpleArrayMap;
import com.bluelinelabs.logansquare.JsonMapper;
import com.fasterxml.jackson.core.JsonParseException;
@ -34,14 +33,16 @@ import org.mariotaku.twidere.util.LoganSquareMapperFinder;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
/**
* Created by mariotaku on 15/5/5.
*/
public class GithubConverterFactory extends RestConverter.SimpleFactory<GithubException> {
private static SimpleArrayMap<Type, RestConverter<HttpResponse, ?, GithubException>> sResponseConverters = new SimpleArrayMap<>();
private static SimpleArrayMap<Type, RestConverter<?, Body, GithubException>> sBodyConverters = new SimpleArrayMap<>();
private static Map<Type, RestConverter<HttpResponse, ?, GithubException>> sResponseConverters = new HashMap<>();
private static Map<Type, RestConverter<?, Body, GithubException>> sBodyConverters = new HashMap<>();
static {
@ -102,8 +103,7 @@ public class GithubConverterFactory extends RestConverter.SimpleFactory<GithubEx
@Override
public Object convert(HttpResponse httpResponse) throws IOException, ConvertException, GithubException {
final Body body = httpResponse.getBody();
final Object object = parseOrThrow(body, mapper);
return object;
return parseOrThrow(body, mapper);
}
}

View File

@ -21,9 +21,6 @@ package org.mariotaku.twidere.extension.shortener.gist;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.support.v4.app.FragmentActivity;
import android.view.Menu;
import android.view.MenuItem;
public class SettingsActivity extends PreferenceActivity {

View File

@ -4,5 +4,5 @@ import org.mariotaku.twidere.TwidereConstants;
public interface Constants extends TwidereConstants{
String TWITLONGER_API_KEY = "h6c4LaVx5g7Entja";
String TWITLONGER_API_KEY = "feOj9pqqqUR0Q9TON29qyQ6tQhW1jU4p";
}

View File

@ -20,7 +20,6 @@
package org.mariotaku.twidere.extension.twitlonger;
import android.support.annotation.NonNull;
import android.support.v4.util.SimpleArrayMap;
import com.bluelinelabs.logansquare.JsonMapper;
import com.fasterxml.jackson.core.JsonParseException;
@ -32,14 +31,16 @@ import org.mariotaku.twidere.util.LoganSquareMapperFinder;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
/**
* Created by mariotaku on 15/5/5.
*/
public class LoganSquareConverterFactory extends RestConverter.SimpleFactory<TwitLongerException> {
private static SimpleArrayMap<Type, RestConverter<HttpResponse, ?, TwitLongerException>> sResponseConverters = new SimpleArrayMap<>();
private static SimpleArrayMap<Type, RestConverter<?, Body, TwitLongerException>> sBodyConverters = new SimpleArrayMap<>();
private static Map<Type, RestConverter<HttpResponse, ?, TwitLongerException>> sResponseConverters = new HashMap<>();
private static Map<Type, RestConverter<?, Body, TwitLongerException>> sBodyConverters = new HashMap<>();
static {

View File

@ -1,10 +1,11 @@
package org.mariotaku.twidere.extension.twitlonger;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import org.mariotaku.twidere.Twidere;
@ -37,7 +38,7 @@ public class TwitLongerStatusShortenerService extends StatusShortenerService imp
return StatusShortenResult.error(-1, getString(R.string.permission_not_granted));
} else if (granted != Twidere.Permission.GRANTED) {
final NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
final NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
final Notification.Builder builder = new Notification.Builder(this);
builder.setSmallIcon(R.drawable.ic_stat_warning);
builder.setTicker(getString(R.string.permission_request));
builder.setContentTitle(getString(R.string.permission_is_required_to_shorten_status));
@ -45,12 +46,18 @@ public class TwitLongerStatusShortenerService extends StatusShortenerService imp
builder.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this,
RequestPermissionActivity.class), PendingIntent.FLAG_ONE_SHOT));
builder.setAutoCancel(true);
nm.notify(NOTIFICATION_ID_REQUEST_PERMISSION, builder.build());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
nm.notify(NOTIFICATION_ID_REQUEST_PERMISSION, builder.build());
} else {
//noinspection deprecation
nm.notify(NOTIFICATION_ID_REQUEST_PERMISSION, builder.getNotification());
}
return StatusShortenResult.error(-1, getString(R.string.permission_not_granted));
}
final ParcelableCredentials credentials;
try {
credentials = getOAuthCredentials(currentAccount);
credentials = getOAuthCredentials(currentAccount.account_id);
} catch (SecurityException e) {
if (BuildConfig.DEBUG) {
Log.w(LOGTAG, e);
@ -73,7 +80,11 @@ public class TwitLongerStatusShortenerService extends StatusShortenerService imp
newPost.setInReplyTo(status.in_reply_to_status.id, status.in_reply_to_status.user_screen_name);
}
final Post response = tl.createPost(newPost);
if (response != null) return StatusShortenResult.shortened(response.content);
if (response != null) {
final StatusShortenResult shortened = StatusShortenResult.shortened(response.tweetContent);
shortened.extra = response.id;
return shortened;
}
} catch (final TwitLongerException e) {
if (BuildConfig.DEBUG) {
Log.w(LOGTAG, e);
@ -85,12 +96,31 @@ public class TwitLongerStatusShortenerService extends StatusShortenerService imp
@Override
protected boolean callback(StatusShortenResult result, ParcelableStatus status) {
return false;
if (result.extra == null) return false;
final ParcelableCredentials credentials;
try {
credentials = getOAuthCredentials(status.account_id);
} catch (SecurityException e) {
if (BuildConfig.DEBUG) {
Log.w(LOGTAG, e);
}
return false;
}
final TwitLonger tl = TwitLongerFactory.getInstance(TWITLONGER_API_KEY, credentials);
try {
tl.updatePost(result.extra, status.id);
} catch (TwitLongerException e) {
if (BuildConfig.DEBUG) {
Log.w(LOGTAG, e);
}
return false;
}
return true;
}
@Nullable
private ParcelableCredentials getOAuthCredentials(ParcelableAccount account) {
ParcelableCredentials credentials = Twidere.getCredentials(this, account.account_id);
private ParcelableCredentials getOAuthCredentials(long accountId) {
ParcelableCredentials credentials = Twidere.getCredentials(this, accountId);
if (credentials == null) return null;
switch (credentials.auth_type) {
case ParcelableCredentials.AUTH_TYPE_OAUTH:

View File

@ -36,5 +36,7 @@ android {
dependencies {
compile project(':twidere.component.common')
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
}

View File

@ -1,32 +0,0 @@
/*
* 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.library.extension;
import android.app.Application;
import android.test.ApplicationTestCase;
/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}

View File

@ -33,7 +33,6 @@ import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.apache.commons.lang3.ArrayUtils;
import org.mariotaku.twidere.model.ComposingStatus;
import org.mariotaku.twidere.model.ParcelableCredentials;
import org.mariotaku.twidere.model.ParcelableCredentialsCursorIndices;
@ -44,8 +43,6 @@ import org.mariotaku.twidere.provider.TwidereDataStore;
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
import org.mariotaku.twidere.provider.TwidereDataStore.DNS;
import org.mariotaku.twidere.provider.TwidereDataStore.Permissions;
import org.mariotaku.twidere.util.TwidereArrayUtils;
import org.mariotaku.twidere.util.content.ContentResolverUtils;
import java.net.Inet4Address;
import java.net.Inet6Address;
@ -147,12 +144,18 @@ public final class Twidere implements TwidereConstants {
if (info.metaData == null) return Permission.NONE;
final String[] required = parsePermissions(info.metaData.getString(METADATA_KEY_EXTENSION_PERMISSIONS));
final String[] permissions = getPermissions(context, pname);
if (ArrayUtils.contains(permissions, PERMISSION_DENIED)) {
return checkPermissionRequirement(required, permissions);
}
public static int checkPermissionRequirement(@NonNull String[] required, @NonNull String[] permissions) {
if (indexOf(permissions, PERMISSION_DENIED) != -1) {
return Permission.DENIED;
} else if (TwidereArrayUtils.contains(permissions, required)) {
} else {
for (String s : required) {
if (indexOf(permissions, s) == -1) return Permission.NONE;
}
return Permission.GRANTED;
}
return Permission.NONE;
}
@NonNull
@ -231,8 +234,7 @@ public final class Twidere implements TwidereConstants {
if (context == null || accountId < 0) return null;
final String selection = Accounts.ACCOUNT_ID + " = ?";
final String[] selectionArgs = {String.valueOf(accountId)};
Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI,
Accounts.COLUMNS, selection, selectionArgs, null);
Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, Accounts.COLUMNS, selection, selectionArgs, null);
if (cur == null) return null;
try {
if (cur.moveToFirst()) {
@ -244,6 +246,14 @@ public final class Twidere implements TwidereConstants {
return null;
}
private static int indexOf(String[] input, String find) {
for (int i = 0, inputLength = input.length; i < inputLength; i++) {
if (find == null) {
if (input[i] == null) return i;
} else if (find.equals(input[i])) return i;
}
return -1;
}
@IntDef({Permission.DENIED, Permission.NONE, Permission.GRANTED})
public @interface Permission {

View File

@ -0,0 +1,19 @@
package org.mariotaku.twidere;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* Created by mariotaku on 16/2/24.
*/
public class TwidereTest {
@Test
public void testCheckPermissionRequirement() {
assertEquals(Twidere.Permission.GRANTED, Twidere.checkPermissionRequirement(new String[]{"a", "b", "c"}, new String[]{"a", "b", "c"}));
assertEquals(Twidere.Permission.GRANTED, Twidere.checkPermissionRequirement(new String[]{"a", "b"}, new String[]{"a", "b", "c"}));
assertEquals(Twidere.Permission.NONE, Twidere.checkPermissionRequirement(new String[]{"a", "b"}, new String[]{"a", "c"}));
assertEquals(Twidere.Permission.DENIED, Twidere.checkPermissionRequirement(new String[]{"a", "b"}, new String[]{"denied"}));
}
}

View File

@ -7,6 +7,7 @@ import java.text.SimpleDateFormat;
import java.util.Locale;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
/**
* Created by mariotaku on 16/1/29.
@ -22,6 +23,9 @@ public class TwitterDateConverterTest {
testDate("Thu Jan 28 11:08:47 +0000 2016");
testDate("Sat Oct 03 16:05:32 +0000 2015");
testDate("Tue Jan 26 18:30:19 +0100 2016");
assertNull(converter.getFromString("Tue Jan 26 18:30:19 +0100"));
assertNull(converter.getFromString("Tue"));
assertNull(converter.getFromString("++++"));
}
private void testDate(String s) throws ParseException {

View File

@ -0,0 +1,32 @@
package org.mariotaku.twidere.model.util;
import android.database.MatrixCursor;
import org.apache.commons.lang3.reflect.TypeUtils;
import org.junit.Test;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertNull;
/**
* Created by mariotaku on 16/2/24.
*/
public class LongArrayConverterTest {
private final LongArrayConverter converter = new LongArrayConverter();
@Test
public void testParseField() throws Exception {
MatrixCursor cursor = new MatrixCursor(new String[]{"a", "b", "c", "d"});
cursor.addRow(new String[]{"1,2,3,4", "5,6,7", "8,", ""});
cursor.moveToFirst();
assertArrayEquals(new long[]{1, 2, 3, 4}, converter.parseField(cursor, 0, TypeUtils.parameterize(long[].class)));
assertArrayEquals(new long[]{5, 6, 7}, converter.parseField(cursor, 1, TypeUtils.parameterize(long[].class)));
assertNull(converter.parseField(cursor, 2, TypeUtils.parameterize(long[].class)));
assertNull(converter.parseField(cursor, 3, TypeUtils.parameterize(long[].class)));
}
@Test
public void testWriteField() throws Exception {
}
}

View File

@ -28,6 +28,7 @@ import com.google.android.youtube.player.YouTubePlayer;
import com.google.android.youtube.player.YouTubePlayerSupportFragment;
import org.mariotaku.twidere.model.ParcelableCardEntity;
import org.mariotaku.twidere.model.util.ParcelableCardEntityUtils;
/**
* Created by mariotaku on 15/1/1.
@ -49,8 +50,8 @@ public final class TwitterCardFragmentFactoryImpl extends TwitterCardFragmentFac
@Override
public Fragment createPlayerFragment(ParcelableCardEntity card) {
if (Boolean.parseBoolean("true")) return null;
final String appUrlResolved = card.getString("app_url_resolved");
final String domain = card.getString("domain");
final String appUrlResolved = ParcelableCardEntityUtils.getString(card, "app_url_resolved");
final String domain = ParcelableCardEntityUtils.getString(card, "domain");
if (domain != null && appUrlResolved != null) {
final Uri uri = Uri.parse(appUrlResolved);
final String paramV = uri.getQueryParameter("v");

View File

@ -33,7 +33,7 @@ import static org.mariotaku.twidere.annotation.PreferenceType.STRING;
public interface Constants extends TwidereConstants {
String DATABASES_NAME = "twidere.sqlite";
int DATABASES_VERSION = 120;
int DATABASES_VERSION = 121;
int MENU_GROUP_STATUS_EXTENSION = 10;
int MENU_GROUP_COMPOSE_EXTENSION = 11;

View File

@ -51,10 +51,11 @@ import org.mariotaku.twidere.fragment.support.SupportProgressDialogFragment;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.model.ParcelableUserList;
import org.mariotaku.twidere.model.SingleResponse;
import org.mariotaku.twidere.model.message.UserListCreatedEvent;
import org.mariotaku.twidere.model.util.ParcelableUserUtils;
import org.mariotaku.twidere.util.AsyncTaskUtils;
import org.mariotaku.twidere.util.ParseUtils;
import org.mariotaku.twidere.util.TwitterAPIFactory;
import org.mariotaku.twidere.model.message.UserListCreatedEvent;
import java.util.ArrayList;
import java.util.List;
@ -357,7 +358,7 @@ public class UserListSelectorActivity extends BaseSupportDialogActivity implemen
final ResponseList<User> lists = twitter.searchUsers(mName, paging);
final List<ParcelableUser> data = new ArrayList<>();
for (final User item : lists) {
data.add(new ParcelableUser(item, mAccountId));
data.add(ParcelableUserUtils.fromUser(item, mAccountId));
}
return SingleResponse.getInstance(data);
} catch (final TwitterException e) {

View File

@ -3,7 +3,7 @@ package org.mariotaku.twidere.api.twitter.model;
import android.support.annotation.NonNull;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.TwitterContentUtils;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import java.util.Date;
@ -15,7 +15,7 @@ public class StatusUtils {
public static Status fromParcelableStatus(@NonNull ParcelableStatus parcelable) {
Status status = new Status();
status.id = parcelable.id;
status.text = TwitterContentUtils.escapeTwitterStatusText(parcelable.text_plain);
status.text = InternalTwitterContentUtils.escapeTwitterStatusText(parcelable.text_plain);
status.createdAt = new Date(parcelable.timestamp);
status.inReplyToStatusId = parcelable.in_reply_to_status_id;
status.inReplyToUserId = parcelable.in_reply_to_user_id;
@ -23,7 +23,7 @@ public class StatusUtils {
if (parcelable.is_retweet) {
Status retweet = status.retweetedStatus = new Status();
retweet.id = parcelable.retweet_id;
retweet.text = TwitterContentUtils.escapeTwitterStatusText(parcelable.text_plain);
retweet.text = InternalTwitterContentUtils.escapeTwitterStatusText(parcelable.text_plain);
retweet.createdAt = new Date(parcelable.retweet_timestamp);
User retweetUser = retweet.user = new User();
retweetUser.id = parcelable.user_id;
@ -39,7 +39,7 @@ public class StatusUtils {
} else if (parcelable.is_quote) {
Status quote = status.quotedStatus = new Status();
quote.id = parcelable.quoted_id;
quote.text = TwitterContentUtils.escapeTwitterStatusText(parcelable.quoted_text_plain);
quote.text = InternalTwitterContentUtils.escapeTwitterStatusText(parcelable.quoted_text_plain);
quote.createdAt = new Date(parcelable.quoted_timestamp);
User quotedUser = quote.user = new User();
quotedUser.id = parcelable.quoted_user_id;

View File

@ -93,6 +93,7 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
import org.mariotaku.twidere.util.CompareUtils;
import org.mariotaku.twidere.util.DataStoreUtils;
import org.mariotaku.twidere.util.IntentUtils;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallback;
import org.mariotaku.twidere.util.ListViewUtils;
@ -100,7 +101,6 @@ import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.TransitionUtils;
import org.mariotaku.twidere.util.TwitterContentUtils;
import org.mariotaku.twidere.util.UserColorNameManager;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.content.SupportFragmentReloadCursorObserver;
@ -708,7 +708,7 @@ public class AccountsDashboardFragment extends BaseSupportFragment implements Lo
final Resources res = getResources();
final int defWidth = res.getDisplayMetrics().widthPixels;
final int width = bannerWidth > 0 ? bannerWidth : defWidth;
final String bannerUrl = TwitterContentUtils.getBestBannerUrl(account.profile_banner_url, width);
final String bannerUrl = InternalTwitterContentUtils.getBestBannerUrl(account.profile_banner_url, width);
final ImageView bannerView = mAccountProfileBannerView;
if (bannerView.getDrawable() == null || !CompareUtils.objectEquals(bannerUrl, bannerView.getTag())) {
mMediaLoader.displayProfileBanner(mAccountProfileBannerView, bannerUrl, this);

View File

@ -113,6 +113,7 @@ import org.mariotaku.twidere.model.SingleResponse;
import org.mariotaku.twidere.model.message.FavoriteTaskEvent;
import org.mariotaku.twidere.model.message.StatusListChangedEvent;
import org.mariotaku.twidere.model.util.ParcelableMediaUtils;
import org.mariotaku.twidere.model.util.ParcelableUserUtils;
import org.mariotaku.twidere.provider.TwidereDataStore.Activities;
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
import org.mariotaku.twidere.util.AsyncTaskUtils;
@ -123,6 +124,7 @@ import org.mariotaku.twidere.util.ContentListScrollListener;
import org.mariotaku.twidere.util.DataStoreUtils;
import org.mariotaku.twidere.util.HtmlSpanBuilder;
import org.mariotaku.twidere.util.IntentUtils;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallback;
import org.mariotaku.twidere.util.LinkCreator;
@ -141,7 +143,6 @@ import org.mariotaku.twidere.util.TwidereLinkify;
import org.mariotaku.twidere.util.TwidereMathUtils;
import org.mariotaku.twidere.util.TwitterAPIFactory;
import org.mariotaku.twidere.util.TwitterCardUtils;
import org.mariotaku.twidere.util.TwitterContentUtils;
import org.mariotaku.twidere.util.UserColorNameManager;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.view.CardMediaContainer;
@ -2022,7 +2023,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
}
public void setTranslationResult(@Nullable TranslationResult translation) {
if (mStatus == null || translation == null || TwitterContentUtils.getOriginalId(mStatus)
if (mStatus == null || translation == null || InternalTwitterContentUtils.getOriginalId(mStatus)
!= translation.getId()) {
mTranslationResult = null;
} else {
@ -2389,7 +2390,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
final List<ParcelableUser> retweeters = new ArrayList<>();
try {
for (Status status : twitter.getRetweets(mStatusId, paging)) {
retweeters.add(new ParcelableUser(status.getUser(), mAccountId));
retweeters.add(ParcelableUserUtils.fromUser(status.getUser(), mAccountId));
}
activitySummary.setRetweeters(retweeters);
final ContentValues statusValues = new ContentValues();

View File

@ -59,6 +59,7 @@ import org.mariotaku.twidere.api.twitter.model.User;
import org.mariotaku.twidere.loader.support.ParcelableUserLoader;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.model.SingleResponse;
import org.mariotaku.twidere.model.util.ParcelableUserUtils;
import org.mariotaku.twidere.util.AsyncTaskManager;
import org.mariotaku.twidere.util.AsyncTaskUtils;
import org.mariotaku.twidere.util.AsyncTwitterWrapper.UpdateProfileBannerImageTask;
@ -483,7 +484,7 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
// User profile unchanged
return SingleResponse.getInstance();
}
return SingleResponse.getInstance(new ParcelableUser(user, mAccountId));
return SingleResponse.getInstance(ParcelableUserUtils.fromUser(user, mAccountId));
} catch (TwitterException e) {
return SingleResponse.getInstance(e);
}

View File

@ -56,6 +56,7 @@ import org.mariotaku.twidere.api.twitter.model.CardEntity;
import org.mariotaku.twidere.fragment.support.BaseSupportFragment;
import org.mariotaku.twidere.model.ParcelableCardEntity;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.util.ParcelableCardEntityUtils;
import org.mariotaku.twidere.util.TwitterAPIFactory;
import org.mariotaku.twidere.util.support.ViewSupport;
@ -133,15 +134,15 @@ public class CardPollFragment extends BaseSupportFragment implements
mCard = card;
final int choicesCount = getChoicesCount(card);
int votesSum = 0;
final boolean countsAreFinal = card.getAsBoolean("counts_are_final", false);
final int selectedChoice = card.getAsInteger("selected_choice", -1);
final Date endDatetimeUtc = card.getAsDate("end_datetime_utc", new Date());
final boolean countsAreFinal = ParcelableCardEntityUtils.getAsBoolean(card, "counts_are_final", false);
final int selectedChoice = ParcelableCardEntityUtils.getAsInteger(card, "selected_choice", -1);
final Date endDatetimeUtc = ParcelableCardEntityUtils.getAsDate(card, "end_datetime_utc", new Date());
final boolean hasChoice = selectedChoice != -1;
final boolean isMyPoll = status.account_id == status.user_id;
final boolean showResult = countsAreFinal || isMyPoll || hasChoice;
for (int i = 0; i < choicesCount; i++) {
final int choiceIndex = i + 1;
votesSum += card.getAsInteger("choice" + choiceIndex + "_count", 0);
votesSum += ParcelableCardEntityUtils.getAsInteger(card, "choice" + choiceIndex + "_count", 0);
}
final View.OnClickListener clickListener = new View.OnClickListener() {
@ -179,7 +180,7 @@ public class CardPollFragment extends BaseSupportFragment implements
if (caps == null) return null;
try {
final CardEntity cardEntity = caps.sendPassThrough(cardDataMap).getCard();
return ParcelableCardEntity.fromCardEntity(cardEntity, card.account_id);
return ParcelableCardEntityUtils.fromCardEntity(cardEntity, card.account_id);
} catch (TwitterException e) {
Log.w(LOGTAG, e);
}
@ -203,8 +204,8 @@ public class CardPollFragment extends BaseSupportFragment implements
final RadioButton choiceRadioButton = (RadioButton) pollItem.findViewById(R.id.choice_button);
final int choiceIndex = i + 1;
final String label = card.getAsString("choice" + choiceIndex + "_label", null);
final int value = card.getAsInteger("choice" + choiceIndex + "_count", 0);
final String label = ParcelableCardEntityUtils.getAsString(card, "choice" + choiceIndex + "_label", null);
final int value = ParcelableCardEntityUtils.getAsInteger(card, "choice" + choiceIndex + "_count", 0);
if (label == null) throw new NullPointerException();
final float choicePercent = votesSum == 0 ? 0 : value / (float) votesSum;
choiceLabelView.setText(label);
@ -350,7 +351,7 @@ public class CardPollFragment extends BaseSupportFragment implements
if (card == null || card.getName() == null) {
return null;
}
final ParcelableCardEntity parcelableCard = ParcelableCardEntity.fromCardEntity(card, mAccountId);
final ParcelableCardEntity parcelableCard = ParcelableCardEntityUtils.fromCardEntity(card, mAccountId);
return parcelableCard;
} catch (TwitterException e) {

View File

@ -32,8 +32,8 @@ import org.mariotaku.twidere.api.twitter.model.Status;
import org.mariotaku.twidere.api.twitter.model.User;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.DataStoreUtils;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import org.mariotaku.twidere.util.TwitterAPIFactory;
import org.mariotaku.twidere.util.TwitterContentUtils;
import org.mariotaku.twidere.util.TwitterWrapper;
import org.mariotaku.twidere.util.Utils;
@ -98,7 +98,7 @@ public class MediaTimelineLoader extends TwitterAPIStatusesLoader {
@Override
protected boolean shouldFilterStatus(final SQLiteDatabase database, final ParcelableStatus status) {
final long retweetUserId = status.is_retweet ? status.user_id : -1;
return !isMyTimeline() && TwitterContentUtils.isFiltered(database, retweetUserId, status.text_plain,
return !isMyTimeline() && InternalTwitterContentUtils.isFiltered(database, retweetUserId, status.text_plain,
status.text_html, status.source, -1, status.quoted_user_id);
}

View File

@ -35,6 +35,7 @@ import org.mariotaku.twidere.api.twitter.model.User;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.model.ParcelableUserCursorIndices;
import org.mariotaku.twidere.model.SingleResponse;
import org.mariotaku.twidere.model.util.ParcelableUserUtils;
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers;
import org.mariotaku.twidere.util.ContentValuesCreator;
@ -111,7 +112,7 @@ public final class ParcelableUserLoader extends AsyncTaskLoader<SingleResponse<P
final ContentValues cachedUserValues = createCachedUser(twitterUser);
final long userId = twitterUser.getId();
resolver.insert(CachedUsers.CONTENT_URI, cachedUserValues);
final ParcelableUser user = new ParcelableUser(twitterUser, mAccountId);
final ParcelableUser user = ParcelableUserUtils.fromUser(twitterUser, mAccountId);
if (isMyAccount(context, userId)) {
final ContentValues accountValues = new ContentValues();
accountValues.put(Accounts.NAME, user.name);

View File

@ -29,7 +29,7 @@ import org.mariotaku.twidere.api.twitter.model.Paging;
import org.mariotaku.twidere.api.twitter.model.ResponseList;
import org.mariotaku.twidere.api.twitter.model.Status;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.TwitterContentUtils;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import java.util.List;
@ -50,7 +50,7 @@ public class RetweetsOfMeLoader extends TwitterAPIStatusesLoader {
@Override
protected boolean shouldFilterStatus(final SQLiteDatabase database, final ParcelableStatus status) {
return TwitterContentUtils.isFiltered(database, -1, status.text_plain, status.text_html, status.source,
return InternalTwitterContentUtils.isFiltered(database, -1, status.text_plain, status.text_html, status.source,
status.retweeted_by_user_id, status.quoted_user_id);
}
}

View File

@ -29,7 +29,7 @@ import org.mariotaku.twidere.api.twitter.model.Paging;
import org.mariotaku.twidere.api.twitter.model.SearchQuery;
import org.mariotaku.twidere.api.twitter.model.Status;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.TwitterContentUtils;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import java.util.List;
@ -68,7 +68,7 @@ public class TweetSearchLoader extends TwitterAPIStatusesLoader {
@Override
protected boolean shouldFilterStatus(final SQLiteDatabase database, final ParcelableStatus status) {
return TwitterContentUtils.isFiltered(database, status, true);
return InternalTwitterContentUtils.isFiltered(database, status, true);
}
@Override

View File

@ -39,12 +39,12 @@ import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.model.ListResponse;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.util.ParcelableStatusUtils;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import org.mariotaku.twidere.util.JsonSerializer;
import org.mariotaku.twidere.util.LoganSquareMapperFinder;
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
import org.mariotaku.twidere.util.TwidereArrayUtils;
import org.mariotaku.twidere.util.TwitterAPIFactory;
import org.mariotaku.twidere.util.TwitterContentUtils;
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
import java.io.File;
@ -126,7 +126,7 @@ public abstract class TwitterAPIStatusesLoader extends ParcelableStatusesLoader
}
statuses = getStatuses(twitter, paging);
if (!TwitterAPIFactory.isOfficialTwitterInstance(context, twitter)) {
TwitterContentUtils.getStatusesWithQuoteData(twitter, statuses);
InternalTwitterContentUtils.getStatusesWithQuoteData(twitter, statuses);
}
} catch (final TwitterException e) {
// mHandler.post(new ShowErrorRunnable(e));

View File

@ -27,6 +27,7 @@ import org.mariotaku.twidere.api.twitter.Twitter;
import org.mariotaku.twidere.api.twitter.TwitterException;
import org.mariotaku.twidere.api.twitter.model.User;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.model.util.ParcelableUserUtils;
import org.mariotaku.twidere.util.TwitterAPIFactory;
import java.util.Collections;
@ -58,7 +59,7 @@ public abstract class TwitterAPIUsersLoader extends ParcelableUsersLoader {
if (hasId(user.getId())) {
continue;
}
data.add(new ParcelableUser(user, mAccountId, pos));
data.add(ParcelableUserUtils.fromUser(user, mAccountId, pos));
pos++;
}
Collections.sort(data);

View File

@ -32,7 +32,7 @@ import org.mariotaku.twidere.api.twitter.model.ResponseList;
import org.mariotaku.twidere.api.twitter.model.Status;
import org.mariotaku.twidere.api.twitter.Twitter;
import org.mariotaku.twidere.api.twitter.TwitterException;
import org.mariotaku.twidere.util.TwitterContentUtils;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
public class UserListTimelineLoader extends TwitterAPIStatusesLoader {
@ -67,7 +67,7 @@ public class UserListTimelineLoader extends TwitterAPIStatusesLoader {
@Override
protected boolean shouldFilterStatus(final SQLiteDatabase database, final ParcelableStatus status) {
return TwitterContentUtils.isFiltered(database, status, true);
return InternalTwitterContentUtils.isFiltered(database, status, true);
}
}

View File

@ -30,7 +30,7 @@ import org.mariotaku.twidere.api.twitter.model.ResponseList;
import org.mariotaku.twidere.api.twitter.model.Status;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.DataStoreUtils;
import org.mariotaku.twidere.util.TwitterContentUtils;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import java.util.List;
@ -64,7 +64,7 @@ public class UserTimelineLoader extends TwitterAPIStatusesLoader {
@Override
protected boolean shouldFilterStatus(final SQLiteDatabase database, final ParcelableStatus status) {
final long retweetUserId = status.is_retweet ? status.user_id : -1;
return !mIsMyTimeline && TwitterContentUtils.isFiltered(database, retweetUserId, status.text_plain,
return !mIsMyTimeline && InternalTwitterContentUtils.isFiltered(database, retweetUserId, status.text_plain,
status.text_html, status.source, -1, status.quoted_user_id);
}
}

View File

@ -62,13 +62,13 @@ public class ParcelableActivityUtils {
result.action = activity.getAction();
result.max_position = activity.getMaxPosition();
result.min_position = activity.getMinPosition();
result.sources = ParcelableUser.fromUsers(activity.getSources(), accountId);
result.target_users = ParcelableUser.fromUsers(activity.getTargetUsers(), accountId);
result.sources = ParcelableUserUtils.fromUsers(activity.getSources(), accountId);
result.target_users = ParcelableUserUtils.fromUsers(activity.getTargetUsers(), accountId);
result.target_user_lists = ParcelableUserList.fromUserLists(activity.getTargetUserLists(), accountId);
result.target_statuses = ParcelableStatusUtils.fromStatuses(activity.getTargetStatuses(), accountId);
result.target_object_statuses = ParcelableStatusUtils.fromStatuses(activity.getTargetObjectStatuses(), accountId);
result.target_object_user_lists = ParcelableUserList.fromUserLists(activity.getTargetObjectUserLists(), accountId);
result.target_object_users = ParcelableUser.fromUsers(activity.getTargetObjectUsers(), accountId);
result.target_object_users = ParcelableUserUtils.fromUsers(activity.getTargetObjectUsers(), accountId);
if (result.sources != null) {
result.source_ids = new long[result.sources.length];
for (int i = 0; i < result.sources.length; i++) {

View File

@ -0,0 +1,82 @@
package org.mariotaku.twidere.model.util;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.util.ArrayMap;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.mariotaku.twidere.api.twitter.model.CardEntity;
import org.mariotaku.twidere.model.ParcelableCardEntity;
import java.text.ParseException;
import java.util.Date;
import java.util.Map;
/**
* Created by mariotaku on 16/2/24.
*/
public class ParcelableCardEntityUtils {
@Nullable
public static ParcelableCardEntity fromCardEntity(@Nullable CardEntity card, long accountId) {
if (card == null) return null;
final ParcelableCardEntity obj = new ParcelableCardEntity();
obj.name = card.getName();
obj.url = card.getUrl();
obj.users = ParcelableUserUtils.fromUsersArray(card.getUsers(), accountId);
obj.account_id = accountId;
obj.values = from(card.getBindingValues());
return obj;
}
public static Map<String, ParcelableCardEntity.ParcelableBindingValue> from(@Nullable Map<String, CardEntity.BindingValue> bindingValues) {
if (bindingValues == null) return null;
final ArrayMap<String, ParcelableCardEntity.ParcelableBindingValue> map = new ArrayMap<>();
for (Map.Entry<String, CardEntity.BindingValue> entry : bindingValues.entrySet()) {
map.put(entry.getKey(), new ParcelableCardEntity.ParcelableBindingValue(entry.getValue()));
}
return map;
}
public static boolean getAsBoolean(@NonNull ParcelableCardEntity obj, @NonNull String key, boolean def) {
final ParcelableCardEntity.ParcelableBindingValue value = obj.getValue(key);
if (value == null) return def;
return Boolean.parseBoolean(value.value);
}
public static String getAsString(@NonNull ParcelableCardEntity obj, @NonNull String key, String def) {
final ParcelableCardEntity.ParcelableBindingValue value = obj.getValue(key);
if (value == null) return def;
return value.value;
}
public static String getString(@NonNull ParcelableCardEntity obj, @NonNull String key) {
final ParcelableCardEntity.ParcelableBindingValue value = obj.getValue(key);
if (value == null || !CardEntity.BindingValue.TYPE_STRING.equals(value.type)) return null;
return getAsString(obj, key, null);
}
public static int getAsInteger(@NonNull ParcelableCardEntity obj, @NonNull String key, int def) {
final ParcelableCardEntity.ParcelableBindingValue value = obj.getValue(key);
if (value == null) return def;
return NumberUtils.toInt(value.value, def);
}
public static long getAsLong(@NonNull ParcelableCardEntity obj, @NonNull String key, long def) {
final ParcelableCardEntity.ParcelableBindingValue value = obj.getValue(key);
if (value == null) return def;
return NumberUtils.toLong(value.value, def);
}
public static Date getAsDate(@NonNull ParcelableCardEntity obj, @NonNull String key, Date def) {
final ParcelableCardEntity.ParcelableBindingValue value = obj.getValue(key);
if (value == null) return def;
try {
return DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.parse(value.value);
} catch (ParseException e) {
return def;
}
}
}

View File

@ -3,6 +3,7 @@ package org.mariotaku.twidere.model.util;
import org.mariotaku.twidere.api.twitter.model.DirectMessage;
import org.mariotaku.twidere.api.twitter.model.User;
import org.mariotaku.twidere.model.ParcelableDirectMessage;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import org.mariotaku.twidere.util.TwitterContentUtils;
import java.util.Date;
@ -25,7 +26,7 @@ public class ParcelableDirectMessageUtils {
result.timestamp = getTime(message.getCreatedAt());
result.sender_id = sender.getId();
result.recipient_id = recipient.getId();
result.text_html = TwitterContentUtils.formatDirectMessageText(message);
result.text_html = InternalTwitterContentUtils.formatDirectMessageText(message);
result.text_plain = message.getText();
result.sender_name = sender.getName();
result.recipient_name = recipient.getName();

View File

@ -13,11 +13,10 @@ import org.mariotaku.twidere.api.twitter.model.ExtendedEntitySupport;
import org.mariotaku.twidere.api.twitter.model.MediaEntity;
import org.mariotaku.twidere.api.twitter.model.Status;
import org.mariotaku.twidere.api.twitter.model.UrlEntity;
import org.mariotaku.twidere.model.ParcelableCardEntity;
import org.mariotaku.twidere.model.ParcelableMedia;
import org.mariotaku.twidere.model.ParcelableMediaUpdate;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import org.mariotaku.twidere.util.TwidereArrayUtils;
import org.mariotaku.twidere.util.TwitterContentUtils;
import org.mariotaku.twidere.util.media.preview.PreviewMediaExtractor;
import java.util.ArrayList;
@ -41,7 +40,7 @@ public class ParcelableMediaUtils {
}
if (mediaEntities != null) {
for (final MediaEntity media : mediaEntities) {
final String mediaURL = TwitterContentUtils.getMediaUrl(media);
final String mediaURL = InternalTwitterContentUtils.getMediaUrl(media);
if (mediaURL != null) {
list.add(ParcelableMediaUtils.fromMediaEntity(media));
}
@ -64,9 +63,9 @@ public class ParcelableMediaUtils {
private static ParcelableMedia fromMediaEntity(MediaEntity entity) {
final ParcelableMedia media = new ParcelableMedia();
media.url = TwitterContentUtils.getMediaUrl(entity);
media.media_url = TwitterContentUtils.getMediaUrl(entity);
media.preview_url = TwitterContentUtils.getMediaUrl(entity);
media.url = InternalTwitterContentUtils.getMediaUrl(entity);
media.media_url = InternalTwitterContentUtils.getMediaUrl(entity);
media.preview_url = InternalTwitterContentUtils.getMediaUrl(entity);
media.start = entity.getStart();
media.end = entity.getEnd();
media.type = ParcelableMediaUtils.getTypeInt(entity.getType());
@ -135,7 +134,7 @@ public class ParcelableMediaUtils {
if ("animated_gif".equals(name) || "player".equals(name)) {
final ParcelableMedia media = new ParcelableMedia();
final CardEntity.BindingValue playerStreamUrl = card.getBindingValue("player_stream_url");
media.card = ParcelableCardEntity.fromCardEntity(card, -1);
media.card = ParcelableCardEntityUtils.fromCardEntity(card, -1);
CardEntity.StringValue appUrlResolved = (CardEntity.StringValue) card.getBindingValue("app_url_resolved");
media.url = checkUrl(appUrlResolved) ? appUrlResolved.getValue() : card.getUrl();
if ("animated_gif".equals(name)) {
@ -180,7 +179,7 @@ public class ParcelableMediaUtils {
final ParcelableMedia media = new ParcelableMedia();
media.url = card.getUrl();
media.card = ParcelableCardEntity.fromCardEntity(card, -1);
media.card = ParcelableCardEntityUtils.fromCardEntity(card, -1);
media.type = ParcelableMedia.Type.IMAGE;
media.media_url = ((CardEntity.ImageValue) photoImageFullSize).getUrl();
media.width = ((CardEntity.ImageValue) photoImageFullSize).getWidth();

View File

@ -6,11 +6,11 @@ import android.support.annotation.Nullable;
import org.mariotaku.twidere.api.twitter.model.Place;
import org.mariotaku.twidere.api.twitter.model.Status;
import org.mariotaku.twidere.api.twitter.model.User;
import org.mariotaku.twidere.model.ParcelableCardEntity;
import org.mariotaku.twidere.model.ParcelableLocation;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableUserMention;
import org.mariotaku.twidere.util.HtmlEscapeHelper;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import org.mariotaku.twidere.util.TwitterContentUtils;
import java.util.Date;
@ -56,8 +56,8 @@ public class ParcelableStatusUtils {
if (quoted != null) {
final User quoted_user = quoted.getUser();
result.quoted_id = quoted.getId();
result.quoted_text_html = TwitterContentUtils.formatStatusText(quoted);
result.quoted_text_plain = TwitterContentUtils.unescapeTwitterStatusText(quoted.getText());
result.quoted_text_html = InternalTwitterContentUtils.formatStatusText(quoted);
result.quoted_text_plain = InternalTwitterContentUtils.unescapeTwitterStatusText(quoted.getText());
result.quoted_text_unescaped = HtmlEscapeHelper.toPlainText(result.quoted_text_html);
result.quoted_timestamp = quoted.getCreatedAt().getTime();
result.quoted_source = quoted.getSource();
@ -105,9 +105,9 @@ public class ParcelableStatusUtils {
result.user_is_protected = user.isProtected();
result.user_is_verified = user.isVerified();
result.user_is_following = user.isFollowing();
result.text_html = TwitterContentUtils.formatStatusText(status);
result.text_html = InternalTwitterContentUtils.formatStatusText(status);
result.media = ParcelableMediaUtils.fromStatus(status);
result.text_plain = TwitterContentUtils.unescapeTwitterStatusText(status.getText());
result.text_plain = InternalTwitterContentUtils.unescapeTwitterStatusText(status.getText());
result.source = status.getSource();
result.location = ParcelableLocation.fromGeoLocation(status.getGeoLocation());
result.is_favorite = status.isFavorited();
@ -115,7 +115,7 @@ public class ParcelableStatusUtils {
result.my_retweet_id = result.retweeted_by_user_id == accountId ? result.id : status.getCurrentUserRetweet();
result.is_possibly_sensitive = status.isPossiblySensitive();
result.mentions = ParcelableUserMention.fromUserMentionEntities(status.getUserMentionEntities());
result.card = ParcelableCardEntity.fromCardEntity(status.getCard(), accountId);
result.card = ParcelableCardEntityUtils.fromCardEntity(status.getCard(), accountId);
result.place_full_name = getPlaceFullName(status.getPlace());
result.card_name = result.card != null ? result.card.name : null;
result.lang = status.getLang();

View File

@ -0,0 +1,87 @@
package org.mariotaku.twidere.model.util;
import android.database.Cursor;
import android.support.annotation.Nullable;
import org.mariotaku.twidere.api.twitter.model.UrlEntity;
import org.mariotaku.twidere.api.twitter.model.User;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.provider.TwidereDataStore;
import org.mariotaku.twidere.util.HtmlEscapeHelper;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import org.mariotaku.twidere.util.ParseUtils;
import org.mariotaku.twidere.util.TwitterContentUtils;
/**
* Created by mariotaku on 16/2/24.
*/
public class ParcelableUserUtils {
public static ParcelableUser fromUser(User user, long accountId) {
return fromUser(user, accountId, 0);
}
public static ParcelableUser fromUser(User user, long accountId, long position) {
ParcelableUser obj = new ParcelableUser();
obj.position = position;
obj.account_id = accountId;
final UrlEntity[] urls_url_entities = user.getUrlEntities();
obj.id = user.getId();
obj.created_at = user.getCreatedAt().getTime();
obj.is_protected = user.isProtected();
obj.is_verified = user.isVerified();
obj.name = user.getName();
obj.screen_name = user.getScreenName();
obj.description_plain = user.getDescription();
obj.description_html = InternalTwitterContentUtils.formatUserDescription(user);
obj.description_expanded = InternalTwitterContentUtils.formatExpandedUserDescription(user);
obj.description_unescaped = HtmlEscapeHelper.toPlainText(obj.description_html);
obj.location = user.getLocation();
obj.profile_image_url = TwitterContentUtils.getProfileImageUrl(user);
obj.profile_banner_url = user.getProfileBannerImageUrl();
obj.url = user.getUrl();
obj.url_expanded = obj.url != null && urls_url_entities != null && urls_url_entities.length > 0 ? urls_url_entities[0].getExpandedUrl() : null;
obj.is_follow_request_sent = user.isFollowRequestSent();
obj.followers_count = user.getFollowersCount();
obj.friends_count = user.getFriendsCount();
obj.statuses_count = user.getStatusesCount();
obj.favorites_count = user.getFavouritesCount();
obj.listed_count = user.getListedCount();
obj.media_count = user.getMediaCount();
obj.is_following = user.isFollowing();
obj.background_color = ParseUtils.parseColor("#" + user.getProfileBackgroundColor(), 0);
obj.link_color = ParseUtils.parseColor("#" + user.getProfileLinkColor(), 0);
obj.text_color = ParseUtils.parseColor("#" + user.getProfileTextColor(), 0);
obj.is_cache = false;
obj.is_basic = false;
return obj;
}
public static ParcelableUser[] fromUsersArray(@Nullable final User[] users, long account_id) {
if (users == null) return null;
final ParcelableUser[] result = new ParcelableUser[users.length];
for (int i = 0, j = users.length; i < j; i++) {
result[i] = fromUser(users[i], account_id);
}
return result;
}
public static ParcelableUser fromDirectMessageConversationEntry(final Cursor cursor) {
final long account_id = cursor.getLong(TwidereDataStore.DirectMessages.ConversationEntries.IDX_ACCOUNT_ID);
final long id = cursor.getLong(TwidereDataStore.DirectMessages.ConversationEntries.IDX_CONVERSATION_ID);
final String name = cursor.getString(TwidereDataStore.DirectMessages.ConversationEntries.IDX_NAME);
final String screen_name = cursor.getString(TwidereDataStore.DirectMessages.ConversationEntries.IDX_SCREEN_NAME);
final String profile_image_url = cursor.getString(TwidereDataStore.DirectMessages.ConversationEntries.IDX_PROFILE_IMAGE_URL);
return new ParcelableUser(account_id, id, name, screen_name, profile_image_url);
}
public static ParcelableUser[] fromUsers(final User[] users, long accountId) {
if (users == null) return null;
int size = users.length;
final ParcelableUser[] result = new ParcelableUser[size];
for (int i = 0; i < size; i++) {
result[i] = fromUser(users[i], accountId);
}
return result;
}
}

View File

@ -25,7 +25,6 @@ import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.preference.Preference;
import android.preference.PreferenceCategory;
import android.preference.PreferenceManager;
@ -42,7 +41,6 @@ import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.util.AsyncTaskUtils;
import org.mariotaku.twidere.util.BitmapUtils;
import org.mariotaku.twidere.util.DataStoreUtils;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
@ -91,7 +89,8 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen
@Override
protected void onAttachedToHierarchy(@NonNull final PreferenceManager preferenceManager) {
super.onAttachedToHierarchy(preferenceManager);
AsyncTaskUtils.executeTask(new LoadAccountsTask(this));
if (getPreferenceCount() > 0) return;
setAccountsData(DataStoreUtils.getAccountsList(getContext(), false));
}
protected abstract void setupPreference(AccountItemPreference preference, ParcelableAccount account);
@ -169,24 +168,4 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen
}
}
private static class LoadAccountsTask extends AsyncTask<Object, Object, List<ParcelableAccount>> {
private final AccountsListPreference mPreference;
public LoadAccountsTask(final AccountsListPreference preference) {
mPreference = preference;
}
@Override
protected List<ParcelableAccount> doInBackground(final Object... params) {
return DataStoreUtils.getAccountsList(mPreference.getContext(), false);
}
@Override
protected void onPostExecute(final List<ParcelableAccount> result) {
mPreference.setAccountsData(result);
}
}
}

View File

@ -32,7 +32,7 @@ import org.mariotaku.twidere.provider.TwidereDataStore.CachedHashtags;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedStatuses;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers;
import org.mariotaku.twidere.util.ContentValuesCreator;
import org.mariotaku.twidere.util.TwitterContentUtils;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import org.mariotaku.twidere.util.TwitterWrapper.TwitterListResponse;
import org.mariotaku.twidere.util.content.ContentResolverUtils;
@ -66,7 +66,7 @@ public class CacheUsersStatusesTask extends TaskRunnable<TwitterListResponse<Sta
final Set<ContentValues> hashTagValues = new HashSet<>();
statusesValues.add(ContentValuesCreator.createStatus(status, params.accountId));
final String text = TwitterContentUtils.unescapeTwitterStatusText(status.getText());
final String text = InternalTwitterContentUtils.unescapeTwitterStatusText(status.getText());
for (final String hashtag : extractor.extractHashtags(text)) {
final ContentValues values = new ContentValues();
values.put(CachedHashtags.NAME, hashtag);

View File

@ -32,9 +32,9 @@ import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.ContentValuesCreator;
import org.mariotaku.twidere.util.DataStoreUtils;
import org.mariotaku.twidere.util.ErrorInfoStore;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
import org.mariotaku.twidere.util.TwitterAPIFactory;
import org.mariotaku.twidere.util.TwitterContentUtils;
import org.mariotaku.twidere.util.TwitterWrapper;
import org.mariotaku.twidere.util.UriUtils;
import org.mariotaku.twidere.util.Utils;
@ -185,7 +185,7 @@ public abstract class GetStatusesTask extends TaskRunnable<RefreshTaskParam,
sinceId = -1;
}
final List<Status> statuses = getStatuses(twitter, paging);
TwitterContentUtils.getStatusesWithQuoteData(twitter, statuses);
InternalTwitterContentUtils.getStatusesWithQuoteData(twitter, statuses);
storeStatus(accountId, statuses, sinceId, maxId, true);
// TODO cache related data and preload
final CacheUsersStatusesTask cacheTask = new CacheUsersStatusesTask(context);

View File

@ -76,6 +76,7 @@ import org.mariotaku.twidere.model.message.StatusRetweetedEvent;
import org.mariotaku.twidere.model.message.UserListCreatedEvent;
import org.mariotaku.twidere.model.message.UserListDestroyedEvent;
import org.mariotaku.twidere.model.util.ParcelableStatusUtils;
import org.mariotaku.twidere.model.util.ParcelableUserUtils;
import org.mariotaku.twidere.provider.TwidereDataStore;
import org.mariotaku.twidere.provider.TwidereDataStore.Activities;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedHashtags;
@ -614,7 +615,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
Log.w(LOGTAG, e);
}
final User user = TwitterWrapper.tryShowUser(twitter, mAccountId, null);
return SingleResponse.getInstance(new ParcelableUser(user, mAccountId));
return SingleResponse.getInstance(ParcelableUserUtils.fromUser(user, mAccountId));
} catch (TwitterException | FileNotFoundException e) {
return SingleResponse.getInstance(e);
}
@ -652,7 +653,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
Log.w(LOGTAG, e);
}
final User user = TwitterWrapper.tryShowUser(twitter, mAccountId, null);
return SingleResponse.getInstance(new ParcelableUser(user, mAccountId));
return SingleResponse.getInstance(ParcelableUserUtils.fromUser(user, mAccountId));
} catch (TwitterException | FileNotFoundException e) {
return SingleResponse.getInstance(e);
}
@ -856,7 +857,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
values.put(CachedRelationships.USER_ID, user_id);
values.put(CachedRelationships.BLOCKING, true);
mResolver.insert(CachedRelationships.CONTENT_URI, values);
return SingleResponse.getInstance(new ParcelableUser(user, account_id), null);
return SingleResponse.getInstance(ParcelableUserUtils.fromUser(user, account_id), null);
} catch (final TwitterException e) {
return SingleResponse.getInstance(null, e);
}
@ -976,7 +977,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
try {
final User user = twitter.createFriendship(user_id);
Utils.setLastSeen(mContext, user.getId(), System.currentTimeMillis());
return SingleResponse.getInstance(new ParcelableUser(user, mAccountId), null);
return SingleResponse.getInstance(ParcelableUserUtils.fromUser(user, mAccountId), null);
} catch (final TwitterException e) {
return SingleResponse.getInstance(null, e);
}
@ -1092,7 +1093,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
Expression.equals(Statuses.USER_ID, mUserId));
mResolver.delete(Statuses.CONTENT_URI, where.getSQL(), null);
return SingleResponse.getInstance(new ParcelableUser(user, mAccountId), null);
return SingleResponse.getInstance(ParcelableUserUtils.fromUser(user, mAccountId), null);
} catch (final TwitterException e) {
return SingleResponse.getInstance(null, e);
}
@ -1390,7 +1391,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
try {
final User user = twitter.destroyBlock(mUserId);
Utils.setLastSeen(mContext, user.getId(), -1);
return SingleResponse.getInstance(new ParcelableUser(user, mAccountId), null);
return SingleResponse.getInstance(ParcelableUserUtils.fromUser(user, mAccountId), null);
} catch (final TwitterException e) {
return SingleResponse.getInstance(null, e);
}
@ -1632,7 +1633,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
Expression.or(Expression.equals(Statuses.USER_ID, user_id),
Expression.equals(Statuses.RETWEETED_BY_USER_ID, user_id)));
mResolver.delete(Statuses.CONTENT_URI, where.getSQL(), null);
return SingleResponse.getInstance(new ParcelableUser(user, mAccountId), null);
return SingleResponse.getInstance(ParcelableUserUtils.fromUser(user, mAccountId), null);
} catch (final TwitterException e) {
return SingleResponse.getInstance(null, e);
}
@ -1674,7 +1675,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
try {
final User user = twitter.destroyMute(mUserId);
Utils.setLastSeen(mContext, user.getId(), -1);
return SingleResponse.getInstance(new ParcelableUser(user, mAccountId), null);
return SingleResponse.getInstance(ParcelableUserUtils.fromUser(user, mAccountId), null);
} catch (final TwitterException e) {
return SingleResponse.getInstance(null, e);
}
@ -2083,7 +2084,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
if (twitter != null) {
try {
final User user = twitter.reportSpam(user_id);
return SingleResponse.getInstance(new ParcelableUser(user, mAccountId), null);
return SingleResponse.getInstance(ParcelableUserUtils.fromUser(user, mAccountId), null);
} catch (final TwitterException e) {
return SingleResponse.getInstance(null, e);
}

View File

@ -48,6 +48,7 @@ import org.mariotaku.twidere.model.ParcelableUserValuesCreator;
import org.mariotaku.twidere.model.draft.SendDirectMessageActionExtra;
import org.mariotaku.twidere.model.util.ParcelableMediaUtils;
import org.mariotaku.twidere.model.util.ParcelableStatusUtils;
import org.mariotaku.twidere.model.util.ParcelableUserUtils;
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
import org.mariotaku.twidere.provider.TwidereDataStore.Activities;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedRelationships;
@ -145,7 +146,7 @@ public final class ContentValuesCreator implements TwidereConstants {
public static ContentValues createCachedUser(final User user) {
if (user == null) return null;
final ContentValues values = new ContentValues();
ParcelableUserValuesCreator.writeTo(new ParcelableUser(user, -1), values);
ParcelableUserValuesCreator.writeTo(ParcelableUserUtils.fromUser(user, -1), values);
return values;
}
@ -167,7 +168,7 @@ public final class ContentValuesCreator implements TwidereConstants {
} else {
values.put(DirectMessages.CONVERSATION_ID, sender.getId());
}
final String text_html = TwitterContentUtils.formatDirectMessageText(message);
final String text_html = InternalTwitterContentUtils.formatDirectMessageText(message);
values.put(DirectMessages.TEXT_HTML, text_html);
values.put(DirectMessages.TEXT_PLAIN, message.getText());
values.put(DirectMessages.TEXT_UNESCAPED, toPlainText(text_html));

View File

@ -71,7 +71,6 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
import org.mariotaku.twidere.provider.TwidereDataStore.Suggestions;
import org.mariotaku.twidere.provider.TwidereDataStore.Tabs;
import org.mariotaku.twidere.provider.TwidereDataStore.UnreadCounts;
import org.mariotaku.twidere.util.content.ContentResolverUtils;
import java.util.ArrayList;
import java.util.Arrays;
@ -246,8 +245,7 @@ public class DataStoreUtils implements Constants {
public static long[] getFilteredUserIds(Context context) {
if (context == null) return new long[0];
final ContentResolver resolver = context.getContentResolver();
final Cursor cur = ContentResolverUtils.query(resolver, Filters.Users.CONTENT_URI,
new String[]{Filters.Users.USER_ID}, null, null, null);
final Cursor cur = resolver.query(Filters.Users.CONTENT_URI, new String[]{Filters.Users.USER_ID}, null, null, null);
if (cur == null) return new long[0];
try {
final long[] ids = new long[cur.getCount()];
@ -321,8 +319,7 @@ public class DataStoreUtils implements Constants {
if (context == null) return null;
final String cached = sAccountScreenNames.get(accountId);
if (!isEmpty(cached)) return cached;
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI,
new String[]{Accounts.SCREEN_NAME}, Accounts.ACCOUNT_ID + " = " + accountId, null, null);
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, new String[]{Accounts.SCREEN_NAME}, Accounts.ACCOUNT_ID + " = " + accountId, null, null);
if (cur == null) return null;
try {
if (cur.getCount() > 0 && cur.moveToFirst()) {
@ -345,8 +342,7 @@ public class DataStoreUtils implements Constants {
final String[] cols = new String[]{Accounts.SCREEN_NAME};
final String where = accountIds != null ? Expression.in(new Column(Accounts.ACCOUNT_ID),
new RawItemArray(accountIds)).getSQL() : null;
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI, cols, where,
null, null);
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, cols, where, null, null);
if (cur == null) return new String[0];
try {
cur.moveToFirst();
@ -365,8 +361,7 @@ public class DataStoreUtils implements Constants {
@NonNull
public static long[] getActivatedAccountIds(final Context context) {
if (context == null) return new long[0];
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI,
new String[]{Accounts.ACCOUNT_ID}, Accounts.IS_ACTIVATED + " = 1", null, null);
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, new String[]{Accounts.ACCOUNT_ID}, Accounts.IS_ACTIVATED + " = 1", null, null);
if (cur == null) return new long[0];
try {
cur.moveToFirst();
@ -537,9 +532,7 @@ public class DataStoreUtils implements Constants {
if (context == null) return Color.TRANSPARENT;
final Integer cached = sAccountColors.get(accountId);
if (cached != null) return cached;
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI,
new String[]{Accounts.COLOR}, Expression.equals(Accounts.ACCOUNT_ID, accountId).getSQL(),
null, null);
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, new String[]{Accounts.COLOR}, Expression.equals(Accounts.ACCOUNT_ID, accountId).getSQL(), null, null);
if (cur == null) return Color.TRANSPARENT;
try {
if (cur.getCount() > 0 && cur.moveToFirst()) {
@ -557,8 +550,7 @@ public class DataStoreUtils implements Constants {
if (context == null || accountIds == null) return new int[0];
final String[] cols = new String[]{Accounts.ACCOUNT_ID, Accounts.COLOR};
final String where = Expression.in(new Column(Accounts.ACCOUNT_ID), new RawItemArray(accountIds)).getSQL();
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI, cols, where,
null, null);
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, cols, where, null, null);
if (cur == null) return new int[0];
try {
final int[] colors = new int[cur.getCount()];
@ -584,9 +576,7 @@ public class DataStoreUtils implements Constants {
public static long getAccountId(final Context context, final String screenName) {
if (context == null || isEmpty(screenName)) return -1;
final Cursor cur = ContentResolverUtils
.query(context.getContentResolver(), Accounts.CONTENT_URI, new String[]{Accounts.ACCOUNT_ID},
Expression.equalsArgs(Accounts.SCREEN_NAME).getSQL(), new String[]{screenName}, null);
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, new String[]{Accounts.ACCOUNT_ID}, Expression.equalsArgs(Accounts.SCREEN_NAME).getSQL(), new String[]{screenName}, null);
if (cur == null) return -1;
try {
if (cur.getCount() > 0 && cur.moveToFirst()) return cur.getLong(0);
@ -599,8 +589,7 @@ public class DataStoreUtils implements Constants {
@NonNull
public static long[] getAccountIds(final Context context) {
if (context == null) return new long[0];
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI,
new String[]{Accounts.ACCOUNT_ID}, null, null, null);
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, new String[]{Accounts.ACCOUNT_ID}, null, null, null);
if (cur == null) return new long[0];
try {
cur.moveToFirst();
@ -618,8 +607,7 @@ public class DataStoreUtils implements Constants {
public static boolean hasAccount(final Context context) {
if (context == null) return false;
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI,
new String[]{SQLFunctions.COUNT()}, null, null, null);
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, new String[]{SQLFunctions.COUNT()}, null, null, null);
if (cur == null) return false;
try {
cur.moveToFirst();
@ -633,8 +621,7 @@ public class DataStoreUtils implements Constants {
if (context == null) return null;
final String cached = sAccountNames.get(accountId);
if (!isEmpty(cached)) return cached;
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI,
new String[]{Accounts.NAME}, Accounts.ACCOUNT_ID + " = " + accountId, null, null);
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, new String[]{Accounts.NAME}, Accounts.ACCOUNT_ID + " = " + accountId, null, null);
if (cur == null) return null;
try {
if (cur.getCount() > 0 && cur.moveToFirst()) {
@ -731,9 +718,7 @@ public class DataStoreUtils implements Constants {
if (sortExpression != null) {
builder.orderBy(sortExpression);
}
final Cursor cur = ContentResolverUtils.query(resolver,
Uri.withAppendedPath(TwidereDataStore.CONTENT_URI_RAW_QUERY, builder.buildSQL()),
null, null, selectionArgs, null);
final Cursor cur = resolver.query(Uri.withAppendedPath(TwidereDataStore.CONTENT_URI_RAW_QUERY, builder.buildSQL()), null, null, selectionArgs, null);
if (cur == null) return messageIds;
try {
while (cur.moveToNext()) {
@ -752,7 +737,7 @@ public class DataStoreUtils implements Constants {
@Nullable final String selection, @Nullable final String[] selectionArgs) {
final ContentResolver resolver = context.getContentResolver();
final String[] projection = new String[]{SQLFunctions.COUNT()};
final Cursor cur = ContentResolverUtils.query(resolver, uri, projection, selection, selectionArgs, null);
final Cursor cur = resolver.query(uri, projection, selection, selectionArgs, null);
if (cur == null) return -1;
try {
if (cur.moveToFirst()) {
@ -766,8 +751,7 @@ public class DataStoreUtils implements Constants {
public static ParcelableAccount getAccount(final Context context, final long accountId) {
if (context == null) return null;
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI,
Accounts.COLUMNS, Expression.equals(Accounts.ACCOUNT_ID, accountId).getSQL(), null, null);
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, Accounts.COLUMNS, Expression.equals(Accounts.ACCOUNT_ID, accountId).getSQL(), null, null);
if (cur == null) return null;
try {
if (cur.moveToFirst()) {
@ -800,8 +784,7 @@ public class DataStoreUtils implements Constants {
if (context == null) return new ParcelableAccount[0];
final String where = accountIds != null ? Expression.in(new Column(Accounts.ACCOUNT_ID),
new RawItemArray(accountIds)).getSQL() : null;
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI,
Accounts.COLUMNS_NO_CREDENTIALS, where, null, null);
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, Accounts.COLUMNS_NO_CREDENTIALS, where, null, null);
if (cur == null) return new ParcelableAccount[0];
return getAccounts(cur, new ParcelableAccountCursorIndices(cur));
}
@ -836,9 +819,8 @@ public class DataStoreUtils implements Constants {
final boolean officialKeyOnly) {
if (context == null) return Collections.emptyList();
final ArrayList<ParcelableAccount> accounts = new ArrayList<>();
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(),
Accounts.CONTENT_URI, Accounts.COLUMNS,
activatedOnly ? Accounts.IS_ACTIVATED + " = 1" : null, null, Accounts.SORT_POSITION);
final String selection = activatedOnly ? Accounts.IS_ACTIVATED + " = 1" : null;
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, Accounts.COLUMNS, selection, null, Accounts.SORT_POSITION);
if (cur == null) return accounts;
final ParcelableCredentialsCursorIndices indices = new ParcelableCredentialsCursorIndices(cur);
cur.moveToFirst();
@ -861,9 +843,7 @@ public class DataStoreUtils implements Constants {
@Nullable
public static ParcelableCredentials getCredentials(final Context context, final long accountId) {
if (context == null || accountId < 0) return null;
Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI,
Accounts.COLUMNS, Expression.equals(Accounts.ACCOUNT_ID, accountId).getSQL(), null,
null);
Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, Accounts.COLUMNS, Expression.equals(Accounts.ACCOUNT_ID, accountId).getSQL(), null, null);
if (cur == null) return null;
try {
if (cur.moveToFirst()) {
@ -889,9 +869,8 @@ public class DataStoreUtils implements Constants {
final boolean officialKeyOnly) {
if (context == null) return Collections.emptyList();
final ArrayList<ParcelableCredentials> accounts = new ArrayList<>();
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(),
Accounts.CONTENT_URI, Accounts.COLUMNS,
activatedOnly ? Accounts.IS_ACTIVATED + " = 1" : null, null, Accounts.SORT_POSITION);
final String selection = activatedOnly ? Accounts.IS_ACTIVATED + " = 1" : null;
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, Accounts.COLUMNS, selection, null, Accounts.SORT_POSITION);
if (cur == null) return accounts;
ParcelableCredentialsCursorIndices indices = new ParcelableCredentialsCursorIndices(cur);
cur.moveToFirst();

View File

@ -0,0 +1,260 @@
package org.mariotaku.twidere.util;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.text.translate.CharSequenceTranslator;
import org.apache.commons.lang3.text.translate.EntityArrays;
import org.apache.commons.lang3.text.translate.LookupTranslator;
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;
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.model.ParcelableStatus;
import org.mariotaku.twidere.provider.TwidereDataStore;
import org.mariotaku.twidere.util.collection.LongSparseMap;
import org.mariotaku.twidere.util.media.preview.PreviewMediaExtractor;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by mariotaku on 16/2/24.
*/
public class InternalTwitterContentUtils {
private static final Pattern PATTERN_TWITTER_STATUS_LINK = Pattern.compile("https?://twitter\\.com/(?:#!/)?(\\w+)/status(es)?/(\\d+)");
private static final CharSequenceTranslator UNESCAPE_TWITTER_RAW_TEXT = new LookupTranslator(EntityArrays.BASIC_UNESCAPE());
private static final CharSequenceTranslator ESCAPE_TWITTER_RAW_TEXT = new LookupTranslator(EntityArrays.BASIC_ESCAPE());
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;
final long def = -1;
final long quoteId = NumberUtils.toLong(m.group(3), def);
if (quoteId > 0) {
quotes.put(quoteId, 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 += TwitterContentUtils.TWITTER_BULK_QUERY_COUNT) {
final int currentBulkCount = Math.min(totalLength, currentBulkIdx + TwitterContentUtils.TWITTER_BULK_QUERY_COUNT) - currentBulkIdx;
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) {
Status.setQuotedStatus(status, quoted);
}
}
}
return list;
}
public static boolean isFiltered(final SQLiteDatabase database, final long user_id, final String text_plain,
final String text_html, final String source, final long retweeted_by_id, final long quotedUserId) {
return isFiltered(database, user_id, text_plain, text_html, source, retweeted_by_id, quotedUserId, true);
}
public static boolean isFiltered(final SQLiteDatabase database, final long userId,
final String textPlain, final String textHtml, final String source,
final long retweetedById, final long quotedUserId, final boolean filterRts) {
if (database == null) return false;
if (textPlain == null && textHtml == null && userId <= 0 && source == null) return false;
final StringBuilder builder = new StringBuilder();
final List<String> selection_args = new ArrayList<>();
builder.append("SELECT NULL WHERE");
if (textPlain != null) {
selection_args.add(textPlain);
builder.append("(SELECT 1 IN (SELECT ? LIKE '%'||" + TwidereDataStore.Filters.Keywords.TABLE_NAME + "." + TwidereDataStore.Filters.VALUE
+ "||'%' FROM " + TwidereDataStore.Filters.Keywords.TABLE_NAME + "))");
}
if (textHtml != null) {
if (!selection_args.isEmpty()) {
builder.append(" OR ");
}
selection_args.add(textHtml);
builder.append("(SELECT 1 IN (SELECT ? LIKE '%<a href=\"%'||" + TwidereDataStore.Filters.Links.TABLE_NAME + "."
+ TwidereDataStore.Filters.VALUE + "||'%\">%' FROM " + TwidereDataStore.Filters.Links.TABLE_NAME + "))");
}
if (userId > 0) {
if (!selection_args.isEmpty()) {
builder.append(" OR ");
}
builder.append("(SELECT ").append(userId).append(" IN (SELECT ").append(TwidereDataStore.Filters.Users.USER_ID).append(" FROM ").append(TwidereDataStore.Filters.Users.TABLE_NAME).append("))");
}
if (retweetedById > 0) {
if (!selection_args.isEmpty()) {
builder.append(" OR ");
}
builder.append("(SELECT ").append(retweetedById).append(" IN (SELECT ").append(TwidereDataStore.Filters.Users.USER_ID).append(" FROM ").append(TwidereDataStore.Filters.Users.TABLE_NAME).append("))");
}
if (quotedUserId > 0) {
if (!selection_args.isEmpty()) {
builder.append(" OR ");
}
builder.append("(SELECT ").append(quotedUserId).append(" IN (SELECT ").append(TwidereDataStore.Filters.Users.USER_ID).append(" FROM ").append(TwidereDataStore.Filters.Users.TABLE_NAME).append("))");
}
if (source != null) {
if (!selection_args.isEmpty()) {
builder.append(" OR ");
}
selection_args.add(source);
builder.append("(SELECT 1 IN (SELECT ? LIKE '%>'||" + TwidereDataStore.Filters.Sources.TABLE_NAME + "." + TwidereDataStore.Filters.VALUE
+ "||'</a>%' FROM " + TwidereDataStore.Filters.Sources.TABLE_NAME + "))");
}
final Cursor cur = database.rawQuery(builder.toString(),
selection_args.toArray(new String[selection_args.size()]));
if (cur == null) return false;
try {
return cur.getCount() > 0;
} finally {
cur.close();
}
}
public static boolean isFiltered(final SQLiteDatabase database, final ParcelableStatus status,
final boolean filter_rts) {
if (database == null || status == null) return false;
return isFiltered(database, status.user_id, status.text_plain, status.text_html, status.source,
status.retweeted_by_user_id, status.quoted_user_id, filter_rts);
}
@Nullable
public static String getBestBannerUrl(@Nullable final String baseUrl, final int width) {
if (baseUrl == null) return null;
final String type = getBestBannerType(width);
final String authority = PreviewMediaExtractor.getAuthority(baseUrl);
return authority != null && authority.endsWith(".twimg.com") ? baseUrl + "/" + type : baseUrl;
}
public static String getBestBannerType(final int width) {
if (width <= 320)
return "mobile";
else if (width <= 520)
return "web";
else if (width <= 626)
return "ipad";
else if (width <= 640)
return "mobile_retina";
else if (width <= 1040)
return "web_retina";
else
return "ipad_retina";
}
public static String formatExpandedUserDescription(final User user) {
if (user == null) return null;
final String text = user.getDescription();
if (text == null) return null;
final HtmlBuilder builder = new HtmlBuilder(text, false, true, true);
final UrlEntity[] urls = user.getDescriptionEntities();
if (urls != null) {
for (final UrlEntity url : urls) {
final String expanded_url = url.getExpandedUrl();
if (expanded_url != null) {
builder.addLink(expanded_url, expanded_url, url.getStart(), url.getEnd());
}
}
}
return HtmlEscapeHelper.toPlainText(builder.build());
}
public static String formatUserDescription(final User user) {
if (user == null) return null;
final String text = user.getDescription();
if (text == null) return null;
final HtmlBuilder builder = new HtmlBuilder(text, false, true, true);
final UrlEntity[] urls = user.getDescriptionEntities();
if (urls != null) {
for (final UrlEntity url : urls) {
final String expanded_url = url.getExpandedUrl();
if (expanded_url != null) {
builder.addLink(expanded_url, url.getDisplayUrl(), url.getStart(), url.getEnd());
}
}
}
return builder.build();
}
public static String unescapeTwitterStatusText(final CharSequence text) {
if (text == null) return null;
return UNESCAPE_TWITTER_RAW_TEXT.translate(text);
}
public static String escapeTwitterStatusText(final CharSequence text) {
if (text == null) return null;
return ESCAPE_TWITTER_RAW_TEXT.translate(text);
}
public static String formatDirectMessageText(final DirectMessage message) {
if (message == null) return null;
final HtmlBuilder builder = new HtmlBuilder(message.getText(), false, true, true);
parseEntities(builder, message);
return builder.build();
}
public static String formatStatusText(final Status status) {
if (status == null) return null;
final HtmlBuilder builder = new HtmlBuilder(status.getText(), false, true, true);
parseEntities(builder, status);
return builder.build();
}
public static String getMediaUrl(MediaEntity entity) {
return TextUtils.isEmpty(entity.getMediaUrlHttps()) ? entity.getMediaUrl() : entity.getMediaUrlHttps();
}
private static void parseEntities(final HtmlBuilder builder, final EntitySupport entities) {
// Format media.
final MediaEntity[] mediaEntities = entities.getMediaEntities();
if (mediaEntities != null) {
for (final MediaEntity mediaEntity : mediaEntities) {
final int start = mediaEntity.getStart(), end = mediaEntity.getEnd();
final String mediaUrl = getMediaUrl(mediaEntity);
if (mediaUrl != null && start >= 0 && end >= 0) {
builder.addLink(mediaUrl, mediaEntity.getDisplayUrl(), start, end);
}
}
}
final UrlEntity[] urlEntities = entities.getUrlEntities();
if (urlEntities != null) {
for (final UrlEntity urlEntity : urlEntities) {
final int start = urlEntity.getStart(), end = urlEntity.getEnd();
final String expandedUrl = urlEntity.getExpandedUrl();
if (expandedUrl != null && start >= 0 && end >= 0) {
builder.addLink(expandedUrl, urlEntity.getDisplayUrl(), start, end);
}
}
}
}
public static long getOriginalId(@NonNull ParcelableStatus status) {
return status.is_retweet ? status.retweet_id : status.id;
}
}

View File

@ -35,7 +35,7 @@ import org.mariotaku.twidere.util.media.MediaExtra;
import javax.inject.Singleton;
import static org.mariotaku.twidere.util.TwitterContentUtils.getBestBannerUrl;
import static org.mariotaku.twidere.util.InternalTwitterContentUtils.getBestBannerUrl;
@Singleton
public class MediaLoaderWrapper implements Constants {

View File

@ -160,12 +160,11 @@ public final class TwidereArrayUtils {
return builder.toString();
}
public static String[] toStringArray(final Object[] array) {
public static String[] toStringArray(final Object[] array, int start, int end) {
if (array == null) return null;
final int length = array.length;
final String[] stringArray = new String[length];
for (int i = 0; i < length; i++) {
stringArray[i] = ParseUtils.parseString(array[i]);
final String[] stringArray = new String[end - start];
for (int i = start; i < end; i++) {
stringArray[i - start] = ParseUtils.parseString(array[i]);
}
return stringArray;
}

View File

@ -27,6 +27,7 @@ import org.mariotaku.twidere.fragment.support.card.CardBrowserFragment;
import org.mariotaku.twidere.fragment.support.card.CardPollFragment;
import org.mariotaku.twidere.model.ParcelableCardEntity;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.util.ParcelableCardEntityUtils;
/**
* Created by mariotaku on 15/1/1.
@ -46,7 +47,7 @@ public abstract class TwitterCardFragmentFactory {
@Nullable
public static Fragment createGenericPlayerFragment(@Nullable ParcelableCardEntity card, Bundle args) {
if (card == null) return null;
final String playerUrl = card.getString("player_url");
final String playerUrl = ParcelableCardEntityUtils.getString(card, "player_url");
if (playerUrl == null) return null;
return CardBrowserFragment.show(playerUrl, args);
}

View File

@ -29,6 +29,7 @@ import org.mariotaku.twidere.fragment.support.card.CardPollFragment;
import org.mariotaku.twidere.model.ParcelableCardEntity;
import org.mariotaku.twidere.model.ParcelableMedia;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.util.ParcelableCardEntityUtils;
/**
* Created by mariotaku on 15/1/1.
@ -65,8 +66,8 @@ public class TwitterCardUtils {
public static Point getCardSize(ParcelableCardEntity card) {
final int playerWidth = card.getAsInteger("player_width", -1);
final int playerHeight = card.getAsInteger("player_height", -1);
final int playerWidth = ParcelableCardEntityUtils.getAsInteger(card, "player_width", -1);
final int playerHeight = ParcelableCardEntityUtils.getAsInteger(card, "player_height", -1);
if (playerWidth > 0 && playerHeight > 0) {
return new Point(playerWidth, playerHeight);
}
@ -78,7 +79,7 @@ public class TwitterCardUtils {
switch (status.card_name) {
case CARD_NAME_PLAYER: {
if (!ArrayUtils.isEmpty(status.media)) {
String appUrlResolved = status.card.getString("app_url_resolved");
String appUrlResolved = ParcelableCardEntityUtils.getString(status.card, "app_url_resolved");
String cardUrl = status.card.url;
for (ParcelableMedia media : status.media) {
if (media.url.equals(appUrlResolved) || media.url.equals(cardUrl)) {
@ -86,7 +87,7 @@ public class TwitterCardUtils {
}
}
}
return TextUtils.isEmpty(status.card.getString("player_stream_url"));
return TextUtils.isEmpty(ParcelableCardEntityUtils.getString(status.card, "player_stream_url"));
}
case CARD_NAME_AUDIO: {
return true;

View File

@ -190,6 +190,7 @@ import org.mariotaku.twidere.model.ParcelableUserList;
import org.mariotaku.twidere.model.ParcelableUserMention;
import org.mariotaku.twidere.model.PebbleMessage;
import org.mariotaku.twidere.model.util.ParcelableStatusUtils;
import org.mariotaku.twidere.model.util.ParcelableUserUtils;
import org.mariotaku.twidere.provider.TwidereDataStore;
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedRelationships;
@ -200,7 +201,6 @@ import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.Conversati
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
import org.mariotaku.twidere.service.RefreshService;
import org.mariotaku.twidere.util.TwidereLinkify.HighlightStyle;
import org.mariotaku.twidere.util.content.ContentResolverUtils;
import org.mariotaku.twidere.util.menu.TwidereMenuInfo;
import org.mariotaku.twidere.view.CardMediaContainer.PreviewStyle;
import org.mariotaku.twidere.view.ShapedImageView;
@ -869,7 +869,7 @@ public final class Utils implements Constants {
final String where = DirectMessages.ACCOUNT_ID + " = " + account_id + " AND " + DirectMessages.MESSAGE_ID
+ " = " + message_id;
for (final Uri uri : DIRECT_MESSAGES_URIS) {
final Cursor cur = ContentResolverUtils.query(resolver, uri, DirectMessages.COLUMNS, where, null, null);
final Cursor cur = resolver.query(uri, DirectMessages.COLUMNS, where, null, null);
if (cur == null) {
continue;
}
@ -907,7 +907,7 @@ public final class Utils implements Constants {
final String where = Expression.and(Expression.equals(Statuses.ACCOUNT_ID, accountId),
Expression.equals(Statuses.STATUS_ID, statusId)).getSQL();
for (final Uri uri : STATUSES_URIS) {
final Cursor cur = ContentResolverUtils.query(resolver, uri, Statuses.COLUMNS, where, null, null);
final Cursor cur = resolver.query(uri, Statuses.COLUMNS, where, null, null);
if (cur == null) {
continue;
}
@ -1197,7 +1197,7 @@ public final class Utils implements Constants {
if (ParseUtils.parseString(uri).startsWith(mediaUriStart)) {
final String[] proj = {MediaStore.Images.Media.DATA};
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), uri, proj, null, null, null);
final Cursor cur = context.getContentResolver().query(uri, proj, null, null, null);
if (cur == null) return null;
@ -1514,8 +1514,7 @@ public final class Utils implements Constants {
public static boolean hasAccountSignedWithOfficialKeys(final Context context) {
if (context == null) return false;
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI,
Accounts.COLUMNS, null, null, null);
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, Accounts.COLUMNS, null, null, null);
if (cur == null) return false;
final String[] keySecrets = context.getResources().getStringArray(R.array.values_official_consumer_secret_crc32);
final ParcelableCredentialsCursorIndices indices = new ParcelableCredentialsCursorIndices(cur);
@ -1552,7 +1551,7 @@ public final class Utils implements Constants {
public static void initAccountColor(final Context context) {
if (context == null) return;
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI, new String[]{
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, new String[]{
Accounts.ACCOUNT_ID, Accounts.COLOR}, null, null, null);
if (cur == null) return;
final int id_idx = cur.getColumnIndex(Accounts.ACCOUNT_ID), color_idx = cur.getColumnIndex(Accounts.COLOR);
@ -1597,7 +1596,8 @@ public final class Utils implements Constants {
if (context == null) return false;
final ContentResolver resolver = context.getContentResolver();
final String where = Expression.equals(Accounts.ACCOUNT_ID, accountId).getSQL();
final Cursor cur = ContentResolverUtils.query(resolver, Accounts.CONTENT_URI, new String[0], where, null, null);
final String[] projection = new String[0];
final Cursor cur = resolver.query(Accounts.CONTENT_URI, projection, where, null, null);
try {
return cur != null && cur.getCount() > 0;
} finally {
@ -1611,8 +1611,8 @@ public final class Utils implements Constants {
if (context == null) return false;
final ContentResolver resolver = context.getContentResolver();
final String where = Expression.equalsArgs(Accounts.SCREEN_NAME).getSQL();
final Cursor cur = ContentResolverUtils.query(resolver, Accounts.CONTENT_URI, new String[0], where,
new String[]{screen_name}, null);
final String[] projection = new String[0];
final Cursor cur = resolver.query(Accounts.CONTENT_URI, projection, where, new String[]{screen_name}, null);
try {
return cur != null && cur.getCount() > 0;
} finally {
@ -2744,7 +2744,7 @@ public final class Utils implements Constants {
final Cursor c = cr.query(ConversationEntries.CONTENT_URI, null, where.getSQL(), null, null);
if (c == null) return null;
try {
if (c.moveToFirst()) return ParcelableUser.fromDirectMessageConversationEntry(c);
if (c.moveToFirst()) return ParcelableUserUtils.fromDirectMessageConversationEntry(c);
} finally {
c.close();
}

View File

@ -19,17 +19,12 @@
package org.mariotaku.twidere.util.content;
import android.annotation.TargetApi;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.CancellationSignal;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.mariotaku.twidere.util.TwidereArrayUtils;
import java.util.Collection;
@ -54,7 +49,7 @@ public class ContentResolverUtils {
int rowsDeleted = 0;
for (int i = 0; i < blocks_count; i++) {
final int start = i * MAX_BULK_COUNT, end = Math.min(start + MAX_BULK_COUNT, colValuesLength);
final String[] block = TwidereArrayUtils.toStringArray(ArrayUtils.subarray(colValues, start, end));
final String[] block = TwidereArrayUtils.toStringArray(colValues, start, end);
if (valuesIsString) {
final StringBuilder where = new StringBuilder(inColumn + " IN(" + TwidereArrayUtils.toStringForSQL(block)
+ ")");
@ -93,18 +88,4 @@ public class ContentResolverUtils {
return rowsInserted;
}
public static Cursor query(@NonNull final ContentResolver resolver, @NonNull final Uri uri,
final String[] projection, final String selection,
final String[] selectionArgs, final String sortOrder) {
return resolver.query(uri, projection, selection, selectionArgs, sortOrder);
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public static Cursor query(@NonNull final ContentResolver resolver, @NonNull final Uri uri,
final String[] projection, final String selection,
final String[] selectionArgs, final String sortOrder,
final CancellationSignal cancellationSignal) {
return resolver.query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal);
}
}