package de.danoeh.antennapod.fragment; import android.annotation.SuppressLint; import android.content.Context; import android.content.DialogInterface; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.support.v4.app.ListFragment; import android.support.v7.app.ActionBarActivity; import android.support.v7.widget.SearchView; import android.text.util.Linkify; import android.util.Log; import android.view.*; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import de.danoeh.antennapod.BuildConfig; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.adapter.DefaultActionButtonCallback; import de.danoeh.antennapod.adapter.InternalFeedItemlistAdapter; import de.danoeh.antennapod.asynctask.DownloadObserver; import de.danoeh.antennapod.asynctask.FeedRemover; import de.danoeh.antennapod.asynctask.ImageLoader; import de.danoeh.antennapod.dialog.ConfirmationDialog; import de.danoeh.antennapod.dialog.DownloadRequestErrorDialogCreator; import de.danoeh.antennapod.dialog.FeedItemDialog; import de.danoeh.antennapod.feed.EventDistributor; import de.danoeh.antennapod.feed.Feed; import de.danoeh.antennapod.feed.FeedItem; import de.danoeh.antennapod.feed.FeedMedia; import de.danoeh.antennapod.service.download.DownloadService; import de.danoeh.antennapod.service.download.Downloader; import de.danoeh.antennapod.storage.DBReader; import de.danoeh.antennapod.storage.DownloadRequestException; import de.danoeh.antennapod.storage.DownloadRequester; import de.danoeh.antennapod.util.QueueAccess; import de.danoeh.antennapod.util.menuhandler.FeedItemMenuHandler; import de.danoeh.antennapod.util.menuhandler.FeedMenuHandler; import de.danoeh.antennapod.util.menuhandler.MenuItemUtils; import java.util.List; /** * Displays a list of FeedItems. */ @SuppressLint("ValidFragment") public class ItemlistFragment extends ListFragment { private static final String TAG = "ItemlistFragment"; private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED | EventDistributor.DOWNLOAD_QUEUED | EventDistributor.QUEUE_UPDATE | EventDistributor.UNREAD_ITEMS_UPDATE; public static final String EXTRA_SELECTED_FEEDITEM = "extra.de.danoeh.antennapod.activity.selected_feeditem"; public static final String ARGUMENT_FEED_ID = "argument.de.danoeh.antennapod.feed_id"; protected InternalFeedItemlistAdapter adapter; private long feedID; private Feed feed; protected QueueAccess queue; private boolean itemsLoaded = false; private boolean viewsCreated = false; private DownloadObserver downloadObserver; private List downloaderList; private FeedItemDialog feedItemDialog; /** * Creates new ItemlistFragment which shows the Feeditems of a specific * feed. Sets 'showFeedtitle' to false * * @param feedId The id of the feed to show * @return the newly created instance of an ItemlistFragment */ public static ItemlistFragment newInstance(long feedId) { ItemlistFragment i = new ItemlistFragment(); Bundle b = new Bundle(); b.putLong(ARGUMENT_FEED_ID, feedId); i.setArguments(b); return i; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); setHasOptionsMenu(true); Bundle args = getArguments(); if (args == null) throw new IllegalArgumentException("args invalid"); feedID = args.getLong(ARGUMENT_FEED_ID); } @Override public void onStart() { super.onStart(); EventDistributor.getInstance().register(contentUpdate); if (downloadObserver != null) { downloadObserver.setActivity(getActivity()); downloadObserver.onResume(); } if (viewsCreated && itemsLoaded) { onFragmentLoaded(); } } @Override public void onStop() { super.onStop(); EventDistributor.getInstance().unregister(contentUpdate); stopItemLoader(); } @Override public void onResume() { super.onResume(); updateProgressBarVisibility(); startItemLoader(); } @Override public void onDetach() { super.onDetach(); stopItemLoader(); } @Override public void onDestroyView() { super.onDestroyView(); resetViewState(); } private void resetViewState() { adapter = null; viewsCreated = false; if (downloadObserver != null) { downloadObserver.onPause(); } feedItemDialog = null; } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); FeedMenuHandler.onCreateOptionsMenu(inflater, menu); final SearchView sv = new SearchView(getActivity()); MenuItemUtils.addSearchItem(menu, sv); sv.setQueryHint(getString(R.string.search_hint)); sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String s) { sv.clearFocus(); if (itemsLoaded) { ((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance(s, feed.getId())); } return true; } @Override public boolean onQueryTextChange(String s) { return false; } }); } @Override public void onPrepareOptionsMenu(Menu menu) { FeedMenuHandler.onPrepareOptionsMenu(menu, feed); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (!super.onOptionsItemSelected(item)) { try { if (!FeedMenuHandler.onOptionsItemClicked(getActivity(), item, feed)) { switch (item.getItemId()) { case R.id.remove_item: final FeedRemover remover = new FeedRemover( getActivity(), feed) { @Override protected void onPostExecute(Void result) { super.onPostExecute(result); ((MainActivity)getActivity()).loadNavFragment(MainActivity.POS_NEW, null); } }; ConfirmationDialog conDialog = new ConfirmationDialog(getActivity(), R.string.remove_feed_label, R.string.feed_delete_confirmation_msg) { @Override public void onConfirmButtonPressed( DialogInterface dialog) { dialog.dismiss(); remover.executeAsync(); } }; conDialog.createNewDialog().show(); return true; default: return false; } } else { return true; } } catch (DownloadRequestException e) { e.printStackTrace(); DownloadRequestErrorDialogCreator.newRequestErrorDialog(getActivity(), e.getMessage()); return true; } } else { return true; } } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle(""); viewsCreated = true; if (itemsLoaded) { onFragmentLoaded(); } } @Override public void onListItemClick(ListView l, View v, int position, long id) { FeedItem selection = adapter.getItem(position - l.getHeaderViewsCount()); feedItemDialog = FeedItemDialog.newInstace(getActivity(), selection, queue); feedItemDialog.show(); } private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() { @Override public void update(EventDistributor eventDistributor, Integer arg) { if ((EVENTS & arg) != 0) { if (BuildConfig.DEBUG) Log.d(TAG, "Received contentUpdate Intent."); if ((EventDistributor.DOWNLOAD_QUEUED & arg) != 0) { updateProgressBarVisibility(); } else { startItemLoader(); updateProgressBarVisibility(); } } } }; private void updateProgressBarVisibility() { if (feed != null) { if (DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFile(feed)) { ((ActionBarActivity) getActivity()) .setSupportProgressBarIndeterminateVisibility(true); } else { ((ActionBarActivity) getActivity()) .setSupportProgressBarIndeterminateVisibility(false); } getActivity().supportInvalidateOptionsMenu(); } } private void onFragmentLoaded() { if (adapter == null) { getListView().setAdapter(null); setupHeaderView(); adapter = new InternalFeedItemlistAdapter(getActivity(), itemAccess, new DefaultActionButtonCallback(getActivity()), false); setListAdapter(adapter); downloadObserver = new DownloadObserver(getActivity(), new Handler(), downloadObserverCallback); downloadObserver.onResume(); } setListShown(true); adapter.notifyDataSetChanged(); if (feedItemDialog != null) { feedItemDialog.updateContent(queue, feed.getItems()); } getActivity().supportInvalidateOptionsMenu(); } private DownloadObserver.Callback downloadObserverCallback = new DownloadObserver.Callback() { @Override public void onContentChanged() { if (adapter != null) { adapter.notifyDataSetChanged(); } if (feedItemDialog != null && feedItemDialog.isShowing()) { feedItemDialog.updateMenuAppearance(); } } @Override public void onDownloadDataAvailable(List downloaderList) { ItemlistFragment.this.downloaderList = downloaderList; if (adapter != null) { adapter.notifyDataSetChanged(); } } }; private void setupHeaderView() { if (getListView() == null || feed == null) { Log.e(TAG, "Unable to setup listview: listView = null or feed = null"); return; } LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); View header = inflater.inflate(R.layout.feeditemlist_header, null); getListView().addHeaderView(header); TextView txtvTitle = (TextView) header.findViewById(R.id.txtvTitle); TextView txtvAuthor = (TextView) header.findViewById(R.id.txtvAuthor); TextView txtvLink = (TextView) header.findViewById(R.id.txtvLink); ImageView imgvCover = (ImageView) header.findViewById(R.id.imgvCover); txtvTitle.setText(feed.getTitle()); txtvAuthor.setText(feed.getAuthor()); txtvLink.setText(feed.getLink()); Linkify.addLinks(txtvLink, Linkify.WEB_URLS); ImageLoader.getInstance().loadThumbnailBitmap(feed.getImage(), imgvCover, (int) getResources().getDimension(R.dimen.thumbnail_length_onlinefeedview)); } private InternalFeedItemlistAdapter.ItemAccess itemAccess = new InternalFeedItemlistAdapter.ItemAccess() { @Override public FeedItem getItem(int position) { return (feed != null) ? feed.getItemAtIndex(true, position) : null; } @Override public int getCount() { return (feed != null) ? feed.getNumOfItems(true) : 0; } @Override public boolean isInQueue(FeedItem item) { return (queue != null) && queue.contains(item.getId()); } @Override public int getItemDownloadProgressPercent(FeedItem item) { if (downloaderList != null) { for (Downloader downloader : downloaderList) { if (downloader.getDownloadRequest().getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA && downloader.getDownloadRequest().getFeedfileId() == item.getMedia().getId()) { return downloader.getDownloadRequest().getProgressPercent(); } } } return 0; } }; private ItemLoader itemLoader; private void startItemLoader() { if (itemLoader != null) { itemLoader.cancel(true); } itemLoader = new ItemLoader(); itemLoader.execute(feedID); } private void stopItemLoader() { if (itemLoader != null) { itemLoader.cancel(true); } } private class ItemLoader extends AsyncTask { @Override protected Object[] doInBackground(Long... params) { long feedID = params[0]; Context context = getActivity(); if (context != null) { return new Object[]{DBReader.getFeed(context, feedID), QueueAccess.IDListAccess(DBReader.getQueueIDList(context))}; } else { return null; } } @Override protected void onPostExecute(Object[] res) { super.onPostExecute(res); if (res != null) { feed = (Feed) res[0]; queue = (QueueAccess) res[1]; itemsLoaded = true; if (viewsCreated) { onFragmentLoaded(); } } } } }