implemented follow request

This commit is contained in:
Mariotaku Lee 2016-02-15 14:53:27 +08:00
parent 3998cb8e64
commit 1969016700
56 changed files with 612 additions and 468 deletions

View File

@ -19,21 +19,26 @@
package org.mariotaku.twidere.api.twitter.api;
import org.mariotaku.restfu.annotation.method.POST;
import org.mariotaku.restfu.annotation.param.KeyValue;
import org.mariotaku.restfu.annotation.param.Param;
import org.mariotaku.restfu.annotation.param.Queries;
import org.mariotaku.twidere.api.twitter.TwitterException;
import org.mariotaku.twidere.api.twitter.model.User;
@SuppressWarnings("RedundantThrows")
@Queries({@KeyValue(key = "include_entities", valueKey = "include_entities")})
public interface PrivateFriendsFollowersResources extends PrivateResources {
User acceptFriendship(long userId) throws TwitterException;
@POST("/friendships/accept.json")
User acceptFriendship(@Param("user_id") long userId) throws TwitterException;
User acceptFriendship(String screenName) throws TwitterException;
@POST("/friendships/accept.json")
User acceptFriendship(@Param("screen_name") String screenName) throws TwitterException;
User denyFriendship(long userId) throws TwitterException;
@POST("/friendships/deny.json")
User denyFriendship(@Param("user_id") long userId) throws TwitterException;
User denyFriendship(String screenName) throws TwitterException;
@POST("/friendships/deny.json")
User denyFriendship(@Param("screen_name") String screenName) throws TwitterException;
}

View File

