Add filters to AccontTimelineFragment
This commit is contained in:
parent
9a698fda18
commit
e5d60050a2
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue