aboutsummaryrefslogtreecommitdiff
path: root/WordPress/src/main/java/org/wordpress/android/ui/stats/StatsFollowersFragment.java
diff options
context:
space:
mode:
Diffstat (limited to 'WordPress/src/main/java/org/wordpress/android/ui/stats/StatsFollowersFragment.java')
-rw-r--r--WordPress/src/main/java/org/wordpress/android/ui/stats/StatsFollowersFragment.java449
1 files changed, 449 insertions, 0 deletions
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/StatsFollowersFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/stats/StatsFollowersFragment.java
new file mode 100644
index 000000000..dc15eab17
--- /dev/null
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/StatsFollowersFragment.java
@@ -0,0 +1,449 @@
+package org.wordpress.android.ui.stats;
+
+import android.app.Activity;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.LinearLayout;
+
+import org.wordpress.android.R;
+import org.wordpress.android.WordPress;
+import org.wordpress.android.ui.reader.ReaderActivityLauncher;
+import org.wordpress.android.ui.stats.models.FollowDataModel;
+import org.wordpress.android.ui.stats.models.FollowerModel;
+import org.wordpress.android.ui.stats.models.FollowersModel;
+import org.wordpress.android.ui.stats.service.StatsService;
+import org.wordpress.android.util.DisplayUtils;
+import org.wordpress.android.util.FormatUtils;
+import org.wordpress.android.util.GravatarUtils;
+import org.wordpress.android.util.UrlUtils;
+import org.wordpress.android.widgets.WPNetworkImageView;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadPoolExecutor;
+
+
+public class StatsFollowersFragment extends StatsAbstractListFragment {
+ public static final String TAG = StatsFollowersFragment.class.getSimpleName();
+
+ private static final String ARG_REST_RESPONSE_FOLLOWERS_EMAIL = "ARG_REST_RESPONSE_FOLLOWERS_EMAIL";
+ private final Map<String, Integer> userBlogs = new HashMap<>();
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View view = super.onCreateView(inflater, container, savedInstanceState);
+
+ Resources res = container.getContext().getResources();
+
+ String[] titles = {
+ res.getString(R.string.stats_followers_wpcom_selector),
+ res.getString(R.string.stats_followers_email_selector),
+ };
+
+
+ setupTopModulePager(inflater, container, view, titles);
+
+ mTopPagerContainer.setVisibility(View.VISIBLE);
+ mTotalsLabel.setVisibility(View.VISIBLE);
+ mTotalsLabel.setText("");
+
+ return view;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Single background thread used to create the blogs list in BG
+ ThreadPoolExecutor blogsListCreatorExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
+ blogsListCreatorExecutor.submit(new Thread() {
+ @Override
+ public void run() {
+ // Read all the dotcomBlog blogs and get the list of home URLs.
+ // This will be used later to check if the user is a member of followers blog marked as private.
+ List<Map<String, Object>> dotComUserBlogs = WordPress.wpDB.getBlogsBy("dotcomFlag=1",
+ new String[]{"homeURL"});
+ for (Map<String, Object> blog : dotComUserBlogs) {
+ if (blog != null && blog.get("homeURL") != null && blog.get("blogId") != null) {
+ String normURL = normalizeAndRemoveScheme(blog.get("homeURL").toString());
+ Integer blogID = (Integer) blog.get("blogId");
+ userBlogs.put(normURL, blogID);
+ }
+ }
+ }
+ });
+ }
+
+ private FollowersModel mFollowersWPCOM;
+ private FollowersModel mFollowersEmail;
+
+ @Override
+ protected boolean hasDataAvailable() {
+ return mFollowersWPCOM != null || mFollowersEmail != null;
+ }
+ @Override
+ protected void saveStatsData(Bundle outState) {
+ if (mFollowersWPCOM != null) {
+ outState.putSerializable(ARG_REST_RESPONSE, mFollowersWPCOM);
+ }
+ if (mFollowersEmail != null) {
+ outState.putSerializable(ARG_REST_RESPONSE_FOLLOWERS_EMAIL, mFollowersEmail);
+ }
+ }
+ @Override
+ protected void restoreStatsData(Bundle savedInstanceState) {
+ if (savedInstanceState.containsKey(ARG_REST_RESPONSE)) {
+ mFollowersWPCOM = (FollowersModel) savedInstanceState.getSerializable(ARG_REST_RESPONSE);
+ }
+ if (savedInstanceState.containsKey(ARG_REST_RESPONSE_FOLLOWERS_EMAIL)) {
+ mFollowersEmail = (FollowersModel) savedInstanceState.getSerializable(ARG_REST_RESPONSE_FOLLOWERS_EMAIL);
+ }
+ }
+
+ @SuppressWarnings("unused")
+ public void onEventMainThread(StatsEvents.FollowersWPCOMUdated event) {
+ if (!shouldUpdateFragmentOnUpdateEvent(event)) {
+ return;
+ }
+
+ mFollowersWPCOM = event.mFollowers;
+ updateUI();
+ }
+
+ @SuppressWarnings("unused")
+ public void onEventMainThread(StatsEvents.FollowersEmailUdated event) {
+ if (!shouldUpdateFragmentOnUpdateEvent(event)) {
+ return;
+ }
+
+ mFollowersEmail = event.mFollowers;
+ updateUI();
+ }
+
+ @SuppressWarnings("unused")
+ public void onEventMainThread(StatsEvents.SectionUpdateError event) {
+ if (!shouldUpdateFragmentOnErrorEvent(event)) {
+ return;
+ }
+
+ mFollowersWPCOM = null;
+ mFollowersEmail = null;
+ showErrorUI(event.mError);
+ }
+
+ @Override
+ protected void updateUI() {
+ if (!isAdded()) {
+ return;
+ }
+
+ if (!hasDataAvailable()) {
+ showHideNoResultsUI(true);
+ mTotalsLabel.setText(getTotalFollowersLabel(0));
+ return;
+ }
+
+ mTotalsLabel.setVisibility(View.VISIBLE);
+
+ final FollowersModel followersModel = getCurrentDataModel();
+
+ if (followersModel != null && followersModel.getFollowers() != null &&
+ followersModel.getFollowers().size() > 0) {
+ ArrayAdapter adapter = new DotComFollowerAdapter(getActivity(), followersModel.getFollowers());
+ StatsUIHelper.reloadLinearLayout(getActivity(), adapter, mList, getMaxNumberOfItemsToShowInList());
+ showHideNoResultsUI(false);
+
+ if (mTopPagerSelectedButtonIndex == 0) {
+ mTotalsLabel.setText(getTotalFollowersLabel(followersModel.getTotalWPCom()));
+ } else {
+ mTotalsLabel.setText(getTotalFollowersLabel(followersModel.getTotalEmail()));
+ }
+
+ if (isSingleView()) {
+ if (followersModel.getPages() > 1) {
+ mBottomPaginationContainer.setVisibility(View.VISIBLE);
+ mTopPaginationContainer.setVisibility(View.VISIBLE);
+ String paginationLabel = String.format(
+ getString(R.string.stats_pagination_label),
+ FormatUtils.formatDecimal(followersModel.getPage()),
+ FormatUtils.formatDecimal(followersModel.getPages())
+ );
+ mBottomPaginationText.setText(paginationLabel);
+ mTopPaginationText.setText(paginationLabel);
+ setNavigationButtonsEnabled(true);
+
+ // Setting up back buttons
+ if (followersModel.getPage() == 1) {
+ // first page. No go back buttons
+ setNavigationBackButtonsVisibility(false);
+ } else {
+ setNavigationBackButtonsVisibility(true);
+ View.OnClickListener clickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ setNavigationButtonsEnabled(false);
+ refreshStats(
+ followersModel.getPage() - 1,
+ new StatsService.StatsEndpointsEnum[]{sectionsToUpdate()[mTopPagerSelectedButtonIndex]}
+ );
+ }
+ };
+ mBottomPaginationGoBackButton.setOnClickListener(clickListener);
+ mTopPaginationGoBackButton.setOnClickListener(clickListener);
+ }
+
+ // Setting up forward buttons
+ if (followersModel.getPage() == followersModel.getPages()) {
+ // last page. No go forward buttons
+ setNavigationForwardButtonsVisibility(false);
+ } else {
+ setNavigationForwardButtonsVisibility(true);
+ View.OnClickListener clickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ setNavigationButtonsEnabled(false);
+ refreshStats(
+ followersModel.getPage() + 1,
+ new StatsService.StatsEndpointsEnum[]{sectionsToUpdate()[mTopPagerSelectedButtonIndex]}
+ );
+ }
+ };
+ mBottomPaginationGoForwardButton.setOnClickListener(clickListener);
+ mTopPaginationGoForwardButton.setOnClickListener(clickListener);
+ }
+
+ // Change the total number of followers label by adding the current paging info
+ int startIndex = followersModel.getPage() * StatsService.MAX_RESULTS_REQUESTED_PER_PAGE - StatsService.MAX_RESULTS_REQUESTED_PER_PAGE + 1;
+ int endIndex = startIndex + followersModel.getFollowers().size() - 1;
+ String pagedLabel = getString(
+ mTopPagerSelectedButtonIndex == 0 ? R.string.stats_followers_total_wpcom_paged : R.string.stats_followers_total_email_paged,
+ startIndex,
+ endIndex,
+ FormatUtils.formatDecimal(mTopPagerSelectedButtonIndex == 0 ? followersModel.getTotalWPCom() : followersModel.getTotalEmail())
+ );
+ mTotalsLabel.setText(pagedLabel);
+ } else {
+ // No paging required. Hide the controls.
+ mBottomPaginationContainer.setVisibility(View.GONE);
+ mTopPaginationContainer.setVisibility(View.GONE);
+ }
+ }
+ } else {
+ showHideNoResultsUI(true);
+ mBottomPaginationContainer.setVisibility(View.GONE);
+ mTotalsLabel.setText(getTotalFollowersLabel(0));
+ }
+
+ // Always visible. Even if the current tab is empty, otherwise the user can't switch tab
+ mTopPagerContainer.setVisibility(View.VISIBLE);
+ }
+
+ private FollowersModel getCurrentDataModel() {
+ return mTopPagerSelectedButtonIndex == 0 ? mFollowersWPCOM : mFollowersEmail;
+ }
+
+ private void setNavigationBackButtonsVisibility(boolean visible) {
+ mBottomPaginationGoBackButton.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+ mTopPaginationGoBackButton.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+ }
+
+ private void setNavigationForwardButtonsVisibility(boolean visible) {
+ mBottomPaginationGoForwardButton.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+ mTopPaginationGoForwardButton.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+ }
+
+ private void setNavigationButtonsEnabled(boolean enable) {
+ mBottomPaginationGoBackButton.setEnabled(enable);
+ mBottomPaginationGoForwardButton.setEnabled(enable);
+ mTopPaginationGoBackButton.setEnabled(enable);
+ mTopPaginationGoForwardButton.setEnabled(enable);
+ }
+
+ @Override
+ protected boolean isViewAllOptionAvailable() {
+ if (!hasDataAvailable()) {
+ return false;
+ }
+ FollowersModel followersModel = getCurrentDataModel();
+ return !(followersModel == null || followersModel.getFollowers() == null
+ || followersModel.getFollowers().size() < MAX_NUM_OF_ITEMS_DISPLAYED_IN_LIST);
+
+ }
+
+ private String getTotalFollowersLabel(int total) {
+ final String totalFollowersLabel;
+
+ if (mTopPagerSelectedButtonIndex == 0) {
+ totalFollowersLabel = getString(R.string.stats_followers_total_wpcom);
+ } else {
+ totalFollowersLabel = getString(R.string.stats_followers_total_email);
+ }
+
+ return String.format(totalFollowersLabel, FormatUtils.formatDecimal(total));
+ }
+
+ @Override
+ protected boolean isExpandableList() {
+ return false;
+ }
+
+ private class DotComFollowerAdapter extends ArrayAdapter<FollowerModel> {
+
+ private final List<FollowerModel> list;
+ private final Activity context;
+ private final LayoutInflater inflater;
+
+ public DotComFollowerAdapter(Activity context, List<FollowerModel> list) {
+ super(context, R.layout.stats_list_cell, list);
+ this.context = context;
+ this.list = list;
+ inflater = LayoutInflater.from(context);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View rowView = convertView;
+ // reuse views
+ if (rowView == null) {
+ rowView = inflater.inflate(R.layout.stats_list_cell, parent, false);
+ // set a min-width value that is large enough to contains the "since" string
+ LinearLayout totalContainer = (LinearLayout) rowView.findViewById(R.id.stats_list_cell_total_container);
+ int dp64 = DisplayUtils.dpToPx(rowView.getContext(), 64);
+ totalContainer.setMinimumWidth(dp64);
+ // configure view holder
+ StatsViewHolder viewHolder = new StatsViewHolder(rowView);
+ rowView.setTag(viewHolder);
+ }
+
+ final FollowerModel currentRowData = list.get(position);
+ final StatsViewHolder holder = (StatsViewHolder) rowView.getTag();
+
+ holder.entryTextView.setTextColor(context.getResources().getColor(R.color.stats_text_color));
+ holder.rowContent.setClickable(false);
+
+ final FollowDataModel followData = currentRowData.getFollowData();
+
+ // entries
+ if (mTopPagerSelectedButtonIndex == 0 && !(TextUtils.isEmpty(currentRowData.getURL()) && followData == null)) {
+ // WPCOM followers with no empty URL or empty follow data
+
+ final int blogID;
+ if (followData == null) {
+ // If follow data is empty, we cannot follow the blog, or access it in the reader.
+ // We need to check if the user is a member of this blog.
+ // If so, we can launch open the reader, otherwise open the blog in the in-app browser.
+ String normURL = normalizeAndRemoveScheme(currentRowData.getURL());
+ blogID = userBlogs.containsKey(normURL) ? userBlogs.get(normURL) : Integer.MIN_VALUE;
+ } else {
+ blogID = followData.getSiteID();
+ }
+
+ if (blogID > Integer.MIN_VALUE) {
+ // Open the Reader
+ holder.entryTextView.setText(currentRowData.getLabel());
+ holder.rowContent.setOnClickListener(
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ ReaderActivityLauncher.showReaderBlogPreview(
+ context,
+ blogID
+ );
+ }
+ });
+ } else {
+ // Open the in-app web browser
+ holder.setEntryTextOrLink(currentRowData.getURL(), currentRowData.getLabel());
+ }
+ holder.entryTextView.setTextColor(context.getResources().getColor(R.color.stats_link_text_color));
+ } else {
+ // Email followers, or wpcom followers with empty URL and no blogID
+ holder.setEntryText(currentRowData.getLabel());
+ }
+
+ // since date
+ holder.totalsTextView.setText(
+ StatsUtils.getSinceLabel(
+ context,
+ currentRowData.getDateSubscribed()
+ )
+ );
+
+ // Avatar
+ holder.networkImageView.setImageUrl(
+ GravatarUtils.fixGravatarUrl(currentRowData.getAvatar(), mResourceVars.headerAvatarSizePx),
+ WPNetworkImageView.ImageType.AVATAR);
+ holder.networkImageView.setVisibility(View.VISIBLE);
+
+ if (followData == null) {
+ holder.imgMore.setVisibility(View.GONE);
+ holder.imgMore.setClickable(false);
+ } else {
+ holder.imgMore.setVisibility(View.VISIBLE);
+ holder.imgMore.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ FollowHelper fh = new FollowHelper(context);
+ fh.showPopup(holder.imgMore, followData);
+ }
+ });
+ }
+
+ return rowView;
+ }
+
+
+ }
+
+ private static String normalizeAndRemoveScheme(String url) {
+ if (TextUtils.isEmpty(url)) {
+ return "";
+ }
+ String normURL = UrlUtils.normalizeUrl(url.toLowerCase());
+ int pos = normURL.indexOf("://");
+ if (pos > -1) {
+ return normURL.substring(pos + 3);
+ } else {
+ return normURL;
+ }
+ }
+
+ @Override
+ protected int getEntryLabelResId() {
+ return R.string.stats_entry_followers;
+ }
+
+ @Override
+ protected int getTotalsLabelResId() {
+ return R.string.stats_totals_followers;
+ }
+
+ @Override
+ protected int getEmptyLabelTitleResId() {
+ return R.string.stats_empty_followers;
+ }
+
+ @Override
+ protected int getEmptyLabelDescResId() {
+ return R.string.stats_empty_followers_desc;
+ }
+
+ @Override
+ protected StatsService.StatsEndpointsEnum[] sectionsToUpdate() {
+ return new StatsService.StatsEndpointsEnum[]{
+ StatsService.StatsEndpointsEnum.FOLLOWERS_WPCOM, StatsService.StatsEndpointsEnum.FOLLOWERS_EMAIL
+ };
+ }
+
+ @Override
+ public String getTitle() {
+ return getString(R.string.stats_view_followers);
+ }
+}