Profile about tab

This commit is contained in:
Grishka
2022-02-09 17:53:27 +03:00
parent 90bd7baa94
commit b8e3426a1e
12 changed files with 235 additions and 37 deletions

View File

@@ -0,0 +1,123 @@
package org.joinmastodon.android.fragments;
import android.app.Fragment;
import android.graphics.Canvas;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.widget.TextView;
import org.joinmastodon.android.R;
import org.joinmastodon.android.model.AccountField;
import org.joinmastodon.android.ui.views.LinkedTextView;
import java.util.Collections;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import me.grishka.appkit.imageloader.ListImageLoaderWrapper;
import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.UsableRecyclerView;
public class ProfileAboutFragment extends Fragment{
public UsableRecyclerView list;
private List<AccountField> fields=Collections.emptyList();
private AboutAdapter adapter;
private Paint dividerPaint=new Paint();
public void setFields(List<AccountField> fields){
this.fields=fields;
if(adapter!=null)
adapter.notifyDataSetChanged();
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState){
list=new UsableRecyclerView(getActivity());
list.setId(R.id.list);
list.setLayoutManager(new LinearLayoutManager(getActivity()));
list.setAdapter(adapter=new AboutAdapter());
int pad=V.dp(16);
list.setPadding(pad, pad, pad, pad);
list.setClipToPadding(false);
dividerPaint.setStyle(Paint.Style.STROKE);
dividerPaint.setStrokeWidth(V.dp(1));
dividerPaint.setColor(getResources().getColor(R.color.gray_200));
list.addItemDecoration(new RecyclerView.ItemDecoration(){
@Override
public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state){
for(int i=0;i<parent.getChildCount();i++){
View item=parent.getChildAt(i);
int pos=parent.getChildAdapterPosition(item);
if(pos<fields.size()-1){
c.drawLine(item.getLeft(), item.getBottom(), item.getRight(), item.getBottom(), dividerPaint);
}
}
}
});
return list;
}
private class AboutAdapter extends UsableRecyclerView.Adapter<AboutViewHolder>{
public AboutAdapter(){
super(null);
}
@NonNull
@Override
public AboutViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
return new AboutViewHolder();
}
@Override
public void onBindViewHolder(AboutViewHolder holder, int position){
holder.bind(fields.get(position));
super.onBindViewHolder(holder, position);
}
@Override
public int getItemCount(){
return fields.size();
}
}
private class AboutViewHolder extends BindableViewHolder<AccountField>{
private TextView title;
private LinkedTextView value;
private ShapeDrawable background=new ShapeDrawable();
public AboutViewHolder(){
super(getActivity(), R.layout.item_profile_about, list);
title=findViewById(R.id.title);
value=findViewById(R.id.value);
background.getPaint().setColor(getResources().getColor(R.color.gray_50));
itemView.setBackground(background);
}
@Override
public void onBind(AccountField item){
title.setText(item.name);
value.setText(item.parsedValue);
boolean first=getAbsoluteAdapterPosition()==0, last=getAbsoluteAdapterPosition()==fields.size()-1;
float radius=V.dp(10);
float[] rad=new float[8];
if(first)
rad[0]=rad[1]=rad[2]=rad[3]=radius;
if(last)
rad[4]=rad[5]=rad[6]=rad[7]=radius;
background.setShape(new RoundRectShape(rad, null, null));
itemView.invalidateOutline();
}
}
}

View File

