package org.wordpress.android.ui.stats; import android.app.Activity; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import org.wordpress.android.R; import org.wordpress.android.ui.stats.models.SearchTermModel; import org.wordpress.android.ui.stats.models.SearchTermsModel; import org.wordpress.android.ui.stats.service.StatsService; import org.wordpress.android.util.FormatUtils; import java.util.ArrayList; import java.util.List; public class StatsSearchTermsFragment extends StatsAbstractListFragment { public static final String TAG = StatsSearchTermsFragment.class.getSimpleName(); private final static String UNKNOWN_SEARCH_TERMS_HELP_PAGE = "https://en.support.wordpress.com/stats/#search-engine-terms"; private SearchTermsModel mSearchTerms; @Override protected boolean hasDataAvailable() { return mSearchTerms != null; } @Override protected void saveStatsData(Bundle outState) { if (hasDataAvailable()) { outState.putSerializable(ARG_REST_RESPONSE, mSearchTerms); } } @Override protected void restoreStatsData(Bundle savedInstanceState) { if (savedInstanceState.containsKey(ARG_REST_RESPONSE)) { mSearchTerms = (SearchTermsModel) savedInstanceState.getSerializable(ARG_REST_RESPONSE); } } @SuppressWarnings("unused") public void onEventMainThread(StatsEvents.SearchTermsUpdated event) { if (!shouldUpdateFragmentOnUpdateEvent(event)) { return; } mSearchTerms = event.mSearchTerms; updateUI(); } @SuppressWarnings("unused") public void onEventMainThread(StatsEvents.SectionUpdateError event) { if (!shouldUpdateFragmentOnErrorEvent(event)) { return; } mSearchTerms = null; showErrorUI(event.mError); } @Override protected void updateUI() { if (!isAdded()) { return; } if (hasSearchTerms()) { /** * At this point we can have: * - A list of search terms * - A list of search terms + Encrypted item * - Encrypted item only * * We want to display max 10 items regardless the kind of the items, AND Encrypted * must be present if available. * * We need to do some counts then... */ List<SearchTermModel> originalSearchTermList = mSearchTerms.getSearchTerms(); List<SearchTermModel> mySearchTermList; if (originalSearchTermList == null) { // No clear-text search terms. we know we have the encrypted search terms item available mySearchTermList = new ArrayList<>(0); } else { // Make sure the list has MAX 9 items if the "Encrypted" is available // we want to show exactly 10 items per module if (mSearchTerms.getEncryptedSearchTerms() > 0 && originalSearchTermList.size() > getMaxNumberOfItemsToShowInList() - 1) { mySearchTermList = new ArrayList<>(); int minIndex = Math.min(originalSearchTermList.size(), getMaxNumberOfItemsToShowInList() - 1); for (int i = 0; i < minIndex; i++) { mySearchTermList.add(originalSearchTermList.get(i)); } } else { mySearchTermList = originalSearchTermList; } } ArrayAdapter adapter = new SearchTermsAdapter(getActivity(), mySearchTermList, mSearchTerms.getEncryptedSearchTerms()); StatsUIHelper.reloadLinearLayout(getActivity(), adapter, mList, getMaxNumberOfItemsToShowInList()); showHideNoResultsUI(false); } else { showHideNoResultsUI(true); } } private boolean hasSearchTerms() { return mSearchTerms != null && ((mSearchTerms.getSearchTerms() != null && mSearchTerms.getSearchTerms().size() > 0) || mSearchTerms.getEncryptedSearchTerms() > 0 ); } @Override protected boolean isViewAllOptionAvailable() { if (!hasSearchTerms()) { return false; } int total = mSearchTerms.getSearchTerms() != null ? mSearchTerms.getSearchTerms().size() : 0; // If "Encrypted" is available we only have 9 items of clear text terms in the list if (mSearchTerms.getEncryptedSearchTerms() > 0) { return total > MAX_NUM_OF_ITEMS_DISPLAYED_IN_LIST - 1; } else { return total > MAX_NUM_OF_ITEMS_DISPLAYED_IN_LIST; } } @Override protected boolean isExpandableList() { return false; } private class SearchTermsAdapter extends ArrayAdapter<SearchTermModel> { private final List<SearchTermModel> list; private final LayoutInflater inflater; private final int encryptedSearchTerms; public SearchTermsAdapter(Activity context, List<SearchTermModel> list, int encryptedSearchTerms) { super(context, R.layout.stats_list_cell, list); this.list = list; this.encryptedSearchTerms = encryptedSearchTerms; this.inflater = LayoutInflater.from(context); } @Override public int getCount() { return super.getCount() + (encryptedSearchTerms > 0 ? 1 : 0); } @Override public SearchTermModel getItem(int position) { // If it's an element in the list returns it, otherwise it's the position of "Encrypted" if (position < super.getCount()) { return super.getItem(position); } return new SearchTermModel(0, null, "Unknown Search Terms", encryptedSearchTerms, true); } @Override public int getPosition(SearchTermModel item) { if (item.isEncriptedTerms()) { return super.getCount(); // "Encrypted" is always at the end of the list } return super.getPosition(item); } @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); // configure view holder StatsViewHolder viewHolder = new StatsViewHolder(rowView); rowView.setTag(viewHolder); } final SearchTermModel currentRowData = this.getItem(position); StatsViewHolder holder = (StatsViewHolder) rowView.getTag(); String term = currentRowData.getTitle(); if (currentRowData.isEncriptedTerms()) { holder.setEntryTextOrLink(UNKNOWN_SEARCH_TERMS_HELP_PAGE, getString(R.string.stats_search_terms_unknown_search_terms)); } else { holder.setEntryText(term, getResources().getColor(R.color.stats_text_color)); } // totals holder.totalsTextView.setText(FormatUtils.formatDecimal(currentRowData.getTotals())); // image holder.networkImageView.setVisibility(View.GONE); return rowView; } } @Override protected int getEntryLabelResId() { return R.string.stats_entry_search_terms; } @Override protected int getTotalsLabelResId() { return R.string.stats_totals_views; } @Override protected int getEmptyLabelTitleResId() { return R.string.stats_empty_search_terms; } @Override protected int getEmptyLabelDescResId() { return R.string.stats_empty_search_terms_desc; } @Override protected StatsService.StatsEndpointsEnum[] sectionsToUpdate() { return new StatsService.StatsEndpointsEnum[]{ StatsService.StatsEndpointsEnum.SEARCH_TERMS }; } @Override public String getTitle() { return getString(R.string.stats_view_search_terms); } }