aboutsummaryrefslogtreecommitdiff
path: root/WordPress/src/main/java/org/wordpress/android/ui/people/PeopleListFragment.java
diff options
context:
space:
mode:
Diffstat (limited to 'WordPress/src/main/java/org/wordpress/android/ui/people/PeopleListFragment.java')
-rw-r--r--WordPress/src/main/java/org/wordpress/android/ui/people/PeopleListFragment.java432
1 files changed, 432 insertions, 0 deletions
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/people/PeopleListFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/people/PeopleListFragment.java
new file mode 100644
index 000000000..ca878b3cf
--- /dev/null
+++ b/WordPress/src/main/java/org/wordpress/android/ui/people/PeopleListFragment.java
@@ -0,0 +1,432 @@
+package org.wordpress.android.ui.people;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import org.wordpress.android.R;
+import org.wordpress.android.WordPress;
+import org.wordpress.android.datasets.PeopleTable;
+import org.wordpress.android.models.Blog;
+import org.wordpress.android.models.FilterCriteria;
+import org.wordpress.android.models.PeopleListFilter;
+import org.wordpress.android.models.Person;
+import org.wordpress.android.ui.EmptyViewMessageType;
+import org.wordpress.android.ui.FilteredRecyclerView;
+import org.wordpress.android.ui.prefs.AppPrefs;
+import org.wordpress.android.util.AppLog;
+import org.wordpress.android.util.GravatarUtils;
+import org.wordpress.android.util.NetworkUtils;
+import org.wordpress.android.util.StringUtils;
+import org.wordpress.android.widgets.WPNetworkImageView;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class PeopleListFragment extends Fragment {
+ private static final String ARG_LOCAL_TABLE_BLOG_ID = "local_table_blog_id";
+
+ private int mLocalTableBlogID;
+ private OnPersonSelectedListener mOnPersonSelectedListener;
+ private OnFetchPeopleListener mOnFetchPeopleListener;
+
+ private FilteredRecyclerView mFilteredRecyclerView;
+ private PeopleListFilter mPeopleListFilter;
+
+ public static PeopleListFragment newInstance(int localTableBlogID) {
+ PeopleListFragment peopleListFragment = new PeopleListFragment();
+ Bundle bundle = new Bundle();
+ bundle.putInt(ARG_LOCAL_TABLE_BLOG_ID, localTableBlogID);
+ peopleListFragment.setArguments(bundle);
+ return peopleListFragment;
+ }
+
+ public void setOnPersonSelectedListener(OnPersonSelectedListener listener) {
+ mOnPersonSelectedListener = listener;
+ }
+
+ public void setOnFetchPeopleListener(OnFetchPeopleListener listener) {
+ mOnFetchPeopleListener = listener;
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ mOnPersonSelectedListener = null;
+ mOnFetchPeopleListener = null;
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ inflater.inflate(R.menu.people_list, menu);
+ super.onCreateOptionsMenu(menu, inflater);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ setHasOptionsMenu(true);
+
+ final ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.people_list_fragment, container, false);
+
+ mLocalTableBlogID = getArguments().getInt(ARG_LOCAL_TABLE_BLOG_ID);
+ final Blog blog = WordPress.getBlog(mLocalTableBlogID);
+ final boolean isPrivate = blog != null && blog.isPrivate();
+
+ mFilteredRecyclerView = (FilteredRecyclerView) rootView.findViewById(R.id.filtered_recycler_view);
+ mFilteredRecyclerView.addItemDecoration(new PeopleItemDecoration(getActivity(), R.drawable.people_list_divider));
+ mFilteredRecyclerView.setLogT(AppLog.T.PEOPLE);
+ mFilteredRecyclerView.setSwipeToRefreshEnabled(false);
+
+ // the following will change the look and feel of the toolbar to match the current design
+ mFilteredRecyclerView.setToolbarBackgroundColor(ContextCompat.getColor(getActivity(), R.color.blue_medium));
+ mFilteredRecyclerView.setToolbarSpinnerTextColor(ContextCompat.getColor(getActivity(), R.color.white));
+ mFilteredRecyclerView.setToolbarSpinnerDrawable(R.drawable.arrow);
+ mFilteredRecyclerView.setToolbarLeftAndRightPadding(
+ getResources().getDimensionPixelSize(R.dimen.margin_filter_spinner),
+ getResources().getDimensionPixelSize(R.dimen.margin_none));
+
+ mFilteredRecyclerView.setFilterListener(new FilteredRecyclerView.FilterListener() {
+ @Override
+ public List<FilterCriteria> onLoadFilterCriteriaOptions(boolean refresh) {
+ ArrayList<FilterCriteria> list = new ArrayList<>();
+ Collections.addAll(list, PeopleListFilter.values());
+ // Only a private blog can have viewers
+ if (!isPrivate) {
+ list.remove(PeopleListFilter.VIEWERS);
+ }
+ return list;
+ }
+
+ @Override
+ public void onLoadFilterCriteriaOptionsAsync(FilteredRecyclerView.FilterCriteriaAsyncLoaderListener listener, boolean refresh) {
+ // no-op
+ }
+
+ @Override
+ public FilterCriteria onRecallSelection() {
+ mPeopleListFilter = AppPrefs.getPeopleListFilter();
+
+ // if viewers is not available for this blog, set the filter to TEAM
+ if (mPeopleListFilter == PeopleListFilter.VIEWERS && !isPrivate) {
+ mPeopleListFilter = PeopleListFilter.TEAM;
+ AppPrefs.setPeopleListFilter(mPeopleListFilter);
+ }
+ return mPeopleListFilter;
+ }
+
+ @Override
+ public void onLoadData() {
+ updatePeople(false);
+ }
+
+ @Override
+ public void onFilterSelected(int position, FilterCriteria criteria) {
+ mPeopleListFilter = (PeopleListFilter) criteria;
+ AppPrefs.setPeopleListFilter(mPeopleListFilter);
+ }
+
+ @Override
+ public String onShowEmptyViewMessage(EmptyViewMessageType emptyViewMsgType) {
+ int stringId = 0;
+ switch (emptyViewMsgType) {
+ case LOADING:
+ stringId = R.string.people_fetching;
+ break;
+ case NETWORK_ERROR:
+ stringId = R.string.no_network_message;
+ break;
+ case NO_CONTENT:
+ switch (mPeopleListFilter) {
+ case TEAM:
+ stringId = R.string.people_empty_list_filtered_users;
+ break;
+ case FOLLOWERS:
+ stringId = R.string.people_empty_list_filtered_followers;
+ break;
+ case EMAIL_FOLLOWERS:
+ stringId = R.string.people_empty_list_filtered_email_followers;
+ break;
+ case VIEWERS:
+ stringId = R.string.people_empty_list_filtered_viewers;
+ break;
+ }
+ break;
+ case GENERIC_ERROR:
+ switch (mPeopleListFilter) {
+ case TEAM:
+ stringId = R.string.error_fetch_users_list;
+ break;
+ case FOLLOWERS:
+ stringId = R.string.error_fetch_followers_list;
+ break;
+ case EMAIL_FOLLOWERS:
+ stringId = R.string.error_fetch_email_followers_list;
+ break;
+ case VIEWERS:
+ stringId = R.string.error_fetch_viewers_list;
+ break;
+ }
+ break;
+ }
+ return getString(stringId);
+ }
+
+ @Override
+ public void onShowCustomEmptyView(EmptyViewMessageType emptyViewMsgType) {
+
+ }
+ });
+
+ return rootView;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ updatePeople(false);
+ }
+
+ private void updatePeople(boolean loadMore) {
+ if (!NetworkUtils.isNetworkAvailable(getActivity())) {
+ mFilteredRecyclerView.updateEmptyView(EmptyViewMessageType.NETWORK_ERROR);
+ mFilteredRecyclerView.setRefreshing(false);
+ return;
+ }
+
+ if (mOnFetchPeopleListener != null) {
+ if (loadMore) {
+ boolean isFetching = mOnFetchPeopleListener.onFetchMorePeople(mPeopleListFilter);
+ if (isFetching) {
+ mFilteredRecyclerView.showLoadingProgress();
+ }
+ } else {
+ boolean isFetching = mOnFetchPeopleListener.onFetchFirstPage(mPeopleListFilter);
+ if (isFetching) {
+ mFilteredRecyclerView.updateEmptyView(EmptyViewMessageType.LOADING);
+ } else {
+ mFilteredRecyclerView.hideEmptyView();
+ mFilteredRecyclerView.setRefreshing(false);
+ }
+ refreshPeopleList(isFetching);
+ }
+ }
+ }
+
+ public void refreshPeopleList(boolean isFetching) {
+ if (!isAdded()) return;
+
+ List<Person> peopleList;
+ switch (mPeopleListFilter) {
+ case TEAM:
+ peopleList = PeopleTable.getUsers(mLocalTableBlogID);
+ break;
+ case FOLLOWERS:
+ peopleList = PeopleTable.getFollowers(mLocalTableBlogID);
+ break;
+ case EMAIL_FOLLOWERS:
+ peopleList = PeopleTable.getEmailFollowers(mLocalTableBlogID);
+ break;
+ case VIEWERS:
+ peopleList = PeopleTable.getViewers(mLocalTableBlogID);
+ break;
+ default:
+ peopleList = new ArrayList<>();
+ break;
+ }
+ PeopleAdapter peopleAdapter = (PeopleAdapter) mFilteredRecyclerView.getAdapter();
+ if (peopleAdapter == null) {
+ peopleAdapter = new PeopleAdapter(getActivity(), peopleList);
+ mFilteredRecyclerView.setAdapter(peopleAdapter);
+ } else {
+ peopleAdapter.setPeopleList(peopleList);
+ }
+
+ if (!peopleList.isEmpty()) {
+ // if the list is not empty, don't show any message
+ mFilteredRecyclerView.hideEmptyView();
+ } else if (!isFetching) {
+ // if we are not fetching and list is empty, show no content message
+ mFilteredRecyclerView.updateEmptyView(EmptyViewMessageType.NO_CONTENT);
+ }
+ }
+
+ public void fetchingRequestFinished(PeopleListFilter filter, boolean isFirstPage, boolean isSuccessful) {
+ if (mPeopleListFilter == filter) {
+ if (isFirstPage) {
+ mFilteredRecyclerView.setRefreshing(false);
+ if (!isSuccessful) {
+ mFilteredRecyclerView.updateEmptyView(EmptyViewMessageType.GENERIC_ERROR);
+ }
+ } else {
+ mFilteredRecyclerView.hideLoadingProgress();
+ }
+ }
+ }
+
+ // Container Activity must implement this interface
+ public interface OnPersonSelectedListener {
+ void onPersonSelected(Person person);
+ }
+
+ public interface OnFetchPeopleListener {
+ boolean onFetchFirstPage(PeopleListFilter filter);
+
+ boolean onFetchMorePeople(PeopleListFilter filter);
+ }
+
+ public class PeopleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
+ private final LayoutInflater mInflater;
+ private List<Person> mPeopleList;
+ private int mAvatarSz;
+
+ public PeopleAdapter(Context context, List<Person> peopleList) {
+ mAvatarSz = context.getResources().getDimensionPixelSize(R.dimen.people_avatar_sz);
+ mInflater = LayoutInflater.from(context);
+ mPeopleList = peopleList;
+ setHasStableIds(true);
+ }
+
+ public void setPeopleList(List<Person> peopleList) {
+ mPeopleList = peopleList;
+ notifyDataSetChanged();
+ }
+
+ public Person getPerson(int position) {
+ if (mPeopleList == null) {
+ return null;
+ }
+ return mPeopleList.get(position);
+ }
+
+ @Override
+ public int getItemCount() {
+ if (mPeopleList == null) {
+ return 0;
+ }
+ return mPeopleList.size();
+ }
+
+ @Override
+ public long getItemId(int position) {
+ Person person = getPerson(position);
+ if (person == null) {
+ return -1;
+ }
+ return person.getPersonID();
+ }
+
+ @Override
+ public PeopleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View view = mInflater.inflate(R.layout.people_list_row, parent, false);
+
+ return new PeopleViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
+ PeopleViewHolder peopleViewHolder = (PeopleViewHolder) holder;
+ final Person person = getPerson(position);
+
+ if (person != null) {
+ String avatarUrl = GravatarUtils.fixGravatarUrl(person.getAvatarUrl(), mAvatarSz);
+ peopleViewHolder.imgAvatar.setImageUrl(avatarUrl, WPNetworkImageView.ImageType.AVATAR);
+ peopleViewHolder.txtDisplayName.setText(StringUtils.unescapeHTML(person.getDisplayName()));
+ if (person.getRole() != null) {
+ peopleViewHolder.txtRole.setVisibility(View.VISIBLE);
+ peopleViewHolder.txtRole.setText(StringUtils.capitalize(person.getRole().toDisplayString()));
+ } else {
+ peopleViewHolder.txtRole.setVisibility(View.GONE);
+ }
+ if (!person.getUsername().isEmpty()) {
+ peopleViewHolder.txtUsername.setVisibility(View.VISIBLE);
+ peopleViewHolder.txtUsername.setText(String.format("@%s", person.getUsername()));
+ } else {
+ peopleViewHolder.txtUsername.setVisibility(View.GONE);
+ }
+ if (person.getPersonType() == Person.PersonType.USER
+ || person.getPersonType() == Person.PersonType.VIEWER) {
+ peopleViewHolder.txtSubscribed.setVisibility(View.GONE);
+ } else {
+ peopleViewHolder.txtSubscribed.setVisibility(View.VISIBLE);
+ String dateSubscribed = SimpleDateFormat.getDateInstance().format(person.getDateSubscribed());
+ String dateText = getString(R.string.follower_subscribed_since, dateSubscribed);
+ peopleViewHolder.txtSubscribed.setText(dateText);
+ }
+ }
+
+ // end of list is reached
+ if (position == getItemCount() - 1) {
+ updatePeople(true);
+ }
+ }
+
+ public class PeopleViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
+ private final WPNetworkImageView imgAvatar;
+ private final TextView txtDisplayName;
+ private final TextView txtUsername;
+ private final TextView txtRole;
+ private final TextView txtSubscribed;
+
+ public PeopleViewHolder(View view) {
+ super(view);
+ imgAvatar = (WPNetworkImageView) view.findViewById(R.id.person_avatar);
+ txtDisplayName = (TextView) view.findViewById(R.id.person_display_name);
+ txtUsername = (TextView) view.findViewById(R.id.person_username);
+ txtRole = (TextView) view.findViewById(R.id.person_role);
+ txtSubscribed = (TextView) view.findViewById(R.id.follower_subscribed_date);
+
+ itemView.setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (mOnPersonSelectedListener != null) {
+ Person person = getPerson(getAdapterPosition());
+ mOnPersonSelectedListener.onPersonSelected(person);
+ }
+ }
+ }
+ }
+
+ // Taken from http://stackoverflow.com/a/27037230
+ private class PeopleItemDecoration extends RecyclerView.ItemDecoration {
+ private Drawable mDivider;
+
+ // use a custom drawable
+ public PeopleItemDecoration(Context context, int resId) {
+ mDivider = ContextCompat.getDrawable(context, resId);
+ }
+
+ @Override
+ public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
+ int left = parent.getPaddingLeft();
+ int right = parent.getWidth() - parent.getPaddingRight();
+
+ int childCount = parent.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = parent.getChildAt(i);
+
+ RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
+
+ int top = child.getBottom() + params.bottomMargin;
+ int bottom = top + mDivider.getIntrinsicHeight();
+
+ mDivider.setBounds(left, top, right, bottom);
+ mDivider.draw(c);
+ }
+ }
+ }
+}