diff --git a/app/src/main/java/com/keylesspalace/tusky/AccountAdapter.java b/app/src/main/java/com/keylesspalace/tusky/AccountAdapter.java index 2773cce1..9941d34d 100644 --- a/app/src/main/java/com/keylesspalace/tusky/AccountAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/AccountAdapter.java @@ -15,6 +15,7 @@ package com.keylesspalace.tusky; +import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import com.keylesspalace.tusky.entity.Account; @@ -64,6 +65,24 @@ abstract class AccountAdapter extends RecyclerView.Adapter { notifyItemRangeInserted(end, newAccounts.size()); } + @Nullable + Account removeItem(int position) { + if (position < 0 || position >= accountList.size()) { + return null; + } + Account account = accountList.remove(position); + notifyItemRemoved(position); + return account; + } + + void addItem(Account account, int position) { + if (position < 0 || position > accountList.size()) { + return; + } + accountList.add(position, account); + notifyItemInserted(position); + } + public Account getItem(int position) { if (position >= 0 && position < accountList.size()) { return accountList.get(position); diff --git a/app/src/main/java/com/keylesspalace/tusky/AccountFragment.java b/app/src/main/java/com/keylesspalace/tusky/AccountFragment.java index ecc63a34..c4c354ad 100644 --- a/app/src/main/java/com/keylesspalace/tusky/AccountFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/AccountFragment.java @@ -20,6 +20,7 @@ import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.annotation.Nullable; +import android.support.design.widget.Snackbar; import android.support.design.widget.TabLayout; import android.support.v7.widget.DividerItemDecoration; import android.support.v7.widget.LinearLayoutManager; @@ -257,7 +258,7 @@ public class AccountFragment extends BaseFragment implements AccountActionListen @Override public void onResponse(Call call, Response response) { if (response.isSuccessful()) { - onMuteSuccess(mute, position); + onMuteSuccess(mute, id, position); } else { onMuteFailure(mute, id); } @@ -279,9 +280,22 @@ public class AccountFragment extends BaseFragment implements AccountActionListen call.enqueue(callback); } - private void onMuteSuccess(boolean muted, int position) { - MutesAdapter mutesAdapter = (MutesAdapter) adapter; - mutesAdapter.setMuted(muted, position); + private void onMuteSuccess(boolean muted, final String id, final int position) { + if (muted) { + return; + } + final MutesAdapter mutesAdapter = (MutesAdapter) adapter; + final Account unmutedUser = mutesAdapter.removeItem(position); + View.OnClickListener listener = new View.OnClickListener() { + @Override + public void onClick(View v) { + mutesAdapter.addItem(unmutedUser, position); + onMute(true, id, position); + } + }; + Snackbar.make(recyclerView, R.string.confirmation_unmuted, Snackbar.LENGTH_LONG) + .setAction(R.string.action_undo, listener) + .show(); } private void onMuteFailure(boolean mute, String id) { @@ -307,7 +321,7 @@ public class AccountFragment extends BaseFragment implements AccountActionListen @Override public void onResponse(Call call, Response response) { if (response.isSuccessful()) { - onBlockSuccess(block, position); + onBlockSuccess(block, id, position); } else { onBlockFailure(block, id); } @@ -329,9 +343,22 @@ public class AccountFragment extends BaseFragment implements AccountActionListen call.enqueue(cb); } - private void onBlockSuccess(boolean blocked, int position) { - BlocksAdapter blocksAdapter = (BlocksAdapter) adapter; - blocksAdapter.setBlocked(blocked, position); + private void onBlockSuccess(boolean blocked, final String id, final int position) { + if (blocked) { + return; + } + final BlocksAdapter blocksAdapter = (BlocksAdapter) adapter; + final Account unblockedUser = blocksAdapter.removeItem(position); + View.OnClickListener listener = new View.OnClickListener() { + @Override + public void onClick(View v) { + blocksAdapter.addItem(unblockedUser, position); + onBlock(true, id, position); + } + }; + Snackbar.make(recyclerView, R.string.confirmation_unblocked, Snackbar.LENGTH_LONG) + .setAction(R.string.action_undo, listener) + .show(); } private void onBlockFailure(boolean block, String id) { diff --git a/app/src/main/java/com/keylesspalace/tusky/BlocksAdapter.java b/app/src/main/java/com/keylesspalace/tusky/BlocksAdapter.java index c8c6abbf..8b00c939 100644 --- a/app/src/main/java/com/keylesspalace/tusky/BlocksAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/BlocksAdapter.java @@ -15,6 +15,7 @@ package com.keylesspalace.tusky; +import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; @@ -26,9 +27,6 @@ import com.keylesspalace.tusky.entity.Account; import com.pkmmte.view.CircularImageView; import com.squareup.picasso.Picasso; -import java.util.HashSet; -import java.util.Set; - import butterknife.BindView; import butterknife.ButterKnife; @@ -36,11 +34,8 @@ class BlocksAdapter extends AccountAdapter { private static final int VIEW_TYPE_BLOCKED_USER = 0; private static final int VIEW_TYPE_FOOTER = 1; - private Set unblockedAccountPositions; - BlocksAdapter(AccountActionListener accountActionListener) { super(accountActionListener); - unblockedAccountPositions = new HashSet<>(); } @Override @@ -65,8 +60,7 @@ class BlocksAdapter extends AccountAdapter { if (position < accountList.size()) { BlockedUserViewHolder holder = (BlockedUserViewHolder) viewHolder; holder.setupWithAccount(accountList.get(position)); - boolean blocked = !unblockedAccountPositions.contains(position); - holder.setupActionListener(accountActionListener, blocked, position); + holder.setupActionListener(accountActionListener, true); } } @@ -79,15 +73,6 @@ class BlocksAdapter extends AccountAdapter { } } - void setBlocked(boolean blocked, int position) { - if (blocked) { - unblockedAccountPositions.remove(position); - } else { - unblockedAccountPositions.add(position); - } - notifyItemChanged(position); - } - static class BlockedUserViewHolder extends RecyclerView.ViewHolder { @BindView(R.id.blocked_user_avatar) CircularImageView avatar; @BindView(R.id.blocked_user_username) TextView username; @@ -114,12 +99,14 @@ class BlocksAdapter extends AccountAdapter { .into(avatar); } - void setupActionListener(final AccountActionListener listener, final boolean blocked, - final int position) { + void setupActionListener(final AccountActionListener listener, final boolean blocked) { unblock.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - listener.onBlock(!blocked, id, position); + int position = getAdapterPosition(); + if (position != RecyclerView.NO_POSITION) { + listener.onBlock(!blocked, id, position); + } } }); avatar.setOnClickListener(new View.OnClickListener() { diff --git a/app/src/main/java/com/keylesspalace/tusky/MutesAdapter.java b/app/src/main/java/com/keylesspalace/tusky/MutesAdapter.java index 94125779..2513cac6 100644 --- a/app/src/main/java/com/keylesspalace/tusky/MutesAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/MutesAdapter.java @@ -21,11 +21,8 @@ class MutesAdapter extends AccountAdapter { private static final int VIEW_TYPE_MUTED_USER = 0; private static final int VIEW_TYPE_FOOTER = 1; - private Set unmutedAccountPositions; - MutesAdapter(AccountActionListener accountActionListener) { super(accountActionListener); - unmutedAccountPositions = new HashSet<>(); } @Override @@ -50,8 +47,7 @@ class MutesAdapter extends AccountAdapter { if (position < accountList.size()) { MutedUserViewHolder holder = (MutedUserViewHolder) viewHolder; holder.setupWithAccount(accountList.get(position)); - boolean muted = !unmutedAccountPositions.contains(position); - holder.setupActionListener(accountActionListener, muted, position); + holder.setupActionListener(accountActionListener, true, position); } } @@ -64,15 +60,6 @@ class MutesAdapter extends AccountAdapter { } } - void setMuted(boolean muted, int position) { - if (muted) { - unmutedAccountPositions.remove(position); - } else { - unmutedAccountPositions.add(position); - } - notifyItemChanged(position); - } - static class MutedUserViewHolder extends RecyclerView.ViewHolder { @BindView(R.id.muted_user_avatar) CircularImageView avatar; @BindView(R.id.muted_user_username) TextView username; diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2b275bdd..966853bf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -94,6 +94,7 @@ Clear Save Edit profile + Undo Share toot URL to… Share toot to… @@ -102,6 +103,8 @@ Toot! Sent! + User unblocked + User unmuted Which instance? What\'s happening?