Blocking and muting now removes all statuses by that user in EVERY currently-loaded timeline.

This commit is contained in:
Vavassor 2017-04-21 23:16:05 -04:00
parent fcebbc2bdb
commit 5179d7e9b3
10 changed files with 137 additions and 71 deletions

View File

@ -28,6 +28,7 @@ import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
@ -54,7 +55,7 @@ import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class AccountActivity extends BaseActivity {
public class AccountActivity extends BaseActivity implements SFragment.OnUserRemovedListener {
private static final String TAG = "AccountActivity"; // logging tag
private String accountId;
@ -63,6 +64,7 @@ public class AccountActivity extends BaseActivity {
private boolean muting = false;
private boolean isSelf;
private TabLayout tabLayout;
private AccountPagerAdapter pagerAdapter;
private Account loadedAccount;
@BindView(R.id.account_locked) ImageView accountLockedView;
@ -80,8 +82,7 @@ public class AccountActivity extends BaseActivity {
accountId = intent.getStringExtra("id");
}
SharedPreferences preferences = getSharedPreferences(
getString(R.string.preferences_file_key), Context.MODE_PRIVATE);
SharedPreferences preferences = getPrivatePreferences();
String loggedInAccountId = preferences.getString("loggedInAccountId", null);
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
@ -142,6 +143,7 @@ public class AccountActivity extends BaseActivity {
// Setup the tabs and timeline pager.
AccountPagerAdapter adapter = new AccountPagerAdapter(getSupportFragmentManager(), this,
accountId);
pagerAdapter = adapter;
String[] pageTitles = {
getString(R.string.title_statuses),
getString(R.string.title_follows),
@ -165,6 +167,12 @@ public class AccountActivity extends BaseActivity {
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putString("accountId", accountId);
super.onSaveInstanceState(outState);
}
private void obtainAccount() {
mastodonAPI.account(accountId).enqueue(new Callback<Account>() {
@Override
@ -183,12 +191,6 @@ public class AccountActivity extends BaseActivity {
});
}
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putString("accountId", accountId);
super.onSaveInstanceState(outState);
}
private void onObtainAccountSuccess(Account account) {
loadedAccount = account;
@ -289,6 +291,16 @@ public class AccountActivity extends BaseActivity {
updateButtons();
}
@Override
public void onUserRemoved(String accountId) {
for (Fragment fragment : pagerAdapter.getRegisteredFragments()) {
if (fragment instanceof StatusRemoveListener) {
StatusRemoveListener listener = (StatusRemoveListener) fragment;
listener.removePostsByUser(accountId);
}
}
}
private void updateFollowButton(FloatingActionButton button) {
if (following) {
button.setImageResource(R.drawable.ic_person_minus_24px);

View File

@ -24,15 +24,20 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
class AccountPagerAdapter extends FragmentPagerAdapter {
private Context context;
private String accountId;
private String[] pageTitles;
private List<Fragment> registeredFragments;
AccountPagerAdapter(FragmentManager manager, Context context, String accountId) {
super(manager);
this.context = context;
this.accountId = accountId;
registeredFragments = new ArrayList<>();
}
void setPageTitles(String[] titles) {
@ -73,4 +78,21 @@ class AccountPagerAdapter extends FragmentPagerAdapter {
title.setText(pageTitles[position]);
return view;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.add(fragment);
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove((Fragment) object);
super.destroyItem(container, position, object);
}
List<Fragment> getRegisteredFragments() {
return registeredFragments;
}
}

View File

@ -17,5 +17,4 @@ package com.keylesspalace.tusky;
interface AdapterItemRemover {
void removeItem(int position);
void removeAllByAccountId(String accountId);
}

View File

@ -20,7 +20,6 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Bundle;
import android.os.PersistableBundle;
@ -43,12 +42,10 @@ import com.arlib.floatingsearchview.suggestions.SearchSuggestionsAdapter;
import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion;
import com.keylesspalace.tusky.entity.Account;
import com.mikepenz.google_material_typeface_library.GoogleMaterial;
import com.mikepenz.iconics.typeface.GenericFont;
import com.mikepenz.materialdrawer.AccountHeader;
import com.mikepenz.materialdrawer.AccountHeaderBuilder;
import com.mikepenz.materialdrawer.Drawer;
import com.mikepenz.materialdrawer.DrawerBuilder;
import com.mikepenz.materialdrawer.icons.MaterialDrawerFont;
import com.mikepenz.materialdrawer.model.DividerDrawerItem;
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
import com.mikepenz.materialdrawer.model.ProfileDrawerItem;
@ -69,8 +66,8 @@ import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class MainActivity extends BaseActivity {
private static final String TAG = "MainActivity"; // logging tag and Volley request tag
public class MainActivity extends BaseActivity implements SFragment.OnUserRemovedListener {
private static final String TAG = "MainActivity"; // logging tag
protected static int COMPOSE_RESULT = 1;
private String loggedInAccountId;
@ -518,12 +515,22 @@ public class MainActivity extends BaseActivity {
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
List<Fragment> fragments = getSupportFragmentManager().getFragments();
if (fragments != null) {
for (Fragment fragment : fragments) {
fragment.onRequestPermissionsResult(requestCode, permissions, grantResults);
TimelinePagerAdapter adapter = (TimelinePagerAdapter) viewPager.getAdapter();
for (Fragment fragment : adapter.getRegisteredFragments()) {
fragment.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
@Override
public void onUserRemoved(String accountId) {
TimelinePagerAdapter adapter = (TimelinePagerAdapter) viewPager.getAdapter();
for (Fragment fragment : adapter.getRegisteredFragments()) {
if (fragment instanceof StatusRemoveListener) {
StatusRemoveListener listener = (StatusRemoveListener) fragment;
listener.removePostsByUser(accountId);
}
}
}

View File

@ -39,7 +39,7 @@ import retrofit2.Callback;
import retrofit2.Response;
public class NotificationsFragment extends SFragment implements
SwipeRefreshLayout.OnRefreshListener, StatusActionListener,
SwipeRefreshLayout.OnRefreshListener, StatusActionListener, StatusRemoveListener,
NotificationsAdapter.NotificationActionListener {
private static final String TAG = "Notifications"; // logging tag
@ -57,11 +57,6 @@ public class NotificationsFragment extends SFragment implements
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@ -117,12 +112,6 @@ public class NotificationsFragment extends SFragment implements
return rootView;
}
@Override
public void onResume() {
super.onResume();
sendFetchNotificationsRequest();
}
@Override
public void onDestroy() {
super.onDestroy();
@ -142,13 +131,11 @@ public class NotificationsFragment extends SFragment implements
}
private void sendFetchNotificationsRequest(final String fromId, String uptoId) {
MastodonAPI api = ((BaseActivity) getActivity()).mastodonAPI;
if (fromId != null || adapter.getItemCount() <= 1) {
adapter.setFooterState(NotificationsAdapter.FooterState.LOADING);
}
listCall = api.notifications(fromId, uptoId, null);
listCall = mastodonAPI.notifications(fromId, uptoId, null);
listCall.enqueue(new Callback<List<Notification>>() {
@Override
@ -172,6 +159,10 @@ public class NotificationsFragment extends SFragment implements
sendFetchNotificationsRequest(null, null);
}
public void removePostsByUser(String accountId) {
adapter.removeAllByAccountId(accountId);
}
private static boolean findNotification(List<Notification> notifications, String id) {
for (Notification notification : notifications) {
if (notification.id.equals(id)) {

View File

@ -46,8 +46,14 @@ import retrofit2.Response;
* overlap functionality. So, I'm momentarily leaving it and hopefully working on those will clear
* up what needs to be where. */
public abstract class SFragment extends BaseFragment {
interface OnUserRemovedListener {
void onUserRemoved(String accountId);
}
protected String loggedInAccountId;
protected String loggedInUsername;
protected MastodonAPI mastodonAPI;
protected OnUserRemovedListener userRemovedListener;
protected static int COMPOSE_RESULT = 1;
@Override
@ -60,8 +66,12 @@ public abstract class SFragment extends BaseFragment {
loggedInUsername = preferences.getString("loggedInAccountUsername", null);
}
public MastodonAPI getApi() {
return ((BaseActivity) getActivity()).mastodonAPI;
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
BaseActivity activity = (BaseActivity) getActivity();
mastodonAPI = activity.mastodonAPI;
userRemovedListener = (OnUserRemovedListener) activity;
}
protected void reply(Status status) {
@ -84,8 +94,7 @@ public abstract class SFragment extends BaseFragment {
startActivityForResult(intent, COMPOSE_RESULT);
}
public void onSuccessfulStatus() {
}
public void onSuccessfulStatus() {}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
@ -115,16 +124,14 @@ public abstract class SFragment extends BaseFragment {
}
@Override
public void onFailure(Call<Status> call, Throwable t) {
}
public void onFailure(Call<Status> call, Throwable t) {}
};
Call<Status> call;
if (reblog) {
call = getApi().reblogStatus(id);
call = mastodonAPI.reblogStatus(id);
} else {
call = getApi().unreblogStatus(id);
call = mastodonAPI.unreblogStatus(id);
}
call.enqueue(cb);
callList.add(call);
@ -149,23 +156,21 @@ public abstract class SFragment extends BaseFragment {
}
@Override
public void onFailure(Call<Status> call, Throwable t) {
}
public void onFailure(Call<Status> call, Throwable t) {}
};
Call<Status> call;
if (favourite) {
call = getApi().favouriteStatus(id);
call = mastodonAPI.favouriteStatus(id);
} else {
call = getApi().unfavouriteStatus(id);
call = mastodonAPI.unfavouriteStatus(id);
}
call.enqueue(cb);
callList.add(call);
}
private void mute(String id) {
Call<Relationship> call = getApi().muteAccount(id);
Call<Relationship> call = mastodonAPI.muteAccount(id);
call.enqueue(new Callback<Relationship>() {
@Override
public void onResponse(Call<Relationship> call, Response<Relationship> response) {}
@ -174,10 +179,11 @@ public abstract class SFragment extends BaseFragment {
public void onFailure(Call<Relationship> call, Throwable t) {}
});
callList.add(call);
userRemovedListener.onUserRemoved(id);
}
private void block(String id) {
Call<Relationship> call = getApi().blockAccount(id);
Call<Relationship> call = mastodonAPI.blockAccount(id);
call.enqueue(new Callback<Relationship>() {
@Override
public void onResponse(Call<Relationship> call, retrofit2.Response<Relationship> response) {}
@ -186,10 +192,11 @@ public abstract class SFragment extends BaseFragment {
public void onFailure(Call<Relationship> call, Throwable t) {}
});
callList.add(call);
userRemovedListener.onUserRemoved(id);
}
private void delete(String id) {
Call<ResponseBody> call = getApi().deleteStatus(id);
Call<ResponseBody> call = mastodonAPI.deleteStatus(id);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {}
@ -242,12 +249,10 @@ public abstract class SFragment extends BaseFragment {
}
case R.id.status_mute: {
mute(accountId);
adapter.removeAllByAccountId(accountId);
return true;
}
case R.id.status_block: {
block(accountId);
adapter.removeAllByAccountId(accountId);
return true;
}
case R.id.status_report: {

View File

@ -0,0 +1,5 @@
package com.keylesspalace.tusky;
interface StatusRemoveListener {
void removePostsByUser(String accountId);
}

View File

@ -142,7 +142,7 @@ class TimelineAdapter extends RecyclerView.Adapter implements AdapterItemRemover
notifyItemRemoved(position);
}
public void removeAllByAccountId(String accountId) {
void removeAllByAccountId(String accountId) {
for (int i = 0; i < statuses.size();) {
Status status = statuses.get(i);
if (accountId.equals(status.account.id)) {

View File

@ -39,7 +39,7 @@ import retrofit2.Call;
import retrofit2.Callback;
public class TimelineFragment extends SFragment implements
SwipeRefreshLayout.OnRefreshListener, StatusActionListener {
SwipeRefreshLayout.OnRefreshListener, StatusActionListener, StatusRemoveListener {
private static final String TAG = "Timeline"; // logging tag
private Call<List<Status>> listCall;
@ -145,7 +145,7 @@ public class TimelineFragment extends SFragment implements
/* This is delayed until onActivityCreated solely because MainActivity.composeButton isn't
* guaranteed to be set until then. */
if (followButtonPresent()) {
if (composeButtonPresent()) {
/* Use a modified scroll listener that both loads more statuses as it goes, and hides
* the follow button on down-scroll. */
MainActivity activity = (MainActivity) getActivity();
@ -202,7 +202,7 @@ public class TimelineFragment extends SFragment implements
return kind != Kind.TAG && kind != Kind.FAVOURITES;
}
private boolean followButtonPresent() {
private boolean composeButtonPresent() {
return kind != Kind.TAG && kind != Kind.FAVOURITES && kind != Kind.USER;
}
@ -212,8 +212,6 @@ public class TimelineFragment extends SFragment implements
}
private void sendFetchTimelineRequest(@Nullable final String fromId, @Nullable String uptoId) {
MastodonAPI api = ((BaseActivity) getActivity()).mastodonAPI;
if (fromId != null || adapter.getItemCount() <= 1) {
adapter.setFooterState(TimelineAdapter.FooterState.LOADING);
}
@ -237,27 +235,27 @@ public class TimelineFragment extends SFragment implements
switch (kind) {
default:
case HOME: {
listCall = api.homeTimeline(fromId, uptoId, null);
listCall = mastodonAPI.homeTimeline(fromId, uptoId, null);
break;
}
case PUBLIC_FEDERATED: {
listCall = api.publicTimeline(null, fromId, uptoId, null);
listCall = mastodonAPI.publicTimeline(null, fromId, uptoId, null);
break;
}
case PUBLIC_LOCAL: {
listCall = api.publicTimeline(true, fromId, uptoId, null);
listCall = mastodonAPI.publicTimeline(true, fromId, uptoId, null);
break;
}
case TAG: {
listCall = api.hashtagTimeline(hashtagOrId, null, fromId, uptoId, null);
listCall = mastodonAPI.hashtagTimeline(hashtagOrId, null, fromId, uptoId, null);
break;
}
case USER: {
listCall = api.accountStatuses(hashtagOrId, fromId, uptoId, null);
listCall = mastodonAPI.accountStatuses(hashtagOrId, fromId, uptoId, null);
break;
}
case FAVOURITES: {
listCall = api.favourites(fromId, uptoId, null);
listCall = mastodonAPI.favourites(fromId, uptoId, null);
break;
}
}
@ -269,6 +267,10 @@ public class TimelineFragment extends SFragment implements
sendFetchTimelineRequest(null, null);
}
public void removePostsByUser(String accountId) {
adapter.removeAllByAccountId(accountId);
}
private static boolean findStatus(List<Status> statuses, String id) {
for (Status status : statuses) {
if (status.id.equals(id)) {

View File

@ -20,21 +20,31 @@ import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
class TimelinePagerAdapter extends FragmentPagerAdapter {
private Fragment currentFragment;
private int currentFragmentIndex;
private List<Fragment> registeredFragments;
TimelinePagerAdapter(FragmentManager manager) {
super(manager);
currentFragmentIndex = 0;
registeredFragments = new ArrayList<>();
}
public Fragment getCurrentFragment() {
return currentFragment;
Fragment getCurrentFragment() {
return registeredFragments.get(currentFragmentIndex);
}
List<Fragment> getRegisteredFragments() {
return registeredFragments;
}
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
if (getCurrentFragment() != object) {
currentFragment = ((Fragment) object);
if (position != currentFragmentIndex) {
currentFragmentIndex = position;
}
super.setPrimaryItem(container, position, object);
}
@ -69,4 +79,17 @@ class TimelinePagerAdapter extends FragmentPagerAdapter {
public CharSequence getPageTitle(int position) {
return null;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.add(fragment);
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove((Fragment) object);
super.destroyItem(container, position, object);
}
}