summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorasdoi <36813904+asdoi@users.noreply.github.com>2020-09-10 12:47:24 +0000
committerGitHub <noreply@github.com>2020-09-10 12:47:24 +0000
commit0adee1ef585159631a04deee9ed43486bae67b24 (patch)
tree90e7661610dea870465ba3dbdbed73bbc9d2113a
parent22e9a9af7e0931fd558066c6ea1bab6aa8237013 (diff)
parentb80978c40ac22bdaaea528c3908c5cf347088562 (diff)
downloadAntennaPod-0adee1ef585159631a04deee9ed43486bae67b24.zip
Merge branch 'develop' into dialog_keyboard
-rw-r--r--.circleci/config.yml14
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.md53
-rw-r--r--.github/ISSUE_TEMPLATE/config.yml5
-rw-r--r--.github/ISSUE_TEMPLATE/feature_request.md25
-rw-r--r--.github/PULL_REQUEST_TEMPLATE/default.md1
-rw-r--r--CONTRIBUTING.md15
-rw-r--r--app/build.gradle11
-rw-r--r--app/src/androidTest/java/de/test/antennapod/EspressoTestUtils.java27
-rw-r--r--app/src/androidTest/java/de/test/antennapod/dialogs/ShareDialogTest.java92
-rw-r--r--app/src/androidTest/java/de/test/antennapod/entities/ExternalMediaTest.java6
-rw-r--r--app/src/androidTest/java/de/test/antennapod/feed/FeedFilterTest.java27
-rw-r--r--app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java2
-rw-r--r--app/src/androidTest/java/de/test/antennapod/playback/PlaybackTest.java2
-rw-r--r--app/src/androidTest/java/de/test/antennapod/service/download/DownloadServiceTest.java20
-rw-r--r--app/src/androidTest/java/de/test/antennapod/service/download/HttpDownloaderTest.java6
-rw-r--r--app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java17
-rw-r--r--app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java21
-rw-r--r--app/src/androidTest/java/de/test/antennapod/storage/DBCleanupTests.java6
-rw-r--r--app/src/androidTest/java/de/test/antennapod/storage/DBNullCleanupAlgorithmTest.java6
-rw-r--r--app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java28
-rw-r--r--app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java24
-rw-r--r--app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java110
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/FeedSettingsTest.java2
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java9
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/NavigationDrawerTest.java6
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java15
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/QueueFragmentTest.java2
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/SpeedChangeTest.java7
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/TextOnlyFeedsTest.java2
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java4
-rw-r--r--app/src/androidTest/java/de/test/antennapod/util/FilenameGeneratorTest.java30
-rw-r--r--app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java4
-rw-r--r--app/src/androidTest/java/de/test/antennapod/util/syndication/FeedDiscovererTest.java8
-rw-r--r--app/src/main/AndroidManifest.xml10
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/BugReportActivity.java5
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java80
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java58
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java20
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java7
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java7
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java18
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java13
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/FeedFilterDialog.java38
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/FeedSortDialog.java38
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/FilterDialog.java60
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java85
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java11
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/ShareDialog.java112
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java196
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java9
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java14
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java45
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java1
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java24
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java62
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java7
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/FeedInfoFragment.java23
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java45
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java10
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java10
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java9
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/OnlineSearchFragment.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java18
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java30
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java43
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java3
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java31
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/preferences/AboutFragment.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/preferences/AutoDownloadPreferencesFragment.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderPreferencesFragment.java7
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/preferences/ImportExportPreferencesFragment.java5
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/preferences/MainPreferencesFragment.java12
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/preferences/PlaybackPreferencesFragment.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java14
-rw-r--r--app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java36
-rw-r--r--app/src/main/java/de/danoeh/antennapod/preferences/MasterSwitchPreference.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/spa/SPAUtil.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/EpisodeItemListRecyclerView.java9
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/ItemOffsetDecoration.java24
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/NestedScrollableHost.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/PlaybackSpeedSeekBar.java86
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/RecursiveRadioGroup.java67
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/ToolbarIconTintManager.java8
-rw-r--r--app/src/main/res/layout-sw720dp/main.xml46
-rw-r--r--app/src/main/res/layout/addfeed.xml6
-rw-r--r--app/src/main/res/layout/all_episodes_fragment.xml3
-rw-r--r--app/src/main/res/layout/audio_controls.xml46
-rw-r--r--app/src/main/res/layout/audioplayer_fragment.xml2
-rw-r--r--app/src/main/res/layout/choose_data_folder_dialog_entry.xml1
-rw-r--r--app/src/main/res/layout/cover_fragment.xml2
-rw-r--r--app/src/main/res/layout/downloadlog_item.xml1
-rw-r--r--app/src/main/res/layout/empty_view_layout.xml1
-rw-r--r--app/src/main/res/layout/feed_item_list_fragment.xml1
-rw-r--r--app/src/main/res/layout/feedinfo.xml2
-rw-r--r--app/src/main/res/layout/feeditemlist_header.xml2
-rw-r--r--app/src/main/res/layout/filter_dialog.xml11
-rw-r--r--app/src/main/res/layout/filter_dialog_row.xml61
-rw-r--r--app/src/main/res/layout/fragment_itunes_search.xml14
-rw-r--r--app/src/main/res/layout/fragment_subscriptions.xml16
-rw-r--r--app/src/main/res/layout/listview_activity.xml12
-rw-r--r--app/src/main/res/layout/main.xml6
-rw-r--r--app/src/main/res/layout/nav_section_item.xml22
-rw-r--r--app/src/main/res/layout/playback_speed_seek_bar.xml43
-rw-r--r--app/src/main/res/layout/queue_fragment.xml1
-rw-r--r--app/src/main/res/layout/quick_feed_discovery.xml11
-rw-r--r--app/src/main/res/layout/search_fragment.xml2
-rw-r--r--app/src/main/res/layout/searchlist_item.xml55
-rw-r--r--app/src/main/res/layout/share_episode_dialog.xml40
-rw-r--r--app/src/main/res/layout/simple_list_fragment.xml4
-rw-r--r--app/src/main/res/layout/speed_select_dialog.xml45
-rw-r--r--app/src/main/res/layout/statistics_fragment.xml24
-rw-r--r--app/src/main/res/menu/downloads_completed.xml6
-rw-r--r--app/src/main/res/menu/downloads_log.xml16
-rw-r--r--app/src/main/res/menu/downloads_running.xml10
-rw-r--r--app/src/main/res/menu/episodes_apply_action_options.xml2
-rw-r--r--app/src/main/res/menu/feeditem_options.xml24
-rw-r--r--app/src/main/res/menu/feedlist.xml24
-rw-r--r--app/src/main/res/menu/mediaplayer.xml24
-rw-r--r--app/src/main/res/menu/subscriptions.xml9
-rw-r--r--app/src/main/res/values-sw600dp/integers.xml4
-rw-r--r--app/src/main/res/values-w1000dp/dimens.xml4
-rw-r--r--app/src/main/res/values-w300dp/dimens-fabspeeddial.xml8
-rw-r--r--app/src/main/res/values-w300dp/dimens.xml11
-rw-r--r--app/src/main/res/values/dimens.xml4
-rw-r--r--app/src/main/res/values/integers.xml5
-rw-r--r--app/src/main/res/xml/automotive_app_desc.xml2
-rw-r--r--app/src/main/res/xml/feed_settings.xml4
-rw-r--r--app/src/main/res/xml/preferences.xml4
-rw-r--r--app/src/main/res/xml/preferences_autodownload.xml5
-rw-r--r--app/src/main/res/xml/preferences_gpodder.xml2
-rw-r--r--app/src/main/res/xml/preferences_network.xml4
-rw-r--r--app/src/main/res/xml/preferences_playback.xml28
-rw-r--r--app/src/main/res/xml/preferences_storage.xml6
-rw-r--r--app/src/main/res/xml/preferences_user_interface.xml42
-rw-r--r--app/src/main/res/xml/provider_paths.xml2
-rw-r--r--app/src/main/res/xml/searchable.xml4
-rw-r--r--app/src/play/java/de/danoeh/antennapod/activity/CastEnabledActivity.java2
-rw-r--r--artwork/screenshots/generateScreenshots.sh19
-rw-r--r--artwork/screenshots/raw/de-DE/tablet.pngbin0 -> 480806 bytes
-rw-r--r--artwork/screenshots/raw/de-DE/texts.txt1
-rw-r--r--artwork/screenshots/raw/en-US/tablet.pngbin0 -> 215587 bytes
-rw-r--r--artwork/screenshots/raw/en-US/texts.txt1
-rw-r--r--artwork/screenshots/raw/fr-FR/tablet.pngbin0 -> 476990 bytes
-rw-r--r--artwork/screenshots/raw/nl-NL/tablet.pngbin0 -> 477148 bytes
-rw-r--r--artwork/screenshots/raw/nl-NL/texts.txt1
-rw-r--r--artwork/screenshots/templates/tablet.pngbin0 -> 165190 bytes
-rw-r--r--core/build.gradle2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/event/DownloadEvent.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/event/DownloadLogEvent.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/event/DownloaderUpdate.java1
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/event/FavoritesEvent.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/event/FeedItemEvent.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedComponent.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedEvent.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java6
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java30
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilterGroup.java36
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java10
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java5
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/preferences/PlaybackPreferences.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java77
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java9
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java22
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java15
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java1
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java145
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java8
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeAction.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeActionChanges.java1
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/AtomText.java10
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/FileNameGenerator.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/RewindAfterPauseUtils.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/comparator/ChapterStartTimeComparator.java8
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/download/AutoUpdateManager.java5
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java7
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/OggInputStream.java2
-rw-r--r--core/src/main/res/color/filter_dialog_background_dark.xml5
-rw-r--r--core/src/main/res/color/filter_dialog_background_light.xml5
-rw-r--r--core/src/main/res/color/filter_dialog_button_text.xml5
-rw-r--r--core/src/main/res/color/filter_dialog_clear_dark.xml5
-rw-r--r--core/src/main/res/color/filter_dialog_clear_light.xml5
-rw-r--r--core/src/main/res/drawable/ic_filter_close.xml55
-rw-r--r--core/src/main/res/values/arrays.xml34
-rw-r--r--core/src/main/res/values/attrs.xml2
-rw-r--r--core/src/main/res/values/colors.xml5
-rw-r--r--core/src/main/res/values/dimens.xml2
-rw-r--r--core/src/main/res/values/strings.xml56
-rw-r--r--core/src/main/res/values/styles.xml6
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/feed/VolumeAdaptionSettingTest.java2
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/storage/ItemEnqueuePositionCalculatorTest.java6
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/util/FeedItemUtilTest.java3
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/util/LongLongMapTest.java8
211 files changed, 2262 insertions, 1227 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
index ccdd5aaee..093954036 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -39,6 +39,10 @@ workflows:
- run:
name: Build debug
command: ./gradlew assembleDebug -PdisablePreDex
+ - store_artifacts:
+ name: Uploading apk artifact
+ path: app/build/outputs/apk/play/debug/app-play-debug.apk
+ destination: app-play-debug.apk
- run:
name: Execute debug unit tests
command: ./gradlew :core:testPlayDebugUnitTest -PdisablePreDex
@@ -80,3 +84,13 @@ workflows:
echo "Comparing to $branchBaseCommit"
curl -s -L https://github.com/yangziwen/diff-checkstyle/releases/download/0.0.4/diff-checkstyle.jar > diff-checkstyle.jar
java -Dconfig_loc=config/checkstyle -jar diff-checkstyle.jar -c config/checkstyle/checkstyle-new-code.xml --git-dir . --base-rev $branchBaseCommit
+ - build:
+ name: Lint app
+ build-steps:
+ - run:
+ name: Lint app
+ command: ./gradlew app:lintPlayRelease
+ - store_artifacts:
+ name: Uploading lint reports
+ path: app/build/reports/lint-results-playRelease.html
+ destination: lint-results.html
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index cb7c71b63..25697186a 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -4,46 +4,24 @@ about: Create a report to help us improve existing features
---
-<!--
-DELETE ME
+# Checklist
+<!-- Place an x in the boxes to tick them: [x] -->
-Use the search function to see if someone else has already submitted the same bug report.
+- [ ] I have used the search function to see if someone else has already submitted the same bug report.
+- [ ] I will describe the problem with as much detail as possible.
+- [ ] If the bug only to occurs with a certain podcast, I will include the URL of that podcast.
-Try to describe the problem with as much detail as possible.
-
-Some bugs may only occur on certain devices or versions of Android. Please add information about your device and the version of Android that is running on it (you can look these up under `Settings → About Phone`), as well as which version of AntennaPod you are using.
-
-If the bug only seems to occur with a certain podcast, please include the URL of that podcast.
-
-If possible, add instructions on how to reproduce the bug.
-
-If possible, add a logfile to your post. This is especially useful if the bug makes the application crash. AntennaPod has an `export logs` feature for this.
-
-Usually, you can take a screenshot of your smartphone by pressing *Power* + *Volume down* for a few seconds.
-
-You don't need to adhere to the template strictly. Feel free to leave out information you feel is not important or does not make sense.
-
-If you are experiencing a crash, including the stacktrace will likely get it fixed sooner.
--->
-
-<!-- READ THIS: The latest version may be different depending on your device. You can find the version in AntennaPod's settings. -->
-**App version**: x.y.z (state whether from Google Play/F-Droid/Custom built APK)
+# System info
+<!-- The following information is very important to fill out because some bugs may only occur on certain devices or versions of Android. -->
+**App version**: x.y.z (Where did you download the app?)
+<!-- The latest version may be different depending on your device. You can find the version in AntennaPod's settings. -->
**Android version**: 5.x (Please mention if you are using a custom rom!)
-
**Device model**:
-
-**Expected behaviour**:
-
-
-**Current behaviour**:
-
-
-**First occurred**: (e.g. about x days/weeks ago)
-
+# Bug description
**Steps to reproduce**:
1. This
@@ -51,11 +29,18 @@ If you are experiencing a crash, including the stacktrace will likely get it fix
3. Then this
4. Etc.
+**Expected behaviour**:
+<!-- After following the steps, what did you think AntennaPod would do? -->
-**Environment**: (Settings you have changed (e.g. Auto Download). "Unusual" devices you use (e.g. Bluetooth headphones). Did you select another media player?)
+**Current behaviour**:
+<!-- What did AntennaPod do instead? Screenshots might help. Usually, you can take a screenshot of your smartphone by pressing *Power* + *Volume down* for a few seconds. -->
+**First occurred**: (e.g. about x days/weeks ago)
+
+**Environment**: (Settings you have changed (e.g. Auto Download). "Unusual" devices you use (e.g. Bluetooth headphones). Did you select another media player?)
-**Stacktrace/Logcat**:
+**Stacktrace/Logcat**:
+<!-- If you are experiencing a crash, including the stacktrace will likely get it fixed sooner. AntennaPod has an `export logs` feature for this. -->
```
[if available]
```
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 000000000..04c65727a
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,5 @@
+blank_issues_enabled: false
+contact_links:
+ - name: AntennaPod Forum
+ url: https://forum.antennapod.org/
+ about: Reduce developer's workload by asking other users.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index 8719120cd..bb60476d6 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -4,28 +4,25 @@ about: Request a new feature
---
-<!--
-DELETE ME
+# Checklist
+<!-- Place an x in the boxes to tick them: [x] -->
-Make sure you are using the latest version of AntennaPod. Perhaps the feature you are looking for has already been implemented.
+- [ ] I have used the search function to see if someone else has already submitted the same feature request.
+- [ ] I will only create one feature request per issue.
+- [ ] I will describe the problem with as much detail as possible.
-Use the search function to see if someone else has already submitted the same feature request. If there is another request already, please upvote the first post instead of commenting something like "I also want this".
+# System info
-To make it easier for us to keep track of requests, please only make one feature request per issue.
-
-Give a brief explanation about the problem that may currently exist and how your requested feature solves this problem.
-
-Try to be as specific as possible. Please not only explain what the feature does, but also how. If your request is about (or includes) changing or extending the UI, describe what the UI would look like and how the user would interact with it.
--->
-
-<!-- READ THIS: The latest version may be different depending on your device. You can find the version in AntennaPod's settings. -->
+<!-- The latest version may be different depending on your device. You can find the version in AntennaPod's settings. -->
**App version**: x.y.z (state whether from Google Play/F-Droid/Custom built APK)
+# Feature description
**Problem you may be having, or feature you want**:
-
+<!-- Give a brief explanation about the problem that may currently exist -->
**Suggested solution**:
-
+<!-- Describe how your requested feature solves this problem. Try to be as specific as possible. Please not only explain what the feature does, but also how. -->
**Screenshots / Drawings / Technical details**:
+<!-- If your request is about (or includes) changing or extending the UI, describe what the UI would look like and how the user would interact with it. -->
diff --git a/.github/PULL_REQUEST_TEMPLATE/default.md b/.github/PULL_REQUEST_TEMPLATE/default.md
new file mode 100644
index 000000000..f9fea783a
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE/default.md
@@ -0,0 +1 @@
+<!-- Please make sure that you have read our contribution guidelines: https://github.com/AntennaPod/AntennaPod/blob/develop/CONTRIBUTING.md#submit-a-pull-request -->
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 7ac62535c..a7cb59fc2 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -29,12 +29,9 @@ Submit a pull request
---------------------
- If you want to work on a feature that has been requested or fix a bug that has been reported on the "issues" page, add a comment to it so that other people know that you are working on it.
- Fork the repository.
-- Almost all changes of AntennaPod are done on the `develop` branch. If a new version of AntennaPod is released, the `develop` branch is merged into `master`. As a result, the `master` branch probably doesn't contain the latest changes when you are reading this. Please make sure that you are branching from `develop`! Otherwise, there might be a lot of merge-conflicts when merging your changes into `develop` and therefore it might take longer to review your pull-request. Exceptions are changes in files like README.md, CONTRIBUTING.md, and other files that are not directly related to the source code.
-- If your pull request fixes a bug that has been reported or implements a feature that has been requested in another issue, try to mention it so that it can be closed once your pull request has been merged. If you use special keywords in the [commit comment](https://help.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue) or [pull request text](https://github.blog/2013-05-14-closing-issues-via-pull-requests/), GitHub will close the issue(s) automatically when the changes land on the master branch.
-- Although not every part of AntennaPod's source code is fully documented yet, it would be very nice if you could add documentation to your changes if it is a larger pull request.
-- If possible, add unit tests for your pull request and make sure that they pass. Information on how to add unit tests and run them can be found here: (TODO)
-
-
-Improving this file
--------------------
-If you think this file needs clarification or additional information on certain topics, feel free to improve it via pull requests or by opening an issue.
+- Almost all changes of AntennaPod are done on the `develop` branch. If a new version of AntennaPod is released, the `develop` branch is merged into `master`. As a result, the `master` branch probably doesn't contain the latest changes when you are reading this. Please make sure that you are branching from `develop`! Otherwise, there might be a lot of merge-conflicts when merging your changes into `develop` and therefore it might take longer to review your pull-request. Exceptions are urgent issues that need to be fixed in the production version.
+- If your pull request fixes a bug that has been reported or implements a feature that has been requested in another issue, try to mention it in the message, so that it can be closed once your pull request has been merged. If you use special keywords in the [commit comment](https://help.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue) or [pull request text](https://github.blog/2013-05-14-closing-issues-via-pull-requests/), GitHub will close the issue(s) automatically.
+- If possible, add unit tests for your pull request and make sure that they pass.
+- Please do not upgrade dependencies or build tools unless you have a good reason for it. Doing so can easily introduce bugs that are hard to track down.
+- If you plan to do a change that touches many files (10+), please ask beforehand. This usually causes merge conflicts for other developers.
+- Please follow our code style. You can use Checkstyle within Android Studio using our [coniguration file](https://github.com/AntennaPod/AntennaPod/blob/develop/config/checkstyle/checkstyle-new-code.xml).
diff --git a/app/build.gradle b/app/build.gradle
index 1b5d8b713..4b44cf80c 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -98,7 +98,14 @@ android {
}
lintOptions {
- abortOnError false
+ disable 'ObsoleteLintCustomCheck', 'CheckResult', 'UnusedAttribute', 'BatteryLife', 'InflateParams',
+ 'GradleDependency', 'RestrictedApi', 'TrustAllX509TrustManager', 'ExportedReceiver', 'AllowBackup',
+ 'StaticFieldLeak', 'UseCompoundDrawables', 'NestedWeights', 'Overdraw', 'UselessParent', 'TextFields',
+ 'AlwaysShowAction', 'Autofill', 'ClickableViewAccessibility', 'ContentDescription',
+ 'KeyboardInaccessibleWidget', 'LabelFor', 'SetTextI18n', 'HardcodedText', 'RelativeOverlap',
+ 'RtlCompat', 'RtlHardcoded', 'MissingMediaBrowserServiceIntentFilter'
+ warningsAsErrors true
+ abortOnError true
}
compileOptions {
@@ -182,6 +189,7 @@ dependencies {
androidTestImplementation "androidx.test.espresso:espresso-intents:$espressoVersion"
androidTestImplementation "androidx.test:runner:$runnerVersion"
androidTestImplementation "androidx.test:rules:$rulesVersion"
+ androidTestImplementation 'androidx.test.ext:junit:1.1.1'
}
if (project.hasProperty("antennaPodPlayPublisherCredentials")) {
@@ -198,7 +206,6 @@ task copyLicense(type: Copy) {
rename { String fileName ->
fileName + ".txt"
}
- outputs.upToDateWhen { false }
}
preBuild.dependsOn copyLicense
diff --git a/app/src/androidTest/java/de/test/antennapod/EspressoTestUtils.java b/app/src/androidTest/java/de/test/antennapod/EspressoTestUtils.java
index 41c8365fb..3c8c5d7f0 100644
--- a/app/src/androidTest/java/de/test/antennapod/EspressoTestUtils.java
+++ b/app/src/androidTest/java/de/test/antennapod/EspressoTestUtils.java
@@ -5,7 +5,7 @@ import android.content.Intent;
import androidx.annotation.IdRes;
import androidx.annotation.StringRes;
import androidx.preference.PreferenceManager;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.espresso.PerformException;
import androidx.test.espresso.UiController;
import androidx.test.espresso.ViewAction;
@@ -116,38 +116,39 @@ public class EspressoTestUtils {
* Clear all app databases
*/
public static void clearPreferences() {
- File root = InstrumentationRegistry.getTargetContext().getFilesDir().getParentFile();
+ File root = InstrumentationRegistry.getInstrumentation().getTargetContext().getFilesDir().getParentFile();
String[] sharedPreferencesFileNames = new File(root, "shared_prefs").list();
for (String fileName : sharedPreferencesFileNames) {
System.out.println("Cleared database: " + fileName);
- InstrumentationRegistry.getTargetContext().getSharedPreferences(
+ InstrumentationRegistry.getInstrumentation().getTargetContext().getSharedPreferences(
fileName.replace(".xml", ""), Context.MODE_PRIVATE).edit().clear().commit();
}
- InstrumentationRegistry.getTargetContext().getSharedPreferences(MainActivity.PREF_NAME, Context.MODE_PRIVATE)
+ InstrumentationRegistry.getInstrumentation().getTargetContext()
+ .getSharedPreferences(MainActivity.PREF_NAME, Context.MODE_PRIVATE)
.edit()
.putBoolean(MainActivity.PREF_IS_FIRST_LAUNCH, false)
.commit();
- PreferenceManager.getDefaultSharedPreferences(InstrumentationRegistry.getTargetContext())
+ PreferenceManager.getDefaultSharedPreferences(InstrumentationRegistry.getInstrumentation().getTargetContext())
.edit()
.putString(UserPreferences.PREF_UPDATE_INTERVAL, "0")
.commit();
- RatingDialog.init(InstrumentationRegistry.getTargetContext());
+ RatingDialog.init(InstrumentationRegistry.getInstrumentation().getTargetContext());
RatingDialog.saveRated();
}
public static void setLastNavFragment(String tag) {
- InstrumentationRegistry.getTargetContext().getSharedPreferences(
- NavDrawerFragment.PREF_NAME, Context.MODE_PRIVATE)
+ InstrumentationRegistry.getInstrumentation().getTargetContext()
+ .getSharedPreferences(NavDrawerFragment.PREF_NAME, Context.MODE_PRIVATE)
.edit()
.putString(NavDrawerFragment.PREF_LAST_FRAGMENT_TAG, tag)
.commit();
}
public static void clearDatabase() {
- PodDBAdapter.init(InstrumentationRegistry.getTargetContext());
+ PodDBAdapter.init(InstrumentationRegistry.getInstrumentation().getTargetContext());
PodDBAdapter.deleteDatabase();
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
@@ -172,7 +173,7 @@ public class EspressoTestUtils {
}
public static void tryKillPlaybackService() {
- Context context = InstrumentationRegistry.getTargetContext();
+ Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
context.stopService(new Intent(context, PlaybackService.class));
try {
// Android has no reliable way to stop a service instantly.
@@ -183,11 +184,11 @@ public class EspressoTestUtils {
} catch (ConditionTimeoutException e) {
e.printStackTrace();
}
- androidx.test.platform.app.InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
public static void tryKillDownloadService() {
- Context context = InstrumentationRegistry.getTargetContext();
+ Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
context.stopService(new Intent(context, DownloadService.class));
try {
// Android has no reliable way to stop a service instantly.
@@ -198,7 +199,7 @@ public class EspressoTestUtils {
} catch (ConditionTimeoutException e) {
e.printStackTrace();
}
- androidx.test.platform.app.InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
public static Matcher<View> actionBarOverflow() {
diff --git a/app/src/androidTest/java/de/test/antennapod/dialogs/ShareDialogTest.java b/app/src/androidTest/java/de/test/antennapod/dialogs/ShareDialogTest.java
new file mode 100644
index 000000000..8c628efd5
--- /dev/null
+++ b/app/src/androidTest/java/de/test/antennapod/dialogs/ShareDialogTest.java
@@ -0,0 +1,92 @@
+package de.test.antennapod.dialogs;
+
+import android.content.Context;
+import android.content.Intent;
+import android.view.View;
+
+import org.hamcrest.Matcher;
+import org.hamcrest.Matchers;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+import androidx.test.espresso.intent.rule.IntentsTestRule;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.activity.MainActivity;
+import de.danoeh.antennapod.core.feed.FeedItem;
+import de.danoeh.antennapod.core.storage.DBReader;
+import de.danoeh.antennapod.fragment.EpisodesFragment;
+import de.test.antennapod.EspressoTestUtils;
+import de.test.antennapod.ui.UITestUtils;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.action.ViewActions.scrollTo;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition;
+import static androidx.test.espresso.matcher.ViewMatchers.hasMinimumChildCount;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+import static de.test.antennapod.EspressoTestUtils.onDrawerItem;
+import static de.test.antennapod.EspressoTestUtils.openNavDrawer;
+import static de.test.antennapod.EspressoTestUtils.waitForView;
+import static de.test.antennapod.NthMatcher.first;
+import static org.hamcrest.CoreMatchers.allOf;
+
+/**
+ * User interface tests for share dialog.
+ */
+@RunWith(AndroidJUnit4.class)
+public class ShareDialogTest {
+
+ @Rule
+ public IntentsTestRule<MainActivity> activityRule = new IntentsTestRule<>(MainActivity.class, false, false);
+
+ private UITestUtils uiTestUtils;
+ protected Context context;
+
+ @Before
+ public void setUp() throws Exception {
+ context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ EspressoTestUtils.clearPreferences();
+ EspressoTestUtils.clearDatabase();
+ EspressoTestUtils.setLastNavFragment(EpisodesFragment.TAG);
+ uiTestUtils = new UITestUtils(context);
+ uiTestUtils.setup();
+ uiTestUtils.addLocalFeedData(true);
+
+ activityRule.launchActivity(new Intent());
+
+ openNavDrawer();
+ onDrawerItem(withText(R.string.episodes_label)).perform(click());
+ onView(isRoot()).perform(waitForView(withText(R.string.all_episodes_short_label), 1000));
+ onView(withText(R.string.all_episodes_short_label)).perform(click());
+
+ Matcher<View> allEpisodesMatcher;
+ final List<FeedItem> episodes = DBReader.getRecentlyPublishedEpisodes(0, 10);
+ allEpisodesMatcher = Matchers.allOf(withId(android.R.id.list), isDisplayed(), hasMinimumChildCount(2));
+ onView(isRoot()).perform(waitForView(allEpisodesMatcher, 1000));
+ onView(allEpisodesMatcher).perform(actionOnItemAtPosition(0, click()));
+ onView(first(EspressoTestUtils.actionBarOverflow())).perform(click());
+ }
+
+ @Test
+ public void testShareDialogDisplayed() throws InterruptedException {
+ onView(withText(R.string.share_label_with_ellipses)).perform(click());
+ onView(allOf(isDisplayed(), withText(R.string.share_label)));
+ }
+
+ @Test
+ public void testShareDialogCancelButton() {
+ onView(withText(R.string.share_label_with_ellipses)).perform(scrollTo()).perform(click());
+ onView(withText(R.string.cancel_label)).check(matches(isDisplayed())).perform(scrollTo()).perform(click());
+ }
+
+}
diff --git a/app/src/androidTest/java/de/test/antennapod/entities/ExternalMediaTest.java b/app/src/androidTest/java/de/test/antennapod/entities/ExternalMediaTest.java
index b3c79367f..83d7a4d22 100644
--- a/app/src/androidTest/java/de/test/antennapod/entities/ExternalMediaTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/entities/ExternalMediaTest.java
@@ -2,9 +2,9 @@ package de.test.antennapod.entities;
import android.annotation.SuppressLint;
import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
+import androidx.preference.PreferenceManager;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.filters.SmallTest;
import de.danoeh.antennapod.core.feed.MediaType;
@@ -36,7 +36,7 @@ public class ExternalMediaTest {
}
private SharedPreferences getDefaultSharedPrefs() {
- return PreferenceManager.getDefaultSharedPreferences(InstrumentationRegistry.getTargetContext());
+ return PreferenceManager.getDefaultSharedPreferences(InstrumentationRegistry.getInstrumentation().getTargetContext());
}
@Test
diff --git a/app/src/androidTest/java/de/test/antennapod/feed/FeedFilterTest.java b/app/src/androidTest/java/de/test/antennapod/feed/FeedFilterTest.java
index 4b81a4f2b..fc2943205 100644
--- a/app/src/androidTest/java/de/test/antennapod/feed/FeedFilterTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/feed/FeedFilterTest.java
@@ -6,6 +6,7 @@ import de.danoeh.antennapod.core.feed.FeedItem;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@SmallTest
@@ -17,8 +18,8 @@ public class FeedFilterTest {
FeedItem item = new FeedItem();
item.setTitle("Hello world");
- assertTrue(!filter.excludeOnly());
- assertTrue(!filter.includeOnly());
+ assertFalse(filter.excludeOnly());
+ assertFalse(filter.includeOnly());
assertEquals("", filter.getExcludeFilter());
assertEquals("", filter.getIncludeFilter());
assertTrue(filter.shouldAutoDownload(item));
@@ -34,12 +35,12 @@ public class FeedFilterTest {
FeedItem item2 = new FeedItem();
item2.setTitle("Don't include me");
- assertTrue(!filter.excludeOnly());
+ assertFalse(filter.excludeOnly());
assertTrue(filter.includeOnly());
assertEquals("", filter.getExcludeFilter());
assertEquals(includeFilter, filter.getIncludeFilter());
assertTrue(filter.shouldAutoDownload(item));
- assertTrue(!filter.shouldAutoDownload(item2));
+ assertFalse(filter.shouldAutoDownload(item2));
}
@Test
@@ -53,10 +54,10 @@ public class FeedFilterTest {
item2.setTitle("Item2");
assertTrue(filter.excludeOnly());
- assertTrue(!filter.includeOnly());
+ assertFalse(filter.includeOnly());
assertEquals(excludeFilter, filter.getExcludeFilter());
assertEquals("", filter.getIncludeFilter());
- assertTrue(!filter.shouldAutoDownload(item));
+ assertFalse(filter.shouldAutoDownload(item));
assertTrue(filter.shouldAutoDownload(item2));
}
@@ -73,12 +74,12 @@ public class FeedFilterTest {
FeedItem item3 = new FeedItem();
item3.setTitle("One two words");
- assertTrue(!filter.excludeOnly());
+ assertFalse(filter.excludeOnly());
assertTrue(filter.includeOnly());
assertEquals("", filter.getExcludeFilter());
assertEquals(includeFilter, filter.getIncludeFilter());
assertTrue(filter.shouldAutoDownload(item));
- assertTrue(!filter.shouldAutoDownload(item2));
+ assertFalse(filter.shouldAutoDownload(item2));
assertTrue(filter.shouldAutoDownload(item3));
}
@@ -96,12 +97,12 @@ public class FeedFilterTest {
item3.setTitle("One two words");
assertTrue(filter.excludeOnly());
- assertTrue(!filter.includeOnly());
+ assertFalse(filter.includeOnly());
assertEquals(excludeFilter, filter.getExcludeFilter());
assertEquals("", filter.getIncludeFilter());
- assertTrue(!filter.shouldAutoDownload(item));
+ assertFalse(filter.shouldAutoDownload(item));
assertTrue(filter.shouldAutoDownload(item2));
- assertTrue(!filter.shouldAutoDownload(item3));
+ assertFalse(filter.shouldAutoDownload(item3));
}
@Test
@@ -122,8 +123,8 @@ public class FeedFilterTest {
assertTrue(filter.hasExcludeFilter());
assertTrue(filter.hasIncludeFilter());
assertTrue(filter.shouldAutoDownload(download));
- assertTrue(!filter.shouldAutoDownload(doNotDownload));
- assertTrue(!filter.shouldAutoDownload(doNotDownload2));
+ assertFalse(filter.shouldAutoDownload(doNotDownload));
+ assertFalse(filter.shouldAutoDownload(doNotDownload2));
}
}
diff --git a/app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java b/app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java
index e7e8c5b09..9b3422a5d 100644
--- a/app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java
@@ -4,7 +4,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetService;
import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetServiceException;
diff --git a/app/src/androidTest/java/de/test/antennapod/playback/PlaybackTest.java b/app/src/androidTest/java/de/test/antennapod/playback/PlaybackTest.java
index 0a3a9f13a..419cf2096 100644
--- a/app/src/androidTest/java/de/test/antennapod/playback/PlaybackTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/playback/PlaybackTest.java
@@ -3,7 +3,7 @@ package de.test.antennapod.playback;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
+import androidx.preference.PreferenceManager;
import android.view.View;
import androidx.test.filters.LargeTest;
diff --git a/app/src/androidTest/java/de/test/antennapod/service/download/DownloadServiceTest.java b/app/src/androidTest/java/de/test/antennapod/service/download/DownloadServiceTest.java
index b75044d73..fd395f7c1 100644
--- a/app/src/androidTest/java/de/test/antennapod/service/download/DownloadServiceTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/service/download/DownloadServiceTest.java
@@ -5,8 +5,8 @@ import android.content.Intent;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.util.Consumer;
-import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import de.test.antennapod.EspressoTestUtils;
import org.awaitility.Awaitility;
@@ -81,7 +81,7 @@ public class DownloadServiceTest {
@After
public void tearDown() throws Exception {
DownloadService.setDownloaderFactory(origFactory);
- Context context = InstrumentationRegistry.getTargetContext();
+ Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
DownloadRequester.getInstance().cancelAllDownloads(context);
context.stopService(new Intent(context, DownloadService.class));
EspressoTestUtils.tryKillDownloadService();
@@ -106,9 +106,7 @@ public class DownloadServiceTest {
// OPEN: Ideally, I'd like the download time long enough so that multiple in-progress DownloadEvents
// are generated (to simulate typical download), but it'll make download time quite long (1-2 seconds)
// to do so
- DownloadService.setDownloaderFactory(new StubDownloaderFactory(50, downloadStatus -> {
- downloadStatus.setSuccessful();
- }));
+ DownloadService.setDownloaderFactory(new StubDownloaderFactory(50, DownloadStatus::setSuccessful));
UserPreferences.setEnqueueDownloadedEpisodes(enqueueDownloaded);
withFeedItemEventListener(feedItemEventListener -> {
@@ -117,7 +115,8 @@ public class DownloadServiceTest {
assertFalse("The media in test should not yet been downloaded",
DBReader.getFeedMedia(testMedia11.getId()).isDownloaded());
- DownloadRequester.getInstance().downloadMedia(false, InstrumentationRegistry.getTargetContext(), true, testMedia11.getItem());
+ DownloadRequester.getInstance().downloadMedia(false, InstrumentationRegistry
+ .getInstrumentation().getTargetContext(), true, testMedia11.getItem());
Awaitility.await()
.atMost(5000, TimeUnit.MILLISECONDS)
.until(() -> feedItemEventListener.getEvents().size() >= numEventsExpected);
@@ -144,11 +143,10 @@ public class DownloadServiceTest {
}
private void doTestCancelDownload_UndoEnqueue(boolean itemAlreadyInQueue) throws Exception {
- Context context = InstrumentationRegistry.getTargetContext();
+ Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
// let download take longer to ensure the test can cancel the download in time
- DownloadService.setDownloaderFactory(new StubDownloaderFactory(30000, downloadStatus -> {
- downloadStatus.setSuccessful();
- }));
+ DownloadService.setDownloaderFactory(
+ new StubDownloaderFactory(30000, DownloadStatus::setSuccessful));
UserPreferences.setEnqueueDownloadedEpisodes(true);
UserPreferences.setEnableAutodownload(false);
diff --git a/app/src/androidTest/java/de/test/antennapod/service/download/HttpDownloaderTest.java b/app/src/androidTest/java/de/test/antennapod/service/download/HttpDownloaderTest.java
index 301ceea6c..4ef6594e3 100644
--- a/app/src/androidTest/java/de/test/antennapod/service/download/HttpDownloaderTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/service/download/HttpDownloaderTest.java
@@ -1,6 +1,6 @@
package de.test.antennapod.service.download;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import android.util.Log;
@@ -51,7 +51,7 @@ public class HttpDownloaderTest {
@Before
public void setUp() throws Exception {
UserPreferences.init(InstrumentationRegistry.getInstrumentation().getTargetContext());
- destDir = InstrumentationRegistry.getTargetContext().getExternalFilesDir(DOWNLOAD_DIR);
+ destDir = InstrumentationRegistry.getInstrumentation().getTargetContext().getExternalFilesDir(DOWNLOAD_DIR);
assertNotNull(destDir);
assertTrue(destDir.exists());
httpServer = new HTTPBin();
@@ -82,7 +82,7 @@ public class HttpDownloaderTest {
downloader.call();
DownloadStatus status = downloader.getResult();
assertNotNull(status);
- assertTrue(status.isSuccessful() == expectedResult);
+ assertEquals(expectedResult, status.isSuccessful());
assertTrue(status.isDone());
// the file should not exist if the download has failed and deleteExisting was true
assertTrue(!deleteExisting || new File(feedFile.getFile_url()).exists() == expectedResult);
diff --git a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java
index cfce069ec..c9cbf1bb2 100644
--- a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java
@@ -38,6 +38,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -173,7 +174,7 @@ public class PlaybackServiceMediaPlayerTest {
throw assertionError;
assertTrue(res);
- assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.INITIALIZED);
+ assertSame(PlayerStatus.INITIALIZED, psmp.getPSMPInfo().playerStatus);
assertFalse(psmp.isStartWhenPrepared());
callback.cancel();
psmp.shutdown();
@@ -214,7 +215,7 @@ public class PlaybackServiceMediaPlayerTest {
throw assertionError;
assertTrue(res);
- assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.INITIALIZED);
+ assertSame(PlayerStatus.INITIALIZED, psmp.getPSMPInfo().playerStatus);
assertTrue(psmp.isStartWhenPrepared());
callback.cancel();
psmp.shutdown();
@@ -256,7 +257,7 @@ public class PlaybackServiceMediaPlayerTest {
if (assertionError != null)
throw assertionError;
assertTrue(res);
- assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.PREPARED);
+ assertSame(PlayerStatus.PREPARED, psmp.getPSMPInfo().playerStatus);
callback.cancel();
psmp.shutdown();
@@ -301,7 +302,7 @@ public class PlaybackServiceMediaPlayerTest {
if (assertionError != null)
throw assertionError;
assertTrue(res);
- assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.PLAYING);
+ assertSame(PlayerStatus.PLAYING, psmp.getPSMPInfo().playerStatus);
callback.cancel();
psmp.shutdown();
}
@@ -339,7 +340,7 @@ public class PlaybackServiceMediaPlayerTest {
if (assertionError != null)
throw assertionError;
assertTrue(res);
- assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.INITIALIZED);
+ assertSame(PlayerStatus.INITIALIZED, psmp.getPSMPInfo().playerStatus);
assertFalse(psmp.isStartWhenPrepared());
callback.cancel();
psmp.shutdown();
@@ -378,7 +379,7 @@ public class PlaybackServiceMediaPlayerTest {
if (assertionError != null)
throw assertionError;
assertTrue(res);
- assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.INITIALIZED);
+ assertSame(PlayerStatus.INITIALIZED, psmp.getPSMPInfo().playerStatus);
assertTrue(psmp.isStartWhenPrepared());
callback.cancel();
psmp.shutdown();
@@ -420,7 +421,7 @@ public class PlaybackServiceMediaPlayerTest {
if (assertionError != null)
throw assertionError;
assertTrue(res);
- assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.PREPARED);
+ assertSame(PlayerStatus.PREPARED, psmp.getPSMPInfo().playerStatus);
callback.cancel();
psmp.shutdown();
}
@@ -465,7 +466,7 @@ public class PlaybackServiceMediaPlayerTest {
if (assertionError != null)
throw assertionError;
assertTrue(res);
- assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.PLAYING);
+ assertSame(PlayerStatus.PLAYING, psmp.getPSMPInfo().playerStatus);
callback.cancel();
psmp.shutdown();
}
diff --git a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java
index fce78ea4f..f039c8bdf 100644
--- a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java
@@ -1,7 +1,7 @@
package de.test.antennapod.service.playback;
import android.content.Context;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.annotation.UiThreadTest;
import androidx.test.filters.LargeTest;
@@ -29,6 +29,7 @@ import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.danoeh.antennapod.core.util.playback.Playable;
import static de.test.antennapod.util.event.FeedItemEventListener.withFeedItemEventListener;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -92,9 +93,9 @@ public class PlaybackServiceTaskManagerTest {
PlaybackServiceTaskManager pstm = new PlaybackServiceTaskManager(c, defaultPSTM);
List<FeedItem> testQueue = pstm.getQueue();
assertNotNull(testQueue);
- assertTrue(queue.size() == testQueue.size());
+ assertEquals(testQueue.size(), queue.size());
for (int i = 0; i < queue.size(); i++) {
- assertTrue(queue.get(i).getId() == testQueue.get(i).getId());
+ assertEquals(testQueue.get(i).getId(), queue.get(i).getId());
}
pstm.shutdown();
}
@@ -114,9 +115,9 @@ public class PlaybackServiceTaskManagerTest {
assertNotNull(queue);
testQueue = pstm.getQueue();
assertNotNull(testQueue);
- assertTrue(queue.size() == testQueue.size());
+ assertEquals(testQueue.size(), queue.size());
for (int i = 0; i < queue.size(); i++) {
- assertTrue(queue.get(i).getId() == testQueue.get(i).getId());
+ assertEquals(testQueue.get(i).getId(), queue.get(i).getId());
}
pstm.shutdown();
}
@@ -171,7 +172,7 @@ public class PlaybackServiceTaskManagerTest {
}
@Override
- public void onSleepTimerAlmostExpired() {
+ public void onSleepTimerAlmostExpired(long timeLeft) {
}
@@ -232,7 +233,7 @@ public class PlaybackServiceTaskManagerTest {
}
@Override
- public void onSleepTimerAlmostExpired() {
+ public void onSleepTimerAlmostExpired(long timeLeft) {
}
@@ -329,7 +330,7 @@ public class PlaybackServiceTaskManagerTest {
}
@Override
- public void onSleepTimerAlmostExpired() {
+ public void onSleepTimerAlmostExpired(long timeLeft) {
}
@@ -375,7 +376,7 @@ public class PlaybackServiceTaskManagerTest {
}
@Override
- public void onSleepTimerAlmostExpired() {
+ public void onSleepTimerAlmostExpired(long timeLeft) {
}
@@ -433,7 +434,7 @@ public class PlaybackServiceTaskManagerTest {
}
@Override
- public void onSleepTimerAlmostExpired() {
+ public void onSleepTimerAlmostExpired(long timeLeft) {
}
diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBCleanupTests.java b/app/src/androidTest/java/de/test/antennapod/storage/DBCleanupTests.java
index 88d78fd14..6c36da13e 100644
--- a/app/src/androidTest/java/de/test/antennapod/storage/DBCleanupTests.java
+++ b/app/src/androidTest/java/de/test/antennapod/storage/DBCleanupTests.java
@@ -2,7 +2,7 @@ package de.test.antennapod.storage;
import android.content.Context;
import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
+import androidx.preference.PreferenceManager;
import java.io.File;
import java.io.IOException;
@@ -10,7 +10,7 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.filters.SmallTest;
import de.danoeh.antennapod.core.feed.Feed;
@@ -64,7 +64,7 @@ public class DBCleanupTests {
@Before
public void setUp() throws Exception {
- context = InstrumentationRegistry.getTargetContext();
+ context = InstrumentationRegistry.getInstrumentation().getTargetContext();
destFolder = new File(context.getCacheDir(), "DDCleanupTests");
destFolder.mkdir();
cleanupDestFolder(destFolder);
diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBNullCleanupAlgorithmTest.java b/app/src/androidTest/java/de/test/antennapod/storage/DBNullCleanupAlgorithmTest.java
index 24cc80061..d7ebf2351 100644
--- a/app/src/androidTest/java/de/test/antennapod/storage/DBNullCleanupAlgorithmTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/storage/DBNullCleanupAlgorithmTest.java
@@ -2,7 +2,7 @@ package de.test.antennapod.storage;
import android.content.Context;
import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
+import androidx.preference.PreferenceManager;
import java.io.File;
import java.io.IOException;
@@ -10,7 +10,7 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.filters.SmallTest;
import de.danoeh.antennapod.core.feed.Feed;
@@ -55,7 +55,7 @@ public class DBNullCleanupAlgorithmTest {
@Before
public void setUp() throws Exception {
- context = InstrumentationRegistry.getTargetContext();
+ context = InstrumentationRegistry.getInstrumentation().getTargetContext();
destFolder = context.getExternalCacheDir();
cleanupDestFolder(destFolder);
assertNotNull(destFolder);
diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java b/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java
index b2458bac6..409100e26 100644
--- a/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java
@@ -5,7 +5,7 @@ import java.util.Date;
import java.util.List;
import java.util.Random;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
@@ -38,7 +38,7 @@ public class DBReaderTest {
@Before
public void setUp() throws Exception {
// create new database
- PodDBAdapter.init(InstrumentationRegistry.getTargetContext());
+ PodDBAdapter.init(InstrumentationRegistry.getInstrumentation().getTargetContext());
PodDBAdapter.deleteDatabase();
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
@@ -52,7 +52,7 @@ public class DBReaderTest {
assertNotNull(savedFeeds);
assertEquals(feeds.size(), savedFeeds.size());
for (int i = 0; i < feeds.size(); i++) {
- assertTrue(savedFeeds.get(i).getId() == feeds.get(i).getId());
+ assertEquals(feeds.get(i).getId(), savedFeeds.get(i).getId());
}
}
@@ -91,7 +91,7 @@ public class DBReaderTest {
List<Feed> feeds = saveFeedlist(10, 0, false);
List<String> urls = DBReader.getFeedListDownloadUrls();
assertNotNull(urls);
- assertTrue(urls.size() == feeds.size());
+ assertEquals(feeds.size(), urls.size());
for (int i = 0; i < urls.size(); i++) {
assertEquals(urls.get(i), feeds.get(i).getDownload_url());
}
@@ -115,8 +115,8 @@ public class DBReaderTest {
for (int j = 0; j < numItems; j++) {
FeedItem item = feeds.get(i).getItems().get(j);
assertNotNull(item.getFeed());
- assertTrue(item.getFeed().getId() == feeds.get(i).getId());
- assertTrue(item.getFeedId() == item.getFeed().getId());
+ assertEquals(feeds.get(i).getId(), item.getFeed().getId());
+ assertEquals(item.getFeed().getId(), item.getFeedId());
}
}
}
@@ -130,9 +130,9 @@ public class DBReaderTest {
feed.setItems(null);
List<FeedItem> savedItems = DBReader.getFeedItemList(feed);
assertNotNull(savedItems);
- assertTrue(savedItems.size() == items.size());
+ assertEquals(items.size(), savedItems.size());
for (int i = 0; i < savedItems.size(); i++) {
- assertTrue(items.get(i).getId() == savedItems.get(i).getId());
+ assertEquals(savedItems.get(i).getId(), items.get(i).getId());
}
}
@@ -167,10 +167,10 @@ public class DBReaderTest {
List<FeedItem> queue = saveQueue(numItems);
LongList ids = DBReader.getQueueIDList();
assertNotNull(ids);
- assertTrue(queue.size() == ids.size());
+ assertEquals(ids.size(), queue.size());
for (int i = 0; i < queue.size(); i++) {
assertTrue(ids.get(i) != 0);
- assertTrue(queue.get(i).getId() == ids.get(i));
+ assertEquals(ids.get(i), queue.get(i).getId());
}
}
@@ -180,10 +180,10 @@ public class DBReaderTest {
List<FeedItem> queue = saveQueue(numItems);
List<FeedItem> savedQueue = DBReader.getQueue();
assertNotNull(savedQueue);
- assertTrue(queue.size() == savedQueue.size());
+ assertEquals(savedQueue.size(), queue.size());
for (int i = 0; i < queue.size(); i++) {
assertTrue(savedQueue.get(i).getId() != 0);
- assertTrue(queue.get(i).getId() == savedQueue.get(i).getId());
+ assertEquals(savedQueue.get(i).getId(), queue.get(i).getId());
}
}
@@ -221,7 +221,7 @@ public class DBReaderTest {
List<FeedItem> downloaded = saveDownloadedItems(numItems);
List<FeedItem> downloaded_saved = DBReader.getDownloadedItems();
assertNotNull(downloaded_saved);
- assertTrue(downloaded_saved.size() == downloaded.size());
+ assertEquals(downloaded.size(), downloaded_saved.size());
for (FeedItem item : downloaded_saved) {
assertNotNull(item.getMedia());
assertTrue(item.getMedia().isDownloaded());
@@ -264,7 +264,7 @@ public class DBReaderTest {
}
List<FeedItem> newItemsSaved = DBReader.getNewItemsList(0, Integer.MAX_VALUE);
assertNotNull(newItemsSaved);
- assertTrue(newItems.size() == newItemsSaved.size());
+ assertEquals(newItemsSaved.size(), newItems.size());
for (FeedItem feedItem : newItemsSaved) {
long savedId = feedItem.getId();
boolean found = false;
diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java b/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java
index 090cd2213..595a9794f 100644
--- a/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java
@@ -2,7 +2,7 @@ package de.test.antennapod.storage;
import android.content.Context;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import org.junit.After;
@@ -29,6 +29,8 @@ import static java.util.Collections.singletonList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
/**
@@ -45,7 +47,7 @@ public class DBTasksTest {
@Before
public void setUp() throws Exception {
- context = InstrumentationRegistry.getTargetContext();
+ context = InstrumentationRegistry.getInstrumentation().getTargetContext();
// create new database
PodDBAdapter.init(context);
@@ -68,7 +70,7 @@ public class DBTasksTest {
}
Feed newFeed = DBTasks.updateFeed(context, feed)[0];
- assertTrue(newFeed == feed);
+ assertSame(feed, newFeed);
assertTrue(feed.getId() != 0);
for (FeedItem item : feed.getItems()) {
assertFalse(item.isPlayed());
@@ -123,13 +125,13 @@ public class DBTasksTest {
}
final Feed newFeed = DBTasks.updateFeed(context, feed)[0];
- assertTrue(feed != newFeed);
+ assertNotSame(newFeed, feed);
updatedFeedTest(newFeed, feedID, itemIDs, NUM_ITEMS_OLD, NUM_ITEMS_NEW);
final Feed feedFromDB = DBReader.getFeed(newFeed.getId());
assertNotNull(feedFromDB);
- assertTrue(feedFromDB.getId() == newFeed.getId());
+ assertEquals(newFeed.getId(), feedFromDB.getId());
updatedFeedTest(feedFromDB, feedID, itemIDs, NUM_ITEMS_OLD, NUM_ITEMS_NEW);
}
@@ -155,7 +157,7 @@ public class DBTasksTest {
feed.setItems(list);
final Feed newFeed = DBTasks.updateFeed(context, feed)[0];
- assertTrue(feed != newFeed);
+ assertNotSame(newFeed, feed);
final Feed feedFromDB = DBReader.getFeed(newFeed.getId());
final FeedItem feedItemFromDB = feedFromDB.getItems().get(0);
@@ -163,21 +165,21 @@ public class DBTasksTest {
}
private void updatedFeedTest(final Feed newFeed, long feedID, List<Long> itemIDs, final int NUM_ITEMS_OLD, final int NUM_ITEMS_NEW) {
- assertTrue(newFeed.getId() == feedID);
- assertTrue(newFeed.getItems().size() == NUM_ITEMS_NEW + NUM_ITEMS_OLD);
+ assertEquals(feedID, newFeed.getId());
+ assertEquals(NUM_ITEMS_NEW + NUM_ITEMS_OLD, newFeed.getItems().size());
Collections.reverse(newFeed.getItems());
Date lastDate = new Date(0);
for (int i = 0; i < NUM_ITEMS_OLD; i++) {
FeedItem item = newFeed.getItems().get(i);
- assertTrue(item.getFeed() == newFeed);
- assertTrue(item.getId() == itemIDs.get(i));
+ assertSame(newFeed, item.getFeed());
+ assertEquals((long) itemIDs.get(i), item.getId());
assertTrue(item.isPlayed());
assertTrue(item.getPubDate().getTime() >= lastDate.getTime());
lastDate = item.getPubDate();
}
for (int i = NUM_ITEMS_OLD; i < NUM_ITEMS_NEW + NUM_ITEMS_OLD; i++) {
FeedItem item = newFeed.getItems().get(i);
- assertTrue(item.getFeed() == newFeed);
+ assertSame(newFeed, item.getFeed());
assertTrue(item.getId() != 0);
assertFalse(item.isPlayed());
assertTrue(item.getPubDate().getTime() >= lastDate.getTime());
diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java b/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java
index d82e366da..d300e23e7 100644
--- a/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java
@@ -3,11 +3,11 @@ package de.test.antennapod.storage;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
-import android.preference.PreferenceManager;
+import androidx.preference.PreferenceManager;
import android.util.Log;
import androidx.core.util.Consumer;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import org.awaitility.Awaitility;
@@ -35,9 +35,9 @@ import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.danoeh.antennapod.core.util.FeedItemUtil;
-import static androidx.test.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -56,7 +56,7 @@ public class DBWriterTest {
public void tearDown() throws Exception {
assertTrue(PodDBAdapter.deleteDatabase());
- final Context context = InstrumentationRegistry.getTargetContext();
+ final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
File testDir = context.getExternalFilesDir(TEST_FOLDER);
assertNotNull(testDir);
for (File f : testDir.listFiles()) {
@@ -67,13 +67,13 @@ public class DBWriterTest {
@Before
public void setUp() throws Exception {
// create new database
- PodDBAdapter.init(InstrumentationRegistry.getTargetContext());
+ PodDBAdapter.init(InstrumentationRegistry.getInstrumentation().getTargetContext());
PodDBAdapter.deleteDatabase();
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.close();
- Context context = InstrumentationRegistry.getTargetContext();
+ Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
SharedPreferences.Editor prefEdit = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()).edit();
prefEdit.putBoolean(UserPreferences.PREF_DELETE_REMOVES_FROM_QUEUE, true).commit();
@@ -116,7 +116,8 @@ public class DBWriterTest {
@Test
public void testDeleteFeedMediaOfItemFileExists()
throws IOException, ExecutionException, InterruptedException, TimeoutException {
- File dest = new File(getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER), "testFile");
+ File dest = new File(InstrumentationRegistry
+ .getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER), "testFile");
assertTrue(dest.createNewFile());
@@ -137,7 +138,7 @@ public class DBWriterTest {
assertTrue(media.getId() != 0);
assertTrue(item.getId() != 0);
- DBWriter.deleteFeedMediaOfItem(getInstrumentation().getTargetContext(), media.getId())
+ DBWriter.deleteFeedMediaOfItem(InstrumentationRegistry.getInstrumentation().getTargetContext(), media.getId())
.get(TIMEOUT, TimeUnit.SECONDS);
media = DBReader.getFeedMedia(media.getId());
assertNotNull(media);
@@ -151,7 +152,8 @@ public class DBWriterTest {
throws IOException, ExecutionException, InterruptedException, TimeoutException {
assertTrue(UserPreferences.shouldDeleteRemoveFromQueue());
- File dest = new File(getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER), "testFile");
+ File dest = new File(InstrumentationRegistry
+ .getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER), "testFile");
assertTrue(dest.createNewFile());
@@ -177,7 +179,7 @@ public class DBWriterTest {
queue = DBReader.getQueue();
assertTrue(queue.size() != 0);
- DBWriter.deleteFeedMediaOfItem(getInstrumentation().getTargetContext(), media.getId());
+ DBWriter.deleteFeedMediaOfItem(InstrumentationRegistry.getInstrumentation().getTargetContext(), media.getId());
Awaitility.await().until(() -> !dest.exists());
media = DBReader.getFeedMedia(media.getId());
assertNotNull(media);
@@ -185,12 +187,12 @@ public class DBWriterTest {
assertFalse(media.isDownloaded());
assertNull(media.getFile_url());
queue = DBReader.getQueue();
- assertTrue(queue.size() == 0);
+ assertEquals(0, queue.size());
}
@Test
public void testDeleteFeed() throws ExecutionException, InterruptedException, IOException, TimeoutException {
- File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
+ File destFolder = InstrumentationRegistry.getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
assertNotNull(destFolder);
Feed feed = new Feed("url", null, "title");
@@ -221,7 +223,8 @@ public class DBWriterTest {
assertTrue(item.getMedia().getId() != 0);
}
- DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS);
+ DBWriter.deleteFeed(InstrumentationRegistry
+ .getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS);
// check if files still exist
for (File f : itemFiles) {
@@ -231,14 +234,14 @@ public class DBWriterTest {
adapter = PodDBAdapter.getInstance();
adapter.open();
Cursor c = adapter.getFeedCursor(feed.getId());
- assertTrue(c.getCount() == 0);
+ assertEquals(0, c.getCount());
c.close();
for (FeedItem item : feed.getItems()) {
c = adapter.getFeedItemCursor(String.valueOf(item.getId()));
- assertTrue(c.getCount() == 0);
+ assertEquals(0, c.getCount());
c.close();
c = adapter.getSingleFeedMediaCursor(item.getMedia().getId());
- assertTrue(c.getCount() == 0);
+ assertEquals(0, c.getCount());
c.close();
}
adapter.close();
@@ -246,7 +249,7 @@ public class DBWriterTest {
@Test
public void testDeleteFeedNoItems() throws IOException, ExecutionException, InterruptedException, TimeoutException {
- File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
+ File destFolder = InstrumentationRegistry.getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
assertNotNull(destFolder);
Feed feed = new Feed("url", null, "title");
@@ -260,19 +263,20 @@ public class DBWriterTest {
assertTrue(feed.getId() != 0);
- DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS);
+ DBWriter.deleteFeed(InstrumentationRegistry
+ .getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS);
adapter = PodDBAdapter.getInstance();
adapter.open();
Cursor c = adapter.getFeedCursor(feed.getId());
- assertTrue(c.getCount() == 0);
+ assertEquals(0, c.getCount());
c.close();
adapter.close();
}
@Test
public void testDeleteFeedNoFeedMedia() throws IOException, ExecutionException, InterruptedException, TimeoutException {
- File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
+ File destFolder = InstrumentationRegistry.getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
assertNotNull(destFolder);
Feed feed = new Feed("url", null, "title");
@@ -297,17 +301,18 @@ public class DBWriterTest {
assertTrue(item.getId() != 0);
}
- DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS);
+ DBWriter.deleteFeed(InstrumentationRegistry
+ .getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS);
adapter = PodDBAdapter.getInstance();
adapter.open();
Cursor c = adapter.getFeedCursor(feed.getId());
- assertTrue(c.getCount() == 0);
+ assertEquals(0, c.getCount());
c.close();
for (FeedItem item : feed.getItems()) {
c = adapter.getFeedItemCursor(String.valueOf(item.getId()));
- assertTrue(c.getCount() == 0);
+ assertEquals(0, c.getCount());
c.close();
}
adapter.close();
@@ -315,7 +320,7 @@ public class DBWriterTest {
@Test
public void testDeleteFeedWithQueueItems() throws ExecutionException, InterruptedException, TimeoutException {
- File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
+ File destFolder = InstrumentationRegistry.getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
assertNotNull(destFolder);
Feed feed = new Feed("url", null, "title");
@@ -344,39 +349,39 @@ public class DBWriterTest {
}
- List<FeedItem> queue = new ArrayList<>();
- queue.addAll(feed.getItems());
+ List<FeedItem> queue = new ArrayList<>(feed.getItems());
adapter.open();
adapter.setQueue(queue);
Cursor queueCursor = adapter.getQueueIDCursor();
- assertTrue(queueCursor.getCount() == queue.size());
+ assertEquals(queue.size(), queueCursor.getCount());
queueCursor.close();
adapter.close();
- DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS);
+ DBWriter.deleteFeed(InstrumentationRegistry
+ .getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS);
adapter.open();
Cursor c = adapter.getFeedCursor(feed.getId());
- assertTrue(c.getCount() == 0);
+ assertEquals(0, c.getCount());
c.close();
for (FeedItem item : feed.getItems()) {
c = adapter.getFeedItemCursor(String.valueOf(item.getId()));
- assertTrue(c.getCount() == 0);
+ assertEquals(0, c.getCount());
c.close();
c = adapter.getSingleFeedMediaCursor(item.getMedia().getId());
- assertTrue(c.getCount() == 0);
+ assertEquals(0, c.getCount());
c.close();
}
c = adapter.getQueueCursor();
- assertTrue(c.getCount() == 0);
+ assertEquals(0, c.getCount());
c.close();
adapter.close();
}
@Test
public void testDeleteFeedNoDownloadedFiles() throws ExecutionException, InterruptedException, TimeoutException {
- File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
+ File destFolder = InstrumentationRegistry.getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
assertNotNull(destFolder);
Feed feed = new Feed("url", null, "title");
@@ -404,19 +409,20 @@ public class DBWriterTest {
assertTrue(item.getMedia().getId() != 0);
}
- DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS);
+ DBWriter.deleteFeed(InstrumentationRegistry
+ .getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS);
adapter = PodDBAdapter.getInstance();
adapter.open();
Cursor c = adapter.getFeedCursor(feed.getId());
- assertTrue(c.getCount() == 0);
+ assertEquals(0, c.getCount());
c.close();
for (FeedItem item : feed.getItems()) {
c = adapter.getFeedItemCursor(String.valueOf(item.getId()));
- assertTrue(c.getCount() == 0);
+ assertEquals(0, c.getCount());
c.close();
c = adapter.getSingleFeedMediaCursor(item.getMedia().getId());
- assertTrue(c.getCount() == 0);
+ assertEquals(0, c.getCount());
c.close();
}
adapter.close();
@@ -465,11 +471,11 @@ public class DBWriterTest {
assertNotNull(media);
assertNotNull(media.getPlaybackCompletionDate());
- assertFalse(OLD_DATE == media.getPlaybackCompletionDate().getTime());
+ assertNotEquals(media.getPlaybackCompletionDate().getTime(), OLD_DATE);
}
private Feed queueTestSetupMultipleItems(final int numItems) throws InterruptedException, ExecutionException, TimeoutException {
- final Context context = getInstrumentation().getTargetContext();
+ final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
UserPreferences.setEnqueueLocation(UserPreferences.EnqueueLocation.BACK);
Feed feed = new Feed("url", null, "title");
feed.setItems(new ArrayList<>());
@@ -498,7 +504,7 @@ public class DBWriterTest {
@Test
public void testAddQueueItemSingleItem() throws InterruptedException, ExecutionException, TimeoutException {
- final Context context = getInstrumentation().getTargetContext();
+ final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
Feed feed = new Feed("url", null, "title");
feed.setItems(new ArrayList<>());
FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), FeedItem.PLAYED, feed);
@@ -516,14 +522,14 @@ public class DBWriterTest {
adapter.open();
Cursor cursor = adapter.getQueueIDCursor();
assertTrue(cursor.moveToFirst());
- assertTrue(cursor.getLong(0) == item.getId());
+ assertEquals(item.getId(), cursor.getLong(0));
cursor.close();
adapter.close();
}
@Test
public void testAddQueueItemSingleItemAlreadyInQueue() throws InterruptedException, ExecutionException, TimeoutException {
- final Context context = getInstrumentation().getTargetContext();
+ final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
Feed feed = new Feed("url", null, "title");
feed.setItems(new ArrayList<>());
FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), FeedItem.PLAYED, feed);
@@ -541,7 +547,7 @@ public class DBWriterTest {
adapter.open();
Cursor cursor = adapter.getQueueIDCursor();
assertTrue(cursor.moveToFirst());
- assertTrue(cursor.getLong(0) == item.getId());
+ assertEquals(item.getId(), cursor.getLong(0));
cursor.close();
adapter.close();
@@ -550,8 +556,8 @@ public class DBWriterTest {
adapter.open();
cursor = adapter.getQueueIDCursor();
assertTrue(cursor.moveToFirst());
- assertTrue(cursor.getLong(0) == item.getId());
- assertTrue(cursor.getCount() == 1);
+ assertEquals(item.getId(), cursor.getLong(0));
+ assertEquals(1, cursor.getCount());
cursor.close();
adapter.close();
}
@@ -565,7 +571,7 @@ public class DBWriterTest {
adapter.open();
Cursor cursor = adapter.getQueueIDCursor();
assertTrue(cursor.moveToFirst());
- assertTrue(cursor.getCount() == NUM_ITEMS);
+ assertEquals(NUM_ITEMS, cursor.getCount());
List<Long> expectedIds = FeedItemUtil.getIdList(feed.getItems());
List<Long> actualIds = new ArrayList<>();
for (int i = 0; i < NUM_ITEMS; i++) {
@@ -595,7 +601,7 @@ public class DBWriterTest {
@Test
public void testRemoveQueueItem() throws InterruptedException, ExecutionException, TimeoutException {
final int NUM_ITEMS = 10;
- final Context context = getInstrumentation().getTargetContext();
+ final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
Feed feed = createTestFeed(NUM_ITEMS);
for (int removeIndex = 0; removeIndex < NUM_ITEMS; removeIndex++) {
@@ -609,7 +615,7 @@ public class DBWriterTest {
adapter = PodDBAdapter.getInstance();
adapter.open();
Cursor queue = adapter.getQueueIDCursor();
- assertTrue(queue.getCount() == NUM_ITEMS - 1);
+ assertEquals(NUM_ITEMS - 1, queue.getCount());
for (int i = 0; i < queue.getCount(); i++) {
assertTrue(queue.moveToPosition(i));
final long queueID = queue.getLong(0);
@@ -631,7 +637,7 @@ public class DBWriterTest {
//
final int NUM_ITEMS = 5;
final int NUM_IN_QUEUE = NUM_ITEMS - 1; // the last one not in queue for boundary condition
- final Context context = getInstrumentation().getTargetContext();
+ final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
Feed feed = createTestFeed(NUM_ITEMS);
List<FeedItem> itemsToAdd = feed.getItems().subList(0, NUM_IN_QUEUE);
@@ -698,11 +704,11 @@ public class DBWriterTest {
adapter = PodDBAdapter.getInstance();
adapter.open();
Cursor queue = adapter.getQueueIDCursor();
- assertTrue(queue.getCount() == NUM_ITEMS);
+ assertEquals(NUM_ITEMS, queue.getCount());
assertTrue(queue.moveToPosition(from));
- assertFalse(queue.getLong(0) == fromID);
+ assertNotEquals(fromID, queue.getLong(0));
assertTrue(queue.moveToPosition(to));
- assertTrue(queue.getLong(0) == fromID);
+ assertEquals(fromID, queue.getLong(0));
queue.close();
adapter.close();
diff --git a/app/src/androidTest/java/de/test/antennapod/ui/FeedSettingsTest.java b/app/src/androidTest/java/de/test/antennapod/ui/FeedSettingsTest.java
index b49be9a04..8bd4f1be6 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/FeedSettingsTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/FeedSettingsTest.java
@@ -3,7 +3,7 @@ package de.test.antennapod.ui;
import android.content.Intent;
import androidx.test.espresso.intent.rule.IntentsTestRule;
import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.feed.Feed;
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 47988d23f..c7520a2e6 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java
@@ -2,10 +2,10 @@ package de.test.antennapod.ui;
import android.app.Activity;
import android.content.Intent;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.espresso.Espresso;
import androidx.test.espresso.intent.rule.IntentsTestRule;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.robotium.solo.Solo;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
@@ -20,7 +20,6 @@ import org.junit.runner.RunWith;
import java.io.IOException;
-import static androidx.test.InstrumentationRegistry.getInstrumentation;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.replaceText;
@@ -55,10 +54,10 @@ public class MainActivityTest {
mActivityRule.launchActivity(new Intent());
- uiTestUtils = new UITestUtils(InstrumentationRegistry.getTargetContext());
+ uiTestUtils = new UITestUtils(InstrumentationRegistry.getInstrumentation().getTargetContext());
uiTestUtils.setup();
- solo = new Solo(getInstrumentation(), mActivityRule.getActivity());
+ solo = new Solo(InstrumentationRegistry.getInstrumentation(), mActivityRule.getActivity());
}
@After
diff --git a/app/src/androidTest/java/de/test/antennapod/ui/NavigationDrawerTest.java b/app/src/androidTest/java/de/test/antennapod/ui/NavigationDrawerTest.java
index bf4dae882..ade5ea298 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/NavigationDrawerTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/NavigationDrawerTest.java
@@ -1,10 +1,10 @@
package de.test.antennapod.ui;
import android.content.Intent;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.espresso.contrib.DrawerActions;
import androidx.test.espresso.intent.rule.IntentsTestRule;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.activity.PreferenceActivity;
@@ -59,7 +59,7 @@ public class NavigationDrawerTest {
@Before
public void setUp() throws IOException {
- uiTestUtils = new UITestUtils(InstrumentationRegistry.getTargetContext());
+ uiTestUtils = new UITestUtils(InstrumentationRegistry.getInstrumentation().getTargetContext());
uiTestUtils.setup();
EspressoTestUtils.clearPreferences();
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 6741cbc86..9bf89980c 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java
@@ -3,11 +3,10 @@ package de.test.antennapod.ui;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
-import android.preference.PreferenceManager;
+import androidx.preference.PreferenceManager;
import androidx.annotation.StringRes;
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
-import com.google.android.material.snackbar.Snackbar;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.PreferenceActivity;
import de.danoeh.antennapod.core.preferences.UserPreferences;
@@ -31,7 +30,6 @@ import java.util.concurrent.TimeUnit;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.replaceText;
-import static androidx.test.espresso.action.ViewActions.scrollTo;
import static androidx.test.espresso.action.ViewActions.swipeDown;
import static androidx.test.espresso.action.ViewActions.swipeUp;
import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
@@ -46,7 +44,6 @@ import static de.test.antennapod.EspressoTestUtils.clickPreference;
import static de.test.antennapod.EspressoTestUtils.waitForView;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static junit.framework.TestCase.assertTrue;
-import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.not;
@@ -235,12 +232,10 @@ public class PreferencesTest {
@Test
public void testPlaybackSpeeds() {
clickPreference(R.string.playback_pref);
- clickPreference(R.string.media_player);
- onView(withText(R.string.media_player_exoplayer)).perform(click());
- clickPreference(R.string.pref_playback_speed_title);
- onView(isRoot()).perform(waitForView(withText("0.50"), 1000));
- onView(withText("0.50")).check(matches(isDisplayed()));
- onView(withText(R.string.cancel_label)).perform(click());
+ clickPreference(R.string.playback_speed);
+ onView(isRoot()).perform(waitForView(withText("0.75"), 1000));
+ onView(withText("0.75")).check(matches(isDisplayed()));
+ onView(withText(R.string.close_label)).perform(click());
}
@Test
diff --git a/app/src/androidTest/java/de/test/antennapod/ui/QueueFragmentTest.java b/app/src/androidTest/java/de/test/antennapod/ui/QueueFragmentTest.java
index b5c7dd0d1..634904f71 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/QueueFragmentTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/QueueFragmentTest.java
@@ -4,7 +4,7 @@ import android.content.Intent;
import android.view.View;
import androidx.test.espresso.Espresso;
import androidx.test.espresso.intent.rule.IntentsTestRule;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.fragment.QueueFragment;
diff --git a/app/src/androidTest/java/de/test/antennapod/ui/SpeedChangeTest.java b/app/src/androidTest/java/de/test/antennapod/ui/SpeedChangeTest.java
index 6c26078c1..5f79e935c 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/SpeedChangeTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/SpeedChangeTest.java
@@ -3,9 +3,9 @@ package de.test.antennapod.ui;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
+import androidx.preference.PreferenceManager;
import androidx.test.rule.ActivityTestRule;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.feed.FeedItem;
@@ -25,6 +25,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -70,7 +71,7 @@ public class SpeedChangeTest {
List<FeedItem> queue = DBReader.getQueue();
PlaybackPreferences.writeMediaPlaying(queue.get(0).getMedia(), PlayerStatus.PAUSED, false);
availableSpeeds = new String[] {"1.00", "2.00", "3.00"};
- UserPreferences.setPlaybackSpeedArray(availableSpeeds);
+ UserPreferences.setPlaybackSpeedArray(Arrays.asList(1.0f, 2.0f, 3.0f));
EspressoTestUtils.tryKillPlaybackService();
activityRule.launchActivity(new Intent().putExtra(MainActivity.EXTRA_OPEN_PLAYER, true));
diff --git a/app/src/androidTest/java/de/test/antennapod/ui/TextOnlyFeedsTest.java b/app/src/androidTest/java/de/test/antennapod/ui/TextOnlyFeedsTest.java
index 782bb09d8..488c87052 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/TextOnlyFeedsTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/TextOnlyFeedsTest.java
@@ -3,7 +3,7 @@ package de.test.antennapod.ui;
import android.content.Intent;
import androidx.test.espresso.intent.rule.IntentsTestRule;
import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.feed.Feed;
diff --git a/app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java b/app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java
index a183b648e..60516454f 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java
@@ -5,7 +5,7 @@ import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.filters.MediumTest;
import de.danoeh.antennapod.core.feed.Feed;
@@ -29,7 +29,7 @@ public class UITestUtilsTest {
@Before
public void setUp() throws Exception {
- uiTestUtils = new UITestUtils(InstrumentationRegistry.getTargetContext());
+ uiTestUtils = new UITestUtils(InstrumentationRegistry.getInstrumentation().getTargetContext());
uiTestUtils.setup();
}
diff --git a/app/src/androidTest/java/de/test/antennapod/util/FilenameGeneratorTest.java b/app/src/androidTest/java/de/test/antennapod/util/FilenameGeneratorTest.java
index 6f8042d61..93e5bcb74 100644
--- a/app/src/androidTest/java/de/test/antennapod/util/FilenameGeneratorTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/util/FilenameGeneratorTest.java
@@ -21,32 +21,28 @@ import static org.junit.Assert.assertTrue;
@SmallTest
public class FilenameGeneratorTest {
- private static final String VALID1 = "abc abc";
- private static final String INVALID1 = "ab/c: <abc";
- private static final String INVALID2 = "abc abc ";
-
public FilenameGeneratorTest() {
super();
}
@Test
public void testGenerateFileName() throws IOException {
- String result = FileNameGenerator.generateFileName(VALID1);
- assertEquals(result, VALID1);
+ String result = FileNameGenerator.generateFileName("abc abc");
+ assertEquals(result, "abc abc");
createFiles(result);
}
@Test
public void testGenerateFileName1() throws IOException {
- String result = FileNameGenerator.generateFileName(INVALID1);
- assertEquals(result, VALID1);
+ String result = FileNameGenerator.generateFileName("ab/c: <abc");
+ assertEquals(result, "abc abc");
createFiles(result);
}
@Test
public void testGenerateFileName2() throws IOException {
- String result = FileNameGenerator.generateFileName(INVALID2);
- assertEquals(result, VALID1);
+ String result = FileNameGenerator.generateFileName("abc abc ");
+ assertEquals(result, "abc abc");
createFiles(result);
}
@@ -63,6 +59,12 @@ public class FilenameGeneratorTest {
}
@Test
+ public void testFeedTitleContainsAccents() {
+ String result = FileNameGenerator.generateFileName("Äàáâãå");
+ assertEquals("Aaaaaa", result);
+ }
+
+ @Test
public void testInvalidInput() {
String result = FileNameGenerator.generateFileName("???");
assertFalse(TextUtils.isEmpty(result));
@@ -97,14 +99,6 @@ public class FilenameGeneratorTest {
assertTrue(testFile.exists());
testFile.delete();
assertTrue(testFile.createNewFile());
-
- }
-
- @After
- public void tearDown() {
- Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
- File f = new File(context.getExternalCacheDir(), VALID1);
- f.delete();
}
}
diff --git a/app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java b/app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java
index 59b9ceaca..ed37b7daa 100644
--- a/app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java
@@ -2,7 +2,7 @@ package de.test.antennapod.util.playback;
import android.content.Context;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
@@ -35,7 +35,7 @@ public class TimelineTest {
@Before
public void setUp() {
- context = InstrumentationRegistry.getTargetContext();
+ context = InstrumentationRegistry.getInstrumentation().getTargetContext();
}
private Playable newTestPlayable(List<Chapter> chapters, String shownotes, int duration) {
diff --git a/app/src/androidTest/java/de/test/antennapod/util/syndication/FeedDiscovererTest.java b/app/src/androidTest/java/de/test/antennapod/util/syndication/FeedDiscovererTest.java
index 2dda77524..b213a5efa 100644
--- a/app/src/androidTest/java/de/test/antennapod/util/syndication/FeedDiscovererTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/util/syndication/FeedDiscovererTest.java
@@ -1,11 +1,12 @@
package de.test.antennapod.util.syndication;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.platform.app.InstrumentationRegistry;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import java.io.File;
import java.io.FileOutputStream;
+import java.nio.charset.Charset;
import java.util.Map;
import de.danoeh.antennapod.core.util.syndication.FeedDiscoverer;
@@ -29,7 +30,8 @@ public class FeedDiscovererTest {
@Before
public void setUp() throws Exception {
fd = new FeedDiscoverer();
- testDir = new File(InstrumentationRegistry.getTargetContext().getFilesDir(), "FeedDiscovererTest");
+ testDir = new File(InstrumentationRegistry
+ .getInstrumentation().getTargetContext().getFilesDir(), "FeedDiscovererTest");
testDir.mkdir();
assertTrue(testDir.exists());
}
@@ -67,7 +69,7 @@ public class FeedDiscovererTest {
} else {
File testFile = new File(testDir, "feed");
FileOutputStream out = new FileOutputStream(testFile);
- IOUtils.write(html, out);
+ IOUtils.write(html, out, Charset.forName("UTF-8"));
out.close();
res = fd.findLinks(testFile, base);
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 926329247..afb53f0bd 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -36,7 +36,8 @@
android:theme="@style/Theme.AntennaPod.Splash"
android:usesCleartextTraffic="true"
android:supportsRtl="true"
- android:logo="@mipmap/ic_launcher">
+ android:logo="@mipmap/ic_launcher"
+ android:resizeableActivity="true">
<meta-data android:name="android.webkit.WebView.MetricsOptOut"
@@ -50,6 +51,11 @@
android:name="com.google.android.backup.api_key"
android:value="AEdPqrEAAAAI3a05VToCTlqBymJrbFGaKQMvF-bBAuLsOdavBA"/>
+ <!-- Version < 3.0. DeX Mode and Screen Mirroring support -->
+ <meta-data android:name="com.samsung.android.keepalive.density" android:value="true"/>
+ <!-- Version >= 3.0. DeX Dual Mode support -->
+ <meta-data android:name="com.samsung.android.multidisplay.keep_process_alive" android:value="true"/>
+
<activity
android:name=".activity.SplashActivity"
android:label="@string/app_name"
@@ -73,7 +79,7 @@
<activity
android:name=".activity.MainActivity"
- android:configChanges="keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout"
+ android:configChanges="keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|density|uiMode|keyboard|navigation"
android:windowSoftInputMode="stateAlwaysHidden"
android:launchMode="singleTask"
android:label="@string/app_name">
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/BugReportActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/BugReportActivity.java
index 48264bb26..b1a0ba2a2 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/BugReportActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/BugReportActivity.java
@@ -42,9 +42,8 @@ public class BugReportActivity extends AppCompatActivity {
}
crashDetailsTextView.setText(crashDetailsText);
- findViewById(R.id.btn_open_bug_tracker).setOnClickListener(v -> {
- IntentUtils.openInBrowser(BugReportActivity.this, "https://github.com/AntennaPod/AntennaPod/issues");
- });
+ findViewById(R.id.btn_open_bug_tracker).setOnClickListener(v -> IntentUtils.openInBrowser(
+ BugReportActivity.this, "https://github.com/AntennaPod/AntennaPod/issues"));
findViewById(R.id.btn_copy_log).setOnClickListener(v -> {
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java
index 810005d2d..1d3d9bf11 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java
@@ -3,6 +3,8 @@ package de.danoeh.antennapod.activity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
+
+import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import android.widget.Button;
@@ -86,7 +88,7 @@ public class DownloadAuthenticationActivity extends AppCompatActivity {
}
@Override
- protected void onSaveInstanceState(Bundle outState) {
+ protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("username", etxtUsername.getText().toString());
outState.putString("password", etxtPassword.getText().toString());
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 eaa423708..f772cb084 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
@@ -5,10 +5,13 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
+import android.util.DisplayMetrics;
import android.util.Log;
+import android.util.TypedValue;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
@@ -31,6 +34,7 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.event.MessageEvent;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.util.StorageUtils;
+import de.danoeh.antennapod.core.util.ThemeUtils;
import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
import de.danoeh.antennapod.dialog.RatingDialog;
import de.danoeh.antennapod.fragment.AddFeedFragment;
@@ -68,9 +72,9 @@ public class MainActivity extends CastEnabledActivity {
public static final String EXTRA_OPEN_PLAYER = "open_player";
public static final String EXTRA_REFRESH_ON_START = "refresh_on_start";
- private DrawerLayout drawerLayout;
+ private @Nullable DrawerLayout drawerLayout;
+ private @Nullable ActionBarDrawerToggle drawerToggle;
private View navDrawer;
- private ActionBarDrawerToggle drawerToggle;
private LockableBottomSheetBehavior sheetBehavior;
private long lastBackButtonPressTime = 0;
private RecyclerView.RecycledViewPool recycledViewPool = new RecyclerView.RecycledViewPool();
@@ -95,10 +99,17 @@ public class MainActivity extends CastEnabledActivity {
drawerLayout = findViewById(R.id.drawer_layout);
navDrawer = findViewById(R.id.navDrawerFragment);
+ setNavDrawerSize();
final FragmentManager fm = getSupportFragmentManager();
- fm.addOnBackStackChangedListener(() ->
- drawerToggle.setDrawerIndicatorEnabled(fm.getBackStackEntryCount() == 0));
+ fm.addOnBackStackChangedListener(() -> {
+ boolean showArrow = fm.getBackStackEntryCount() != 0;
+ if (drawerToggle != null) { // Tablet layout does not have a drawer
+ drawerToggle.setDrawerIndicatorEnabled(!showArrow);
+ } else if (getActionBar() != null) {
+ getActionBar().setDisplayHomeAsUpEnabled(showArrow);
+ }
+ });
if (fm.findFragmentByTag(MAIN_FRAGMENT_TAG) == null) {
String lastFragment = NavDrawerFragment.getLastNavFragment(this);
@@ -151,12 +162,18 @@ public class MainActivity extends CastEnabledActivity {
@Override
public void setSupportActionBar(@Nullable Toolbar toolbar) {
- drawerLayout.removeDrawerListener(drawerToggle);
- drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar,
- R.string.drawer_open, R.string.drawer_close);
- drawerLayout.addDrawerListener(drawerToggle);
- drawerToggle.syncState();
- drawerToggle.setDrawerIndicatorEnabled(getSupportFragmentManager().getBackStackEntryCount() == 0);
+ if (drawerLayout != null) { // Tablet layout does not have a drawer
+ drawerLayout.removeDrawerListener(drawerToggle);
+ drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar,
+ R.string.drawer_open, R.string.drawer_close);
+ drawerLayout.addDrawerListener(drawerToggle);
+ drawerToggle.syncState();
+ drawerToggle.setDrawerIndicatorEnabled(getSupportFragmentManager().getBackStackEntryCount() == 0);
+ } else if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
+ toolbar.setNavigationIcon(null);
+ } else {
+ toolbar.setNavigationIcon(ThemeUtils.getDrawableFromAttr(this, R.attr.homeAsUpIndicator));
+ }
super.setSupportActionBar(toolbar);
}
@@ -164,7 +181,11 @@ public class MainActivity extends CastEnabledActivity {
SharedPreferences prefs = getSharedPreferences(PREF_NAME, MODE_PRIVATE);
if (prefs.getBoolean(PREF_IS_FIRST_LAUNCH, true)) {
loadFragment(AddFeedFragment.TAG, null);
- new Handler().postDelayed(() -> drawerLayout.openDrawer(navDrawer), 1500);
+ new Handler().postDelayed(() -> {
+ if (drawerLayout != null) { // Tablet layout does not have a drawer
+ drawerLayout.openDrawer(navDrawer);
+ }
+ }, 1500);
// for backward compatibility, we only change defaults for fresh installs
UserPreferences.setUpdateInterval(12);
@@ -258,7 +279,10 @@ public class MainActivity extends CastEnabledActivity {
// not commit anything in an AsyncTask, but that's a bigger
// change than we want now.
t.commitAllowingStateLoss();
- drawerLayout.closeDrawer(navDrawer);
+
+ if (drawerLayout != null) { // Tablet layout does not have a drawer
+ drawerLayout.closeDrawer(navDrawer);
+ }
}
public void loadChildFragment(Fragment fragment, TransitionEffect transition) {
@@ -292,13 +316,35 @@ public class MainActivity extends CastEnabledActivity {
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
- drawerToggle.syncState();
+ if (drawerToggle != null) { // Tablet layout does not have a drawer
+ drawerToggle.syncState();
+ }
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- drawerToggle.onConfigurationChanged(newConfig);
+ if (drawerToggle != null) { // Tablet layout does not have a drawer
+ drawerToggle.onConfigurationChanged(newConfig);
+ }
+ setNavDrawerSize();
+ }
+
+ private void setNavDrawerSize() {
+ if (drawerToggle == null) { // Tablet layout does not have a drawer
+ return;
+ }
+ float screenPercent = getResources().getInteger(R.integer.nav_drawer_screen_size_percent) * 0.01f;
+ int width = (int) (getScreenWidth() * screenPercent);
+ int maxWidth = (int) getResources().getDimension(R.dimen.nav_drawer_max_screen_size);
+
+ navDrawer.getLayoutParams().width = Math.min(width, maxWidth);
+ }
+
+ private int getScreenWidth() {
+ DisplayMetrics displayMetrics = new DisplayMetrics();
+ getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
+ return displayMetrics.widthPixels;
}
@Override
@@ -351,7 +397,7 @@ public class MainActivity extends CastEnabledActivity {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- if (drawerToggle.onOptionsItemSelected(item)) {
+ if (drawerToggle != null && drawerToggle.onOptionsItemSelected(item)) { // Tablet layout does not have a drawer
return true;
} else if (item.getItemId() == android.R.id.home) {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
@@ -374,7 +420,9 @@ public class MainActivity extends CastEnabledActivity {
} else {
switch (UserPreferences.getBackButtonBehavior()) {
case OPEN_DRAWER:
- drawerLayout.openDrawer(navDrawer);
+ if (drawerLayout != null) { // Tablet layout does not have drawer
+ drawerLayout.openDrawer(navDrawer);
+ }
break;
case SHOW_PROMPT:
new AlertDialog.Builder(this)
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java
index 34c7e3aba..b03d1e5cd 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java
@@ -18,16 +18,23 @@ import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.Toast;
+
+import com.bumptech.glide.Glide;
+
+import org.apache.commons.lang3.StringUtils;
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
+import java.text.NumberFormat;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
-import androidx.arch.core.util.Function;
+import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.app.ActivityOptionsCompat;
import androidx.core.content.ContextCompat;
-import androidx.core.util.Consumer;
-import androidx.core.util.Supplier;
-import com.bumptech.glide.Glide;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import de.danoeh.antennapod.core.feed.FeedItem;
@@ -39,7 +46,6 @@ import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.FeedItemUtil;
-import de.danoeh.antennapod.core.util.Flavors;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.ShareUtils;
import de.danoeh.antennapod.core.util.StorageUtils;
@@ -51,18 +57,13 @@ import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
import de.danoeh.antennapod.dialog.PlaybackControlsDialog;
+import de.danoeh.antennapod.dialog.ShareDialog;
import de.danoeh.antennapod.dialog.SkipPreferenceDialog;
import de.danoeh.antennapod.dialog.SleepTimerDialog;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
-import org.apache.commons.lang3.StringUtils;
-import org.greenrobot.eventbus.EventBus;
-import org.greenrobot.eventbus.Subscribe;
-import org.greenrobot.eventbus.ThreadMode;
-
-import java.text.NumberFormat;
/**
@@ -304,7 +305,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
return false;
}
Playable media = controller.getMedia();
- boolean isFeedMedia = media != null && (media instanceof FeedMedia);
+ boolean isFeedMedia = (media instanceof FeedMedia);
menu.findItem(R.id.open_feed_item).setVisible(isFeedMedia); // FeedMedia implies it belongs to a Feed
@@ -313,13 +314,8 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
boolean isItemAndHasLink = isFeedMedia &&
ShareUtils.hasLinkToShare(((FeedMedia) media).getItem());
- menu.findItem(R.id.share_link_item).setVisible(isItemAndHasLink);
- menu.findItem(R.id.share_link_with_position_item).setVisible(isItemAndHasLink);
boolean isItemHasDownloadLink = isFeedMedia && ((FeedMedia) media).getDownload_url() != null;
- menu.findItem(R.id.share_download_url_item).setVisible(isItemHasDownloadLink);
- menu.findItem(R.id.share_download_url_with_position_item).setVisible(isItemHasDownloadLink);
- menu.findItem(R.id.share_file).setVisible(isFeedMedia && ((FeedMedia) media).fileExists());
menu.findItem(R.id.share_item).setVisible(hasWebsiteLink || isItemAndHasLink || isItemHasDownloadLink);
@@ -380,8 +376,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
new SleepTimerDialog().show(getSupportFragmentManager(), "SleepTimerDialog");
break;
case R.id.audio_controls:
- boolean isPlayingVideo = controller.getMedia().getMediaType() == MediaType.VIDEO;
- PlaybackControlsDialog dialog = PlaybackControlsDialog.newInstance(isPlayingVideo);
+ PlaybackControlsDialog dialog = PlaybackControlsDialog.newInstance();
dialog.show(getSupportFragmentManager(), "playback_controls");
break;
case R.id.open_feed_item:
@@ -393,29 +388,10 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
case R.id.visit_website_item:
IntentUtils.openInBrowser(MediaplayerActivity.this, getWebsiteLinkWithFallback(media));
break;
- case R.id.share_link_item:
- if (feedItem != null) {
- ShareUtils.shareFeedItemLink(this, feedItem);
- }
- break;
- case R.id.share_download_url_item:
- if (feedItem != null) {
- ShareUtils.shareFeedItemDownloadLink(this, feedItem);
- }
- break;
- case R.id.share_link_with_position_item:
+ case R.id.share_item:
if (feedItem != null) {
- ShareUtils.shareFeedItemLink(this, feedItem, true);
- }
- break;
- case R.id.share_download_url_with_position_item:
- if (feedItem != null) {
- ShareUtils.shareFeedItemDownloadLink(this, feedItem, true);
- }
- break;
- case R.id.share_file:
- if (media instanceof FeedMedia) {
- ShareUtils.shareFeedItemFile(this, ((FeedMedia) media));
+ ShareDialog shareDialog = ShareDialog.newInstance(feedItem);
+ shareDialog.show(getSupportFragmentManager(), "ShareEpisodeDialog");
}
break;
default:
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
index beb6e0a9f..f6623d5dc 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
@@ -227,15 +227,14 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- Intent destIntent = new Intent(this, MainActivity.class);
- if (NavUtils.shouldUpRecreateTask(this, destIntent)) {
- startActivity(destIntent);
- } else {
- NavUtils.navigateUpFromSameTask(this);
- }
- return true;
+ if (item.getItemId() == android.R.id.home) {
+ Intent destIntent = new Intent(this, MainActivity.class);
+ if (NavUtils.shouldUpRecreateTask(this, destIntent)) {
+ startActivity(destIntent);
+ } else {
+ NavUtils.navigateUpFromSameTask(this);
+ }
+ return true;
}
return super.onOptionsItemSelected(item);
}
@@ -606,9 +605,8 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
}
final List<String> titles = new ArrayList<>();
- final List<String> urls = new ArrayList<>();
- urls.addAll(urlsMap.keySet());
+ final List<String> urls = new ArrayList<>(urlsMap.keySet());
for (String url : urls) {
titles.add(urlsMap.get(url));
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java
index 337880317..cfd6ec702 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java
@@ -88,10 +88,9 @@ public class GpodnetAuthenticationActivity extends AppCompatActivity {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- finish();
- return true;
+ if (item.getItemId() == android.R.id.home) {
+ finish();
+ return true;
}
return super.onOptionsItemSelected(item);
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java
index 690bb9e3d..6bfd34d5c 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java
@@ -7,6 +7,10 @@ import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.MediaType;
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
@@ -32,8 +36,9 @@ public class FeedItemlistDescriptionAdapter extends ArrayAdapter<FeedItem> {
super(context, resource, objects);
}
+ @NonNull
@Override
- public View getView(int position, View convertView, ViewGroup parent) {
+ public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Holder holder;
FeedItem item = getItem(position);
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 e66032e11..a53adc719 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java
@@ -5,7 +5,7 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
-import android.preference.PreferenceManager;
+import androidx.preference.PreferenceManager;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
@@ -61,7 +61,7 @@ public class NavListAdapter extends BaseAdapter
private final ItemAccess itemAccess;
private final WeakReference<Activity> activity;
- private boolean showSubscriptionList = true;
+ public boolean showSubscriptionList = true;
public NavListAdapter(ItemAccess itemAccess, Activity context) {
this.itemAccess = itemAccess;
@@ -194,7 +194,7 @@ public class NavListAdapter extends BaseAdapter
@Override
public View getView(int position, View convertView, ViewGroup parent) {
int viewType = getItemViewType(position);
- View v = null;
+ View v;
if (viewType == VIEW_TYPE_NAV) {
v = getNavView((String) getItem(position), position, convertView, parent);
} else if (viewType == VIEW_TYPE_SECTION_DIVIDER) {
@@ -296,9 +296,17 @@ public class NavListAdapter extends BaseAdapter
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.nav_section_item, parent, false);
+ TextView feedsFilteredMsg = convertView.findViewById(R.id.nav_feeds_filtered_message);
- convertView.setEnabled(false);
- convertView.setOnClickListener(null);
+ if (UserPreferences.getFeedFilter() != UserPreferences.FEED_FILTER_NONE && showSubscriptionList) {
+ convertView.setEnabled(true);
+ feedsFilteredMsg.setText("{md-info-outline} " + context.getString(R.string.subscriptions_are_filtered));
+ Iconify.addIcons(feedsFilteredMsg);
+ feedsFilteredMsg.setVisibility(View.VISIBLE);
+ } else {
+ convertView.setEnabled(false);
+ feedsFilteredMsg.setVisibility(View.GONE);
+ }
return convertView;
}
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 428a968c6..7ce086694 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
@@ -20,16 +20,17 @@ public class QueueRecyclerAdapter extends EpisodeItemListAdapter {
private static final String TAG = "QueueRecyclerAdapter";
private final ItemTouchHelper itemTouchHelper;
- private boolean locked;
+ private boolean dragDropEnabled;
+
public QueueRecyclerAdapter(MainActivity mainActivity, ItemTouchHelper itemTouchHelper) {
super(mainActivity);
this.itemTouchHelper = itemTouchHelper;
- locked = UserPreferences.isQueueLocked();
+ dragDropEnabled = ! (UserPreferences.isQueueKeepSorted() || UserPreferences.isQueueLocked());
}
- public void setLocked(boolean locked) {
- this.locked = locked;
+ public void updateDragDropEnabled() {
+ dragDropEnabled = ! (UserPreferences.isQueueKeepSorted() || UserPreferences.isQueueLocked());
notifyDataSetChanged();
}
@@ -37,14 +38,14 @@ public class QueueRecyclerAdapter extends EpisodeItemListAdapter {
@SuppressLint("ClickableViewAccessibility")
protected void afterBindViewHolder(EpisodeItemViewHolder holder, int pos) {
View.OnTouchListener startDragTouchListener = (v1, event) -> {
- if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
+ if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
Log.d(TAG, "startDrag()");
itemTouchHelper.startDrag(holder);
}
return false;
};
- if (locked) {
+ if (!dragDropEnabled) {
holder.dragHandle.setVisibility(View.GONE);
holder.dragHandle.setOnTouchListener(null);
holder.coverHolder.setOnTouchListener(null);
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 ac1e94437..c3177668a 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
@@ -220,7 +220,7 @@ public class EpisodesApplyActionFragment extends Fragment {
}
@Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.episodes_apply_action_options, menu);
@@ -236,7 +236,7 @@ public class EpisodesApplyActionFragment extends Fragment {
}
@Override
- public void onPrepareOptionsMenu(Menu menu) {
+ public void onPrepareOptionsMenu(@NonNull Menu menu) {
// Prepare icon for select toggle button
int[] icon = new int[1];
@@ -413,7 +413,7 @@ public class EpisodesApplyActionFragment extends Fragment {
boolean checked = checkedIds.contains(episode.getId());
mListView.setItemChecked(i, checked);
}
- ActivityCompat.invalidateOptionsMenu(EpisodesApplyActionFragment.this.getActivity());
+ getActivity().invalidateOptionsMenu();
toolbar.setTitle(getResources().getQuantityString(R.plurals.num_selected_label,
checkedIds.size(), checkedIds.size()));
}
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/FeedFilterDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/FeedFilterDialog.java
new file mode 100644
index 000000000..3b0e2d04b
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/FeedFilterDialog.java
@@ -0,0 +1,38 @@
+package de.danoeh.antennapod.dialog;
+
+import android.content.Context;
+
+import androidx.appcompat.app.AlertDialog;
+
+import org.greenrobot.eventbus.EventBus;
+
+import java.util.Arrays;
+import java.util.List;
+
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+
+public class FeedFilterDialog {
+ public static void showDialog(Context context) {
+ AlertDialog.Builder dialog = new AlertDialog.Builder(context);
+ dialog.setTitle(context.getString(R.string.pref_filter_feed_title));
+ dialog.setNegativeButton(android.R.string.cancel, (d, listener) -> d.dismiss());
+
+ int selected = UserPreferences.getFeedFilter();
+ List<String> entryValues =
+ Arrays.asList(context.getResources().getStringArray(R.array.nav_drawer_feed_filter_values));
+ final int selectedIndex = entryValues.indexOf("" + selected);
+
+ String[] items = context.getResources().getStringArray(R.array.nav_drawer_feed_filter_options);
+ dialog.setSingleChoiceItems(items, selectedIndex, (d, which) -> {
+ if (selectedIndex != which) {
+ UserPreferences.setFeedFilter(entryValues.get(which));
+ //Update subscriptions
+ EventBus.getDefault().post(new UnreadItemsUpdateEvent());
+ }
+ d.dismiss();
+ });
+ dialog.show();
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/FeedSortDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/FeedSortDialog.java
new file mode 100644
index 000000000..96d1b9b67
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/FeedSortDialog.java
@@ -0,0 +1,38 @@
+package de.danoeh.antennapod.dialog;
+
+import android.content.Context;
+
+import androidx.appcompat.app.AlertDialog;
+
+import org.greenrobot.eventbus.EventBus;
+
+import java.util.Arrays;
+import java.util.List;
+
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+
+public class FeedSortDialog {
+ public static void showDialog(Context context) {
+ AlertDialog.Builder dialog = new AlertDialog.Builder(context);
+ dialog.setTitle(context.getString(R.string.pref_nav_drawer_feed_order_title));
+ dialog.setNegativeButton(android.R.string.cancel, (d, listener) -> d.dismiss());
+
+ int selected = UserPreferences.getFeedOrder();
+ List<String> entryValues =
+ Arrays.asList(context.getResources().getStringArray(R.array.nav_drawer_feed_order_values));
+ final int selectedIndex = entryValues.indexOf("" + selected);
+
+ String[] items = context.getResources().getStringArray(R.array.nav_drawer_feed_order_options);
+ dialog.setSingleChoiceItems(items, selectedIndex, (d, which) -> {
+ if (selectedIndex != which) {
+ UserPreferences.setFeedOrder(entryValues.get(which));
+ //Update subscriptions
+ EventBus.getDefault().post(new UnreadItemsUpdateEvent());
+ }
+ d.dismiss();
+ });
+ dialog.show();
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/FilterDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/FilterDialog.java
index d2912f90f..82010637f 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/FilterDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/FilterDialog.java
@@ -1,8 +1,12 @@
package de.danoeh.antennapod.dialog;
import android.content.Context;
-import androidx.appcompat.app.AlertDialog;
import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.widget.LinearLayout;
+import android.widget.RadioButton;
+
+import androidx.appcompat.app.AlertDialog;
import java.util.Arrays;
import java.util.HashSet;
@@ -10,6 +14,8 @@ import java.util.Set;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.FeedItemFilter;
+import de.danoeh.antennapod.core.feed.FeedItemFilterGroup;
+import de.danoeh.antennapod.view.RecursiveRadioGroup;
public abstract class FilterDialog {
@@ -22,36 +28,46 @@ public abstract class FilterDialog {
}
public void openDialog() {
- final String[] items = context.getResources().getStringArray(R.array.episode_filter_options);
- final String[] values = context.getResources().getStringArray(R.array.episode_filter_values);
- final boolean[] checkedItems = new boolean[items.length];
final Set<String> filterValues = new HashSet<>(Arrays.asList(filter.getValues()));
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setTitle(R.string.filter);
- // make sure we have no empty strings in the filter list
- for (String filterValue : filterValues) {
- if (TextUtils.isEmpty(filterValue)) {
- filterValues.remove(filterValue);
- }
+ LayoutInflater inflater = LayoutInflater.from(this.context);
+ LinearLayout layout = (LinearLayout) inflater.inflate(R.layout.filter_dialog, null, false);
+ builder.setView(layout);
+
+ for (FeedItemFilterGroup item : FeedItemFilterGroup.values()) {
+ RecursiveRadioGroup row = (RecursiveRadioGroup) inflater.inflate(R.layout.filter_dialog_row, null);
+ RadioButton filter1 = row.findViewById(R.id.filter_dialog_radioButton1);
+ RadioButton filter2 = row.findViewById(R.id.filter_dialog_radioButton2);
+ filter1.setText(item.values[0].displayName);
+ filter1.setTag(item.values[0].filterId);
+ filter2.setText(item.values[1].displayName);
+ filter2.setTag(item.values[1].filterId);
+ layout.addView(row);
}
- for (int i = 0; i < values.length; i++) {
- String value = values[i];
- if (filterValues.contains(value)) {
- checkedItems[i] = true;
+ for (String filterId : filterValues) {
+ if (!TextUtils.isEmpty(filterId)) {
+ ((RadioButton) layout.findViewWithTag(filterId)).setChecked(true);
}
}
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(R.string.filter);
- builder.setMultiChoiceItems(items, checkedItems, (dialog, which, isChecked) -> {
- if (isChecked) {
- filterValues.add(values[which]);
- } else {
- filterValues.remove(values[which]);
- }
- });
builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
+ filterValues.clear();
+ for (int i = 0; i < layout.getChildCount(); i++) {
+ if (!(layout.getChildAt(i) instanceof RecursiveRadioGroup)) {
+ continue;
+ }
+ RecursiveRadioGroup group = (RecursiveRadioGroup) layout.getChildAt(i);
+ if (group.getCheckedButton() != null) {
+ String tag = (String) group.getCheckedButton().getTag();
+ if (tag != null) { // Clear buttons use no tag
+ filterValues.add((String) group.getCheckedButton().getTag());
+ }
+ }
+ }
updateFilter(filterValues);
});
builder.setNegativeButton(R.string.cancel_label, null);
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java
index d1ffdc148..e45533826 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java
@@ -11,27 +11,21 @@ import android.widget.Button;
import android.widget.CheckBox;
import android.widget.SeekBar;
import android.widget.TextView;
-import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.core.feed.util.PlaybackSpeedUtils;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.util.Converter;
-import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
+import de.danoeh.antennapod.view.PlaybackSpeedSeekBar;
import java.util.List;
import java.util.Locale;
public class PlaybackControlsDialog extends DialogFragment {
- private static final String ARGUMENT_IS_PLAYING_VIDEO = "isPlayingVideo";
-
private PlaybackController controller;
private AlertDialog dialog;
- private boolean isPlayingVideo;
- public static PlaybackControlsDialog newInstance(boolean isPlayingVideo) {
+ public static PlaybackControlsDialog newInstance() {
Bundle arguments = new Bundle();
- arguments.putBoolean(ARGUMENT_IS_PLAYING_VIDEO, isPlayingVideo);
PlaybackControlsDialog dialog = new PlaybackControlsDialog();
dialog.setArguments(arguments);
return dialog;
@@ -65,8 +59,6 @@ public class PlaybackControlsDialog extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
- isPlayingVideo = getArguments() != null && getArguments().getBoolean(ARGUMENT_IS_PLAYING_VIDEO);
-
dialog = new AlertDialog.Builder(getContext())
.setTitle(R.string.audio_controls)
.setView(R.layout.audio_controls)
@@ -79,68 +71,18 @@ public class PlaybackControlsDialog extends DialogFragment {
}
private void setupUi() {
- final SeekBar barPlaybackSpeed = dialog.findViewById(R.id.playback_speed);
- final TextView butDecSpeed = dialog.findViewById(R.id.butDecSpeed);
- butDecSpeed.setOnClickListener(v -> {
- if (controller != null && controller.canSetPlaybackSpeed()) {
- barPlaybackSpeed.setProgress(barPlaybackSpeed.getProgress() - 2);
- } else {
- VariableSpeedDialog.showGetPluginDialog(getContext());
- }
- });
- final TextView butIncSpeed = dialog.findViewById(R.id.butIncSpeed);
- butIncSpeed.setOnClickListener(v -> {
- if (controller != null && controller.canSetPlaybackSpeed()) {
- barPlaybackSpeed.setProgress(barPlaybackSpeed.getProgress() + 2);
- } else {
- VariableSpeedDialog.showGetPluginDialog(getContext());
- }
- });
-
final TextView txtvPlaybackSpeed = dialog.findViewById(R.id.txtvPlaybackSpeed);
- float currentSpeed = getCurrentSpeed();
- txtvPlaybackSpeed.setText(String.format(Locale.getDefault(), "%.2fx", currentSpeed));
- barPlaybackSpeed.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- if (controller != null && controller.canSetPlaybackSpeed()) {
- float playbackSpeed = (progress + 10) / 20.0f;
- controller.setPlaybackSpeed(playbackSpeed);
-
- PlaybackPreferences.setCurrentlyPlayingTemporaryPlaybackSpeed(playbackSpeed);
- if (isPlayingVideo) {
- UserPreferences.setVideoPlaybackSpeed(playbackSpeed);
- } else {
- UserPreferences.setPlaybackSpeed(playbackSpeed);
- }
-
- String speedStr = String.format(Locale.getDefault(), "%.2fx", playbackSpeed);
- txtvPlaybackSpeed.setText(speedStr);
- } else if (fromUser) {
- float speed = getCurrentSpeed();
- barPlaybackSpeed.post(() -> barPlaybackSpeed.setProgress(Math.round((20 * speed) - 10)));
- }
- }
+ PlaybackSpeedSeekBar speedSeekBar = dialog.findViewById(R.id.speed_seek_bar);
+ speedSeekBar.setController(controller);
+ speedSeekBar.setProgressChangedListener(speed
+ -> txtvPlaybackSpeed.setText(String.format(Locale.getDefault(), "%.2fx", speed)));
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- if (controller != null && !controller.canSetPlaybackSpeed()) {
- VariableSpeedDialog.showGetPluginDialog(getContext());
- }
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- }
- });
- barPlaybackSpeed.setProgress(Math.round((20 * currentSpeed) - 10));
-
- final SeekBar barLeftVolume = (SeekBar) dialog.findViewById(R.id.volume_left);
+ final SeekBar barLeftVolume = dialog.findViewById(R.id.volume_left);
barLeftVolume.setProgress(UserPreferences.getLeftVolumePercentage());
- final SeekBar barRightVolume = (SeekBar) dialog.findViewById(R.id.volume_right);
+ final SeekBar barRightVolume = dialog.findViewById(R.id.volume_right);
barRightVolume.setProgress(UserPreferences.getRightVolumePercentage());
- final CheckBox stereoToMono = (CheckBox) dialog.findViewById(R.id.stereo_to_mono);
+ final CheckBox stereoToMono = dialog.findViewById(R.id.stereo_to_mono);
stereoToMono.setChecked(UserPreferences.stereoToMono());
if (controller != null && !controller.canDownmix()) {
stereoToMono.setEnabled(false);
@@ -220,13 +162,4 @@ public class PlaybackControlsDialog extends DialogFragment {
new Handler().postDelayed(this::setupAudioTracks, 500);
});
}
-
- private float getCurrentSpeed() {
- Playable media = null;
- if (controller != null) {
- media = controller.getMedia();
- }
-
- return PlaybackSpeedUtils.getCurrentPlaybackSpeed(media);
- }
}
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java
index 0c25e3e9f..d0fb91692 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java
@@ -23,6 +23,7 @@ import java.net.Proxy;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.R;
@@ -63,6 +64,8 @@ public class ProxyDialog {
public Dialog show() {
View content = View.inflate(context, R.layout.proxy_settings, null);
+ spType = content.findViewById(R.id.spType);
+
dialog = new AlertDialog.Builder(context)
.setTitle(R.string.pref_proxy_title)
.setView(content)
@@ -76,7 +79,7 @@ public class ProxyDialog {
test();
return;
}
- String type = (String) ((Spinner) content.findViewById(R.id.spType)).getSelectedItem();
+ String type = (String) spType.getSelectedItem();
ProxyConfig proxy;
if (Proxy.Type.valueOf(type) == Proxy.Type.DIRECT) {
proxy = ProxyConfig.direct();
@@ -106,7 +109,6 @@ public class ProxyDialog {
dialog.dismiss();
});
- spType = content.findViewById(R.id.spType);
List<String> types = new ArrayList<>();
types.add(Proxy.Type.DIRECT.name());
types.add(Proxy.Type.HTTP.name());
@@ -227,12 +229,11 @@ public class ProxyDialog {
if(required) {
testSuccessful = false;
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setText(R.string.proxy_test_label);
- dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true);
} else {
testSuccessful = true;
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setText(android.R.string.ok);
- dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true);
}
+ dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true);
}
private void test() {
@@ -261,7 +262,7 @@ public class ProxyDialog {
portValue = Integer.parseInt(port);
}
SocketAddress address = InetSocketAddress.createUnresolved(host, portValue);
- Proxy.Type proxyType = Proxy.Type.valueOf(type.toUpperCase());
+ Proxy.Type proxyType = Proxy.Type.valueOf(type.toUpperCase(Locale.US));
Proxy proxy = new Proxy(proxyType, address);
OkHttpClient.Builder builder = AntennapodHttpClient.newBuilder()
.connectTimeout(10, TimeUnit.SECONDS)
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/ShareDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/ShareDialog.java
new file mode 100644
index 000000000..8104d3539
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/ShareDialog.java
@@ -0,0 +1,112 @@
+package de.danoeh.antennapod.dialog;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.feed.FeedItem;
+import de.danoeh.antennapod.core.util.ShareUtils;
+
+public class ShareDialog extends DialogFragment {
+
+ private static final String ARGUMENT_FEED_ITEM = "feedItem";
+
+ private static final String TAG = "ShareDialog";
+ private Context ctx;
+ private FeedItem item;
+
+ private static final String PREF_SHARE_DIALOG_OPTION = "prefShareDialogOption";
+ private static final String PREF_SHARE_EPISODE_START_AT = "prefShareEpisodeStartAt";
+
+ private RadioGroup radioGroup;
+ private RadioButton radioEpisodeWebsite;
+ private RadioButton radioMediaFile;
+ private CheckBox checkBoxStartAt;
+ private SharedPreferences prefs;
+
+ public ShareDialog() {
+ // Empty constructor required for DialogFragment
+ }
+
+ public static ShareDialog newInstance(FeedItem item) {
+ Bundle arguments = new Bundle();
+ arguments.putSerializable(ARGUMENT_FEED_ITEM, item);
+ ShareDialog dialog = new ShareDialog();
+ dialog.setArguments(arguments);
+ return dialog;
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ if (getArguments() != null) {
+ ctx = getActivity();
+ item = (FeedItem) getArguments().getSerializable(ARGUMENT_FEED_ITEM);
+ prefs = getActivity().getSharedPreferences("ShareDialog", Context.MODE_PRIVATE);
+ }
+
+ View content = View.inflate(ctx, R.layout.share_episode_dialog, null);
+ AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
+ builder.setTitle(R.string.share_label);
+ builder.setView(content);
+
+ radioGroup = content.findViewById(R.id.share_dialog_radio_group);
+ radioEpisodeWebsite = content.findViewById(R.id.share_episode_website_radio);
+ radioMediaFile = content.findViewById(R.id.share_media_file_radio);
+ checkBoxStartAt = content.findViewById(R.id.share_start_at_timer_dialog);
+
+ setupOptions();
+
+ builder.setPositiveButton(R.string.share_label, (dialog, id) -> {
+ boolean includePlaybackPosition = checkBoxStartAt.isChecked();
+ if (radioEpisodeWebsite.isChecked()) {
+ ShareUtils.shareFeedItemLink(ctx, item, includePlaybackPosition);
+ prefs.edit().putString(PREF_SHARE_DIALOG_OPTION, "website").apply();
+ } else {
+ ShareUtils.shareFeedItemDownloadLink(ctx, item, includePlaybackPosition);
+ prefs.edit().putString(PREF_SHARE_DIALOG_OPTION, "media").apply();
+ }
+ prefs.edit().putBoolean(PREF_SHARE_EPISODE_START_AT, includePlaybackPosition).apply();
+ }).setNegativeButton(R.string.cancel_label, (dialog, id) -> dialog.dismiss());
+
+ return builder.create();
+ }
+
+ private void setupOptions() {
+ final boolean hasMedia = item.getMedia() != null;
+
+ if (!ShareUtils.hasLinkToShare(item)) {
+ radioEpisodeWebsite.setVisibility(View.GONE);
+ radioMediaFile.setChecked(true);
+ }
+
+ if (!hasMedia || item.getMedia().getDownload_url() == null) {
+ radioMediaFile.setVisibility(View.GONE);
+ radioEpisodeWebsite.setChecked(true);
+ }
+
+ if (radioEpisodeWebsite.getVisibility() == View.VISIBLE && radioMediaFile.getVisibility() == View.VISIBLE) {
+ String option = prefs.getString(PREF_SHARE_DIALOG_OPTION, "website");
+ if (option.equals("website")) {
+ radioEpisodeWebsite.setChecked(true);
+ radioMediaFile.setChecked(false);
+ } else {
+ radioEpisodeWebsite.setChecked(false);
+ radioMediaFile.setChecked(true);
+ }
+ }
+
+ boolean switchIsChecked = prefs.getBoolean(PREF_SHARE_EPISODE_START_AT, false);
+ checkBoxStartAt.setChecked(switchIsChecked);
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java
index 3a6ba183f..ef8ed335d 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java
@@ -1,97 +1,171 @@
package de.danoeh.antennapod.dialog;
+import android.app.Dialog;
import android.content.Context;
-import android.os.Build;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import com.google.android.material.chip.Chip;
+import com.google.android.material.snackbar.Snackbar;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.util.playback.PlaybackController;
+import de.danoeh.antennapod.view.ItemOffsetDecoration;
+import de.danoeh.antennapod.view.PlaybackSpeedSeekBar;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.Locale;
-public class VariableSpeedDialog {
+public class VariableSpeedDialog extends DialogFragment {
+ private SpeedSelectionAdapter adapter;
+ private final DecimalFormat speedFormat;
+ private PlaybackController controller;
+ private final List<Float> selectedSpeeds;
+ private PlaybackSpeedSeekBar speedSeekBar;
+ private Chip addCurrentSpeedChip;
- private VariableSpeedDialog() {
- }
-
- public static void showDialog(final Context context) {
- if (UserPreferences.useSonic()
- || UserPreferences.useExoplayer()
- || Build.VERSION.SDK_INT >= 23) {
- showSpeedSelectorDialog(context);
- } else {
- showGetPluginDialog(context, true);
- }
+ public VariableSpeedDialog() {
+ DecimalFormatSymbols format = new DecimalFormatSymbols(Locale.US);
+ format.setDecimalSeparator('.');
+ speedFormat = new DecimalFormat("0.00", format);
+ selectedSpeeds = new ArrayList<>(UserPreferences.getPlaybackSpeedArray());
}
public static void showGetPluginDialog(final Context context) {
- showGetPluginDialog(context, false);
- }
-
- private static void showGetPluginDialog(final Context context, boolean showSpeedSelector) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.no_playback_plugin_title);
builder.setMessage(R.string.no_playback_plugin_or_sonic_msg);
builder.setPositiveButton(R.string.enable_sonic, (dialog, which) -> {
UserPreferences.enableSonic();
- if (showSpeedSelector) {
- showSpeedSelectorDialog(context);
- }
});
builder.setNeutralButton(R.string.close_label, null);
builder.show();
}
- private static void showSpeedSelectorDialog(final Context context) {
- DecimalFormatSymbols format = new DecimalFormatSymbols(Locale.US);
- format.setDecimalSeparator('.');
- DecimalFormat speedFormat = new DecimalFormat("0.00", format);
-
- final String[] speedValues = context.getResources().getStringArray(
- R.array.playback_speed_values);
- // According to Java spec these get initialized to false on creation
- final boolean[] speedChecked = new boolean[speedValues.length];
-
- // Build the "isChecked" array so that multiChoice dialog is populated correctly
- List<String> selectedSpeedList = new ArrayList<>();
- float[] selectedSpeeds = UserPreferences.getPlaybackSpeedArray();
- for (float speed : selectedSpeeds) {
- selectedSpeedList.add(speedFormat.format(speed));
+ @Override
+ public void onStart() {
+ super.onStart();
+ controller = new PlaybackController(getActivity()) {
+ @Override
+ public void setupGUI() {
+ updateSpeed();
+ }
+
+ @Override
+ public void onPlaybackSpeedChange() {
+ updateSpeed();
+ }
+ };
+ controller.init();
+ speedSeekBar.setController(controller);
+ }
+
+ private void updateSpeed() {
+ speedSeekBar.updateSpeed();
+ addCurrentSpeedChip.setText(speedFormat.format(controller.getCurrentPlaybackSpeedMultiplier()));
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ controller.release();
+ controller = null;
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+ builder.setPositiveButton(R.string.close_label, null);
+
+ View root = View.inflate(getContext(), R.layout.speed_select_dialog, null);
+ speedSeekBar = root.findViewById(R.id.speed_seek_bar);
+ RecyclerView selectedSpeedsGrid = root.findViewById(R.id.selected_speeds_grid);
+ selectedSpeedsGrid.setLayoutManager(new GridLayoutManager(getContext(), 3));
+ selectedSpeedsGrid.addItemDecoration(new ItemOffsetDecoration(getContext(), 4));
+ adapter = new SpeedSelectionAdapter();
+ adapter.setHasStableIds(true);
+ selectedSpeedsGrid.setAdapter(adapter);
+
+ addCurrentSpeedChip = root.findViewById(R.id.add_current_speed_chip);
+ addCurrentSpeedChip.setCloseIconVisible(true);
+ addCurrentSpeedChip.setCloseIconResource(R.drawable.ic_add_black);
+ addCurrentSpeedChip.setOnCloseIconClickListener(v -> addCurrentSpeed());
+ addCurrentSpeedChip.setOnClickListener(v -> addCurrentSpeed());
+
+ builder.setView(root);
+ return builder.create();
+ }
+
+ private void addCurrentSpeed() {
+ float newSpeed = controller.getCurrentPlaybackSpeedMultiplier();
+ if (selectedSpeeds.contains(newSpeed)) {
+ Snackbar.make(addCurrentSpeedChip,
+ getString(R.string.preset_already_exists, newSpeed), Snackbar.LENGTH_LONG).show();
+ } else {
+ selectedSpeeds.add(newSpeed);
+ Collections.sort(selectedSpeeds);
+ UserPreferences.setPlaybackSpeedArray(selectedSpeeds);
+ adapter.notifyDataSetChanged();
}
+ }
- for (int i = 0; i < speedValues.length; i++) {
- speedChecked[i] = selectedSpeedList.contains(speedValues[i]);
+ public class SpeedSelectionAdapter extends RecyclerView.Adapter<SpeedSelectionAdapter.ViewHolder> {
+
+ @Override
+ @NonNull
+ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ Chip chip = new Chip(getContext());
+ chip.setCloseIconVisible(true);
+ chip.setCloseIconResource(R.drawable.ic_delete_black);
+ return new ViewHolder(chip);
}
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(R.string.set_playback_speed_label);
- builder.setMultiChoiceItems(R.array.playback_speed_values,
- speedChecked, (dialog, which, isChecked) -> speedChecked[which] = isChecked);
- builder.setNegativeButton(android.R.string.cancel, null);
- builder.setPositiveButton(android.R.string.ok,
- (dialog, which) -> {
- int choiceCount = 0;
- for (boolean checked : speedChecked) {
- if (checked) {
- choiceCount++;
- }
- }
- String[] newSpeedValues = new String[choiceCount];
- int newSpeedIndex = 0;
- for (int i = 0; i < speedChecked.length; i++) {
- if (speedChecked[i]) {
- newSpeedValues[newSpeedIndex++] = speedValues[i];
- }
+ @Override
+ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
+ float speed = selectedSpeeds.get(position);
+
+ holder.chip.setText(speedFormat.format(speed));
+ holder.chip.setOnCloseIconClickListener(v -> {
+ selectedSpeeds.remove(speed);
+ UserPreferences.setPlaybackSpeedArray(selectedSpeeds);
+ notifyDataSetChanged();
+ });
+ holder.chip.setOnClickListener(v -> {
+ if (controller != null) {
+ controller.setPlaybackSpeed(speed);
+ notifyDataSetChanged();
}
+ });
+ }
- UserPreferences.setPlaybackSpeedArray(newSpeedValues);
+ @Override
+ public int getItemCount() {
+ return selectedSpeeds.size();
+ }
- });
- builder.create().show();
- }
+ @Override
+ public long getItemId(int position) {
+ return selectedSpeeds.get(position).hashCode();
+ }
+
+ public class ViewHolder extends RecyclerView.ViewHolder {
+ Chip chip;
+ ViewHolder(Chip itemView) {
+ super(itemView);
+ chip = itemView;
+ }
+ }
+ }
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java
index 546684f14..167daa08b 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java
@@ -12,9 +12,13 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
+
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.activity.OnlineFeedViewActivity;
@@ -36,7 +40,10 @@ public class AddFeedFragment extends Fragment {
private MainActivity activity;
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ @Nullable
+ public View onCreateView(@NonNull LayoutInflater inflater,
+ @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View root = inflater.inflate(R.layout.addfeed, container, false);
activity = (MainActivity) getActivity();
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 05f38000c..4a1c12e0a 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
@@ -45,20 +45,18 @@ public class AllEpisodesFragment extends EpisodesListFragment {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (!super.onOptionsItemSelected(item)) {
- switch (item.getItemId()) {
- case R.id.filter_items:
- showFilterDialog();
- return true;
- default:
- return false;
+ if (item.getItemId() == R.id.filter_items) {
+ showFilterDialog();
+ return true;
}
+ return false;
} else {
return true;
}
}
@Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.findItem(R.id.filter_items).setVisible(true);
menu.findItem(R.id.mark_all_read_item).setVisible(true);
@@ -69,7 +67,7 @@ public class AllEpisodesFragment extends EpisodesListFragment {
super.onFragmentLoaded(episodes);
if (feedItemFilter.getValues().length > 0) {
- txtvInformation.setText("{fa-info-circle} " + this.getString(R.string.filtered_label));
+ txtvInformation.setText("{md-info-outline} " + this.getString(R.string.filtered_label));
Iconify.addIcons(txtvInformation);
txtvInformation.setVisibility(View.VISIBLE);
} else {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java
index 5ca8b666a..7eb749681 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java
@@ -13,7 +13,6 @@ import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.TextView;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
@@ -21,17 +20,8 @@ import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
-
import com.google.android.material.bottomsheet.BottomSheetBehavior;
-
import com.google.android.material.snackbar.Snackbar;
-import org.greenrobot.eventbus.EventBus;
-import org.greenrobot.eventbus.Subscribe;
-import org.greenrobot.eventbus.ThreadMode;
-
-import java.text.DecimalFormat;
-import java.text.NumberFormat;
-
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.CastEnabledActivity;
import de.danoeh.antennapod.activity.MainActivity;
@@ -40,7 +30,6 @@ import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.util.PlaybackSpeedUtils;
-import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.util.Converter;
@@ -60,6 +49,13 @@ import io.reactivex.Maybe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.List;
/**
* Shows the audio player.
@@ -96,7 +92,9 @@ public class AudioPlayerFragment extends Fragment implements
private boolean showTimeLeft;
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ public View onCreateView(@NonNull LayoutInflater inflater,
+ @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View root = inflater.inflate(R.layout.audioplayer_fragment, container, false);
toolbar = root.findViewById(R.id.toolbar);
@@ -206,30 +204,29 @@ public class AudioPlayerFragment extends Fragment implements
VariableSpeedDialog.showGetPluginDialog(getContext());
return;
}
- float[] availableSpeeds = UserPreferences.getPlaybackSpeedArray();
+ List<Float> availableSpeeds = UserPreferences.getPlaybackSpeedArray();
float currentSpeed = controller.getCurrentPlaybackSpeedMultiplier();
int newSpeedIndex = 0;
- while (newSpeedIndex < availableSpeeds.length && availableSpeeds[newSpeedIndex] < currentSpeed + EPSILON) {
+ while (newSpeedIndex < availableSpeeds.size()
+ && availableSpeeds.get(newSpeedIndex) < currentSpeed + EPSILON) {
newSpeedIndex++;
}
float newSpeed;
- if (availableSpeeds.length == 0) {
+ if (availableSpeeds.size() == 0) {
newSpeed = 1.0f;
- } else if (newSpeedIndex == availableSpeeds.length) {
- newSpeed = availableSpeeds[0];
+ } else if (newSpeedIndex == availableSpeeds.size()) {
+ newSpeed = availableSpeeds.get(0);
} else {
- newSpeed = availableSpeeds[newSpeedIndex];
+ newSpeed = availableSpeeds.get(newSpeedIndex);
}
- PlaybackPreferences.setCurrentlyPlayingTemporaryPlaybackSpeed(newSpeed);
- UserPreferences.setPlaybackSpeed(newSpeed);
controller.setPlaybackSpeed(newSpeed);
loadMediaInfo();
});
butPlaybackSpeed.setOnLongClickListener(v -> {
- VariableSpeedDialog.showDialog(getContext());
+ new VariableSpeedDialog().show(getChildFragmentManager(), null);
return true;
});
butPlaybackSpeed.setVisibility(View.VISIBLE);
@@ -491,11 +488,11 @@ public class AudioPlayerFragment extends Fragment implements
switch (item.getItemId()) {
case R.id.disable_sleeptimer_item: // Fall-through
case R.id.set_sleeptimer_item:
- new SleepTimerDialog().show(getFragmentManager(), "SleepTimerDialog");
+ new SleepTimerDialog().show(getChildFragmentManager(), "SleepTimerDialog");
return true;
case R.id.audio_controls:
- PlaybackControlsDialog dialog = PlaybackControlsDialog.newInstance(false);
- dialog.show(getFragmentManager(), "playback_controls");
+ PlaybackControlsDialog dialog = PlaybackControlsDialog.newInstance();
+ dialog.show(getChildFragmentManager(), "playback_controls");
return true;
case R.id.open_feed_item:
if (feedItem != null) {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java
index 48c25552f..6911687dd 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java
@@ -45,7 +45,6 @@ public class ChaptersFragment extends Fragment {
RecyclerView recyclerView = root.findViewById(R.id.recyclerView);
layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
- recyclerView.setHasFixedSize(true);
recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getActivity()).build());
adapter = new ChaptersListAdapter(getActivity(), pos -> {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
index 13941dd2c..55a5d744e 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
@@ -17,16 +17,21 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.EpisodeItemListAdapter;
import de.danoeh.antennapod.adapter.actionbutton.DeleteActionButton;
+import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.DownloadLogEvent;
import de.danoeh.antennapod.core.event.FeedItemEvent;
import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import de.danoeh.antennapod.core.event.PlayerStatusEvent;
import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
import de.danoeh.antennapod.core.feed.FeedItem;
+import de.danoeh.antennapod.core.service.download.DownloadService;
import de.danoeh.antennapod.core.storage.DBReader;
+import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.FeedItemUtil;
+import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
import de.danoeh.antennapod.dialog.EpisodesApplyActionFragment;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
+import de.danoeh.antennapod.menuhandler.MenuItemUtils;
import de.danoeh.antennapod.view.EmptyViewHandler;
import de.danoeh.antennapod.view.EpisodeItemListRecyclerView;
import de.danoeh.antennapod.view.viewholder.EpisodeItemViewHolder;
@@ -58,6 +63,8 @@ public class CompletedDownloadsFragment extends Fragment {
private Disposable disposable;
private EmptyViewHandler emptyView;
+ private boolean isUpdatingFeeds = false;
+
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
@@ -104,10 +111,11 @@ public class CompletedDownloadsFragment extends Fragment {
}
@Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.downloads_completed, menu);
menu.findItem(R.id.episode_actions).setVisible(items.size() > 0);
+ isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker);
}
@Override
@@ -116,10 +124,24 @@ public class CompletedDownloadsFragment extends Fragment {
((MainActivity) requireActivity())
.loadChildFragment(EpisodesApplyActionFragment.newInstance(items, ACTION_DELETE | ACTION_ADD_TO_QUEUE));
return true;
+ } else if (item.getItemId() == R.id.refresh_item) {
+ AutoUpdateManager.runImmediate(requireContext());
+ return true;
}
return false;
}
+ @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
+ public void onEventMainThread(DownloadEvent event) {
+ Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
+ if (event.hasChangedFeedUpdateStatus(isUpdatingFeeds)) {
+ getActivity().invalidateOptionsMenu();
+ }
+ }
+
+ private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker =
+ () -> DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds();
+
@Override
public boolean onContextItemSelected(@NonNull MenuItem item) {
FeedItem selectedItem = adapter.getSelectedItem();
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 312e3cb62..055d88285 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java
@@ -1,11 +1,16 @@
package de.danoeh.antennapod.fragment;
import android.app.Dialog;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
import android.content.res.TypedArray;
import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.ListFragment;
-import androidx.core.view.MenuItemCompat;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
@@ -17,14 +22,21 @@ import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
+import com.google.android.material.snackbar.Snackbar;
import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.DownloadLogAdapter;
+import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.DownloadLogEvent;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedMedia;
+import de.danoeh.antennapod.core.service.download.DownloadService;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
+import de.danoeh.antennapod.core.storage.DownloadRequester;
+import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
+import de.danoeh.antennapod.menuhandler.MenuItemUtils;
import de.danoeh.antennapod.view.EmptyViewHandler;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
@@ -32,6 +44,7 @@ import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
/**
* Shows the download log
@@ -44,6 +57,8 @@ public class DownloadLogFragment extends ListFragment {
private DownloadLogAdapter adapter;
private Disposable disposable;
+ private boolean isUpdatingFeeds = false;
+
@Override
public void onStart() {
super.onStart();
@@ -65,7 +80,7 @@ public class DownloadLogFragment extends ListFragment {
}
@Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// add padding
final ListView lv = getListView();
@@ -93,11 +108,11 @@ public class DownloadLogFragment extends ListFragment {
private void onFragmentLoaded() {
setListShown(true);
adapter.notifyDataSetChanged();
- getActivity().supportInvalidateOptionsMenu();
+ getActivity().invalidateOptionsMenu();
}
@Override
- public void onListItemClick(ListView l, View v, int position, long id) {
+ public void onListItemClick(@NonNull ListView l, @NonNull View v, int position, long id) {
super.onListItemClick(l, v, position, id);
DownloadStatus status = adapter.getItem(position);
@@ -119,10 +134,17 @@ public class DownloadLogFragment extends ListFragment {
message = status.getReasonDetailed();
}
+ String messageFull = getString(R.string.download_error_details_message, message, url);
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle(R.string.download_error_details);
- builder.setMessage(getString(R.string.download_error_details_message, message, url));
+ builder.setMessage(messageFull);
builder.setPositiveButton(android.R.string.ok, null);
+ builder.setNeutralButton(R.string.copy_to_clipboard, (dialog, which) -> {
+ ClipboardManager clipboard = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
+ ClipData clip = ClipData.newPlainText(getString(R.string.download_error_details), messageFull);
+ clipboard.setPrimaryClip(clip);
+ ((MainActivity) getActivity()).showSnackbarAbovePlayer(R.string.copied_to_clipboard, Snackbar.LENGTH_SHORT);
+ });
Dialog dialog = builder.show();
((TextView) dialog.findViewById(android.R.id.message)).setTextIsSelectable(true);
}
@@ -150,20 +172,14 @@ public class DownloadLogFragment extends ListFragment {
}
@Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- if (!isAdded()) {
- return;
- }
+ public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
- MenuItem clearHistory = menu.add(Menu.NONE, R.id.clear_history_item, Menu.CATEGORY_CONTAINER, R.string.clear_history_label);
- MenuItemCompat.setShowAsAction(clearHistory, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
- TypedArray drawables = getActivity().obtainStyledAttributes(new int[]{R.attr.ic_delete});
- clearHistory.setIcon(drawables.getDrawable(0));
- drawables.recycle();
+ inflater.inflate(R.menu.downloads_log, menu);
+ isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker);
}
@Override
- public void onPrepareOptionsMenu(Menu menu) {
+ public void onPrepareOptionsMenu(@NonNull Menu menu) {
super.onPrepareOptionsMenu(menu);
MenuItem menuItem = menu.findItem(R.id.clear_history_item);
if (menuItem != null) {
@@ -172,12 +188,15 @@ public class DownloadLogFragment extends ListFragment {
}
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
+ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (!super.onOptionsItemSelected(item)) {
switch (item.getItemId()) {
case R.id.clear_history_item:
DBWriter.clearDownloadLog();
return true;
+ case R.id.refresh_item:
+ AutoUpdateManager.runImmediate(requireContext());
+ return true;
default:
return false;
}
@@ -186,6 +205,17 @@ public class DownloadLogFragment extends ListFragment {
}
}
+ @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
+ public void onEventMainThread(DownloadEvent event) {
+ Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
+ if (event.hasChangedFeedUpdateStatus(isUpdatingFeeds)) {
+ getActivity().invalidateOptionsMenu();
+ }
+ }
+
+ private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker =
+ () -> DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds();
+
private void loadItems() {
if (disposable != null) {
disposable.dispose();
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 cf0c6db90..c173bf8ee 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java
@@ -8,6 +8,7 @@ import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
@@ -39,7 +40,9 @@ public class DownloadsFragment extends Fragment {
private TabLayout tabLayout;
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ public View onCreateView(@NonNull LayoutInflater inflater,
+ @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View root = inflater.inflate(R.layout.pager_fragment, container, false);
Toolbar toolbar = root.findViewById(R.id.toolbar);
@@ -76,7 +79,7 @@ public class DownloadsFragment extends Fragment {
}
@Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (getArguments() != null) {
int tab = getArguments().getInt(ARG_SELECTED_TAB);
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java
index 29b6a1b16..44f6c8827 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java
@@ -120,7 +120,7 @@ public abstract class EpisodesListFragment extends Fragment {
}
@Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
if (!isAdded()) {
return;
}
@@ -131,7 +131,7 @@ public abstract class EpisodesListFragment extends Fragment {
}
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
+ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (!super.onOptionsItemSelected(item)) {
switch (item.getItemId()) {
case R.id.refresh_item:
@@ -176,7 +176,7 @@ public abstract class EpisodesListFragment extends Fragment {
}
@Override
- public boolean onContextItemSelected(MenuItem item) {
+ public boolean onContextItemSelected(@NonNull MenuItem item) {
Log.d(TAG, "onContextItemSelected() called with: " + "item = [" + item + "]");
if (!getUserVisibleHint()) {
return false;
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java
index 4f8b4f00c..d50be88c5 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java
@@ -53,12 +53,14 @@ public class FavoriteEpisodesFragment extends EpisodesListFragment {
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0,
ItemTouchHelper.LEFT) {
@Override
- public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
+ public boolean onMove(@NonNull RecyclerView recyclerView,
+ @NonNull RecyclerView.ViewHolder viewHolder,
+ @NonNull RecyclerView.ViewHolder target) {
return false;
}
@Override
- public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
+ public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int swipeDir) {
EpisodeItemViewHolder holder = (EpisodeItemViewHolder) viewHolder;
Log.d(TAG, String.format("remove(%s)", holder.getFeedItem().getId()));
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FeedInfoFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FeedInfoFragment.java
index c58e6c15f..ae03b5032 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/FeedInfoFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/FeedInfoFragment.java
@@ -3,6 +3,7 @@ package de.danoeh.antennapod.fragment;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Configuration;
import android.graphics.LightingColorFilter;
import android.net.Uri;
import android.os.Bundle;
@@ -47,9 +48,6 @@ import io.reactivex.MaybeOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
-import org.apache.commons.lang3.StringUtils;
-import org.jsoup.Jsoup;
-import org.jsoup.nodes.Document;
/**
* Displays information about a feed.
@@ -71,6 +69,8 @@ public class FeedInfoFragment extends Fragment {
private TextView txtvUrl;
private TextView txtvAuthorHeader;
private ImageView imgvBackground;
+ private View infoContainer;
+ private View header;
private Menu optionsMenu;
private ToolbarIconTintManager iconTintManager;
@@ -124,6 +124,8 @@ public class FeedInfoFragment extends Fragment {
txtvTitle = root.findViewById(R.id.txtvTitle);
txtvAuthorHeader = root.findViewById(R.id.txtvAuthor);
imgvBackground = root.findViewById(R.id.imgvBackground);
+ header = root.findViewById(R.id.headerContainer);
+ infoContainer = root.findViewById(R.id.infoContainer);
root.findViewById(R.id.butShowInfo).setVisibility(View.INVISIBLE);
root.findViewById(R.id.butShowSettings).setVisibility(View.INVISIBLE);
// https://github.com/bumptech/glide/issues/529
@@ -159,6 +161,15 @@ public class FeedInfoFragment extends Fragment {
}, error -> Log.d(TAG, Log.getStackTraceString(error)), () -> { });
}
+ @Override
+ public void onConfigurationChanged(@NonNull Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ int horizontalSpacing = (int) getResources().getDimension(R.dimen.additional_horizontal_spacing);
+ header.setPadding(horizontalSpacing, header.getPaddingTop(), horizontalSpacing, header.getPaddingBottom());
+ infoContainer.setPadding(horizontalSpacing, infoContainer.getPaddingTop(),
+ horizontalSpacing, infoContainer.getPaddingBottom());
+ }
+
private void showFeed() {
Log.d(TAG, "Language is " + feed.getLanguage());
Log.d(TAG, "Author is " + feed.getAuthor());
@@ -216,7 +227,7 @@ public class FeedInfoFragment extends Fragment {
}
@Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.feedinfo, menu);
optionsMenu = menu;
@@ -224,7 +235,7 @@ public class FeedInfoFragment extends Fragment {
}
@Override
- public void onPrepareOptionsMenu(Menu menu) {
+ public void onPrepareOptionsMenu(@NonNull Menu menu) {
super.onPrepareOptionsMenu(menu);
menu.findItem(R.id.share_link_item).setVisible(feed != null && feed.getLink() != null);
menu.findItem(R.id.visit_website_item).setVisible(feed != null && feed.getLink() != null
@@ -232,7 +243,7 @@ public class FeedInfoFragment extends Fragment {
}
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
+ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (feed == null) {
((MainActivity) getActivity()).showSnackbarAbovePlayer(
R.string.please_wait_for_data, Toast.LENGTH_LONG);
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java
index 67433166c..965cfdc86 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java
@@ -2,6 +2,8 @@ package de.danoeh.antennapod.fragment;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.res.Configuration;
+import android.content.Intent;
import android.graphics.LightingColorFilter;
import android.os.Bundle;
import android.util.Log;
@@ -52,6 +54,7 @@ import de.danoeh.antennapod.core.glide.FastBlurTransformation;
import de.danoeh.antennapod.core.service.download.DownloadService;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
+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.FeedItemPermutors;
@@ -60,6 +63,7 @@ import de.danoeh.antennapod.core.util.Optional;
import de.danoeh.antennapod.core.util.ThemeUtils;
import de.danoeh.antennapod.core.util.gui.MoreContentListFooterUtil;
import de.danoeh.antennapod.dialog.EpisodesApplyActionFragment;
+import de.danoeh.antennapod.dialog.FilterDialog;
import de.danoeh.antennapod.dialog.RenameFeedDialog;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
import de.danoeh.antennapod.menuhandler.FeedMenuHandler;
@@ -77,6 +81,7 @@ import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.List;
+import java.util.Set;
/**
* Displays a list of FeedItems.
@@ -98,6 +103,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
private TextView txtvAuthor;
private ImageButton butShowInfo;
private ImageButton butShowSettings;
+ private View header;
private Menu optionsMenu;
private ToolbarIconTintManager iconTintManager;
@@ -155,6 +161,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
butShowSettings = root.findViewById(R.id.butShowSettings);
txtvInformation = root.findViewById(R.id.txtvInformation);
txtvFailure = root.findViewById(R.id.txtvFailure);
+ header = root.findViewById(R.id.headerContainer);
AppBarLayout appBar = root.findViewById(R.id.appBar);
CollapsingToolbarLayout collapsingToolbar = root.findViewById(R.id.collapsing_toolbar);
@@ -221,7 +228,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
};
@Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
if (!isAdded()) {
return;
}
@@ -239,14 +246,21 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
}
@Override
- public void onPrepareOptionsMenu(Menu menu) {
+ public void onPrepareOptionsMenu(@NonNull Menu menu) {
if (feed != null) {
FeedMenuHandler.onPrepareOptionsMenu(menu, feed);
}
}
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
+ public void onConfigurationChanged(@NonNull Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ int horizontalSpacing = (int) getResources().getDimension(R.dimen.additional_horizontal_spacing);
+ header.setPadding(horizontalSpacing, header.getPaddingTop(), horizontalSpacing, header.getPaddingBottom());
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (!super.onOptionsItemSelected(item)) {
if (feed == null) {
((MainActivity) getActivity()).showSnackbarAbovePlayer(
@@ -405,7 +419,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
private void updateSyncProgressBarVisibility() {
if (isUpdatingFeed != updateRefreshMenuItemChecker.isRefreshing()) {
- getActivity().supportInvalidateOptionsMenu();
+ getActivity().invalidateOptionsMenu();
}
if (!DownloadRequester.getInstance().isDownloadingFeeds()) {
nextPageLoader.getRoot().setVisibility(View.GONE);
@@ -429,7 +443,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
adapter.updateItems(feed.getItems());
}
- getActivity().supportInvalidateOptionsMenu();
+ getActivity().invalidateOptionsMenu();
updateSyncProgressBarVisibility();
}
@@ -454,8 +468,19 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) txtvInformation.getLayoutParams();
p.addRule(RelativeLayout.BELOW, R.id.txtvFailure);
}
- txtvInformation.setText("{fa-info-circle} " + this.getString(R.string.filtered_label));
+ txtvInformation.setText("{md-info-outline} " + this.getString(R.string.filtered_label));
Iconify.addIcons(txtvInformation);
+ txtvInformation.setOnClickListener((l) -> {
+ FilterDialog filterDialog = new FilterDialog(requireContext(), feed.getItemFilter()) {
+ @Override
+ protected void updateFilter(Set<String> filterValues) {
+ feed.setItemFilter(filterValues.toArray(new String[0]));
+ DBWriter.setFeedItemsFilter(feed.getId(), filterValues);
+ }
+ };
+
+ filterDialog.openDialog();
+ });
txtvInformation.setVisibility(View.VISIBLE);
} else {
txtvInformation.setVisibility(View.GONE);
@@ -482,6 +507,14 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
((MainActivity) getActivity()).loadChildFragment(fragment, TransitionEffect.SLIDE);
}
});
+ txtvFailure.setOnClickListener(v -> {
+ Intent intent = new Intent(getContext(), MainActivity.class);
+ intent.putExtra(MainActivity.EXTRA_FRAGMENT_TAG, DownloadsFragment.TAG);
+ Bundle args = new Bundle();
+ args.putInt(DownloadsFragment.ARG_SELECTED_TAB, DownloadsFragment.POS_LOG);
+ intent.putExtra(MainActivity.EXTRA_FRAGMENT_ARGS, args);
+ startActivity(intent);
+ });
headerCreated = true;
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java
index 8251e8716..a82c60d6c 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java
@@ -14,7 +14,7 @@ import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.preference.ListPreference;
import androidx.preference.PreferenceFragmentCompat;
-import androidx.preference.SwitchPreference;
+import androidx.preference.SwitchPreferenceCompat;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.event.settings.SkipIntroEndingChangedEvent;
@@ -66,7 +66,7 @@ public class FeedSettingsFragment extends Fragment {
Toolbar toolbar = root.findViewById(R.id.toolbar);
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
- getFragmentManager().beginTransaction()
+ getParentFragmentManager().beginTransaction()
.replace(R.id.settings_fragment_container,
FeedSettingsPreferenceFragment.newInstance(feedId), "settings_fragment")
.commitAllowingStateLoss();
@@ -322,7 +322,7 @@ public class FeedSettingsFragment extends Fragment {
}
private void setupKeepUpdatedPreference() {
- SwitchPreference pref = findPreference("keepUpdated");
+ SwitchPreferenceCompat pref = findPreference("keepUpdated");
pref.setChecked(feedPreferences.getKeepUpdated());
pref.setOnPreferenceChangeListener((preference, newValue) -> {
@@ -336,7 +336,7 @@ public class FeedSettingsFragment extends Fragment {
private void setupAutoDownloadGlobalPreference() {
if (!UserPreferences.isEnableAutodownload()) {
- SwitchPreference autodl = findPreference("autoDownload");
+ SwitchPreferenceCompat autodl = findPreference("autoDownload");
autodl.setChecked(false);
autodl.setEnabled(false);
autodl.setSummary(R.string.auto_download_disabled_globally);
@@ -345,7 +345,7 @@ public class FeedSettingsFragment extends Fragment {
}
private void setupAutoDownloadPreference() {
- SwitchPreference pref = findPreference("autoDownload");
+ SwitchPreferenceCompat pref = findPreference("autoDownload");
pref.setEnabled(UserPreferences.isEnableAutodownload());
if (UserPreferences.isEnableAutodownload()) {
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 aaf0fc7d4..337c789fe 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
@@ -145,9 +145,7 @@ public class ItemFragment extends Fragment {
}
txtvDuration = layout.findViewById(R.id.txtvDuration);
txtvPublished = layout.findViewById(R.id.txtvPublished);
- if (Build.VERSION.SDK_INT >= 14) { // ellipsize is causing problems on old versions, see #448
- txtvTitle.setEllipsize(TextUtils.TruncateAt.END);
- }
+ txtvTitle.setEllipsize(TextUtils.TruncateAt.END);
webvDescription = layout.findViewById(R.id.webvDescription);
webvDescription.setTimecodeSelectedListener(time -> {
if (controller != null && item.getMedia() != null && controller.getMedia() != null
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java
index c198ce258..3b1171df4 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java
@@ -140,13 +140,11 @@ public class ItemPagerFragment extends Fragment {
@Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
- switch (menuItem.getItemId()) {
- case R.id.open_podcast:
- openPodcast();
- return true;
- default:
- return FeedItemMenuHandler.onMenuItemClicked(this, menuItem.getItemId(), item);
+ if (menuItem.getItemId() == R.id.open_podcast) {
+ openPodcast();
+ return true;
}
+ return FeedItemMenuHandler.onMenuItemClicked(this, menuItem.getItemId(), item);
}
@Subscribe(threadMode = ThreadMode.MAIN)
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java
index da5710936..8b7d2b886 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java
@@ -37,6 +37,7 @@ import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.IntentUtils;
+import de.danoeh.antennapod.dialog.FeedFilterDialog;
import de.danoeh.antennapod.dialog.RenameFeedDialog;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
@@ -86,9 +87,8 @@ public class NavDrawerFragment extends Fragment implements AdapterView.OnItemCli
registerForContextMenu(navList);
updateSelection();
- root.findViewById(R.id.nav_settings).setOnClickListener(v -> {
- startActivity(new Intent(getActivity(), PreferenceActivity.class));
- });
+ root.findViewById(R.id.nav_settings).setOnClickListener(v ->
+ startActivity(new Intent(getActivity(), PreferenceActivity.class)));
getContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.registerOnSharedPreferenceChangeListener(this);
return root;
@@ -388,6 +388,9 @@ public class NavDrawerFragment extends Fragment implements AdapterView.OnItemCli
startActivity(intent);
}
}
+ } else if (UserPreferences.getFeedFilter() != UserPreferences.FEED_FILTER_NONE
+ && navAdapter.showSubscriptionList) {
+ FeedFilterDialog.showDialog(requireContext());
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/OnlineSearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/OnlineSearchFragment.java
index d9c31f993..e8bd5a1e1 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/OnlineSearchFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/OnlineSearchFragment.java
@@ -107,8 +107,8 @@ public class OnlineSearchFragment extends Fragment {
txtvError = root.findViewById(R.id.txtvError);
butRetry = root.findViewById(R.id.butRetry);
txtvEmpty = root.findViewById(android.R.id.empty);
-
- txtvEmpty.setText(getString(R.string.search_powered_by, searchProvider.getName()));
+ TextView txtvPoweredBy = root.findViewById(R.id.search_powered_by);
+ txtvPoweredBy.setText(getString(R.string.search_powered_by, searchProvider.getName()));
return root;
}
@@ -126,7 +126,7 @@ public class OnlineSearchFragment extends Fragment {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.online_search, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
- final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
+ final SearchView sv = (SearchView) searchItem.getActionView();
sv.setQueryHint(getString(R.string.search_podcast_hint));
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
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 dabff7269..db4bda1f5 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
@@ -153,7 +153,7 @@ public class PlaybackHistoryFragment extends Fragment {
}
super.onCreateOptionsMenu(menu, inflater);
MenuItem clearHistory = menu.add(Menu.NONE, R.id.clear_history_item, Menu.CATEGORY_CONTAINER, R.string.clear_history_label);
- MenuItemCompat.setShowAsAction(clearHistory, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
+ clearHistory.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
TypedArray drawables = getActivity().obtainStyledAttributes(new int[]{R.attr.ic_delete});
clearHistory.setIcon(drawables.getDrawable(0));
drawables.recycle();
@@ -171,13 +171,11 @@ public class PlaybackHistoryFragment extends Fragment {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (!super.onOptionsItemSelected(item)) {
- switch (item.getItemId()) {
- case R.id.clear_history_item:
- DBWriter.clearPlaybackHistory();
- return true;
- default:
- return false;
+ if (item.getItemId() == R.id.clear_history_item) {
+ DBWriter.clearPlaybackHistory();
+ return true;
}
+ return false;
} else {
return true;
}
@@ -196,18 +194,18 @@ public class PlaybackHistoryFragment extends Fragment {
@Subscribe(threadMode = ThreadMode.MAIN)
public void onHistoryUpdated(PlaybackHistoryEvent event) {
loadItems();
- getActivity().supportInvalidateOptionsMenu();
+ getActivity().invalidateOptionsMenu();
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onPlayerStatusChanged(PlayerStatusEvent event) {
loadItems();
- getActivity().supportInvalidateOptionsMenu();
+ getActivity().invalidateOptionsMenu();
}
private void onFragmentLoaded() {
adapter.notifyDataSetChanged();
- getActivity().supportInvalidateOptionsMenu();
+ getActivity().invalidateOptionsMenu();
}
private void loadItems() {
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 49c53627f..26216b375 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
@@ -16,7 +16,6 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
-import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
@@ -136,6 +135,7 @@ public class QueueFragment extends Fragment {
recyclerAdapter.notifyItemInserted(event.position);
break;
case SET_QUEUE:
+ case SORTED: //Deliberate fall-through
queue = event.items;
recyclerAdapter.notifyDataSetChanged();
break;
@@ -149,10 +149,6 @@ public class QueueFragment extends Fragment {
queue.clear();
recyclerAdapter.notifyDataSetChanged();
break;
- case SORTED:
- queue = event.items;
- recyclerAdapter.notifyDataSetChanged();
- break;
case MOVED:
return;
}
@@ -216,7 +212,7 @@ public class QueueFragment extends Fragment {
public void onPlayerStatusChanged(PlayerStatusEvent event) {
loadItems(false);
if (isUpdatingFeeds != updateRefreshMenuItemChecker.isRefreshing()) {
- getActivity().supportInvalidateOptionsMenu();
+ getActivity().invalidateOptionsMenu();
}
}
@@ -225,7 +221,7 @@ public class QueueFragment extends Fragment {
// Sent when playback position is reset
loadItems(false);
if (isUpdatingFeeds != updateRefreshMenuItemChecker.isRefreshing()) {
- getActivity().supportInvalidateOptionsMenu();
+ getActivity().invalidateOptionsMenu();
}
}
@@ -340,10 +336,10 @@ public class QueueFragment extends Fragment {
SortOrder sortOrder = UserPreferences.getQueueKeepSortedOrder();
DBWriter.reorderQueue(sortOrder, true);
if (recyclerAdapter != null) {
- recyclerAdapter.setLocked(true);
+ recyclerAdapter.updateDragDropEnabled();
}
} else if (recyclerAdapter != null) {
- recyclerAdapter.setLocked(UserPreferences.isQueueLocked());
+ recyclerAdapter.updateDragDropEnabled();
}
getActivity().invalidateOptionsMenu();
return true;
@@ -384,14 +380,16 @@ public class QueueFragment extends Fragment {
private void setQueueLocked(boolean locked) {
UserPreferences.setQueueLocked(locked);
- getActivity().supportInvalidateOptionsMenu();
+ getActivity().invalidateOptionsMenu();
if (recyclerAdapter != null) {
- recyclerAdapter.setLocked(locked);
+ recyclerAdapter.updateDragDropEnabled();
}
- if (locked) {
- ((MainActivity) getActivity()).showSnackbarAbovePlayer(R.string.queue_locked, Snackbar.LENGTH_SHORT);
- } else {
- ((MainActivity) getActivity()).showSnackbarAbovePlayer(R.string.queue_unlocked, Snackbar.LENGTH_SHORT);
+ if (queue.size() == 0) {
+ if (locked) {
+ ((MainActivity) getActivity()).showSnackbarAbovePlayer(R.string.queue_locked, Snackbar.LENGTH_SHORT);
+ } else {
+ ((MainActivity) getActivity()).showSnackbarAbovePlayer(R.string.queue_unlocked, Snackbar.LENGTH_SHORT);
+ }
}
}
@@ -572,7 +570,7 @@ public class QueueFragment extends Fragment {
// we need to refresh the options menu because it sometimes
// needs data that may have just been loaded.
- getActivity().supportInvalidateOptionsMenu();
+ getActivity().invalidateOptionsMenu();
refreshInfoBar();
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java
index ddcf09992..ca9fba694 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java
@@ -1,8 +1,13 @@
package de.danoeh.antennapod.fragment;
import android.os.Bundle;
+
+import androidx.annotation.NonNull;
import androidx.fragment.app.ListFragment;
import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
import android.widget.Toast;
@@ -21,10 +26,13 @@ import de.danoeh.antennapod.core.event.DownloaderUpdate;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadRequest;
+import de.danoeh.antennapod.core.service.download.DownloadService;
import de.danoeh.antennapod.core.service.download.Downloader;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.DownloadRequester;
+import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
+import de.danoeh.antennapod.menuhandler.MenuItemUtils;
import de.danoeh.antennapod.view.EmptyViewHandler;
import org.greenrobot.eventbus.ThreadMode;
@@ -38,6 +46,8 @@ public class RunningDownloadsFragment extends ListFragment {
private DownloadlistAdapter adapter;
private List<Downloader> downloaderList = new ArrayList<>();
+ private boolean isUpdatingFeeds = false;
+
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
@@ -66,6 +76,12 @@ public class RunningDownloadsFragment extends ListFragment {
}
@Override
+ public void onResume() {
+ super.onResume();
+ setHasOptionsMenu(true);
+ }
+
+ @Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
@@ -77,6 +93,33 @@ public class RunningDownloadsFragment extends ListFragment {
setListAdapter(null);
}
+ @Override
+ public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
+ super.onCreateOptionsMenu(menu, inflater);
+ inflater.inflate(R.menu.downloads_running, menu);
+ isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == R.id.refresh_item) {
+ AutoUpdateManager.runImmediate(requireContext());
+ return true;
+ }
+ return false;
+ }
+
+ @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
+ public void onEventMainThread(DownloadEvent event) {
+ Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
+ if (event.hasChangedFeedUpdateStatus(isUpdatingFeeds)) {
+ getActivity().invalidateOptionsMenu();
+ }
+ }
+
+ private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker =
+ () -> DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds();
+
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(DownloadEvent event) {
Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]");
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java
index 0d33c1282..0c03d407e 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java
@@ -124,7 +124,6 @@ public class SearchFragment extends Fragment {
LinearLayoutManager layoutManagerFeeds = new LinearLayoutManager(getActivity());
layoutManagerFeeds.setOrientation(RecyclerView.HORIZONTAL);
recyclerViewFeeds.setLayoutManager(layoutManagerFeeds);
- recyclerViewFeeds.setHasFixedSize(true);
adapterFeeds = new FeedSearchResultAdapter((MainActivity) getActivity());
recyclerViewFeeds.setAdapter(adapterFeeds);
@@ -174,7 +173,7 @@ public class SearchFragment extends Fragment {
@Override
public boolean onMenuItemActionCollapse(MenuItem item) {
- getFragmentManager().popBackStack();
+ getParentFragmentManager().popBackStack();
return true;
}
});
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java
index ba5d44b4d..3837c5025 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java
@@ -19,8 +19,10 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.GridView;
+import android.widget.TextView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
+import com.joanzapata.iconify.Iconify;
import java.util.concurrent.Callable;
@@ -34,6 +36,7 @@ import de.danoeh.antennapod.core.event.FeedListUpdateEvent;
import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadService;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.storage.DBReader;
@@ -42,6 +45,8 @@ import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
+import de.danoeh.antennapod.dialog.FeedFilterDialog;
+import de.danoeh.antennapod.dialog.FeedSortDialog;
import de.danoeh.antennapod.dialog.RenameFeedDialog;
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
import de.danoeh.antennapod.view.EmptyViewHandler;
@@ -68,6 +73,7 @@ public class SubscriptionFragment extends Fragment {
private FloatingActionButton subscriptionAddButton;
private ProgressBar progressBar;
private EmptyViewHandler emptyView;
+ private TextView feedsFilteredMsg;
private int mPosition = -1;
private boolean isUpdatingFeeds = false;
@@ -90,10 +96,13 @@ public class SubscriptionFragment extends Fragment {
View root = inflater.inflate(R.layout.fragment_subscriptions, container, false);
((AppCompatActivity) getActivity()).setSupportActionBar(root.findViewById(R.id.toolbar));
subscriptionGridLayout = root.findViewById(R.id.subscriptions_grid);
- subscriptionGridLayout.setNumColumns(prefs.getInt(PREF_NUM_COLUMNS, 3));
+ subscriptionGridLayout.setNumColumns(prefs.getInt(PREF_NUM_COLUMNS, getDefaultNumOfColumns()));
registerForContextMenu(subscriptionGridLayout);
subscriptionAddButton = root.findViewById(R.id.subscriptions_add);
progressBar = root.findViewById(R.id.progLoading);
+
+ feedsFilteredMsg = root.findViewById(R.id.feeds_filtered_message);
+ feedsFilteredMsg.setOnClickListener((l) -> FeedFilterDialog.showDialog(requireContext()));
return root;
}
@@ -102,7 +111,7 @@ public class SubscriptionFragment extends Fragment {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.subscriptions, menu);
- int columns = prefs.getInt(PREF_NUM_COLUMNS, 3);
+ int columns = prefs.getInt(PREF_NUM_COLUMNS, getDefaultNumOfColumns());
menu.findItem(R.id.subscription_num_columns_2).setChecked(columns == 2);
menu.findItem(R.id.subscription_num_columns_3).setChecked(columns == 3);
menu.findItem(R.id.subscription_num_columns_4).setChecked(columns == 4);
@@ -120,6 +129,12 @@ public class SubscriptionFragment extends Fragment {
case R.id.refresh_item:
AutoUpdateManager.runImmediate(requireContext());
return true;
+ case R.id.subscriptions_filter:
+ FeedFilterDialog.showDialog(requireContext());
+ return true;
+ case R.id.subscriptions_sort:
+ FeedSortDialog.showDialog(requireContext());
+ return true;
case R.id.subscription_num_columns_2:
setColumnNumber(2);
return true;
@@ -198,6 +213,18 @@ public class SubscriptionFragment extends Fragment {
emptyView.updateVisibility();
progressBar.setVisibility(View.GONE);
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
+
+ if (UserPreferences.getFeedFilter() != UserPreferences.FEED_FILTER_NONE) {
+ feedsFilteredMsg.setText("{md-info-outline} " + getString(R.string.subscriptions_are_filtered));
+ Iconify.addIcons(feedsFilteredMsg);
+ feedsFilteredMsg.setVisibility(View.VISIBLE);
+ } else {
+ feedsFilteredMsg.setVisibility(View.GONE);
+ }
+ }
+
+ private int getDefaultNumOfColumns() {
+ return getResources().getInteger(R.integer.subscriptions_default_num_of_columns);
}
@Override
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java
index e1c85a2d3..d5cac07f1 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java
@@ -56,9 +56,9 @@ public abstract class PodcastListFragment extends Fragment {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.gpodder_podcasts, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
- final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
+ final SearchView sv = (SearchView) searchItem.getActionView();
sv.setQueryHint(getString(R.string.gpodnet_search_hint));
- sv.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
+ sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String s) {
sv.clearFocus();
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java
index 80f1a6ae0..72a752bf1 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java
@@ -48,7 +48,7 @@ public class SearchListFragment extends PodcastListFragment {
super.onCreateOptionsMenu(menu, inflater);
// parent already inflated menu
MenuItem searchItem = menu.findItem(R.id.action_search);
- final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
+ final SearchView sv = (SearchView) searchItem.getActionView();
sv.setQueryHint(getString(R.string.gpodnet_search_hint));
sv.setQuery(query, false);
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java
index a7a0781ce..53a31b68d 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java
@@ -38,7 +38,7 @@ public class TagListFragment extends ListFragment {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.gpodder_podcasts, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
- final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
+ final SearchView sv = (SearchView) searchItem.getActionView();
sv.setQueryHint(getString(R.string.gpodnet_search_hint));
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AboutFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AboutFragment.java
index 0fa7bd4bb..eb57972a1 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AboutFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AboutFragment.java
@@ -28,12 +28,12 @@ public class AboutFragment extends PreferenceFragmentCompat {
return true;
});
findPreference("about_developers").setOnPreferenceClickListener((preference) -> {
- getFragmentManager().beginTransaction().replace(R.id.content, new AboutDevelopersFragment())
+ getParentFragmentManager().beginTransaction().replace(R.id.content, new AboutDevelopersFragment())
.addToBackStack(getString(R.string.developers)).commit();
return true;
});
findPreference("about_translators").setOnPreferenceClickListener((preference) -> {
- getFragmentManager().beginTransaction().replace(R.id.content, new AboutTranslatorsFragment())
+ getParentFragmentManager().beginTransaction().replace(R.id.content, new AboutTranslatorsFragment())
.addToBackStack(getString(R.string.translators)).commit();
return true;
});
@@ -42,7 +42,7 @@ public class AboutFragment extends PreferenceFragmentCompat {
return true;
});
findPreference("about_licenses").setOnPreferenceClickListener((preference) -> {
- getFragmentManager().beginTransaction().replace(R.id.content, new AboutLicensesFragment())
+ getParentFragmentManager().beginTransaction().replace(R.id.content, new AboutLicensesFragment())
.addToBackStack(getString(R.string.translators)).commit();
return true;
});
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AutoDownloadPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AutoDownloadPreferencesFragment.java
index 6b15e4301..064c4b3bc 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AutoDownloadPreferencesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AutoDownloadPreferencesFragment.java
@@ -1,5 +1,6 @@
package de.danoeh.antennapod.fragment.preferences;
+import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
@@ -85,6 +86,7 @@ public class AutoDownloadPreferencesFragment extends PreferenceFragmentCompat {
return val == null ? "" : val;
}
+ @SuppressLint("MissingPermission") // getConfiguredNetworks needs location permission starting with API 29
private void buildAutodownloadSelectedNetworksPreference() {
if (Build.VERSION.SDK_INT >= 29) {
return;
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderPreferencesFragment.java
index 8f8b4675d..546e12e65 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderPreferencesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderPreferencesFragment.java
@@ -3,9 +3,11 @@ package de.danoeh.antennapod.fragment.preferences;
import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
+import androidx.core.text.HtmlCompat;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
-import android.text.Html;
+
+import android.text.Spanned;
import android.text.format.DateUtils;
import android.widget.Toast;
import com.google.android.material.snackbar.Snackbar;
@@ -115,7 +117,8 @@ public class GpodderPreferencesFragment extends PreferenceFragmentCompat {
String format = getActivity().getString(R.string.pref_gpodnet_login_status);
String summary = String.format(format, GpodnetPreferences.getUsername(),
GpodnetPreferences.getDeviceID());
- findPreference(PREF_GPODNET_LOGOUT).setSummary(Html.fromHtml(summary));
+ Spanned formattedSummary = HtmlCompat.fromHtml(summary, HtmlCompat.FROM_HTML_MODE_LEGACY);
+ findPreference(PREF_GPODNET_LOGOUT).setSummary(formattedSummary);
updateLastGpodnetSyncReport(SyncService.isLastSyncSuccessful(getContext()),
SyncService.getLastSyncAttempt(getContext()));
} else {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/ImportExportPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/ImportExportPreferencesFragment.java
index f3b4d3003..5eb4a3aea 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/ImportExportPreferencesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/ImportExportPreferencesFragment.java
@@ -38,6 +38,7 @@ import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
+import java.util.Locale;
public class ImportExportPreferencesFragment extends PreferenceFragmentCompat {
private static final String TAG = "ImportExPrefFragment";
@@ -86,9 +87,7 @@ public class ImportExportPreferencesFragment extends PreferenceFragmentCompat {
}
private String dateStampFilename(String fname) {
- return String.format(fname,
- new SimpleDateFormat("yyyy-MM-dd")
- .format(new Date()));
+ return String.format(fname, new SimpleDateFormat("yyyy-MM-dd", Locale.US).format(new Date()));
}
private void setupStorageScreen() {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/MainPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/MainPreferencesFragment.java
index 406585808..3f1cec729 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/MainPreferencesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/MainPreferencesFragment.java
@@ -22,6 +22,7 @@ public class MainPreferencesFragment extends PreferenceFragmentCompat {
private static final String PREF_FAQ = "prefFaq";
private static final String PREF_VIEW_FORUM = "prefViewForum";
private static final String PREF_SEND_BUG_REPORT = "prefSendBugReport";
+ private static final String PREF_CATEGORY_PROJECT = "project";
private static final String STATISTICS = "statistics";
private static final String PREF_ABOUT = "prefAbout";
@@ -30,6 +31,13 @@ public class MainPreferencesFragment extends PreferenceFragmentCompat {
addPreferencesFromResource(R.xml.preferences);
setupMainScreen();
setupSearch();
+
+ // If you are writing a spin-off, please update the details on screens like "About" and "Report bug"
+ // and afterwards remove the following lines.
+ String packageName = getContext().getPackageName();
+ if (!"de.danoeh.antennapod".equals(packageName) && !"de.danoeh.antennapod.debug".equals(packageName)) {
+ findPreference(PREF_CATEGORY_PROJECT).setVisible(false);
+ }
}
@Override
@@ -62,14 +70,14 @@ public class MainPreferencesFragment extends PreferenceFragmentCompat {
findPreference(PREF_ABOUT).setOnPreferenceClickListener(
preference -> {
- getFragmentManager().beginTransaction().replace(R.id.content, new AboutFragment())
+ getParentFragmentManager().beginTransaction().replace(R.id.content, new AboutFragment())
.addToBackStack(getString(R.string.about_pref)).commit();
return true;
}
);
findPreference(STATISTICS).setOnPreferenceClickListener(
preference -> {
- getFragmentManager().beginTransaction().replace(R.id.content, new StatisticsFragment())
+ getParentFragmentManager().beginTransaction().replace(R.id.content, new StatisticsFragment())
.addToBackStack(getString(R.string.statistics_label)).commit();
return true;
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/PlaybackPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/PlaybackPreferencesFragment.java
index 741080cf1..f07e59afe 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/PlaybackPreferencesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/PlaybackPreferencesFragment.java
@@ -45,7 +45,7 @@ public class PlaybackPreferencesFragment extends PreferenceFragmentCompat {
final Activity activity = getActivity();
findPreference(PREF_PLAYBACK_SPEED_LAUNCHER).setOnPreferenceClickListener(preference -> {
- VariableSpeedDialog.showDialog(activity);
+ new VariableSpeedDialog().show(getChildFragmentManager(), null);
return true;
});
findPreference(PREF_PLAYBACK_REWIND_DELTA_LAUNCHER).setOnPreferenceClickListener(preference -> {
@@ -116,7 +116,7 @@ public class PlaybackPreferencesFragment extends PreferenceFragmentCompat {
if(x == 0) {
entries[x] = res.getString(R.string.pref_smart_mark_as_played_disabled);
} else {
- Integer v = Integer.parseInt(values[x]);
+ int v = Integer.parseInt(values[x]);
if(v < 60) {
entries[x] = res.getQuantityString(R.plurals.time_seconds_quantified, v, v);
} else {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java
index a44623f48..12be76ba7 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java
@@ -12,6 +12,8 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.activity.PreferenceActivity;
import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.dialog.FeedFilterDialog;
+import de.danoeh.antennapod.dialog.FeedSortDialog;
import de.danoeh.antennapod.fragment.NavDrawerFragment;
import org.apache.commons.lang3.ArrayUtils;
@@ -75,6 +77,18 @@ public class UserInterfacePreferencesFragment extends PreferenceFragmentCompat {
return true;
});
+ findPreference(UserPreferences.PREF_FILTER_FEED)
+ .setOnPreferenceClickListener((preference -> {
+ FeedFilterDialog.showDialog(requireContext());
+ return true;
+ }));
+
+ findPreference(UserPreferences.PREF_DRAWER_FEED_ORDER)
+ .setOnPreferenceClickListener((preference -> {
+ FeedSortDialog.showDialog(requireContext());
+ return true;
+ }));
+
if (Build.VERSION.SDK_INT >= 26) {
findPreference(UserPreferences.PREF_EXPANDED_NOTIFICATION).setVisible(false);
}
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 1f15f66ec..bddafb75e 100644
--- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
+++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
@@ -2,13 +2,14 @@ package de.danoeh.antennapod.menuhandler;
import android.content.Context;
import android.os.Handler;
-import androidx.annotation.NonNull;
-import com.google.android.material.snackbar.Snackbar;
-import androidx.fragment.app.Fragment;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
+import com.google.android.material.snackbar.Snackbar;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.feed.FeedItem;
@@ -23,6 +24,7 @@ import de.danoeh.antennapod.core.sync.model.EpisodeAction;
import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.ShareUtils;
+import de.danoeh.antennapod.dialog.ShareDialog;
/**
* Handles interactions with the FeedItemMenu.
@@ -61,20 +63,9 @@ public class FeedItemMenuHandler {
}
if (!ShareUtils.hasLinkToShare(selectedItem)) {
setItemVisibility(menu, R.id.visit_website_item, false);
- setItemVisibility(menu, R.id.share_link_item, false);
- setItemVisibility(menu, R.id.share_link_with_position_item, false);
- }
- if (!hasMedia || selectedItem.getMedia().getDownload_url() == null) {
- setItemVisibility(menu, R.id.share_download_url_item, false);
- setItemVisibility(menu, R.id.share_download_url_with_position_item, false);
- }
- if(!hasMedia || selectedItem.getMedia().getPosition() <= 0) {
- setItemVisibility(menu, R.id.share_download_url_with_position_item, false);
- setItemVisibility(menu, R.id.share_link_with_position_item, false);
}
boolean fileDownloaded = hasMedia && selectedItem.getMedia().fileExists();
- setItemVisibility(menu, R.id.share_file, fileDownloaded);
setItemVisibility(menu, R.id.remove_new_flag_item, selectedItem.isNew());
if (selectedItem.isPlayed()) {
@@ -243,20 +234,9 @@ public class FeedItemMenuHandler {
case R.id.visit_website_item:
IntentUtils.openInBrowser(context, FeedItemUtil.getLinkWithFallback(selectedItem));
break;
- case R.id.share_link_item:
- ShareUtils.shareFeedItemLink(context, selectedItem);
- break;
- case R.id.share_download_url_item:
- ShareUtils.shareFeedItemDownloadLink(context, selectedItem);
- break;
- case R.id.share_link_with_position_item:
- ShareUtils.shareFeedItemLink(context, selectedItem, true);
- break;
- case R.id.share_download_url_with_position_item:
- ShareUtils.shareFeedItemDownloadLink(context, selectedItem, true);
- break;
- case R.id.share_file:
- ShareUtils.shareFeedItemFile(context, selectedItem.getMedia());
+ case R.id.share_item:
+ ShareDialog shareDialog = ShareDialog.newInstance(selectedItem);
+ shareDialog.show((fragment.getActivity().getSupportFragmentManager()), "ShareEpisodeDialog");
break;
default:
Log.d(TAG, "Unknown menuItemId: " + menuItemId);
diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/MasterSwitchPreference.java b/app/src/main/java/de/danoeh/antennapod/preferences/MasterSwitchPreference.java
index 007457c24..94e60ef61 100644
--- a/app/src/main/java/de/danoeh/antennapod/preferences/MasterSwitchPreference.java
+++ b/app/src/main/java/de/danoeh/antennapod/preferences/MasterSwitchPreference.java
@@ -4,7 +4,7 @@ import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Typeface;
import android.os.Build;
-import androidx.preference.SwitchPreference;
+import androidx.preference.SwitchPreferenceCompat;
import androidx.preference.PreferenceViewHolder;
import android.util.AttributeSet;
import android.util.TypedValue;
@@ -12,7 +12,7 @@ import android.widget.TextView;
import de.danoeh.antennapod.R;
-public class MasterSwitchPreference extends SwitchPreference {
+public class MasterSwitchPreference extends SwitchPreferenceCompat {
public MasterSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java
index 367593131..2a157c23b 100644
--- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java
+++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java
@@ -2,7 +2,7 @@ package de.danoeh.antennapod.preferences;
import android.content.Context;
import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
+import androidx.preference.PreferenceManager;
import de.danoeh.antennapod.BuildConfig;
import de.danoeh.antennapod.CrashReportWriter;
diff --git a/app/src/main/java/de/danoeh/antennapod/spa/SPAUtil.java b/app/src/main/java/de/danoeh/antennapod/spa/SPAUtil.java
index 1f28b5c49..f9c10041e 100644
--- a/app/src/main/java/de/danoeh/antennapod/spa/SPAUtil.java
+++ b/app/src/main/java/de/danoeh/antennapod/spa/SPAUtil.java
@@ -3,7 +3,7 @@ package de.danoeh.antennapod.spa;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
+import androidx.preference.PreferenceManager;
import android.util.Log;
import de.danoeh.antennapod.BuildConfig;
diff --git a/app/src/main/java/de/danoeh/antennapod/view/EpisodeItemListRecyclerView.java b/app/src/main/java/de/danoeh/antennapod/view/EpisodeItemListRecyclerView.java
index 58d562616..83d90f98b 100644
--- a/app/src/main/java/de/danoeh/antennapod/view/EpisodeItemListRecyclerView.java
+++ b/app/src/main/java/de/danoeh/antennapod/view/EpisodeItemListRecyclerView.java
@@ -2,6 +2,7 @@ package de.danoeh.antennapod.view;
import android.content.Context;
import android.content.SharedPreferences;
+import android.content.res.Configuration;
import android.util.AttributeSet;
import android.view.View;
import androidx.appcompat.view.ContextThemeWrapper;
@@ -39,6 +40,14 @@ public class EpisodeItemListRecyclerView extends RecyclerView {
setLayoutManager(layoutManager);
setHasFixedSize(true);
addItemDecoration(new HorizontalDividerItemDecoration.Builder(getContext()).build());
+ setClipToPadding(false);
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ int horizontalSpacing = (int) getResources().getDimension(R.dimen.additional_horizontal_spacing);
+ setPadding(horizontalSpacing, getPaddingTop(), horizontalSpacing, getPaddingBottom());
}
public void saveScrollPosition(String tag) {
diff --git a/app/src/main/java/de/danoeh/antennapod/view/ItemOffsetDecoration.java b/app/src/main/java/de/danoeh/antennapod/view/ItemOffsetDecoration.java
new file mode 100644
index 000000000..4a1267d81
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/view/ItemOffsetDecoration.java
@@ -0,0 +1,24 @@
+package de.danoeh.antennapod.view;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.view.View;
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+/**
+ * Source: https://stackoverflow.com/a/30794046
+ */
+public class ItemOffsetDecoration extends RecyclerView.ItemDecoration {
+ private final int itemOffset;
+
+ public ItemOffsetDecoration(@NonNull Context context, int itemOffsetDp) {
+ itemOffset = (int) (itemOffsetDp * context.getResources().getDisplayMetrics().density);
+ }
+
+ @Override
+ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
+ super.getItemOffsets(outRect, view, parent, state);
+ outRect.set(itemOffset, itemOffset, itemOffset, itemOffset);
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/view/NestedScrollableHost.java b/app/src/main/java/de/danoeh/antennapod/view/NestedScrollableHost.java
index a4daa9109..0e1846f1c 100644
--- a/app/src/main/java/de/danoeh/antennapod/view/NestedScrollableHost.java
+++ b/app/src/main/java/de/danoeh/antennapod/view/NestedScrollableHost.java
@@ -54,7 +54,7 @@ class NestedScrollableHost extends FrameLayout {
touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}
- private int touchSlop = 0;
+ private int touchSlop;
private float initialX = 0f;
private float initialY = 0f;
diff --git a/app/src/main/java/de/danoeh/antennapod/view/PlaybackSpeedSeekBar.java b/app/src/main/java/de/danoeh/antennapod/view/PlaybackSpeedSeekBar.java
new file mode 100644
index 000000000..47797e4a4
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/view/PlaybackSpeedSeekBar.java
@@ -0,0 +1,86 @@
+package de.danoeh.antennapod.view;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.SeekBar;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.util.Consumer;
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.util.playback.PlaybackController;
+import de.danoeh.antennapod.dialog.VariableSpeedDialog;
+
+public class PlaybackSpeedSeekBar extends FrameLayout {
+ private SeekBar seekBar;
+ private PlaybackController controller;
+ private Consumer<Float> progressChangedListener;
+
+ public PlaybackSpeedSeekBar(@NonNull Context context) {
+ super(context);
+ setup();
+ }
+
+ public PlaybackSpeedSeekBar(@NonNull Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ setup();
+ }
+
+ public PlaybackSpeedSeekBar(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ setup();
+ }
+
+ private void setup() {
+ View.inflate(getContext(), R.layout.playback_speed_seek_bar, this);
+ seekBar = findViewById(R.id.playback_speed);
+ findViewById(R.id.butDecSpeed).setOnClickListener(v -> seekBar.setProgress(seekBar.getProgress() - 2));
+ findViewById(R.id.butIncSpeed).setOnClickListener(v -> seekBar.setProgress(seekBar.getProgress() + 2));
+
+ seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if (controller != null && controller.canSetPlaybackSpeed()) {
+ float playbackSpeed = (progress + 10) / 20.0f;
+ controller.setPlaybackSpeed(playbackSpeed);
+
+ if (progressChangedListener != null) {
+ progressChangedListener.accept(playbackSpeed);
+ }
+ } else if (fromUser) {
+ seekBar.post(() -> updateSpeed());
+ }
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ if (controller != null && !controller.canSetPlaybackSpeed()) {
+ VariableSpeedDialog.showGetPluginDialog(getContext());
+ }
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+ });
+ }
+
+ public void updateSpeed() {
+ if (controller != null) {
+ seekBar.setProgress(Math.round((20 * controller.getCurrentPlaybackSpeedMultiplier()) - 10));
+ }
+ }
+
+ public void setController(PlaybackController controller) {
+ this.controller = controller;
+ updateSpeed();
+ if (progressChangedListener != null && controller != null) {
+ progressChangedListener.accept(controller.getCurrentPlaybackSpeedMultiplier());
+ }
+ }
+
+ public void setProgressChangedListener(Consumer<Float> progressChangedListener) {
+ this.progressChangedListener = progressChangedListener;
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/view/RecursiveRadioGroup.java b/app/src/main/java/de/danoeh/antennapod/view/RecursiveRadioGroup.java
new file mode 100644
index 000000000..ee5e7c51d
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/view/RecursiveRadioGroup.java
@@ -0,0 +1,67 @@
+package de.danoeh.antennapod.view;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.RadioButton;
+import java.util.ArrayList;
+
+/**
+ * An alternative to {@link android.widget.RadioGroup} that allows to nest children.
+ * Basend on https://stackoverflow.com/a/14309274.
+ */
+public class RecursiveRadioGroup extends LinearLayout {
+ private final ArrayList<RadioButton> radioButtons = new ArrayList<>();
+ private RadioButton checkedButton = null;
+
+ public RecursiveRadioGroup(Context context) {
+ super(context);
+ }
+
+ public RecursiveRadioGroup(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public RecursiveRadioGroup(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ public void addView(View child, int index, ViewGroup.LayoutParams params) {
+ super.addView(child, index, params);
+ parseChild(child);
+ }
+
+ public void parseChild(final View child) {
+ if (child instanceof RadioButton) {
+ RadioButton button = (RadioButton) child;
+ radioButtons.add(button);
+ button.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ if (!isChecked) {
+ return;
+ }
+ checkedButton = (RadioButton) buttonView;
+
+ for (RadioButton view : radioButtons) {
+ if (view != buttonView) {
+ view.setChecked(false);
+ }
+ }
+ });
+ } else if (child instanceof ViewGroup) {
+ parseChildren((ViewGroup) child);
+ }
+ }
+
+ public void parseChildren(final ViewGroup child) {
+ for (int i = 0; i < child.getChildCount(); i++) {
+ parseChild(child.getChildAt(i));
+ }
+ }
+
+ public RadioButton getCheckedButton() {
+ return checkedButton;
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/view/ToolbarIconTintManager.java b/app/src/main/java/de/danoeh/antennapod/view/ToolbarIconTintManager.java
index dcf8ff20d..163100fff 100644
--- a/app/src/main/java/de/danoeh/antennapod/view/ToolbarIconTintManager.java
+++ b/app/src/main/java/de/danoeh/antennapod/view/ToolbarIconTintManager.java
@@ -33,11 +33,15 @@ public abstract class ToolbarIconTintManager implements AppBarLayout.OnOffsetCha
public void updateTint() {
if (isTinted) {
doTint(new ContextThemeWrapper(context, R.style.Theme_AntennaPod_Dark));
- toolbar.getNavigationIcon().setColorFilter(0xffffffff, PorterDuff.Mode.SRC_ATOP);
+ if (toolbar.getNavigationIcon() != null) { // Tablets do not show a navigation icon
+ toolbar.getNavigationIcon().setColorFilter(0xffffffff, PorterDuff.Mode.SRC_ATOP);
+ }
toolbar.getOverflowIcon().setColorFilter(0xffffffff, PorterDuff.Mode.SRC_ATOP);
} else {
doTint(context);
- toolbar.getNavigationIcon().clearColorFilter();
+ if (toolbar.getNavigationIcon() != null) { // Tablets do not show a navigation icon
+ toolbar.getNavigationIcon().clearColorFilter();
+ }
toolbar.getOverflowIcon().clearColorFilter();
}
}
diff --git a/app/src/main/res/layout-sw720dp/main.xml b/app/src/main/res/layout-sw720dp/main.xml
new file mode 100644
index 000000000..79b7213e0
--- /dev/null
+++ b/app/src/main/res/layout-sw720dp/main.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <FrameLayout
+ android:id="@+id/navDrawerFragment"
+ android:layout_width="300dp"
+ android:layout_height="match_parent"
+ android:layout_gravity="start"
+ android:orientation="vertical" />
+
+ <View
+ android:layout_width="1dp"
+ android:layout_height="match_parent"
+ android:background="?android:attr/listDivider" />
+
+ <androidx.coordinatorlayout.widget.CoordinatorLayout
+ android:id="@+id/overview_coordinator_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <FrameLayout
+ android:id="@+id/main_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentTop="true"
+ android:foreground="?android:windowContentOverlay"
+ tools:background="@android:color/holo_red_dark" />
+
+ <FrameLayout
+ android:elevation="8dp"
+ android:id="@+id/audioplayerFragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="?android:attr/windowBackground"
+ android:visibility="gone"
+ app:layout_behavior="de.danoeh.antennapod.view.LockableBottomSheetBehavior" />
+
+ </androidx.coordinatorlayout.widget.CoordinatorLayout>
+
+</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/addfeed.xml b/app/src/main/res/layout/addfeed.xml
index 9d14d209a..ff0a54bc1 100644
--- a/app/src/main/res/layout/addfeed.xml
+++ b/app/src/main/res/layout/addfeed.xml
@@ -71,7 +71,7 @@
android:focusableInTouchMode="true"
android:padding="16dp">
- <fragment
+ <androidx.fragment.app.FragmentContainerView
android:id="@+id/quickFeedDiscovery"
android:name="de.danoeh.antennapod.fragment.QuickFeedDiscoveryFragment"
android:layout_width="match_parent"
@@ -91,8 +91,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawablePadding="8dp"
- app:drawableStartCompat="?attr/content_new"
- app:drawableLeftCompat="?attr/content_new"
+ app:drawableStartCompat="?attr/feed"
+ app:drawableLeftCompat="?attr/feed"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:background="?android:attr/selectableItemBackground"
diff --git a/app/src/main/res/layout/all_episodes_fragment.xml b/app/src/main/res/layout/all_episodes_fragment.xml
index 73f061a0f..353e4f1d0 100644
--- a/app/src/main/res/layout/all_episodes_fragment.xml
+++ b/app/src/main/res/layout/all_episodes_fragment.xml
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
@@ -24,9 +23,9 @@
android:layout_below="@+id/txtvInformation"
android:layout_marginTop="0dp"
android:layout_marginBottom="0dp"
- android:clipToPadding="false"
android:paddingTop="@dimen/list_vertical_padding"
android:paddingBottom="@dimen/list_vertical_padding"
+ android:paddingHorizontal="@dimen/additional_horizontal_spacing"
android:layout_above="@id/loadingMore"
tools:itemCount="13"
tools:listitem="@layout/feeditemlist_item" />
diff --git a/app/src/main/res/layout/audio_controls.xml b/app/src/main/res/layout/audio_controls.xml
index aa1bdf236..2c9665aad 100644
--- a/app/src/main/res/layout/audio_controls.xml
+++ b/app/src/main/res/layout/audio_controls.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -38,47 +39,10 @@
</LinearLayout>
- <LinearLayout
+ <de.danoeh.antennapod.view.PlaybackSpeedSeekBar
+ android:id="@+id/speed_seek_bar"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:gravity="center_vertical">
-
- <TextView
- android:id="@+id/butDecSpeed"
- android:layout_width="32dp"
- android:layout_height="32dp"
- android:gravity="center"
- android:text="-"
- android:clickable="true"
- android:focusable="true"
- android:textStyle="bold"
- android:textSize="24sp"
- android:textColor="?attr/colorSecondary"
- android:contentDescription="@string/decrease_speed"
- android:background="?attr/selectableItemBackgroundBorderless"/>
-
- <SeekBar
- android:id="@+id/playback_speed"
- android:layout_width="0dp"
- android:layout_height="32dp"
- android:max="70"
- android:layout_weight="1" />
-
- <TextView
- android:id="@+id/butIncSpeed"
- android:layout_width="32dp"
- android:layout_height="32dp"
- android:gravity="center"
- android:text="+"
- android:clickable="true"
- android:focusable="true"
- android:textStyle="bold"
- android:textSize="24sp"
- android:textColor="?attr/colorSecondary"
- android:contentDescription="@string/increase_speed"
- android:background="?attr/selectableItemBackgroundBorderless" />
- </LinearLayout>
+ android:layout_height="wrap_content"/>
<TextView
android:layout_width="wrap_content"
diff --git a/app/src/main/res/layout/audioplayer_fragment.xml b/app/src/main/res/layout/audioplayer_fragment.xml
index 5b4e26b69..1c2866a1b 100644
--- a/app/src/main/res/layout/audioplayer_fragment.xml
+++ b/app/src/main/res/layout/audioplayer_fragment.xml
@@ -184,7 +184,7 @@
android:layout_toStartOf="@id/butRev"
android:layout_centerVertical="true"
android:background="?attr/selectableItemBackgroundBorderless"
- android:contentDescription="@string/set_playback_speed_label"
+ android:contentDescription="@string/playback_speed"
tools:srcCompat="@drawable/ic_playback_speed_white"/>
<TextView
diff --git a/app/src/main/res/layout/choose_data_folder_dialog_entry.xml b/app/src/main/res/layout/choose_data_folder_dialog_entry.xml
index ae59c0614..addc63f4d 100644
--- a/app/src/main/res/layout/choose_data_folder_dialog_entry.xml
+++ b/app/src/main/res/layout/choose_data_folder_dialog_entry.xml
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root"
android:layout_width="match_parent"
diff --git a/app/src/main/res/layout/cover_fragment.xml b/app/src/main/res/layout/cover_fragment.xml
index 443f19835..a66a5f5d7 100644
--- a/app/src/main/res/layout/cover_fragment.xml
+++ b/app/src/main/res/layout/cover_fragment.xml
@@ -12,7 +12,7 @@
<de.danoeh.antennapod.view.SquareImageView
android:id="@+id/imgvCover"
- android:layout_width="200dp"
+ android:layout_width="0dp"
android:layout_height="200dp"
android:layout_gravity="center"
android:layout_marginLeft="64dp"
diff --git a/app/src/main/res/layout/downloadlog_item.xml b/app/src/main/res/layout/downloadlog_item.xml
index dd8328c8c..5cde763a0 100644
--- a/app/src/main/res/layout/downloadlog_item.xml
+++ b/app/src/main/res/layout/downloadlog_item.xml
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
- xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
diff --git a/app/src/main/res/layout/empty_view_layout.xml b/app/src/main/res/layout/empty_view_layout.xml
index 768f74c41..da2040d93 100644
--- a/app/src/main/res/layout/empty_view_layout.xml
+++ b/app/src/main/res/layout/empty_view_layout.xml
@@ -1,6 +1,5 @@
<?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"
diff --git a/app/src/main/res/layout/feed_item_list_fragment.xml b/app/src/main/res/layout/feed_item_list_fragment.xml
index d6c7409a8..b995ff28f 100644
--- a/app/src/main/res/layout/feed_item_list_fragment.xml
+++ b/app/src/main/res/layout/feed_item_list_fragment.xml
@@ -52,6 +52,7 @@
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:paddingHorizontal="@dimen/additional_horizontal_spacing"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<ProgressBar
diff --git a/app/src/main/res/layout/feedinfo.xml b/app/src/main/res/layout/feedinfo.xml
index fa6aac251..dd349c15c 100644
--- a/app/src/main/res/layout/feedinfo.xml
+++ b/app/src/main/res/layout/feedinfo.xml
@@ -62,6 +62,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:id="@+id/infoContainer"
+ android:paddingHorizontal="@dimen/additional_horizontal_spacing"
android:orientation="vertical">
<TextView
diff --git a/app/src/main/res/layout/feeditemlist_header.xml b/app/src/main/res/layout/feeditemlist_header.xml
index e74aeac0a..a8845ec27 100644
--- a/app/src/main/res/layout/feeditemlist_header.xml
+++ b/app/src/main/res/layout/feeditemlist_header.xml
@@ -5,6 +5,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:id="@+id/headerContainer"
+ android:paddingHorizontal="@dimen/additional_horizontal_spacing"
android:orientation="vertical">
<LinearLayout
diff --git a/app/src/main/res/layout/filter_dialog.xml b/app/src/main/res/layout/filter_dialog.xml
new file mode 100644
index 000000000..39e9258d9
--- /dev/null
+++ b/app/src/main/res/layout/filter_dialog.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingLeft="24dp"
+ android:paddingTop="24dp"
+ android:paddingRight="24dp"
+ android:paddingBottom="8dp">
+
+</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/filter_dialog_row.xml b/app/src/main/res/layout/filter_dialog_row.xml
new file mode 100644
index 000000000..0863997b3
--- /dev/null
+++ b/app/src/main/res/layout/filter_dialog_row.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<de.danoeh.antennapod.view.RecursiveRadioGroup
+ 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:paddingBottom="8dp"
+ android:orientation="horizontal">
+
+ <androidx.cardview.widget.CardView
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:clipChildren="true"
+ app:cardCornerRadius="32dp"
+ app:cardElevation="0dp">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
+
+ <RadioButton
+ android:id="@+id/filter_dialog_radioButton1"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_marginEnd="2dp"
+ android:layout_marginRight="2dp"
+ android:layout_weight="1"
+ android:background="?attr/filter_dialog_button_background"
+ android:button="@android:color/transparent"
+ android:foreground="?android:attr/selectableItemBackground"
+ android:checked="false"
+ android:gravity="center"
+ android:textColor="@color/filter_dialog_button_text" />
+
+ <RadioButton
+ android:id="@+id/filter_dialog_radioButton2"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:background="?attr/filter_dialog_button_background"
+ android:button="@android:color/transparent"
+ android:foreground="?android:attr/selectableItemBackground"
+ android:checked="false"
+ android:gravity="center"
+ android:textColor="@color/filter_dialog_button_text" />
+ </LinearLayout>
+ </androidx.cardview.widget.CardView>
+
+ <RadioButton
+ android:id="@+id/filter_dialog_clear"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:background="@drawable/ic_filter_close"
+ android:button="@android:color/transparent"
+ android:foreground="?android:attr/selectableItemBackground"
+ android:layout_gravity="center_vertical"
+ android:checked="true" />
+
+</de.danoeh.antennapod.view.RecursiveRadioGroup>
diff --git a/app/src/main/res/layout/fragment_itunes_search.xml b/app/src/main/res/layout/fragment_itunes_search.xml
index 228bfb803..d82051867 100644
--- a/app/src/main/res/layout/fragment_itunes_search.xml
+++ b/app/src/main/res/layout/fragment_itunes_search.xml
@@ -36,6 +36,7 @@
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:gravity="center"
+ android:visibility="gone"
android:text="@string/search_status_no_results" />
<ProgressBar
@@ -71,4 +72,17 @@
tools:visibility="visible"
tools:background="@android:color/holo_red_light" />
+ <TextView
+ android:id="@+id/search_powered_by"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="?android:attr/textColorTertiary"
+ android:text="@string/discover_powered_by_itunes"
+ android:textSize="12sp"
+ android:padding="4dp"
+ android:background="?android:attr/windowBackground"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentEnd="true"
+ android:textAlignment="textEnd"/>
</RelativeLayout>
diff --git a/app/src/main/res/layout/fragment_subscriptions.xml b/app/src/main/res/layout/fragment_subscriptions.xml
index f37a6febd..a1a5a26f2 100644
--- a/app/src/main/res/layout/fragment_subscriptions.xml
+++ b/app/src/main/res/layout/fragment_subscriptions.xml
@@ -14,8 +14,22 @@
app:title="@string/subscriptions_label"
android:id="@+id/toolbar"/>
- <GridView
+ <TextView
+ android:id="@+id/feeds_filtered_message"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
android:layout_below="@id/toolbar"
+ android:background="?android:attr/selectableItemBackground"
+ android:gravity="start"
+ android:paddingStart="8dp"
+ android:paddingTop="4dp"
+ android:paddingEnd="8dp"
+ android:paddingBottom="8dp"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textSize="@dimen/text_size_small" />
+
+ <GridView
+ android:layout_below="@id/feeds_filtered_message"
android:id="@+id/subscriptions_grid"
android:layout_width="match_parent"
android:numColumns="3"
diff --git a/app/src/main/res/layout/listview_activity.xml b/app/src/main/res/layout/listview_activity.xml
deleted file mode 100644
index b276f506c..000000000
--- a/app/src/main/res/layout/listview_activity.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <ListView
- android:id="@+id/listview"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
-
-</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/main.xml b/app/src/main/res/layout/main.xml
index 6da514b4a..48195a176 100644
--- a/app/src/main/res/layout/main.xml
+++ b/app/src/main/res/layout/main.xml
@@ -5,7 +5,9 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ tools:ignore="InconsistentLayout">
+ <!-- InconsistentLayout: Tablet layout does not have a drawer -->
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/overview_coordinator_layout"
@@ -35,8 +37,6 @@
android:id="@+id/navDrawerFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_marginEnd="24dp"
- android:layout_marginRight="24dp"
android:layout_gravity="start"
android:orientation="vertical" />
diff --git a/app/src/main/res/layout/nav_section_item.xml b/app/src/main/res/layout/nav_section_item.xml
index 45d0dff59..fb3021556 100644
--- a/app/src/main/res/layout/nav_section_item.xml
+++ b/app/src/main/res/layout/nav_section_item.xml
@@ -1,16 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
- android:layout_height="16dp"
+ android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:orientation="vertical"
- android:importantForAccessibility="no">
+ android:importantForAccessibility="no"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
- android:layout_centerVertical="true"
android:background="?android:attr/listDivider"
tools:background="@android:color/holo_red_dark"/>
-</RelativeLayout>
+
+ <TextView
+ android:id="@+id/nav_feeds_filtered_message"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="start"
+ android:paddingStart="@dimen/listitem_icon_leftpadding"
+ android:paddingTop="4dp"
+ android:paddingEnd="@dimen/listitem_icon_leftpadding"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textSize="@dimen/text_size_small" />
+</LinearLayout>
diff --git a/app/src/main/res/layout/playback_speed_seek_bar.xml b/app/src/main/res/layout/playback_speed_seek_bar.xml
new file mode 100644
index 000000000..0d3985f5a
--- /dev/null
+++ b/app/src/main/res/layout/playback_speed_seek_bar.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:gravity="center_vertical">
+
+ <TextView
+ android:id="@+id/butDecSpeed"
+ android:layout_width="32dp"
+ android:layout_height="32dp"
+ android:gravity="center"
+ android:text="-"
+ android:clickable="true"
+ android:focusable="true"
+ android:textStyle="bold"
+ android:textSize="24sp"
+ android:textColor="?attr/colorSecondary"
+ android:contentDescription="@string/decrease_speed"
+ android:background="?attr/selectableItemBackgroundBorderless"/>
+
+ <SeekBar
+ android:id="@+id/playback_speed"
+ android:layout_width="0dp"
+ android:layout_height="32dp"
+ android:max="70"
+ android:layout_weight="1" />
+
+ <TextView
+ android:id="@+id/butIncSpeed"
+ android:layout_width="32dp"
+ android:layout_height="32dp"
+ android:gravity="center"
+ android:text="+"
+ android:clickable="true"
+ android:focusable="true"
+ android:textStyle="bold"
+ android:textSize="24sp"
+ android:textColor="?attr/colorSecondary"
+ android:contentDescription="@string/increase_speed"
+ android:background="?attr/selectableItemBackgroundBorderless" />
+</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/queue_fragment.xml b/app/src/main/res/layout/queue_fragment.xml
index 94f929d30..6a1851648 100644
--- a/app/src/main/res/layout/queue_fragment.xml
+++ b/app/src/main/res/layout/queue_fragment.xml
@@ -36,6 +36,7 @@
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:paddingHorizontal="@dimen/additional_horizontal_spacing"
android:layout_below="@id/divider" />
<ProgressBar
diff --git a/app/src/main/res/layout/quick_feed_discovery.xml b/app/src/main/res/layout/quick_feed_discovery.xml
index a274fcdc7..b125206c1 100644
--- a/app/src/main/res/layout/quick_feed_discovery.xml
+++ b/app/src/main/res/layout/quick_feed_discovery.xml
@@ -62,4 +62,15 @@
android:layout_height="wrap_content"/>
</RelativeLayout>
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textColor="?android:attr/textColorTertiary"
+ android:text="@string/discover_powered_by_itunes"
+ android:textSize="12sp"
+ android:layout_gravity="right|end"
+ android:paddingHorizontal="4dp"
+ android:textAlignment="textEnd"/>
+
</LinearLayout>
diff --git a/app/src/main/res/layout/search_fragment.xml b/app/src/main/res/layout/search_fragment.xml
index 19cd87409..0bc663db1 100644
--- a/app/src/main/res/layout/search_fragment.xml
+++ b/app/src/main/res/layout/search_fragment.xml
@@ -36,7 +36,7 @@
android:layout_below="@id/recyclerViewFeeds"
android:layout_marginTop="-4dp"
android:paddingTop="12dp"
- android:clipToPadding="false"
+ android:paddingHorizontal="@dimen/additional_horizontal_spacing"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
diff --git a/app/src/main/res/layout/searchlist_item.xml b/app/src/main/res/layout/searchlist_item.xml
deleted file mode 100644
index 608bfc3bc..000000000
--- a/app/src/main/res/layout/searchlist_item.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- tools:background="@android:color/darker_gray"
- android:paddingTop="@dimen/listitem_threeline_verticalpadding"
- android:paddingBottom="@dimen/listitem_threeline_verticalpadding">
-
- <ImageView
- android:id="@+id/imgvFeedimage"
- android:layout_width="@dimen/thumbnail_length_itemlist"
- android:layout_height="@dimen/thumbnail_length_itemlist"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_centerVertical="true"
- android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding"
- android:layout_marginStart="@dimen/listitem_threeline_horizontalpadding"
- android:importantForAccessibility="no"
- android:scaleType="centerCrop"
- tools:src="@drawable/ic_antenna"
- tools:background="@android:color/holo_green_dark"/>
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_marginLeft="@dimen/listitem_iconwithtext_textleftpadding"
- android:layout_marginStart="@dimen/listitem_iconwithtext_textleftpadding"
- android:layout_marginRight="@dimen/listitem_threeline_verticalpadding"
- android:layout_marginEnd="@dimen/listitem_threeline_verticalpadding"
- android:layout_toRightOf="@id/imgvFeedimage"
- android:layout_toEndOf="@id/imgvFeedimage"
- android:orientation="vertical"
- tools:background="@android:color/holo_red_dark">
-
- <TextView
- android:id="@+id/txtvTitle"
- style="@style/AntennaPod.TextView.ListItemPrimaryTitle"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="8dp"
- tools:text="Search item title"
- tools:background="@android:color/holo_green_dark" />
-
- <TextView
- android:id="@+id/txtvSubtitle"
- style="@style/AntennaPod.TextView.ListItemSecondaryTitle"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:lines="1"
- tools:text="Search item subtitle"
- tools:background="@android:color/holo_blue_light"/>
- </LinearLayout>
-
-</RelativeLayout>
diff --git a/app/src/main/res/layout/share_episode_dialog.xml b/app/src/main/res/layout/share_episode_dialog.xml
new file mode 100644
index 000000000..8cf955d4c
--- /dev/null
+++ b/app/src/main/res/layout/share_episode_dialog.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:padding="16dp">
+
+ <RadioGroup
+ android:id="@+id/share_dialog_radio_group"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="16dp"
+ android:orientation="vertical">
+
+ <RadioButton android:id="@+id/share_episode_website_radio"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/share_dialog_episode_website_label"
+ android:checked="true"
+ />
+ <RadioButton android:id="@+id/share_media_file_radio"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/share_dialog_media_file_label"
+ />
+ </RadioGroup>
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:text="@string/share_dialog_include_label"/>
+
+ <CheckBox
+ android:id="@+id/share_start_at_timer_dialog"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/share_playback_position_dialog_label" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/simple_list_fragment.xml b/app/src/main/res/layout/simple_list_fragment.xml
index 368029932..989566499 100644
--- a/app/src/main/res/layout/simple_list_fragment.xml
+++ b/app/src/main/res/layout/simple_list_fragment.xml
@@ -14,9 +14,9 @@
<de.danoeh.antennapod.view.EpisodeItemListRecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:paddingHorizontal="@dimen/additional_horizontal_spacing"
android:layout_below="@id/toolbar"
- android:id="@+id/recyclerView"
- android:clipToPadding="false"/>
+ android:id="@+id/recyclerView"/>
<ProgressBar
android:id="@+id/progLoading"
diff --git a/app/src/main/res/layout/speed_select_dialog.xml b/app/src/main/res/layout/speed_select_dialog.xml
new file mode 100644
index 000000000..e4d78c3fa
--- /dev/null
+++ b/app/src/main/res/layout/speed_select_dialog.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:padding="16dp"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:text="@string/playback_speed"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ style="@style/AntennaPod.TextView.ListItemPrimaryTitle"/>
+
+ <com.google.android.material.chip.Chip
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/add_current_speed_chip"/>
+ </LinearLayout>
+
+ <de.danoeh.antennapod.view.PlaybackSpeedSeekBar
+ android:id="@+id/speed_seek_bar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="8dp">
+ </de.danoeh.antennapod.view.PlaybackSpeedSeekBar>
+
+ <TextView
+ android:text="@string/speed_presets"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ style="@style/AntennaPod.TextView.ListItemPrimaryTitle"
+ android:layout_marginBottom="8dp"/>
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/selected_speeds_grid"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/statistics_fragment.xml b/app/src/main/res/layout/statistics_fragment.xml
deleted file mode 100644
index e44c7ca81..000000000
--- a/app/src/main/res/layout/statistics_fragment.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?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">
-
-
- <com.google.android.material.tabs.TabLayout
- android:id="@+id/sliding_tabs"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="?android:attr/windowBackground"
- app:tabBackground="?attr/selectableItemBackground"
- app:tabGravity="fill"
- app:tabMode="fixed" />
-
- <androidx.viewpager2.widget.ViewPager2
- 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/app/src/main/res/menu/downloads_completed.xml b/app/src/main/res/menu/downloads_completed.xml
index 8badc4927..e07af520f 100644
--- a/app/src/main/res/menu/downloads_completed.xml
+++ b/app/src/main/res/menu/downloads_completed.xml
@@ -7,4 +7,10 @@
android:title="@string/multi_select"
android:icon="?attr/checkbox_multiple"
app:showAsAction="ifRoom" />
+ <item
+ android:id="@+id/refresh_item"
+ android:title="@string/refresh_label"
+ android:menuCategory="container"
+ app:showAsAction="ifRoom"
+ android:icon="?attr/navigation_refresh"/>
</menu>
diff --git a/app/src/main/res/menu/downloads_log.xml b/app/src/main/res/menu/downloads_log.xml
new file mode 100644
index 000000000..d37d9bf3f
--- /dev/null
+++ b/app/src/main/res/menu/downloads_log.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+ <item
+ android:id="@+id/clear_history_item"
+ android:menuCategory="container"
+ android:title="@string/clear_history_label"
+ android:icon="?attr/ic_delete"
+ app:showAsAction="ifRoom" />
+ <item
+ android:id="@+id/refresh_item"
+ android:title="@string/refresh_label"
+ android:menuCategory="container"
+ app:showAsAction="ifRoom"
+ android:icon="?attr/navigation_refresh"/>
+</menu> \ No newline at end of file
diff --git a/app/src/main/res/menu/downloads_running.xml b/app/src/main/res/menu/downloads_running.xml
new file mode 100644
index 000000000..a2240d4aa
--- /dev/null
+++ b/app/src/main/res/menu/downloads_running.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+ <item
+ android:id="@+id/refresh_item"
+ android:title="@string/refresh_label"
+ android:menuCategory="container"
+ app:showAsAction="ifRoom"
+ android:icon="?attr/navigation_refresh"/>
+</menu> \ No newline at end of file
diff --git a/app/src/main/res/menu/episodes_apply_action_options.xml b/app/src/main/res/menu/episodes_apply_action_options.xml
index c3f117386..181300fc5 100644
--- a/app/src/main/res/menu/episodes_apply_action_options.xml
+++ b/app/src/main/res/menu/episodes_apply_action_options.xml
@@ -33,7 +33,7 @@
<item android:id="@+id/check_all"
android:title="@string/all_label"/>
<item android:id="@+id/check_none"
- android:title="@string/none_label"/>
+ android:title="@string/select_none_label"/>
<item android:id="@+id/check_played"
android:title="@string/played_label"/>
<item android:id="@+id/check_unplayed"
diff --git a/app/src/main/res/menu/feeditem_options.xml b/app/src/main/res/menu/feeditem_options.xml
index e415ff85a..c29229e37 100644
--- a/app/src/main/res/menu/feeditem_options.xml
+++ b/app/src/main/res/menu/feeditem_options.xml
@@ -71,29 +71,7 @@
<item
android:id="@+id/share_item"
android:menuCategory="container"
- android:title="@string/share_label">
- <menu>
- <item
- android:id="@+id/share_link_item"
- android:menuCategory="container"
- android:title="@string/share_link_label" />
- <item
- android:id="@+id/share_link_with_position_item"
- android:menuCategory="container"
- android:title="@string/share_link_with_position_label" />
- <item
- android:id="@+id/share_download_url_item"
- android:menuCategory="container"
- android:title="@string/share_item_url_label" />
- <item
- android:id="@+id/share_download_url_with_position_item"
- android:menuCategory="container"
- android:title="@string/share_item_url_with_position_label" />
- <item
- android:id="@+id/share_file"
- android:menuCategory="container"
- android:title="@string/share_file_label" />
- </menu>
+ android:title="@string/share_label_with_ellipses">
</item>
<item
diff --git a/app/src/main/res/menu/feedlist.xml b/app/src/main/res/menu/feedlist.xml
index 939a51ab2..3614cfffa 100644
--- a/app/src/main/res/menu/feedlist.xml
+++ b/app/src/main/res/menu/feedlist.xml
@@ -52,19 +52,25 @@
android:title="@string/visit_website_label"
android:visible="true">
</item>
+
<item
- android:id="@+id/share_link_item"
- android:menuCategory="container"
- custom:showAsAction="collapseActionView"
- android:title="@string/share_website_url_label">
- </item>
- <item
- android:id="@+id/share_download_url_item"
+ android:id="@+id/share_item"
android:menuCategory="container"
- custom:showAsAction="collapseActionView"
- android:title="@string/share_feed_url_label">
+ custom:showAsAction="never"
+ android:title="@string/share_label_with_ellipses">
+ <menu>
+ <item
+ android:id="@+id/share_link_item"
+ android:title="@string/share_website_url_label">
+ </item>
+ <item
+ android:id="@+id/share_download_url_item"
+ android:title="@string/share_feed_url_label">
+ </item>
+ </menu>
</item>
+
<item
android:id="@+id/rename_item"
android:menuCategory="container"
diff --git a/app/src/main/res/menu/mediaplayer.xml b/app/src/main/res/menu/mediaplayer.xml
index a61616ce9..8afdba369 100644
--- a/app/src/main/res/menu/mediaplayer.xml
+++ b/app/src/main/res/menu/mediaplayer.xml
@@ -62,28 +62,6 @@
android:id="@+id/share_item"
android:menuCategory="container"
custom:showAsAction="never"
- android:title="@string/share_label">
- <menu>
- <item
- android:id="@+id/share_link_item"
- android:menuCategory="container"
- android:title="@string/share_link_label" />
- <item
- android:id="@+id/share_link_with_position_item"
- android:menuCategory="container"
- android:title="@string/share_link_with_position_label" />
- <item
- android:id="@+id/share_download_url_item"
- android:menuCategory="container"
- android:title="@string/share_item_url_label" />
- <item
- android:id="@+id/share_download_url_with_position_item"
- android:menuCategory="container"
- android:title="@string/share_item_url_with_position_label" />
- <item
- android:id="@+id/share_file"
- android:menuCategory="container"
- android:title="@string/share_file_label" />
- </menu>
+ android:title="@string/share_label_with_ellipses">
</item>
</menu> \ No newline at end of file
diff --git a/app/src/main/res/menu/subscriptions.xml b/app/src/main/res/menu/subscriptions.xml
index 1780592d5..b7dc95299 100644
--- a/app/src/main/res/menu/subscriptions.xml
+++ b/app/src/main/res/menu/subscriptions.xml
@@ -9,6 +9,15 @@
custom:showAsAction="always"
android:icon="?attr/navigation_refresh"/>
+
+ <item
+ android:id="@+id/subscriptions_filter"
+ android:title="@string/filter"
+ custom:showAsAction="never" />
+ <item
+ android:id="@+id/subscriptions_sort"
+ android:title="@string/sort"
+ custom:showAsAction="never" />
<item
android:id="@+id/subscription_num_columns"
android:title="@string/subscription_num_columns"
diff --git a/app/src/main/res/values-sw600dp/integers.xml b/app/src/main/res/values-sw600dp/integers.xml
new file mode 100644
index 000000000..fb43e5de6
--- /dev/null
+++ b/app/src/main/res/values-sw600dp/integers.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <integer name="subscriptions_default_num_of_columns">5</integer>
+</resources> \ No newline at end of file
diff --git a/app/src/main/res/values-w1000dp/dimens.xml b/app/src/main/res/values-w1000dp/dimens.xml
new file mode 100644
index 000000000..59ddcb5c0
--- /dev/null
+++ b/app/src/main/res/values-w1000dp/dimens.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <dimen name="additional_horizontal_spacing">56dp</dimen>
+</resources> \ No newline at end of file
diff --git a/app/src/main/res/values-w300dp/dimens-fabspeeddial.xml b/app/src/main/res/values-w300dp/dimens-fabspeeddial.xml
deleted file mode 100644
index 1b90da786..000000000
--- a/app/src/main/res/values-w300dp/dimens-fabspeeddial.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:tools="http://schemas.android.com/tools">
- <!-- increase FAB speed dial label's max width if the screen is wide enough
- (300dp ~ 1.875 inch, devices with 3.5-inch screens have a width of ~ 1.9in
- so the setup is applicable for most phones)
- -->
- <dimen name="sd_label_max_width" tools:ignore="MissingDefaultResource">240dp</dimen>
-</resources>
diff --git a/app/src/main/res/values-w300dp/dimens.xml b/app/src/main/res/values-w300dp/dimens.xml
new file mode 100644
index 000000000..8adaf4c2d
--- /dev/null
+++ b/app/src/main/res/values-w300dp/dimens.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:tools="http://schemas.android.com/tools">
+ <dimen name="additional_horizontal_spacing">0dp</dimen>
+ <!--
+ Overwrites FAB library.
+ Increase FAB speed dial label's max width if the screen is wide enough
+ (300dp ~ 1.875 inch, devices with 3.5-inch screens have a width of ~ 1.9in
+ so the setup is applicable for most phones)
+ -->
+ <dimen name="sd_label_max_width" tools:ignore="MissingDefaultResource, UnusedResources">240dp</dimen>
+</resources>
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
new file mode 100644
index 000000000..f5f6aa0a8
--- /dev/null
+++ b/app/src/main/res/values/dimens.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <dimen name="additional_horizontal_spacing">0dp</dimen>
+</resources> \ No newline at end of file
diff --git a/app/src/main/res/values/integers.xml b/app/src/main/res/values/integers.xml
new file mode 100644
index 000000000..a7a7ead7b
--- /dev/null
+++ b/app/src/main/res/values/integers.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <integer name="subscriptions_default_num_of_columns">3</integer>
+ <integer name="nav_drawer_screen_size_percent">80</integer>
+</resources> \ No newline at end of file
diff --git a/app/src/main/res/xml/automotive_app_desc.xml b/app/src/main/res/xml/automotive_app_desc.xml
index 8f0a7c59c..0a6a3c9fb 100644
--- a/app/src/main/res/xml/automotive_app_desc.xml
+++ b/app/src/main/res/xml/automotive_app_desc.xml
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
-<automotiveApp xmlns:android="http://schemas.android.com/apk/res/android">
+<automotiveApp>
<uses name="media"/>
</automotiveApp> \ No newline at end of file
diff --git a/app/src/main/res/xml/feed_settings.xml b/app/src/main/res/xml/feed_settings.xml
index 9f8392f44..a6820a4ad 100644
--- a/app/src/main/res/xml/feed_settings.xml
+++ b/app/src/main/res/xml/feed_settings.xml
@@ -3,7 +3,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:key="feedSettingsScreen">
- <SwitchPreference
+ <SwitchPreferenceCompat
android:key="keepUpdated"
android:icon="?attr/navigation_refresh"
android:title="@string/keep_updated"
@@ -45,7 +45,7 @@
android:key="volumeReduction"/>
<PreferenceCategory android:title="@string/auto_download_settings_label">
- <SwitchPreference
+ <SwitchPreferenceCompat
android:key="autoDownload"
android:title="@string/auto_download_label"/>
<Preference
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
index b69f27473..0a19a36b1 100644
--- a/app/src/main/res/xml/preferences.xml
+++ b/app/src/main/res/xml/preferences.xml
@@ -44,7 +44,9 @@
android:title="@string/statistics_label"
android:icon="?attr/statistics" />
- <PreferenceCategory android:title="@string/project_pref">
+ <PreferenceCategory
+ android:key="project"
+ android:title="@string/project_pref">
<Preference
android:key="prefFaq"
android:title="@string/pref_faq"
diff --git a/app/src/main/res/xml/preferences_autodownload.xml b/app/src/main/res/xml/preferences_autodownload.xml
index 333224aa0..2b541afa3 100644
--- a/app/src/main/res/xml/preferences_autodownload.xml
+++ b/app/src/main/res/xml/preferences_autodownload.xml
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:search="http://schemas.android.com/apk/com.bytehamster.lib.preferencesearch">
<de.danoeh.antennapod.preferences.MasterSwitchPreference
@@ -23,12 +22,12 @@
android:title="@string/pref_episode_cleanup_title"
android:summary="@string/pref_episode_cleanup_summary"
android:entryValues="@array/episode_cleanup_values"/>
- <SwitchPreference
+ <SwitchPreferenceCompat
android:key="prefEnableAutoDownloadOnBattery"
android:title="@string/pref_automatic_download_on_battery_title"
android:summary="@string/pref_automatic_download_on_battery_sum"
android:defaultValue="true"/>
- <SwitchPreference
+ <SwitchPreferenceCompat
android:key="prefEnableAutoDownloadWifiFilter"
android:title="@string/pref_autodl_wifi_filter_title"
android:summary="@string/pref_autodl_wifi_filter_sum"/>
diff --git a/app/src/main/res/xml/preferences_gpodder.xml b/app/src/main/res/xml/preferences_gpodder.xml
index 5789f5f84..d8478faf2 100644
--- a/app/src/main/res/xml/preferences_gpodder.xml
+++ b/app/src/main/res/xml/preferences_gpodder.xml
@@ -26,7 +26,7 @@
<Preference
android:key="pref_gpodnet_hostname"
android:title="@string/pref_gpodnet_sethostname_title"/>
- <SwitchPreference
+ <SwitchPreferenceCompat
android:key="pref_gpodnet_notifications"
android:title="@string/pref_gpodnet_notifications_title"
android:summary="@string/pref_gpodnet_notifications_sum"
diff --git a/app/src/main/res/xml/preferences_network.xml b/app/src/main/res/xml/preferences_network.xml
index 5d1831ef0..f51b9561e 100644
--- a/app/src/main/res/xml/preferences_network.xml
+++ b/app/src/main/res/xml/preferences_network.xml
@@ -29,13 +29,13 @@
numberpicker:maxValue="50"
android:key="prefParallelDownloads"
android:title="@string/pref_parallel_downloads_title"/>
- <SwitchPreference
+ <SwitchPreferenceCompat
android:defaultValue="true"
android:enabled="true"
android:key="prefShowDownloadReport"
android:summary="@string/pref_showDownloadReport_sum"
android:title="@string/pref_showDownloadReport_title"/>
- <SwitchPreference
+ <SwitchPreferenceCompat
android:defaultValue="false"
android:enabled="true"
android:key="prefShowAutoDownloadReport"
diff --git a/app/src/main/res/xml/preferences_playback.xml b/app/src/main/res/xml/preferences_playback.xml
index 32bf383d7..161332d2f 100644
--- a/app/src/main/res/xml/preferences_playback.xml
+++ b/app/src/main/res/xml/preferences_playback.xml
@@ -2,33 +2,33 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/interruptions">
- <SwitchPreference
+ <SwitchPreferenceCompat
android:defaultValue="true"
android:enabled="true"
android:key="prefPauseOnHeadsetDisconnect"
android:summary="@string/pref_pauseOnDisconnect_sum"
android:title="@string/pref_pauseOnHeadsetDisconnect_title"/>
- <SwitchPreference
+ <SwitchPreferenceCompat
android:defaultValue="true"
android:enabled="true"
android:dependency="prefPauseOnHeadsetDisconnect"
android:key="prefUnpauseOnHeadsetReconnect"
android:summary="@string/pref_unpauseOnHeadsetReconnect_sum"
android:title="@string/pref_unpauseOnHeadsetReconnect_title"/>
- <SwitchPreference
+ <SwitchPreferenceCompat
android:defaultValue="false"
android:enabled="true"
android:dependency="prefPauseOnHeadsetDisconnect"
android:key="prefUnpauseOnBluetoothReconnect"
android:summary="@string/pref_unpauseOnBluetoothReconnect_sum"
android:title="@string/pref_unpauseOnBluetoothReconnect_title"/>
- <SwitchPreference
+ <SwitchPreferenceCompat
android:defaultValue="false"
android:enabled="true"
android:key="prefPauseForFocusLoss"
android:summary="@string/pref_pausePlaybackForFocusLoss_sum"
android:title="@string/pref_pausePlaybackForFocusLoss_title"/>
- <SwitchPreference
+ <SwitchPreferenceCompat
android:defaultValue="true"
android:enabled="true"
android:key="prefResumeAfterCall"
@@ -44,13 +44,13 @@
</PreferenceCategory>
<PreferenceCategory android:title="@string/playback_control">
- <SwitchPreference
+ <SwitchPreferenceCompat
android:defaultValue="false"
android:enabled="true"
android:key="prefHardwareForwardButtonSkips"
android:summary="@string/pref_hardwareForwardButtonSkips_sum"
android:title="@string/pref_hardwareForwardButtonSkips_title"/>
- <SwitchPreference
+ <SwitchPreferenceCompat
android:defaultValue="false"
android:enabled="true"
android:key="prefHardwarePreviousButtonRestarts"
@@ -67,13 +67,13 @@
<Preference
android:key="prefPlaybackSpeedLauncher"
android:summary="@string/pref_playback_speed_sum"
- android:title="@string/pref_playback_speed_title"/>
- <SwitchPreference
+ android:title="@string/playback_speed"/>
+ <SwitchPreferenceCompat
android:defaultValue="false"
android:key="prefPlaybackTimeRespectsSpeed"
android:summary="@string/pref_playback_time_respects_speed_sum"
android:title="@string/pref_playback_time_respects_speed_title"/>
- <SwitchPreference
+ <SwitchPreferenceCompat
android:defaultValue="false"
android:key="prefStreamOverDownload"
android:summary="@string/pref_stream_over_download_sum"
@@ -81,7 +81,7 @@
</PreferenceCategory>
<PreferenceCategory android:title="@string/queue_label">
- <SwitchPreference
+ <SwitchPreferenceCompat
android:defaultValue="true"
android:enabled="true"
android:key="prefEnqueueDownloaded"
@@ -93,7 +93,7 @@
android:entryValues="@array/enqueue_location_values"
android:key="prefEnqueueLocation"
android:title="@string/pref_enqueue_location_title"/>
- <SwitchPreference
+ <SwitchPreferenceCompat
android:defaultValue="true"
android:enabled="true"
android:key="prefFollowQueue"
@@ -106,7 +106,7 @@
android:key="prefSmartMarkAsPlayedSecs"
android:summary="@string/pref_smart_mark_as_played_sum"
android:title="@string/pref_smart_mark_as_played_title"/>
- <SwitchPreference
+ <SwitchPreferenceCompat
android:defaultValue="true"
android:enabled="true"
android:key="prefSkipKeepsEpisode"
@@ -125,7 +125,7 @@
</PreferenceCategory>
<PreferenceCategory android:title="@string/experimental_pref">
- <SwitchPreference
+ <SwitchPreferenceCompat
android:defaultValue="false"
android:enabled="true"
android:key="prefCast"
diff --git a/app/src/main/res/xml/preferences_storage.xml b/app/src/main/res/xml/preferences_storage.xml
index 18e2abb31..d3d570e6c 100644
--- a/app/src/main/res/xml/preferences_storage.xml
+++ b/app/src/main/res/xml/preferences_storage.xml
@@ -13,19 +13,19 @@
android:key="prefImageCacheSize"
android:summary="@string/pref_image_cache_size_sum"
android:defaultValue="100"/>
- <SwitchPreference
+ <SwitchPreferenceCompat
android:defaultValue="false"
android:enabled="true"
android:key="prefAutoDelete"
android:summary="@string/pref_auto_delete_sum"
android:title="@string/pref_auto_delete_title"/>
- <SwitchPreference
+ <SwitchPreferenceCompat
android:defaultValue="true"
android:enabled="true"
android:key="prefFavoriteKeepsEpisode"
android:summary="@string/pref_favorite_keeps_episodes_sum"
android:title="@string/pref_favorite_keeps_episodes_title"/>
- <SwitchPreference
+ <SwitchPreferenceCompat
android:defaultValue="false"
android:enabled="true"
android:key="prefDeleteRemovesFromQueue"
diff --git a/app/src/main/res/xml/preferences_user_interface.xml b/app/src/main/res/xml/preferences_user_interface.xml
index a2fc970e0..c1db2dc1e 100644
--- a/app/src/main/res/xml/preferences_user_interface.xml
+++ b/app/src/main/res/xml/preferences_user_interface.xml
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto">
+ xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/appearance">
<ListPreference
@@ -15,35 +14,38 @@
android:key="prefHiddenDrawerItems"
android:summary="@string/pref_nav_drawer_items_sum"
android:title="@string/pref_nav_drawer_items_title"/>
- <ListPreference
- android:entryValues="@array/nav_drawer_feed_order_values"
- android:entries="@array/nav_drawer_feed_order_options"
- android:title="@string/pref_nav_drawer_feed_order_title"
- android:key="prefDrawerFeedOrder"
- android:summary="@string/pref_nav_drawer_feed_order_sum"
- android:defaultValue="0"/>
- <ListPreference
- android:entryValues="@array/nav_drawer_feed_counter_values"
- android:entries="@array/nav_drawer_feed_counter_options"
- android:title="@string/pref_nav_drawer_feed_counter_title"
- android:key="prefDrawerFeedIndicator"
- android:summary="@string/pref_nav_drawer_feed_counter_sum"
- android:defaultValue="1"/>
- <SwitchPreference
+ <SwitchPreferenceCompat
android:title="@string/pref_episode_cover_title"
android:key="prefEpisodeCover"
android:summary="@string/pref_episode_cover_summary"
android:defaultValue="true"
android:enabled="true"/>
</PreferenceCategory>
+ <PreferenceCategory android:title="@string/subscriptions_label">
+ <Preference
+ android:title="@string/pref_nav_drawer_feed_order_title"
+ android:key="prefDrawerFeedOrder"
+ android:summary="@string/pref_nav_drawer_feed_order_sum"/>
+ <ListPreference
+ android:entryValues="@array/nav_drawer_feed_counter_values"
+ android:entries="@array/nav_drawer_feed_counter_options"
+ android:title="@string/pref_nav_drawer_feed_counter_title"
+ android:key="prefDrawerFeedIndicator"
+ android:summary="@string/pref_nav_drawer_feed_counter_sum"
+ android:defaultValue="1"/>
+ <Preference
+ android:title="@string/pref_filter_feed_title"
+ android:key="prefFeedFilter"
+ android:summary="@string/pref_filter_feed_sum" />
+ </PreferenceCategory>
<PreferenceCategory android:title="@string/external_elements">
- <SwitchPreference
+ <SwitchPreferenceCompat
android:defaultValue="false"
android:enabled="true"
android:key="prefExpandNotify"
android:summary="@string/pref_expandNotify_sum"
android:title="@string/pref_expandNotify_title"/>
- <SwitchPreference
+ <SwitchPreferenceCompat
android:defaultValue="true"
android:enabled="true"
android:key="prefPersistNotify"
@@ -53,7 +55,7 @@
android:key="prefCompactNotificationButtons"
android:summary="@string/pref_compact_notification_buttons_sum"
android:title="@string/pref_compact_notification_buttons_title"/>
- <SwitchPreference
+ <SwitchPreferenceCompat
android:defaultValue="true"
android:enabled="true"
android:key="prefLockscreenBackground"
diff --git a/app/src/main/res/xml/provider_paths.xml b/app/src/main/res/xml/provider_paths.xml
index c4ed430be..a16b679e3 100644
--- a/app/src/main/res/xml/provider_paths.xml
+++ b/app/src/main/res/xml/provider_paths.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<paths xmlns:android="http://schemas.android.com/apk/res/android">
+<paths>
<external-path name="external_storage" path="."/>
<root-path name="external_files" path="/storage/" />
</paths>
diff --git a/app/src/main/res/xml/searchable.xml b/app/src/main/res/xml/searchable.xml
deleted file mode 100644
index 0861ecdae..000000000
--- a/app/src/main/res/xml/searchable.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<searchable xmlns:android="http://schemas.android.com/apk/res/android"
- android:hint="@string/search_label"
- android:label="@string/app_name"/> \ No newline at end of file
diff --git a/app/src/play/java/de/danoeh/antennapod/activity/CastEnabledActivity.java b/app/src/play/java/de/danoeh/antennapod/activity/CastEnabledActivity.java
index 10678f556..753feb3e7 100644
--- a/app/src/play/java/de/danoeh/antennapod/activity/CastEnabledActivity.java
+++ b/app/src/play/java/de/danoeh/antennapod/activity/CastEnabledActivity.java
@@ -3,7 +3,7 @@ package de.danoeh.antennapod.activity;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.os.Bundle;
-import android.preference.PreferenceManager;
+import androidx.preference.PreferenceManager;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
diff --git a/artwork/screenshots/generateScreenshots.sh b/artwork/screenshots/generateScreenshots.sh
index 7ffc4be65..5b1d7f7e8 100644
--- a/artwork/screenshots/generateScreenshots.sh
+++ b/artwork/screenshots/generateScreenshots.sh
@@ -6,6 +6,12 @@ function generateText() {
-annotate 0 "$1" /tmp/text.png
}
+function generateTabletText() {
+ echo "$1"
+ convert -size 1730x350 xc:none -gravity Center -pointsize 80 -fill white -font Lato-Regular \
+ -annotate 0 "$1" /tmp/text.png
+}
+
function simplePhone() {
generateText "$1"
convert templates/phone.png \
@@ -14,6 +20,15 @@ function simplePhone() {
$3
}
+function simpleTablet() {
+ generateTabletText "$1"
+ convert $2 -resize 1280 "/tmp/resized-image.png"
+ convert templates/tablet.png \
+ /tmp/resized-image.png -geometry +227+459 -composite \
+ /tmp/text.png -geometry +0+0 -composite \
+ $3
+}
+
function addLayer() {
convert $2 $1 -composite $2
}
@@ -27,6 +42,7 @@ function generateScreenshots() {
text3=`cat raw/$language/texts.txt | head -4 | tail -1`
text4=`cat raw/$language/texts.txt | head -5 | tail -1`
text5=`cat raw/$language/texts.txt | head -6 | tail -1`
+ text6=`cat raw/$language/texts.txt | head -7 | tail -1`
simplePhone "$text0" raw/$language/00.png output/$language/00.png
simplePhone "$text1" raw/$language/01.png output/$language/01.png
@@ -42,7 +58,8 @@ function generateScreenshots() {
simplePhone "$text4" raw/$language/04.png output/$language/04.png
simplePhone "$text5" raw/$language/05.png output/$language/05.png
addLayer templates/suggestions.png output/$language/05.png
- mogrify -resize 1120 "output/$language/*.png"
+ simpleTablet "$text6" raw/$language/tablet.png output/$language/tablet.png
+ mogrify -resize 1120 "output/$language/0*.png"
}
mkdir output 2>/dev/null
diff --git a/artwork/screenshots/raw/de-DE/tablet.png b/artwork/screenshots/raw/de-DE/tablet.png
new file mode 100644
index 000000000..592238234
--- /dev/null
+++ b/artwork/screenshots/raw/de-DE/tablet.png
Binary files differ
diff --git a/artwork/screenshots/raw/de-DE/texts.txt b/artwork/screenshots/raw/de-DE/texts.txt
index a0ea2c731..7c85b8df2 100644
--- a/artwork/screenshots/raw/de-DE/texts.txt
+++ b/artwork/screenshots/raw/de-DE/texts.txt
@@ -4,3 +4,4 @@ Spare Zeit mit\nautomatischen Downloads
Wähle dein\nLieblings-Theme
Passe AntennaPod\nan deine Wünsche an
Entdecke tausende\nneuer Podcasts
+Genieße deine Podcasts. Überall. Jederzeit.
diff --git a/artwork/screenshots/raw/en-US/tablet.png b/artwork/screenshots/raw/en-US/tablet.png
new file mode 100644
index 000000000..6593bd625
--- /dev/null
+++ b/artwork/screenshots/raw/en-US/tablet.png
Binary files differ
diff --git a/artwork/screenshots/raw/en-US/texts.txt b/artwork/screenshots/raw/en-US/texts.txt
index f1ef1c960..e946bb27c 100644
--- a/artwork/screenshots/raw/en-US/texts.txt
+++ b/artwork/screenshots/raw/en-US/texts.txt
@@ -4,3 +4,4 @@ Save time with\nautomatic downloads
Select the theme\nthat fits best to you
Adapt AntennaPod\nto your needs
Discover thousands\nof great podcasts
+Enjoy your podcasts. Anywhere. Anytime.
diff --git a/artwork/screenshots/raw/fr-FR/tablet.png b/artwork/screenshots/raw/fr-FR/tablet.png
new file mode 100644
index 000000000..a86766ba3
--- /dev/null
+++ b/artwork/screenshots/raw/fr-FR/tablet.png
Binary files differ
diff --git a/artwork/screenshots/raw/nl-NL/tablet.png b/artwork/screenshots/raw/nl-NL/tablet.png
new file mode 100644
index 000000000..54463f161
--- /dev/null
+++ b/artwork/screenshots/raw/nl-NL/tablet.png
Binary files differ
diff --git a/artwork/screenshots/raw/nl-NL/texts.txt b/artwork/screenshots/raw/nl-NL/texts.txt
index ebd140cf4..9f3651ca6 100644
--- a/artwork/screenshots/raw/nl-NL/texts.txt
+++ b/artwork/screenshots/raw/nl-NL/texts.txt
@@ -4,3 +4,4 @@ Bespaar tijd met\nautomatische downloads
Selecteer het thema\ndat het best bij je past
Pas AntennaPod aan\naan jouw wensen
Ontdek honderden\ninteressante podcasts
+Enjoy your podcasts. Anywhere. Anytime.
diff --git a/artwork/screenshots/templates/tablet.png b/artwork/screenshots/templates/tablet.png
new file mode 100644
index 000000000..0a757ab1d
--- /dev/null
+++ b/artwork/screenshots/templates/tablet.png
Binary files differ
diff --git a/core/build.gradle b/core/build.gradle
index 4c7ef5a0a..bfaffd14f 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -76,7 +76,7 @@ dependencies {
implementation "io.reactivex.rxjava2:rxandroid:$rxAndroidVersion"
implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion"
- implementation 'com.google.android.exoplayer:exoplayer:2.10.8'
+ implementation 'com.google.android.exoplayer:exoplayer:2.11.8'
implementation "com.github.AntennaPod:AntennaPod-AudioPlayer:$audioPlayerVersion"
// Add casting features
diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/DownloadEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/DownloadEvent.java
index 24a71ec96..efd53ab9d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/event/DownloadEvent.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/event/DownloadEvent.java
@@ -1,5 +1,7 @@
package de.danoeh.antennapod.core.event;
+import androidx.annotation.NonNull;
+
import java.util.ArrayList;
import java.util.List;
@@ -19,6 +21,7 @@ public class DownloadEvent {
return new DownloadEvent(update);
}
+ @NonNull
@Override
public String toString() {
return "DownloadEvent{" +
diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/DownloadLogEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/DownloadLogEvent.java
index 7428c5b00..5ab5decf9 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/event/DownloadLogEvent.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/event/DownloadLogEvent.java
@@ -1,5 +1,7 @@
package de.danoeh.antennapod.core.event;
+import androidx.annotation.NonNull;
+
public class DownloadLogEvent {
private DownloadLogEvent() {
@@ -9,6 +11,7 @@ public class DownloadLogEvent {
return new DownloadLogEvent();
}
+ @NonNull
@Override
public String toString() {
return "DownloadLogEvent";
diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/DownloaderUpdate.java b/core/src/main/java/de/danoeh/antennapod/core/event/DownloaderUpdate.java
index f549940b7..10992408d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/event/DownloaderUpdate.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/event/DownloaderUpdate.java
@@ -46,6 +46,7 @@ public class DownloaderUpdate {
this.mediaIds = mediaIds1.toArray();
}
+ @NonNull
@Override
public String toString() {
return "DownloaderUpdate{" +
diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/FavoritesEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/FavoritesEvent.java
index 578007561..d3be8fac0 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/event/FavoritesEvent.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/event/FavoritesEvent.java
@@ -1,5 +1,7 @@
package de.danoeh.antennapod.core.event;
+import androidx.annotation.NonNull;
+
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
@@ -27,6 +29,7 @@ public class FavoritesEvent {
return new FavoritesEvent(Action.REMOVED, item);
}
+ @NonNull
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/FeedItemEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/FeedItemEvent.java
index 4b14a72d2..02559b2f5 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/event/FeedItemEvent.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/event/FeedItemEvent.java
@@ -21,7 +21,7 @@ public class FeedItemEvent {
private final Action action;
@NonNull public final List<FeedItem> items;
- private FeedItemEvent(Action action, List<FeedItem> items) {
+ private FeedItemEvent(@NonNull Action action, @NonNull List<FeedItem> items) {
this.action = action;
this.items = items;
}
@@ -42,6 +42,7 @@ public class FeedItemEvent {
return updated(Arrays.asList(items));
}
+ @NonNull
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedComponent.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedComponent.java
index 2610d253f..3edecd35c 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedComponent.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedComponent.java
@@ -50,7 +50,7 @@ public abstract class FeedComponent {
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || !(o instanceof FeedComponent)) return false;
+ if (!(o instanceof FeedComponent)) return false;
FeedComponent that = (FeedComponent) o;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedEvent.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedEvent.java
index 15cdf92dc..044554451 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedEvent.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedEvent.java
@@ -1,5 +1,7 @@
package de.danoeh.antennapod.core.feed;
+import androidx.annotation.NonNull;
+
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
@@ -18,6 +20,7 @@ public class FeedEvent {
this.feedId = feedId;
}
+ @NonNull
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
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 20ed402fc..b681c21d1 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
@@ -1,12 +1,15 @@
package de.danoeh.antennapod.core.feed;
import android.database.Cursor;
+
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.text.TextUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
+import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
@@ -24,7 +27,7 @@ import de.danoeh.antennapod.core.util.ShownotesProvider;
*
* @author daniel
*/
-public class FeedItem extends FeedComponent implements ShownotesProvider, ImageResource {
+public class FeedItem extends FeedComponent implements ShownotesProvider, ImageResource, Serializable {
/** tag that indicates this item is in the queue */
public static final String TAG_QUEUE = "Queue";
@@ -481,6 +484,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, ImageR
*/
public void removeTag(String tag) { tags.remove(tag); }
+ @NonNull
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java
index 719383d23..d34e23506 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java
@@ -1,8 +1,10 @@
package de.danoeh.antennapod.core.feed;
import android.text.TextUtils;
+import android.util.Log;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import de.danoeh.antennapod.core.storage.DBReader;
@@ -11,17 +13,21 @@ import de.danoeh.antennapod.core.util.LongList;
import static de.danoeh.antennapod.core.feed.FeedItem.TAG_FAVORITE;
public class FeedItemFilter {
+
private final String[] mProperties;
private boolean showPlayed = false;
private boolean showUnplayed = false;
private boolean showPaused = false;
+ private boolean showNotPaused = false;
private boolean showQueued = false;
private boolean showNotQueued = false;
private boolean showDownloaded = false;
private boolean showNotDownloaded = false;
private boolean showHasMedia = false;
+ private boolean showNoMedia = false;
private boolean showIsFavorite = false;
+ private boolean showNotFavorite = false;
public FeedItemFilter(String properties) {
this(TextUtils.split(properties, ","));
@@ -29,15 +35,18 @@ public class FeedItemFilter {
public FeedItemFilter(String[] properties) {
this.mProperties = properties;
- for(String property : properties) {
+ for (String property : properties) {
// see R.arrays.feed_filter_values
- switch(property) {
+ switch (property) {
case "unplayed":
showUnplayed = true;
break;
case "paused":
showPaused = true;
break;
+ case "not_paused":
+ showNotPaused = true;
+ break;
case "played":
showPlayed = true;
break;
@@ -56,9 +65,17 @@ public class FeedItemFilter {
case "has_media":
showHasMedia = true;
break;
+ case "no_media":
+ showNoMedia = true;
+ break;
case "is_favorite":
showIsFavorite = true;
break;
+ case "not_favorite":
+ showNotFavorite = true;
+ break;
+ default:
+ break;
}
}
}
@@ -77,12 +94,15 @@ public class FeedItemFilter {
if (showQueued && showNotQueued) return result;
if (showDownloaded && showNotDownloaded) return result;
- final LongList queuedIds = DBReader.getQueueIDList();
- for(FeedItem item : items) {
+ final LongList queuedIds = DBReader.getQueueIDList();
+ for (FeedItem item : items) {
// If the item does not meet a requirement, skip it.
+
if (showPlayed && !item.isPlayed()) continue;
if (showUnplayed && item.isPlayed()) continue;
+
if (showPaused && item.getState() != FeedItem.State.IN_PROGRESS) continue;
+ if (showNotPaused && item.getState() == FeedItem.State.IN_PROGRESS) continue;
boolean queued = queuedIds.contains(item.getId());
if (showQueued && !queued) continue;
@@ -93,8 +113,10 @@ public class FeedItemFilter {
if (showNotDownloaded && downloaded) continue;
if (showHasMedia && !item.hasMedia()) continue;
+ if (showNoMedia && item.hasMedia()) continue;
if (showIsFavorite && !item.isTagged(TAG_FAVORITE)) continue;
+ if (showNotFavorite && item.isTagged(TAG_FAVORITE)) continue;
// If the item reaches here, it meets all criteria
result.add(item);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilterGroup.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilterGroup.java
new file mode 100644
index 000000000..fcbe2e4ab
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilterGroup.java
@@ -0,0 +1,36 @@
+package de.danoeh.antennapod.core.feed;
+
+import de.danoeh.antennapod.core.R;
+
+public enum FeedItemFilterGroup {
+ PLAYED(new ItemProperties(R.string.hide_played_episodes_label, "played"),
+ new ItemProperties(R.string.not_played, "unplayed")),
+ PAUSED(new ItemProperties(R.string.hide_paused_episodes_label, "paused"),
+ new ItemProperties(R.string.not_paused, "not_paused")),
+ FAVORITE(new ItemProperties(R.string.hide_is_favorite_label, "is_favorite"),
+ new ItemProperties(R.string.not_favorite, "not_favorite")),
+ MEDIA(new ItemProperties(R.string.has_media, "has_media"),
+ new ItemProperties(R.string.no_media, "no_media")),
+ QUEUED(new ItemProperties(R.string.queued_label, "queued"),
+ new ItemProperties(R.string.not_queued_label, "not_queued")),
+ DOWNLOADED(new ItemProperties(R.string.hide_downloaded_episodes_label, "downloaded"),
+ new ItemProperties(R.string.hide_not_downloaded_episodes_label, "not_downloaded"));
+
+ public final ItemProperties[] values;
+
+ FeedItemFilterGroup(ItemProperties... values) {
+ this.values = values;
+ }
+
+ public static class ItemProperties {
+
+ public final int displayName;
+ public final String filterId;
+
+ public ItemProperties(int displayName, String filterId) {
+ this.displayName = displayName;
+ this.filterId = filterId;
+ }
+
+ }
+}
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 7e1a5fd9b..d1c90cfa7 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
@@ -481,7 +481,7 @@ public class FeedMedia extends FeedFile implements Playable {
@Override
public void onPlaybackStart() {
- startPosition = (position > 0) ? position : 0;
+ startPosition = Math.max(position, 0);
playedDurationWhenStarted = played_duration;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java
index 36da11eca..35a9d987b 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java
@@ -28,8 +28,9 @@ import org.apache.commons.io.IOUtils;
public final class ChapterImageModelLoader implements ModelLoader<EmbeddedChapterImage, ByteBuffer> {
public static class Factory implements ModelLoaderFactory<EmbeddedChapterImage, ByteBuffer> {
+ @NonNull
@Override
- public ModelLoader<EmbeddedChapterImage, ByteBuffer> build(MultiModelLoaderFactory unused) {
+ public ModelLoader<EmbeddedChapterImage, ByteBuffer> build(@NonNull MultiModelLoaderFactory unused) {
return new ChapterImageModelLoader();
}
@@ -41,12 +42,15 @@ public final class ChapterImageModelLoader implements ModelLoader<EmbeddedChapte
@Nullable
@Override
- public LoadData<ByteBuffer> buildLoadData(EmbeddedChapterImage model, int width, int height, Options options) {
+ public LoadData<ByteBuffer> buildLoadData(@NonNull EmbeddedChapterImage model,
+ int width,
+ int height,
+ @NonNull Options options) {
return new LoadData<>(new ObjectKey(model), new EmbeddedImageFetcher(model));
}
@Override
- public boolean handles(EmbeddedChapterImage model) {
+ public boolean handles(@NonNull EmbeddedChapterImage model) {
return true;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java
index d0301db2f..1f8ae5ad9 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java
@@ -21,7 +21,10 @@ public class FastBlurTransformation extends BitmapTransformation {
}
@Override
- protected Bitmap transform(BitmapPool pool, Bitmap source, int outWidth, int outHeight) {
+ protected Bitmap transform(@NonNull BitmapPool pool,
+ @NonNull Bitmap source,
+ int outWidth,
+ int outHeight) {
int targetWidth = outWidth / 3;
int targetHeight = (int) (1.0 * outHeight * targetWidth / outWidth);
Bitmap resized = ThumbnailUtils.extractThumbnail(source, targetWidth, targetHeight);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/PlaybackPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/PlaybackPreferences.java
index a4612d857..08ea27434 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/preferences/PlaybackPreferences.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/PlaybackPreferences.java
@@ -2,7 +2,7 @@ package de.danoeh.antennapod.core.preferences;
import android.content.Context;
import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
+import androidx.preference.PreferenceManager;
import android.util.Log;
import de.danoeh.antennapod.core.event.PlayerStatusEvent;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java
index 876251563..bcbc041a6 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java
@@ -4,7 +4,7 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Build;
-import android.preference.PreferenceManager;
+import androidx.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.Log;
@@ -19,10 +19,14 @@ import org.json.JSONException;
import java.io.File;
import java.io.IOException;
import java.net.Proxy;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
+import java.util.Locale;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -46,14 +50,12 @@ import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
public class UserPreferences {
private UserPreferences(){}
- private static final String IMPORT_DIR = "import/";
-
private static final String TAG = "UserPreferences";
// User Interface
public static final String PREF_THEME = "prefTheme";
public static final String PREF_HIDDEN_DRAWER_ITEMS = "prefHiddenDrawerItems";
- private static final String PREF_DRAWER_FEED_ORDER = "prefDrawerFeedOrder";
+ public static final String PREF_DRAWER_FEED_ORDER = "prefDrawerFeedOrder";
private static final String PREF_DRAWER_FEED_COUNTER = "prefDrawerFeedIndicator";
public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify";
public static final String PREF_USE_EPISODE_COVER = "prefEpisodeCover";
@@ -64,6 +66,7 @@ public class UserPreferences {
private static final String PREF_SHOW_AUTO_DOWNLOAD_REPORT = "prefShowAutoDownloadReport";
public static final String PREF_BACK_BUTTON_BEHAVIOR = "prefBackButtonBehavior";
private static final String PREF_BACK_BUTTON_GO_TO_PAGE = "prefBackButtonGoToPage";
+ public static final String PREF_FILTER_FEED = "prefFeedFilter";
public static final String PREF_QUEUE_KEEP_SORTED = "prefQueueKeepSorted";
public static final String PREF_QUEUE_KEEP_SORTED_ORDER = "prefQueueKeepSortedOrder";
@@ -146,6 +149,8 @@ public class UserPreferences {
public static final int FEED_COUNTER_SHOW_UNPLAYED = 2;
public static final int FEED_COUNTER_SHOW_NONE = 3;
public static final int FEED_COUNTER_SHOW_DOWNLOADED = 4;
+ public static final int FEED_FILTER_NONE = 0;
+ public static final int FEED_FILTER_COUNTER_ZERO = 1;
private static Context context;
private static SharedPreferences prefs;
@@ -161,7 +166,6 @@ public class UserPreferences {
UserPreferences.context = context.getApplicationContext();
UserPreferences.prefs = PreferenceManager.getDefaultSharedPreferences(context);
- createImportDirectory();
createNoMediaFile();
}
@@ -242,6 +246,12 @@ public class UserPreferences {
return Integer.parseInt(value);
}
+ public static void setFeedOrder(String selected) {
+ prefs.edit()
+ .putString(PREF_DRAWER_FEED_ORDER, selected)
+ .commit();
+ }
+
public static int getFeedCounterSetting() {
String value = prefs.getString(PREF_DRAWER_FEED_COUNTER, "" + FEED_COUNTER_SHOW_NEW);
return Integer.parseInt(value);
@@ -414,7 +424,7 @@ public class UserPreferences {
return prefs.getBoolean(PREF_PLAYBACK_SKIP_SILENCE, false);
}
- public static float[] getPlaybackSpeedArray() {
+ public static List<Float> getPlaybackSpeedArray() {
return readPlaybackSpeedArray(prefs.getString(PREF_PLAYBACK_SPEED_ARRAY, null));
}
@@ -628,8 +638,7 @@ public class UserPreferences {
}
public static boolean isQueueLocked() {
- return prefs.getBoolean(PREF_QUEUE_LOCKED, false)
- || isQueueKeepSorted();
+ return prefs.getBoolean(PREF_QUEUE_LOCKED, false);
}
public static void setFastForwardSecs(int secs) {
@@ -662,10 +671,13 @@ public class UserPreferences {
.apply();
}
- public static void setPlaybackSpeedArray(String[] speeds) {
+ public static void setPlaybackSpeedArray(List<Float> speeds) {
+ DecimalFormatSymbols format = new DecimalFormatSymbols(Locale.US);
+ format.setDecimalSeparator('.');
+ DecimalFormat speedFormat = new DecimalFormat("0.00", format);
JSONArray jsonArray = new JSONArray();
- for (String speed : speeds) {
- jsonArray.put(speed);
+ for (float speed : speeds) {
+ jsonArray.put(speedFormat.format(speed));
}
prefs.edit()
.putString(PREF_PLAYBACK_SPEED_ARRAY, jsonArray.toString())
@@ -775,13 +787,13 @@ public class UserPreferences {
}
}
- private static float[] readPlaybackSpeedArray(String valueFromPrefs) {
+ private static List<Float> readPlaybackSpeedArray(String valueFromPrefs) {
if (valueFromPrefs != null) {
try {
JSONArray jsonArray = new JSONArray(valueFromPrefs);
- float[] selectedSpeeds = new float[jsonArray.length()];
+ List<Float> selectedSpeeds = new ArrayList<>();
for (int i = 0; i < jsonArray.length(); i++) {
- selectedSpeeds[i] = (float) jsonArray.getDouble(i);
+ selectedSpeeds.add((float) jsonArray.getDouble(i));
}
return selectedSpeeds;
} catch (JSONException e) {
@@ -790,7 +802,7 @@ public class UserPreferences {
}
}
// If this preference hasn't been set yet, return the default options
- return new float[] { 0.75f, 1.0f, 1.25f, 1.5f, 1.75f, 2.0f };
+ return Arrays.asList(0.75f, 1.0f, 1.25f, 1.5f, 1.75f, 2.0f);
}
public static String getMediaPlayer() {
@@ -826,8 +838,8 @@ public class UserPreferences {
public static VideoBackgroundBehavior getVideoBackgroundBehavior() {
switch (prefs.getString(PREF_VIDEO_BEHAVIOR, "pip")) {
case "stop": return VideoBackgroundBehavior.STOP;
- case "pip": return VideoBackgroundBehavior.PICTURE_IN_PICTURE;
case "continue": return VideoBackgroundBehavior.CONTINUE_PLAYING;
+ case "pip": //Deliberate fall-through
default: return VideoBackgroundBehavior.PICTURE_IN_PICTURE;
}
}
@@ -914,7 +926,6 @@ public class UserPreferences {
prefs.edit()
.putString(PREF_DATA_FOLDER, dir)
.apply();
- createImportDirectory();
}
/**
@@ -934,24 +945,6 @@ public class UserPreferences {
}
/**
- * Creates the import directory if it doesn't exist and if storage is
- * available
- */
- private static void createImportDirectory() {
- File importDir = getDataFolder(IMPORT_DIR);
- if (importDir != null) {
- if (importDir.exists()) {
- Log.d(TAG, "Import directory already exists");
- } else {
- Log.d(TAG, "Creating import directory");
- importDir.mkdir();
- }
- } else {
- Log.d(TAG, "Could not access external storage.");
- }
- }
-
- /**
*
* @return true if auto update is set to a specific time
* false if auto update is set to interval
@@ -977,11 +970,11 @@ public class UserPreferences {
public static BackButtonBehavior getBackButtonBehavior() {
switch (prefs.getString(PREF_BACK_BUTTON_BEHAVIOR, "default")) {
- case "default": return BackButtonBehavior.DEFAULT;
case "drawer": return BackButtonBehavior.OPEN_DRAWER;
case "doubletap": return BackButtonBehavior.DOUBLE_TAP;
case "prompt": return BackButtonBehavior.SHOW_PROMPT;
case "page": return BackButtonBehavior.GO_TO_PAGE;
+ case "default": // Deliberate fall-through
default: return BackButtonBehavior.DEFAULT;
}
}
@@ -1052,4 +1045,16 @@ public class UserPreferences {
.putString(PREF_QUEUE_KEEP_SORTED_ORDER, sortOrder.name())
.apply();
}
+
+ public static int getFeedFilter() {
+ String value = prefs.getString(PREF_FILTER_FEED, "" + FEED_FILTER_NONE);
+ return Integer.parseInt(value);
+ }
+
+ public static void setFeedFilter(String value) {
+ prefs.edit()
+ .putString(PREF_FILTER_FEED, value)
+ .commit();
+ }
+
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java b/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java
index f39ac0df8..7585e9d33 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java
@@ -121,7 +121,7 @@ public class PlayerWidgetJobService extends SafeJobIntentService {
views.setOnClickPendingIntent(R.id.layout_left, startMediaPlayer);
try {
- Bitmap icon = null;
+ Bitmap icon;
int iconSize = getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
icon = Glide.with(PlayerWidgetJobService.this)
.asBitmap()
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java
index d0484f2a2..9d0b3c5ad 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java
@@ -156,8 +156,8 @@ public class AntennapodHttpClient {
// workaround for Android 4.x for certain web sites.
// see: https://github.com/square/okhttp/issues/4053#issuecomment-402579554
- List<CipherSuite> cipherSuites = new ArrayList<>();
- cipherSuites.addAll(ConnectionSpec.MODERN_TLS.cipherSuites());
+ List<CipherSuite> cipherSuites = new ArrayList<>(
+ ConnectionSpec.MODERN_TLS.cipherSuites());
cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA);
cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java
index 78c4d3f48..3f503c6b4 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java
@@ -115,7 +115,7 @@ public class DownloadRequest implements Parcelable {
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || !(o instanceof DownloadRequest)) return false;
+ if (!(o instanceof DownloadRequest)) return false;
DownloadRequest that = (DownloadRequest) o;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java
index e65e6fe26..61608992b 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java
@@ -190,7 +190,7 @@ public class HttpDownloader extends Downloader {
}
byte[] buffer = new byte[BUFFER_SIZE];
- int count = 0;
+ int count;
request.setStatusMsg(R.string.download_running);
Log.d(TAG, "Getting size of download");
request.setSize(responseBody.contentLength() + request.getSoFar());
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java
index dddf442f3..71bbf2efd 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java
@@ -8,7 +8,6 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.ExoPlaybackException;
-import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
@@ -76,9 +75,11 @@ public class ExoPlayerWrapper implements IPlayer {
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS,
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS);
loadControl.setBackBuffer(UserPreferences.getRewindSecs() * 1000 + 500, true);
- trackSelector = new DefaultTrackSelector();
- exoPlayer = ExoPlayerFactory.newSimpleInstance(context, new DefaultRenderersFactory(context),
- trackSelector, loadControl.createDefaultLoadControl());
+ trackSelector = new DefaultTrackSelector(context);
+ exoPlayer = new SimpleExoPlayer.Builder(context, new DefaultRenderersFactory(context))
+ .setTrackSelector(trackSelector)
+ .setLoadControl(loadControl.createDefaultLoadControl())
+ .build();
exoPlayer.setSeekParameters(SeekParameters.EXACT);
exoPlayer.addListener(new Player.EventListener() {
@Override
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 585510ef8..9b373b3b9 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
@@ -19,7 +19,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Vibrator;
-import android.preference.PreferenceManager;
+import androidx.preference.PreferenceManager;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.core.app.NotificationCompat;
@@ -419,7 +419,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
e.printStackTrace();
}
} else if (parentId.startsWith("FeedId:")) {
- Long feedId = Long.parseLong(parentId.split(":")[1]);
+ long feedId = Long.parseLong(parentId.split(":")[1]);
List<FeedItem> feedItems = DBReader.getFeedItemList(DBReader.getFeed(feedId));
for (FeedItem feedItem : feedItems) {
if (feedItem.getMedia() != null && feedItem.getMedia().getMediaItem() != null) {
@@ -711,9 +711,12 @@ public class PlaybackService extends MediaBrowserServiceCompat {
}
@Override
- public void onSleepTimerAlmostExpired() {
- float leftVolume = 0.1f * UserPreferences.getLeftVolume();
- float rightVolume = 0.1f * UserPreferences.getRightVolume();
+ public void onSleepTimerAlmostExpired(long timeLeft) {
+ final float[] multiplicators = {0.1f, 0.2f, 0.3f, 0.3f, 0.3f, 0.4f, 0.4f, 0.4f, 0.6f, 0.8f};
+ float multiplicator = multiplicators[Math.max(0, (int) timeLeft / 1000)];
+ Log.d(TAG, "onSleepTimerAlmostExpired: " + multiplicator);
+ float leftVolume = multiplicator * UserPreferences.getLeftVolume();
+ float rightVolume = multiplicator * UserPreferences.getRightVolume();
mediaPlayer.setVolume(leftVolume, rightVolume);
}
@@ -1140,13 +1143,11 @@ public class PlaybackService extends MediaBrowserServiceCompat {
case INITIALIZING:
state = PlaybackStateCompat.STATE_CONNECTING;
break;
- case INITIALIZED:
- case INDETERMINATE:
- state = PlaybackStateCompat.STATE_NONE;
- break;
case ERROR:
state = PlaybackStateCompat.STATE_ERROR;
break;
+ case INITIALIZED: // Deliberate fall-through
+ case INDETERMINATE:
default:
state = PlaybackStateCompat.STATE_NONE;
break;
@@ -1158,7 +1159,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
long capabilities = PlaybackStateCompat.ACTION_PLAY_PAUSE
| PlaybackStateCompat.ACTION_REWIND
| PlaybackStateCompat.ACTION_FAST_FORWARD
- | PlaybackStateCompat.ACTION_SKIP_TO_NEXT;
+ | PlaybackStateCompat.ACTION_SKIP_TO_NEXT
+ | PlaybackStateCompat.ACTION_SEEK_TO;
if (useSkipToPreviousForRewindInLockscreen()) {
// Workaround to fool Android so that Lockscreen will expose a skip-to-previous button,
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java
index 4bb88200a..3239f3378 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java
@@ -183,15 +183,14 @@ public class PlaybackServiceNotificationBuilder {
notification.addAction(R.drawable.ic_notification_pause, //pause action
context.getString(R.string.pause_label),
pauseButtonPendingIntent);
- compactActionList.add(numActions++);
} else {
PendingIntent playButtonPendingIntent = getPendingIntentForMediaAction(
KeyEvent.KEYCODE_MEDIA_PLAY, numActions);
notification.addAction(R.drawable.ic_notification_play, //play action
context.getString(R.string.play_label),
playButtonPendingIntent);
- compactActionList.add(numActions++);
}
+ compactActionList.add(numActions++);
// ff follows play, then we have skip (if it's present)
PendingIntent ffButtonPendingIntent = getPendingIntentForMediaAction(
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java
index afa7fcebf..883ba6023 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java
@@ -360,7 +360,8 @@ public class PlaybackServiceTaskManager {
class SleepTimer implements Runnable {
private static final String TAG = "SleepTimer";
private static final long UPDATE_INTERVAL = 1000L;
- private static final long NOTIFICATION_THRESHOLD = 10000;
+ public static final long NOTIFICATION_THRESHOLD = 10000;
+ private boolean hasVibrated = false;
private final long waitingTime;
private long timeLeft;
private ShakeListener shakeListener;
@@ -390,7 +391,6 @@ public class PlaybackServiceTaskManager {
@Override
public void run() {
Log.d(TAG, "Starting");
- boolean notifiedAlmostExpired = false;
long lastTick = System.currentTimeMillis();
while (timeLeft > 0) {
try {
@@ -405,19 +405,19 @@ public class PlaybackServiceTaskManager {
timeLeft -= now - lastTick;
lastTick = now;
- if (timeLeft < NOTIFICATION_THRESHOLD && !notifiedAlmostExpired) {
+ if (timeLeft < NOTIFICATION_THRESHOLD) {
Log.d(TAG, "Sleep timer is about to expire");
- if (SleepTimerPreferences.vibrate()) {
+ if (SleepTimerPreferences.vibrate() && !hasVibrated) {
Vibrator v = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
if (v != null) {
v.vibrate(500);
+ hasVibrated = true;
}
}
if (shakeListener == null && SleepTimerPreferences.shakeToReset()) {
shakeListener = new ShakeListener(context, this);
}
- postCallback(callback::onSleepTimerAlmostExpired);
- notifiedAlmostExpired = true;
+ postCallback(() -> callback.onSleepTimerAlmostExpired(timeLeft));
}
if (timeLeft <= 0) {
Log.d(TAG, "Sleep timer expired");
@@ -425,6 +425,7 @@ public class PlaybackServiceTaskManager {
shakeListener.pause();
shakeListener = null;
}
+ hasVibrated = false;
if (!Thread.currentThread().isInterrupted()) {
postCallback(callback::onSleepTimerExpired);
} else {
@@ -461,7 +462,7 @@ public class PlaybackServiceTaskManager {
public interface PSTMCallback {
void positionSaverTick();
- void onSleepTimerAlmostExpired();
+ void onSleepTimerAlmostExpired(long timeLeft);
void onSleepTimerExpired();
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java
index b0b6e164d..b967577af 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java
@@ -58,7 +58,6 @@ class ShakeListener implements SensorEventListener
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
- return;
}
} \ No newline at end of file
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 c30f46315..0de67b306 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
@@ -72,19 +72,13 @@ public final class DBReader {
@NonNull
private static List<Feed> getFeedList(PodDBAdapter adapter) {
- Cursor cursor = null;
- try {
- cursor = adapter.getAllFeedsCursor();
+ try (Cursor cursor = adapter.getAllFeedsCursor()) {
List<Feed> feeds = new ArrayList<>(cursor.getCount());
while (cursor.moveToNext()) {
Feed feed = extractFeedFromCursorRow(cursor);
feeds.add(feed);
}
return feeds;
- } finally {
- if (cursor != null) {
- cursor.close();
- }
}
}
@@ -96,18 +90,13 @@ public final class DBReader {
public static List<String> getFeedListDownloadUrls() {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getFeedCursorDownloadUrls();
+ try (Cursor cursor = adapter.getFeedCursorDownloadUrls()) {
List<String> result = new ArrayList<>(cursor.getCount());
while (cursor.moveToNext()) {
result.add(cursor.getString(1));
}
return result;
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -172,9 +161,7 @@ public final class DBReader {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getAllItemsOfFeedCursor(feed);
+ try (Cursor cursor = adapter.getAllItemsOfFeedCursor(feed)) {
List<FeedItem> items = extractItemlistFromCursor(adapter, cursor);
Collections.sort(items, new FeedItemPubdateComparator());
for (FeedItem item : items) {
@@ -182,9 +169,6 @@ public final class DBReader {
}
return items;
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -226,16 +210,10 @@ public final class DBReader {
@NonNull
static List<FeedItem> getQueue(PodDBAdapter adapter) {
Log.d(TAG, "getQueue()");
- Cursor cursor = null;
- try {
- cursor = adapter.getQueueCursor();
+ try (Cursor cursor = adapter.getQueueCursor()) {
List<FeedItem> items = extractItemlistFromCursor(adapter, cursor);
loadAdditionalFeedItemListData(items);
return items;
- } finally {
- if (cursor != null) {
- cursor.close();
- }
}
}
@@ -257,18 +235,12 @@ public final class DBReader {
}
private static LongList getQueueIDList(PodDBAdapter adapter) {
- Cursor cursor = null;
- try {
- cursor = adapter.getQueueIDCursor();
+ try (Cursor cursor = adapter.getQueueIDCursor()) {
LongList queueIds = new LongList(cursor.getCount());
while (cursor.moveToNext()) {
queueIds.add(cursor.getLong(0));
}
return queueIds;
- } finally {
- if (cursor != null) {
- cursor.close();
- }
}
}
@@ -302,17 +274,12 @@ public final class DBReader {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getDownloadedItemsCursor();
+ try (Cursor cursor = adapter.getDownloadedItemsCursor()) {
List<FeedItem> items = extractItemlistFromCursor(adapter, cursor);
loadAdditionalFeedItemListData(items);
Collections.sort(items, new FeedItemPubdateComparator());
return items;
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -328,16 +295,11 @@ public final class DBReader {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getPlayedItemsCursor();
+ try (Cursor cursor = adapter.getPlayedItemsCursor()) {
List<FeedItem> items = extractItemlistFromCursor(adapter, cursor);
loadAdditionalFeedItemListData(items);
return items;
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -355,16 +317,11 @@ public final class DBReader {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getNewItemsCursor(offset, limit);
+ try (Cursor cursor = adapter.getNewItemsCursor(offset, limit)) {
List<FeedItem> items = extractItemlistFromCursor(adapter, cursor);
loadAdditionalFeedItemListData(items);
return items;
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -381,16 +338,11 @@ public final class DBReader {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getFavoritesCursor(offset, limit);
+ try (Cursor cursor = adapter.getFavoritesCursor(offset, limit)) {
List<FeedItem> items = extractItemlistFromCursor(adapter, cursor);
loadAdditionalFeedItemListData(items);
return items;
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -400,18 +352,13 @@ public final class DBReader {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getFavoritesCursor(0, Integer.MAX_VALUE);
+ try (Cursor cursor = adapter.getFavoritesCursor(0, Integer.MAX_VALUE)) {
LongList favoriteIDs = new LongList(cursor.getCount());
while (cursor.moveToNext()) {
favoriteIDs.add(cursor.getLong(0));
}
return favoriteIDs;
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -428,16 +375,11 @@ public final class DBReader {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getRecentlyPublishedItemsCursor(offset, limit);
+ try (Cursor cursor = adapter.getRecentlyPublishedItemsCursor(offset, limit)) {
List<FeedItem> items = extractItemlistFromCursor(adapter, cursor);
loadAdditionalFeedItemListData(items);
return items;
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -492,9 +434,7 @@ public final class DBReader {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getDownloadLogCursor(DOWNLOAD_LOG_SIZE);
+ try (Cursor cursor = adapter.getDownloadLogCursor(DOWNLOAD_LOG_SIZE)) {
List<DownloadStatus> downloadLog = new ArrayList<>(cursor.getCount());
while (cursor.moveToNext()) {
downloadLog.add(DownloadStatus.fromCursor(cursor));
@@ -502,9 +442,6 @@ public final class DBReader {
Collections.sort(downloadLog, new DownloadStatusComparator());
return downloadLog;
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -521,9 +458,7 @@ public final class DBReader {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getDownloadLog(Feed.FEEDFILETYPE_FEED, feedId);
+ try (Cursor cursor = adapter.getDownloadLog(Feed.FEEDFILETYPE_FEED, feedId)) {
List<DownloadStatus> downloadLog = new ArrayList<>(cursor.getCount());
while (cursor.moveToNext()) {
downloadLog.add(DownloadStatus.fromCursor(cursor));
@@ -531,9 +466,6 @@ public final class DBReader {
Collections.sort(downloadLog, new DownloadStatusComparator());
return downloadLog;
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -560,9 +492,7 @@ public final class DBReader {
@Nullable
static Feed getFeed(final long feedId, PodDBAdapter adapter) {
Feed feed = null;
- Cursor cursor = null;
- try {
- cursor = adapter.getFeedCursor(feedId);
+ try (Cursor cursor = adapter.getFeedCursor(feedId)) {
if (cursor.moveToNext()) {
feed = extractFeedFromCursorRow(cursor);
feed.setItems(getFeedItemList(feed));
@@ -570,10 +500,6 @@ public final class DBReader {
Log.e(TAG, "getFeed could not find feed with id " + feedId);
}
return feed;
- } finally {
- if (cursor != null) {
- cursor.close();
- }
}
}
@@ -582,9 +508,7 @@ public final class DBReader {
Log.d(TAG, "Loading feeditem with id " + itemId);
FeedItem item = null;
- Cursor cursor = null;
- try {
- cursor = adapter.getFeedItemCursor(Long.toString(itemId));
+ try (Cursor cursor = adapter.getFeedItemCursor(Long.toString(itemId))) {
if (cursor.moveToNext()) {
List<FeedItem> list = extractItemlistFromCursor(adapter, cursor);
if (!list.isEmpty()) {
@@ -593,10 +517,6 @@ public final class DBReader {
}
}
return item;
- } finally {
- if (cursor != null) {
- cursor.close();
- }
}
}
@@ -631,9 +551,7 @@ public final class DBReader {
@Nullable
private static FeedItem getFeedItemByUrl(final String podcastUrl, final String episodeUrl, PodDBAdapter adapter) {
Log.d(TAG, "Loading feeditem with podcast url " + podcastUrl + " and episode url " + episodeUrl);
- Cursor cursor = null;
- try {
- cursor = adapter.getFeedItemCursor(podcastUrl, episodeUrl);
+ try (Cursor cursor = adapter.getFeedItemCursor(podcastUrl, episodeUrl)) {
if (!cursor.moveToNext()) {
return null;
}
@@ -642,10 +560,6 @@ public final class DBReader {
return list.get(0);
}
return null;
- } finally {
- if (cursor != null) {
- cursor.close();
- }
}
}
@@ -668,10 +582,8 @@ public final class DBReader {
}
private static String getImageAuthentication(final String imageUrl, PodDBAdapter adapter) {
- String credentials = null;
- Cursor cursor = null;
- try {
- cursor = adapter.getImageAuthenticationCursor(imageUrl);
+ String credentials;
+ try (Cursor cursor = adapter.getImageAuthenticationCursor(imageUrl)) {
if (cursor.moveToFirst()) {
String username = cursor.getString(0);
String password = cursor.getString(1);
@@ -683,10 +595,6 @@ public final class DBReader {
} else {
credentials = "";
}
- } finally {
- if (cursor != null) {
- cursor.close();
- }
}
return credentials;
}
@@ -720,9 +628,7 @@ public final class DBReader {
Log.d(TAG, "loadDescriptionOfFeedItem() called with: " + "item = [" + item + "]");
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getDescriptionOfItem(item);
+ try (Cursor cursor = adapter.getDescriptionOfItem(item)) {
if (cursor.moveToFirst()) {
int indexDescription = cursor.getColumnIndex(PodDBAdapter.KEY_DESCRIPTION);
String description = cursor.getString(indexDescription);
@@ -732,9 +638,6 @@ public final class DBReader {
item.setContentEncoded(contentEncoded);
}
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -898,6 +801,16 @@ public final class DBReader {
}
final LongIntMap feedCounters = adapter.getFeedCounters(feedIds);
+ int feedFilter = UserPreferences.getFeedFilter();
+ if (feedFilter == UserPreferences.FEED_FILTER_COUNTER_ZERO) {
+ for (int i = feeds.size() - 1; i >= 0; i--) {
+ if (feedCounters.get(feeds.get(i).getId()) <= 0) {
+ feedCounters.delete(feeds.get(i).getId());
+ feeds.remove(i);
+ }
+ }
+ }
+
Comparator<Feed> comparator;
int feedOrder = UserPreferences.getFeedOrder();
if (feedOrder == UserPreferences.FEED_ORDER_COUNTER) {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java
index f10dde65f..e3121caa2 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java
@@ -340,7 +340,7 @@ public class DownloadRequester implements DownloadStateProvider {
/**
* Checks if feedfile is in the downloads list
*/
- public synchronized boolean isDownloadingFile(FeedFile item) {
+ public synchronized boolean isDownloadingFile(@NonNull FeedFile item) {
return item.getDownload_url() != null && downloads.containsKey(item.getDownload_url());
}
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 e6d47b32a..8a3f44e18 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
@@ -1218,7 +1218,7 @@ public class PodDBAdapter {
public Cursor searchItems(long feedID, String searchQuery) {
String preparedQuery = prepareSearchQuery(searchQuery);
- String queryFeedId = "";
+ String queryFeedId;
if (feedID != 0) {
// search items in specific feed
queryFeedId = KEY_FEED + " = " + feedID;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java b/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java
index eae7a08af..62c8ce5f3 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java
@@ -21,7 +21,6 @@ import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
-import org.apache.commons.io.Charsets;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -34,6 +33,7 @@ import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
+import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
@@ -505,7 +505,7 @@ public class GpodnetService implements ISyncService {
RequestBody requestBody = RequestBody.create(TEXT, "");
Request request = new Request.Builder().url(url).post(requestBody).build();
try {
- String credential = Credentials.basic(username, password, Charsets.UTF_8);
+ String credential = Credentials.basic(username, password, Charset.forName("UTF-8"));
Request authRequest = request.newBuilder().header("Authorization", credential).build();
Response response = httpClient.newCall(authRequest).execute();
checkStatusCode(response);
@@ -519,8 +519,8 @@ public class GpodnetService implements ISyncService {
private String executeRequest(@NonNull Request.Builder requestB) throws GpodnetServiceException {
Request request = requestB.build();
- String responseString = null;
- Response response = null;
+ String responseString;
+ Response response;
ResponseBody body = null;
try {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeAction.java b/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeAction.java
index 6154ccc84..798be8d96 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeAction.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeAction.java
@@ -3,6 +3,7 @@ package de.danoeh.antennapod.core.sync.model;
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.NonNull;
import androidx.core.util.ObjectsCompat;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.util.DateUtils;
@@ -179,6 +180,7 @@ public class EpisodeAction {
return obj;
}
+ @NonNull
@Override
public String toString() {
return "EpisodeAction{"
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeActionChanges.java b/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeActionChanges.java
index 77942ffa0..90af585af 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeActionChanges.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeActionChanges.java
@@ -23,6 +23,7 @@ public class EpisodeActionChanges {
return this.timestamp;
}
+ @NonNull
@Override
public String toString() {
return "EpisodeActionGetResponse{"
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/AtomText.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/AtomText.java
index e85d5fae1..0c0561279 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/AtomText.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/AtomText.java
@@ -1,7 +1,7 @@
package de.danoeh.antennapod.core.syndication.namespace.atom;
-import android.os.Build;
-import android.text.Html;
+import androidx.core.text.HtmlCompat;
+
import de.danoeh.antennapod.core.syndication.namespace.Namespace;
import de.danoeh.antennapod.core.syndication.namespace.SyndElement;
@@ -24,11 +24,7 @@ public class AtomText extends SyndElement {
if (type == null) {
return content;
} else if (type.equals(TYPE_HTML)) {
- if (Build.VERSION.SDK_INT >= 24) {
- return Html.fromHtml(content, Html.FROM_HTML_MODE_LEGACY).toString();
- } else {
- return Html.fromHtml(content).toString();
- }
+ return HtmlCompat.fromHtml(content, HtmlCompat.FROM_HTML_MODE_LEGACY).toString();
} else if (type.equals(TYPE_XHTML)) {
return content;
} else { // Handle as text by default
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/FileNameGenerator.java b/core/src/main/java/de/danoeh/antennapod/core/util/FileNameGenerator.java
index 220a783f3..2a387b7b0 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/FileNameGenerator.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/FileNameGenerator.java
@@ -4,6 +4,7 @@ import android.text.TextUtils;
import androidx.annotation.VisibleForTesting;
import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
@@ -29,6 +30,7 @@ public class FileNameGenerator {
* characters of the given string.
*/
public static String generateFileName(String string) {
+ string = StringUtils.stripAccents(string);
StringBuilder buf = new StringBuilder();
for (int i = 0; i < string.length(); i++) {
char c = string.charAt(i);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/RewindAfterPauseUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/RewindAfterPauseUtils.java
index 366f86707..813c6d0f7 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/RewindAfterPauseUtils.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/RewindAfterPauseUtils.java
@@ -39,7 +39,7 @@ public class RewindAfterPauseUtils {
int newPosition = currentPosition - (int) rewindTime;
- return newPosition > 0 ? newPosition : 0;
+ return Math.max(newPosition, 0);
} else {
return currentPosition;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/ChapterStartTimeComparator.java b/core/src/main/java/de/danoeh/antennapod/core/util/comparator/ChapterStartTimeComparator.java
index 8bd23c2ed..920a1ef8a 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/ChapterStartTimeComparator.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/comparator/ChapterStartTimeComparator.java
@@ -8,13 +8,7 @@ public class ChapterStartTimeComparator implements Comparator<Chapter> {
@Override
public int compare(Chapter lhs, Chapter rhs) {
- if (lhs.getStart() == rhs.getStart()) {
- return 0;
- } else if (lhs.getStart() < rhs.getStart()) {
- return -1;
- } else {
- return 1;
- }
+ return Long.compare(lhs.getStart(), rhs.getStart());
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/download/AutoUpdateManager.java b/core/src/main/java/de/danoeh/antennapod/core/util/download/AutoUpdateManager.java
index 991089910..a8ca43ccb 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/download/AutoUpdateManager.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/download/AutoUpdateManager.java
@@ -118,9 +118,8 @@ public class AutoUpdateManager {
*/
public static void runImmediate(@NonNull Context context) {
Log.d(TAG, "Run auto update immediately in background.");
- new Thread(() -> {
- DBTasks.refreshAllFeeds(context.getApplicationContext(), true);
- }, "ManualRefreshAllFeeds").start();
+ new Thread(() -> DBTasks.refreshAllFeeds(
+ context.getApplicationContext(), true), "ManualRefreshAllFeeds").start();
}
public static void disableAutoUpdate(Context context) {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java
index aec53da4c..fecb14d25 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java
@@ -2,7 +2,7 @@ package de.danoeh.antennapod.core.util.playback;
import android.content.Context;
import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
+import androidx.preference.PreferenceManager;
import android.util.Log;
import android.view.SurfaceHolder;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java
index 24aabf212..c44c0f925 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java
@@ -3,7 +3,7 @@ package de.danoeh.antennapod.core.util.playback;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Parcelable;
-import android.preference.PreferenceManager;
+import androidx.preference.PreferenceManager;
import androidx.annotation.Nullable;
import android.util.Log;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java
index 44f5f9b11..d47d26af9 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java
@@ -599,6 +599,13 @@ public class PlaybackController {
}
public void setPlaybackSpeed(float speed) {
+ PlaybackPreferences.setCurrentlyPlayingTemporaryPlaybackSpeed(speed);
+ if (getMedia() != null && getMedia().getMediaType() == MediaType.VIDEO) {
+ UserPreferences.setVideoPlaybackSpeed(speed);
+ } else {
+ UserPreferences.setPlaybackSpeed(speed);
+ }
+
if (playbackService != null) {
playbackService.setSpeed(speed);
} else {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/OggInputStream.java b/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/OggInputStream.java
index cdf171299..9277af6e6 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/OggInputStream.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/OggInputStream.java
@@ -39,7 +39,7 @@ class OggInputStream extends InputStream {
private void readOggPage() throws IOException {
// find OggS
int[] buffer = new int[4];
- int c = 0;
+ int c;
boolean isInOggS = false;
while ((c = input.read()) != -1) {
switch (c) {
diff --git a/core/src/main/res/color/filter_dialog_background_dark.xml b/core/src/main/res/color/filter_dialog_background_dark.xml
new file mode 100644
index 000000000..3df2a80dc
--- /dev/null
+++ b/core/src/main/res/color/filter_dialog_background_dark.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="@color/accent_dark" android:state_checked="true"/>
+ <item android:color="@color/dialog_filter_inactive_dark" />
+</selector> \ No newline at end of file
diff --git a/core/src/main/res/color/filter_dialog_background_light.xml b/core/src/main/res/color/filter_dialog_background_light.xml
new file mode 100644
index 000000000..930325629
--- /dev/null
+++ b/core/src/main/res/color/filter_dialog_background_light.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="@color/accent_light" android:state_checked="true" />
+ <item android:color="@color/dialog_filter_inactive_light" />
+</selector> \ No newline at end of file
diff --git a/core/src/main/res/color/filter_dialog_button_text.xml b/core/src/main/res/color/filter_dialog_button_text.xml
new file mode 100644
index 000000000..fea8b3e74
--- /dev/null
+++ b/core/src/main/res/color/filter_dialog_button_text.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="?attr/colorOnSecondary" android:state_checked="true" />
+ <item android:color="?android:textColorPrimary" />
+</selector> \ No newline at end of file
diff --git a/core/src/main/res/color/filter_dialog_clear_dark.xml b/core/src/main/res/color/filter_dialog_clear_dark.xml
new file mode 100644
index 000000000..88e022d0f
--- /dev/null
+++ b/core/src/main/res/color/filter_dialog_clear_dark.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="@color/dialog_filter_inactive_dark" android:state_checked="true" />
+ <item android:color="@color/dialog_filter_clear_inactive_dark" />
+</selector> \ No newline at end of file
diff --git a/core/src/main/res/color/filter_dialog_clear_light.xml b/core/src/main/res/color/filter_dialog_clear_light.xml
new file mode 100644
index 000000000..9d513f72a
--- /dev/null
+++ b/core/src/main/res/color/filter_dialog_clear_light.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="@color/dialog_filter_inactive_light" android:state_checked="true" />
+ <item android:color="@color/dialog_filter_clear_inactive_light" />
+</selector> \ No newline at end of file
diff --git a/core/src/main/res/drawable/ic_filter_close.xml b/core/src/main/res/drawable/ic_filter_close.xml
new file mode 100644
index 000000000..9e0a26905
--- /dev/null
+++ b/core/src/main/res/drawable/ic_filter_close.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:bottom="5dp"
+ android:left="5dp"
+ android:right="5dp"
+ android:top="5dp">
+
+ <shape android:shape="oval">
+ <stroke
+ android:width="4dp"
+ android:color="?attr/filter_dialog_clear" />
+ </shape>
+ </item>
+
+ <!-- x -->
+ <item
+ android:bottom="12dp"
+ android:left="12dp"
+ android:right="12dp"
+ android:top="12dp">
+ <rotate
+ android:fromDegrees="135"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:toDegrees="135">
+ <shape android:shape="line">
+ <stroke
+ android:width="4dp"
+ android:color="?attr/filter_dialog_clear" />
+ </shape>
+ </rotate>
+ </item>
+
+ <item
+ android:bottom="12dp"
+ android:left="12dp"
+ android:right="12dp"
+ android:top="12dp">
+ <rotate
+ android:fromDegrees="45"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:toDegrees="45">
+ <shape android:shape="line">
+ <stroke
+ android:width="4dp"
+ android:color="?attr/filter_dialog_clear" />
+ </shape>
+
+ </rotate>
+ </item>
+
+</layer-list> \ No newline at end of file
diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml
index dc79905cd..ba6c2f196 100644
--- a/core/src/main/res/values/arrays.xml
+++ b/core/src/main/res/values/arrays.xml
@@ -233,6 +233,16 @@
<item>3</item>
</string-array>
+ <string-array name="nav_drawer_feed_filter_values">
+ <item>0</item>
+ <item>1</item>
+ </string-array>
+
+ <string-array name="nav_drawer_feed_filter_options">
+ <item>@string/no_filter_label</item>
+ <item>@string/hide_subscriptions_where_counter_is_zero</item>
+ </string-array>
+
<string-array name="media_player_options">
<item>@string/media_player_builtin</item>
<item>@string/media_player_sonic</item>
@@ -245,30 +255,6 @@
<item>exoplayer</item>
</string-array>
- <string-array name="episode_filter_options">
- <item>@string/hide_unplayed_episodes_label</item>
- <item>@string/hide_paused_episodes_label</item>
- <item>@string/hide_played_episodes_label</item>
- <item>@string/hide_queued_episodes_label</item>
- <item>@string/hide_not_queued_episodes_label</item>
- <item>@string/hide_downloaded_episodes_label</item>
- <item>@string/hide_not_downloaded_episodes_label</item>
- <item>@string/hide_has_media_label</item>
- <item>@string/hide_is_favorite_label</item>
- </string-array>
-
- <string-array name="episode_filter_values">
- <item>unplayed</item>
- <item>paused</item>
- <item>played</item>
- <item>queued</item>
- <item>not_queued</item>
- <item>downloaded</item>
- <item>not_downloaded</item>
- <item>has_media</item>
- <item>is_favorite</item>
- </string-array>
-
<!-- sort for podcast screen, not for queue -->
<string-array name="feed_episodes_sort_options">
<item>@string/sort_date_new_old</item>
diff --git a/core/src/main/res/values/attrs.xml b/core/src/main/res/values/attrs.xml
index b89a819f1..4a18f6ae6 100644
--- a/core/src/main/res/values/attrs.xml
+++ b/core/src/main/res/values/attrs.xml
@@ -58,6 +58,8 @@
<attr name="action_icon_color" format="color"/>
<attr name="scrollbar_thumb" format="reference"/>
<attr name="background_elevated" format="color"/>
+ <attr name="filter_dialog_clear" format="reference"/>
+ <attr name="filter_dialog_button_background" format="reference"/>
<declare-styleable name="SquareImageView">
<attr name="direction" format="enum">
diff --git a/core/src/main/res/values/colors.xml b/core/src/main/res/values/colors.xml
index a86d61eba..a55378931 100644
--- a/core/src/main/res/values/colors.xml
+++ b/core/src/main/res/values/colors.xml
@@ -28,4 +28,9 @@
<color name="master_switch_background_light">#DDDDDD</color>
<color name="master_switch_background_dark">#191919</color>
+ <!-- filter dialog -->
+ <color name="dialog_filter_clear_inactive_light">#666666</color>
+ <color name="dialog_filter_clear_inactive_dark">#bbbbbb</color>
+ <color name="dialog_filter_inactive_light">#eeeeee</color>
+ <color name="dialog_filter_inactive_dark">#555555</color>
</resources>
diff --git a/core/src/main/res/values/dimens.xml b/core/src/main/res/values/dimens.xml
index 41a24f6fa..4702a5302 100644
--- a/core/src/main/res/values/dimens.xml
+++ b/core/src/main/res/values/dimens.xml
@@ -38,4 +38,6 @@
<dimen name="media_router_controller_playback_control_start_padding">24dp</dimen>
<dimen name="media_router_controller_bottom_margin">8dp</dimen>
+ <dimen name="nav_drawer_max_screen_size">480dp</dimen>
+
</resources>
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index 93a21ef13..0813d8aa5 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -136,12 +136,13 @@
<string name="feed_settings_label">Podcast settings</string>
<string name="rename_feed_label">Rename podcast</string>
<string name="remove_feed_label">Remove podcast</string>
- <string name="share_label">Share&#8230;</string>
+ <string name="share_label">Share</string>
+ <string name="share_label_with_ellipses">Share…</string>
<string name="share_link_label">Share Episode URL</string>
<string name="share_link_with_position_label">Share Episode URL with Position</string>
<string name="share_file_label">Share File</string>
- <string name="share_website_url_label">Share Website URL</string>
- <string name="share_feed_url_label">Share Podcast URL</string>
+ <string name="share_website_url_label">Website address</string>
+ <string name="share_feed_url_label">Podcast feed URL</string>
<string name="share_item_url_label">Share Media File URL</string>
<string name="share_item_url_with_position_label">Share Media File URL with Position</string>
<string name="feed_delete_confirmation_msg">Please confirm that you want to delete the podcast \"%1$s\" and ALL its episodes (including downloaded episodes).</string>
@@ -151,14 +152,9 @@
<string name="select_all_above">Select all above</string>
<string name="select_all_below">Select all below</string>
<string name="hide_unplayed_episodes_label">Unplayed</string>
- <string name="hide_paused_episodes_label">Paused</string>
- <string name="hide_played_episodes_label">Played</string>
<string name="hide_queued_episodes_label">Queued</string>
<string name="hide_not_queued_episodes_label">Not queued</string>
- <string name="hide_downloaded_episodes_label">Downloaded</string>
- <string name="hide_not_downloaded_episodes_label">Not downloaded</string>
<string name="hide_has_media_label">Has media</string>
- <string name="hide_is_favorite_label">Is favorite</string>
<string name="filtered_label">Filtered</string>
<string name="refresh_failed_msg">{fa-exclamation-circle} Last Refresh failed</string>
<string name="open_podcast">Open Podcast</string>
@@ -315,8 +311,9 @@
<string name="download_plugin_label">Download Plugin</string>
<string name="no_playback_plugin_title">Plugin Not Installed</string>
<string name="no_playback_plugin_or_sonic_msg">For variable speed playback to work, we recommend to enable the built-in Sonic mediaplayer.</string>
- <string name="set_playback_speed_label">Playback Speeds</string>
<string name="enable_sonic">Enable Sonic</string>
+ <string name="speed_presets">Presets</string>
+ <string name="preset_already_exists">%1$.2fx is already saved as a preset.</string>
<!-- Empty list labels -->
<string name="no_items_header_label">No queued episodes</string>
@@ -391,7 +388,7 @@
<string name="pref_autoUpdateIntervallOrTime_every">every %1$s</string>
<string name="pref_autoUpdateIntervallOrTime_at">at %1$s</string>
<string name="pref_followQueue_title">Continuous Playback</string>
- <string name="pref_pauseOnHeadsetDisconnect_title">Headphones Disconnect</string>
+ <string name="pref_pauseOnHeadsetDisconnect_title">Headphones or Bluetooth disconnect</string>
<string name="pref_unpauseOnHeadsetReconnect_title">Headphones Reconnect</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Bluetooth Reconnect</string>
<string name="pref_stream_over_download_title">Prefer Streaming</string>
@@ -404,7 +401,7 @@
<string name="pref_mobileUpdate_episode_download">Episode download</string>
<string name="pref_mobileUpdate_streaming">Streaming</string>
<string name="user_interface_label">User Interface</string>
- <string name="user_interface_sum">Appearance, Subscription order, Lockscreen</string>
+ <string name="user_interface_sum">Appearance, Subscriptions, Lockscreen</string>
<string name="pref_set_theme_title">Select Theme</string>
<string name="pref_nav_drawer_items_title">Set Navigation Drawer items</string>
<string name="pref_nav_drawer_items_sum">Change which items appear in the navigation drawer.</string>
@@ -445,8 +442,7 @@
<string name="pref_gpodnet_login_status"><![CDATA[Logged in as <i>%1$s</i> with device <i>%2$s</i>]]></string>
<string name="pref_gpodnet_notifications_title">Show sync error notifications</string>
<string name="pref_gpodnet_notifications_sum">This setting does not apply to authentication errors.</string>
- <string name="pref_playback_speed_title">Playback Speeds</string>
- <string name="pref_playback_speed_sum">Customize the speeds available for variable speed audio playback</string>
+ <string name="pref_playback_speed_sum">Customize the speeds available for variable speed playback</string>
<string name="pref_feed_playback_speed_sum">The speed to use when starting audio playback for episodes in this podcast</string>
<string name="pref_feed_skip">Auto Skip</string>
<string name="pref_feed_skip_sum">Skip introductions and ending credits.</string>
@@ -526,6 +522,11 @@
<string name="back_button_go_to_page_title">Select page</string>
<string name="pref_delete_removes_from_queue_title">Delete removes from Queue</string>
<string name="pref_delete_removes_from_queue_sum">Automatically remove an episode from the queue when it is deleted.</string>
+ <string name="pref_filter_feed_title">Subscription Filter</string>
+ <string name="pref_filter_feed_sum">Filter your subscriptions in navigation drawer and subscriptions screen.</string>
+ <string name="hide_subscriptions_where_counter_is_zero">Hide if counter is zero</string>
+ <string name="no_filter_label">None</string>
+ <string name="subscriptions_are_filtered">Subscriptions are filtered.</string>
<!-- About screen -->
<string name="about_pref">About</string>
@@ -714,19 +715,20 @@
<string name="search_itunes_label">Search iTunes</string>
<string name="search_fyyd_label">Search fyyd</string>
<string name="advanced">Advanced</string>
- <string name="add_podcast_by_url">Add Podcast by URL</string>
+ <string name="add_podcast_by_url">Add Podcast by RSS address</string>
<string name="add_podcast_by_url_hint" translatable="false">www.example.com/feed</string>
<string name="browse_gpoddernet_label">Browse gpodder.net</string>
<string name="discover">Discover</string>
<string name="discover_more">more »</string>
- <string name="search_powered_by">Search powered by %1$s</string>
+ <string name="discover_powered_by_itunes">Suggestions by iTunes</string>
+ <string name="search_powered_by">Results by %1$s</string>
<string name="filter">Filter</string>
<!-- Episodes apply actions -->
<string name="all_label">All</string>
<string name="selected_all_label">Selected all Episodes</string>
- <string name="none_label">None</string>
+ <string name="select_none_label">None</string>
<string name="deselected_all_label">Deselected all Episodes</string>
<string name="played_label">Played</string>
<string name="selected_played_label">Selected played Episodes</string>
@@ -736,13 +738,23 @@
<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="queued_label">Queued</string>
<string name="selected_queued_label">Selected queued Episodes</string>
- <string name="not_queued_label">Not queued</string>
<string name="selected_not_queued_label">Selected not queued Episodes</string>
- <string name="has_media">Has media</string>
<string name="selected_has_media_label">Selected episodes with media</string>
+ <string name="hide_is_favorite_label">Is favorite</string>
+ <string name="not_favorite">Not favorite</string>
+ <string name="hide_downloaded_episodes_label">Downloaded</string>
+ <string name="hide_not_downloaded_episodes_label">Not downloaded</string>
+ <string name="queued_label">Queued</string>
+ <string name="not_queued_label">Not queued</string>
+ <string name="has_media">Has media</string>
+ <string name="no_media">No media</string>
+ <string name="hide_paused_episodes_label">Paused</string>
+ <string name="not_paused">Not paused</string>
+ <string name="hide_played_episodes_label">Played</string>
+ <string name="not_played">Not played</string>
+
<!-- Sort -->
<string name="sort_title_a_z">Title (A \u2192 Z)</string>
<string name="sort_title_z_a">Title (Z \u2192 A)</string>
@@ -765,6 +777,12 @@
<string name="rating_later_label">Remind me later</string>
<string name="rating_now_label">Sure, let\'s do this!</string>
+ <!-- Share episode dialog -->
+ <string name="share_dialog_include_label">Include:</string>
+ <string name="share_playback_position_dialog_label">Playback position</string>
+ <string name="share_dialog_media_file_label">Media file URL</string>
+ <string name="share_dialog_episode_website_label">Episode webpage</string>
+
<!-- Audio controls -->
<string name="audio_controls">Audio controls</string>
<string name="playback_speed">Playback Speed</string>
diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml
index ab78eac47..972174da5 100644
--- a/core/src/main/res/values/styles.xml
+++ b/core/src/main/res/values/styles.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android">
+<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
<style name="Theme.AntennaPod.Light" parent="Theme.Base.AntennaPod.Light">
<!-- Room for API dependent attributes -->
@@ -73,6 +73,8 @@
<item name="ic_key">@drawable/ic_key_black</item>
<item name="ic_volume_adaption">@drawable/ic_volume_adaption_black</item>
<item name="scrollbar_thumb">@drawable/scrollbar_thumb_light</item>
+ <item name="filter_dialog_clear">@color/filter_dialog_clear_light</item>
+ <item name="filter_dialog_button_background">@color/filter_dialog_background_light</item>
</style>
<style name="Theme.AntennaPod.Dark" parent="Theme.Base.AntennaPod.Dark">
@@ -148,6 +150,8 @@
<item name="ic_key">@drawable/ic_key_white</item>
<item name="ic_volume_adaption">@drawable/ic_volume_adaption_white</item>
<item name="scrollbar_thumb">@drawable/scrollbar_thumb_dark</item>
+ <item name="filter_dialog_clear">@color/filter_dialog_clear_dark</item>
+ <item name="filter_dialog_button_background">@color/filter_dialog_background_dark</item>
</style>
<style name="Theme.AntennaPod.TrueBlack" parent="Theme.Base.AntennaPod.TrueBlack">
diff --git a/core/src/test/java/de/danoeh/antennapod/core/feed/VolumeAdaptionSettingTest.java b/core/src/test/java/de/danoeh/antennapod/core/feed/VolumeAdaptionSettingTest.java
index 45c86cb83..e933ce034 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/feed/VolumeAdaptionSettingTest.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/feed/VolumeAdaptionSettingTest.java
@@ -5,7 +5,7 @@ import org.junit.Test;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
+import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertTrue;
public class VolumeAdaptionSettingTest {
diff --git a/core/src/test/java/de/danoeh/antennapod/core/storage/ItemEnqueuePositionCalculatorTest.java b/core/src/test/java/de/danoeh/antennapod/core/storage/ItemEnqueuePositionCalculatorTest.java
index 80777d036..ed7d2fa75 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/storage/ItemEnqueuePositionCalculatorTest.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/storage/ItemEnqueuePositionCalculatorTest.java
@@ -13,6 +13,7 @@ import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
+import de.danoeh.antennapod.core.feed.FeedComponent;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.FeedMother;
@@ -27,6 +28,7 @@ import static de.danoeh.antennapod.core.preferences.UserPreferences.EnqueueLocat
import static de.danoeh.antennapod.core.util.CollectionTestUtil.concat;
import static de.danoeh.antennapod.core.util.CollectionTestUtil.list;
import static de.danoeh.antennapod.core.util.FeedItemUtil.getIdList;
+import static java.util.Collections.emptyList;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
@@ -248,13 +250,13 @@ public class ItemEnqueuePositionCalculatorTest {
assertEquals(message, idsExpected, getIdList(queue));
}
- static final List<FeedItem> QUEUE_EMPTY = Collections.unmodifiableList(Arrays.asList());
+ static final List<FeedItem> QUEUE_EMPTY = Collections.unmodifiableList(emptyList());
static final List<FeedItem> QUEUE_DEFAULT =
Collections.unmodifiableList(Arrays.asList(
createFeedItem(11), createFeedItem(12), createFeedItem(13), createFeedItem(14)));
static final List<Long> QUEUE_DEFAULT_IDS =
- QUEUE_DEFAULT.stream().map(fi -> fi.getId()).collect(Collectors.toList());
+ QUEUE_DEFAULT.stream().map(FeedComponent::getId).collect(Collectors.toList());
static Playable getCurrentlyPlaying(long idCurrentlyPlaying) {
diff --git a/core/src/test/java/de/danoeh/antennapod/core/util/FeedItemUtilTest.java b/core/src/test/java/de/danoeh/antennapod/core/util/FeedItemUtilTest.java
index 2560ac6a0..a3744035b 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/util/FeedItemUtilTest.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/util/FeedItemUtilTest.java
@@ -7,6 +7,7 @@ import org.junit.runners.Parameterized.Parameters;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
@@ -55,7 +56,7 @@ public class FeedItemUtilTest {
FeedItem feedItem = new FeedItem();
feedItem.setLink(itemLink);
feedItem.setFeed(feed);
- feed.setItems(Arrays.asList(feedItem));
+ feed.setItems(Collections.singletonList(feedItem));
return feedItem;
}
}
diff --git a/core/src/test/java/de/danoeh/antennapod/core/util/LongLongMapTest.java b/core/src/test/java/de/danoeh/antennapod/core/util/LongLongMapTest.java
index 0ed77eb9f..21df71bec 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/util/LongLongMapTest.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/util/LongLongMapTest.java
@@ -3,6 +3,8 @@ package de.danoeh.antennapod.core.util;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
public class LongLongMapTest {
@@ -13,7 +15,7 @@ public class LongLongMapTest {
assertEquals("LongLongMap{}", map.toString());
assertEquals(0, map.get(42));
assertEquals(-1, map.get(42, -1));
- assertEquals(false, map.delete(42));
+ assertFalse(map.delete(42));
assertEquals(-1, map.indexOfKey(42));
assertEquals(-1, map.indexOfValue(42));
assertEquals(1, map.hashCode());
@@ -29,7 +31,7 @@ public class LongLongMapTest {
assertEquals(42, map.get(17, -1));
assertEquals(0, map.indexOfKey(17));
assertEquals(0, map.indexOfValue(42));
- assertEquals(true, map.delete(17));
+ assertTrue(map.delete(17));
}
@Test
@@ -45,7 +47,7 @@ public class LongLongMapTest {
assertEquals(1, map.indexOfKey(17));
assertEquals(1, map.indexOfValue(42));
for(int i=0; i < 100; i++) {
- assertEquals(true, map.delete(i * 17));
+ assertTrue(map.delete(i * 17));
}
}