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

fanfou support

This commit is contained in:
Mariotaku Lee 2016-03-10 20:34:43 +08:00
parent 2b6c3e5e71
commit 5b9b727b09
60 changed files with 512 additions and 205 deletions

View File

@ -254,4 +254,5 @@ public interface TwidereConstants extends SharedPreferenceConstants, IntentConst
int TWITTER_MAX_IMAGE_HEIGHT = 2048;
String USER_TYPE_TWITTER_COM = "twitter.com";
String USER_TYPE_FANFOU_COM = "fanfou.com";
}

View File

@ -49,11 +49,11 @@ public interface TimelineResources {
ResponseList<Status> getRetweetsOfMe(@Query Paging paging) throws TwitterException;
@GET("/statuses/user_timeline.json")
ResponseList<Status> getUserTimeline(@Query("user_id") long userId, @Query Paging paging) throws TwitterException;
ResponseList<Status> getUserTimeline(@Query("user_id") String userId, @Query Paging paging) throws TwitterException;
@GET("/statuses/user_timeline.json")
ResponseList<Status> getUserTimeline(@Query Paging paging) throws TwitterException;
@GET("/statuses/user_timeline.json")
ResponseList<Status> getUserTimeline(@Query("screen_name") String screenName, @Query Paging paging) throws TwitterException;
ResponseList<Status> getUserTimelineByScreenName(@Query("screen_name") String screenName, @Query Paging paging) throws TwitterException;
}

View File

