diff options
32 files changed, 307 insertions, 92 deletions
diff --git a/app/build.gradle b/app/build.gradle index 7025d46ad..f2888cf2f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -32,8 +32,8 @@ dependencies { compile "io.reactivex:rxjava:$rxJavaVersion" // And ProGuard rules for RxJava! compile "com.artemzin.rxjava:proguard-rules:$rxJavaRulesVersion" - compile "com.joanzapata.iconify:android-iconify-fontawesome:$iconifyFontawesomeVersion" - compile "com.joanzapata.iconify:android-iconify-material:$iconifyFontawesomeVersion" + compile "com.joanzapata.iconify:android-iconify-fontawesome:$iconifyVersion" + compile "com.joanzapata.iconify:android-iconify-material:$iconifyVersion" compile("com.github.afollestad.material-dialogs:commons:$materialDialogsVersion") { transitive = true } diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java index d65925703..d4994fb1a 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java @@ -49,10 +49,11 @@ public class PlaybackSonicTest extends ActivityInstrumentationTestCase2<MainActi public void setUp() throws Exception { super.setUp(); - PodDBAdapter.deleteDatabase(); - context = getInstrumentation().getTargetContext(); + PodDBAdapter.init(context); + PodDBAdapter.deleteDatabase(); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); prefs.edit() .clear() 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 016c868b4..5ce495f9a 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java @@ -46,10 +46,11 @@ public class PlaybackTest extends ActivityInstrumentationTestCase2<MainActivity> public void setUp() throws Exception { super.setUp(); - PodDBAdapter.deleteDatabase(); - context = getInstrumentation().getTargetContext(); + PodDBAdapter.init(context); + PodDBAdapter.deleteDatabase(); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); prefs.edit() .clear() diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java index 897098c00..b70336a30 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java @@ -223,6 +223,8 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference String[] values = res.getStringArray(R.array.episode_cache_size_values); String entry = entries[entries.length/2]; final int value = Integer.valueOf(values[values.length/2]); + solo.clickOnText(solo.getString(R.string.pref_automatic_download_title)); + solo.waitForText(solo.getString(R.string.pref_automatic_download_title)); solo.clickOnText(solo.getString(R.string.pref_episode_cache_title)); solo.waitForDialogToOpen(); solo.clickOnText(entry); @@ -234,6 +236,11 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference String[] values = res.getStringArray(R.array.episode_cache_size_values); String minEntry = entries[0]; final int minValue = Integer.valueOf(values[0]); + solo.clickOnText(solo.getString(R.string.pref_automatic_download_title)); + solo.waitForText(solo.getString(R.string.pref_automatic_download_title)); + if(!UserPreferences.isEnableAutodownload()) { + solo.clickOnText(solo.getString(R.string.pref_automatic_download_title)); + } solo.clickOnText(solo.getString(R.string.pref_episode_cache_title)); solo.waitForDialogToOpen(1000); solo.scrollUp(); @@ -241,12 +248,16 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference assertTrue(solo.waitForCondition(() -> UserPreferences.getEpisodeCacheSize() == minValue, Timeout.getLargeTimeout())); } - public void testSetEpisodeCacheMax() { String[] entries = res.getStringArray(R.array.episode_cache_size_entries); String[] values = res.getStringArray(R.array.episode_cache_size_values); String maxEntry = entries[entries.length-1]; final int maxValue = Integer.valueOf(values[values.length-1]); + solo.clickOnText(solo.getString(R.string.pref_automatic_download_title)); + solo.waitForText(solo.getString(R.string.pref_automatic_download_title)); + if(!UserPreferences.isEnableAutodownload()) { + solo.clickOnText(solo.getString(R.string.pref_automatic_download_title)); + } solo.clickOnText(solo.getString(R.string.pref_episode_cache_title)); solo.waitForDialogToOpen(); solo.clickOnText(maxEntry); diff --git a/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java index 014c65e11..50d557735 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java @@ -499,6 +499,11 @@ public class AudioplayerActivity extends MediaplayerActivity implements NavDrawe } @Override + public int getNumberOfDownloadedItems() { + return (navDrawerData != null) ? navDrawerData.numDownloadedItems : 0; + } + + @Override public int getFeedCounter(long feedId) { return navDrawerData != null ? navDrawerData.feedCounters.get(feedId) : 0; } 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 17cd5ace3..2181e7d2d 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java @@ -636,6 +636,11 @@ public class MainActivity extends AppCompatActivity implements NavDrawerActivity } @Override + public int getNumberOfDownloadedItems() { + return (navDrawerData != null) ? navDrawerData.numDownloadedItems : 0; + } + + @Override public int getFeedCounter(long feedId) { return navDrawerData != null ? navDrawerData.feedCounters.get(feedId) : 0; } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java index f120aa1d5..1fa4b7c48 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java @@ -4,7 +4,6 @@ import android.graphics.drawable.Drawable; import android.net.Uri; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; -import android.text.format.DateUtils; import android.util.Log; import android.view.ContextMenu; import android.view.LayoutInflater; @@ -15,7 +14,6 @@ import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.TextView; @@ -36,6 +34,7 @@ import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DownloadRequester; import de.danoeh.antennapod.core.util.Converter; +import de.danoeh.antennapod.core.util.DateUtils; import de.danoeh.antennapod.core.util.NetworkUtils; import de.danoeh.antennapod.fragment.ItemFragment; import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; @@ -118,8 +117,8 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR holder.placeholder.setVisibility(View.VISIBLE); holder.placeholder.setText(item.getFeed().getTitle()); holder.title.setText(item.getTitle()); - holder.pubDate.setText(DateUtils.formatDateTime(mainActivityRef.get(), - item.getPubDate().getTime(), DateUtils.FORMAT_ABBREV_ALL)); + String pubDateStr = DateUtils.formatAbbrev(mainActivityRef.get(), item.getPubDate()); + holder.pubDate.setText(pubDateStr); if (showOnlyNewEpisodes || false == item.isNew()) { holder.statusUnread.setVisibility(View.INVISIBLE); } else { diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java index 2b1eccea5..ca747b9b0 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java @@ -1,7 +1,6 @@ package de.danoeh.antennapod.adapter; import android.content.Context; -import android.text.format.DateUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -11,12 +10,12 @@ import android.widget.ImageView; import android.widget.TextView; import com.bumptech.glide.Glide; -import com.bumptech.glide.load.engine.DiskCacheStrategy; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.util.Converter; +import de.danoeh.antennapod.core.util.DateUtils; /** * Shows a list of downloaded episodes @@ -75,7 +74,8 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter { } holder.title.setText(item.getTitle()); - holder.pubDate.setText(DateUtils.formatDateTime(context, item.getPubDate().getTime(), DateUtils.FORMAT_ABBREV_ALL)); + String pubDateStr = DateUtils.formatAbbrev(context, item.getPubDate()); + holder.pubDate.setText(pubDateStr); holder.txtvSize.setText(Converter.byteToString(item.getMedia().getSize())); FeedItem.State state = item.getState(); diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java index e1d158d6a..e483738b4 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java @@ -2,7 +2,6 @@ package de.danoeh.antennapod.adapter; import android.content.Context; import android.content.res.TypedArray; -import android.text.format.DateUtils; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; @@ -23,6 +22,7 @@ import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.MediaType; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DownloadRequester; +import de.danoeh.antennapod.core.util.DateUtils; import de.danoeh.antennapod.core.util.ThemeUtils; /** @@ -143,8 +143,8 @@ public class FeedItemlistAdapter extends BaseAdapter { ViewHelper.setAlpha(convertView, 1.0f); } - holder.published.setText(DateUtils.formatDateTime(context, item.getPubDate().getTime(), DateUtils.FORMAT_ABBREV_ALL)); - + String pubDateStr = DateUtils.formatAbbrev(context, item.getPubDate()); + holder.published.setText(pubDateStr); FeedMedia media = item.getMedia(); if (media == null) { 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 183c1a44e..d43e30d8f 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java @@ -6,6 +6,7 @@ import android.content.res.TypedArray; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.preference.PreferenceManager; +import android.support.v7.app.AlertDialog; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -15,7 +16,7 @@ import android.widget.RelativeLayout; import android.widget.TextView; import com.bumptech.glide.Glide; -import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.joanzapata.iconify.Iconify; import com.joanzapata.iconify.widget.IconTextView; import org.apache.commons.lang3.ArrayUtils; @@ -208,7 +209,8 @@ public class NavListAdapter extends BaseAdapter holder.title.setText(title); - if (tags.get(position).equals(QueueFragment.TAG)) { + String tag = tags.get(position); + if (tag.equals(QueueFragment.TAG)) { int queueSize = itemAccess.getQueueSize(); if (queueSize > 0) { holder.count.setVisibility(View.VISIBLE); @@ -216,7 +218,7 @@ public class NavListAdapter extends BaseAdapter } else { holder.count.setVisibility(View.GONE); } - } else if (tags.get(position).equals(EpisodesFragment.TAG)) { + } else if (tag.equals(EpisodesFragment.TAG)) { int unreadItems = itemAccess.getNumberOfNewItems(); if (unreadItems > 0) { holder.count.setVisibility(View.VISIBLE); @@ -224,6 +226,22 @@ public class NavListAdapter extends BaseAdapter } else { holder.count.setVisibility(View.GONE); } + } else if(tag.equals(DownloadsFragment.TAG) && UserPreferences.isEnableAutodownload()) { + int epCacheSize = UserPreferences.getEpisodeCacheSize(); + if(itemAccess.getNumberOfDownloadedItems() >= epCacheSize) { + holder.count.setText("{md-disc-full 150%}"); + Iconify.addIcons(holder.count); + holder.count.setVisibility(View.VISIBLE); + holder.count.setOnClickListener(v -> { + new AlertDialog.Builder(context) + .setTitle(R.string.episode_cache_full_title) + .setMessage(R.string.episode_cache_full_message) + .setPositiveButton(android.R.string.ok, (dialog, which) -> {}) + .show(); + }); + } else { + holder.count.setVisibility(View.GONE); + } } else { holder.count.setVisibility(View.GONE); } @@ -316,6 +334,7 @@ public class NavListAdapter extends BaseAdapter int getSelectedItemIndex(); int getQueueSize(); int getNumberOfNewItems(); + int getNumberOfDownloadedItems(); int getFeedCounter(long feedId); } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java index 3e4dd4deb..ca1f59e8d 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java @@ -6,7 +6,6 @@ import android.support.annotation.Nullable; import android.support.v4.view.MotionEventCompat; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; -import android.text.format.DateUtils; import android.util.Log; import android.view.ContextMenu; import android.view.LayoutInflater; @@ -28,6 +27,8 @@ import com.bumptech.glide.request.target.GlideDrawableImageViewTarget; import com.joanzapata.iconify.Iconify; import com.nineoldandroids.view.ViewHelper; +import org.apache.commons.lang3.StringUtils; + import java.lang.ref.WeakReference; import de.danoeh.antennapod.R; @@ -38,6 +39,7 @@ import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DownloadRequester; import de.danoeh.antennapod.core.util.Converter; +import de.danoeh.antennapod.core.util.DateUtils; import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.core.util.NetworkUtils; import de.danoeh.antennapod.fragment.ItemFragment; @@ -209,9 +211,21 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap FeedMedia media = item.getMedia(); title.setText(item.getTitle()); - String pubDateStr = DateUtils.formatDateTime(mainActivity.get(), - item.getPubDate().getTime(), DateUtils.FORMAT_ABBREV_ALL); - pubDate.setText(pubDateStr.replace(" ", "\n")); + String pubDateStr = DateUtils.formatAbbrev(mainActivity.get(), item.getPubDate()); + int index = 0; + if(StringUtils.countMatches(pubDateStr, ' ') == 1 || StringUtils.countMatches(pubDateStr, ' ') == 2) { + index = pubDateStr.lastIndexOf(' '); + } else if(StringUtils.countMatches(pubDateStr, '.') == 2) { + index = pubDateStr.lastIndexOf('.'); + } else if(StringUtils.countMatches(pubDateStr, '-') == 2) { + index = pubDateStr.lastIndexOf('-'); + } else if(StringUtils.countMatches(pubDateStr, '/') == 2) { + index = pubDateStr.lastIndexOf('/'); + } + if(index > 0) { + pubDateStr = pubDateStr.substring(0, index+1).trim() + "\n" + pubDateStr.substring(index+1); + } + pubDate.setText(pubDateStr); if (media != null) { final boolean isDownloadingMedia = DownloadRequester.getInstance().isDownloadingFile(media); 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 9ccb0fbe3..2bc4e9ded 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java @@ -190,6 +190,9 @@ public class AllEpisodesFragment extends Fragment { @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + if(!isAdded()) { + return; + } super.onCreateOptionsMenu(menu, inflater); if (itemsLoaded) { inflater.inflate(R.menu.new_episodes, menu); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java index 47ed9676a..b470d379a 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java @@ -111,6 +111,9 @@ public class DownloadLogFragment extends ListFragment { @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + if(!isAdded()) { + return; + } super.onCreateOptionsMenu(menu, inflater); if (itemsLoaded) { MenuItem clearHistory = menu.add(Menu.NONE, R.id.clear_history_item, Menu.CATEGORY_CONTAINER, R.string.clear_history_label); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java index f71b90570..bbffd2dea 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java @@ -11,7 +11,6 @@ import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.util.Pair; import android.text.TextUtils; -import android.text.format.DateUtils; import android.util.Log; import android.view.ContextMenu; import android.view.LayoutInflater; @@ -55,6 +54,7 @@ import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.storage.DownloadRequestException; import de.danoeh.antennapod.core.storage.DownloadRequester; import de.danoeh.antennapod.core.util.Converter; +import de.danoeh.antennapod.core.util.DateUtils; import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.core.util.ShareUtils; @@ -243,7 +243,7 @@ public class ItemFragment extends Fragment { @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - if(item == null) { + if(!isAdded() || item == null) { return; } inflater.inflate(R.menu.feeditem_options, menu); @@ -297,7 +297,8 @@ public class ItemFragment extends Fragment { txtvTitle.setText(item.getTitle()); if (item.getPubDate() != null) { - txtvPublished.setText(DateUtils.formatDateTime(getActivity(), item.getPubDate().getTime(), DateUtils.FORMAT_ABBREV_ALL)); + String pubDateStr = DateUtils.formatAbbrev(getActivity(), item.getPubDate()); + txtvPublished.setText(pubDateStr); } Glide.with(getActivity()) @@ -331,7 +332,7 @@ public class ItemFragment extends Fragment { butAction1Text = R.string.mark_read_label; } if (item.getLink() != null) { - butAction2Icon = "{ma-web 24sp}"; + butAction2Icon = "{md-web 24sp}"; butAction2Text = R.string.visit_website_label; } } else { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java index bc5024426..97c446fab 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java @@ -194,6 +194,9 @@ public class ItemlistFragment extends ListFragment { @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + if(!isAdded()) { + return; + } super.onCreateOptionsMenu(menu, inflater); if (itemsLoaded) { @@ -370,6 +373,9 @@ public class ItemlistFragment extends ListFragment { @Override public void onListItemClick(ListView l, View v, int position, long id) { + if(adapter == null) { + return; + } FeedItem selection = adapter.getItem(position - l.getHeaderViewsCount()); if (selection != null) { MainActivity activity = (MainActivity) getActivity(); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java index 64e3a7da7..c5b77fae2 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java @@ -148,6 +148,9 @@ public class PlaybackHistoryFragment extends ListFragment { @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + if(!isAdded()) { + return; + } super.onCreateOptionsMenu(menu, inflater); if (itemsLoaded) { MenuItem clearHistory = menu.add(Menu.NONE, R.id.clear_history_item, Menu.CATEGORY_CONTAINER, R.string.clear_history_label); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java index cc6b44f6a..43f22a587 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java @@ -68,6 +68,7 @@ public class QueueFragment extends Fragment { public static final String TAG = "QueueFragment"; private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED | + EventDistributor.UNREAD_ITEMS_UPDATE | // sent when playback position is reset EventDistributor.PLAYER_STATUS_UPDATE; private TextView infoBar; @@ -235,6 +236,9 @@ public class QueueFragment extends Fragment { @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + if(!isAdded()) { + return; + } super.onCreateOptionsMenu(menu, inflater); if (queue != null) { inflater.inflate(R.menu.queue, menu); @@ -268,10 +272,17 @@ public class QueueFragment extends Fragment { if (!super.onOptionsItemSelected(item)) { switch (item.getItemId()) { case R.id.queue_lock: - boolean locked = !UserPreferences.isQueueLocked(); - UserPreferences.setQueueLocked(locked); + boolean newLockState = !UserPreferences.isQueueLocked(); + UserPreferences.setQueueLocked(newLockState); getActivity().supportInvalidateOptionsMenu(); - recyclerAdapter.setLocked(locked); + recyclerAdapter.setLocked(newLockState); + if (newLockState) { + Snackbar.make(getActivity().findViewById(R.id.content), R.string + .queue_locked, Snackbar.LENGTH_SHORT).show(); + } else { + Snackbar.make(getActivity().findViewById(R.id.content), R.string + .queue_unlocked, Snackbar.LENGTH_SHORT).show(); + } return true; case R.id.refresh_item: List<Feed> feeds = ((MainActivity) getActivity()).getFeeds(); 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 06dbe4963..0224d2c7e 100644 --- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java +++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java @@ -72,7 +72,10 @@ public class FeedItemMenuHandler { mi.setItemVisibility(R.id.skip_episode_item, false); } - boolean isInQueue = selectedItem.isTagged(FeedItem.TAG_QUEUE); + boolean isInQueue = false; + if(queueAccess != null) { + isInQueue = queueAccess.contains(selectedItem.getId()); + } if(queueAccess == null || queueAccess.size() == 0 || queueAccess.get(0) == selectedItem.getId()) { mi.setItemVisibility(R.id.move_to_top_item, false); } diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java index cfc540fd6..0d2ff8a75 100644 --- a/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java +++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java @@ -34,10 +34,10 @@ public class MenuItemUtils extends de.danoeh.antennapod.core.menuhandler.MenuIte TypedArray ta = context.obtainStyledAttributes(lockIcons); if (UserPreferences.isQueueLocked()) { queueLock.setTitle(de.danoeh.antennapod.R.string.unlock_queue); - queueLock.setIcon(ta.getDrawable(1)); + queueLock.setIcon(ta.getDrawable(0)); } else { queueLock.setTitle(de.danoeh.antennapod.R.string.lock_queue); - queueLock.setIcon(ta.getDrawable(0)); + queueLock.setIcon(ta.getDrawable(1)); } } 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 a872039f9..083ac5202 100644 --- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java +++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java @@ -30,10 +30,15 @@ import android.widget.Toast; import com.afollestad.materialdialogs.MaterialDialog; +import org.apache.commons.lang3.ArrayUtils; + import java.io.File; import java.util.ArrayList; import java.util.Arrays; +import java.util.Calendar; +import java.util.GregorianCalendar; import java.util.List; +import java.util.concurrent.TimeUnit; import de.danoeh.antennapod.CrashReportWriter; import de.danoeh.antennapod.R; @@ -216,17 +221,16 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc } }); - ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL) - .setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - if (newValue instanceof Boolean) { - ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER).setEnabled((Boolean) newValue); - setSelectedNetworksEnabled((Boolean) newValue && UserPreferences.isEnableAutodownloadWifiFilter()); - ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_ON_BATTERY).setEnabled((Boolean) newValue); - } - return true; + ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL).setOnPreferenceChangeListener( + (preference, newValue) -> { + if (newValue instanceof Boolean) { + boolean enabled = (Boolean) newValue; + ui.findPreference(UserPreferences.PREF_EPISODE_CACHE_SIZE).setEnabled(enabled); + ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_ON_BATTERY).setEnabled(enabled); + ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER).setEnabled(enabled); + setSelectedNetworksEnabled(enabled && UserPreferences.isEnableAutodownloadWifiFilter()); } + return true; }); ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER) .setOnPreferenceChangeListener( @@ -411,6 +415,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc public void onResume() { checkItemVisibility(); + setUpdateIntervalText(); setParallelDownloadsText(UserPreferences.getParallelDownloads()); setEpisodeCacheSizeText(UserPreferences.getEpisodeCacheSize()); setDataFolderText(); @@ -503,15 +508,19 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc final Resources res = ui.getActivity().getResources(); ListPreference pref = (ListPreference) ui.findPreference(UserPreferences.PREF_SMART_MARK_AS_PLAYED_SECS); - String[] values = res.getStringArray( - R.array.smart_mark_as_played_values); + String[] values = res.getStringArray(R.array.smart_mark_as_played_values); String[] entries = new String[values.length]; for (int x = 0; x < values.length; x++) { if(x == 0) { entries[x] = res.getString(R.string.pref_smart_mark_as_played_disabled); } else { Integer v = Integer.parseInt(values[x]); - entries[x] = res.getQuantityString(R.plurals.time_seconds_quantified, v, v); + if(v < 60) { + entries[x] = res.getQuantityString(R.plurals.time_seconds_quantified, v, v); + } else { + v /= 60; + entries[x] = res.getQuantityString(R.plurals.time_minutes_quantified, v, v); + } } } pref.setEntries(entries); @@ -527,21 +536,17 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc @SuppressWarnings("deprecation") private void checkItemVisibility() { - boolean hasFlattrToken = FlattrUtils.hasToken(); - ui.findPreference(PreferenceController.PREF_FLATTR_SETTINGS).setEnabled(FlattrUtils.hasAPICredentials()); ui.findPreference(PreferenceController.PREF_FLATTR_AUTH).setEnabled(!hasFlattrToken); ui.findPreference(PreferenceController.PREF_FLATTR_REVOKE).setEnabled(hasFlattrToken); ui.findPreference(PreferenceController.PREF_AUTO_FLATTR_PREFS).setEnabled(hasFlattrToken); - ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER) - .setEnabled(UserPreferences.isEnableAutodownload()); - setSelectedNetworksEnabled(UserPreferences.isEnableAutodownload() - && UserPreferences.isEnableAutodownloadWifiFilter()); - - ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_ON_BATTERY) - .setEnabled(UserPreferences.isEnableAutodownload()); + boolean autoDownload = UserPreferences.isEnableAutodownload(); + ui.findPreference(UserPreferences.PREF_EPISODE_CACHE_SIZE).setEnabled(autoDownload); + ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_ON_BATTERY).setEnabled(autoDownload); + ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER).setEnabled(autoDownload); + setSelectedNetworksEnabled(autoDownload && UserPreferences.isEnableAutodownloadWifiFilter()); ui.findPreference("prefSendCrashReport").setEnabled(CrashReportWriter.getFile().exists()); @@ -553,6 +558,32 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc } } + private void setUpdateIntervalText() { + Context context = ui.getActivity().getApplicationContext(); + String val; + long interval = UserPreferences.getUpdateInterval(); + if(interval > 0) { + int hours = (int) TimeUnit.MILLISECONDS.toHours(interval); + String hoursStr = context.getResources().getQuantityString(R.plurals.time_hours_quantified, hours, hours); + val = String.format(context.getString(R.string.pref_autoUpdateIntervallOrTime_every), hoursStr); + } else { + int[] timeOfDay = UserPreferences.getUpdateTimeOfDay(); + if(timeOfDay.length == 2) { + Calendar cal = new GregorianCalendar(); + cal.set(Calendar.HOUR_OF_DAY, timeOfDay[0]); + cal.set(Calendar.MINUTE, timeOfDay[1]); + String timeOfDayStr = DateFormat.getTimeFormat(context).format(cal.getTime()); + val = String.format(context.getString(R.string.pref_autoUpdateIntervallOrTime_at), + timeOfDayStr); + } else { + val = context.getString(R.string.pref_smart_mark_as_played_disabled); + } + } + String summary = context.getString(R.string.pref_autoUpdateIntervallOrTime_sum) + "\n" + + String.format(context.getString(R.string.pref_current_value), val); + ui.findPreference(UserPreferences.PREF_UPDATE_INTERVAL).setSummary(summary); + } + private void setParallelDownloadsText(int downloads) { final Resources res = ui.getActivity().getResources(); @@ -772,10 +803,17 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc 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, (dialog1, which) -> { + long currInterval = UserPreferences.getUpdateInterval(); + int checkedItem = -1; + if(currInterval > 0) { + String currIntervalStr = String.valueOf(TimeUnit.MILLISECONDS.toHours(currInterval)); + checkedItem = ArrayUtils.indexOf(values, currIntervalStr); + } + builder.setSingleChoiceItems(entries, checkedItem, (dialog1, which) -> { int hours = Integer.valueOf(values[which]); UserPreferences.setUpdateInterval(hours); dialog1.dismiss(); + setUpdateIntervalText(); }); builder.setNegativeButton(context.getString(R.string.cancel_label), null); builder.show(); @@ -794,6 +832,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc if (view.getTag() == null) { // onTimeSet() may get called twice! view.setTag("TAGGED"); UserPreferences.setUpdateTimeOfDay(selectedHourOfDay, selectedMinute); + setUpdateIntervalText(); } }, hourOfDay, minute, DateFormat.is24HourFormat(context)); timePickerDialog.setTitle(context.getString(R.string.pref_autoUpdateIntervallOrTime_TimeOfDay)); @@ -803,6 +842,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc @Override public void onNeutral(MaterialDialog dialog) { UserPreferences.setUpdateInterval(0); + setUpdateIntervalText(); } }); builder.forceStacking(true); diff --git a/app/src/main/res/layout/queue_listitem.xml b/app/src/main/res/layout/queue_listitem.xml index e55b254f3..99e96c9fb 100644 --- a/app/src/main/res/layout/queue_listitem.xml +++ b/app/src/main/res/layout/queue_listitem.xml @@ -77,7 +77,7 @@ android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_marginLeft="8dp" - android:gravity="right|bottom" + android:gravity="right|top" android:text="Feb\n12" tools:background="@android:color/holo_blue_light" /> diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index cdb582898..b2a28e871 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -170,13 +170,6 @@ android:key="prefParallelDownloads" android:title="@string/pref_parallel_downloads_title" app:useStockLayout="true"/> - <com.afollestad.materialdialogs.prefs.MaterialListPreference - android:defaultValue="20" - android:entries="@array/episode_cache_size_entries" - android:key="prefEpisodeCacheSize" - android:title="@string/pref_episode_cache_title" - android:entryValues="@array/episode_cache_size_values" - app:useStockLayout="true"/> <PreferenceScreen android:summary="@string/pref_automatic_download_sum" android:key="prefAutoDownloadSettings" @@ -185,6 +178,13 @@ android:key="prefEnableAutoDl" android:title="@string/pref_automatic_download_title" android:defaultValue="false"/> + <com.afollestad.materialdialogs.prefs.MaterialListPreference + android:defaultValue="20" + android:entries="@array/episode_cache_size_entries" + android:key="prefEpisodeCacheSize" + android:title="@string/pref_episode_cache_title" + android:entryValues="@array/episode_cache_size_values" + app:useStockLayout="true"/> <de.danoeh.antennapod.preferences.SwitchCompatPreference android:key="prefEnableAutoDownloadOnBattery" android:title="@string/pref_automatic_download_on_battery_title" diff --git a/build.gradle b/build.gradle index 0d2cf9dfb..b2e6cd902 100644 --- a/build.gradle +++ b/build.gradle @@ -47,8 +47,8 @@ project.ext { eventbusVersion = "2.4.0" flattr4jVersion = "2.12" glideVersion = "3.6.1" + iconifyVersion = "2.1.1" jsoupVersion = "1.7.3" - iconifyFontawesomeVersion = "2.1.1" materialDialogsVersion = "0.8.5.3@aar" okhttpVersion = "2.7.2" okioVersion = "1.6.0" diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java index c54cc1d5b..00b32de5f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java @@ -11,6 +11,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; import de.danoeh.antennapod.core.asynctask.ImageResource; import de.danoeh.antennapod.core.storage.DBReader; @@ -75,7 +76,13 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr private List<Chapter> chapters; private FeedImage image; - private boolean autoDownload = true; + /* + * 0: auto download disabled + * 1: auto download enabled + * > 1: auto download enabled, (approx.) timestamp of the last failed attempt + * where last digit denotes the number of failed attempts + */ + private long autoDownload = 0; /** * Any tags assigned to this item @@ -93,7 +100,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr * */ public FeedItem(long id, String title, String link, Date pubDate, String paymentLink, long feedId, FlattrStatus flattrStatus, boolean hasChapters, FeedImage image, int state, - String itemIdentifier, boolean autoDownload) { + String itemIdentifier, long autoDownload) { this.id = id; this.title = title; this.link = link; @@ -162,7 +169,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr FlattrStatus flattrStatus = new FlattrStatus(cursor.getLong(indexFlattrStatus)); int state = cursor.getInt(indexRead); String itemIdentifier = cursor.getString(indexItemIdentifier); - boolean autoDownload = cursor.getInt(indexAutoDownload) > 0; + long autoDownload = cursor.getLong(indexAutoDownload); FeedItem item = new FeedItem(id, title, link, pubDate, paymentLink, feedId, flattrStatus, hasChapters, null, state, itemIdentifier, autoDownload); @@ -449,18 +456,37 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr } public void setAutoDownload(boolean autoDownload) { - this.autoDownload = autoDownload; + this.autoDownload = autoDownload ? 1 : 0; } public boolean getAutoDownload() { - return this.autoDownload; + return this.autoDownload > 0; + } + + public int getFailedAutoDownloadAttempts() { + if (autoDownload <= 1) { + return 0; + } + int failedAttempts = (int)(autoDownload % 10); + if (failedAttempts == 0) { + failedAttempts = 10; + } + return failedAttempts; } public boolean isAutoDownloadable() { - return this.hasMedia() && - false == this.getMedia().isPlaying() && - false == this.getMedia().isDownloaded() && - this.getAutoDownload(); + if (media == null || media.isPlaying() || media.isDownloaded() || autoDownload == 0) { + return false; + } + if (autoDownload == 1) { + return true; + } + int failedAttempts = getFailedAutoDownloadAttempts(); + double magicValue = 1.767; // 1.767^(10[=#maxNumAttempts]-1) = 168 hours / 7 days + int millisecondsInHour = 3600000; + long waitingTime = (long) (Math.pow(magicValue, failedAttempts - 1) * millisecondsInHour); + long grace = TimeUnit.MINUTES.toMillis(5); + return System.currentTimeMillis() > (autoDownload + waitingTime - grace); } /** diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 29c44207d..c3afff276 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -26,6 +26,7 @@ import org.xml.sax.SAXException; import java.io.File; import java.io.IOException; +import java.net.HttpURLConnection; import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -196,11 +197,19 @@ public class DownloadService extends Service { saveDownloadStatus(status); handleFailedDownload(status, downloader.getDownloadRequest()); - // to make lists reload the failed item, we fake an item update if(type == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { long id = status.getFeedfileId(); FeedMedia media = DBReader.getFeedMedia(id); - EventBus.getDefault().post(FeedItemEvent.updated(media.getItem())); + if(media == null || media.getItem() == null) { + return; + } + FeedItem item = media.getItem(); + if (status.getReason() == DownloadError.ERROR_HTTP_DATA_ERROR && + Integer.valueOf(status.getReasonDetailed()) == HttpURLConnection.HTTP_NOT_FOUND) { + DBWriter.saveFeedItemAutoDownloadFailed(item).get(); + } + // to make lists reload the failed item, we fake an item update + EventBus.getDefault().post(FeedItemEvent.updated(item)); } } } else { diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index fe5b177ab..16e65f9f3 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -1015,7 +1015,9 @@ public final class DBReader { Collections.sort(feeds, comparator); int queueSize = adapter.getQueueSize(); int numNewItems = adapter.getNumberOfNewItems(); - NavDrawerData result = new NavDrawerData(feeds, queueSize, numNewItems, feedCounters); + int numDownloadedItems = adapter.getNumberOfDownloadedEpisodes(); + + NavDrawerData result = new NavDrawerData(feeds, queueSize, numNewItems, numDownloadedItems, feedCounters); adapter.close(); return result; } @@ -1024,15 +1026,18 @@ public final class DBReader { public List<Feed> feeds; public int queueSize; public int numNewItems; + public int numDownloadedItems; public LongIntMap feedCounters; public NavDrawerData(List<Feed> feeds, int queueSize, int numNewItems, + int numDownloadedItems, LongIntMap feedIndicatorValues) { this.feeds = feeds; this.queueSize = queueSize; this.numNewItems = numNewItems; + this.numDownloadedItems = numDownloadedItems; this.feedCounters = feedIndicatorValues; } } 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 f74064cfc..d1d6bd750 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 @@ -977,13 +977,35 @@ public class DBWriter { * Sets the 'auto_download'-attribute of specific FeedItem. * * @param feedItem FeedItem. + * @param autoDownload true enables auto download, false disables it */ public static Future<?> setFeedItemAutoDownload(final FeedItem feedItem, final boolean autoDownload) { - Log.d(TAG, "FeedItem[id=" + feedItem.getId() + "] SET auto_download " + autoDownload); return dbExec.submit(() -> { final PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); + adapter.setFeedItemAutoDownload(feedItem, autoDownload ? 1 : 0); + adapter.close(); + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); + }); + } + + public static Future<?> saveFeedItemAutoDownloadFailed(final FeedItem feedItem) { + return dbExec.submit(() -> { + int failedAttempts = feedItem.getFailedAutoDownloadAttempts() + 1; + Log.d(TAG, "failedAttempts: " + failedAttempts); + long autoDownload; + if(!feedItem.getAutoDownload() || failedAttempts >= 10) { + autoDownload = 0; // giving up, disable auto download + feedItem.setAutoDownload(false); + } else { + long now = System.currentTimeMillis(); + autoDownload = (now / 10) * 10 + failedAttempts; + Log.d(TAG, "now: " + now); + Log.d(TAG, "autoDownload: " + autoDownload); + } + final PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); adapter.setFeedItemAutoDownload(feedItem, autoDownload); adapter.close(); EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); @@ -992,7 +1014,8 @@ public class DBWriter { /** * Sets the 'auto_download'-attribute of specific FeedItem. - * @param feed This feed's episodes will be processed. + * + * @param feed This feed's episodes will be processed. * @param autoDownload If true, auto download will be enabled for the feed's episodes. Else, */ public static Future<?> setFeedsItemsAutoDownload(final Feed feed, 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 629b73668..915ca14c7 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 @@ -794,7 +794,7 @@ public class PodDBAdapter { return status.getId(); } - public void setFeedItemAutoDownload(FeedItem feedItem, boolean autoDownload) { + public void setFeedItemAutoDownload(FeedItem feedItem, long autoDownload) { ContentValues values = new ContentValues(); values.put(KEY_AUTO_DOWNLOAD, autoDownload); db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?", diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java index 6406295c1..9b9849c49 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java @@ -1,5 +1,7 @@ package de.danoeh.antennapod.core.syndication.namespace; +import android.text.TextUtils; + import org.xml.sax.Attributes; import java.util.concurrent.TimeUnit; @@ -36,8 +38,10 @@ public class NSITunes extends Namespace { } else { // this is the feed image // prefer to all other images - image.setOwner(state.getFeed()); - state.getFeed().setImage(image); + if(!TextUtils.isEmpty(image.getDownload_url())) { + image.setOwner(state.getFeed()); + state.getFeed().setImage(image); + } } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java index 1a148673c..4b4201b50 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java @@ -1,5 +1,6 @@ package de.danoeh.antennapod.core.util; +import android.content.Context; import android.util.Log; import org.apache.commons.lang3.StringUtils; @@ -7,6 +8,7 @@ import org.apache.commons.lang3.StringUtils; import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.GregorianCalendar; import java.util.Locale; import java.util.TimeZone; @@ -141,4 +143,17 @@ public class DateUtils { format.setTimeZone(defaultTimezone); return format.format(date); } + + public static String formatAbbrev(final Context context, final Date date) { + GregorianCalendar cal = new GregorianCalendar(); + cal.add(GregorianCalendar.YEAR, -1); + // some padding, because no one really remembers what day of the month it is + cal.add(GregorianCalendar.DAY_OF_MONTH, 10); + boolean withinLastYear = date.after(cal.getTime()); + int format = android.text.format.DateUtils.FORMAT_ABBREV_ALL; + if(withinLastYear) { + format |= android.text.format.DateUtils.FORMAT_NO_YEAR; + } + return android.text.format.DateUtils.formatDateTime(context, date.getTime(), format); + } } diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 80e3d57f5..55da0ee04 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -11,8 +11,9 @@ <item>0</item> <item>15</item> <item>30</item> - <item>45</item> <item>60</item> + <item>120</item> + <item>300</item> </string-array> diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index fa54ad22e..91a77e6e2 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -26,6 +26,8 @@ <string name="gpodnet_main_label">gpodder.net</string> <string name="gpodnet_auth_label">gpodder.net Login</string> <string name="free_space_label">%1$s free</string> + <string name="episode_cache_full_title">Episode cache full</string> + <string name="episode_cache_full_message">The episode cache limit has been reached. You can increase the cache size in the Settings.</string> <!-- New episodes fragment --> <string name="recently_published_episodes_label">Recently published</string> @@ -75,7 +77,7 @@ <string name="length_prefix">Length:\u0020</string> <string name="size_prefix">Size:\u0020</string> <string name="processing_label">Processing</string> - <string name="loading_label">Loading...</string> + <string name="loading_label">Loading…</string> <string name="save_username_password_label">Save username and password</string> <string name="close_label">Close</string> <string name="retry_label">Retry</string> @@ -87,7 +89,7 @@ <string name="feed_auto_download_global">Global</string> <string name="feed_auto_download_always">Always</string> <string name="feed_auto_download_never">Never</string> - <string name="send_label">Send...</string> + <string name="send_label">Send…</string> <string name="episode_cleanup_never">Never</string> <string name="episode_cleanup_queue_removal">When not in queue</string> <string name="episode_cleanup_after_listening">After finishing</string> @@ -112,7 +114,7 @@ <string name="mark_all_seen_label">Mark all as seen</string> <string name="show_info_label">Show information</string> <string name="remove_feed_label">Remove Podcast</string> - <string name="share_label">Share...</string> + <string name="share_label">Share…</string> <string name="share_link_label">Share Link</string> <string name="share_link_with_position_label">Share Link with Position</string> <string name="share_feed_url_label">Share Feed URL</string> @@ -219,6 +221,8 @@ <!-- Queue operations --> <string name="lock_queue">Lock Queue</string> <string name="unlock_queue">Unlock Queue</string> + <string name="queue_locked">Queue locked</string> + <string name="queue_unlocked">Queue unlocked</string> <string name="clear_queue_label">Clear Queue</string> <string name="undo">Undo</string> <string name="removed_from_queue">Item removed</string> @@ -300,6 +304,8 @@ <string name="pref_autoUpdateIntervallOrTime_Disable">Disable</string> <string name="pref_autoUpdateIntervallOrTime_Interval">Set Interval</string> <string name="pref_autoUpdateIntervallOrTime_TimeOfDay">Set Time of Day</string> + <string name="pref_autoUpdateIntervallOrTime_every">every %1$s</string> + <string name="pref_autoUpdateIntervallOrTime_at">at %1$s</string> <string name="pref_downloadMediaOnWifiOnly_sum">Download media files only over WiFi</string> <string name="pref_followQueue_title">Continuous Playback</string> <string name="pref_downloadMediaOnWifiOnly_title">WiFi media download</string> @@ -375,6 +381,7 @@ <string name="experimental_pref">Experimental</string> <string name="pref_sonic_title">Sonic media player</string> <string name="pref_sonic_message">Use built-in sonic media player as a replacement for Prestissimo</string> + <string name="pref_current_value">Current value: %1$s</string> <!-- Auto-Flattr dialog --> <string name="auto_flattr_enable">Enable automatic flattring</string> @@ -403,11 +410,11 @@ <string name="opml_import_error_dir_empty">The import directory is empty.</string> <string name="select_all_label">Select all</string> <string name="deselect_all_label">Deselect all</string> - <string name="select_options_label">Select ...</string> + <string name="select_options_label">Select…</string> <string name="choose_file_from_filesystem">From local filesystem</string> <string name="choose_file_from_external_application">Use external application</string> <string name="opml_export_label">OPML export</string> - <string name="exporting_label">Exporting...</string> + <string name="exporting_label">Exporting…</string> <string name="export_error_label">Export error</string> <string name="opml_export_success_title">OPML Export successful.</string> <string name="opml_export_success_sum">The .opml file was written to:\u0020</string> @@ -495,7 +502,7 @@ <!-- Online feed view --> <string name="subscribe_label">Subscribe</string> <string name="subscribed_label">Subscribed</string> - <string name="downloading_label">Downloading...</string> + <string name="downloading_label">Downloading…</string> <!-- Content descriptions for image buttons --> <string name="show_chapters_label">Show chapters</string> @@ -530,7 +537,7 @@ <string name="sp_apps_importing_feeds_msg">Importing subscriptions from single-purpose apps…</string> <string name="search_itunes_label">Search iTunes</string> - <string name="select_label"><b>Select ...</b></string> + <string name="select_label"><b>Select…</b></string> <string name="all_label">All</string> <string name="selected_all_label">Selected all Episodes</string> <string name="none_label">None</string> @@ -543,7 +550,7 @@ <string name="selected_downloaded_label">Selected downloaded Episodes</string> <string name="not_downloaded_label">Not downloaded</string> <string name="selected_not_downloaded_label">Selected not downloaded Episodes</string> - <string name="sort_title"><b>Sort by ...</b></string> + <string name="sort_title"><b>Sort by…</b></string> <string name="sort_title_a_z">Title (A \u2192 Z)</string> <string name="sort_title_z_a">Title (Z \u2192 A)</string> <string name="sort_date_new_old">Date (New \u2192 Old)</string> |