Add filters to AccontTimelineFragment

This commit is contained in:
Grishka 2023-03-22 03:22:04 +03:00
parent 9a698fda18
commit e5d60050a2
3 changed files with 135 additions and 7 deletions

View File

@ -3,6 +3,8 @@ package org.joinmastodon.android.fragments;
import android.app.Activity; import android.app.Activity;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.accounts.GetAccountStatuses; import org.joinmastodon.android.api.requests.accounts.GetAccountStatuses;
@ -11,27 +13,34 @@ import org.joinmastodon.android.events.RemoveAccountPostsEvent;
import org.joinmastodon.android.events.StatusCreatedEvent; import org.joinmastodon.android.events.StatusCreatedEvent;
import org.joinmastodon.android.model.Account; import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.drawables.EmptyDrawable;
import org.joinmastodon.android.ui.views.FilterChipView;
import org.parceler.Parcels; import org.parceler.Parcels;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import androidx.recyclerview.widget.RecyclerView;
import me.grishka.appkit.api.SimpleCallback; import me.grishka.appkit.api.SimpleCallback;
import me.grishka.appkit.utils.MergeRecyclerAdapter;
import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
import me.grishka.appkit.utils.V;
public class AccountTimelineFragment extends StatusListFragment{ public class AccountTimelineFragment extends StatusListFragment{
private Account user; private Account user;
private GetAccountStatuses.Filter filter; private GetAccountStatuses.Filter filter;
private HorizontalScrollView filtersBar;
private FilterChipView defaultFilter, withRepliesFilter, mediaFilter;
public AccountTimelineFragment(){ public AccountTimelineFragment(){
setListLayoutId(R.layout.recycler_fragment_no_refresh); setListLayoutId(R.layout.recycler_fragment_no_refresh);
} }
public static AccountTimelineFragment newInstance(String accountID, Account profileAccount, GetAccountStatuses.Filter filter, boolean load){ public static AccountTimelineFragment newInstance(String accountID, Account profileAccount, boolean load){
AccountTimelineFragment f=new AccountTimelineFragment(); AccountTimelineFragment f=new AccountTimelineFragment();
Bundle args=new Bundle(); Bundle args=new Bundle();
args.putString("account", accountID); args.putString("account", accountID);
args.putParcelable("profileAccount", Parcels.wrap(profileAccount)); args.putParcelable("profileAccount", Parcels.wrap(profileAccount));
args.putString("filter", filter.toString());
if(!load) if(!load)
args.putBoolean("noAutoLoad", true); args.putBoolean("noAutoLoad", true);
args.putBoolean("__is_tab", true); args.putBoolean("__is_tab", true);
@ -41,9 +50,9 @@ public class AccountTimelineFragment extends StatusListFragment{
@Override @Override
public void onAttach(Activity activity){ public void onAttach(Activity activity){
super.onAttach(activity);
user=Parcels.unwrap(getArguments().getParcelable("profileAccount")); user=Parcels.unwrap(getArguments().getParcelable("profileAccount"));
filter=GetAccountStatuses.Filter.valueOf(getArguments().getString("filter")); filter=GetAccountStatuses.Filter.DEFAULT;
super.onAttach(activity);
} }
@Override @Override
@ -92,4 +101,77 @@ public class AccountTimelineFragment extends StatusListFragment{
protected void onRemoveAccountPostsEvent(RemoveAccountPostsEvent ev){ protected void onRemoveAccountPostsEvent(RemoveAccountPostsEvent ev){
// no-op // no-op
} }
@Override
protected RecyclerView.Adapter getAdapter(){
filtersBar=new HorizontalScrollView(getActivity());
LinearLayout filtersLayout=new LinearLayout(getActivity());
filtersBar.addView(filtersLayout);
filtersLayout.setOrientation(LinearLayout.HORIZONTAL);
filtersLayout.setPadding(V.dp(16), V.dp(16), V.dp(16), V.dp(8));
filtersLayout.setDividerDrawable(new EmptyDrawable(V.dp(8), 1));
filtersLayout.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
defaultFilter=new FilterChipView(getActivity());
defaultFilter.setText(R.string.posts);
defaultFilter.setTag(GetAccountStatuses.Filter.DEFAULT);
defaultFilter.setSelected(filter==GetAccountStatuses.Filter.DEFAULT);
defaultFilter.setOnClickListener(this::onFilterClick);
filtersLayout.addView(defaultFilter);
withRepliesFilter=new FilterChipView(getActivity());
withRepliesFilter.setText(R.string.posts_and_replies);
withRepliesFilter.setTag(GetAccountStatuses.Filter.INCLUDE_REPLIES);
withRepliesFilter.setSelected(filter==GetAccountStatuses.Filter.INCLUDE_REPLIES);
withRepliesFilter.setOnClickListener(this::onFilterClick);
filtersLayout.addView(withRepliesFilter);
mediaFilter=new FilterChipView(getActivity());
mediaFilter.setText(R.string.media);
mediaFilter.setTag(GetAccountStatuses.Filter.MEDIA);
mediaFilter.setSelected(filter==GetAccountStatuses.Filter.MEDIA);
mediaFilter.setOnClickListener(this::onFilterClick);
filtersLayout.addView(mediaFilter);
MergeRecyclerAdapter mergeAdapter=new MergeRecyclerAdapter();
mergeAdapter.addAdapter(new SingleViewRecyclerAdapter(filtersBar));
mergeAdapter.addAdapter(super.getAdapter());
return mergeAdapter;
}
@Override
protected int getMainAdapterOffset(){
return super.getMainAdapterOffset()+1;
}
private FilterChipView getViewForFilter(GetAccountStatuses.Filter filter){
return switch(filter){
case DEFAULT -> defaultFilter;
case INCLUDE_REPLIES -> withRepliesFilter;
case MEDIA -> mediaFilter;
default -> throw new IllegalStateException("Unexpected value: "+filter);
};
}
private void onFilterClick(View v){
GetAccountStatuses.Filter newFilter=(GetAccountStatuses.Filter) v.getTag();
if(newFilter==filter)
return;
// TODO maybe cache the filtered timelines that were already loaded?
if(currentRequest!=null){
currentRequest.cancel();
currentRequest=null;
}
getViewForFilter(filter).setSelected(false);
filter=newFilter;
v.setSelected(true);
data.clear();
preloadedData.clear();
int size=displayItems.size();
displayItems.clear();
adapter.notifyItemRangeRemoved(0, size);
loaded=false;
dataLoading=true;
doLoadData();
}
} }

View File

@ -18,7 +18,6 @@ import android.graphics.drawable.LayerDrawable;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Parcelable;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.style.ImageSpan; import android.text.style.ImageSpan;
@ -48,7 +47,6 @@ import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.accounts.GetAccountByID; import org.joinmastodon.android.api.requests.accounts.GetAccountByID;
import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships; import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships;
import org.joinmastodon.android.api.requests.accounts.GetAccountStatuses;
import org.joinmastodon.android.api.requests.accounts.GetOwnAccount; import org.joinmastodon.android.api.requests.accounts.GetOwnAccount;
import org.joinmastodon.android.api.requests.accounts.SetAccountFollowed; import org.joinmastodon.android.api.requests.accounts.SetAccountFollowed;
import org.joinmastodon.android.api.requests.accounts.UpdateAccountCredentials; import org.joinmastodon.android.api.requests.accounts.UpdateAccountCredentials;
@ -342,7 +340,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
args.putParcelable("profileAccount", Parcels.wrap(account)); args.putParcelable("profileAccount", Parcels.wrap(account));
args.putBoolean("__is_tab", true); args.putBoolean("__is_tab", true);
featuredFragment.setArguments(args); featuredFragment.setArguments(args);
timelineFragment=AccountTimelineFragment.newInstance(accountID, account, GetAccountStatuses.Filter.DEFAULT, true); timelineFragment=AccountTimelineFragment.newInstance(accountID, account, true);
aboutFragment=new ProfileAboutFragment(); aboutFragment=new ProfileAboutFragment();
aboutFragment.setFields(fields); aboutFragment.setFields(fields);
} }

View File

@ -0,0 +1,48 @@
package org.joinmastodon.android.ui.drawables;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class EmptyDrawable extends Drawable{
private final int width, height;
public EmptyDrawable(int width, int height){
this.width=width;
this.height=height;
}
@Override
public void draw(@NonNull Canvas canvas){
}
@Override
public void setAlpha(int alpha){
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter){
}
@Override
public int getOpacity(){
return PixelFormat.TRANSPARENT;
}
@Override
public int getIntrinsicWidth(){
return width;
}
@Override
public int getIntrinsicHeight(){
return height;
}
}