package de.danoeh.antennapod.adapter; import android.content.Context; import android.content.SharedPreferences; import android.content.res.TypedArray; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.preference.PreferenceManager; import android.support.v7.app.AlertDialog; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import com.bumptech.glide.Glide; import com.joanzapata.iconify.Iconify; import com.joanzapata.iconify.widget.IconTextView; import org.apache.commons.lang3.ArrayUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.fragment.AddFeedFragment; import de.danoeh.antennapod.fragment.AllEpisodesFragment; import de.danoeh.antennapod.fragment.DownloadsFragment; import de.danoeh.antennapod.fragment.EpisodesFragment; import de.danoeh.antennapod.fragment.NewEpisodesFragment; import de.danoeh.antennapod.fragment.PlaybackHistoryFragment; import de.danoeh.antennapod.fragment.QueueFragment; import de.danoeh.antennapod.fragment.SubscriptionFragment; /** * BaseAdapter for the navigation drawer */ public class NavListAdapter extends BaseAdapter implements SharedPreferences.OnSharedPreferenceChangeListener { public static final int VIEW_TYPE_COUNT = 3; public static final int VIEW_TYPE_NAV = 0; public static final int VIEW_TYPE_SECTION_DIVIDER = 1; public static final int VIEW_TYPE_SUBSCRIPTION = 2; /** * a tag used as a placeholder to indicate if the subscription list should be displayed or not * This tag doesn't correspond to any specific activity. */ public static final String SUBSCRIPTION_LIST_TAG = "SubscriptionList"; private static List<String> tags; private static String[] titles; private ItemAccess itemAccess; private Context context; private boolean showSubscriptionList = true; public NavListAdapter(ItemAccess itemAccess, Context context) { this.itemAccess = itemAccess; this.context = context; titles = context.getResources().getStringArray(R.array.nav_drawer_titles); loadItems(); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); prefs.registerOnSharedPreferenceChangeListener(this); } public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (key.equals(UserPreferences.PREF_HIDDEN_DRAWER_ITEMS)) { loadItems(); } } private void loadItems() { List<String> newTags = new ArrayList<>(Arrays.asList(MainActivity.NAV_DRAWER_TAGS)); List<String> hiddenFragments = UserPreferences.getHiddenDrawerItems(); for(String hidden : hiddenFragments) { newTags.remove(hidden); } if (newTags.contains(SUBSCRIPTION_LIST_TAG)) { // we never want SUBSCRIPTION_LIST_TAG to be in 'tags' // since it doesn't actually correspond to a position in the list, but is // a placeholder that indicates if we should show the subscription list in the // nav drawer at all. showSubscriptionList = true; newTags.remove(SUBSCRIPTION_LIST_TAG); } else { showSubscriptionList = false; } tags = newTags; notifyDataSetChanged(); } public String getLabel(String tag) { int index = ArrayUtils.indexOf(MainActivity.NAV_DRAWER_TAGS, tag); return titles[index]; } private Drawable getDrawable(String tag) { int icon; switch (tag) { case QueueFragment.TAG: icon = R.attr.stat_playlist; break; case NewEpisodesFragment.TAG: icon = R.attr.ic_new; break; case EpisodesFragment.TAG: icon = R.attr.feed; break; case AllEpisodesFragment.TAG: icon = R.attr.feed; break; case DownloadsFragment.TAG: icon = R.attr.av_download; break; case PlaybackHistoryFragment.TAG: icon = R.attr.ic_history; break; case SubscriptionFragment.TAG: icon = R.attr.ic_folder; break; case AddFeedFragment.TAG: icon = R.attr.content_new; break; default: return null; } TypedArray ta = context.obtainStyledAttributes(new int[] { icon } ); Drawable result = ta.getDrawable(0); ta.recycle(); return result; } public List<String> getTags() { return Collections.unmodifiableList(tags); } @Override public int getCount() { int baseCount = getSubscriptionOffset(); if (showSubscriptionList) { baseCount += itemAccess.getCount(); } return baseCount; } @Override public Object getItem(int position) { int viewType = getItemViewType(position); if (viewType == VIEW_TYPE_NAV) { return getLabel(tags.get(position)); } else if (viewType == VIEW_TYPE_SECTION_DIVIDER) { return ""; } else { return itemAccess.getItem(position); } } @Override public long getItemId(int position) { return position; } @Override public int getItemViewType(int position) { if (0 <= position && position < tags.size()) { return VIEW_TYPE_NAV; } else if (position < getSubscriptionOffset()) { return VIEW_TYPE_SECTION_DIVIDER; } else { return VIEW_TYPE_SUBSCRIPTION; } } @Override public int getViewTypeCount() { return VIEW_TYPE_COUNT; } public int getSubscriptionOffset() { return tags.size() > 0 ? tags.size() + 1 : 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { int viewType = getItemViewType(position); View v = null; if (viewType == VIEW_TYPE_NAV) { v = getNavView((String) getItem(position), position, convertView, parent); } else if (viewType == VIEW_TYPE_SECTION_DIVIDER) { v = getSectionDividerView(convertView, parent); } else { v = getFeedView(position, convertView, parent); } if (v != null && viewType != VIEW_TYPE_SECTION_DIVIDER) { TextView txtvTitle = (TextView) v.findViewById(R.id.txtvTitle); if (position == itemAccess.getSelectedItemIndex()) { txtvTitle.setTypeface(null, Typeface.BOLD); } else { txtvTitle.setTypeface(null, Typeface.NORMAL); } } return v; } private View getNavView(String title, int position, View convertView, ViewGroup parent) { NavHolder holder; if (convertView == null) { holder = new NavHolder(); LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.nav_listitem, parent, false); holder.image = (ImageView) convertView.findViewById(R.id.imgvCover); holder.title = (TextView) convertView.findViewById(R.id.txtvTitle); holder.count = (TextView) convertView.findViewById(R.id.txtvCount); convertView.setTag(holder); } else { holder = (NavHolder) convertView.getTag(); } holder.title.setText(title); String tag = tags.get(position); if (tag.equals(QueueFragment.TAG)) { int queueSize = itemAccess.getQueueSize(); if (queueSize > 0) { holder.count.setVisibility(View.VISIBLE); holder.count.setText(String.valueOf(queueSize)); } else { holder.count.setVisibility(View.GONE); } } else if (tag.equals(EpisodesFragment.TAG)) { int unreadItems = itemAccess.getNumberOfNewItems(); if (unreadItems > 0) { holder.count.setVisibility(View.VISIBLE); holder.count.setText(String.valueOf(unreadItems)); } else { holder.count.setVisibility(View.GONE); } } else if (tag.equals(SubscriptionFragment.TAG)) { int sum = itemAccess.getFeedCounterSum(); if (sum > 0) { holder.count.setVisibility(View.VISIBLE); holder.count.setText(String.valueOf(sum)); } else { holder.count.setVisibility(View.GONE); } } else if(tag.equals(DownloadsFragment.TAG) && UserPreferences.isEnableAutodownload()) { int epCacheSize = UserPreferences.getEpisodeCacheSize(); // don't count episodes that can be reclaimed int spaceUsed = itemAccess.getNumberOfDownloadedItems() - itemAccess.getReclaimableItems(); if (epCacheSize > 0 && spaceUsed >= epCacheSize) { holder.count.setText("{md-disc-full 150%}"); Iconify.addIcons(holder.count); holder.count.setVisibility(View.VISIBLE); holder.count.setOnClickListener(v -> new AlertDialog.Builder(context) .setTitle(R.string.episode_cache_full_title) .setMessage(R.string.episode_cache_full_message) .setPositiveButton(android.R.string.ok, (dialog, which) -> {}) .show() ); } else { holder.count.setVisibility(View.GONE); } } else { holder.count.setVisibility(View.GONE); } holder.image.setImageDrawable(getDrawable(tags.get(position))); return convertView; } private View getSectionDividerView(View convertView, ViewGroup parent) { LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.nav_section_item, parent, false); convertView.setEnabled(false); convertView.setOnClickListener(null); return convertView; } private View getFeedView(int position, View convertView, ViewGroup parent) { int feedPos = position - getSubscriptionOffset(); Feed feed = itemAccess.getItem(feedPos); FeedHolder holder; if (convertView == null) { holder = new FeedHolder(); LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.nav_feedlistitem, parent, false); holder.image = (ImageView) convertView.findViewById(R.id.imgvCover); holder.title = (TextView) convertView.findViewById(R.id.txtvTitle); holder.failure = (IconTextView) convertView.findViewById(R.id.itxtvFailure); holder.count = (TextView) convertView.findViewById(R.id.txtvCount); convertView.setTag(holder); } else { holder = (FeedHolder) convertView.getTag(); } Glide.with(context) .load(feed.getImageUri()) .placeholder(R.color.light_gray) .error(R.color.light_gray) .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) .fitCenter() .dontAnimate() .into(holder.image); holder.title.setText(feed.getTitle()); if(feed.hasLastUpdateFailed()) { RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) holder.title.getLayoutParams(); p.addRule(RelativeLayout.LEFT_OF, R.id.itxtvFailure); holder.failure.setVisibility(View.VISIBLE); } else { RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) holder.title.getLayoutParams(); p.addRule(RelativeLayout.LEFT_OF, R.id.txtvCount); holder.failure.setVisibility(View.GONE); } int counter = itemAccess.getFeedCounter(feed.getId()); if(counter > 0) { holder.count.setVisibility(View.VISIBLE); holder.count.setText(String.valueOf(counter)); if (itemAccess.getSelectedItemIndex() == position) { holder.count.setTypeface(null, Typeface.BOLD); } else { holder.count.setTypeface(null, Typeface.NORMAL); } } else { holder.count.setVisibility(View.GONE); } return convertView; } static class NavHolder { ImageView image; TextView title; TextView count; } static class FeedHolder { ImageView image; TextView title; IconTextView failure; TextView count; } public interface ItemAccess { int getCount(); Feed getItem(int position); int getSelectedItemIndex(); int getQueueSize(); int getNumberOfNewItems(); int getNumberOfDownloadedItems(); int getReclaimableItems(); int getFeedCounter(long feedId); int getFeedCounterSum(); } }