/* * Copyright 2014 Gleb Godonoga. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.andrada.sitracker.ui.fragment.adapters; import android.app.Activity; import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseExpandableListAdapter; import android.widget.ExpandableListView; import android.widget.ListView; import com.andrada.sitracker.Constants; import com.andrada.sitracker.R; import com.andrada.sitracker.analytics.PublicationOpenedEvent; import com.andrada.sitracker.contracts.IsNewItemTappedListener; import com.andrada.sitracker.contracts.SIPrefs_; import com.andrada.sitracker.db.beans.Publication; import com.andrada.sitracker.db.dao.PublicationDao; import com.andrada.sitracker.db.manager.SiDBHelper; import com.andrada.sitracker.events.PublicationMarkedAsReadEvent; import com.andrada.sitracker.ui.components.PublicationCategoryItemView; import com.andrada.sitracker.ui.components.PublicationCategoryItemView_; import com.andrada.sitracker.ui.components.PublicationItemView; import com.andrada.sitracker.ui.components.PublicationItemView_; import com.andrada.sitracker.analytics.AnalyticsManager; import com.github.amlcurran.showcaseview.ShowcaseView; import com.github.amlcurran.showcaseview.targets.ViewTarget; import org.androidannotations.annotations.Background; import org.androidannotations.annotations.EBean; import org.androidannotations.annotations.OrmLiteDao; import org.androidannotations.annotations.RootContext; import org.androidannotations.annotations.UiThread; import org.androidannotations.annotations.sharedpreferences.Pref; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import de.greenrobot.event.EventBus; import static com.andrada.sitracker.util.LogUtils.LOGE; @EBean public class PublicationsAdapter extends BaseExpandableListAdapter implements IsNewItemTappedListener, AdapterView.OnItemLongClickListener { private final Map<Long, Publication> mDownloadingPublications = new HashMap<Long, Publication>(); List<CategoryValue> mCategories = new ArrayList<CategoryValue>(); List<List<Publication>> mChildren = new ArrayList<List<Publication>>(); @OrmLiteDao(helper = SiDBHelper.class) PublicationDao publicationsDao; @RootContext Context context; @Pref SIPrefs_ prefs; @Nullable ListView listView = null; boolean shouldShowImages; private PublicationShareAttemptListener listener; private boolean showcaseViewShown = false; @Background public void reloadPublicationsForAuthorId(long id) { try { shouldShowImages = prefs.displayPubImages().get(); List<Publication> pubs = publicationsDao.getSortedPublicationsForAuthorId(id); List<CategoryValue> newCategories = new ArrayList<CategoryValue>(); List<List<Publication>> newChildren = new ArrayList<List<Publication>>(); for (Publication publication : pubs) { CategoryValue possibleVal = new CategoryValue(publication.getCategory()); if (!newCategories.contains(possibleVal)) { if (publication.getNew()) { possibleVal.incrementNewCount(); } newCategories.add(possibleVal); } else if (publication.getNew()) { newCategories.get(newCategories.indexOf(possibleVal)).incrementNewCount(); } } for (CategoryValue category : newCategories) { List<Publication> categoryList = new ArrayList<Publication>(); for (Publication publication : pubs) { if (category.equals(publication.getCategory())) { categoryList.add(publication); } } newChildren.add(categoryList); } updateAdapterDataSet(newCategories, newChildren); } catch (SQLException e) { LOGE("SiTracker", "Exception while reloading pubs", e); } } @UiThread(propagation = UiThread.Propagation.REUSE) void updateAdapterDataSet(List<CategoryValue> newCategories, List<List<Publication>> newChildren) { mCategories = newCategories; mChildren = newChildren; postDataSetChanged(); } @UiThread(delay = 300) void createAndShowShowcaseView(View view) { if (context instanceof Activity) { new ShowcaseView.Builder((Activity) context) .setTarget(new ViewTarget(view)) .setContentTitle(context.getString(R.string.showcase_pub_quick_title)) .setContentText(context.getString(R.string.showcase_pub_quick_detail)) .setStyle(R.style.ShowcaseView_Base) .singleShot(Constants.SHOWCASE_PUBLICATION_QUICK_ACCESS_SHOT_ID) .build(); } } @UiThread(propagation = UiThread.Propagation.REUSE) void postDataSetChanged() { notifyDataSetChanged(); } @Override public int getGroupCount() { return mCategories.size(); } @Override public int getChildrenCount(int groupPosition) { return mChildren.get(groupPosition).size(); } @Override public Object getGroup(int groupPosition) { return mCategories.get(groupPosition); } @Override public Object getChild(int groupPosition, int childPosition) { List<Publication> items = mChildren.get(groupPosition); return items.get(childPosition); } @Override public long getGroupId(int groupPosition) { return groupPosition; } @Override public long getChildId(int groupPosition, int childPosition) { List<Publication> items = mChildren.get(groupPosition); return items.get(childPosition).getId(); } @Override public boolean hasStableIds() { return false; } @NotNull @Override public View getGroupView(int groupPosition, boolean isExpanded, @Nullable View convertView, ViewGroup parent) { if (listView == null) { listView = (ListView) parent; } PublicationCategoryItemView publicationCategoryView; //For some weird reason, convertView is PublicationItemView instead of PublicationCategoryItemView_ if (!(convertView instanceof PublicationCategoryItemView)) { publicationCategoryView = PublicationCategoryItemView_.build(context); } else { publicationCategoryView = (PublicationCategoryItemView) convertView; } publicationCategoryView.bind(mCategories.get(groupPosition).categoryName, mChildren.get(groupPosition).size(), mCategories.get(groupPosition).getNewCount()); return publicationCategoryView; } @NotNull @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, @Nullable View convertView, ViewGroup parent) { Publication pub = (Publication) getChild(groupPosition, childPosition); PublicationItemView publicationItemView; if (convertView == null) { publicationItemView = PublicationItemView_.build(context); publicationItemView.setListener(this); } else { publicationItemView = (PublicationItemView) convertView; } publicationItemView.bind(pub, shouldShowImages); if (!showcaseViewShown) { showcaseViewShown = true; createAndShowShowcaseView(publicationItemView); } return publicationItemView; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } @Override public void onIsNewItemTapped(@NotNull View checkBox) { if (listView != null) { Publication pub = (Publication) checkBox.getTag(); if (pub != null) { updateStatusOfPublication(pub); } } } public void stopProgressOnPublication(long id, boolean success) { Publication loadingPub = mDownloadingPublications.get(id); if (loadingPub != null) { loadingPub.setLoading(false); mDownloadingPublications.remove(id); if (success) { updateStatusOfPublication(loadingPub); } } notifyDataSetChanged(); } public void setShareListener(PublicationShareAttemptListener listener) { this.listener = listener; } @Background protected void updateStatusOfPublication(@NotNull Publication pub) { if (pub.getNew()) { try { int index = mCategories.indexOf(new CategoryValue(pub.getCategory())); if (index >= 0 && index < mCategories.size()) { mCategories.get(index).decrementNewCount(); } boolean authorNewChanged = publicationsDao.markPublicationRead(pub); EventBus.getDefault().post(new PublicationMarkedAsReadEvent(authorNewChanged)); } catch (SQLException e) { AnalyticsManager.getInstance().sendException("Publication Set update", e); } postDataSetChanged(); } } @Override public boolean onItemLongClick(@NotNull AdapterView<?> parent, View view, int position, long id) { if (ExpandableListView.getPackedPositionType(id) == ExpandableListView.PACKED_POSITION_TYPE_CHILD) { long packedPosition = ((ExpandableListView) parent).getExpandableListPosition(position); int groupPosition = ExpandableListView.getPackedPositionGroup(packedPosition); int childPosition = ExpandableListView.getPackedPositionChild(packedPosition); List<Publication> items = mChildren.get(groupPosition); Publication pub = items.get(childPosition); if (pub.getLoading()) { //Ignore if it is loading now return true; } if (listener != null) { //Mark item as loading mDownloadingPublications.put(pub.getId(), pub); pub.setLoading(true); notifyDataSetChanged(); //Attempt to open or download publication listener.publicationShare(pub, pub.getNew()); AnalyticsManager.getInstance().logEvent(new PublicationOpenedEvent(pub.getName(), false)); } // Return true as we are handling the event. return true; } return false; } public interface PublicationShareAttemptListener { void publicationShare(Publication pub, boolean forceDownload); } public class CategoryValue { public final String categoryName; private int newCount; private CategoryValue(@NotNull String categoryName) { this.categoryName = categoryName; this.newCount = 0; } public void incrementNewCount() { ++newCount; } public void decrementNewCount() { --newCount; } public int getNewCount() { return newCount; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; CategoryValue that = (CategoryValue) o; return categoryName.equals(that.categoryName); } @Override public int hashCode() { return categoryName.hashCode(); } public boolean equals(String value) { return categoryName.equals(value); } } }