@@ -4,7 +4,6 @@ import android.app.Activity;
import android.app.Fragment;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Matrix;
import android.graphics.Outline;
import android.os.Bundle;
import android.util.Log;
@@ -28,6 +27,7 @@ import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships;
import org.joinmastodon.android.api.requests.accounts.GetAccountStatuses;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.AccountField;
import org.joinmastodon.android.model.Relationship;
import org.joinmastodon.android.ui.drawables.CoverOverlayGradientDrawable;
import org.joinmastodon.android.ui.tabs.TabLayout;
@@ -38,6 +38,12 @@ import org.joinmastodon.android.ui.views.CoverImageView;
import org.joinmastodon.android.ui.views.NestedRecyclerScrollView;
import org.parceler.Parcels;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -63,16 +69,18 @@ public class ProfileFragment extends LoaderFragment{
private ViewPager2 pager;
private NestedRecyclerScrollView scrollView;
private AccountTimelineFragment postsFragment, postsWithRepliesFragment, mediaFragment;
private ProfileAboutFragment aboutFragment;
private TabLayout tabbar;
private SwipeRefreshLayout refreshLayout;
private CoverOverlayGradientDrawable coverGradient=new CoverOverlayGradientDrawable();
private Matrix coverMatrix=new Matrix();
private float titleTransY;
private Account account;
private String accountID;
private Relationship relationship;
private int statusBarHeight;
private boolean isOwnProfile;
private ArrayList<AccountField> fields=new ArrayList<>();
public ProfileFragment(){
super(R.layout.loader_fragment_overlay_toolbar);
@@ -123,9 +131,11 @@ public class ProfileFragment extends LoaderFragment{
if(getArguments().containsKey("profileAccount")){
account=Parcels.unwrap(getArguments().getParcelable("profileAccount"));
isOwnProfile=AccountSessionManager.getInstance().isSelf(accountID, account);
bindHeaderView();
dataLoaded();
loadRelationship();
if(!isOwnProfile)
loadRelationship();
}
scrollView.setScrollableChildSupplier(this::getScrollableRecyclerView);
@@ -157,6 +167,12 @@ public class ProfileFragment extends LoaderFragment{
}).attach();
cover.setForeground(coverGradient);
cover.setOutlineProvider(new ViewOutlineProvider(){
@Override
public void getOutline(View view, Outline outline){
outline.setEmpty();
}
});
return sizeWrapper;
}
@@ -184,9 +200,12 @@ public class ProfileFragment extends LoaderFragment{
public void onPageSelected(int position){
if(position==0)
return;
BaseRecyclerFragment<?> page=getFragmentForPage(position);
if(!page.loaded && !page.isDataLoading())
page.loadData();
Fragment _page=getFragmentForPage(position);
if(_page instanceof BaseRecyclerFragment){
BaseRecyclerFragment page=(BaseRecyclerFragment) _page;
if(!page.loaded && !page.isDataLoading())
page.loadData();
}
}
});
return true;
@@ -235,6 +254,22 @@ public class ProfileFragment extends LoaderFragment{
}else{
actionButton.setVisibility(View.GONE);
}
fields.clear();
AccountField joined=new AccountField();
joined.name=getString(R.string.profile_joined);
joined.parsedValue=joined.value=DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).format(LocalDateTime.ofInstant(account.createdAt, ZoneId.systemDefault()));
fields.add(joined);
for(AccountField field:account.fields){
field.parsedValue=HtmlParser.parse(field.value, account.emojis);
fields.add(field);
}
if(aboutFragment!=null){
aboutFragment.setFields(fields);
}
}
private void updateToolbar(){
@@ -334,11 +369,12 @@ public class ProfileFragment extends LoaderFragment{
}
}
private BaseRecyclerFragment<?> getFragmentForPage(int page){
private Fragment getFragmentForPage(int page){
return switch(page){
case 0 -> postsFragment;
case 1 -> postsWithRepliesFragment;
case 2 -> mediaFragment;
case 3 -> aboutFragment;
default -> throw new IllegalStateException();
};
}
@@ -363,6 +399,11 @@ public class ProfileFragment extends LoaderFragment{
case 0 -> postsFragment=AccountTimelineFragment.newInstance(accountID, account, GetAccountStatuses.Filter.DEFAULT, true);
case 1 -> postsWithRepliesFragment=AccountTimelineFragment.newInstance(accountID, account, GetAccountStatuses.Filter.INCLUDE_REPLIES, false);
case 2 -> mediaFragment=AccountTimelineFragment.newInstance(accountID, account, GetAccountStatuses.Filter.MEDIA, false);
case 3 -> {
aboutFragment=new ProfileAboutFragment();
aboutFragment.setFields(fields);
yield aboutFragment;
}
default -> throw new IllegalArgumentException();
};
getChildFragmentManager().beginTransaction().add(holder.itemView.getId(), fragment).commit();
@@ -370,7 +411,7 @@ public class ProfileFragment extends LoaderFragment{
@Override
public int getItemCount(){
return 3;
return 4;
}
@Override