@ -58,6 +58,14 @@ public class Activity$$JsonObjectMapper extends JsonMapper<Activity> {
parseField(instance, fieldName, jsonParser);
jsonParser.skipChildren();
}
try {
instance.maxSortPosition = Long.parseLong(instance.maxPosition);
instance.minSortPosition = Long.parseLong(instance.minPosition);
} catch (NumberFormatException e) {
final long time = instance.createdAt != null ? instance.createdAt.getTime() : -1;
instance.maxSortPosition = time;
instance.minSortPosition = time;
}
return instance;
}
@ -77,9 +85,9 @@ public class Activity$$JsonObjectMapper extends JsonMapper<Activity> {
throw new IOException(e);
}
} else if ("min_position".equals(fieldName)) {
instance.minPosition = jsonParser.getValueAsLong(-1);
instance.minPosition = jsonParser.getValueAsString();
} else if ("max_position".equals(fieldName)) {
instance.maxPosition = jsonParser.getValueAsLong(-1);
instance.maxPosition = jsonParser.getValueAsString();
} else if ("sources_size".equals(fieldName)) {
instance.sourcesSize = jsonParser.getValueAsInt();
} else if ("targets_size".equals(fieldName)) {

View File

@ -39,7 +39,8 @@ public class Activity extends TwitterResponseObject implements TwitterResponse,
User[] targetObjectUsers;
Status[] targetObjectStatuses, targetStatuses;
UserList[] targetUserLists, targetObjectUserLists;
long maxPosition, minPosition = -1;
String maxPosition = null, minPosition = null;
long maxSortPosition =-1, minSortPosition = -1;
int targetObjectsSize, targetsSize, sourcesSize;
Activity() {
@ -66,14 +67,22 @@ public class Activity extends TwitterResponseObject implements TwitterResponse,
return createdAt;
}
public long getMaxPosition() {
public String getMaxPosition() {
return maxPosition;
}
public long getMinPosition() {
public String getMinPosition() {
return minPosition;
}
public long getMaxSortPosition() {
return maxSortPosition;
}
public long getMinSortPosition() {
return minSortPosition;
}
public User[] getSources() {
return sources;
}
@ -112,28 +121,33 @@ public class Activity extends TwitterResponseObject implements TwitterResponse,
@Override
public String toString() {
return "ActivityJSONImpl{" +
"action=" + action +
return "Activity{" +
"action='" + action + '\'' +
", rawAction='" + rawAction + '\'' +
", createdAt=" + createdAt +
", sources=" + Arrays.toString(sources) +
", targetUsers=" + Arrays.toString(targetUsers) +
", targetObjectUsers=" + Arrays.toString(targetObjectUsers) +
", targetObjectStatuses=" + Arrays.toString(targetObjectStatuses) +
", targetStatuses=" + Arrays.toString(targetStatuses) +
", targetUserLists=" + Arrays.toString(targetUserLists) +
", targetObjectUserLists=" + Arrays.toString(targetObjectUserLists) +
", maxPosition=" + maxPosition +
", minPosition=" + minPosition +
", maxPosition='" + maxPosition + '\'' +
", minPosition='" + minPosition + '\'' +
", maxSortPosition=" + maxSortPosition +
", minSortPosition=" + minSortPosition +
", targetObjectsSize=" + targetObjectsSize +
", targetsSize=" + targetsSize +
", sourcesSize=" + sourcesSize +
'}';
"} " + super.toString();
}
public static Activity fromMention(String twitterId, Status status) {
final Activity activity = new Activity();
// TODO handle this -1 position case
activity.maxPosition = activity.minPosition = -1;
activity.maxPosition = activity.minPosition = null;
activity.maxSortPosition = activity.minSortPosition = status.getSortId();
activity.createdAt = status.getCreatedAt();
if (TextUtils.equals(status.getInReplyToUserId(), twitterId)) {

View File

@ -71,7 +71,10 @@ public class SavedSearch extends TwitterResponseObject implements Comparable<Sav
@Override
public int compareTo(@NonNull SavedSearch another) {
return (int) (id - another.id);
final long diff = id - another.id;
if (diff > Integer.MAX_VALUE) return Integer.MAX_VALUE;
if (diff < Integer.MIN_VALUE) return Integer.MIN_VALUE;
return (int) diff;
}
}

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.api.twitter.model;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
@ -47,7 +48,8 @@ public class Status extends TwitterResponseObject implements Comparable<Status>,
@JsonField(name = "id")
String id;
@JsonField(name = "raw_id")
// Fanfou uses this key
@JsonField(name = "rawid")
long rawId = -1;
@JsonField(name = "text")
@ -65,12 +67,15 @@ public class Status extends TwitterResponseObject implements Comparable<Status>,
@JsonField(name = "extended_entities")
Entities extendedEntities;
@Nullable
@JsonField(name = "in_reply_to_status_id")
String inReplyToStatusId;
@Nullable
@JsonField(name = "in_reply_to_user_id")
String inReplyToUserId;
@Nullable
@JsonField(name = "in_reply_to_screen_name")
String inReplyToScreenName;
@ -115,6 +120,9 @@ public class Status extends TwitterResponseObject implements Comparable<Status>,
@JsonField(name = "quoted_status")
Status quotedStatus;
@JsonField(name = "repost_status")
Status repostStatus;
@JsonField(name = "card")
CardEntity card;
@ -138,17 +146,18 @@ public class Status extends TwitterResponseObject implements Comparable<Status>,
return user;
}
@Nullable
public String getInReplyToScreenName() {
return inReplyToScreenName;
}
@Nullable
public String getInReplyToUserId() {
return inReplyToUserId;
}
@Nullable
public String getInReplyToStatusId() {
return inReplyToStatusId;
}
@ -325,18 +334,10 @@ public class Status extends TwitterResponseObject implements Comparable<Status>,
@Override
public int compareTo(@NonNull final Status that) {
final int delta = createdAt.compareTo(that.createdAt);
if (delta == 0) {
if (rawId != -1) {
return (int) (rawId - that.rawId);
}
try {
return (int) (Long.parseLong(id) - Long.parseLong(that.id));
} catch (NumberFormatException e) {
// Ignore
}
}
return delta;
final long diff = getSortId() - that.getSortId();
if (diff > Integer.MAX_VALUE) return Integer.MAX_VALUE;
if (diff < Integer.MIN_VALUE) return Integer.MIN_VALUE;
return (int) diff;
}
@Override
@ -394,6 +395,15 @@ public class Status extends TwitterResponseObject implements Comparable<Status>,
@OnJsonParseComplete
void onJsonParseComplete() throws IOException {
if (id == null || text == null) throw new IOException("Malformed Status object");
// Fix for fanfou
if (TextUtils.isEmpty(inReplyToStatusId)) {
inReplyToStatusId = null;
inReplyToUserId = null;
inReplyToScreenName = null;
}
if (quotedStatus == null && repostStatus != null) {
quotedStatus = repostStatus;
}
}
public String getLang() {
@ -410,7 +420,11 @@ public class Status extends TwitterResponseObject implements Comparable<Status>,
sortId = rawId;
if (sortId == -1) {
// Try use long id
sortId = Long.parseLong(id);
try {
sortId = Long.parseLong(id);
} catch (NumberFormatException e) {
// Ignore
}
}
if (sortId == -1 && createdAt != null) {
// Try use timestamp

View File

@ -144,6 +144,12 @@ public class User extends TwitterResponseObject implements Comparable<User> {
@JsonField(name = "profile_image_url_https")
String profileImageUrlHttps;
/**
* Fanfou has this field
*/
@JsonField(name = "profile_image_url_large")
String profileImageUrlLarge;
@JsonField(name = "profile_banner_url")
String profileBannerUrl;
@ -363,11 +369,13 @@ public class User extends TwitterResponseObject implements Comparable<User> {
return profileImageUrl;
}
public String getProfileImageUrlHttps() {
return profileImageUrlHttps;
}
public String getProfileImageUrlLarge() {
return profileImageUrlLarge;
}
public String getProfileLinkColor() {
if (profileLinkColor != null) return profileLinkColor;

View File

@ -123,7 +123,10 @@ public class UserList extends TwitterResponseObject implements Comparable<UserLi
@Override
public int compareTo(@NonNull UserList another) {
return (int) (id - another.id);
final long diff = id - another.id;
if (diff > Integer.MAX_VALUE) return Integer.MAX_VALUE;
if (diff < Integer.MIN_VALUE) return Integer.MIN_VALUE;
return (int) diff;
}
@Override

View File

@ -211,4 +211,5 @@ public interface IntentConstants {
String EXTRA_CARD = "card";
String EXTRA_IS_POSSIBLY_SENSITIVE = "is_possibly_sensitive";
String EXTRA_REFERRAL = "referral";
String EXTRA_LOADING_MORE = "loading_more";
}

View File

@ -69,12 +69,19 @@ public class ParcelableActivity implements Comparable<ParcelableActivity>, Parce
public long timestamp;
@ParcelableThisPlease
@JsonField(name = "max_position")
@CursorField(value = Activities.MAX_POSITION)
public long max_position;
@CursorField(value = Activities.MAX_SORT_POSITION)
public long max_sort_position;
@ParcelableThisPlease
@JsonField(name = "min_position")
@CursorField(value = Activities.MIN_POSITION)
public long min_position;
@CursorField(value = Activities.MIN_SORT_POSITION)
public long min_sort_position;
@JsonField(name = "max_request_position")
@CursorField(value = Activities.MAX_REQUEST_POSITION)
public String max_position;
@ParcelableThisPlease
@JsonField(name = "min_request_position")
@CursorField(value = Activities.MIN_REQUEST_POSITION)
public String min_position;
@ParcelableThisPlease
@JsonField(name = "action")
@CursorField(value = Activities.ACTION)
@ -147,8 +154,10 @@ public class ParcelableActivity implements Comparable<ParcelableActivity>, Parce
"_id=" + _id +
", account_key=" + account_key +
", timestamp=" + timestamp +
", max_position=" + max_position +
", min_position=" + min_position +
", max_sort_position=" + max_sort_position +
", min_sort_position=" + min_sort_position +
", max_position='" + max_position + '\'' +
", min_position='" + min_position + '\'' +
", action='" + action + '\'' +
", source_ids=" + Arrays.toString(source_ids) +
", sources=" + Arrays.toString(sources) +
@ -160,6 +169,7 @@ public class ParcelableActivity implements Comparable<ParcelableActivity>, Parce
", target_object_users=" + Arrays.toString(target_object_users) +
", is_gap=" + is_gap +
", status_user_following=" + status_user_following +
", account_color=" + account_color +
", after_filtered_source_ids=" + Arrays.toString(after_filtered_source_ids) +
", after_filtered_sources=" + Arrays.toString(after_filtered_sources) +
'}';
@ -167,7 +177,7 @@ public class ParcelableActivity implements Comparable<ParcelableActivity>, Parce
@Override
public int hashCode() {
return calculateHashCode(account_key, timestamp, max_position, min_position);
return calculateHashCode(account_key, timestamp, max_sort_position, min_sort_position);
}
@Override
@ -182,7 +192,7 @@ public class ParcelableActivity implements Comparable<ParcelableActivity>, Parce
public boolean equals(final Object that) {
if (!(that instanceof ParcelableActivity)) return false;
final ParcelableActivity activity = (ParcelableActivity) that;
return max_position == activity.max_position && min_position == activity.min_position;
return max_sort_position == activity.max_sort_position && min_sort_position == activity.min_sort_position;
}
@Override

View File

@ -118,7 +118,9 @@ public class ParcelableDirectMessage implements Parcelable, Comparable<Parcelabl
@Override
public int compareTo(@NonNull final ParcelableDirectMessage another) {
final long diff = another.timestamp - timestamp;
final long diff = timestamp - another.timestamp;
if (diff > Integer.MAX_VALUE) return Integer.MAX_VALUE;
if (diff < Integer.MIN_VALUE) return Integer.MIN_VALUE;
return (int) diff;
}

View File

@ -316,11 +316,13 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
@Override
public int compareTo(@NonNull final ParcelableStatus another) {
long timeDelta = timestamp - another.timestamp;
if (timeDelta == 0) {
return (int) (sort_id - another.sort_id);
long diff = timestamp - another.timestamp;
if (diff == 0) {
diff = sort_id - another.sort_id;
}
return (int) timeDelta;
if (diff > Integer.MAX_VALUE) return Integer.MAX_VALUE;
if (diff < Integer.MIN_VALUE) return Integer.MIN_VALUE;
return (int) diff;
}
@Override

View File

@ -82,7 +82,10 @@ public class ParcelableUserList implements Parcelable, Comparable<ParcelableUser
@Override
public int compareTo(@NonNull final ParcelableUserList another) {
return (int) (position - another.position);
final long diff = position - another.position;
if (diff > Integer.MAX_VALUE) return Integer.MAX_VALUE;
if (diff < Integer.MIN_VALUE) return Integer.MIN_VALUE;
return (int) diff;
}
@Override

View File

@ -122,24 +122,27 @@ public class UserKey implements Comparable<UserKey>, Parcelable {
StringBuilder idBuilder = new StringBuilder(), hostBuilder = new StringBuilder();
for (int i = 0, j = str.length(); i < j; i++) {
final char ch = str.charAt(i);
// accept all characters if is escaping
if (!escaping) {
if (ch == '\\') {
escaping = true;
} else if (ch == '@') {
idFinished = true;
} else if (ch == ',') {
// end of item
break;
}
boolean append = false;
if (escaping) {
// accept all characters if is escaping
append = true;
escaping = false;
} else if (ch == '\\') {
escaping = true;
} else if (ch == '@') {
idFinished = true;
} else if (ch == ',') {
// end of item, just jump out
break;
} else {
append = true;
}
if (!isSpecialChar(ch) || !escaping) {
if (append) {
if (idFinished) {
hostBuilder.append(ch);
} else {
idBuilder.append(ch);
}
escaping = false;
}
}
if (hostBuilder.length() != 0) {

View File

@ -919,8 +919,11 @@ public interface TwidereDataStore {
String STATUS_QUOTE_TEXT_HTML = "status_quote_text_html";
String STATUS_USER_FOLLOWING = "status_user_following";
String IS_GAP = "status_is_gap";
String MIN_POSITION = "min_position";
String MAX_POSITION = "max_position";
String MIN_SORT_POSITION = "min_position";
String MAX_SORT_POSITION = "max_position";
;
String MIN_REQUEST_POSITION = "min_request_position";
String MAX_REQUEST_POSITION = "max_request_position";
String SOURCES = "sources";
String SOURCE_IDS = "source_ids";
String TARGET_STATUSES = "target_statuses";
@ -933,13 +936,15 @@ public interface TwidereDataStore {
String[] COLUMNS = {_ID, ACCOUNT_KEY, ACTION, TIMESTAMP, STATUS_ID, STATUS_USER_ID,
STATUS_RETWEETED_BY_USER_ID, STATUS_QUOTED_USER_ID, STATUS_SOURCE, STATUS_QUOTE_SOURCE,
STATUS_TEXT_PLAIN, STATUS_QUOTE_TEXT_PLAIN, STATUS_TEXT_HTML, STATUS_QUOTE_TEXT_HTML,
IS_GAP, MIN_POSITION, MAX_POSITION, SOURCES, SOURCE_IDS, TARGET_STATUSES, TARGET_USERS,
IS_GAP, MIN_SORT_POSITION, MAX_SORT_POSITION, SOURCES, SOURCE_IDS, TARGET_STATUSES, TARGET_USERS,
TARGET_USER_LISTS, TARGET_OBJECT_STATUSES, TARGET_OBJECT_USER_LISTS, TARGET_OBJECT_USERS,
STATUS_RETWEET_ID, STATUS_USER_FOLLOWING, INSERTED_DATE};
STATUS_RETWEET_ID, STATUS_USER_FOLLOWING, INSERTED_DATE, MIN_REQUEST_POSITION,
MAX_REQUEST_POSITION};
String[] TYPES = {TYPE_PRIMARY_KEY, TYPE_TEXT, TYPE_TEXT, TYPE_INT, TYPE_INT, TYPE_INT,
TYPE_INT, TYPE_INT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT,
TYPE_BOOLEAN, TYPE_INT, TYPE_INT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT,
TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_INT, TYPE_BOOLEAN, INSERTED_DATE_TYPE};
TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_INT, TYPE_BOOLEAN, INSERTED_DATE_TYPE, TYPE_TEXT,
TYPE_TEXT};
String DEFAULT_SORT_ORDER = TIMESTAMP + " DESC";

View File

@ -0,0 +1,24 @@
package org.mariotaku.twidere.model;
import junit.framework.TestCase;
/**
* Created by mariotaku on 16/3/10.
*/
public class UserKeyLocalTest extends TestCase {
public void testToString() throws Exception {
assertEquals("abc@twitter.com", new UserKey("abc", "twitter.com").toString());
assertEquals("\\@user@twitter.com", new UserKey("@user", "twitter.com").toString());
assertEquals("\\@u\\\\ser@twitter.com", new UserKey("@u\\ser", "twitter.com").toString());
}
public void testValueOf() throws Exception {
assertEquals(new UserKey("abc", "twitter.com"), UserKey.valueOf("abc@twitter.com"));
assertEquals(new UserKey("abc@", "twitter.com"), UserKey.valueOf("abc\\@@twitter.com"));
assertEquals(new UserKey("abc@", "twitter.com"), UserKey.valueOf("a\\bc\\@@twitter.com"));
assertEquals(new UserKey("a\\bc@", "twitter.com"), UserKey.valueOf("a\\\\bc\\@@twitter.com"));
assertEquals(new UserKey("abc", "twitter.com"), UserKey.valueOf("abc@twitter.com,def@twitter.com"));
assertEquals(new UserKey("@abc", "twitter.com"), UserKey.valueOf("\\@abc@twitter.com,def@twitter.com"));
}
}

View File

@ -12,10 +12,15 @@ public class UserKeyTest {
@Test
public void testToString() throws Exception {
assertEquals("abc@twitter.com", new UserKey("abc", "twitter.com").toString());
assertEquals("\\@user@twitter.com", new UserKey("@user", "twitter.com").toString());
assertEquals("\\@u\\\\ser@twitter.com", new UserKey("@u\\ser", "twitter.com").toString());
}
@Test
public void testValueOf() throws Exception {
assertEquals(UserKey.valueOf("abc@twitter.com"), new UserKey("abc", "twitter.com"));
assertEquals(new UserKey("abc", "twitter.com"), UserKey.valueOf("abc@twitter.com"));
assertEquals(new UserKey("abc@", "twitter.com"), UserKey.valueOf("abc\\@@twitter.com"));
assertEquals(new UserKey("abc@", "twitter.com"), UserKey.valueOf("a\\bc\\@@twitter.com"));
assertEquals(new UserKey("a\\bc@", "twitter.com"), UserKey.valueOf("a\\\\bc\\@@twitter.com"));
}
}

View File

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

View File

@ -567,7 +567,7 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
}
@Nullable
private static Pair<String, String> detectAccountType(Twitter twitter) {
private static Pair<String, String> detectAccountType(Twitter twitter, User user) {
try {
// Get StatusNet specific resource
StatusNetConfig config = twitter.getStatusNetConfig();
@ -593,6 +593,9 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
} catch (TwitterException e) {
// Ignore
}
if (UserKeyUtils.isFanfouUser(user)) {
return Pair.create(ParcelableCredentials.ACCOUNT_TYPE_FANFOU, null);
}
return Pair.create(ParcelableCredentials.ACCOUNT_TYPE_TWITTER, null);
}
@ -680,7 +683,7 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
final int color = analyseUserProfileColor(user);
return new SignInResponse(isUserLoggedIn(context, userId), auth, user,
ParcelableCredentials.AUTH_TYPE_OAUTH, color, apiUrlFormat, sameOauthSigningUrl,
noVersionSuffix, detectAccountType(twitter));
noVersionSuffix, detectAccountType(twitter, user));
} catch (final TwitterException e) {
return new SignInResponse(false, false, e);
}
@ -802,7 +805,7 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
if (userId == null) return new SignInResponse(false, false, null);
final int color = analyseUserProfileColor(user);
return new SignInResponse(isUserLoggedIn(activity, userId), username, password, user,
color, apiUrlFormat, noVersionSuffix, detectAccountType(twitter));
color, apiUrlFormat, noVersionSuffix, detectAccountType(twitter, user));
}
@ -818,7 +821,7 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
if (userId == null) return new SignInResponse(false, false, null);
final int color = analyseUserProfileColor(user);
return new SignInResponse(isUserLoggedIn(activity, userId), user, color, apiUrlFormat,
noVersionSuffix, detectAccountType(twitter));
noVersionSuffix, detectAccountType(twitter, user));
}
private SignInResponse getOAuthSignInResponse(SignInActivity activity, OAuthToken accessToken,
@ -829,7 +832,7 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
final User user = twitter.verifyCredentials();
final int color = analyseUserProfileColor(user);
return new SignInResponse(isUserLoggedIn(activity, userId), auth, user, authType, color,
apiUrlFormat, sameOAuthSigningUrl, noVersionSuffix, detectAccountType(twitter));
apiUrlFormat, sameOAuthSigningUrl, noVersionSuffix, detectAccountType(twitter, user));
}
static class WrongBasicCredentialException extends AuthenticationException {

View File

@ -30,10 +30,12 @@ import com.mobeta.android.dslv.SimpleDragSortCursorAdapter;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.iface.IBaseAdapter;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.ParcelableAccountCursorIndices;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
import org.mariotaku.twidere.util.JsonSerializer;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
import org.mariotaku.twidere.view.holder.AccountViewHolder;
@ -80,7 +82,14 @@ public class AccountsAdapter extends SimpleDragSortCursorAdapter implements Cons
holder.screenName.setText(String.format("@%s", cursor.getString(mIndices.screen_name)));
holder.setAccountColor(color);
if (mDisplayProfileImage) {
mImageLoader.displayProfileImage(holder.profileImage, cursor.getString(mIndices.profile_image_url));
final ParcelableUser user = JsonSerializer.parse(cursor.getString(mIndices.account_user),
ParcelableUser.class);
if (user != null) {
mImageLoader.displayProfileImage(holder.profileImage, user);
} else {
mImageLoader.displayProfileImage(holder.profileImage,
cursor.getString(mIndices.profile_image_url));
}
} else {
mImageLoader.cancelDisplayTask(holder.profileImage);
}

View File

@ -58,8 +58,6 @@ import org.mariotaku.twidere.util.dagger.ApplicationModule;
import org.mariotaku.twidere.util.dagger.DependencyHolder;
import org.mariotaku.twidere.util.net.TwidereDns;
import static org.mariotaku.twidere.util.DataStoreUtils.initAccountColor;
public class TwidereApplication extends Application implements Constants,
OnSharedPreferenceChangeListener {
@ -122,7 +120,6 @@ public class TwidereApplication extends Application implements Constants,
initDebugMode();
initBugReport();
mHandler = new Handler();
initAccountColor(this);
final PackageManager pm = getPackageManager();
final ComponentName main = new ComponentName(this, MainActivity.class);

View File

@ -341,8 +341,9 @@ public abstract class AbsActivitiesFragment extends AbsContentListRecyclerViewFr
final ParcelableActivitiesAdapter adapter = getAdapter();
final ParcelableActivity activity = adapter.getActivity(position);
final UserKey[] accountIds = {activity.account_key};
final String[] maxIds = {String.valueOf(activity.min_position)};
getActivities(new BaseRefreshTaskParam(accountIds, maxIds, null));
final String[] maxIds = {activity.min_position};
final long[] maxSortIds = {activity.min_sort_position};
getActivities(new BaseRefreshTaskParam(accountIds, maxIds, null, maxSortIds, null));
}
@Override

View File

@ -73,7 +73,6 @@ import org.mariotaku.twidere.view.holder.iface.IStatusViewHolder;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.TimeZone;
import edu.tsinghua.hotmobi.HotMobiLogger;
@ -333,7 +332,8 @@ public abstract class AbsStatusesFragment extends AbsContentListRecyclerViewFrag
if (status == null) return;
final UserKey[] accountIds = {status.account_key};
final String[] maxIds = {status.id};
getStatuses(new BaseRefreshTaskParam(accountIds, maxIds, null));
final long[] maxSortIds = {status.sort_id};
getStatuses(new BaseRefreshTaskParam(accountIds, maxIds, null, maxSortIds, null));
}
@Override
@ -356,7 +356,8 @@ public abstract class AbsStatusesFragment extends AbsContentListRecyclerViewFrag
}
}
protected void onHasMoreDataChanged(boolean hasMoreData) {}
protected void onHasMoreDataChanged(boolean hasMoreData) {
}
@NonNull
@TimelineType
@ -531,7 +532,7 @@ public abstract class AbsStatusesFragment extends AbsContentListRecyclerViewFrag
protected abstract boolean hasMoreData(List<ParcelableStatus> data);
protected abstract Loader<List<ParcelableStatus>> onCreateStatusesLoader(final Context context, final Bundle args,
final boolean fromUser);
final boolean fromUser);
protected abstract void onLoadingFinished();
@ -555,7 +556,7 @@ public abstract class AbsStatusesFragment extends AbsContentListRecyclerViewFrag
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
if (!getUserVisibleHint()) return;
if (!getUserVisibleHint() || menuInfo == null) return;
final ParcelableStatusesAdapter adapter = getAdapter();
final MenuInflater inflater = new MenuInflater(getContext());
final ExtendedRecyclerView.ContextMenuInfo contextMenuInfo =

View File

@ -44,8 +44,8 @@ import org.mariotaku.twidere.R;
import org.mariotaku.twidere.activity.support.ColorPickerDialogActivity;
import org.mariotaku.twidere.activity.support.SignInActivity;
import org.mariotaku.twidere.adapter.AccountsAdapter;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.provider.TwidereDataStore.AccountSupportColumns;
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.Inbox;
@ -151,9 +151,16 @@ public class AccountsManagerFragment extends BaseSupportFragment implements Load
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final Context context = getContext();
if (context == null) return;
final ParcelableAccount account = mAdapter.getAccount(position);
IntentUtils.openUserProfile(getActivity(), account.account_key, account.account_key.getId(),
account.screen_name, null, true, UserFragment.Referral.SELF_PROFILE);
if (account.account_user != null) {
IntentUtils.openUserProfile(context, account.account_user, null, true,
UserFragment.Referral.SELF_PROFILE);
} else {
IntentUtils.openUserProfile(context, account.account_key, account.account_key.getId(),
account.screen_name, null, true, UserFragment.Referral.SELF_PROFILE);
}
}
@Override

View File

@ -42,12 +42,11 @@ import org.mariotaku.twidere.activity.support.HomeActivity;
import org.mariotaku.twidere.adapter.ParcelableActivitiesAdapter;
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter.IndicatorPosition;
import org.mariotaku.twidere.loader.support.ExtendedObjectCursorLoader;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.BaseRefreshTaskParam;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.ParcelableActivity;
import org.mariotaku.twidere.model.ParcelableActivityCursorIndices;
import org.mariotaku.twidere.model.RefreshTaskParam;
import org.mariotaku.twidere.model.SimpleRefreshTaskParam;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.message.AccountChangedEvent;
import org.mariotaku.twidere.model.message.FavoriteTaskEvent;
import org.mariotaku.twidere.model.message.GetActivitiesTaskEvent;
@ -58,8 +57,6 @@ import org.mariotaku.twidere.model.util.ParcelableAccountUtils;
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
import org.mariotaku.twidere.provider.TwidereDataStore.Activities;
import org.mariotaku.twidere.provider.TwidereDataStore.Filters;
import org.mariotaku.twidere.task.AbstractTask;
import org.mariotaku.twidere.task.util.TaskStarter;
import org.mariotaku.twidere.util.DataStoreUtils;
import org.mariotaku.twidere.util.ErrorInfoStore;
import org.mariotaku.twidere.util.TwidereArrayUtils;
@ -195,41 +192,61 @@ public abstract class CursorActivitiesFragment extends AbsActivitiesFragment {
if ((position & IndicatorPosition.START) != 0) return;
super.onLoadMoreContents(position);
if (position == 0) return;
TaskStarter.execute(new AbstractTask<Object, RefreshTaskParam, CursorActivitiesFragment>() {
getActivities(new SimpleRefreshTaskParam() {
@NonNull
@Override
public RefreshTaskParam doLongOperation(Object o) {
final UserKey[] accountKeys = getAccountKeys();
final String[] maxIds = getOldestActivityIds(accountKeys);
return new BaseRefreshTaskParam(accountKeys, maxIds, null);
public UserKey[] getAccountKeysWorker() {
return CursorActivitiesFragment.this.getAccountKeys();
}
@Nullable
@Override
public String[] getMaxIds() {
return getOldestActivityIds(getAccountKeys());
}
@Nullable
@Override
public long[] getMaxSortIds() {
return DataStoreUtils.getOldestActivityMaxSortPositions(getActivity(),
getContentUri(), getAccountKeys());
}
@Override
public void afterExecute(CursorActivitiesFragment fragment, RefreshTaskParam result) {
fragment.getActivities(result);
public boolean hasMaxIds() {
return true;
}
}.setResultHandler(this));
});
}
@Override
public boolean triggerRefresh() {
super.triggerRefresh();
TaskStarter.execute(new AbstractTask<Object, RefreshTaskParam, CursorActivitiesFragment>() {
getActivities(new SimpleRefreshTaskParam() {
@NonNull
@Override
public RefreshTaskParam doLongOperation(Object o) {
if (getActivity() == null) {
return null;
}
final UserKey[] accountKeys = getAccountKeys();
final String[] sinceIds = getNewestActivityIds(accountKeys);
return new BaseRefreshTaskParam(accountKeys, sinceIds, null);
public UserKey[] getAccountKeysWorker() {
return CursorActivitiesFragment.this.getAccountKeys();
}
@Nullable
@Override
public String[] getSinceIds() {
return getNewestActivityIds(getAccountKeys());
}
@Nullable
@Override
public long[] getSinceSortIds() {
return DataStoreUtils.getNewestActivityMaxSortPositions(getActivity(),
getContentUri(), getAccountKeys());
}
@Override
public void afterExecute(CursorActivitiesFragment fragment, RefreshTaskParam result) {
if (result == null) return;
fragment.getActivities(result);
public boolean hasSinceIds() {
return true;
}
}.setResultHandler(this));
});
return true;
}

View File

@ -43,11 +43,11 @@ import org.mariotaku.twidere.adapter.ListParcelableStatusesAdapter;
import org.mariotaku.twidere.adapter.ParcelableStatusesAdapter;
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter.IndicatorPosition;
import org.mariotaku.twidere.loader.support.ExtendedObjectCursorLoader;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableStatusCursorIndices;
import org.mariotaku.twidere.model.SimpleRefreshTaskParam;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.message.AccountChangedEvent;
import org.mariotaku.twidere.model.message.FavoriteTaskEvent;
import org.mariotaku.twidere.model.message.GetStatusesTaskEvent;
@ -253,11 +253,12 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment {
// Only supports load from end, skip START flag
if ((position & IndicatorPosition.START) != 0) return;
super.onLoadMoreContents(position);
final Context context = getContext();
if (position == 0) return;
getStatuses(new SimpleRefreshTaskParam() {
@NonNull
@Override
public UserKey[] getAccountKeys() {
public UserKey[] getAccountKeysWorker() {
return CursorStatusesFragment.this.getAccountKeys();
}
@ -267,6 +268,13 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment {
return getOldestStatusIds(getAccountKeys());
}
@Nullable
@Override
public long[] getMaxSortIds() {
return DataStoreUtils.getOldestStatusSortIds(context, getContentUri(),
getAccountKeys());
}
@Override
public boolean hasMaxIds() {
return true;
@ -277,10 +285,11 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment {
@Override
public boolean triggerRefresh() {
super.triggerRefresh();
final Context context = getContext();
getStatuses(new SimpleRefreshTaskParam() {
@NonNull
@Override
public UserKey[] getAccountKeys() {
public UserKey[] getAccountKeysWorker() {
return CursorStatusesFragment.this.getAccountKeys();
}
@ -294,6 +303,13 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment {
public String[] getSinceIds() {
return getNewestStatusIds(getAccountKeys());
}
@Nullable
@Override
public long[] getSinceSortIds() {
return DataStoreUtils.getNewestStatusSortIds(context, getContentUri(),
getAccountKeys());
}
});
return true;
}

View File

@ -94,6 +94,7 @@ public abstract class ParcelableStatusesFragment extends AbsStatusesFragment {
if (mPage > 0) {
args.putInt(EXTRA_PAGE, mPage);
}
args.putBoolean(EXTRA_LOADING_MORE, param.isLoadingMore());
args.putBoolean(EXTRA_FROM_USER, true);
getLoaderManager().restartLoader(0, args, this);
return true;
@ -149,12 +150,16 @@ public abstract class ParcelableStatusesFragment extends AbsStatusesFragment {
super.onLoadMoreContents(position);
if (position == 0) return;
final ParcelableStatusesAdapter adapter = getAdapter();
final ParcelableStatus status = adapter.getStatus(adapter.getStatusStartIndex() +
adapter.getStatusCount() - 1);
// Load the last item
final int idx = adapter.getStatusStartIndex() + adapter.getStatusCount() - 1;
if (idx < 0) return;
final ParcelableStatus status = adapter.getStatus(idx);
UserKey[] accountKeys = {status.account_key};
final String[] maxIds = {status.id};
mPage += mPageDelta;
getStatuses(new BaseRefreshTaskParam(accountKeys, maxIds, null));
final BaseRefreshTaskParam param = new BaseRefreshTaskParam(accountKeys, maxIds, null);
param.setIsLoadingMore(true);
getStatuses(param);
}
public final void replaceStatus(final ParcelableStatus status) {

View File

@ -42,8 +42,9 @@ public class RetweetsOfMeFragment extends ParcelableStatusesFragment {
final String maxId = args.getString(EXTRA_MAX_ID);
final String sinceId = args.getString(EXTRA_SINCE_ID);
final int tabPosition = args.getInt(EXTRA_TAB_POSITION, -1);
final boolean loadingMore = args.getBoolean(EXTRA_LOADING_MORE, false);
return new RetweetsOfMeLoader(context, accountKey, sinceId, maxId, getAdapterData(),
getSavedStatusesFileArgs(), tabPosition, fromUser);
getSavedStatusesFileArgs(), tabPosition, fromUser, loadingMore);
}
@Override

View File

@ -222,10 +222,12 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
final String sinceId = args.getString(EXTRA_SINCE_ID);
final long maxSortId = args.getLong(EXTRA_MAX_SORT_ID);
final long sinceSortId = args.getLong(EXTRA_SINCE_SORT_ID);
final boolean loadingMore = args.getBoolean(EXTRA_LOADING_MORE, false);
assert status != null;
final ConversationLoader loader = new ConversationLoader(getActivity(), status, sinceId,
maxId, sinceSortId, maxSortId, mStatusAdapter.getData(), true);
loader.setComparator(ParcelableStatus.REVERSE_COMPARATOR);
maxId, sinceSortId, maxSortId, mStatusAdapter.getData(), true, loadingMore);
// Setting comparator to null lets statuses sort ascending
loader.setComparator(null);
return loader;
}

View File

@ -59,8 +59,10 @@ public class StatusesSearchFragment extends ParcelableStatusesFragment {
final String query = args.getString(EXTRA_QUERY);
final int tabPosition = args.getInt(EXTRA_TAB_POSITION, -1);
final boolean makeGap = args.getBoolean(EXTRA_MAKE_GAP, true);
final boolean loadingMore = args.getBoolean(EXTRA_LOADING_MORE, false);
return new TweetSearchLoader(getActivity(), accountKey, query, sinceId, maxId, page,
getAdapterData(), getSavedStatusesFileArgs(), tabPosition, fromUser, makeGap);
getAdapterData(), getSavedStatusesFileArgs(), tabPosition, fromUser, makeGap,
loadingMore);
}
@Override

View File

@ -48,8 +48,9 @@ public class UserFavoritesFragment extends ParcelableStatusesFragment {
final String userId = args.getString(EXTRA_USER_ID);
final String screenName = args.getString(EXTRA_SCREEN_NAME);
final int tabPosition = args.getInt(EXTRA_TAB_POSITION, -1);
final boolean loadingMore = args.getBoolean(EXTRA_LOADING_MORE, false);
return new UserFavoritesLoader(context, accountKey, userId, screenName, sinceId, maxId,
getAdapterData(), getSavedStatusesFileArgs(), tabPosition, fromUser);
getAdapterData(), getSavedStatusesFileArgs(), tabPosition, fromUser, loadingMore);
}
@Override

View File

@ -58,8 +58,10 @@ public class UserListTimelineFragment extends ParcelableStatusesFragment {
final String screenName = args.getString(EXTRA_SCREEN_NAME);
final String listName = args.getString(EXTRA_LIST_NAME);
final int tabPosition = args.getInt(EXTRA_TAB_POSITION, -1);
final boolean loadingMore = args.getBoolean(EXTRA_LOADING_MORE, false);
return new UserListTimelineLoader(getActivity(), accountKey, listId, userId, screenName,
listName, sinceId, maxId, getAdapterData(), getSavedStatusesFileArgs(), tabPosition, fromUser);
listName, sinceId, maxId, getAdapterData(), getSavedStatusesFileArgs(), tabPosition,
fromUser, loadingMore);
}
@Override

View File

@ -105,8 +105,9 @@ public class UserMediaTimelineFragment extends AbsContentRecyclerViewFragment<St
final String screenName = args.getString(EXTRA_SCREEN_NAME);
final int tabPosition = args.getInt(EXTRA_TAB_POSITION, -1);
final boolean fromUser = args.getBoolean(EXTRA_FROM_USER);
final boolean loadingMore = args.getBoolean(EXTRA_LOADING_MORE, false);
return new MediaTimelineLoader(context, accountKey, userId, screenName, sinceId, maxId,
getAdapter().getData(), null, tabPosition, fromUser);
getAdapter().getData(), null, tabPosition, fromUser, loadingMore);
}
@Override

View File

@ -46,8 +46,10 @@ public class UserMentionsFragment extends StatusesSearchFragment {
final int page = args.getInt(EXTRA_PAGE, -1);
final int tabPosition = args.getInt(EXTRA_TAB_POSITION, -1);
final boolean makeGap = args.getBoolean(EXTRA_MAKE_GAP, true);
final boolean loadingMore = args.getBoolean(EXTRA_LOADING_MORE, false);
return new UserMentionsLoader(getActivity(), accountKey, screenName, maxId, sinceId, page,
getAdapterData(), getSavedStatusesFileArgs(), tabPosition, fromUser, makeGap);
getAdapterData(), getSavedStatusesFileArgs(), tabPosition, fromUser, makeGap,
loadingMore);
}
@Override

View File

@ -56,8 +56,9 @@ public class UserTimelineFragment extends ParcelableStatusesFragment {
final String userId = args.getString(EXTRA_USER_ID);
final String screenName = args.getString(EXTRA_SCREEN_NAME);
final int tabPosition = args.getInt(EXTRA_TAB_POSITION, -1);
final boolean loadingMore = args.getBoolean(EXTRA_LOADING_MORE, false);
return new UserTimelineLoader(context, accountKey, userId, screenName, sinceId, maxId, data,
getSavedStatusesFileArgs(), tabPosition, fromUser);
getSavedStatusesFileArgs(), tabPosition, fromUser, loadingMore);
}
@Override

View File

@ -52,8 +52,9 @@ public class ConversationLoader extends TwitterAPIStatusesLoader {
public ConversationLoader(final Context context, @NonNull final ParcelableStatus status,
final String sinceId, final String maxId,
final long sinceSortId, final long maxSortId,
final List<ParcelableStatus> data, final boolean fromUser) {
super(context, status.account_key, sinceId, maxId, data, null, -1, fromUser);
final List<ParcelableStatus> data, final boolean fromUser,
final boolean loadingMore) {
super(context, status.account_key, sinceId, maxId, data, null, -1, fromUser, loadingMore);
mStatus = Nullables.assertNonNull(ParcelUtils.clone(status));
mSinceSortId = sinceSortId;
mMaxSortId = maxSortId;

View File

@ -55,8 +55,9 @@ public class MediaTimelineLoader extends TwitterAPIStatusesLoader {
public MediaTimelineLoader(final Context context, final UserKey accountKey, final String userId,
final String screenName, final String sinceId, final String maxId,
final List<ParcelableStatus> data, final String[] savedStatusesArgs,
final int tabPosition, final boolean fromUser) {
super(context, accountKey, sinceId, maxId, data, savedStatusesArgs, tabPosition, fromUser);
final int tabPosition, final boolean fromUser, boolean loadingMore) {
super(context, accountKey, sinceId, maxId, data, savedStatusesArgs, tabPosition, fromUser,
loadingMore);
mUserId = userId;
mUserScreenName = screenName;
}

View File

@ -30,6 +30,7 @@ import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.collection.NoDuplicatesArrayList;
import java.util.List;
import java.util.Objects;
public abstract class ParcelableStatusesLoader extends AsyncTaskLoader<List<ParcelableStatus>>
implements Constants, IExtendedLoader {
@ -39,7 +40,7 @@ public abstract class ParcelableStatusesLoader extends AsyncTaskLoader<List<Parc
private final int mTabPosition;
private boolean mFromUser;
public ParcelableStatusesLoader(final Context context, final List<ParcelableStatus> data,
public ParcelableStatusesLoader(final Context context, @Nullable final List<ParcelableStatus> data,
final int tabPosition, final boolean fromUser) {
super(context);
mFirstLoad = data == null;
@ -71,7 +72,7 @@ public abstract class ParcelableStatusesLoader extends AsyncTaskLoader<List<Parc
if (statuses == null || statuses.isEmpty()) return false;
boolean result = false;
for (int i = statuses.size() - 1; i >= 0; i--) {
if (statuses.get(i).id == statusId) {
if (TextUtils.equals(statuses.get(i).id, statusId)) {
statuses.remove(i);
result = true;
}

View File

@ -42,8 +42,9 @@ public class RetweetsOfMeLoader extends TwitterAPIStatusesLoader {
public RetweetsOfMeLoader(final Context context, final UserKey accountKey,
final String sinceId, final String maxId,
final List<ParcelableStatus> data, final String[] savedStatusesArgs,
final int tabPosition, boolean fromUser) {
super(context, accountKey, sinceId, maxId, data, savedStatusesArgs, tabPosition, fromUser);
final int tabPosition, boolean fromUser, boolean loadingMore) {
super(context, accountKey, sinceId, maxId, data, savedStatusesArgs, tabPosition, fromUser,
loadingMore);
}
@NonNull

View File

@ -48,8 +48,9 @@ public class TweetSearchLoader extends TwitterAPIStatusesLoader {
public TweetSearchLoader(final Context context, final UserKey accountKey, @Nullable final String query,
final String sinceId, final String maxId, final int page,
final List<ParcelableStatus> data, final String[] savedStatusesArgs,
final int tabPosition, final boolean fromUser, final boolean makeGap) {
super(context, accountKey, sinceId, maxId, data, savedStatusesArgs, tabPosition, fromUser);
final int tabPosition, final boolean fromUser, final boolean makeGap,
boolean loadingMore) {
super(context, accountKey, sinceId, maxId, data, savedStatusesArgs, tabPosition, fromUser, loadingMore);
mPage = page;
mQuery = query;
mGapEnabled = makeGap;

View File

@ -72,7 +72,9 @@ public abstract class TwitterAPIStatusesLoader extends ParcelableStatusesLoader
private final String mMaxId, mSinceId;
@Nullable
private final Object[] mSavedStatusesFileArgs;
private Comparator<ParcelableStatus> mComparator;
private final boolean mLoadingMore;
// Statuses sorted descending by default
private Comparator<ParcelableStatus> mComparator = ParcelableStatus.REVERSE_COMPARATOR;
@Inject
DiskCache mFileCache;
@Inject
@ -81,15 +83,16 @@ public abstract class TwitterAPIStatusesLoader extends ParcelableStatusesLoader
public TwitterAPIStatusesLoader(@NonNull final Context context,
@Nullable final UserKey accountKey,
final String sinceId, final String maxId,
final List<ParcelableStatus> data,
@Nullable final List<ParcelableStatus> data,
@Nullable final String[] savedStatusesArgs,
final int tabPosition, final boolean fromUser) {
final int tabPosition, final boolean fromUser, boolean loadingMore) {
super(context, data, tabPosition, fromUser);
GeneralComponentHelper.build(context).inject(this);
mAccountKey = accountKey;
mMaxId = maxId;
mSinceId = sinceId;
mSavedStatusesFileArgs = savedStatusesArgs;
mLoadingMore = loadingMore;
}
@SuppressWarnings("unchecked")
@ -163,7 +166,7 @@ public abstract class TwitterAPIStatusesLoader extends ParcelableStatusesLoader
final boolean deletedOldGap = rowsDeleted > 0 && ArrayUtils.contains(statusIds, mMaxId);
final boolean noRowsDeleted = rowsDeleted == 0;
final boolean insertGap = minIdx != -1 && (noRowsDeleted || deletedOldGap) && !noItemsBefore
&& statuses.size() >= loadItemLimit;
&& statuses.size() >= loadItemLimit && !mLoadingMore;
for (int i = 0, j = statuses.size(); i < j; i++) {
final Status status = statuses.get(i);
final ParcelableStatus item = ParcelableStatusUtils.fromStatus(status, mAccountKey,

View File

@ -43,8 +43,9 @@ public class UserFavoritesLoader extends TwitterAPIStatusesLoader {
public UserFavoritesLoader(final Context context, final UserKey accountKey, final String userId,
final String screenName, final String sinceId, final String maxId,
final List<ParcelableStatus> data, final String[] savedStatusesArgs,
final int tabPosition, boolean fromUser) {
super(context, accountKey, sinceId, maxId, data, savedStatusesArgs, tabPosition, fromUser);
final int tabPosition, boolean fromUser, boolean loadingMore) {
super(context, accountKey, sinceId, maxId, data, savedStatusesArgs, tabPosition, fromUser,
loadingMore);
mUserId = userId;
mUserScreenName = screenName;
}

View File

@ -45,8 +45,8 @@ public class UserListTimelineLoader extends TwitterAPIStatusesLoader {
public UserListTimelineLoader(final Context context, final UserKey accountKey, final long listId,
final String userId, final String screenName, final String listName,
final String sinceId, final String maxId, final List<ParcelableStatus> data,
final String[] savedStatusesArgs, final int tabPosition, boolean fromUser) {
super(context, accountKey, sinceId, maxId, data, savedStatusesArgs, tabPosition, fromUser);
final String[] savedStatusesArgs, final int tabPosition, boolean fromUser, boolean loadingMore) {
super(context, accountKey, sinceId, maxId, data, savedStatusesArgs, tabPosition, fromUser, loadingMore);
mListId = listId;
mUserId = userId;
mScreenName = screenName;

View File

@ -35,9 +35,9 @@ public class UserMentionsLoader extends TweetSearchLoader {
public UserMentionsLoader(final Context context, final UserKey accountId, final String screenName,
final String maxId, final String sinceId, int page, final List<ParcelableStatus> data,
final String[] savedStatusesArgs, final int tabPosition, boolean fromUser,
boolean makeGap) {
boolean makeGap, boolean loadingMore) {
super(context, accountId, screenName, sinceId, maxId, page, data, savedStatusesArgs, tabPosition,
fromUser, makeGap);
fromUser, makeGap, loadingMore);
}
@NonNull

View File

@ -46,8 +46,8 @@ public class UserTimelineLoader extends TwitterAPIStatusesLoader {
public UserTimelineLoader(final Context context, final UserKey accountId, final String userId,
final String screenName, final String sinceId, final String maxId,
final List<ParcelableStatus> data, final String[] savedStatusesArgs,
final int tabPosition, boolean fromUser) {
super(context, accountId, sinceId, maxId, data, savedStatusesArgs, tabPosition, fromUser);
final int tabPosition, boolean fromUser, boolean loadingMore) {
super(context, accountId, sinceId, maxId, data, savedStatusesArgs, tabPosition, fromUser, loadingMore);
mUserId = userId;
mUserScreenName = screenName;
mIsMyTimeline = TextUtils.equals(accountId.getId(), userId);
@ -59,7 +59,7 @@ public class UserTimelineLoader extends TwitterAPIStatusesLoader {
if (mUserId != null)
return twitter.getUserTimeline(mUserId, paging);
else if (mUserScreenName != null)
return twitter.getUserTimeline(mUserScreenName, paging);
return twitter.getUserTimelineByScreenName(mUserScreenName, paging);
else
throw new TwitterException("Invalid user");
}

View File

@ -13,6 +13,7 @@ public class BaseRefreshTaskParam implements RefreshTaskParam {
private final String[] sinceIds;
private final long[] maxSortIds;
private final long[] sinceSortIds;
private boolean isLoadingMore;
public BaseRefreshTaskParam(UserKey[] accountKeys, String[] maxIds, String[] sinceIds) {
this(accountKeys, maxIds, sinceIds, null, null);
@ -55,12 +56,22 @@ public class BaseRefreshTaskParam implements RefreshTaskParam {
return sinceIds != null;
}
@Override
public long[] getMaxSortIds() {
return maxSortIds;
}
@Override
public long[] getSinceSortIds() {
return sinceSortIds;
}
@Override
public boolean isLoadingMore() {
return isLoadingMore;
}
public void setIsLoadingMore(boolean isLoadingMore) {
this.isLoadingMore = isLoadingMore;
}
}

View File

@ -26,4 +26,6 @@ public interface RefreshTaskParam {
boolean hasSinceIds();
boolean isLoadingMore();
}

View File

@ -1,5 +1,6 @@
package org.mariotaku.twidere.model;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
/**
@ -7,6 +8,18 @@ import android.support.annotation.Nullable;
*/
public abstract class SimpleRefreshTaskParam implements RefreshTaskParam {
UserKey[] cached;
@NonNull
@Override
public final UserKey[] getAccountKeys() {
if (cached != null) return cached;
return cached = getAccountKeysWorker();
}
@NonNull
public abstract UserKey[] getAccountKeysWorker();
@Nullable
@Override
public String[] getMaxIds() {
@ -40,4 +53,9 @@ public abstract class SimpleRefreshTaskParam implements RefreshTaskParam {
public long[] getMaxSortIds() {
return null;
}
@Override
public boolean isLoadingMore() {
return false;
}
}

View File

@ -88,4 +88,17 @@ public class Tab {
public void setExtras(TabExtras extras) {
this.extras = extras;
}
@Override
public String toString() {
return "Tab{" +
"id=" + id +
", name='" + name + '\'' +
", icon='" + icon + '\'' +
", type='" + type + '\'' +
", position=" + position +
", arguments=" + arguments +
", extras=" + extras +
'}';
}
}

View File

@ -70,6 +70,8 @@ public class ParcelableActivityUtils {
result.account_key = accountKey;
result.timestamp = activity.getCreatedAt().getTime();
result.action = activity.getAction();
result.max_sort_position = activity.getMaxSortPosition();
result.min_sort_position = activity.getMinSortPosition();
result.max_position = activity.getMaxPosition();
result.min_position = activity.getMinPosition();
result.sources = ParcelableUserUtils.fromUsers(activity.getSources(), accountKey);

View File

@ -4,7 +4,6 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.mariotaku.twidere.api.statusnet.model.Attention;
import org.mariotaku.twidere.api.twitter.model.Place;
import org.mariotaku.twidere.api.twitter.model.Status;
@ -40,26 +39,18 @@ public class ParcelableStatusUtils {
result.is_gap = isGap;
result.account_key = accountKey;
result.id = orig.getId();
result.sort_id = orig.getSortId();
result.timestamp = getTime(orig.getCreatedAt());
result.sort_id = orig.getRawId();
if (result.sort_id == -1) {
// Try use long id
result.sort_id = NumberUtils.toLong(result.id, -1);
}
if (result.sort_id == -1) {
// Try use timestamp
result.sort_id = result.timestamp;
}
result.extras = new ParcelableStatus.Extras();
result.extras.external_url = orig.getExternalUrl();
result.extras.support_entities = orig.getEntities() != null;
final Status retweetedStatus = orig.getRetweetedStatus();
final User retweetUser = retweetedStatus != null ? orig.getUser() : null;
result.is_retweet = orig.isRetweet();
result.retweeted = orig.wasRetweeted();
if (retweetedStatus != null) {
final User retweetUser = orig.getUser();
result.retweet_id = retweetedStatus.getId();
result.retweet_timestamp = getTime(retweetedStatus.getCreatedAt());
result.retweeted_by_user_id = UserKeyUtils.fromUser(retweetUser);
@ -123,6 +114,9 @@ public class ParcelableStatusUtils {
result.user_is_verified = user.isVerified();
result.user_is_following = user.isFollowing();
result.extras.user_profile_image_url_profile_size = user.getProfileImageUrlProfileSize();
if (result.extras.user_profile_image_url_profile_size == null) {
result.extras.user_profile_image_url_profile_size = user.getProfileImageUrlLarge();
}
result.text_html = InternalTwitterContentUtils.formatStatusText(status);
result.media = ParcelableMediaUtils.fromStatus(status);
result.text_plain = InternalTwitterContentUtils.unescapeTwitterStatusText(status.getText());
@ -145,8 +139,10 @@ public class ParcelableStatusUtils {
return result;
}
@Nullable
private static UserKey getInReplyToUserId(Status status, UserKey accountKey) {
final String inReplyToUserId = status.getInReplyToUserId();
if (inReplyToUserId == null) return null;
final UserMentionEntity[] entities = status.getUserMentionEntities();
if (entities != null) {
for (final UserMentionEntity entity : entities) {

View File

@ -67,6 +67,9 @@ public class ParcelableUserUtils implements TwidereConstants {
extras.statusnet_profile_url = user.getStatusnetProfileUrl();
extras.profile_image_url_original = user.getProfileImageUrlOriginal();
extras.profile_image_url_profile_size = user.getProfileImageUrlProfileSize();
if (extras.profile_image_url_profile_size == null) {
extras.profile_image_url_profile_size = user.getProfileImageUrlLarge();
}
extras.groups_count = user.getGroupsCount();
obj.extras = extras;
return obj;

View File

@ -56,9 +56,30 @@ public class UserKeyUtils {
}
public static String getUserHost(User user) {
if (isFanfouUser(user)) return TwidereConstants.USER_TYPE_FANFOU_COM;
return getUserHost(user.getOstatusUri(), TwidereConstants.USER_TYPE_TWITTER_COM);
}
public static boolean isFanfouUser(User user) {
String url = user.getProfileImageUrlLarge();
if (url != null && isFanfouHost(getUserHost(url, "twitter.com"))) {
return true;
}
url = user.getProfileImageUrl();
if (url != null && isFanfouHost(getUserHost(url, "twitter.com"))) {
return true;
}
url = user.getProfileBackgroundImageUrl();
if (url != null && isFanfouHost(getUserHost(url, "twitter.com"))) {
return true;
}
return false;
}
private static boolean isFanfouHost(@NonNull String host) {
return TextUtils.equals("fanfou.com", host) || host.endsWith(".fanfou.com");
}
@NonNull
public static String getUserHost(@Nullable String uri, @Nullable String def) {
if (def == null) {

View File

@ -95,7 +95,7 @@ public class RefreshService extends Service implements Constants {
@NonNull
@Override
public UserKey[] getAccountKeys() {
public UserKey[] getAccountKeysWorker() {
if (accountIds != null) return accountIds;
final AccountPreferences[] prefs = AccountPreferences.getAccountPreferences(context,
DataStoreUtils.getAccountKeys(context));
@ -116,7 +116,7 @@ public class RefreshService extends Service implements Constants {
@NonNull
@Override
public UserKey[] getAccountKeys() {
public UserKey[] getAccountKeysWorker() {
if (accountIds != null) return accountIds;
final AccountPreferences[] prefs = AccountPreferences.getAccountPreferences(context,
DataStoreUtils.getAccountKeys(context));
@ -137,7 +137,7 @@ public class RefreshService extends Service implements Constants {
@NonNull
@Override
public UserKey[] getAccountKeys() {
public UserKey[] getAccountKeysWorker() {
if (accountIds != null) return accountIds;
final AccountPreferences[] prefs = AccountPreferences.getAccountPreferences(context,
DataStoreUtils.getAccountKeys(context));

View File

@ -91,7 +91,6 @@ public abstract class GetActivitiesTask extends AbstractTask<RefreshTaskParam, O
try {
final ResponseList<Activity> activities = getActivities(twitter, accountKey, paging);
storeActivities(cr, loadItemLimit, accountKey, noItemsBefore, activities);
// if (saveReadPosition && TwitterAPIFactory.isOfficialTwitterInstance(context, twitter)) {
if (saveReadPosition) {
saveReadPosition(accountKey, twitter);
}
@ -124,14 +123,14 @@ public abstract class GetActivitiesTask extends AbstractTask<RefreshTaskParam, O
final ParcelableActivity parcelableActivity = ParcelableActivityUtils.fromActivity(activity,
accountKey, false);
if (deleteBound[0] < 0) {
deleteBound[0] = parcelableActivity.min_position;
deleteBound[0] = parcelableActivity.min_sort_position;
} else {
deleteBound[0] = Math.min(deleteBound[0], parcelableActivity.min_position);
deleteBound[0] = Math.min(deleteBound[0], parcelableActivity.min_sort_position);
}
if (deleteBound[1] < 0) {
deleteBound[1] = parcelableActivity.max_position;
deleteBound[1] = parcelableActivity.max_sort_position;
} else {
deleteBound[1] = Math.max(deleteBound[1], parcelableActivity.max_position);
deleteBound[1] = Math.max(deleteBound[1], parcelableActivity.max_sort_position);
}
final ContentValues values = ContentValuesCreator.createActivity(parcelableActivity);
values.put(Statuses.INSERTED_DATE, System.currentTimeMillis());
@ -140,8 +139,8 @@ public abstract class GetActivitiesTask extends AbstractTask<RefreshTaskParam, O
if (deleteBound[0] > 0 && deleteBound[1] > 0) {
final Expression where = Expression.and(
Expression.equalsArgs(Activities.ACCOUNT_KEY),
Expression.greaterEqualsArgs(Activities.MIN_POSITION),
Expression.lesserEqualsArgs(Activities.MAX_POSITION)
Expression.greaterEqualsArgs(Activities.MIN_SORT_POSITION),
Expression.lesserEqualsArgs(Activities.MAX_SORT_POSITION)
);
final String[] whereArgs = {accountKey.toString(), String.valueOf(deleteBound[0]),
String.valueOf(deleteBound[1])};

View File

@ -390,7 +390,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
@NonNull
@Override
public UserKey[] getAccountKeys() {
public UserKey[] getAccountKeysWorker() {
return closure.getAccountKeys();
}
@ -404,7 +404,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
getActivitiesAboutMeAsync(new SimpleRefreshTaskParam() {
@NonNull
@Override
public UserKey[] getAccountKeys() {
public UserKey[] getAccountKeysWorker() {
return closure.getAccountKeys();
}
@ -418,14 +418,14 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
getReceivedDirectMessagesAsync(new SimpleRefreshTaskParam() {
@NonNull
@Override
public UserKey[] getAccountKeys() {
public UserKey[] getAccountKeysWorker() {
return closure.getAccountKeys();
}
});
getSentDirectMessagesAsync(new SimpleRefreshTaskParam() {
@NonNull
@Override
public UserKey[] getAccountKeys() {
public UserKey[] getAccountKeysWorker() {
return closure.getAccountKeys();
}
});

View File

@ -83,7 +83,6 @@ import org.mariotaku.twidere.provider.TwidereDataStore.UnreadCounts;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@ -203,45 +202,76 @@ public class DataStoreUtils implements Constants {
@NonNull
public static String[] getNewestMessageIds(@NonNull final Context context, @NonNull final Uri uri,
@NonNull final UserKey[] accountKeys) {
return getLongFieldArray(context, uri, accountKeys, DirectMessages.ACCOUNT_KEY,
return getStringFieldArray(context, uri, accountKeys, DirectMessages.ACCOUNT_KEY,
DirectMessages.MESSAGE_ID, new OrderBy(SQLFunctions.MAX(DirectMessages.MESSAGE_TIMESTAMP)));
}
@NonNull
public static String[] getNewestStatusIds(@NonNull final Context context, @NonNull final Uri uri,
@NonNull final UserKey[] accountKeys) {
return getLongFieldArray(context, uri, accountKeys, Statuses.ACCOUNT_KEY,
return getStringFieldArray(context, uri, accountKeys, Statuses.ACCOUNT_KEY,
Statuses.STATUS_ID, new OrderBy(SQLFunctions.MAX(Statuses.STATUS_TIMESTAMP)));
}
@NonNull
public static long[] getNewestStatusSortIds(@NonNull final Context context, @NonNull final Uri uri,
@NonNull final UserKey[] accountKeys) {
return getLongFieldArray(context, uri, accountKeys, Statuses.ACCOUNT_KEY,
Statuses.SORT_ID, new OrderBy(SQLFunctions.MAX(Statuses.STATUS_TIMESTAMP)));
}
@NonNull
public static String[] getOldestMessageIds(@NonNull final Context context, @NonNull final Uri uri,
@NonNull final UserKey[] accountKeys) {
return getLongFieldArray(context, uri, accountKeys, DirectMessages.ACCOUNT_KEY,
return getStringFieldArray(context, uri, accountKeys, DirectMessages.ACCOUNT_KEY,
DirectMessages.MESSAGE_ID, new OrderBy(SQLFunctions.MIN(DirectMessages.MESSAGE_TIMESTAMP)));
}
@NonNull
public static String[] getOldestStatusIds(@NonNull final Context context, @NonNull final Uri uri,
@NonNull final UserKey[] accountKeys) {
return getLongFieldArray(context, uri, accountKeys, Statuses.ACCOUNT_KEY,
return getStringFieldArray(context, uri, accountKeys, Statuses.ACCOUNT_KEY,
Statuses.STATUS_ID, new OrderBy(SQLFunctions.MIN(Statuses.STATUS_TIMESTAMP)));
}
@NonNull
public static long[] getOldestStatusSortIds(@NonNull final Context context, @NonNull final Uri uri,
@NonNull final UserKey[] accountKeys) {
return getLongFieldArray(context, uri, accountKeys, Statuses.ACCOUNT_KEY,
Statuses.SORT_ID, new OrderBy(SQLFunctions.MIN(Statuses.STATUS_TIMESTAMP)));
}
@NonNull
public static String[] getNewestActivityMaxPositions(final Context context, final Uri uri,
final UserKey[] accountKeys) {
return getLongFieldArray(context, uri, accountKeys, Activities.ACCOUNT_KEY,
Activities.MAX_POSITION, new OrderBy(SQLFunctions.MAX(Activities.TIMESTAMP)));
return getStringFieldArray(context, uri, accountKeys, Activities.ACCOUNT_KEY,
Activities.MAX_REQUEST_POSITION, new OrderBy(SQLFunctions.MAX(Activities.TIMESTAMP)));
}
@NonNull
public static String[] getOldestActivityMaxPositions(@NonNull final Context context,
@NonNull final Uri uri,
@NonNull final UserKey[] accountKeys) {
return getStringFieldArray(context, uri, accountKeys, Activities.ACCOUNT_KEY,
Activities.MAX_REQUEST_POSITION, new OrderBy(SQLFunctions.MIN(Activities.TIMESTAMP)));
}
@NonNull
public static long[] getNewestActivityMaxSortPositions(final Context context, final Uri uri,
final UserKey[] accountKeys) {
return getLongFieldArray(context, uri, accountKeys, Activities.ACCOUNT_KEY,
Activities.MAX_POSITION, new OrderBy(SQLFunctions.MIN(Activities.TIMESTAMP)));
Activities.MAX_SORT_POSITION, new OrderBy(SQLFunctions.MAX(Activities.TIMESTAMP)));
}
@NonNull
public static long[] getOldestActivityMaxSortPositions(@NonNull final Context context,
@NonNull final Uri uri,
@NonNull final UserKey[] accountKeys) {
return getLongFieldArray(context, uri, accountKeys, Activities.ACCOUNT_KEY,
Activities.MAX_SORT_POSITION, new OrderBy(SQLFunctions.MIN(Activities.TIMESTAMP)));
}
public static int getStatusCount(final Context context, final Uri uri, final UserKey accountId) {
@ -829,12 +859,46 @@ public class DataStoreUtils implements Constants {
}
@NonNull
static String[] getLongFieldArray(@NonNull Context context, @NonNull Uri uri,
@NonNull UserKey[] keys, @NonNull String keyField,
@NonNull String valueField, @Nullable OrderBy sortExpression) {
static String[] getStringFieldArray(@NonNull Context context, @NonNull Uri uri,
@NonNull UserKey[] keys, @NonNull String keyField,
@NonNull String valueField, @Nullable OrderBy sortExpression) {
return getFieldArray(context, uri, keys, keyField, valueField, sortExpression, new FieldArrayCreator<String[]>() {
@Override
public String[] newArray(int size) {
return new String[size];
}
@Override
public void assign(String[] array, int arrayIdx, Cursor cur, int colIdx) {
array[arrayIdx] = cur.getString(colIdx);
}
});
}
@NonNull
static long[] getLongFieldArray(@NonNull Context context, @NonNull Uri uri,
@NonNull UserKey[] keys, @NonNull String keyField,
@NonNull String valueField, @Nullable OrderBy sortExpression) {
return getFieldArray(context, uri, keys, keyField, valueField, sortExpression, new FieldArrayCreator<long[]>() {
@Override
public long[] newArray(int size) {
return new long[size];
}
@Override
public void assign(long[] array, int arrayIdx, Cursor cur, int colIdx) {
array[arrayIdx] = cur.getLong(colIdx);
}
});
}
@NonNull
static <T> T getFieldArray(@NonNull Context context, @NonNull Uri uri,
@NonNull UserKey[] keys, @NonNull String keyField,
@NonNull String valueField, @Nullable OrderBy sortExpression,
@NonNull FieldArrayCreator<T> creator) {
final ContentResolver resolver = context.getContentResolver();
final String[] messageIds = new String[keys.length];
Arrays.fill(messageIds, -1);
final T messageIds = creator.newArray(keys.length);
final String[] selectionArgs = TwidereArrayUtils.toStringArray(keys);
final SQLSelectQuery.Builder builder = SQLQueryBuilder.select(new Columns(keyField, valueField))
.from(new Table(getTableNameByUri(uri)))
@ -851,7 +915,7 @@ public class DataStoreUtils implements Constants {
final UserKey accountKey = UserKey.valueOf(cur.getString(0));
int idx = ArrayUtils.indexOf(keys, accountKey);
if (idx < 0) continue;
messageIds[idx] = cur.getString(1);
creator.assign(messageIds, idx, cur, 1);
}
return messageIds;
} finally {
@ -859,6 +923,12 @@ public class DataStoreUtils implements Constants {
}
}
interface FieldArrayCreator<T> {
T newArray(int size);
void assign(T array, int arrayIdx, Cursor cur, int colIdx);
}
static int queryCount(@NonNull final Context context, @NonNull final Uri uri,
@Nullable final String selection, @Nullable final String[] selectionArgs) {
final ContentResolver resolver = context.getContentResolver();
@ -1014,18 +1084,4 @@ public class DataStoreUtils implements Constants {
position, followingOnly, accountIds);
}
public static void initAccountColor(final Context context) {
if (context == null) return;
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, new String[]{
Accounts.ACCOUNT_KEY, Accounts.COLOR}, null, null, null);
if (cur == null) return;
final int id_idx = cur.getColumnIndex(Accounts.ACCOUNT_KEY), color_idx = cur.getColumnIndex(Accounts.COLOR);
cur.moveToFirst();
while (!cur.isAfterLast()) {
// sAccountColors.put(cur.getLong(id_idx), cur.getInt(color_idx));
// TODO
cur.moveToNext();
}
cur.close();
}
}

View File

@ -33,10 +33,10 @@ import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.util.imageloader.OvalBitmapDisplayer;
import org.mariotaku.twidere.util.media.MediaExtra;
@ -141,6 +141,8 @@ public class MediaLoaderWrapper implements Constants {
public void displayOriginalProfileImage(final ImageView view, final ParcelableUser user) {
if (user.extras != null && !TextUtils.isEmpty(user.extras.profile_image_url_original)) {
displayProfileImage(view, user.extras.profile_image_url_original);
} else if (user.extras != null && !TextUtils.isEmpty(user.extras.profile_image_url_profile_size)) {
displayProfileImage(view, user.extras.profile_image_url_profile_size);
} else {
displayProfileImage(view, Utils.getOriginalTwitterProfileImage(user.profile_image_url));
}

View File

@ -138,7 +138,7 @@ public class TwitterWrapper implements Constants {
if (TextUtils.equals(user.getId(), id)) return user;
}
} else {
final ResponseList<Status> timeline = twitter.getUserTimeline(screenName, paging);
final ResponseList<Status> timeline = twitter.getUserTimelineByScreenName(screenName, paging);
for (final Status status : timeline) {
final User user = status.getUser();
if (searchScreenName.equalsIgnoreCase(user.getScreenName()))

View File

@ -22,6 +22,7 @@ package org.mariotaku.twidere.view.holder;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Typeface;
import android.support.annotation.UiThread;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.view.View;
import android.view.View.OnClickListener;
@ -32,7 +33,6 @@ import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.MessageEntriesAdapter;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.ConversationEntries;
import org.mariotaku.twidere.util.DataStoreUtils;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.UserColorNameManager;
import org.mariotaku.twidere.view.NameView;
@ -64,6 +64,7 @@ public class MessageEntryViewHolder extends ViewHolder implements OnClickListene
profileImageView.setOnClickListener(this);
}
@UiThread
public void displayMessage(Cursor cursor, boolean isUnread) {
final Context context = adapter.getContext();
final MediaLoaderWrapper loader = adapter.getMediaLoader();
@ -90,7 +91,7 @@ public class MessageEntryViewHolder extends ViewHolder implements OnClickListene
nameView.setTypeface(null, isUnread && !isOutgoing ? Typeface.BOLD : Typeface.NORMAL);
textView.setTypeface(null, isUnread && !isOutgoing ? Typeface.BOLD : Typeface.NORMAL);
if (adapter.shouldShowAccountsColor()) {
content.drawEnd(DataStoreUtils.getAccountColor(context, accountKey));
// FIXME draw account color
} else {
content.drawEnd();
}