fix link header handling in AccountActivityFragment

- fixes douplication of users after undoing unblocks/unmutes
- removes unnecessary loading when scrolled to end of list
This commit is contained in:
Conny Duck 2018-03-02 20:56:09 +01:00
parent a81f691689
commit fec1dbc470
2 changed files with 29 additions and 42 deletions

View file

@ -46,16 +46,14 @@ public abstract class AccountAdapter extends RecyclerView.Adapter {
} }
public void update(@Nullable List<Account> newAccounts, @Nullable String fromId, public void update(@Nullable List<Account> newAccounts, @Nullable String fromId,
@Nullable String uptoId) { @Nullable String uptoId) {
if (newAccounts == null || newAccounts.isEmpty()) { if (newAccounts == null || newAccounts.isEmpty()) {
return; return;
} }
if (fromId != null) {
bottomId = fromId; bottomId = fromId;
} topId = uptoId;
if (uptoId != null) {
topId = uptoId;
}
if (accountList.isEmpty()) { if (accountList.isEmpty()) {
accountList = ListUtils.removeDuplicates(newAccounts); accountList = ListUtils.removeDuplicates(newAccounts);
} else { } else {

View file

@ -19,6 +19,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.support.v7.widget.DividerItemDecoration; import android.support.v7.widget.DividerItemDecoration;
@ -29,20 +30,19 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import com.keylesspalace.tusky.AccountActivity; import com.keylesspalace.tusky.AccountActivity;
import com.keylesspalace.tusky.BaseActivity;
import com.keylesspalace.tusky.R;
import com.keylesspalace.tusky.adapter.AccountAdapter; import com.keylesspalace.tusky.adapter.AccountAdapter;
import com.keylesspalace.tusky.adapter.BlocksAdapter; import com.keylesspalace.tusky.adapter.BlocksAdapter;
import com.keylesspalace.tusky.adapter.FollowAdapter; import com.keylesspalace.tusky.adapter.FollowAdapter;
import com.keylesspalace.tusky.adapter.FollowRequestsAdapter; import com.keylesspalace.tusky.adapter.FollowRequestsAdapter;
import com.keylesspalace.tusky.adapter.FooterViewHolder; import com.keylesspalace.tusky.adapter.FooterViewHolder;
import com.keylesspalace.tusky.adapter.MutesAdapter; import com.keylesspalace.tusky.adapter.MutesAdapter;
import com.keylesspalace.tusky.BaseActivity;
import com.keylesspalace.tusky.entity.Account; import com.keylesspalace.tusky.entity.Account;
import com.keylesspalace.tusky.entity.Relationship; import com.keylesspalace.tusky.entity.Relationship;
import com.keylesspalace.tusky.interfaces.AccountActionListener; import com.keylesspalace.tusky.interfaces.AccountActionListener;
import com.keylesspalace.tusky.network.MastodonApi; import com.keylesspalace.tusky.network.MastodonApi;
import com.keylesspalace.tusky.R;
import com.keylesspalace.tusky.util.HttpHeaderLink; import com.keylesspalace.tusky.util.HttpHeaderLink;
import com.keylesspalace.tusky.util.ThemeUtils; import com.keylesspalace.tusky.util.ThemeUtils;
import com.keylesspalace.tusky.view.EndlessOnScrollListener; import com.keylesspalace.tusky.view.EndlessOnScrollListener;
@ -107,7 +107,7 @@ public class AccountListFragment extends BaseFragment implements AccountActionLi
@Nullable @Nullable
@Override @Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) { @Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_account_list, container, false); View rootView = inflater.inflate(R.layout.fragment_account_list, container, false);
@ -161,6 +161,9 @@ public class AccountListFragment extends BaseFragment implements AccountActionLi
}; };
recyclerView.addOnScrollListener(scrollListener); recyclerView.addOnScrollListener(scrollListener);
fetchAccounts(null, null, FetchEnd.BOTTOM);
} }
@Override @Override
@ -182,7 +185,7 @@ public class AccountListFragment extends BaseFragment implements AccountActionLi
Callback<Relationship> callback = new Callback<Relationship>() { Callback<Relationship> callback = new Callback<Relationship>() {
@Override @Override
public void onResponse(Call<Relationship> call, Response<Relationship> response) { public void onResponse(@NonNull Call<Relationship> call, @NonNull Response<Relationship> response) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
onMuteSuccess(mute, id, position); onMuteSuccess(mute, id, position);
} else { } else {
@ -191,7 +194,7 @@ public class AccountListFragment extends BaseFragment implements AccountActionLi
} }
@Override @Override
public void onFailure(Call<Relationship> call, Throwable t) { public void onFailure(@NonNull Call<Relationship> call, @NonNull Throwable t) {
onMuteFailure(mute, id); onMuteFailure(mute, id);
} }
}; };
@ -212,12 +215,9 @@ public class AccountListFragment extends BaseFragment implements AccountActionLi
} }
final MutesAdapter mutesAdapter = (MutesAdapter) adapter; final MutesAdapter mutesAdapter = (MutesAdapter) adapter;
final Account unmutedUser = mutesAdapter.removeItem(position); final Account unmutedUser = mutesAdapter.removeItem(position);
View.OnClickListener listener = new View.OnClickListener() { View.OnClickListener listener = v -> {
@Override mutesAdapter.addItem(unmutedUser, position);
public void onClick(View v) { onMute(true, id, position);
mutesAdapter.addItem(unmutedUser, position);
onMute(true, id, position);
}
}; };
Snackbar.make(recyclerView, R.string.confirmation_unmuted, Snackbar.LENGTH_LONG) Snackbar.make(recyclerView, R.string.confirmation_unmuted, Snackbar.LENGTH_LONG)
.setAction(R.string.action_undo, listener) .setAction(R.string.action_undo, listener)
@ -246,7 +246,7 @@ public class AccountListFragment extends BaseFragment implements AccountActionLi
Callback<Relationship> cb = new Callback<Relationship>() { Callback<Relationship> cb = new Callback<Relationship>() {
@Override @Override
public void onResponse(Call<Relationship> call, Response<Relationship> response) { public void onResponse(@NonNull Call<Relationship> call, @NonNull Response<Relationship> response) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
onBlockSuccess(block, id, position); onBlockSuccess(block, id, position);
} else { } else {
@ -255,7 +255,7 @@ public class AccountListFragment extends BaseFragment implements AccountActionLi
} }
@Override @Override
public void onFailure(Call<Relationship> call, Throwable t) { public void onFailure(@NonNull Call<Relationship> call, @NonNull Throwable t) {
onBlockFailure(block, id); onBlockFailure(block, id);
} }
}; };
@ -276,12 +276,9 @@ public class AccountListFragment extends BaseFragment implements AccountActionLi
} }
final BlocksAdapter blocksAdapter = (BlocksAdapter) adapter; final BlocksAdapter blocksAdapter = (BlocksAdapter) adapter;
final Account unblockedUser = blocksAdapter.removeItem(position); final Account unblockedUser = blocksAdapter.removeItem(position);
View.OnClickListener listener = new View.OnClickListener() { View.OnClickListener listener = v -> {
@Override blocksAdapter.addItem(unblockedUser, position);
public void onClick(View v) { onBlock(true, id, position);
blocksAdapter.addItem(unblockedUser, position);
onBlock(true, id, position);
}
}; };
Snackbar.make(recyclerView, R.string.confirmation_unblocked, Snackbar.LENGTH_LONG) Snackbar.make(recyclerView, R.string.confirmation_unblocked, Snackbar.LENGTH_LONG)
.setAction(R.string.action_undo, listener) .setAction(R.string.action_undo, listener)
@ -311,7 +308,7 @@ public class AccountListFragment extends BaseFragment implements AccountActionLi
Callback<Relationship> callback = new Callback<Relationship>() { Callback<Relationship> callback = new Callback<Relationship>() {
@Override @Override
public void onResponse(Call<Relationship> call, Response<Relationship> response) { public void onResponse(@NonNull Call<Relationship> call, @NonNull Response<Relationship> response) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
onRespondToFollowRequestSuccess(position); onRespondToFollowRequestSuccess(position);
} else { } else {
@ -320,7 +317,7 @@ public class AccountListFragment extends BaseFragment implements AccountActionLi
} }
@Override @Override
public void onFailure(Call<Relationship> call, Throwable t) { public void onFailure(@NonNull Call<Relationship> call, @NonNull Throwable t) {
onRespondToFollowRequestFailure(accept, accountId); onRespondToFollowRequestFailure(accept, accountId);
} }
}; };
@ -351,11 +348,6 @@ public class AccountListFragment extends BaseFragment implements AccountActionLi
Log.e(TAG, message); Log.e(TAG, message);
} }
private void jumpToTop() {
layoutManager.scrollToPositionWithOffset(0, 0);
scrollListener.reset();
}
private enum FetchEnd { private enum FetchEnd {
TOP, TOP,
BOTTOM BOTTOM
@ -393,17 +385,12 @@ public class AccountListFragment extends BaseFragment implements AccountActionLi
/* When this is called by the EndlessScrollListener it cannot refresh the footer state /* When this is called by the EndlessScrollListener it cannot refresh the footer state
* using adapter.notifyItemChanged. So its necessary to postpone doing so until a * using adapter.notifyItemChanged. So its necessary to postpone doing so until a
* convenient time for the UI thread using a Runnable. */ * convenient time for the UI thread using a Runnable. */
recyclerView.post(new Runnable() { recyclerView.post(() -> adapter.setFooterState(FooterViewHolder.State.LOADING));
@Override
public void run() {
adapter.setFooterState(FooterViewHolder.State.LOADING);
}
});
} }
Callback<List<Account>> cb = new Callback<List<Account>>() { Callback<List<Account>> cb = new Callback<List<Account>>() {
@Override @Override
public void onResponse(Call<List<Account>> call, Response<List<Account>> response) { public void onResponse(@NonNull Call<List<Account>> call, @NonNull Response<List<Account>> response) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
String linkHeader = response.headers().get("Link"); String linkHeader = response.headers().get("Link");
onFetchAccountsSuccess(response.body(), linkHeader, fetchEnd); onFetchAccountsSuccess(response.body(), linkHeader, fetchEnd);
@ -413,7 +400,7 @@ public class AccountListFragment extends BaseFragment implements AccountActionLi
} }
@Override @Override
public void onFailure(Call<List<Account>> call, Throwable t) { public void onFailure(@NonNull Call<List<Account>> call, @NonNull Throwable t) {
onFetchAccountsFailure((Exception) t, fetchEnd); onFetchAccountsFailure((Exception) t, fetchEnd);
} }
}; };
@ -476,6 +463,8 @@ public class AccountListFragment extends BaseFragment implements AccountActionLi
private void onLoadMore(RecyclerView recyclerView) { private void onLoadMore(RecyclerView recyclerView) {
AccountAdapter adapter = (AccountAdapter) recyclerView.getAdapter(); AccountAdapter adapter = (AccountAdapter) recyclerView.getAdapter();
//if we do not have a bottom id, we know we do not need to load more
if(adapter.getBottomId() == null) return;
fetchAccounts(adapter.getBottomId(), null, FetchEnd.BOTTOM); fetchAccounts(adapter.getBottomId(), null, FetchEnd.BOTTOM);
} }