diff options
author | daniel oeh <daniel.oeh@gmail.com> | 2013-09-11 15:09:11 +0200 |
---|---|---|
committer | daniel oeh <daniel.oeh@gmail.com> | 2013-09-11 15:09:11 +0200 |
commit | cef7772a90b7221de20e0a3176a8fc7d40ec9044 (patch) | |
tree | 53307e00a26e105f0cfa73518783187467f3f565 /src/de/danoeh/antennapod/fragment | |
parent | 6043f79128586bc2925b81a852f0758a53f7990c (diff) | |
parent | 30c681d1cf5e0d33b716f6c8885ab92f46efbaa3 (diff) | |
download | AntennaPod-cef7772a90b7221de20e0a3176a8fc7d40ec9044.zip |
Merge branch 'release-0975'0.9.7.5
Diffstat (limited to 'src/de/danoeh/antennapod/fragment')
8 files changed, 1013 insertions, 749 deletions
diff --git a/src/de/danoeh/antennapod/fragment/CoverFragment.java b/src/de/danoeh/antennapod/fragment/CoverFragment.java index 6be76f515..791315719 100644 --- a/src/de/danoeh/antennapod/fragment/CoverFragment.java +++ b/src/de/danoeh/antennapod/fragment/CoverFragment.java @@ -1,14 +1,13 @@ package de.danoeh.antennapod.fragment; import android.os.Bundle; +import android.support.v4.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; -import com.actionbarsherlock.app.SherlockFragment; - import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.AudioplayerActivity.AudioplayerContentFragment; @@ -16,7 +15,7 @@ import de.danoeh.antennapod.asynctask.ImageLoader; import de.danoeh.antennapod.util.playback.Playable; /** Displays the cover and the title of a FeedItem. */ -public class CoverFragment extends SherlockFragment implements +public class CoverFragment extends Fragment implements AudioplayerContentFragment { private static final String TAG = "CoverFragment"; private static final String ARG_PLAYABLE = "arg.playable"; diff --git a/src/de/danoeh/antennapod/fragment/EpisodesFragment.java b/src/de/danoeh/antennapod/fragment/EpisodesFragment.java index 4039235e0..a99056c9a 100644 --- a/src/de/danoeh/antennapod/fragment/EpisodesFragment.java +++ b/src/de/danoeh/antennapod/fragment/EpisodesFragment.java @@ -1,20 +1,16 @@ package de.danoeh.antennapod.fragment; +import android.content.Context; import android.content.Intent; +import android.os.AsyncTask; import android.os.Bundle; +import android.support.v4.app.Fragment; import android.util.Log; -import android.view.ContextMenu; +import android.view.*; import android.view.ContextMenu.ContextMenuInfo; -import android.view.LayoutInflater; -import android.view.MenuInflater; -import android.view.View; -import android.view.ViewGroup; import android.widget.ExpandableListView; import android.widget.ExpandableListView.OnChildClickListener; -import com.actionbarsherlock.app.SherlockFragment; -import com.actionbarsherlock.view.Menu; - import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.ItemviewActivity; @@ -24,11 +20,16 @@ import de.danoeh.antennapod.adapter.ExternalEpisodesListAdapter; import de.danoeh.antennapod.dialog.DownloadRequestErrorDialogCreator; import de.danoeh.antennapod.feed.EventDistributor; import de.danoeh.antennapod.feed.FeedItem; -import de.danoeh.antennapod.feed.FeedManager; +import de.danoeh.antennapod.storage.DBReader; +import de.danoeh.antennapod.storage.DBTasks; +import de.danoeh.antennapod.storage.DBWriter; import de.danoeh.antennapod.storage.DownloadRequestException; +import de.danoeh.antennapod.util.QueueAccess; import de.danoeh.antennapod.util.menuhandler.FeedItemMenuHandler; -public class EpisodesFragment extends SherlockFragment { +import java.util.List; + +public class EpisodesFragment extends Fragment { private static final String TAG = "EpisodesFragment"; private static final int EVENTS = EventDistributor.QUEUE_UPDATE @@ -40,6 +41,9 @@ public class EpisodesFragment extends SherlockFragment { private ExpandableListView listView; private ExternalEpisodesListAdapter adapter; + private List<FeedItem> queue; + private List<FeedItem> unreadItems; + protected FeedItem selectedItem = null; protected long selectedGroupId = -1; protected boolean contextMenuClosed = true; @@ -92,7 +96,7 @@ public class EpisodesFragment extends SherlockFragment { public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); adapter = new ExternalEpisodesListAdapter(getActivity(), - adapterCallback, groupActionCallback); + adapterCallback, groupActionCallback, itemAccess); listView.setAdapter(adapter); listView.expandGroup(ExternalEpisodesListAdapter.GROUP_POS_QUEUE); listView.expandGroup(ExternalEpisodesListAdapter.GROUP_POS_UNREAD); @@ -117,9 +121,73 @@ public class EpisodesFragment extends SherlockFragment { return true; } }); + loadData(); registerForContextMenu(listView); + } + ExternalEpisodesListAdapter.ItemAccess itemAccess = new ExternalEpisodesListAdapter.ItemAccess() { + + @Override + public int getQueueSize() { + return (queue != null) ? queue.size() : 0; + } + + @Override + public int getUnreadItemsSize() { + return (unreadItems != null) ? unreadItems.size() : 0; + } + + @Override + public FeedItem getQueueItemAt(int position) { + return (queue != null) ? queue.get(position) : null; + } + + @Override + public FeedItem getUnreadItemAt(int position) { + return (unreadItems != null) ? unreadItems.get(position) : null; + } + }; + + private void loadData() { + AsyncTask<Void, Void, Void> loadTask = new AsyncTask<Void, Void, Void>() { + private volatile List<FeedItem> queueRef; + private volatile List<FeedItem> unreadItemsRef; + + @Override + protected Void doInBackground(Void... voids) { + if (AppConfig.DEBUG) Log.d(TAG, "Starting to load list data"); + Context context = EpisodesFragment.this.getActivity(); + if (context != null) { + queueRef = DBReader.getQueue(context); + unreadItemsRef = DBReader.getUnreadItemsList(context); + } + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + super.onPostExecute(aVoid); + if (queueRef != null && unreadItemsRef != null) { + if (AppConfig.DEBUG) Log.d(TAG, "Done loading list data"); + queue = queueRef; + unreadItems = unreadItemsRef; + if (adapter != null) { + adapter.notifyDataSetChanged(); + } + } else { + if (queueRef == null) { + Log.e(TAG, "Could not load queue"); + } + if (unreadItemsRef == null) { + Log.e(TAG, "Could not load unread items"); + } + } + } + }; + loadTask.execute(); + } + private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() { @Override @@ -127,7 +195,7 @@ public class EpisodesFragment extends SherlockFragment { if ((EVENTS & arg) != 0) { if (AppConfig.DEBUG) Log.d(TAG, "Received contentUpdate Intent."); - adapter.notifyDataSetChanged(); + loadData(); } } }; @@ -146,13 +214,13 @@ public class EpisodesFragment extends SherlockFragment { menu.setHeaderTitle(selectedItem.getTitle()); FeedItemMenuHandler.onPrepareMenu( - new FeedItemMenuHandler.MenuInterface() { + new FeedItemMenuHandler.MenuInterface() { - @Override - public void setItemVisibility(int id, boolean visible) { - menu.findItem(id).setVisible(visible); - } - }, selectedItem, false); + @Override + public void setItemVisibility(int id, boolean visible) { + menu.findItem(id).setVisible(visible); + } + }, selectedItem, false, QueueAccess.ItemListAccess(queue)); } else if (selectedGroupId == ExternalEpisodesListAdapter.GROUP_POS_QUEUE) { menu.add(Menu.NONE, R.id.organize_queue_item, Menu.NONE, @@ -172,11 +240,10 @@ public class EpisodesFragment extends SherlockFragment { @Override public boolean onContextItemSelected(android.view.MenuItem item) { boolean handled = false; - FeedManager manager = FeedManager.getInstance(); if (selectedItem != null) { try { handled = FeedItemMenuHandler.onMenuItemClicked( - getSherlockActivity(), item.getItemId(), selectedItem); + getActivity(), item.getItemId(), selectedItem); } catch (DownloadRequestException e) { e.printStackTrace(); DownloadRequestErrorDialogCreator.newRequestErrorDialog( @@ -191,10 +258,10 @@ public class EpisodesFragment extends SherlockFragment { OrganizeQueueActivity.class)); break; case R.id.clear_queue_item: - manager.clearQueue(getActivity()); + DBWriter.clearQueue(getActivity()); break; case R.id.download_all_item: - manager.downloadAllItemsInQueue(getActivity()); + DBTasks.downloadAllItemsInQueue(getActivity()); break; default: handled = false; @@ -203,10 +270,10 @@ public class EpisodesFragment extends SherlockFragment { handled = true; switch (item.getItemId()) { case R.id.mark_all_read_item: - manager.markAllItemsRead(getActivity()); + DBWriter.markAllItemsRead(getActivity()); break; case R.id.enqueue_all_item: - manager.enqueueAllNewItems(getActivity()); + DBTasks.enqueueAllNewItems(getActivity()); break; default: handled = false; diff --git a/src/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java b/src/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java index a50e820b6..3f967bbbe 100644 --- a/src/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java +++ b/src/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java @@ -1,6 +1,7 @@ package de.danoeh.antennapod.fragment; import android.os.Bundle; +import android.support.v4.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -10,8 +11,6 @@ import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; -import com.actionbarsherlock.app.SherlockFragment; - import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.R; import de.danoeh.antennapod.asynctask.ImageLoader; @@ -24,7 +23,7 @@ import de.danoeh.antennapod.util.playback.PlaybackController; * Fragment which is supposed to be displayed outside of the MediaplayerActivity * if the PlaybackService is running */ -public class ExternalPlayerFragment extends SherlockFragment { +public class ExternalPlayerFragment extends Fragment { private static final String TAG = "ExternalPlayerFragment"; private ViewGroup fragmentLayout; @@ -139,7 +138,10 @@ public class ExternalPlayerFragment extends SherlockFragment { @Override public void loadMediaInfo() { - ExternalPlayerFragment.this.loadMediaInfo(); + ExternalPlayerFragment fragment = ExternalPlayerFragment.this; + if (fragment != null) { + fragment.loadMediaInfo(); + } } @Override @@ -174,6 +176,12 @@ public class ExternalPlayerFragment extends SherlockFragment { .newOnPlayButtonClickListener()); } } + + @Override + public void onPlaybackSpeedChange() { + // TODO Auto-generated method stub + + } }; } diff --git a/src/de/danoeh/antennapod/fragment/FeedlistFragment.java b/src/de/danoeh/antennapod/fragment/FeedlistFragment.java index c3034c2af..ed607b279 100644 --- a/src/de/danoeh/antennapod/fragment/FeedlistFragment.java +++ b/src/de/danoeh/antennapod/fragment/FeedlistFragment.java @@ -1,24 +1,18 @@ package de.danoeh.antennapod.fragment; import android.annotation.SuppressLint; -import android.app.Activity; +import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.os.AsyncTask; +import android.os.Build; import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v7.app.ActionBarActivity; +import android.support.v7.view.ActionMode; import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.GridView; -import android.widget.ListView; -import android.widget.TextView; - -import com.actionbarsherlock.app.SherlockFragment; -import com.actionbarsherlock.view.ActionMode; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuItem; - +import android.view.*; +import android.widget.*; import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.FeedItemlistActivity; @@ -28,201 +22,280 @@ import de.danoeh.antennapod.dialog.ConfirmationDialog; import de.danoeh.antennapod.dialog.DownloadRequestErrorDialogCreator; import de.danoeh.antennapod.feed.EventDistributor; import de.danoeh.antennapod.feed.Feed; -import de.danoeh.antennapod.feed.FeedManager; +import de.danoeh.antennapod.storage.DBReader; import de.danoeh.antennapod.storage.DownloadRequestException; +import de.danoeh.antennapod.storage.FeedItemStatistics; import de.danoeh.antennapod.util.menuhandler.FeedMenuHandler; -public class FeedlistFragment extends SherlockFragment implements - ActionMode.Callback, AdapterView.OnItemClickListener, - AdapterView.OnItemLongClickListener { - private static final String TAG = "FeedlistFragment"; - - private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED - | EventDistributor.DOWNLOAD_QUEUED - | EventDistributor.FEED_LIST_UPDATE - | EventDistributor.UNREAD_ITEMS_UPDATE; - - public static final String EXTRA_SELECTED_FEED = "extra.de.danoeh.antennapod.activity.selected_feed"; - - private FeedManager manager; - private FeedlistAdapter fla; - - private Feed selectedFeed; - private ActionMode mActionMode; - - private GridView gridView; - private ListView listView; - private TextView txtvEmpty; - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - } - - @Override - public void onDetach() { - super.onDetach(); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (AppConfig.DEBUG) - Log.d(TAG, "Creating"); - manager = FeedManager.getInstance(); - fla = new FeedlistAdapter(getActivity()); - - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View result = inflater.inflate(R.layout.feedlist, container, false); - listView = (ListView) result.findViewById(android.R.id.list); - gridView = (GridView) result.findViewById(R.id.grid); - txtvEmpty = (TextView) result.findViewById(android.R.id.empty); - - return result; - - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - if (listView != null) { - listView.setOnItemClickListener(this); - listView.setOnItemLongClickListener(this); - listView.setAdapter(fla); - listView.setEmptyView(txtvEmpty); - if (AppConfig.DEBUG) - Log.d(TAG, "Using ListView"); - } else { - gridView.setOnItemClickListener(this); - gridView.setOnItemLongClickListener(this); - gridView.setAdapter(fla); - gridView.setEmptyView(txtvEmpty); - if (AppConfig.DEBUG) - Log.d(TAG, "Using GridView"); - } - } - - @Override - public void onResume() { - super.onResume(); - if (AppConfig.DEBUG) - Log.d(TAG, "Resuming"); - EventDistributor.getInstance().register(contentUpdate); - fla.notifyDataSetChanged(); - } - - @Override - public void onPause() { - super.onPause(); - EventDistributor.getInstance().unregister(contentUpdate); - if (mActionMode != null) { - mActionMode.finish(); - } - } - - private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() { - - @Override - public void update(EventDistributor eventDistributor, Integer arg) { - if ((EVENTS & arg) != 0) { - if (AppConfig.DEBUG) - Log.d(TAG, "Received contentUpdate Intent."); - fla.notifyDataSetChanged(); - } - } - }; - - @Override - public boolean onCreateActionMode(ActionMode mode, Menu menu) { - FeedMenuHandler.onCreateOptionsMenu(mode.getMenuInflater(), menu); - mode.setTitle(selectedFeed.getTitle()); - return true; - } - - @Override - public boolean onPrepareActionMode(ActionMode mode, Menu menu) { - return FeedMenuHandler.onPrepareOptionsMenu(menu, selectedFeed); - } - - @SuppressLint("NewApi") - @Override - public boolean onActionItemClicked(ActionMode mode, MenuItem item) { - try { - if (FeedMenuHandler.onOptionsItemClicked(getSherlockActivity(), - item, selectedFeed)) { - fla.notifyDataSetChanged(); - } else { - switch (item.getItemId()) { - case R.id.remove_item: - final FeedRemover remover = new FeedRemover( - getSherlockActivity(), selectedFeed) { - @Override - protected void onPostExecute(Void result) { - super.onPostExecute(result); - fla.notifyDataSetChanged(); - } - }; - 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(); - break; - } - } - } catch (DownloadRequestException e) { - e.printStackTrace(); - DownloadRequestErrorDialogCreator.newRequestErrorDialog( - getActivity(), e.getMessage()); - } - mode.finish(); - return true; - } - - @Override - public void onDestroyActionMode(ActionMode mode) { - mActionMode = null; - selectedFeed = null; - fla.setSelectedItemIndex(FeedlistAdapter.SELECTION_NONE); - } - - @Override - public void onItemClick(AdapterView<?> arg0, View arg1, int position, - long id) { - Feed selection = fla.getItem(position); - Intent showFeed = new Intent(getActivity(), FeedItemlistActivity.class); - showFeed.putExtra(EXTRA_SELECTED_FEED, selection.getId()); - - getActivity().startActivity(showFeed); - } - - @Override - public boolean onItemLongClick(AdapterView<?> parent, View view, - int position, long id) { - Feed selection = fla.getItem(position); - if (AppConfig.DEBUG) - Log.d(TAG, "Selected Feed with title " + selection.getTitle()); - if (selection != null) { - if (mActionMode != null) { - mActionMode.finish(); - } - fla.setSelectedItemIndex(position); - selectedFeed = selection; - mActionMode = getSherlockActivity().startActionMode( - FeedlistFragment.this); - - } - return true; - } +import java.util.List; + +public class FeedlistFragment extends Fragment implements + ActionMode.Callback, AdapterView.OnItemClickListener, + AdapterView.OnItemLongClickListener { + private static final String TAG = "FeedlistFragment"; + + private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED + | EventDistributor.DOWNLOAD_QUEUED + | EventDistributor.FEED_LIST_UPDATE + | EventDistributor.UNREAD_ITEMS_UPDATE; + + public static final String EXTRA_SELECTED_FEED = "extra.de.danoeh.antennapod.activity.selected_feed"; + + private FeedlistAdapter fla; + private List<Feed> feeds; + private List<FeedItemStatistics> feedItemStatistics; + + private Feed selectedFeed; + private ActionMode mActionMode; + + private GridView gridView; + private ListView listView; + private TextView emptyView; + + private FeedlistAdapter.ItemAccess itemAccess = new FeedlistAdapter.ItemAccess() { + + @Override + public Feed getItem(int position) { + if (feeds != null) { + return feeds.get(position); + } else { + return null; + } + } + + @Override + public FeedItemStatistics getFeedItemStatistics(int position) { + if (feedItemStatistics != null && position < feedItemStatistics.size()) { + return feedItemStatistics.get(position); + } else { + return null; + } + } + + @Override + public int getCount() { + if (feeds != null) { + return feeds.size(); + } else { + return 0; + } + } + }; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (AppConfig.DEBUG) + Log.d(TAG, "Creating"); + fla = new FeedlistAdapter(getActivity(), itemAccess); + loadFeeds(); + } + + private void loadFeeds() { + AsyncTask<Void, Void, List[]> loadTask = new AsyncTask<Void, Void, List[]>() { + @Override + protected List[] doInBackground(Void... params) { + Context context = getActivity(); + if (context != null) { + return new List[]{DBReader.getFeedList(context), + DBReader.getFeedStatisticsList(context)}; + } else { + return null; + } + } + + + @Override + protected void onPostExecute(List[] result) { + super.onPostExecute(result); + if (result != null) { + feeds = result[0]; + feedItemStatistics = result[1]; + setEmptyViewIfListIsEmpty(); + if (fla != null) { + fla.notifyDataSetChanged(); + } + } else { + Log.e(TAG, "Failed to load feeds"); + } + } + }; + loadTask.execute(); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View result = inflater.inflate(R.layout.feedlist, container, false); + listView = (ListView) result.findViewById(android.R.id.list); + gridView = (GridView) result.findViewById(R.id.grid); + emptyView = (TextView) result.findViewById(android.R.id.empty); + + return result; + + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + if (listView != null) { + listView.setOnItemClickListener(this); + listView.setOnItemLongClickListener(this); + listView.setAdapter(fla); + listView.setEmptyView(emptyView); + if (AppConfig.DEBUG) + Log.d(TAG, "Using ListView"); + } else { + gridView.setOnItemClickListener(this); + gridView.setOnItemLongClickListener(this); + gridView.setAdapter(fla); + gridView.setEmptyView(emptyView); + if (AppConfig.DEBUG) + Log.d(TAG, "Using GridView"); + } + setEmptyViewIfListIsEmpty(); + } + + @Override + public void onResume() { + super.onResume(); + if (AppConfig.DEBUG) + Log.d(TAG, "Resuming"); + EventDistributor.getInstance().register(contentUpdate); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventDistributor.getInstance().unregister(contentUpdate); + } + + @Override + public void onPause() { + super.onPause(); + if (mActionMode != null) { + mActionMode.finish(); + } + } + + private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() { + + @Override + public void update(EventDistributor eventDistributor, Integer arg) { + if ((EVENTS & arg) != 0) { + if (AppConfig.DEBUG) + Log.d(TAG, "Received contentUpdate Intent."); + loadFeeds(); + } + } + }; + + @Override + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + FeedMenuHandler.onCreateOptionsMenu(mode.getMenuInflater(), menu); + mode.setTitle(selectedFeed.getTitle()); + return true; + } + + @Override + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + return FeedMenuHandler.onPrepareOptionsMenu(menu, selectedFeed); + } + + @SuppressLint("NewApi") + @Override + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + try { + if (FeedMenuHandler.onOptionsItemClicked(getActivity(), + item, selectedFeed)) { + loadFeeds(); + } else { + switch (item.getItemId()) { + case R.id.remove_item: + final FeedRemover remover = new FeedRemover( + getActivity(), selectedFeed) { + @Override + protected void onPostExecute(Void result) { + super.onPostExecute(result); + loadFeeds(); + } + }; + 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(); + break; + } + } + } catch (DownloadRequestException e) { + e.printStackTrace(); + DownloadRequestErrorDialogCreator.newRequestErrorDialog( + getActivity(), e.getMessage()); + } + mode.finish(); + return true; + } + + private boolean actionModeDestroyWorkaround = false; // TODO remove this workaround + private boolean skipWorkAround = Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH; + + @Override + public void onDestroyActionMode(ActionMode mode) { + if (skipWorkAround || actionModeDestroyWorkaround) { + mActionMode = null; + selectedFeed = null; + fla.setSelectedItemIndex(FeedlistAdapter.SELECTION_NONE); + actionModeDestroyWorkaround = false; + } else { + actionModeDestroyWorkaround = true; + } + } + + @Override + public void onItemClick(AdapterView<?> arg0, View arg1, int position, + long id) { + Feed selection = fla.getItem(position); + Intent showFeed = new Intent(getActivity(), FeedItemlistActivity.class); + showFeed.putExtra(EXTRA_SELECTED_FEED, selection.getId()); + + getActivity().startActivity(showFeed); + } + + @Override + public boolean onItemLongClick(AdapterView<?> parent, View view, + int position, long id) { + Feed selection = fla.getItem(position); + if (selection != null) { + if (AppConfig.DEBUG) + Log.d(TAG, "Selected Feed with title " + selection.getTitle()); + if (mActionMode != null) { + mActionMode.finish(); + } + fla.setSelectedItemIndex(position); + selectedFeed = selection; + mActionMode = ((ActionBarActivity) getActivity()).startSupportActionMode(FeedlistFragment.this); + + } + return true; + } + + private AbsListView getMainView() { + return (listView != null) ? listView : gridView; + } + + private void setEmptyViewIfListIsEmpty() { + if (getMainView() != null && emptyView != null && feeds != null) { + if (feeds.isEmpty()) { + emptyView.setText(R.string.no_feeds_label); + } + } + } } diff --git a/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java b/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java index 10f43718f..c996f497e 100644 --- a/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java +++ b/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java @@ -1,13 +1,15 @@ package de.danoeh.antennapod.fragment; +import android.content.*; +import android.support.v4.app.Fragment; +import android.support.v7.app.ActionBarActivity; +import de.danoeh.antennapod.feed.FeedItem; +import de.danoeh.antennapod.storage.DBReader; +import de.danoeh.antennapod.util.ShownotesProvider; import org.apache.commons.lang3.StringEscapeUtils; import android.annotation.SuppressLint; import android.app.Activity; -import android.content.ClipData; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; import android.content.res.TypedArray; import android.net.Uri; import android.os.AsyncTask; @@ -27,442 +29,429 @@ import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Toast; -import com.actionbarsherlock.app.SherlockFragment; - import de.danoeh.antennapod.AppConfig; -import de.danoeh.antennapod.PodcastApp; import de.danoeh.antennapod.R; -import de.danoeh.antennapod.feed.FeedItem; -import de.danoeh.antennapod.feed.FeedManager; import de.danoeh.antennapod.preferences.UserPreferences; import de.danoeh.antennapod.util.ShareUtils; import de.danoeh.antennapod.util.playback.Playable; +import java.util.concurrent.Callable; + /** Displays the description of a Playable object in a Webview. */ -public class ItemDescriptionFragment extends SherlockFragment { - - private static final String TAG = "ItemDescriptionFragment"; - - private static final String PREF = "ItemDescriptionFragmentPrefs"; - private static final String PREF_SCROLL_Y = "prefScrollY"; - private static final String PREF_PLAYABLE_ID = "prefPlayableId"; - - private static final String ARG_PLAYABLE = "arg.playable"; - - private static final String ARG_FEED_ID = "arg.feedId"; - private static final String ARG_FEED_ITEM_ID = "arg.feeditemId"; - private static final String ARG_SAVE_STATE = "arg.saveState"; - - private WebView webvDescription; - private Playable media; - - private FeedItem item; - - private AsyncTask<Void, Void, Void> webViewLoader; - - private String shownotes; - - /** URL that was selected via long-press. */ - private String selectedURL; - - /** - * True if Fragment should save its state (e.g. scrolling position) in a - * shared preference. - */ - private boolean saveState; - - public static ItemDescriptionFragment newInstance(Playable media, - boolean saveState) { - ItemDescriptionFragment f = new ItemDescriptionFragment(); - Bundle args = new Bundle(); - args.putParcelable(ARG_PLAYABLE, media); - args.putBoolean(ARG_SAVE_STATE, saveState); - f.setArguments(args); - return f; - } - - public static ItemDescriptionFragment newInstance(FeedItem item, - boolean saveState) { - ItemDescriptionFragment f = new ItemDescriptionFragment(); - Bundle args = new Bundle(); - args.putLong(ARG_FEED_ID, item.getFeed().getId()); - args.putLong(ARG_FEED_ITEM_ID, item.getId()); - args.putBoolean(ARG_SAVE_STATE, saveState); - f.setArguments(args); - return f; - } - - @SuppressLint("NewApi") - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - if (AppConfig.DEBUG) - Log.d(TAG, "Creating view"); - webvDescription = new WebView(getActivity()); - if (UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) { - if (Build.VERSION.SDK_INT >= 11 - && Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { - webvDescription.setLayerType(View.LAYER_TYPE_SOFTWARE, null); - } - webvDescription.setBackgroundColor(getResources().getColor( - R.color.black)); - } - webvDescription.getSettings().setUseWideViewPort(false); - webvDescription.getSettings().setLayoutAlgorithm( - LayoutAlgorithm.NARROW_COLUMNS); - webvDescription.getSettings().setLoadWithOverviewMode(true); - webvDescription.setOnLongClickListener(webViewLongClickListener); - webvDescription.setWebViewClient(new WebViewClient() { - - @Override - public boolean shouldOverrideUrlLoading(WebView view, String url) { - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - startActivity(intent); - return true; - } - - @Override - public void onPageFinished(WebView view, String url) { - super.onPageFinished(view, url); - if (AppConfig.DEBUG) - Log.d(TAG, "Page finished"); - // Restoring the scroll position might not always work - view.postDelayed(new Runnable() { - - @Override - public void run() { - restoreFromPreference(); - } - - }, 50); - } - - }); - registerForContextMenu(webvDescription); - return webvDescription; - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - } - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - if (AppConfig.DEBUG) - Log.d(TAG, "Fragment attached"); - } - - @Override - public void onDetach() { - super.onDetach(); - if (AppConfig.DEBUG) - Log.d(TAG, "Fragment detached"); - if (webViewLoader != null) { - webViewLoader.cancel(true); - } - } - - @Override - public void onDestroy() { - super.onDestroy(); - if (AppConfig.DEBUG) - Log.d(TAG, "Fragment destroyed"); - if (webViewLoader != null) { - webViewLoader.cancel(true); - } - } - - @SuppressLint("NewApi") - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (AppConfig.DEBUG) - Log.d(TAG, "Creating fragment"); - Bundle args = getArguments(); - saveState = args.getBoolean(ARG_SAVE_STATE, false); - if (args.containsKey(ARG_PLAYABLE)) { - media = args.getParcelable(ARG_PLAYABLE); - } else if (args.containsKey(ARG_FEED_ID) - && args.containsKey(ARG_FEED_ITEM_ID)) { - long feedId = args.getLong(ARG_FEED_ID); - long itemId = args.getLong(ARG_FEED_ITEM_ID); - FeedItem f = FeedManager.getInstance().getFeedItem(itemId, feedId); - if (f != null) { - item = f; - } - } - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - if (media != null) { - media.loadShownotes(new Playable.ShownoteLoaderCallback() { - - @Override - public void onShownotesLoaded(String shownotes) { - ItemDescriptionFragment.this.shownotes = shownotes; - if (ItemDescriptionFragment.this.shownotes != null) { - startLoader(); - } - } - }); - } else if (item != null) { - if (item.getDescription() == null - || item.getContentEncoded() == null) { - FeedManager.getInstance().loadExtraInformationOfItem( - PodcastApp.getInstance(), item, - new FeedManager.TaskCallback<String[]>() { - @Override - public void onCompletion(String[] result) { - if (result[1] != null) { - shownotes = result[1]; - } else { - shownotes = result[0]; - } - if (shownotes != null) { - startLoader(); - } - - } - }); - } else { - shownotes = item.getContentEncoded(); - startLoader(); - } - } else { - Log.e(TAG, "Error in onViewCreated: Item and media were null"); - } - } - - @Override - public void onResume() { - super.onResume(); - } - - @SuppressLint("NewApi") - private void startLoader() { - webViewLoader = createLoader(); - if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) { - webViewLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } else { - webViewLoader.execute(); - } - } - - /** - * Return the CSS style of the Webview. - * - * @param textColor - * the default color to use for the text in the webview. This - * value is inserted directly into the CSS String. - * */ - private String applyWebviewStyle(String textColor, String data) { - final String WEBVIEW_STYLE = "<html><head><style type=\"text/css\"> * { color: %s; font-family: Helvetica; line-height: 1.5em; font-size: 11pt; } a { font-style: normal; text-decoration: none; font-weight: normal; color: #00A8DF; } img { display: block; margin: 10 auto; max-width: %s; height: auto; } body { margin: %dpx %dpx %dpx %dpx; }</style></head><body>%s</body></html>"; - final int pageMargin = (int) TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, 8, getResources() - .getDisplayMetrics()); - return String.format(WEBVIEW_STYLE, textColor, "100%", pageMargin, - pageMargin, pageMargin, pageMargin, data); - } - - private View.OnLongClickListener webViewLongClickListener = new View.OnLongClickListener() { - - @Override - public boolean onLongClick(View v) { - WebView.HitTestResult r = webvDescription.getHitTestResult(); - if (r != null - && r.getType() == WebView.HitTestResult.SRC_ANCHOR_TYPE) { - if (AppConfig.DEBUG) - Log.d(TAG, - "Link of webview was long-pressed. Extra: " - + r.getExtra()); - selectedURL = r.getExtra(); - webvDescription.showContextMenu(); - return true; - } - selectedURL = null; - return false; - } - }; - - @SuppressWarnings("deprecation") - @SuppressLint("NewApi") - @Override - public boolean onContextItemSelected(MenuItem item) { - boolean handled = selectedURL != null; - if (selectedURL != null) { - switch (item.getItemId()) { - case R.id.open_in_browser_item: - Uri uri = Uri.parse(selectedURL); - getActivity() - .startActivity(new Intent(Intent.ACTION_VIEW, uri)); - break; - case R.id.share_url_item: - ShareUtils.shareLink(getActivity(), selectedURL); - break; - case R.id.copy_url_item: - if (android.os.Build.VERSION.SDK_INT >= 11) { - ClipData clipData = ClipData.newPlainText(selectedURL, - selectedURL); - android.content.ClipboardManager cm = (android.content.ClipboardManager) getActivity() - .getSystemService(Context.CLIPBOARD_SERVICE); - cm.setPrimaryClip(clipData); - } else { - android.text.ClipboardManager cm = (android.text.ClipboardManager) getActivity() - .getSystemService(Context.CLIPBOARD_SERVICE); - cm.setText(selectedURL); - } - Toast t = Toast.makeText(getActivity(), - R.string.copied_url_msg, Toast.LENGTH_SHORT); - t.show(); - break; - default: - handled = false; - break; - - } - selectedURL = null; - } - return handled; - - } - - @Override - public void onCreateContextMenu(ContextMenu menu, View v, - ContextMenuInfo menuInfo) { - if (selectedURL != null) { - super.onCreateContextMenu(menu, v, menuInfo); - menu.add(Menu.NONE, R.id.open_in_browser_item, Menu.NONE, - R.string.open_in_browser_label); - menu.add(Menu.NONE, R.id.copy_url_item, Menu.NONE, - R.string.copy_url_label); - menu.add(Menu.NONE, R.id.share_url_item, Menu.NONE, - R.string.share_url_label); - menu.setHeaderTitle(selectedURL); - } - } - - private AsyncTask<Void, Void, Void> createLoader() { - return new AsyncTask<Void, Void, Void>() { - @Override - protected void onCancelled() { - super.onCancelled(); - if (getSherlockActivity() != null) { - getSherlockActivity() - .setSupportProgressBarIndeterminateVisibility(false); - } - webViewLoader = null; - } - - String data; - - @Override - protected void onPostExecute(Void result) { - super.onPostExecute(result); - // /webvDescription.loadData(url, "text/html", "utf-8"); - webvDescription.loadDataWithBaseURL(null, data, "text/html", - "utf-8", "about:blank"); - if (getSherlockActivity() != null) { - getSherlockActivity() - .setSupportProgressBarIndeterminateVisibility(false); - } - if (AppConfig.DEBUG) - Log.d(TAG, "Webview loaded"); - webViewLoader = null; - } - - @Override - protected void onPreExecute() { - super.onPreExecute(); - if (getSherlockActivity() != null) { - getSherlockActivity() - .setSupportProgressBarIndeterminateVisibility(true); - } - } - - @Override - protected Void doInBackground(Void... params) { - if (AppConfig.DEBUG) - Log.d(TAG, "Loading Webview"); - data = ""; - data = StringEscapeUtils.unescapeHtml4(shownotes); - Activity activity = getActivity(); - if (activity != null) { - TypedArray res = getActivity() - .getTheme() - .obtainStyledAttributes( - new int[] { android.R.attr.textColorPrimary }); - int colorResource = res.getColor(0, 0); - String colorString = String.format("#%06X", - 0xFFFFFF & colorResource); - Log.i(TAG, "text color: " + colorString); - res.recycle(); - data = applyWebviewStyle(colorString, data); - } else { - cancel(true); - } - return null; - } - - }; - } - - @Override - public void onPause() { - super.onPause(); - savePreference(); - } - - private void savePreference() { - if (saveState) { - if (AppConfig.DEBUG) - Log.d(TAG, "Saving preferences"); - SharedPreferences prefs = getActivity().getSharedPreferences(PREF, - Activity.MODE_PRIVATE); - SharedPreferences.Editor editor = prefs.edit(); - if (media != null && webvDescription != null) { - if (AppConfig.DEBUG) - Log.d(TAG, - "Saving scroll position: " - + webvDescription.getScrollY()); - editor.putInt(PREF_SCROLL_Y, webvDescription.getScrollY()); - editor.putString(PREF_PLAYABLE_ID, media.getIdentifier() - .toString()); - } else { - if (AppConfig.DEBUG) - Log.d(TAG, - "savePreferences was called while media or webview was null"); - editor.putInt(PREF_SCROLL_Y, -1); - editor.putString(PREF_PLAYABLE_ID, ""); - } - editor.commit(); - } - } - - private boolean restoreFromPreference() { - if (saveState) { - if (AppConfig.DEBUG) - Log.d(TAG, "Restoring from preferences"); - Activity activity = getActivity(); - if (activity != null) { - SharedPreferences prefs = activity.getSharedPreferences( - PREF, Activity.MODE_PRIVATE); - String id = prefs.getString(PREF_PLAYABLE_ID, ""); - int scrollY = prefs.getInt(PREF_SCROLL_Y, -1); - if (scrollY != -1 && media != null - && id.equals(media.getIdentifier().toString()) - && webvDescription != null) { - if (AppConfig.DEBUG) - Log.d(TAG, "Restored scroll Position: " + scrollY); - webvDescription.scrollTo(webvDescription.getScrollX(), - scrollY); - return true; - } - } - } - return false; - } +public class ItemDescriptionFragment extends Fragment { + + private static final String TAG = "ItemDescriptionFragment"; + + private static final String PREF = "ItemDescriptionFragmentPrefs"; + private static final String PREF_SCROLL_Y = "prefScrollY"; + private static final String PREF_PLAYABLE_ID = "prefPlayableId"; + + private static final String ARG_PLAYABLE = "arg.playable"; + private static final String ARG_FEEDITEM_ID = "arg.feeditem"; + + private static final String ARG_SAVE_STATE = "arg.saveState"; + + private WebView webvDescription; + + private ShownotesProvider shownotesProvider; + private Playable media; + + + private AsyncTask<Void, Void, Void> webViewLoader; + + /** + * URL that was selected via long-press. + */ + private String selectedURL; + + /** + * True if Fragment should save its state (e.g. scrolling position) in a + * shared preference. + */ + private boolean saveState; + + public static ItemDescriptionFragment newInstance(Playable media, + boolean saveState) { + ItemDescriptionFragment f = new ItemDescriptionFragment(); + Bundle args = new Bundle(); + args.putParcelable(ARG_PLAYABLE, media); + args.putBoolean(ARG_SAVE_STATE, saveState); + f.setArguments(args); + return f; + } + + public static ItemDescriptionFragment newInstance(FeedItem item, boolean saveState) { + ItemDescriptionFragment f = new ItemDescriptionFragment(); + Bundle args = new Bundle(); + args.putLong(ARG_FEEDITEM_ID, item.getId()); + args.putBoolean(ARG_SAVE_STATE, saveState); + f.setArguments(args); + return f; + } + + @SuppressLint("NewApi") + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + if (AppConfig.DEBUG) + Log.d(TAG, "Creating view"); + webvDescription = new WebView(getActivity()); + if (UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) { + if (Build.VERSION.SDK_INT >= 11 + && Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { + webvDescription.setLayerType(View.LAYER_TYPE_SOFTWARE, null); + } + webvDescription.setBackgroundColor(getResources().getColor( + R.color.black)); + } + webvDescription.getSettings().setUseWideViewPort(false); + webvDescription.getSettings().setLayoutAlgorithm( + LayoutAlgorithm.NARROW_COLUMNS); + webvDescription.getSettings().setLoadWithOverviewMode(true); + webvDescription.setOnLongClickListener(webViewLongClickListener); + webvDescription.setWebViewClient(new WebViewClient() { + + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + try { + startActivity(intent); + } catch (ActivityNotFoundException e) { + e.printStackTrace(); + return false; + } + return true; + } + + @Override + public void onPageFinished(WebView view, String url) { + super.onPageFinished(view, url); + if (AppConfig.DEBUG) + Log.d(TAG, "Page finished"); + // Restoring the scroll position might not always work + view.postDelayed(new Runnable() { + + @Override + public void run() { + restoreFromPreference(); + } + + }, 50); + } + + }); + + registerForContextMenu(webvDescription); + return webvDescription; + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + if (AppConfig.DEBUG) + Log.d(TAG, "Fragment attached"); + } + + @Override + public void onDetach() { + super.onDetach(); + if (AppConfig.DEBUG) + Log.d(TAG, "Fragment detached"); + if (webViewLoader != null) { + webViewLoader.cancel(true); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (AppConfig.DEBUG) + Log.d(TAG, "Fragment destroyed"); + if (webViewLoader != null) { + webViewLoader.cancel(true); + } + } + + @SuppressLint("NewApi") + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (AppConfig.DEBUG) + Log.d(TAG, "Creating fragment"); + Bundle args = getArguments(); + saveState = args.getBoolean(ARG_SAVE_STATE, false); + + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + Bundle args = getArguments(); + if (args.containsKey(ARG_PLAYABLE)) { + media = args.getParcelable(ARG_PLAYABLE); + shownotesProvider = media; + startLoader(); + } else if (args.containsKey(ARG_FEEDITEM_ID)) { + AsyncTask<Void, Void, FeedItem> itemLoadTask = new AsyncTask<Void, Void, FeedItem>() { + + @Override + protected FeedItem doInBackground(Void... voids) { + return DBReader.getFeedItem(getActivity(), getArguments().getLong(ARG_FEEDITEM_ID)); + } + + @Override + protected void onPostExecute(FeedItem feedItem) { + super.onPostExecute(feedItem); + shownotesProvider = feedItem; + startLoader(); + } + }; + if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) { + itemLoadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } else { + itemLoadTask.execute(); + } + } + + + } + + @Override + public void onResume() { + super.onResume(); + } + + @SuppressLint("NewApi") + private void startLoader() { + webViewLoader = createLoader(); + if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) { + webViewLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } else { + webViewLoader.execute(); + } + } + + /** + * Return the CSS style of the Webview. + * + * @param textColor the default color to use for the text in the webview. This + * value is inserted directly into the CSS String. + */ + private String applyWebviewStyle(String textColor, String data) { + final String WEBVIEW_STYLE = "<html><head><style type=\"text/css\"> * { color: %s; font-family: Helvetica; line-height: 1.5em; font-size: 11pt; } a { font-style: normal; text-decoration: none; font-weight: normal; color: #00A8DF; } img { display: block; margin: 10 auto; max-width: %s; height: auto; } body { margin: %dpx %dpx %dpx %dpx; }</style></head><body>%s</body></html>"; + final int pageMargin = (int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, 8, getResources() + .getDisplayMetrics()); + return String.format(WEBVIEW_STYLE, textColor, "100%", pageMargin, + pageMargin, pageMargin, pageMargin, data); + } + + private View.OnLongClickListener webViewLongClickListener = new View.OnLongClickListener() { + + @Override + public boolean onLongClick(View v) { + WebView.HitTestResult r = webvDescription.getHitTestResult(); + if (r != null + && r.getType() == WebView.HitTestResult.SRC_ANCHOR_TYPE) { + if (AppConfig.DEBUG) + Log.d(TAG, + "Link of webview was long-pressed. Extra: " + + r.getExtra()); + selectedURL = r.getExtra(); + webvDescription.showContextMenu(); + return true; + } + selectedURL = null; + return false; + } + }; + + @SuppressWarnings("deprecation") + @SuppressLint("NewApi") + @Override + public boolean onContextItemSelected(MenuItem item) { + boolean handled = selectedURL != null; + if (selectedURL != null) { + switch (item.getItemId()) { + case R.id.open_in_browser_item: + Uri uri = Uri.parse(selectedURL); + getActivity() + .startActivity(new Intent(Intent.ACTION_VIEW, uri)); + break; + case R.id.share_url_item: + ShareUtils.shareLink(getActivity(), selectedURL); + break; + case R.id.copy_url_item: + if (android.os.Build.VERSION.SDK_INT >= 11) { + ClipData clipData = ClipData.newPlainText(selectedURL, + selectedURL); + android.content.ClipboardManager cm = (android.content.ClipboardManager) getActivity() + .getSystemService(Context.CLIPBOARD_SERVICE); + cm.setPrimaryClip(clipData); + } else { + android.text.ClipboardManager cm = (android.text.ClipboardManager) getActivity() + .getSystemService(Context.CLIPBOARD_SERVICE); + cm.setText(selectedURL); + } + Toast t = Toast.makeText(getActivity(), + R.string.copied_url_msg, Toast.LENGTH_SHORT); + t.show(); + break; + default: + handled = false; + break; + + } + selectedURL = null; + } + return handled; + + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, + ContextMenuInfo menuInfo) { + if (selectedURL != null) { + super.onCreateContextMenu(menu, v, menuInfo); + menu.add(Menu.NONE, R.id.open_in_browser_item, Menu.NONE, + R.string.open_in_browser_label); + menu.add(Menu.NONE, R.id.copy_url_item, Menu.NONE, + R.string.copy_url_label); + menu.add(Menu.NONE, R.id.share_url_item, Menu.NONE, + R.string.share_url_label); + menu.setHeaderTitle(selectedURL); + } + } + + private AsyncTask<Void, Void, Void> createLoader() { + return new AsyncTask<Void, Void, Void>() { + @Override + protected void onCancelled() { + super.onCancelled(); + if (getActivity() != null) { + ((ActionBarActivity) getActivity()) + .setSupportProgressBarIndeterminateVisibility(false); + } + webViewLoader = null; + } + + String data; + + @Override + protected void onPostExecute(Void result) { + super.onPostExecute(result); + // /webvDescription.loadData(url, "text/html", "utf-8"); + webvDescription.loadDataWithBaseURL(null, data, "text/html", + "utf-8", "about:blank"); + if (getActivity() != null) { + ((ActionBarActivity) getActivity()) + .setSupportProgressBarIndeterminateVisibility(false); + } + if (AppConfig.DEBUG) + Log.d(TAG, "Webview loaded"); + webViewLoader = null; + } + + @Override + protected void onPreExecute() { + super.onPreExecute(); + if (getActivity() != null) { + ((ActionBarActivity) getActivity()) + .setSupportProgressBarIndeterminateVisibility(false); + } + } + + @Override + protected Void doInBackground(Void... params) { + if (AppConfig.DEBUG) + Log.d(TAG, "Loading Webview"); + try { + Callable<String> shownotesLoadTask = shownotesProvider.loadShownotes(); + final String shownotes = shownotesLoadTask.call(); + + data = StringEscapeUtils.unescapeHtml4(shownotes); + Activity activity = getActivity(); + if (activity != null) { + TypedArray res = activity + .getTheme() + .obtainStyledAttributes( + new int[]{android.R.attr.textColorPrimary}); + int colorResource = res.getColor(0, 0); + String colorString = String.format("#%06X", + 0xFFFFFF & colorResource); + Log.i(TAG, "text color: " + colorString); + res.recycle(); + data = applyWebviewStyle(colorString, data); + } else { + cancel(true); + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + }; + } + + @Override + public void onPause() { + super.onPause(); + savePreference(); + } + + private void savePreference() { + if (saveState) { + if (AppConfig.DEBUG) + Log.d(TAG, "Saving preferences"); + SharedPreferences prefs = getActivity().getSharedPreferences(PREF, + Activity.MODE_PRIVATE); + SharedPreferences.Editor editor = prefs.edit(); + if (media != null && webvDescription != null) { + if (AppConfig.DEBUG) + Log.d(TAG, + "Saving scroll position: " + + webvDescription.getScrollY()); + editor.putInt(PREF_SCROLL_Y, webvDescription.getScrollY()); + editor.putString(PREF_PLAYABLE_ID, media.getIdentifier() + .toString()); + } else { + if (AppConfig.DEBUG) + Log.d(TAG, + "savePreferences was called while media or webview was null"); + editor.putInt(PREF_SCROLL_Y, -1); + editor.putString(PREF_PLAYABLE_ID, ""); + } + editor.commit(); + } + } + + private boolean restoreFromPreference() { + if (saveState) { + if (AppConfig.DEBUG) + Log.d(TAG, "Restoring from preferences"); + Activity activity = getActivity(); + if (activity != null) { + SharedPreferences prefs = activity.getSharedPreferences( + PREF, Activity.MODE_PRIVATE); + String id = prefs.getString(PREF_PLAYABLE_ID, ""); + int scrollY = prefs.getInt(PREF_SCROLL_Y, -1); + if (scrollY != -1 && media != null + && id.equals(media.getIdentifier().toString()) + && webvDescription != null) { + if (AppConfig.DEBUG) + Log.d(TAG, "Restored scroll Position: " + scrollY); + webvDescription.scrollTo(webvDescription.getScrollX(), + scrollY); + return true; + } + } + } + return false; + } } diff --git a/src/de/danoeh/antennapod/fragment/ItemlistFragment.java b/src/de/danoeh/antennapod/fragment/ItemlistFragment.java index 6265694f6..282bb4d5c 100644 --- a/src/de/danoeh/antennapod/fragment/ItemlistFragment.java +++ b/src/de/danoeh/antennapod/fragment/ItemlistFragment.java @@ -1,8 +1,12 @@ package de.danoeh.antennapod.fragment; import android.annotation.SuppressLint; +import android.content.Context; import android.content.Intent; +import android.os.AsyncTask; import android.os.Bundle; +import android.support.v4.app.ListFragment; +import android.support.v7.app.ActionBarActivity; import android.util.Log; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; @@ -12,27 +16,30 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ListView; -import com.actionbarsherlock.app.SherlockListFragment; +import android.widget.TextView; import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.ItemviewActivity; import de.danoeh.antennapod.adapter.ActionButtonCallback; -import de.danoeh.antennapod.adapter.DefaultFeedItemlistAdapter; import de.danoeh.antennapod.adapter.InternalFeedItemlistAdapter; import de.danoeh.antennapod.dialog.DownloadRequestErrorDialogCreator; import de.danoeh.antennapod.feed.EventDistributor; import de.danoeh.antennapod.feed.Feed; import de.danoeh.antennapod.feed.FeedItem; -import de.danoeh.antennapod.feed.FeedManager; import de.danoeh.antennapod.service.download.DownloadService; +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 java.util.Iterator; +import java.util.List; + /** Displays a list of FeedItems. */ @SuppressLint("ValidFragment") -public class ItemlistFragment extends SherlockListFragment { +public class ItemlistFragment extends ListFragment { private static final String TAG = "ItemlistFragment"; private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED @@ -43,12 +50,9 @@ public class ItemlistFragment extends SherlockListFragment { 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 fila; - protected FeedManager manager = FeedManager.getInstance(); - protected DownloadRequester requester = DownloadRequester.getInstance(); - - private DefaultFeedItemlistAdapter.ItemAccess itemAccess; private Feed feed; + protected List<Long> queue; protected FeedItem selectedItem = null; protected boolean contextMenuClosed = true; @@ -56,10 +60,10 @@ public class ItemlistFragment extends SherlockListFragment { /** Argument for FeeditemlistAdapter */ protected boolean showFeedtitle; - public ItemlistFragment(DefaultFeedItemlistAdapter.ItemAccess itemAccess, - boolean showFeedtitle) { + private AsyncTask<Long, Void, Feed> currentLoadTask; + + public ItemlistFragment(boolean showFeedtitle) { super(); - this.itemAccess = itemAccess; this.showFeedtitle = showFeedtitle; } @@ -83,51 +87,117 @@ public class ItemlistFragment extends SherlockListFragment { return i; } + private InternalFeedItemlistAdapter.ItemAccess itemAccessRef; + protected InternalFeedItemlistAdapter.ItemAccess itemAccess() { + if (itemAccessRef == null) { + itemAccessRef = 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()); + } + }; + } + return itemAccessRef; + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.feeditemlist, container, false); } - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (itemAccess == null) { - long feedId = getArguments().getLong(ARGUMENT_FEED_ID); - final Feed feed = FeedManager.getInstance().getFeed(feedId); - this.feed = feed; - itemAccess = new DefaultFeedItemlistAdapter.ItemAccess() { - - @Override - public FeedItem getItem(int position) { - return feed.getItemAtIndex(true, position); - } - - @Override - public int getCount() { - return feed.getNumOfItems(true); - } - }; - } - } + @Override + public void onStart() { + super.onStart(); + EventDistributor.getInstance().register(contentUpdate); + loadData(); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + EventDistributor.getInstance().unregister(contentUpdate); + if (currentLoadTask != null) { + currentLoadTask.cancel(true); + } + } + + protected void loadData() { + final long feedId; + if (feed == null) { + feedId = getArguments().getLong(ARGUMENT_FEED_ID); + } else { + feedId = feed.getId(); + } + AsyncTask<Long, Void, Feed> loadTask = new AsyncTask<Long, Void, Feed>(){ + private volatile List<Long> queueRef; + + @Override + protected Feed doInBackground(Long... longs) { + Context context = ItemlistFragment.this.getActivity(); + if (context != null) { + Feed result = DBReader.getFeed(context, longs[0]); + if (result != null) { + result.setItems(DBReader.getFeedItemList(context, result)); + queueRef = DBReader.getQueueIDList(context); + return result; + } + } + return null; + } + + @Override + protected void onPostExecute(Feed result) { + super.onPostExecute(result); + if (result != null && result.getItems() != null) { + feed = result; + if (queueRef != null) { + queue = queueRef; + } else { + Log.e(TAG, "Could not load queue"); + } + setEmptyViewIfListIsEmpty(); + if (fila != null) { + fila.notifyDataSetChanged(); + } + } else { + if (result == null) { + Log.e(TAG, "Could not load feed with id " + feedId); + } else if (result.getItems() == null) { + Log.e(TAG, "Could not load feed items"); + } + } + } + }; + currentLoadTask = loadTask; + loadTask.execute(feedId); + } + + private void setEmptyViewIfListIsEmpty() { + if (getListView() != null && feed != null && feed.getItems() != null) { + if (feed.getItems().isEmpty()) { + ((TextView) getActivity().findViewById(android.R.id.empty)).setText(R.string.no_items_label); + } + } + } protected InternalFeedItemlistAdapter createListAdapter() { - return new InternalFeedItemlistAdapter(getActivity(), itemAccess, + return new InternalFeedItemlistAdapter(getActivity(), itemAccess(), adapterCallback, showFeedtitle); } @Override - public void onPause() { - super.onPause(); - } - - @Override - public void onDestroy() { - super.onDestroy(); - EventDistributor.getInstance().unregister(contentUpdate); - } - - @Override public void onResume() { super.onResume(); getActivity().runOnUiThread(new Runnable() { @@ -138,7 +208,6 @@ public class ItemlistFragment extends SherlockListFragment { } }); updateProgressBarVisibility(); - EventDistributor.getInstance().register(contentUpdate); } @Override @@ -162,7 +231,9 @@ public class ItemlistFragment extends SherlockListFragment { if ((EventDistributor.DOWNLOAD_QUEUED & arg) != 0) { updateProgressBarVisibility(); } else { - fila.notifyDataSetChanged(); + if (feed != null) { + loadData(); + } updateProgressBarVisibility(); } } @@ -173,13 +244,13 @@ public class ItemlistFragment extends SherlockListFragment { if (feed != null) { if (DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFile(feed)) { - getSherlockActivity() + ((ActionBarActivity) getActivity()) .setSupportProgressBarIndeterminateVisibility(true); } else { - getSherlockActivity() + ((ActionBarActivity) getActivity()) .setSupportProgressBarIndeterminateVisibility(false); } - getSherlockActivity().supportInvalidateOptionsMenu(); + getActivity().supportInvalidateOptionsMenu(); } } @@ -218,13 +289,13 @@ public class ItemlistFragment extends SherlockListFragment { menu.setHeaderTitle(selectedItem.getTitle()); FeedItemMenuHandler.onPrepareMenu( - new FeedItemMenuHandler.MenuInterface() { + new FeedItemMenuHandler.MenuInterface() { - @Override - public void setItemVisibility(int id, boolean visible) { - menu.findItem(id).setVisible(visible); - } - }, selectedItem, false); + @Override + public void setItemVisibility(int id, boolean visible) { + menu.findItem(id).setVisible(visible); + } + }, selectedItem, false, QueueAccess.IDListAccess(queue)); } } @@ -237,7 +308,7 @@ public class ItemlistFragment extends SherlockListFragment { try { handled = FeedItemMenuHandler.onMenuItemClicked( - getSherlockActivity(), item.getItemId(), selectedItem); + getActivity(), item.getItemId(), selectedItem); } catch (DownloadRequestException e) { e.printStackTrace(); DownloadRequestErrorDialogCreator.newRequestErrorDialog( diff --git a/src/de/danoeh/antennapod/fragment/MiroGuideChannellistFragment.java b/src/de/danoeh/antennapod/fragment/MiroGuideChannellistFragment.java index c378c0acd..c6901ad17 100644 --- a/src/de/danoeh/antennapod/fragment/MiroGuideChannellistFragment.java +++ b/src/de/danoeh/antennapod/fragment/MiroGuideChannellistFragment.java @@ -10,6 +10,7 @@ import android.content.DialogInterface; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; +import android.support.v4.app.ListFragment; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -17,8 +18,6 @@ import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.ListView; -import com.actionbarsherlock.app.SherlockListFragment; - import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MiroGuideChannelViewActivity; @@ -33,7 +32,7 @@ import de.danoeh.antennapod.miroguide.model.MiroGuideChannel; * entries will be loaded until all entries have been loaded or the maximum * number of channels has been reached. * */ -public class MiroGuideChannellistFragment extends SherlockListFragment { +public class MiroGuideChannellistFragment extends ListFragment { private static final String TAG = "MiroGuideChannellistFragment"; private static final String ARG_FILTER = "filter"; diff --git a/src/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java b/src/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java index b471d5303..d20cb63c4 100644 --- a/src/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java +++ b/src/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java @@ -1,33 +1,53 @@ package de.danoeh.antennapod.fragment; +import android.content.Context; +import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import de.danoeh.antennapod.AppConfig; -import de.danoeh.antennapod.adapter.DefaultFeedItemlistAdapter; +import de.danoeh.antennapod.adapter.InternalFeedItemlistAdapter; import de.danoeh.antennapod.feed.EventDistributor; import de.danoeh.antennapod.feed.FeedItem; -import de.danoeh.antennapod.feed.FeedManager; +import de.danoeh.antennapod.storage.DBReader; + +import java.util.Iterator; +import java.util.List; public class PlaybackHistoryFragment extends ItemlistFragment { private static final String TAG = "PlaybackHistoryFragment"; + private List<FeedItem> playbackHistory; + public PlaybackHistoryFragment() { - super(new DefaultFeedItemlistAdapter.ItemAccess() { + super(true); + } - @Override - public FeedItem getItem(int position) { - return FeedManager.getInstance().getPlaybackHistoryItemIndex( - position); - } + InternalFeedItemlistAdapter.ItemAccess itemAccessRef; + @Override + protected InternalFeedItemlistAdapter.ItemAccess itemAccess() { + if (itemAccessRef == null) { + itemAccessRef = new InternalFeedItemlistAdapter.ItemAccess() { - @Override - public int getCount() { - return FeedManager.getInstance().getPlaybackHistorySize(); - } - }, true); - } + @Override + public FeedItem getItem(int position) { + return (playbackHistory != null) ? playbackHistory.get(position) : null; + } - @Override + @Override + public int getCount() { + return (playbackHistory != null) ? playbackHistory.size() : 0; + } + + @Override + public boolean isInQueue(FeedItem item) { + return (queue != null) ? queue.contains(item.getId()) : false; + } + }; + } + return itemAccessRef; + } + + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EventDistributor.getInstance().register(historyUpdate); @@ -46,10 +66,48 @@ public class PlaybackHistoryFragment extends ItemlistFragment { if ((EventDistributor.PLAYBACK_HISTORY_UPDATE & arg) != 0) { if (AppConfig.DEBUG) Log.d(TAG, "Received content update"); - fila.notifyDataSetChanged(); + loadData(); } } }; + @Override + protected void loadData() { + AsyncTask<Void, Void, Void> loadTask = new AsyncTask<Void, Void, Void>() { + private volatile List<FeedItem> phRef; + private volatile List<Long> queueRef; + + @Override + protected Void doInBackground(Void... voids) { + Context context = PlaybackHistoryFragment.this.getActivity(); + if (context != null) { + queueRef = DBReader.getQueueIDList(context); + phRef = DBReader.getPlaybackHistory(context); + } + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + super.onPostExecute(aVoid); + if (queueRef != null && phRef != null) { + queue = queueRef; + playbackHistory = phRef; + Log.i(TAG, "Number of items in playback history: " + playbackHistory.size()); + if (fila != null) { + fila.notifyDataSetChanged(); + } + } else { + if (queueRef == null) { + Log.e(TAG, "Could not load queue"); + } + if (phRef == null) { + Log.e(TAG, "Could not load playback history"); + } + } + } + }; + loadTask.execute(); + } } |