aboutsummaryrefslogtreecommitdiff
path: root/WordPress/src/main/java/org/wordpress/android/ui/main/SitePickerAdapter.java
diff options
context:
space:
mode:
Diffstat (limited to 'WordPress/src/main/java/org/wordpress/android/ui/main/SitePickerAdapter.java')
-rw-r--r--WordPress/src/main/java/org/wordpress/android/ui/main/SitePickerAdapter.java508
1 files changed, 508 insertions, 0 deletions
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/main/SitePickerAdapter.java b/WordPress/src/main/java/org/wordpress/android/ui/main/SitePickerAdapter.java
new file mode 100644
index 000000000..7267d8d5e
--- /dev/null
+++ b/WordPress/src/main/java/org/wordpress/android/ui/main/SitePickerAdapter.java
@@ -0,0 +1,508 @@
+package org.wordpress.android.ui.main;
+
+import android.content.Context;
+import android.graphics.Typeface;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.support.v7.widget.RecyclerView;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+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.models.AccountHelper;
+import org.wordpress.android.util.AppLog;
+import org.wordpress.android.util.BlogUtils;
+import org.wordpress.android.util.GravatarUtils;
+import org.wordpress.android.util.MapUtils;
+import org.wordpress.android.util.StringUtils;
+import org.wordpress.android.widgets.WPNetworkImageView;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+class SitePickerAdapter extends RecyclerView.Adapter<SitePickerAdapter.SiteViewHolder> {
+
+ interface OnSiteClickListener {
+ void onSiteClick(SiteRecord site);
+ }
+
+ interface OnSelectedCountChangedListener {
+ void onSelectedCountChanged(int numSelected);
+ }
+
+ private final int mTextColorNormal;
+ private final int mTextColorHidden;
+
+ private static int mBlavatarSz;
+
+ private SiteList mSites = new SiteList();
+ private final int mCurrentLocalId;
+
+ private final Drawable mSelectedItemBackground;
+
+ private final LayoutInflater mInflater;
+ private final HashSet<Integer> mSelectedPositions = new HashSet<>();
+
+ private boolean mIsMultiSelectEnabled;
+ private final boolean mIsInSearchMode;
+ private boolean mShowHiddenSites = false;
+ private boolean mShowSelfHostedSites = true;
+ private String mLastSearch;
+ private SiteList mAllSites;
+
+ private OnSiteClickListener mSiteSelectedListener;
+ private OnSelectedCountChangedListener mSelectedCountListener;
+
+ class SiteViewHolder extends RecyclerView.ViewHolder {
+ private final ViewGroup layoutContainer;
+ private final TextView txtTitle;
+ private final TextView txtDomain;
+ private final WPNetworkImageView imgBlavatar;
+ private final View divider;
+ private Boolean isSiteHidden;
+
+ public SiteViewHolder(View view) {
+ super(view);
+ layoutContainer = (ViewGroup) view.findViewById(R.id.layout_container);
+ txtTitle = (TextView) view.findViewById(R.id.text_title);
+ txtDomain = (TextView) view.findViewById(R.id.text_domain);
+ imgBlavatar = (WPNetworkImageView) view.findViewById(R.id.image_blavatar);
+ divider = view.findViewById(R.id.divider);
+ isSiteHidden = null;
+
+ itemView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ int clickedPosition = getAdapterPosition();
+ if (isValidPosition(clickedPosition)) {
+ if (mIsMultiSelectEnabled) {
+ toggleSelection(clickedPosition);
+ } else if (mSiteSelectedListener != null) {
+ mSiteSelectedListener.onSiteClick(getItem(clickedPosition));
+ }
+ } else {
+ AppLog.w(AppLog.T.MAIN, "site picker > invalid clicked position " + clickedPosition);
+ }
+ }
+ });
+ }
+ }
+
+ public SitePickerAdapter(Context context, int currentLocalBlogId, String lastSearch, boolean isInSearchMode) {
+ super();
+
+ setHasStableIds(true);
+
+ mLastSearch = StringUtils.notNullStr(lastSearch);
+ mAllSites = new SiteList();
+ mIsInSearchMode = isInSearchMode;
+ mCurrentLocalId = currentLocalBlogId;
+ mInflater = LayoutInflater.from(context);
+
+ mBlavatarSz = context.getResources().getDimensionPixelSize(R.dimen.blavatar_sz);
+ mTextColorNormal = context.getResources().getColor(R.color.grey_dark);
+ mTextColorHidden = context.getResources().getColor(R.color.grey);
+
+ mSelectedItemBackground = new ColorDrawable(context.getResources().getColor(R.color.translucent_grey_lighten_20));
+
+ loadSites();
+ }
+
+ @Override
+ public int getItemCount() {
+ return mSites.size();
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return getItem(position).localId;
+ }
+
+ private SiteRecord getItem(int position) {
+ return mSites.get(position);
+ }
+
+ void setOnSelectedCountChangedListener(OnSelectedCountChangedListener listener) {
+ mSelectedCountListener = listener;
+ }
+
+ public void setOnSiteClickListener(OnSiteClickListener listener) {
+ mSiteSelectedListener = listener;
+ }
+
+ @Override
+ public SiteViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View itemView = mInflater.inflate(R.layout.site_picker_listitem, parent, false);
+ return new SiteViewHolder(itemView);
+ }
+
+ @Override
+ public void onBindViewHolder(SiteViewHolder holder, int position) {
+ SiteRecord site = getItem(position);
+
+ holder.txtTitle.setText(site.getBlogNameOrHomeURL());
+ holder.txtDomain.setText(site.homeURL);
+ holder.imgBlavatar.setImageUrl(site.blavatarUrl, WPNetworkImageView.ImageType.BLAVATAR);
+
+ if (site.localId == mCurrentLocalId || (mIsMultiSelectEnabled && isItemSelected(position))) {
+ holder.layoutContainer.setBackgroundDrawable(mSelectedItemBackground);
+ } else {
+ holder.layoutContainer.setBackgroundDrawable(null);
+ }
+
+ // different styling for visible/hidden sites
+ if (holder.isSiteHidden == null || holder.isSiteHidden != site.isHidden) {
+ holder.isSiteHidden = site.isHidden;
+ holder.txtTitle.setTextColor(site.isHidden ? mTextColorHidden : mTextColorNormal);
+ holder.txtTitle.setTypeface(holder.txtTitle.getTypeface(), site.isHidden ? Typeface.NORMAL : Typeface.BOLD);
+ holder.imgBlavatar.setAlpha(site.isHidden ? 0.5f : 1f);
+ }
+
+ // hide the divider for the last item
+ boolean isLastItem = (position == getItemCount() - 1);
+ holder.divider.setVisibility(isLastItem ? View.INVISIBLE : View.VISIBLE);
+ }
+
+ public String getLastSearch() {
+ return mLastSearch;
+ }
+
+ public void setLastSearch(String lastSearch) {
+ mLastSearch = lastSearch;
+ }
+
+ public boolean getIsInSearchMode() {
+ return mIsInSearchMode;
+ }
+
+ public void searchSites(String searchText) {
+ mLastSearch = searchText;
+ mSites = filteredSitesByText(mAllSites);
+
+ notifyDataSetChanged();
+ }
+
+ private boolean isValidPosition(int position) {
+ return (position >= 0 && position < mSites.size());
+ }
+
+ /*
+ * called when the user chooses to edit the visibility of wp.com blogs
+ */
+ void setEnableEditMode(boolean enable) {
+ if (mIsMultiSelectEnabled == enable) return;
+
+ if (enable) {
+ mShowHiddenSites = true;
+ mShowSelfHostedSites = false;
+ } else {
+ mShowHiddenSites = false;
+ mShowSelfHostedSites = true;
+ }
+
+ mIsMultiSelectEnabled = enable;
+ mSelectedPositions.clear();
+
+ loadSites();
+ }
+
+ int getNumSelected() {
+ return mSelectedPositions.size();
+ }
+
+ int getNumHiddenSelected() {
+ int numHidden = 0;
+ for (Integer i: mSelectedPositions) {
+ if (mSites.get(i).isHidden) {
+ numHidden++;
+ }
+ }
+ return numHidden;
+ }
+
+ int getNumVisibleSelected() {
+ int numVisible = 0;
+ for (Integer i: mSelectedPositions) {
+ if (!mSites.get(i).isHidden) {
+ numVisible++;
+ }
+ }
+ return numVisible;
+ }
+
+ private void toggleSelection(int position) {
+ setItemSelected(position, !isItemSelected(position));
+ }
+
+ private boolean isItemSelected(int position) {
+ return mSelectedPositions.contains(position);
+ }
+
+ private void setItemSelected(int position, boolean isSelected) {
+ if (isItemSelected(position) == isSelected) {
+ return;
+ }
+
+ if (isSelected) {
+ mSelectedPositions.add(position);
+ } else {
+ mSelectedPositions.remove(position);
+ }
+ notifyItemChanged(position);
+
+ if (mSelectedCountListener != null) {
+ mSelectedCountListener.onSelectedCountChanged(getNumSelected());
+ }
+ }
+
+ void selectAll() {
+ if (mSelectedPositions.size() == mSites.size()) return;
+
+ mSelectedPositions.clear();
+ for (int i = 0; i < mSites.size(); i++) {
+ mSelectedPositions.add(i);
+ }
+ notifyDataSetChanged();
+
+ if (mSelectedCountListener != null) {
+ mSelectedCountListener.onSelectedCountChanged(getNumSelected());
+ }
+ }
+
+ void deselectAll() {
+ if (mSelectedPositions.size() == 0) return;
+
+ mSelectedPositions.clear();
+ notifyDataSetChanged();
+
+ if (mSelectedCountListener != null) {
+ mSelectedCountListener.onSelectedCountChanged(getNumSelected());
+ }
+ }
+
+ private SiteList getSelectedSites() {
+ SiteList sites = new SiteList();
+ if (!mIsMultiSelectEnabled) {
+ return sites;
+ }
+
+ for (Integer position : mSelectedPositions) {
+ if (isValidPosition(position))
+ sites.add(mSites.get(position));
+ }
+
+ return sites;
+ }
+
+ SiteList getHiddenSites() {
+ SiteList hiddenSites = new SiteList();
+ for (SiteRecord site: mSites) {
+ if (site.isHidden) {
+ hiddenSites.add(site);
+ }
+ }
+
+ return hiddenSites;
+ }
+
+ void setVisibilityForSelectedSites(boolean makeVisible) {
+ SiteList sites = getSelectedSites();
+ if (sites != null && sites.size() > 0) {
+ for (SiteRecord site: sites) {
+ int index = mSites.indexOfSite(site);
+ if (index > -1) {
+ mSites.get(index).isHidden = !makeVisible;
+ }
+ }
+ }
+ }
+
+ void loadSites() {
+ if (mIsTaskRunning) {
+ AppLog.w(AppLog.T.UTILS, "site picker > already loading sites");
+ } else {
+ new LoadSitesTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+ }
+
+ private SiteList filteredSitesByTextIfInSearchMode(SiteList sites) {
+ if (!mIsInSearchMode) {
+ return sites;
+ } else {
+ return filteredSitesByText(sites);
+ }
+ }
+
+ private SiteList filteredSitesByText(SiteList sites) {
+ SiteList filteredSiteList = new SiteList();
+
+ for (int i = 0; i < sites.size(); i++) {
+ SiteRecord record = sites.get(i);
+ String siteNameLowerCase = record.blogName.toLowerCase();
+ String hostNameLowerCase = record.homeURL.toLowerCase();
+
+ if (siteNameLowerCase.contains(mLastSearch.toLowerCase()) || hostNameLowerCase.contains(mLastSearch.toLowerCase())) {
+ filteredSiteList.add(record);
+ }
+ }
+
+ return filteredSiteList;
+ }
+
+ /*
+ * AsyncTask which loads sites from database and populates the adapter
+ */
+ private boolean mIsTaskRunning;
+ private class LoadSitesTask extends AsyncTask<Void, Void, Void> {
+ @Override
+ protected void onPreExecute() {
+ super.onPreExecute();
+ mIsTaskRunning = true;
+ }
+
+ @Override
+ protected void onCancelled() {
+ super.onCancelled();
+ mIsTaskRunning = false;
+ }
+
+ @Override
+ protected Void doInBackground(Void... params) {
+ List<Map<String, Object>> blogs;
+ String[] extraFields = {"isHidden", "dotcomFlag", "homeURL"};
+
+ if (mIsInSearchMode) {
+ blogs = WordPress.wpDB.getBlogsBy(null, extraFields);
+ } else {
+ blogs = getBlogsForCurrentView(extraFields);
+ }
+
+ SiteList sites = new SiteList(blogs);
+
+ // sort by blog/host
+ final long primaryBlogId = AccountHelper.getDefaultAccount().getPrimaryBlogId();
+ Collections.sort(sites, new Comparator<SiteRecord>() {
+ public int compare(SiteRecord site1, SiteRecord site2) {
+ if (primaryBlogId > 0) {
+ if (site1.blogId == primaryBlogId) {
+ return -1;
+ } else if (site2.blogId == primaryBlogId) {
+ return 1;
+ }
+ }
+ return site1.getBlogNameOrHomeURL().compareToIgnoreCase(site2.getBlogNameOrHomeURL());
+ }
+ });
+
+ if (mSites == null || !mSites.isSameList(sites)) {
+ mAllSites = (SiteList) sites.clone();
+ mSites = filteredSitesByTextIfInSearchMode(sites);
+ }
+
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void results) {
+ notifyDataSetChanged();
+ mIsTaskRunning = false;
+ }
+
+ private List<Map<String, Object>> getBlogsForCurrentView(String[] extraFields) {
+ if (mShowHiddenSites) {
+ if (mShowSelfHostedSites) {
+ // all self-hosted blogs and all wp.com blogs
+ return WordPress.wpDB.getBlogsBy(null, extraFields);
+ } else {
+ // only wp.com blogs
+ return WordPress.wpDB.getBlogsBy("dotcomFlag=1", extraFields);
+ }
+ } else {
+ if (mShowSelfHostedSites) {
+ // all self-hosted blogs plus visible wp.com blogs
+ return WordPress.wpDB.getBlogsBy("dotcomFlag=0 OR (isHidden=0 AND dotcomFlag=1) ", extraFields);
+ } else {
+ // only visible wp.com blogs
+ return WordPress.wpDB.getBlogsBy("isHidden=0 AND dotcomFlag=1", extraFields);
+ }
+ }
+ }
+ }
+
+ /**
+ * SiteRecord is a simplified version of the full account (blog) record
+ */
+ static class SiteRecord {
+ final int localId;
+ final int blogId;
+ final String blogName;
+ final String homeURL;
+ final String url;
+ final String blavatarUrl;
+ final boolean isDotCom;
+ boolean isHidden;
+
+ SiteRecord(Map<String, Object> account) {
+ localId = MapUtils.getMapInt(account, "id");
+ blogId = MapUtils.getMapInt(account, "blogId");
+ blogName = BlogUtils.getBlogNameOrHomeURLFromAccountMap(account);
+ homeURL = BlogUtils.getHomeURLOrHostNameFromAccountMap(account);
+ url = MapUtils.getMapStr(account, "url");
+ blavatarUrl = GravatarUtils.blavatarFromUrl(url, mBlavatarSz);
+ isDotCom = MapUtils.getMapBool(account, "dotcomFlag");
+ isHidden = MapUtils.getMapBool(account, "isHidden");
+ }
+
+ String getBlogNameOrHomeURL() {
+ if (TextUtils.isEmpty(blogName)) {
+ return homeURL;
+ }
+ return blogName;
+ }
+ }
+
+ static class SiteList extends ArrayList<SiteRecord> {
+ SiteList() { }
+ SiteList(List<Map<String, Object>> accounts) {
+ if (accounts != null) {
+ for (Map<String, Object> account : accounts) {
+ add(new SiteRecord(account));
+ }
+ }
+ }
+
+ boolean isSameList(SiteList sites) {
+ if (sites == null || sites.size() != this.size()) {
+ return false;
+ }
+ int i;
+ for (SiteRecord site: sites) {
+ i = indexOfSite(site);
+ if (i == -1 || this.get(i).isHidden != site.isHidden) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ int indexOfSite(SiteRecord site) {
+ if (site != null && site.blogId > 0) {
+ for (int i = 0; i < size(); i++) {
+ if (site.blogId == this.get(i).blogId) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+ }
+}