@ -75,8 +75,6 @@ public interface IntentConstants {
String BROADCAST_NOTIFICATION_DELETED = INTENT_PACKAGE_PREFIX + "NOTIFICATION_DELETED";
String BROADCAST_USER_LIST_DETAILS_UPDATED = INTENT_PACKAGE_PREFIX
+ "USER_LIST_DETAILS_UPDATED";
String BROADCAST_FRIENDSHIP_ACCEPTED = INTENT_PACKAGE_PREFIX + "FRIENDSHIP_ACCEPTED";
String BROADCAST_FRIENDSHIP_DENIED = INTENT_PACKAGE_PREFIX + "FRIENDSHIP_DENIED";
String BROADCAST_USER_LIST_MEMBERS_DELETED = INTENT_PACKAGE_PREFIX + "USER_LIST_MEMBER_DELETED";
String BROADCAST_USER_LIST_MEMBERS_ADDED = INTENT_PACKAGE_PREFIX + "USER_LIST_MEMBER_ADDED";

View File

@ -170,6 +170,17 @@ public class ParcelableUser implements Parcelable, Comparable<ParcelableUser> {
@ParcelableThisPlease
@JsonField(name = "is_basic")
public boolean is_basic;
public static final Creator<ParcelableUser> CREATOR = new Creator<ParcelableUser>() {
public ParcelableUser createFromParcel(Parcel source) {
ParcelableUser target = new ParcelableUser();
ParcelableUserParcelablePlease.readFromParcel(target, source);
return target;
}
public ParcelableUser[] newArray(int size) {
return new ParcelableUser[size];
}
};
public ParcelableUser() {
}
@ -208,13 +219,6 @@ public class ParcelableUser implements Parcelable, Comparable<ParcelableUser> {
is_basic = true;
}
@AfterCursorObjectCreated
void afterCursorObjectCreated() {
is_cache = true;
description_unescaped = HtmlEscapeHelper.toPlainText(description_html);
is_basic = description_plain == null || url == null || location == null;
}
public ParcelableUser(final User user, final long account_id) {
this(user, account_id, 0);
}
@ -253,12 +257,12 @@ public class ParcelableUser implements Parcelable, Comparable<ParcelableUser> {
is_basic = false;
}
@Override
public int compareTo(@NonNull final ParcelableUser that) {
final long diff = position - that.position;
if (diff > Integer.MAX_VALUE) return Integer.MAX_VALUE;
if (diff < Integer.MIN_VALUE) return Integer.MIN_VALUE;
return (int) diff;
public static int calculateHashCode(long accountId, long userId) {
final int prime = 31;
int result = 1;
result = prime * result + (int) (accountId ^ accountId >>> 32);
result = prime * result + (int) (userId ^ userId >>> 32);
return result;
}
public static ParcelableUser[] fromUsersArray(@Nullable final User[] users, long account_id) {
@ -270,40 +274,6 @@ public class ParcelableUser implements Parcelable, Comparable<ParcelableUser> {
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (!(obj instanceof ParcelableUser)) return false;
final ParcelableUser other = (ParcelableUser) obj;
if (account_id != other.account_id) return false;
if (id != other.id) return false;
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (account_id ^ account_id >>> 32);
result = prime * result + (int) (id ^ id >>> 32);
return result;
}
@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 + "}";
}
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);
@ -323,6 +293,50 @@ public class ParcelableUser implements Parcelable, Comparable<ParcelableUser> {
return result;
}
@AfterCursorObjectCreated
void afterCursorObjectCreated() {
is_cache = true;
description_unescaped = HtmlEscapeHelper.toPlainText(description_html);
is_basic = description_plain == null || url == null || location == null;
}
@Override
public int compareTo(@NonNull final ParcelableUser that) {
final long diff = position - that.position;
if (diff > Integer.MAX_VALUE) return Integer.MAX_VALUE;
if (diff < Integer.MIN_VALUE) return Integer.MIN_VALUE;
return (int) diff;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (!(obj instanceof ParcelableUser)) return false;
final ParcelableUser other = (ParcelableUser) obj;
if (account_id != other.account_id) return false;
if (id != other.id) return false;
return true;
}
@Override
public int hashCode() {
return calculateHashCode(account_id, id);
}
@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 + "}";
}
@Override
public int describeContents() {
@ -333,16 +347,4 @@ public class ParcelableUser implements Parcelable, Comparable<ParcelableUser> {
public void writeToParcel(Parcel dest, int flags) {
ParcelableUserParcelablePlease.writeToParcel(this, dest, flags);
}
public static final Creator<ParcelableUser> CREATOR = new Creator<ParcelableUser>() {
public ParcelableUser createFromParcel(Parcel source) {
ParcelableUser target = new ParcelableUser();
ParcelableUserParcelablePlease.readFromParcel(target, source);
return target;
}
public ParcelableUser[] newArray(int size) {
return new ParcelableUser[size];
}
};
}

View File

@ -98,8 +98,8 @@ import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.TwidereColorUtils;
import org.mariotaku.twidere.util.TwidereMathUtils;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.message.TaskStateChangedEvent;
import org.mariotaku.twidere.util.message.UnreadCountUpdatedEvent;
import org.mariotaku.twidere.model.message.TaskStateChangedEvent;
import org.mariotaku.twidere.model.message.UnreadCountUpdatedEvent;
import org.mariotaku.twidere.util.support.ActivitySupport;
import org.mariotaku.twidere.util.support.ActivitySupport.TaskDescriptionCompat;
import org.mariotaku.twidere.util.support.ViewSupport;

View File

@ -54,7 +54,7 @@ import org.mariotaku.twidere.model.SingleResponse;
import org.mariotaku.twidere.util.AsyncTaskUtils;
import org.mariotaku.twidere.util.ParseUtils;
import org.mariotaku.twidere.util.TwitterAPIFactory;
import org.mariotaku.twidere.util.message.UserListCreatedEvent;
import org.mariotaku.twidere.model.message.UserListCreatedEvent;
import java.util.ArrayList;
import java.util.List;

View File

@ -46,9 +46,10 @@ public abstract class AbsParcelableStatusesAdapter extends AbsStatusesAdapter<Li
}
@Override
public ParcelableStatus getStatus(int position) {
if (position == getStatusCount()) return null;
return mData.get(position);
public ParcelableStatus getStatus(int adapterPosition) {
int dataPosition = adapterPosition - getStatusStartIndex();
if (dataPosition < 0 || dataPosition >= getStatusCount()) return null;
return mData.get(dataPosition);
}
@Override

View File

@ -45,6 +45,8 @@ public abstract class AbsUsersAdapter<D> extends LoadMoreSupportAdapter<ViewHold
private final int mTextSize;
private final boolean mDisplayProfileImage;
private final boolean mShowAbsoluteTime;
private UserAdapterListener mUserAdapterListener;
private RequestClickListener mRequestClickListener;
public AbsUsersAdapter(final Context context) {
super(context);
@ -74,7 +76,7 @@ public abstract class AbsUsersAdapter<D> extends LoadMoreSupportAdapter<ViewHold
public abstract D getData();
public boolean isUser(int position) {
return position < getUsersCount();
return position < getUserCount();
}
@Override
@ -118,37 +120,30 @@ public abstract class AbsUsersAdapter<D> extends LoadMoreSupportAdapter<ViewHold
if ((getLoadMoreIndicatorPosition() & IndicatorPosition.START) != 0 && position == 0) {
return ITEM_VIEW_TYPE_LOAD_INDICATOR;
}
if (position == getUsersCount()) {
if (position == getUserCount()) {
return ITEM_VIEW_TYPE_LOAD_INDICATOR;
}
return ITEM_VIEW_TYPE_USER;
}
@Override
public void onItemActionClick(ViewHolder holder, int id, int position) {
public UserAdapterListener getUserAdapterListener() {
return mUserAdapterListener;
}
@Override
public void onItemMenuClick(ViewHolder holder, View menuView, int position) {
}
@Override
public void onUserClick(UserViewHolder holder, int position) {
if (mUserAdapterListener == null) return;
mUserAdapterListener.onUserClick(holder, position);
}
@Override
public boolean onUserLongClick(UserViewHolder holder, int position) {
return mUserAdapterListener != null && mUserAdapterListener.onUserLongClick(holder, position);
}
public void setListener(UserAdapterListener userAdapterListener) {
public void setUserAdapterListener(UserAdapterListener userAdapterListener) {
mUserAdapterListener = userAdapterListener;
}
@Override
public RequestClickListener getRequestClickListener() {
return mRequestClickListener;
}
public void setRequestClickListener(RequestClickListener requestClickListener) {
mRequestClickListener = requestClickListener;
}
@Override
public boolean shouldShowAccountsColor() {
return false;
@ -156,14 +151,4 @@ public abstract class AbsUsersAdapter<D> extends LoadMoreSupportAdapter<ViewHold
protected abstract void bindUser(UserViewHolder holder, int position);
private UserAdapterListener mUserAdapterListener;
public interface UserAdapterListener {
void onUserClick(UserViewHolder holder, int position);
boolean onUserLongClick(UserViewHolder holder, int position);
}
}

View File

@ -91,13 +91,10 @@ public class ParcelableActivitiesAdapter extends AbsActivitiesAdapter<List<Parce
}
@Override
public ParcelableActivity getActivity(int position) {
int offset = 0;
if ((getLoadMoreIndicatorPosition() & IndicatorPosition.START) != 0) {
offset = -1;
}
if (position == getActivityCount()) return null;
return mData.get(position + offset);
public ParcelableActivity getActivity(int adapterPosition) {
int dataPosition = adapterPosition - getActivityStartIndex();
if (dataPosition < 0 || dataPosition >= getActivityCount()) return null;
return mData.get(dataPosition);
}
@Override

View File

@ -20,6 +20,7 @@
package org.mariotaku.twidere.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.view.holder.UserViewHolder;
@ -55,7 +56,7 @@ public class ParcelableUsersAdapter extends AbsUsersAdapter<List<ParcelableUser>
@Override
public int getItemCount() {
final int position = getLoadMoreIndicatorPosition();
int count = getUsersCount();
int count = getUserCount();
if ((position & IndicatorPosition.START) != 0) {
count++;
}
@ -66,20 +67,49 @@ public class ParcelableUsersAdapter extends AbsUsersAdapter<List<ParcelableUser>
}
@Override
public ParcelableUser getUser(int position) {
if (position == getUsersCount()) return null;
return mData.get(position);
public ParcelableUser getUser(int adapterPosition) {
int dataPosition = adapterPosition - getUserStartIndex();
if (dataPosition < 0 || dataPosition >= getUserCount()) return null;
return mData.get(dataPosition);
}
public int getUserStartIndex() {
final int position = getLoadMoreIndicatorPosition();
int start = 0;
if ((position & IndicatorPosition.START) != 0) {
start += 1;
}
return start;
}
@Override
public long getUserId(int position) {
if (position == getUsersCount()) return -1;
if (position == getUserCount()) return -1;
return mData.get(position).id;
}
@Override
public int getUsersCount() {
public int getUserCount() {
if (mData == null) return 0;
return mData.size();
}
public boolean removeUserAt(int adapterPosition) {
int dataPosition = adapterPosition - getUserStartIndex();
if (dataPosition < 0 || dataPosition >= getUserCount()) return false;
mData.remove(dataPosition);
notifyItemRemoved(adapterPosition);
return true;
}
public int findPosition(long accountId, long userId) {
if (mData == null) return RecyclerView.NO_POSITION;
for (int i = getUserStartIndex(), j = i + getUserCount(); i < j; i++) {
final ParcelableUser user = mData.get(i);
if (user.account_id == accountId && user.id == userId) {
return i;
}
}
return RecyclerView.NO_POSITION;
}
}

View File

@ -23,25 +23,43 @@ import android.support.annotation.NonNull;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.view.holder.UserViewHolder.UserClickListener;
import org.mariotaku.twidere.view.holder.UserViewHolder;
/**
* Created by mariotaku on 15/4/16.
*/
public interface IUsersAdapter<Data> extends IContentCardAdapter, UserClickListener {
public interface IUsersAdapter<Data> extends IContentCardAdapter {
ParcelableUser getUser(int position);
long getUserId(int position);
int getUsersCount();
int getUserCount();
void setData(Data data);
UserAdapterListener getUserAdapterListener();
RequestClickListener getRequestClickListener();
boolean shouldShowAccountsColor();
@NonNull
@Override
MediaLoaderWrapper getMediaLoader();
interface UserAdapterListener {
void onUserClick(UserViewHolder holder, int position);
boolean onUserLongClick(UserViewHolder holder, int position);
}
interface RequestClickListener {
void onAcceptClicked(UserViewHolder holder, int position);
void onDenyClicked(UserViewHolder holder, int position);
}
}

View File

@ -57,7 +57,7 @@ import org.mariotaku.twidere.util.RecyclerViewNavigationHelper;
import org.mariotaku.twidere.util.RecyclerViewUtils;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.imageloader.PauseRecyclerViewOnScrollListener;
import org.mariotaku.twidere.util.message.StatusListChangedEvent;
import org.mariotaku.twidere.model.message.StatusListChangedEvent;
import org.mariotaku.twidere.view.holder.ActivityTitleSummaryViewHolder;
import org.mariotaku.twidere.view.holder.GapViewHolder;
import org.mariotaku.twidere.view.holder.iface.IStatusViewHolder;

View File

@ -60,7 +60,7 @@ import org.mariotaku.twidere.util.RecyclerViewNavigationHelper;
import org.mariotaku.twidere.util.RecyclerViewUtils;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.imageloader.PauseRecyclerViewOnScrollListener;
import org.mariotaku.twidere.util.message.StatusListChangedEvent;
import org.mariotaku.twidere.model.message.StatusListChangedEvent;
import org.mariotaku.twidere.view.holder.GapViewHolder;
import org.mariotaku.twidere.view.holder.iface.IStatusViewHolder;

View File

@ -31,7 +31,7 @@ import android.support.v7.widget.RecyclerView;
import android.view.KeyEvent;
import org.mariotaku.twidere.adapter.AbsUsersAdapter;
import org.mariotaku.twidere.adapter.AbsUsersAdapter.UserAdapterListener;
import org.mariotaku.twidere.adapter.iface.IUsersAdapter.UserAdapterListener;
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter.IndicatorPosition;
import org.mariotaku.twidere.loader.iface.IExtendedLoader;
import org.mariotaku.twidere.model.ParcelableUser;
@ -71,7 +71,7 @@ abstract class AbsUsersFragment<Data> extends AbsContentListRecyclerViewFragment
final AbsUsersAdapter<Data> adapter = getAdapter();
final RecyclerView recyclerView = getRecyclerView();
final LinearLayoutManager layoutManager = getLayoutManager();
adapter.setListener(this);
adapter.setUserAdapterListener(this);
mNavigationHelper = new RecyclerViewNavigationHelper(recyclerView, layoutManager, adapter,
this);
@ -131,7 +131,7 @@ abstract class AbsUsersFragment<Data> extends AbsContentListRecyclerViewFragment
@Override
protected void setupRecyclerView(Context context, boolean compact) {
super.setupRecyclerView(context, true);
}
}

View File

@ -52,13 +52,13 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Activities;
import org.mariotaku.twidere.provider.TwidereDataStore.Filters;
import org.mariotaku.twidere.util.DataStoreUtils;
import org.mariotaku.twidere.util.ErrorInfoStore;
import org.mariotaku.twidere.util.message.AccountChangedEvent;
import org.mariotaku.twidere.util.message.FavoriteCreatedEvent;
import org.mariotaku.twidere.util.message.FavoriteDestroyedEvent;
import org.mariotaku.twidere.util.message.GetActivitiesTaskEvent;
import org.mariotaku.twidere.util.message.StatusDestroyedEvent;
import org.mariotaku.twidere.util.message.StatusListChangedEvent;
import org.mariotaku.twidere.util.message.StatusRetweetedEvent;
import org.mariotaku.twidere.model.message.AccountChangedEvent;
import org.mariotaku.twidere.model.message.FavoriteCreatedEvent;
import org.mariotaku.twidere.model.message.FavoriteDestroyedEvent;
import org.mariotaku.twidere.model.message.GetActivitiesTaskEvent;
import org.mariotaku.twidere.model.message.StatusDestroyedEvent;
import org.mariotaku.twidere.model.message.StatusListChangedEvent;
import org.mariotaku.twidere.model.message.StatusRetweetedEvent;
import java.util.List;

View File

@ -49,13 +49,13 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Filters;
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
import org.mariotaku.twidere.util.DataStoreUtils;
import org.mariotaku.twidere.util.ErrorInfoStore;
import org.mariotaku.twidere.util.message.AccountChangedEvent;
import org.mariotaku.twidere.util.message.FavoriteCreatedEvent;
import org.mariotaku.twidere.util.message.FavoriteDestroyedEvent;
import org.mariotaku.twidere.util.message.GetStatusesTaskEvent;
import org.mariotaku.twidere.util.message.StatusDestroyedEvent;
import org.mariotaku.twidere.util.message.StatusListChangedEvent;
import org.mariotaku.twidere.util.message.StatusRetweetedEvent;
import org.mariotaku.twidere.model.message.AccountChangedEvent;
import org.mariotaku.twidere.model.message.FavoriteCreatedEvent;
import org.mariotaku.twidere.model.message.FavoriteDestroyedEvent;
import org.mariotaku.twidere.model.message.GetStatusesTaskEvent;
import org.mariotaku.twidere.model.message.StatusDestroyedEvent;
import org.mariotaku.twidere.model.message.StatusListChangedEvent;
import org.mariotaku.twidere.model.message.StatusRetweetedEvent;
import java.util.List;

View File

@ -65,7 +65,7 @@ import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallb
import org.mariotaku.twidere.util.RecyclerViewNavigationHelper;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.content.SupportFragmentReloadCursorObserver;
import org.mariotaku.twidere.util.message.GetMessagesTaskEvent;
import org.mariotaku.twidere.model.message.GetMessagesTaskEvent;
import java.util.Collections;
import java.util.HashSet;

View File

@ -23,10 +23,31 @@ import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import com.squareup.otto.Subscribe;
import org.mariotaku.twidere.adapter.AbsUsersAdapter;
import org.mariotaku.twidere.adapter.ParcelableUsersAdapter;
import org.mariotaku.twidere.adapter.iface.IUsersAdapter;
import org.mariotaku.twidere.loader.support.IDsUsersLoader;
import org.mariotaku.twidere.loader.support.IncomingFriendshipsLoader;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.model.message.FollowRequestTaskEvent;
import org.mariotaku.twidere.view.holder.UserViewHolder;
public class IncomingFriendshipsFragment extends CursorSupportUsersListFragment {
import java.util.List;
public class IncomingFriendshipsFragment extends CursorSupportUsersListFragment implements IUsersAdapter.RequestClickListener {
@Override
public void onStart() {
super.onStart();
mBus.register(this);
}
@Override
public void onStop() {
mBus.unregister(this);
super.onStop();
}
@Override
public IDsUsersLoader onCreateUsersLoader(final Context context, @NonNull final Bundle args, boolean fromUser) {
@ -34,4 +55,38 @@ public class IncomingFriendshipsFragment extends CursorSupportUsersListFragment
return new IncomingFriendshipsLoader(context, accountId, getNextCursor(), getData(), fromUser);
}
@NonNull
@Override
protected ParcelableUsersAdapter onCreateAdapter(Context context, boolean compact) {
final ParcelableUsersAdapter adapter = super.onCreateAdapter(context, compact);
adapter.setRequestClickListener(this);
return adapter;
}
@Override
public void onAcceptClicked(UserViewHolder holder, int position) {
final AbsUsersAdapter<List<ParcelableUser>> adapter = getAdapter();
final ParcelableUser user = adapter.getUser(position);
if (user == null) return;
mTwitterWrapper.acceptFriendshipAsync(user.account_id, user.id);
}
@Override
public void onDenyClicked(UserViewHolder holder, int position) {
final AbsUsersAdapter<List<ParcelableUser>> adapter = getAdapter();
final ParcelableUser user = adapter.getUser(position);
if (user == null) return;
mTwitterWrapper.denyFriendshipAsync(user.account_id, user.id);
}
@Subscribe
public void onFollowRequestTaskEvent(FollowRequestTaskEvent event) {
final ParcelableUsersAdapter adapter = getAdapter();
final int position = adapter.findPosition(event.getAccountId(), event.getUserId());
if (event.isFinished() && event.isSucceeded()) {
adapter.removeUserAt(position);
} else {
adapter.notifyItemChanged(position);
}
}
}

View File

@ -107,7 +107,7 @@ import org.mariotaku.twidere.util.ReadStateManager;
import org.mariotaku.twidere.util.UserColorNameManager;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
import org.mariotaku.twidere.util.message.TaskStateChangedEvent;
import org.mariotaku.twidere.model.message.TaskStateChangedEvent;
import org.mariotaku.twidere.view.ComposeEditText;
import java.util.ArrayList;

View File

@ -30,11 +30,11 @@ import org.mariotaku.twidere.adapter.ListParcelableStatusesAdapter;
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter.IndicatorPosition;
import org.mariotaku.twidere.adapter.iface.IStatusesAdapter;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.message.FavoriteCreatedEvent;
import org.mariotaku.twidere.util.message.FavoriteDestroyedEvent;
import org.mariotaku.twidere.util.message.StatusDestroyedEvent;
import org.mariotaku.twidere.util.message.StatusListChangedEvent;
import org.mariotaku.twidere.util.message.StatusRetweetedEvent;
import org.mariotaku.twidere.model.message.FavoriteCreatedEvent;
import org.mariotaku.twidere.model.message.FavoriteDestroyedEvent;
import org.mariotaku.twidere.model.message.StatusDestroyedEvent;
import org.mariotaku.twidere.model.message.StatusListChangedEvent;
import org.mariotaku.twidere.model.message.StatusRetweetedEvent;
import java.util.HashSet;
import java.util.List;

View File

@ -25,7 +25,6 @@ import android.support.annotation.NonNull;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import org.mariotaku.twidere.adapter.AbsUsersAdapter;
import org.mariotaku.twidere.adapter.ParcelableUsersAdapter;
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter.IndicatorPosition;
import org.mariotaku.twidere.model.ParcelableUser;
@ -42,10 +41,16 @@ public abstract class ParcelableUsersFragment extends AbsUsersFragment<List<Parc
@NonNull
@Override
protected AbsUsersAdapter<List<ParcelableUser>> onCreateAdapter(Context context, boolean compact) {
protected ParcelableUsersAdapter onCreateAdapter(Context context, boolean compact) {
return new ParcelableUsersAdapter(context);
}
@NonNull
@Override
public ParcelableUsersAdapter getAdapter() {
return (ParcelableUsersAdapter) super.getAdapter();
}
protected long getAccountId() {
final Bundle args = getArguments();
return args != null ? args.getLong(EXTRA_ACCOUNT_ID, -1) : -1;

View File

@ -140,9 +140,9 @@ 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.util.message.FavoriteCreatedEvent;
import org.mariotaku.twidere.util.message.FavoriteDestroyedEvent;
import org.mariotaku.twidere.util.message.StatusListChangedEvent;
import org.mariotaku.twidere.model.message.FavoriteCreatedEvent;
import org.mariotaku.twidere.model.message.FavoriteDestroyedEvent;
import org.mariotaku.twidere.model.message.StatusListChangedEvent;
import org.mariotaku.twidere.view.CardMediaContainer;
import org.mariotaku.twidere.view.CardMediaContainer.OnMediaClickListener;
import org.mariotaku.twidere.view.ColorLabelRelativeLayout;

View File

@ -36,7 +36,7 @@ import com.squareup.otto.Subscribe;
import org.mariotaku.twidere.adapter.TrendsAdapter;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedTrends;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.message.TaskStateChangedEvent;
import org.mariotaku.twidere.model.message.TaskStateChangedEvent;
import static org.mariotaku.twidere.util.DataStoreUtils.getTableNameByUri;
import static org.mariotaku.twidere.util.Utils.getDefaultAccountId;

View File

@ -135,10 +135,10 @@ import org.mariotaku.twidere.util.TwitterAPIFactory;
import org.mariotaku.twidere.util.UserColorNameManager;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.menu.TwidereMenuInfo;
import org.mariotaku.twidere.util.message.FriendshipUpdatedEvent;
import org.mariotaku.twidere.util.message.FriendshipUserUpdatedEvent;
import org.mariotaku.twidere.util.message.ProfileUpdatedEvent;
import org.mariotaku.twidere.util.message.TaskStateChangedEvent;
import org.mariotaku.twidere.model.message.FriendshipUpdatedEvent;
import org.mariotaku.twidere.model.message.FriendshipUserUpdatedEvent;
import org.mariotaku.twidere.model.message.ProfileUpdatedEvent;
import org.mariotaku.twidere.model.message.TaskStateChangedEvent;
import org.mariotaku.twidere.util.support.ActivitySupport;
import org.mariotaku.twidere.util.support.ActivitySupport.TaskDescriptionCompat;
import org.mariotaku.twidere.util.support.ViewSupport;

View File

@ -35,7 +35,7 @@ import org.mariotaku.twidere.loader.support.UserListsLoader;
import org.mariotaku.twidere.model.ParcelableUserList;
import org.mariotaku.twidere.util.MenuUtils;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.message.UserListDestroyedEvent;
import org.mariotaku.twidere.model.message.UserListDestroyedEvent;
import java.util.List;

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util.message;
package org.mariotaku.twidere.model.message;
/**
* Created by mariotaku on 15/4/24.

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util.message;
package org.mariotaku.twidere.model.message;
import android.support.annotation.NonNull;

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util.message;
package org.mariotaku.twidere.model.message;
import android.support.annotation.NonNull;

View File

@ -0,0 +1,67 @@
package org.mariotaku.twidere.model.message;
import android.support.annotation.IntDef;
/**
* Created by mariotaku on 16/2/15.
*/
public class FollowRequestTaskEvent {
@Action
private int action;
private boolean finished;
private boolean succeeded;
private long accountId;
private long userId;
public FollowRequestTaskEvent(@Action int action, long accountId, long userId) {
this.action = action;
this.accountId = accountId;
this.userId = userId;
}
@Action
public int getAction() {
return action;
}
public boolean isFinished() {
return finished;
}
public void setFinished(boolean finished) {
this.finished = finished;
}
public long getAccountId() {
return accountId;
}
public long getUserId() {
return userId;
}
public boolean isSucceeded() {
return succeeded;
}
public void setSucceeded(boolean succeeded) {
this.succeeded = succeeded;
}
@Override
public String toString() {
return "FollowRequestTaskEvent{" +
"action=" + action +
", finished=" + finished +
", accountId=" + accountId +
", userId=" + userId +
'}';
}
@IntDef({Action.ACCEPT, Action.DENY})
public @interface Action {
int ACCEPT = 1;
int DENY = 2;
}
}

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util.message;
package org.mariotaku.twidere.model.message;
import android.support.annotation.NonNull;

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util.message;
package org.mariotaku.twidere.model.message;
import android.support.annotation.NonNull;

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util.message;
package org.mariotaku.twidere.model.message;
import android.net.Uri;
import android.support.annotation.NonNull;

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util.message;
package org.mariotaku.twidere.model.message;
import android.net.Uri;
import android.support.annotation.NonNull;

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util.message;
package org.mariotaku.twidere.model.message;
import android.net.Uri;
import android.support.annotation.NonNull;

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util.message;
package org.mariotaku.twidere.model.message;
import android.support.annotation.NonNull;

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util.message;
package org.mariotaku.twidere.model.message;
import org.mariotaku.twidere.model.ParcelableStatus;

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util.message;
package org.mariotaku.twidere.model.message;
import org.mariotaku.twidere.model.ParcelableStatus;

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util.message;
package org.mariotaku.twidere.model.message;
/**
* Created by mariotaku on 14/12/12.

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util.message;
package org.mariotaku.twidere.model.message;
import org.mariotaku.twidere.model.ParcelableStatus;

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util.message;
package org.mariotaku.twidere.model.message;
/**
* Created by mariotaku on 14/12/7.

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util.message;
package org.mariotaku.twidere.model.message;
/**
* Created by mariotaku on 14/12/7.

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util.message;
package org.mariotaku.twidere.model.message;
import android.support.annotation.NonNull;

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util.message;
package org.mariotaku.twidere.model.message;
import android.support.annotation.NonNull;

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util.message;
package org.mariotaku.twidere.model.message;
/**
* Created by mariotaku on 15/3/23.

View File

@ -127,7 +127,7 @@ import org.mariotaku.twidere.util.UserColorNameManager;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.collection.CompactHashSet;
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
import org.mariotaku.twidere.util.message.UnreadCountUpdatedEvent;
import org.mariotaku.twidere.model.message.UnreadCountUpdatedEvent;
import org.mariotaku.twidere.util.net.TwidereDns;
import org.oshkimaadziig.george.androidutils.SpanFormatter;

View File

@ -28,7 +28,7 @@ import org.mariotaku.twidere.util.UriUtils;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.content.ContentResolverUtils;
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
import org.mariotaku.twidere.util.message.GetMessagesTaskEvent;
import org.mariotaku.twidere.model.message.GetMessagesTaskEvent;
import java.util.ArrayList;
import java.util.List;

View File

@ -26,8 +26,11 @@ import com.squareup.otto.Bus;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.util.AsyncTaskManager;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
import org.mariotaku.twidere.util.UserColorNameManager;
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
import org.mariotaku.twidere.util.message.TaskStateChangedEvent;
import org.mariotaku.twidere.model.message.TaskStateChangedEvent;
import javax.inject.Inject;
@ -38,6 +41,12 @@ public abstract class ManagedAsyncTask<Params, Progress, Result> extends AsyncTa
protected AsyncTaskManager manager;
@Inject
protected Bus bus;
@Inject
protected UserColorNameManager mUserColorNameManager;
@Inject
protected SharedPreferencesWrapper mPreferences;
@Inject
protected AsyncTwitterWrapper mAsyncTwitterWrapper;
private final Context context;
private final String tag;

View File

@ -34,7 +34,7 @@ import org.mariotaku.twidere.util.TwitterAPIFactory;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.content.ContentResolverUtils;
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
import org.mariotaku.twidere.util.message.GetActivitiesTaskEvent;
import org.mariotaku.twidere.model.message.GetActivitiesTaskEvent;
import java.util.ArrayList;
import java.util.Arrays;

View File

@ -40,7 +40,7 @@ import org.mariotaku.twidere.util.UriUtils;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.content.ContentResolverUtils;
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
import org.mariotaku.twidere.util.message.GetStatusesTaskEvent;
import org.mariotaku.twidere.model.message.GetStatusesTaskEvent;
import java.util.ArrayList;
import java.util.List;

View File

@ -36,7 +36,9 @@ import com.desmond.asyncmanager.BackgroundTask;
import com.desmond.asyncmanager.TaskRunnable;
import com.squareup.otto.Bus;
import org.apache.commons.collections.primitives.ArrayIntList;
import org.apache.commons.collections.primitives.ArrayLongList;
import org.apache.commons.collections.primitives.IntList;
import org.apache.commons.collections.primitives.LongList;
import org.mariotaku.sqliteqb.library.Expression;
import org.mariotaku.twidere.BuildConfig;
@ -66,6 +68,17 @@ import org.mariotaku.twidere.model.ParcelableUserList;
import org.mariotaku.twidere.model.RefreshTaskParam;
import org.mariotaku.twidere.model.Response;
import org.mariotaku.twidere.model.SingleResponse;
import org.mariotaku.twidere.model.message.FavoriteCreatedEvent;
import org.mariotaku.twidere.model.message.FavoriteDestroyedEvent;
import org.mariotaku.twidere.model.message.FollowRequestTaskEvent;
import org.mariotaku.twidere.model.message.FriendshipUpdatedEvent;
import org.mariotaku.twidere.model.message.FriendshipUserUpdatedEvent;
import org.mariotaku.twidere.model.message.ProfileUpdatedEvent;
import org.mariotaku.twidere.model.message.StatusDestroyedEvent;
import org.mariotaku.twidere.model.message.StatusListChangedEvent;
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.provider.TwidereDataStore;
import org.mariotaku.twidere.provider.TwidereDataStore.Activities;
@ -87,16 +100,6 @@ import org.mariotaku.twidere.task.ManagedAsyncTask;
import org.mariotaku.twidere.task.twitter.GetActivitiesTask;
import org.mariotaku.twidere.util.collection.LongSparseMap;
import org.mariotaku.twidere.util.content.ContentResolverUtils;
import org.mariotaku.twidere.util.message.FavoriteCreatedEvent;
import org.mariotaku.twidere.util.message.FavoriteDestroyedEvent;
import org.mariotaku.twidere.util.message.FriendshipUpdatedEvent;
import org.mariotaku.twidere.util.message.FriendshipUserUpdatedEvent;
import org.mariotaku.twidere.util.message.ProfileUpdatedEvent;
import org.mariotaku.twidere.util.message.StatusDestroyedEvent;
import org.mariotaku.twidere.util.message.StatusListChangedEvent;
import org.mariotaku.twidere.util.message.StatusRetweetedEvent;
import org.mariotaku.twidere.util.message.UserListCreatedEvent;
import org.mariotaku.twidere.util.message.UserListDestroyedEvent;
import java.io.FileNotFoundException;
import java.util.ArrayList;
@ -123,6 +126,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
private LongSparseMap<Long> mDestroyingFavoriteIds = new LongSparseMap<>();
private LongSparseMap<Long> mCreatingRetweetIds = new LongSparseMap<>();
private LongSparseMap<Long> mDestroyingStatusIds = new LongSparseMap<>();
private IntList mProcessingFriendshipRequestIds = new ArrayIntList();
private final LongList mSendingDraftIds = new ArrayLongList();
@ -139,7 +143,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
}
public int acceptFriendshipAsync(final long accountId, final long userId) {
final AcceptFriendshipTask task = new AcceptFriendshipTask(accountId, userId);
final AcceptFriendshipTask task = new AcceptFriendshipTask(mContext, accountId, userId);
return mAsyncTaskManager.add(task, true);
}
@ -584,6 +588,18 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
return mErrorInfoStore;
}
private void addProcessingFriendshipRequestId(long accountId, long userId) {
mProcessingFriendshipRequestIds.add(ParcelableUser.calculateHashCode(accountId, userId));
}
private void removeProcessingFriendshipRequestId(long accountId, long userId) {
mProcessingFriendshipRequestIds.removeElement(ParcelableUser.calculateHashCode(accountId, userId));
}
public boolean isProcessingFollowRequest(long accountId, long userId) {
return mProcessingFriendshipRequestIds.contains(ParcelableUser.calculateHashCode(accountId, userId));
}
public static class UpdateProfileBannerImageTask extends ManagedAsyncTask<Object, Object, SingleResponse<ParcelableUser>> {
private final long mAccountId;
@ -684,15 +700,15 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
}
class AcceptFriendshipTask extends ManagedAsyncTask<Object, Object, SingleResponse<User>> {
static class AcceptFriendshipTask extends ManagedAsyncTask<Object, Object, SingleResponse<User>> {
private final long mAccountId;
private final long mUserId;
public AcceptFriendshipTask(final long account_id, final long user_id) {
super(mContext);
mAccountId = account_id;
mUserId = user_id;
public AcceptFriendshipTask(final Context context, final long accountId, final long userId) {
super(context);
mAccountId = accountId;
mUserId = userId;
}
public long getAccountId() {
@ -703,10 +719,21 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
return mUserId;
}
@Override
protected void onPreExecute() {
final FollowRequestTaskEvent event = new FollowRequestTaskEvent(FollowRequestTaskEvent.Action.ACCEPT,
mAccountId, mUserId);
event.setFinished(false);
bus.post(event);
mAsyncTwitterWrapper.addProcessingFriendshipRequestId(mAccountId, mUserId);
super.onPreExecute();
}
@Override
protected SingleResponse<User> doInBackground(final Object... params) {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mContext, mAccountId, false);
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(getContext(), mAccountId, false);
if (twitter == null) return SingleResponse.getInstance();
try {
final User user = twitter.acceptFriendship(mUserId);
@ -718,19 +745,23 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
@Override
protected void onPostExecute(final SingleResponse<User> result) {
final FollowRequestTaskEvent event = new FollowRequestTaskEvent(FollowRequestTaskEvent.Action.ACCEPT,
mAccountId, mUserId);
event.setFinished(true);
if (result.hasData()) {
final User user = result.getData();
final boolean nameFirst = mPreferences.getBoolean(KEY_NAME_FIRST);
final String message = mContext.getString(R.string.accepted_users_follow_request,
final String message = getContext().getString(R.string.accepted_users_follow_request,
mUserColorNameManager.getDisplayName(user, nameFirst, true));
Utils.showOkMessage(mContext, message, false);
Utils.showOkMessage(getContext(), message, false);
event.setSucceeded(true);
} else {
Utils.showErrorMessage(mContext, R.string.action_accepting_follow_request,
Utils.showErrorMessage(getContext(), R.string.action_accepting_follow_request,
result.getException(), false);
event.setSucceeded(false);
}
final Intent intent = new Intent(BROADCAST_FRIENDSHIP_ACCEPTED);
intent.putExtra(EXTRA_USER_ID, mUserId);
mContext.sendBroadcast(intent);
mAsyncTwitterWrapper.removeProcessingFriendshipRequestId(mAccountId, mUserId);
bus.post(event);
super.onPostExecute(result);
}
@ -1311,10 +1342,10 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
private final long mAccountId;
private final long mUserId;
public DenyFriendshipTask(final long account_id, final long user_id) {
public DenyFriendshipTask(final long accountId, final long userId) {
super(mContext);
mAccountId = account_id;
mUserId = user_id;
mAccountId = accountId;
mUserId = userId;
}
public long getAccountId() {
@ -1338,21 +1369,35 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
}
}
@Override
protected void onPreExecute() {
addProcessingFriendshipRequestId(mAccountId, mUserId);
final FollowRequestTaskEvent event = new FollowRequestTaskEvent(FollowRequestTaskEvent.Action.ACCEPT,
mAccountId, mUserId);
event.setFinished(false);
bus.post(event);
super.onPreExecute();
}
@Override
protected void onPostExecute(final SingleResponse<User> result) {
final FollowRequestTaskEvent event = new FollowRequestTaskEvent(FollowRequestTaskEvent.Action.ACCEPT,
mAccountId, mUserId);
event.setFinished(true);
if (result.hasData()) {
final User user = result.getData();
final boolean nameFirst = mPreferences.getBoolean(KEY_NAME_FIRST);
final String message = mContext.getString(R.string.denied_users_follow_request,
mUserColorNameManager.getDisplayName(user, nameFirst, true));
Utils.showOkMessage(mContext, message, false);
event.setSucceeded(true);
} else {
Utils.showErrorMessage(mContext, R.string.action_denying_follow_request, result.getException(), false);
event.setSucceeded(false);
}
final Intent intent = new Intent(BROADCAST_FRIENDSHIP_DENIED);
intent.putExtra(EXTRA_USER_ID, mUserId);
mContext.sendBroadcast(intent);
super.onPostExecute(result);
removeProcessingFriendshipRequestId(mAccountId, mUserId);
bus.post(event);
}
}

View File

@ -64,12 +64,7 @@ public class NameView extends ThemedTextView {
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NameView, defStyleAttr, 0);
setPrimaryTextColor(a.getColor(R.styleable.NameView_nv_primaryTextColor, 0));
setSecondaryTextColor(a.getColor(R.styleable.NameView_nv_secondaryTextColor, 0));
if (mTwoLine = a.getBoolean(R.styleable.NameView_nv_twoLine, false)) {
setSingleLine(false);
setMaxLines(2);
} else {
setSingleLine(true);
}
setTwoLine(a.getBoolean(R.styleable.NameView_nv_twoLine, false));
mPrimaryTextStyle = new StyleSpan(a.getInt(R.styleable.NameView_nv_primaryTextStyle, 0));
mSecondaryTextStyle = new StyleSpan(a.getInt(R.styleable.NameView_nv_secondaryTextStyle, 0));
a.recycle();
@ -156,4 +151,13 @@ public class NameView extends ThemedTextView {
mSecondaryTextSize = new AbsoluteSizeSpan((int) calculateTextSize(TypedValue.COMPLEX_UNIT_SP, textSize));
}
public void setTwoLine(boolean twoLine) {
mTwoLine = twoLine;
if (twoLine) {
setSingleLine(false);
setMaxLines(2);
} else {
setSingleLine(true);
}
}
}

View File

@ -28,9 +28,11 @@ import android.widget.ImageView;
import android.widget.TextView;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.iface.ContentCardClickListener;
import org.mariotaku.twidere.adapter.iface.IUsersAdapter;
import org.mariotaku.twidere.adapter.iface.IUsersAdapter.RequestClickListener;
import org.mariotaku.twidere.adapter.iface.IUsersAdapter.UserAdapterListener;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.UserColorNameManager;
import org.mariotaku.twidere.view.NameView;
@ -52,7 +54,12 @@ public class UserViewHolder extends ViewHolder implements OnClickListener, OnLon
private final TextView descriptionView, locationView, urlView,
statusesCountView, followersCountView, friendsCountView;
private UserClickListener userClickListener;
private final View acceptRequestButton, denyRequestButton;
private final View followRequestContainer;
private final View processingRequestProgress;
private UserAdapterListener userClickListener;
private RequestClickListener requestClickListener;
public UserViewHolder(final IUsersAdapter<?> adapter, final View itemView) {
super(itemView);
@ -67,12 +74,17 @@ public class UserViewHolder extends ViewHolder implements OnClickListener, OnLon
statusesCountView = (TextView) itemView.findViewById(R.id.statuses_count);
followersCountView = (TextView) itemView.findViewById(R.id.followers_count);
friendsCountView = (TextView) itemView.findViewById(R.id.friends_count);
followRequestContainer = itemView.findViewById(R.id.follow_request_container);
acceptRequestButton = itemView.findViewById(R.id.accept_request);
denyRequestButton = itemView.findViewById(R.id.deny_request);
processingRequestProgress = itemView.findViewById(R.id.processing_request);
}
public void displayUser(ParcelableUser user) {
final MediaLoaderWrapper loader = adapter.getMediaLoader();
final UserColorNameManager manager = adapter.getUserColorNameManager();
final AsyncTwitterWrapper twitter = adapter.getTwitterWrapper();
itemContent.drawStart(manager.getUserColor(user.id, false));
@ -103,6 +115,16 @@ public class UserViewHolder extends ViewHolder implements OnClickListener, OnLon
profileImageView.setVisibility(View.GONE);
loader.cancelDisplayTask(profileImageView);
}
if (twitter.isProcessingFollowRequest(user.account_id, user.id)) {
processingRequestProgress.setVisibility(View.VISIBLE);
acceptRequestButton.setVisibility(View.GONE);
denyRequestButton.setVisibility(View.GONE);
} else {
processingRequestProgress.setVisibility(View.GONE);
acceptRequestButton.setVisibility(View.VISIBLE);
denyRequestButton.setVisibility(View.VISIBLE);
}
}
public ImageView getProfileImageView() {
@ -115,12 +137,22 @@ public class UserViewHolder extends ViewHolder implements OnClickListener, OnLon
@Override
public void onClick(View v) {
if (userClickListener == null) return;
switch (v.getId()) {
case R.id.item_content: {
if (userClickListener == null) return;
userClickListener.onUserClick(this, getLayoutPosition());
break;
}
case R.id.accept_request: {
if (requestClickListener == null) return;
requestClickListener.onAcceptClicked(this, getLayoutPosition());
break;
}
case R.id.deny_request: {
if (requestClickListener == null) return;
requestClickListener.onDenyClicked(this, getLayoutPosition());
break;
}
}
}
@ -136,7 +168,22 @@ public class UserViewHolder extends ViewHolder implements OnClickListener, OnLon
}
public void setOnClickListeners() {
setUserClickListener(adapter);
setUserClickListener(adapter.getUserAdapterListener());
setRequestClickListener(adapter.getRequestClickListener());
}
private void setRequestClickListener(RequestClickListener listener) {
requestClickListener = listener;
if (listener != null) {
nameView.setTwoLine(true);
followRequestContainer.setVisibility(View.VISIBLE);
} else {
nameView.setTwoLine(false);
followRequestContainer.setVisibility(View.GONE);
}
nameView.updateText();
acceptRequestButton.setOnClickListener(this);
denyRequestButton.setOnClickListener(this);
}
public void setTextSize(final float textSize) {
@ -150,7 +197,7 @@ public class UserViewHolder extends ViewHolder implements OnClickListener, OnLon
friendsCountView.setTextSize(textSize);
}
public void setUserClickListener(UserClickListener listener) {
public void setUserClickListener(UserAdapterListener listener) {
userClickListener = listener;
((View) itemContent).setOnClickListener(this);
((View) itemContent).setOnLongClickListener(this);
@ -160,11 +207,4 @@ public class UserViewHolder extends ViewHolder implements OnClickListener, OnLon
setTextSize(adapter.getTextSize());
}
public interface UserClickListener extends ContentCardClickListener {
void onUserClick(UserViewHolder holder, int position);
boolean onUserLongClick(UserViewHolder holder, int position);
}
}

View File

@ -17,10 +17,10 @@
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<org.mariotaku.twidere.view.TintedStatusNativeActionModeAwareLayout
android:id="@+id/main_content"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:setPadding="true">
@ -87,7 +87,7 @@
android:minHeight="48dp"
android:text="@string/register"/>
<Button
<android.support.v7.widget.AppCompatButton
android:id="@+id/sign_in"
style="?android:buttonStyleSmall"
android:layout_width="match_parent"
@ -95,7 +95,8 @@
android:layout_weight="1"
android:minHeight="48dp"
android:onClick="onClick"
android:text="@string/sign_in" />
android:text="@string/sign_in"
app:backgroundTint="@color/material_light_green"/>
</LinearLayout>

View File

@ -1,177 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Twidere - Twitter client for Android
~
~ Copyright (C) 2012-2014 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/>.
-->
<android.support.v7.widget.CardView
android:id="@+id/card"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/element_spacing_small"
android:layout_marginLeft="@dimen/element_spacing_normal"
android:layout_marginRight="@dimen/element_spacing_normal"
android:layout_marginTop="@dimen/element_spacing_small"
app:cardBackgroundColor="?cardItemBackgroundColor"
app:cardCornerRadius="2dp"
app:cardElevation="2dp"
tools:context=".adapter.ParcelableUsersAdapter">
<org.mariotaku.twidere.view.ColorLabelLinearLayout
android:id="@+id/item_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:focusable="true"
android:orientation="vertical"
android:paddingBottom="@dimen/element_spacing_small"
android:paddingLeft="@dimen/element_spacing_normal"
android:paddingRight="@dimen/element_spacing_normal"
android:paddingTop="@dimen/element_spacing_small">
<RelativeLayout
android:id="@+id/profile_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/element_spacing_normal"
android:paddingEnd="@dimen/element_spacing_xlarge"
android:paddingLeft="@dimen/element_spacing_normal"
android:paddingRight="@dimen/element_spacing_xlarge"
android:paddingStart="@dimen/element_spacing_normal"
android:paddingTop="@dimen/element_spacing_normal">
<org.mariotaku.twidere.view.ProfileImageView
android:id="@+id/profile_image"
style="?profileImageStyle"
android:layout_width="@dimen/icon_size_card_list_item"
android:layout_height="@dimen/icon_size_card_list_item"
android:layout_centerVertical="true"
android:contentDescription="@string/profile_image"
android:scaleType="fitCenter"
tools:src="@mipmap/ic_launcher"/>
<ImageView
android:id="@+id/profile_type"
android:layout_width="@dimen/icon_size_profile_type"
android:layout_height="@dimen/icon_size_profile_type"
android:layout_alignBottom="@id/profile_image"
android:layout_alignEnd="@id/profile_image"
android:layout_alignRight="@id/profile_image"
android:layout_marginBottom="@dimen/element_spacing_minus_small"
android:layout_marginEnd="@dimen/element_spacing_minus_normal"
android:layout_marginRight="@dimen/element_spacing_minus_normal"
android:scaleType="centerInside"
tools:ignore="ContentDescription"/>
<org.mariotaku.twidere.view.NameView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toEndOf="@+id/profile_image"
android:layout_toRightOf="@+id/profile_image"
android:paddingEnd="0dp"
android:paddingLeft="8dp"
android:paddingRight="0dp"
android:paddingStart="8dp"
app:nv_primaryTextColor="?android:textColorPrimary"
app:nv_primaryTextStyle="bold"
app:nv_secondaryTextColor="?android:textColorSecondary"
app:nv_twoLine="true"/>
</RelativeLayout>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
tools:text="@string/sample_status_text"/>
<org.mariotaku.twidere.view.ActionIconThemedTextView
android:id="@+id/location"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_indicator_location"
android:drawablePadding="4dp"
android:drawableStart="@drawable/ic_indicator_location"
android:padding="8dp"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:text="Earth"/>
<org.mariotaku.twidere.view.ActionIconThemedTextView
android:id="@+id/url"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_indicator_link"
android:drawablePadding="4dp"
android:drawableStart="@drawable/ic_indicator_link"
android:padding="8dp"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:text="https://github.com/TwidereProject"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dp">
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/statuses_count"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawableLeft="@drawable/ic_indicator_twitter"
android:drawablePadding="4dp"
android:drawableStart="@drawable/ic_indicator_twitter"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:text="255"/>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/followers_count"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawableLeft="@drawable/ic_indicator_followers"
android:drawablePadding="4dp"
android:drawableStart="@drawable/ic_indicator_followers"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:text="255"/>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/friends_count"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawableLeft="@drawable/ic_indicator_following"
android:drawablePadding="4dp"
android:drawableStart="@drawable/ic_indicator_following"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:text="255"/>
</LinearLayout>
</org.mariotaku.twidere.view.ColorLabelLinearLayout>
</android.support.v7.widget.CardView>

View File

@ -34,23 +34,33 @@
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:paddingBottom="@dimen/element_spacing_normal"
android:paddingEnd="@dimen/item_menu_card_padding_compact"
android:paddingEnd="@dimen/element_spacing_normal"
android:paddingLeft="@dimen/element_spacing_normal"
android:paddingRight="@dimen/item_menu_card_padding_compact"
android:paddingRight="@dimen/element_spacing_normal"
android:paddingStart="@dimen/element_spacing_normal"
android:paddingTop="@dimen/element_spacing_normal">
<RelativeLayout
android:id="@+id/profile_image_container"
android:layout_width="@dimen/icon_size_card_list_item"
android:layout_height="@dimen/icon_size_card_list_item"
android:layout_alignBottom="@+id/name_request"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignTop="@+id/name_request"
android:layout_marginEnd="@dimen/element_spacing_normal"
android:layout_marginRight="@dimen/element_spacing_normal"
android:clipChildren="false">
<org.mariotaku.twidere.view.ProfileImageView
android:id="@+id/profile_image"
style="?profileImageStyle"
android:layout_width="@dimen/icon_size_card_list_item"
android:layout_height="@dimen/icon_size_card_list_item"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginEnd="@dimen/element_spacing_normal"
android:layout_marginRight="@dimen/element_spacing_normal"
android:layout_centerInParent="true"
android:contentDescription="@string/profile_image"
tools:src="@mipmap/ic_launcher"/>
@ -65,41 +75,92 @@
android:layout_marginEnd="@dimen/element_spacing_minus_normal"
android:layout_marginRight="@dimen/element_spacing_minus_normal"
android:scaleType="centerInside"
tools:ignore="ContentDescription"/>
tools:ignore="ContentDescription"
tools:src="@drawable/ic_user_type_verified"
tools:visibility="visible"/>
</RelativeLayout>
<org.mariotaku.twidere.view.NameView
android:id="@+id/name"
android:layout_width="wrap_content"
<LinearLayout
android:id="@+id/name_request"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_alignWithParentIfMissing="true"
android:layout_toEndOf="@id/profile_image"
android:layout_toRightOf="@id/profile_image"
android:layout_toEndOf="@id/profile_image_container"
android:layout_toRightOf="@id/profile_image_container"
android:clipChildren="false"
android:gravity="center_vertical"
android:orientation="horizontal">
<org.mariotaku.twidere.view.NameView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
app:nv_primaryTextColor="?android:textColorPrimary"
app:nv_primaryTextStyle="bold"
app:nv_secondaryTextColor="?android:textColorSecondary"/>
app:nv_secondaryTextColor="?android:textColorSecondary"
app:nv_twoLine="true"/>
<LinearLayout
android:id="@+id/follow_request_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:clipChildren="false"
android:gravity="center"
android:minHeight="@dimen/element_size_normal"
android:minWidth="@dimen/element_size_normal"
android:orientation="horizontal">
<org.mariotaku.twidere.view.themed.ThemedTextView
<android.support.v7.widget.AppCompatImageButton
android:id="@+id/accept_request"
style="?buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/accept"
android:src="@drawable/ic_action_confirm"
app:backgroundTint="@color/material_light_green"/>
<android.support.v7.widget.AppCompatImageButton
android:id="@+id/deny_request"
style="?buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/deny"
android:src="@drawable/ic_action_cancel"
app:backgroundTint="@color/material_red"/>
<ProgressBar
android:id="@+id/processing_request"
style="?android:progressBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
<org.mariotaku.twidere.view.ActionIconThemedTextView
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/name"
android:layout_alignStart="@+id/name"
android:layout_below="@+id/name"
android:layout_alignLeft="@+id/name_request"
android:layout_alignStart="@+id/name_request"
android:layout_below="@+id/name_request"
android:paddingTop="@dimen/element_spacing_small"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
tools:text="@string/sample_status_text"/>
<org.mariotaku.twidere.view.themed.ThemedTextView
<org.mariotaku.twidere.view.ActionIconThemedTextView
android:id="@+id/location"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/name"
android:layout_alignStart="@+id/name"
android:layout_alignLeft="@+id/name_request"
android:layout_alignStart="@+id/name_request"
android:layout_below="@+id/description"
android:drawableLeft="@drawable/ic_indicator_location"
android:drawablePadding="@dimen/element_spacing_small"
@ -109,12 +170,12 @@
android:textAppearance="?android:attr/textAppearanceSmall"
tools:text="Earth"/>
<org.mariotaku.twidere.view.themed.ThemedTextView
<org.mariotaku.twidere.view.ActionIconThemedTextView
android:id="@+id/url"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/name"
android:layout_alignStart="@+id/name"
android:layout_alignLeft="@+id/name_request"
android:layout_alignStart="@+id/name_request"
android:layout_below="@+id/location"
android:drawableLeft="@drawable/ic_indicator_web"
android:drawablePadding="@dimen/element_spacing_small"
@ -127,13 +188,13 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/name"
android:layout_alignStart="@+id/name"
android:layout_alignLeft="@+id/name_request"
android:layout_alignStart="@+id/name_request"
android:layout_below="@+id/url"
android:orientation="horizontal"
android:paddingTop="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.themed.ThemedTextView
<org.mariotaku.twidere.view.ActionIconThemedTextView
android:id="@+id/statuses_count"
android:layout_width="0dp"
android:layout_height="wrap_content"
@ -145,7 +206,7 @@
android:textAppearance="?android:attr/textAppearanceSmall"
tools:text="255"/>
<org.mariotaku.twidere.view.themed.ThemedTextView
<org.mariotaku.twidere.view.ActionIconThemedTextView
android:id="@+id/followers_count"
android:layout_width="0dp"
android:layout_height="wrap_content"
@ -157,7 +218,7 @@
android:textAppearance="?android:attr/textAppearanceSmall"
tools:text="255"/>
<org.mariotaku.twidere.view.themed.ThemedTextView
<org.mariotaku.twidere.view.ActionIconThemedTextView
android:id="@+id/friends_count"
android:layout_width="0dp"
android:layout_height="wrap_content"

View File

@ -17,9 +17,10 @@
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<org.mariotaku.twidere.view.ColorLabelFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
<org.mariotaku.twidere.view.ColorLabelFrameLayout
android:id="@+id/item_content"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
@ -33,9 +34,9 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/element_spacing_normal"
android:paddingEnd="@dimen/item_menu_card_padding_compact"
android:paddingEnd="@dimen/element_spacing_normal"
android:paddingLeft="@dimen/element_spacing_normal"
android:paddingRight="@dimen/item_menu_card_padding_compact"
android:paddingRight="@dimen/element_spacing_normal"
android:paddingStart="@dimen/element_spacing_normal"
android:paddingTop="@dimen/element_spacing_normal">

View File

@ -53,9 +53,6 @@
<dimen name="line_indicator_line_width_wizard">24dp</dimen>
<dimen name="line_indicator_stroke_width_wizard">3dp</dimen>
<!-- Size of the item menu -->
<dimen name="item_menu_card_padding_compact">28dp</dimen>
<!-- Dimensions for color picker -->
<dimen name="color_button_width">48dp</dimen>
<dimen name="color_button_height">48dp</dimen>