diff options
25 files changed, 341 insertions, 163 deletions
diff --git a/app/build.gradle b/app/build.gradle index 90d0c108e..e18708878 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,6 +12,7 @@ dependencies { compile 'com.android.support:appcompat-v7:22.2.1' compile 'com.android.support:gridlayout-v7:22.2.1' compile 'com.android.support:cardview-v7:22.2.1' + compile 'com.android.support:design:22.2.1' compile 'org.apache.commons:commons-lang3:3.3.2' compile('org.shredzone.flattr4j:flattr4j-core:2.12') { exclude group: 'org.json', module: 'json' @@ -25,6 +26,8 @@ dependencies { compile 'de.greenrobot:eventbus:2.4.0' compile 'io.reactivex:rxandroid:1.0.1' compile 'com.joanzapata.iconify:android-iconify-fontawesome:2.0.3' + compile 'com.afollestad:material-dialogs:0.7.8.0' + compile project(':core') compile project(':library:drag-sort-listview') diff --git a/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java b/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java index 286095210..4988d1020 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java @@ -18,9 +18,8 @@ import de.danoeh.antennapod.activity.OnlineFeedViewActivity; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.PodDBAdapter; -import de.danoeh.antennapod.fragment.AllEpisodesFragment; import de.danoeh.antennapod.fragment.DownloadsFragment; -import de.danoeh.antennapod.fragment.NewEpisodesFragment; +import de.danoeh.antennapod.fragment.EpisodesFragment; import de.danoeh.antennapod.fragment.PlaybackHistoryFragment; import de.danoeh.antennapod.fragment.QueueFragment; import de.danoeh.antennapod.preferences.PreferenceController; @@ -98,17 +97,11 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv solo.waitForView(android.R.id.list); assertEquals(solo.getString(R.string.queue_label), getActionbarTitle()); - // new episodes + // episodes openNavDrawer(); - solo.clickOnText(solo.getString(R.string.new_episodes_label)); + solo.clickOnText(solo.getString(R.string.episodes_label)); solo.waitForView(android.R.id.list); - assertEquals(solo.getString(R.string.new_episodes_label), getActionbarTitle()); - - // all episodes - openNavDrawer(); - solo.clickOnText(solo.getString(R.string.all_episodes_label)); - solo.waitForView(android.R.id.list); - assertEquals(solo.getString(R.string.all_episodes_label), getActionbarTitle()); + assertEquals(solo.getString(R.string.episodes_label), getActionbarTitle()); // downloads openNavDrawer(); @@ -156,18 +149,18 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv openNavDrawer(); solo.clickLongOnText(solo.getString(R.string.queue_label)); solo.waitForDialogToOpen(); - solo.clickOnText(solo.getString(R.string.all_episodes_label)); + solo.clickOnText(solo.getString(R.string.episodes_label)); solo.clickOnText(solo.getString(R.string.playback_history_label)); solo.clickOnText(solo.getString(R.string.confirm_label)); solo.waitForDialogToClose(); List<String> hidden = UserPreferences.getHiddenDrawerItems(); assertEquals(2, hidden.size()); - assertTrue(hidden.contains(AllEpisodesFragment.TAG)); + assertTrue(hidden.contains(EpisodesFragment.TAG)); assertTrue(hidden.contains(PlaybackHistoryFragment.TAG)); } public void testDrawerPreferencesUnhideSomeElements() { - List<String> hidden = Arrays.asList(NewEpisodesFragment.TAG, DownloadsFragment.TAG); + List<String> hidden = Arrays.asList(PlaybackHistoryFragment.TAG, DownloadsFragment.TAG); UserPreferences.setHiddenDrawerItems(getInstrumentation().getTargetContext(), hidden); openNavDrawer(); solo.clickLongOnText(solo.getString(R.string.queue_label)); @@ -179,7 +172,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv hidden = UserPreferences.getHiddenDrawerItems(); assertEquals(2, hidden.size()); assertTrue(hidden.contains(QueueFragment.TAG)); - assertTrue(hidden.contains(NewEpisodesFragment.TAG)); + assertTrue(hidden.contains(PlaybackHistoryFragment.TAG)); } public void testDrawerPreferencesHideAllElements() { @@ -195,7 +188,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv solo.clickOnText(solo.getString(R.string.confirm_label)); solo.waitForDialogToClose(); List<String> hidden = UserPreferences.getHiddenDrawerItems(); - assertEquals(6, hidden.size()); + assertEquals(titles.length, hidden.size()); for(String tag : MainActivity.NAV_DRAWER_TAGS) { assertTrue(hidden.contains(tag)); } diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java index 775bc0ecd..8f32f86bb 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java @@ -86,8 +86,8 @@ public class PlaybackTest extends ActivityInstrumentationTestCase2<MainActivity> private void startLocalPlayback() { openNavDrawer(); - - solo.clickOnText(solo.getString(R.string.all_episodes_label)); + solo.clickOnText(solo.getString(R.string.episodes_label)); + solo.clickOnText(solo.getString(R.string.all_episodes_short_label)); final List<FeedItem> episodes = DBReader.getRecentlyPublishedEpisodes(context, 10); assertTrue(solo.waitForView(solo.getView(R.id.butSecondaryAction))); diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java index e10e8041e..7f3e2399f 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java @@ -45,11 +45,10 @@ import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.StorageUtils; 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.ExternalPlayerFragment; import de.danoeh.antennapod.fragment.ItemlistFragment; -import de.danoeh.antennapod.fragment.NewEpisodesFragment; import de.danoeh.antennapod.fragment.PlaybackHistoryFragment; import de.danoeh.antennapod.fragment.QueueFragment; import de.danoeh.antennapod.menuhandler.NavDrawerActivity; @@ -82,8 +81,7 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity public static final String[] NAV_DRAWER_TAGS = { QueueFragment.TAG, - NewEpisodesFragment.TAG, - AllEpisodesFragment.TAG, + EpisodesFragment.TAG, DownloadsFragment.TAG, PlaybackHistoryFragment.TAG, AddFeedFragment.TAG @@ -169,10 +167,17 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity transaction.replace(R.id.main_view, mainFragment); } else { String lastFragment = getLastNavFragment(); - if(ArrayUtils.contains(NAV_DRAWER_TAGS, lastFragment)) { + if (ArrayUtils.contains(NAV_DRAWER_TAGS, lastFragment)) { loadFragment(lastFragment, null); } else { - loadFeedFragmentById(Integer.valueOf(lastFragment), null); + try { + loadFeedFragmentById(Integer.valueOf(lastFragment), null); + } catch (NumberFormatException e) { + // it's not a number, this happens if we removed + // a label from the NAV_DRAWER_TAGS + // give them a nice default... + loadFragment(QueueFragment.TAG, null); + } } } externalPlayerFragment = new ExternalPlayerFragment(); @@ -281,11 +286,8 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity case QueueFragment.TAG: fragment = new QueueFragment(); break; - case NewEpisodesFragment.TAG: - fragment = new NewEpisodesFragment(); - break; - case AllEpisodesFragment.TAG: - fragment = new AllEpisodesFragment(); + case EpisodesFragment.TAG: + fragment = new EpisodesFragment(); break; case DownloadsFragment.TAG: fragment = new DownloadsFragment(); @@ -296,6 +298,10 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity case AddFeedFragment.TAG: fragment = new AddFeedFragment(); break; + default: + // default to the queue + fragment = new QueueFragment(); + break; } currentTitle = navAdapter.getLabel(tag); getSupportActionBar().setTitle(currentTitle); @@ -538,7 +544,7 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity protected void onPostExecute(Void result) { super.onPostExecute(result); if(getSelectedNavListIndex() == position) { - loadFragment(NewEpisodesFragment.TAG, null); + loadFragment(EpisodesFragment.TAG, null); } } }; diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java b/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java index c3486f2f2..b9247e76b 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java @@ -93,7 +93,7 @@ public class DefaultActionButtonCallback implements ActionButtonCallback { } } else { if (!item.isPlayed()) { - DBWriter.markItemRead(context, item, true, true); + DBWriter.markItemPlayed(context, item, FeedItem.PLAYED, true); } } } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java index c3bf8faa5..183c1a44e 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java @@ -33,6 +33,7 @@ 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; @@ -94,6 +95,9 @@ public class NavListAdapter extends BaseAdapter 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; @@ -212,7 +216,7 @@ public class NavListAdapter extends BaseAdapter } else { holder.count.setVisibility(View.GONE); } - } else if (tags.get(position).equals(NewEpisodesFragment.TAG)) { + } else if (tags.get(position).equals(EpisodesFragment.TAG)) { int unreadItems = itemAccess.getNumberOfNewItems(); if (unreadItems > 0) { holder.count.setVisibility(View.VISIBLE); diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java index 0751ee602..dbc99b21a 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java @@ -372,12 +372,12 @@ public class EpisodesApplyActionFragment extends Fragment { } private void markedCheckedPlayed() { - DBWriter.markItemRead(getActivity(), true, checkedIds.toArray()); + DBWriter.markItemPlayed(getActivity(), FeedItem.PLAYED, checkedIds.toArray()); close(); } private void markedCheckedUnplayed() { - DBWriter.markItemRead(getActivity(), false, checkedIds.toArray()); + DBWriter.markItemPlayed(getActivity(), FeedItem.UNPLAYED, checkedIds.toArray()); close(); } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java index b4c4f1822..d55466b10 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java @@ -105,7 +105,6 @@ public class AllEpisodesFragment extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setRetainInstance(true); setHasOptionsMenu(true); } @@ -270,16 +269,14 @@ public class AllEpisodesFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return onCreateViewHelper(inflater, container, savedInstanceState, - R.layout.all_episodes_fragment, R.string.all_episodes_label); + R.layout.all_episodes_fragment); } protected View onCreateViewHelper(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState, - int fragmentResource, - int titleString) { + int fragmentResource) { super.onCreateView(inflater, container, savedInstanceState); - ((MainActivity) getActivity()).getSupportActionBar().setTitle(titleString); View root = inflater.inflate(fragmentResource, container, false); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java index 1ce379cf8..52a38ccb9 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java @@ -1,7 +1,10 @@ package de.danoeh.antennapod.fragment; +import android.content.Context; +import android.content.SharedPreferences; import android.content.res.Resources; import android.os.Bundle; +import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; @@ -25,15 +28,24 @@ public class DownloadsFragment extends Fragment { public static final int POS_COMPLETED = 1; public static final int POS_LOG = 2; - private ViewPager pager; + private static final String PREF_LAST_TAB_POSITION = "tab_position"; + + private ViewPager viewPager; + private TabLayout tabLayout; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); View root = inflater.inflate(R.layout.pager_fragment, container, false); - pager = (ViewPager) root.findViewById(R.id.pager); + + viewPager = (ViewPager)root.findViewById(R.id.viewpager); DownloadsPagerAdapter pagerAdapter = new DownloadsPagerAdapter(getChildFragmentManager(), getResources()); - pager.setAdapter(pagerAdapter); + viewPager.setAdapter(pagerAdapter); + + // Give the TabLayout the ViewPager + tabLayout = (TabLayout) root.findViewById(R.id.sliding_tabs); + tabLayout.setupWithViewPager(viewPager); + return root; } @@ -42,10 +54,30 @@ public class DownloadsFragment extends Fragment { super.onViewCreated(view, savedInstanceState); if (getArguments() != null) { int tab = getArguments().getInt(ARG_SELECTED_TAB); - pager.setCurrentItem(tab, false); + viewPager.setCurrentItem(tab, false); } } + @Override + public void onPause() { + super.onPause(); + // save our tab selection + SharedPreferences prefs = getActivity().getSharedPreferences(TAG, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = prefs.edit(); + editor.putInt(PREF_LAST_TAB_POSITION, tabLayout.getSelectedTabPosition()); + editor.apply(); + } + + @Override + public void onStart() { + super.onStart(); + + // restore our last position + SharedPreferences prefs = getActivity().getSharedPreferences(TAG, Context.MODE_PRIVATE); + int lastPosition = prefs.getInt(PREF_LAST_TAB_POSITION, 0); + viewPager.setCurrentItem(lastPosition); + } + public class DownloadsPagerAdapter extends FragmentPagerAdapter { Resources resources; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java new file mode 100644 index 000000000..e234d95ad --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java @@ -0,0 +1,115 @@ +package de.danoeh.antennapod.fragment; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.res.Resources; +import android.os.Bundle; +import android.support.design.widget.TabLayout; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.activity.MainActivity; + +public class EpisodesFragment extends Fragment { + + public static final String TAG = "EpisodesFragment"; + private static final String PREF_LAST_TAB_POSITION = "tab_position"; + + public static final int POS_NEW_EPISODES = 0; + public static final int POS_ALL_EPISODES = 1; + public static final int TOTAL_COUNT = 2; + + + private TabLayout tabLayout; + private ViewPager viewPager; + + //Mandatory Constructor + public EpisodesFragment() { + } + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setRetainInstance(true); + } + + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + setHasOptionsMenu(true); + ((MainActivity) getActivity()).getSupportActionBar().setTitle(R.string.episodes_label); + + View rootView = inflater.inflate(R.layout.pager_fragment, container, false); + viewPager = (ViewPager)rootView.findViewById(R.id.viewpager); + viewPager.setAdapter(new EpisodesPagerAdapter(getChildFragmentManager(), getResources())); + + // Give the TabLayout the ViewPager + tabLayout = (TabLayout) rootView.findViewById(R.id.sliding_tabs); + tabLayout.setupWithViewPager(viewPager); + + return rootView; + } + + @Override + public void onPause() { + super.onPause(); + // save our tab selection + SharedPreferences prefs = getActivity().getSharedPreferences(TAG, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = prefs.edit(); + editor.putInt(PREF_LAST_TAB_POSITION, tabLayout.getSelectedTabPosition()); + editor.apply(); + } + + @Override + public void onStart() { + super.onStart(); + + // restore our last position + SharedPreferences prefs = getActivity().getSharedPreferences(TAG, Context.MODE_PRIVATE); + int lastPosition = prefs.getInt(PREF_LAST_TAB_POSITION, 0); + viewPager.setCurrentItem(lastPosition); + } + + public static class EpisodesPagerAdapter extends FragmentPagerAdapter { + + private final Resources resources; + + public EpisodesPagerAdapter(FragmentManager fm, Resources resources) { + super(fm); + this.resources = resources; + } + + @Override + public Fragment getItem(int position) { + switch (position) { + case POS_ALL_EPISODES: + return new AllEpisodesFragment(); + case POS_NEW_EPISODES: + return new NewEpisodesFragment(); + } + return null; + } + + @Override + public int getCount() { + return TOTAL_COUNT; + } + + @Override + public CharSequence getPageTitle(int position) { + switch (position) { + case POS_ALL_EPISODES: + return resources.getString(R.string.all_episodes_short_label); + case POS_NEW_EPISODES: + return resources.getString(R.string.new_label); + default: + return super.getPageTitle(position); + } + } + } +} diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java index 9a25674b6..6c2271d79 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java @@ -13,7 +13,6 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.QueueEvent; -import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.gui.FeedItemUndoToken; @@ -64,7 +63,7 @@ public class NewEpisodesFragment extends AllEpisodesFragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = super.onCreateViewHelper(inflater, container, savedInstanceState, - R.layout.new_episodes_fragment, R.string.new_episodes_label); + R.layout.new_episodes_fragment); listView.setRemoveListener(new DragSortListView.RemoveListener() { @Override @@ -72,7 +71,9 @@ public class NewEpisodesFragment extends AllEpisodesFragment { Log.d(TAG, "remove(" + which + ")"); stopItemLoader(); FeedItem item = (FeedItem) listView.getAdapter().getItem(which); - DBWriter.markItemRead(getActivity(), true, item.getId()); + // we're marking it as unplayed since the user didn't actually play it + // but they don't want it considered 'NEW' anymore + DBWriter.markItemPlayed(getActivity(), FeedItem.UNPLAYED, item.getId()); undoBarController.showUndoBar(false, getString(R.string.marked_as_read_label), new FeedItemUndoToken(item, which) @@ -88,7 +89,7 @@ public class NewEpisodesFragment extends AllEpisodesFragment { public void onUndo(FeedItemUndoToken token) { if (token != null) { long itemId = token.getFeedItemId(); - DBWriter.markItemRead(context, false, itemId); + DBWriter.markItemPlayed(context, FeedItem.NEW, itemId); } } @Override diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java index 55d4b940f..aff5069c6 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java @@ -1,7 +1,10 @@ package de.danoeh.antennapod.fragment.gpodnet; +import android.content.Context; +import android.content.SharedPreferences; import android.content.res.Resources; import android.os.Bundle; +import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; @@ -17,16 +20,49 @@ import de.danoeh.antennapod.R; */ public class GpodnetMainFragment extends Fragment { + public static final String TAG = "GpodnetMainFragment"; + + private static final String PREF_LAST_TAB_POSITION = "tab_position"; + private TabLayout tabLayout; + private ViewPager viewPager; + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); View root = inflater.inflate(R.layout.pager_fragment, container, false); - ViewPager pager = (ViewPager) root.findViewById(R.id.pager); + + viewPager = (ViewPager)root.findViewById(R.id.viewpager); GpodnetPagerAdapter pagerAdapter = new GpodnetPagerAdapter(getChildFragmentManager(), getResources()); - pager.setAdapter(pagerAdapter); + viewPager.setAdapter(pagerAdapter); + + // Give the TabLayout the ViewPager + tabLayout = (TabLayout) root.findViewById(R.id.sliding_tabs); + tabLayout.setupWithViewPager(viewPager); + return root; } + + @Override + public void onPause() { + super.onPause(); + // save our tab selection + SharedPreferences prefs = getActivity().getSharedPreferences(TAG, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = prefs.edit(); + editor.putInt(PREF_LAST_TAB_POSITION, tabLayout.getSelectedTabPosition()); + editor.apply(); + } + + @Override + public void onStart() { + super.onStart(); + + // restore our last position + SharedPreferences prefs = getActivity().getSharedPreferences(TAG, Context.MODE_PRIVATE); + int lastPosition = prefs.getInt(PREF_LAST_TAB_POSITION, 0); + viewPager.setCurrentItem(lastPosition); + } + public class GpodnetPagerAdapter extends FragmentPagerAdapter { diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java index 3e2fdf24f..014b44078 100644 --- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java +++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java @@ -155,7 +155,7 @@ public class FeedItemMenuHandler { break; case R.id.mark_read_item: selectedItem.setPlayed(true); - DBWriter.markItemRead(context, selectedItem, true, false); + DBWriter.markItemPlayed(context, selectedItem, FeedItem.PLAYED, false); if(GpodnetPreferences.loggedIn()) { FeedMedia media = selectedItem.getMedia(); // not all items have media, Gpodder only cares about those that do @@ -173,7 +173,7 @@ public class FeedItemMenuHandler { break; case R.id.mark_unread_item: selectedItem.setPlayed(false); - DBWriter.markItemRead(context, selectedItem, false, false); + DBWriter.markItemPlayed(context, selectedItem, FeedItem.UNPLAYED, false); if(GpodnetPreferences.loggedIn()) { GpodnetEpisodeAction actionNew = new GpodnetEpisodeAction.Builder(selectedItem, Action.NEW) .currentDeviceId() @@ -195,7 +195,7 @@ public class FeedItemMenuHandler { break; case R.id.reset_position: selectedItem.getMedia().setPosition(0); - DBWriter.markItemRead(context, selectedItem, false, true); + DBWriter.markItemPlayed(context, selectedItem, FeedItem.UNPLAYED, true); break; case R.id.activate_auto_download: selectedItem.setAutoDownload(true); diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java index 4d4b2be63..3c9bf464c 100644 --- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java +++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java @@ -20,9 +20,10 @@ import android.text.TextWatcher; import android.text.format.DateFormat; import android.util.Log; import android.widget.EditText; -import android.widget.TimePicker; import android.widget.Toast; +import com.afollestad.materialdialogs.MaterialDialog; + import java.io.File; import java.util.ArrayList; import java.util.Arrays; @@ -586,17 +587,15 @@ public class PreferenceController { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.drawer_preferences); - builder.setMultiChoiceItems(navTitles, checked, new DialogInterface.OnMultiChoiceClickListener() { - @Override - public void onClick(DialogInterface dialog, int which, boolean isChecked) { - if (isChecked) { - hiddenDrawerItems.remove(NAV_DRAWER_TAGS[which]); - } else { - hiddenDrawerItems.add(NAV_DRAWER_TAGS[which]); - } + builder.setMultiChoiceItems(navTitles, checked, (dialog, which, isChecked) -> { + if (isChecked) { + hiddenDrawerItems.remove(NAV_DRAWER_TAGS[which]); + } else { + hiddenDrawerItems.add(NAV_DRAWER_TAGS[which]); } }); - builder.setPositiveButton(R.string.confirm_label, new DialogInterface.OnClickListener() { + builder.setPositiveButton(R.string.confirm_label, new DialogInterface + .OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { UserPreferences.setHiddenDrawerItems(context, hiddenDrawerItems); @@ -609,69 +608,64 @@ public class PreferenceController { private void showUpdateIntervalTimePreferencesDialog() { final Context context = ui.getActivity(); - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(R.string.pref_autoUpdateIntervallOrTime_title); - builder.setMessage(R.string.pref_autoUpdateIntervallOrTime_message); - builder.setNegativeButton(R.string.pref_autoUpdateIntervallOrTime_Disable, new DialogInterface.OnClickListener() { + MaterialDialog.Builder builder = new MaterialDialog.Builder(context); + builder.title(R.string.pref_autoUpdateIntervallOrTime_title); + builder.content(R.string.pref_autoUpdateIntervallOrTime_message); + builder.positiveText(R.string.pref_autoUpdateIntervallOrTime_Interval); + builder.negativeText(R.string.pref_autoUpdateIntervallOrTime_TimeOfDay); + builder.neutralText(R.string.pref_autoUpdateIntervallOrTime_Disable); + builder.callback(new MaterialDialog.ButtonCallback() { @Override - public void onClick(DialogInterface dialog, int which) { - UserPreferences.setUpdateInterval(0); - } - }); - builder.setNeutralButton(R.string.pref_autoUpdateIntervallOrTime_Interval, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { + public void onPositive(MaterialDialog dialog) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(context.getString(R.string.pref_autoUpdateIntervallOrTime_Interval)); final String[] values = context.getResources().getStringArray(R.array.update_intervall_values); final String[] entries = getUpdateIntervalEntries(values); - builder.setSingleChoiceItems(entries, -1, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - int hours = Integer.valueOf(values[which]); - UserPreferences.setUpdateInterval(hours); - dialog.dismiss(); - } + builder.setSingleChoiceItems(entries, -1, (dialog1, which) -> { + int hours = Integer.valueOf(values[which]); + UserPreferences.setUpdateInterval(hours); + dialog1.dismiss(); }); builder.setNegativeButton(context.getString(R.string.cancel_label), null); builder.show(); } - }); - builder.setPositiveButton(R.string.pref_autoUpdateIntervallOrTime_TimeOfDay, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - int hourOfDay = 7, minute = 0; - int[] updateTime = UserPreferences.getUpdateTimeOfDay(); - if (updateTime.length == 2) { - hourOfDay = updateTime[0]; - minute = updateTime[1]; - } - TimePickerDialog timePickerDialog = new TimePickerDialog(context, new TimePickerDialog.OnTimeSetListener() { - @Override - public void onTimeSet(TimePicker view, int hourOfDay, int minute) { - if (view.getTag() == null) { // onTimeSet() may get called twice! - view.setTag("TAGGED"); - UserPreferences.setUpdateTimeOfDay(hourOfDay, minute); - } + + @Override + public void onNegative(MaterialDialog dialog) { + int hourOfDay = 7, minute = 0; + int[] updateTime = UserPreferences.getUpdateTimeOfDay(); + if (updateTime.length == 2) { + hourOfDay = updateTime[0]; + minute = updateTime[1]; + } + TimePickerDialog timePickerDialog = new TimePickerDialog(context, + (view, selectedHourOfDay, selectedMinute) -> { + if (view.getTag() == null) { // onTimeSet() may get called twice! + view.setTag("TAGGED"); + UserPreferences.setUpdateTimeOfDay(selectedHourOfDay, selectedMinute); } }, hourOfDay, minute, DateFormat.is24HourFormat(context)); - timePickerDialog.setTitle(context.getString(R.string.pref_autoUpdateIntervallOrTime_TimeOfDay)); - timePickerDialog.show(); - } - } + timePickerDialog.setTitle(context.getString(R.string.pref_autoUpdateIntervallOrTime_TimeOfDay)); + timePickerDialog.show(); + } - ); + @Override + public void onNeutral(MaterialDialog dialog) { + UserPreferences.setUpdateInterval(0); + } + }); + builder.forceStacking(true); builder.show(); } - public static interface PreferenceUI { + public interface PreferenceUI { /** * Finds a preference based on its key. */ - public Preference findPreference(CharSequence key); + Preference findPreference(CharSequence key); - public Activity getActivity(); + Activity getActivity(); } } diff --git a/app/src/main/java/de/danoeh/antennapod/service/PlayerWidgetService.java b/app/src/main/java/de/danoeh/antennapod/service/PlayerWidgetService.java index 990b3bd54..0f726f214 100644 --- a/app/src/main/java/de/danoeh/antennapod/service/PlayerWidgetService.java +++ b/app/src/main/java/de/danoeh/antennapod/service/PlayerWidgetService.java @@ -16,7 +16,6 @@ import android.widget.RemoteViews; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; -import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.receiver.MediaButtonReceiver; import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.service.playback.PlayerStatus; @@ -59,7 +58,7 @@ public class PlayerWidgetService extends Service { if (media.hasAlmostEnded()) { Log.d(TAG, "smart mark as read"); FeedItem item = media.getItem(); - DBWriter.markItemRead(this, item, true, false); + DBWriter.markItemPlayed(this, item, FeedItem.PLAYED, false); DBWriter.removeQueueItem(this, item, false); DBWriter.addItemToPlaybackHistory(this, media); if (item.getFeed().getPreferences().getCurrentAutoDelete()) { diff --git a/app/src/main/res/layout/pager_fragment.xml b/app/src/main/res/layout/pager_fragment.xml index ed639a2db..54b711b1c 100644 --- a/app/src/main/res/layout/pager_fragment.xml +++ b/app/src/main/res/layout/pager_fragment.xml @@ -1,18 +1,22 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> - <android.support.v4.view.ViewPager - android:id="@+id/pager" + + <android.support.design.widget.TabLayout + android:id="@+id/sliding_tabs" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="wrap_content" + app:tabGravity="fill" + app:tabMode="fixed" /> - <android.support.v4.view.PagerTabStrip - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_gravity="top" /> - </android.support.v4.view.ViewPager> + <android.support.v4.view.ViewPager + android:id="@+id/viewpager" + android:layout_width="match_parent" + android:layout_height="0px" + android:layout_weight="1" /> </LinearLayout>
\ No newline at end of file diff --git a/core/build.gradle b/core/build.gradle index b88780772..4b1ab98a6 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -36,7 +36,7 @@ dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:support-v4:22.2.1' compile 'com.android.support:appcompat-v7:22.2.1' - compile 'com.android.support:support-v4:22.2.1' + compile 'com.android.support:design:22.2.1' compile 'org.apache.commons:commons-lang3:3.3.2' compile ('org.shredzone.flattr4j:flattr4j-core:2.12') { exclude group: 'org.json', module: 'json' diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java index 9dbf6cc61..ddb71fa7e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java @@ -391,7 +391,7 @@ public class FeedMedia extends FeedFile implements Playable { public void saveCurrentPosition(SharedPreferences pref, int newPosition) { DBWriter.setFeedMediaPlaybackInformation(ClientConfig.applicationCallbacks.getApplicationInstance(), this); if(item.isNew()) { - DBWriter.markItemRead(ClientConfig.applicationCallbacks.getApplicationInstance(), false, item.getId()); + DBWriter.markItemPlayed(ClientConfig.applicationCallbacks.getApplicationInstance(), FeedItem.UNPLAYED, item.getId()); } setPosition(newPosition); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java b/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java index 915f5ee1b..e925f89a7 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java @@ -244,7 +244,7 @@ public class GpodnetSyncService extends Service { case NEW: FeedItem newItem = DBReader.getFeedItem(this, action.getPodcast(), action.getEpisode()); if(newItem != null) { - DBWriter.markItemRead(this, newItem, false, true); + DBWriter.markItemPlayed(this, newItem, FeedItem.UNPLAYED, true); } else { Log.i(TAG, "Unknown feed item: " + action); } @@ -279,7 +279,7 @@ public class GpodnetSyncService extends Service { media.setPosition(action.getPosition() * 1000); DBWriter.setFeedMedia(this, media); if(playItem.getMedia().hasAlmostEnded()) { - DBWriter.markItemRead(this, playItem, true, true); + DBWriter.markItemPlayed(this, playItem, FeedItem.PLAYED, true); DBWriter.addItemToPlaybackHistory(this, playItem.getMedia()); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index 0e3a347bc..0ccc04238 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -5,9 +5,7 @@ import android.app.Notification; import android.app.PendingIntent; import android.app.Service; import android.bluetooth.BluetoothA2dp; -import android.bluetooth.BluetoothHeadset; import android.content.BroadcastReceiver; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -15,10 +13,8 @@ import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.media.AudioManager; -import android.media.MediaMetadataRetriever; import android.media.MediaPlayer; import android.media.RemoteControlClient; -import android.media.RemoteControlClient.MetadataEditor; import android.os.Binder; import android.os.Build; import android.os.IBinder; @@ -31,7 +27,6 @@ import android.view.SurfaceHolder; import android.widget.Toast; import com.bumptech.glide.Glide; -import com.bumptech.glide.load.engine.DiskCacheStrategy; import org.apache.commons.lang3.StringUtils; @@ -569,7 +564,7 @@ public class PlaybackService extends Service { if (playable instanceof FeedMedia) { FeedMedia media = (FeedMedia) playable; FeedItem item = media.getItem(); - DBWriter.markItemRead(PlaybackService.this, item, true, true); + DBWriter.markItemPlayed(PlaybackService.this, item, FeedItem.PLAYED, true); try { final List<FeedItem> queue = taskManager.getQueue(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index e4149a6c5..c54afc7d6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -201,7 +201,7 @@ public class PlaybackServiceMediaPlayer { if(oldMedia.hasAlmostEnded()) { Log.d(TAG, "smart mark as read"); FeedItem item = oldMedia.getItem(); - DBWriter.markItemRead(context, item, true, false); + DBWriter.markItemPlayed(context, item, FeedItem.PLAYED, false); DBWriter.removeQueueItem(context, item, false); DBWriter.addItemToPlaybackHistory(context, oldMedia); if (item.getFeed().getPreferences().getCurrentAutoDelete()) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java index 12bc208a6..0f7065c59 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java @@ -366,7 +366,7 @@ public class DBWriter { adapter.setQueue(queue); EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED, item, index)); if(item.isNew()) { - DBWriter.markItemRead(context, false, item.getId()); + DBWriter.markItemPlayed(context, FeedItem.UNPLAYED, item.getId()); } } } @@ -432,7 +432,7 @@ public class DBWriter { adapter.setQueue(queue); EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED_ITEMS, queue)); if(markAsUnplayedIds.size() > 0) { - DBWriter.markItemRead(context, false, markAsUnplayedIds.toArray()); + DBWriter.markItemPlayed(context, FeedItem.UNPLAYED, markAsUnplayedIds.toArray()); } } } @@ -614,20 +614,17 @@ public class DBWriter { * Sets the 'read'-attribute of all specified FeedItems * * @param context A context that is used for opening a database connection. - * @param read New value of the 'read'-attribute + * @param played New value of the 'read'-attribute, one of FeedItem.PLAYED, FeedItem.NEW, + * FeedItem.UNPLAYED * @param itemIds IDs of the FeedItems. */ - public static Future<?> markItemRead(final Context context, final boolean read, final long... itemIds) { - return dbExec.submit(new Runnable() { - @Override - public void run() { - final PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - int played = read ? FeedItem.PLAYED : FeedItem.UNPLAYED; - adapter.setFeedItemRead(played, itemIds); - adapter.close(); - EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); - } + public static Future<?> markItemPlayed(final Context context, final int played, final long... itemIds) { + return dbExec.submit(() -> { + final PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + adapter.setFeedItemRead(played, itemIds); + adapter.close(); + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); }); } @@ -637,30 +634,27 @@ public class DBWriter { * * @param context A context that is used for opening a database connection. * @param item The FeedItem object - * @param read New value of the 'read'-attribute + * @param played New value of the 'read'-attribute one of FeedItem.PLAYED, + * FeedItem.NEW, FeedItem.UNPLAYED * @param resetMediaPosition true if this method should also reset the position of the FeedItem's FeedMedia object. * If the FeedItem has no FeedMedia object, this parameter will be ignored. */ - public static Future<?> markItemRead(Context context, FeedItem item, boolean read, boolean resetMediaPosition) { + public static Future<?> markItemPlayed(Context context, FeedItem item, int played, boolean resetMediaPosition) { long mediaId = (item.hasMedia()) ? item.getMedia().getId() : 0; - return markItemRead(context, item.getId(), read, mediaId, resetMediaPosition); + return markItemPlayed(context, item.getId(), played, mediaId, resetMediaPosition); } - private static Future<?> markItemRead(final Context context, final long itemId, - final boolean read, final long mediaId, - final boolean resetMediaPosition) { - return dbExec.submit(new Runnable() { - - @Override - public void run() { - final PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.setFeedItemRead(read, itemId, mediaId, - resetMediaPosition); - adapter.close(); - - EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); - } + private static Future<?> markItemPlayed(final Context context, final long itemId, + final int played, final long mediaId, + final boolean resetMediaPosition) { + return dbExec.submit(() -> { + final PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + adapter.setFeedItemRead(played, itemId, mediaId, + resetMediaPosition); + adapter.close(); + + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); }); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index b179c6f24..4714f4880 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -778,12 +778,12 @@ public class PodDBAdapter { return item.getId(); } - public void setFeedItemRead(boolean read, long itemId, long mediaId, + public void setFeedItemRead(int played, long itemId, long mediaId, boolean resetMediaPosition) { db.beginTransaction(); ContentValues values = new ContentValues(); - values.put(KEY_READ, read ? FeedItem.PLAYED : FeedItem.UNPLAYED); + values.put(KEY_READ, played); db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?", new String[]{String.valueOf(itemId)}); if (resetMediaPosition) { @@ -796,6 +796,11 @@ public class PodDBAdapter { db.endTransaction(); } + /** + * Sets the 'read' attribute of the item. + * @param read must be one of FeedItem.PLAYED, FeedItem.NEW, FeedItem.UNPLAYED + * @param itemIds items to change the value of + */ public void setFeedItemRead(int read, long... itemIds) { db.beginTransaction(); ContentValues values = new ContentValues(); diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index bd4a58922..20eb79f84 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -120,8 +120,7 @@ <string-array name="nav_drawer_titles"> <item>@string/queue_label</item> - <item>@string/new_episodes_label</item> - <item>@string/all_episodes_label</item> + <item>@string/episodes_label</item> <item>@string/downloads_label</item> <item>@string/playback_history_label</item> <item>@string/add_feed_label</item> diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index e868fd914..3682d4307 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -9,9 +9,10 @@ <string name="feeds_label">Feeds</string> <string name="add_feed_label">Add Podcast</string> <string name="podcasts_label">PODCASTS</string> - <string name="episodes_label">EPISODES</string> + <string name="episodes_label">Episodes</string> <string name="new_episodes_label">New Episodes</string> <string name="all_episodes_label">All Episodes</string> + <string name="all_episodes_short_label">All</string> <string name="new_label">New</string> <string name="waiting_list_label">Waiting List</string> <string name="settings_label">Settings</string> |