summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.circleci/config.yml94
-rw-r--r--.tx/.gitignore2
-rw-r--r--.tx/antennapod.description/pt_translation43
-rw-r--r--.tx/antennapod.shortdescription/pt_translation1
-rw-r--r--.tx/config8
-rw-r--r--CHANGELOG.md11
-rw-r--r--CONTRIBUTORS34
-rw-r--r--app/build.gradle29
-rw-r--r--app/src/androidTest/java/de/test/antennapod/EspressoTestUtils.java32
-rw-r--r--app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java12
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java47
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/NavigationDrawerTest.java135
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java16
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java4
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java2
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/QueueFragmentTest.java58
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java2
-rw-r--r--app/src/androidTest/java/de/test/antennapod/util/service/download/HTTPBin.java14
-rw-r--r--app/src/free/java/de/danoeh/antennapod/activity/CastEnabledActivity.java203
-rw-r--r--app/src/main/AndroidManifest.xml9
-rw-r--r--app/src/main/java/de/danoeh/antennapod/CrashReportWriter.java22
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java23
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/BugReportActivity.java55
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java1
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java50
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java257
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java7
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java8
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java29
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java8
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java13
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java32
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java12
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java40
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/ItemActionButton.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/asynctask/DocumentFileExportWorker.java72
-rw-r--r--app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/ChooseDataFolderDialog.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java21
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/FilterDialog.java62
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java214
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/RatingDialog.java9
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java1
-rw-r--r--app/src/main/java/de/danoeh/antennapod/discovery/CombinedSearcher.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/discovery/ItunesTopListLoader.java14
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java7
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java505
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java13
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java445
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java12
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java3
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java (renamed from app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java)37
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java14
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java29
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java12
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java113
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java28
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/preferences/AutoDownloadPreferencesFragment.java71
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/preferences/MainPreferencesFragment.java55
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/preferences/StoragePreferencesFragment.java180
-rw-r--r--app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java92
-rw-r--r--app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java54
-rw-r--r--app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java28
-rw-r--r--app/src/main/java/de/danoeh/antennapod/spa/SPAUtil.java4
-rw-r--r--app/src/main/play/listings/de-DE/full-description.txt7
-rw-r--r--app/src/main/play/listings/de-DE/title.txt1
-rw-r--r--app/src/main/play/listings/en-US/graphics/icon/icon_play.pngbin0 -> 25302 bytes
-rw-r--r--app/src/main/play/listings/es-ES/full-description.txt42
-rw-r--r--app/src/main/play/listings/es-ES/short-description.txt1
-rw-r--r--app/src/main/play/listings/es-ES/title.txt1
-rw-r--r--app/src/main/play/listings/fr-FR/full-description.txt5
-rw-r--r--app/src/main/play/listings/fr-FR/short-description.txt2
-rw-r--r--app/src/main/play/listings/fr-FR/title.txt1
-rw-r--r--app/src/main/play/listings/gl-ES/full-description.txt3
-rw-r--r--app/src/main/play/listings/gl-ES/title.txt1
-rw-r--r--app/src/main/play/listings/it-IT/title.txt1
-rw-r--r--app/src/main/play/listings/iw-IL/full-description.txt (renamed from .tx/antennapod.description/he_IL_translation)3
-rw-r--r--app/src/main/play/listings/iw-IL/short-description.txt (renamed from .tx/antennapod.shortdescription/he_IL_translation)0
-rw-r--r--app/src/main/play/listings/iw-IL/title.txt1
-rw-r--r--app/src/main/play/listings/ja-JP/full-description.txt3
-rw-r--r--app/src/main/play/listings/ja-JP/title.txt1
-rw-r--r--app/src/main/play/listings/nl-NL/full-description.txt3
-rw-r--r--app/src/main/play/listings/nl-NL/title.txt1
-rw-r--r--app/src/main/play/listings/sv-SE/full-description.txt42
-rw-r--r--app/src/main/play/listings/sv-SE/short-description.txt1
-rw-r--r--app/src/main/play/listings/sv-SE/title.txt1
-rw-r--r--app/src/main/play/listings/zh-CN/full-description.txt42
-rw-r--r--app/src/main/play/listings/zh-CN/short-description.txt2
-rw-r--r--app/src/main/play/listings/zh-CN/title.txt1
-rw-r--r--app/src/main/play/release-notes/en-US/default.txt3
-rw-r--r--app/src/main/res/layout/addfeed.xml22
-rw-r--r--app/src/main/res/layout/all_episodes_fragment.xml35
-rw-r--r--app/src/main/res/layout/bug_report.xml28
-rw-r--r--app/src/main/res/layout/checkbox_do_not_show_again.xml17
-rw-r--r--app/src/main/res/layout/downloaded_episodeslist_item.xml2
-rw-r--r--app/src/main/res/layout/episodes_apply_action_fragment.xml11
-rw-r--r--app/src/main/res/layout/feeditem_fragment.xml4
-rw-r--r--app/src/main/res/layout/feeditemlist_header.xml2
-rw-r--r--app/src/main/res/layout/gpodnet_podcast_listitem.xml2
-rw-r--r--app/src/main/res/layout/itunes_podcast_listitem.xml2
-rw-r--r--app/src/main/res/layout/mediaplayerinfo_activity.xml29
-rw-r--r--app/src/main/res/layout/nav_feedlistitem.xml2
-rw-r--r--app/src/main/res/layout/queue_listitem.xml2
-rw-r--r--app/src/main/res/layout/searchlist_item.xml2
-rw-r--r--app/src/main/res/layout/statistics_listitem.xml2
-rw-r--r--app/src/main/res/menu/allepisodes_context.xml86
-rw-r--r--app/src/main/res/menu/episodes.xml10
-rw-r--r--app/src/main/res/menu/feedinfo.xml2
-rw-r--r--app/src/main/res/menu/feeditem_options.xml5
-rw-r--r--app/src/main/res/menu/feeditemlist_context.xml5
-rw-r--r--app/src/main/res/menu/feedlist.xml4
-rw-r--r--app/src/main/res/menu/mediaplayer.xml8
-rw-r--r--app/src/main/res/menu/queue_context.xml73
-rw-r--r--app/src/main/res/menu/subscriptions.xml7
-rw-r--r--app/src/main/res/values-w300dp/dimens-fabspeeddial.xml4
-rw-r--r--app/src/main/res/xml/preferences.xml22
-rw-r--r--app/src/main/res/xml/preferences_user_interface.xml2
-rw-r--r--app/src/main/templates/about.html8
-rw-r--r--app/src/play/java/de/danoeh/antennapod/activity/CastEnabledActivity.java54
-rw-r--r--app/src/play/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java15
-rw-r--r--artwork/feature-graphic.svg138
-rw-r--r--build.gradle17
-rw-r--r--config/checkstyle/checkstyle.xml82
-rw-r--r--core/build.gradle2
-rw-r--r--core/src/free/java/de/danoeh/antennapod/core/ClientConfig.java4
-rw-r--r--core/src/main/AndroidManifest.xml5
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/event/DownloadEvent.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java23
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/event/PlaybackPositionEvent.java19
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/event/ProgressEvent.java36
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java8
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/preferences/PlaybackPreferences.java77
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java70
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java6
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/FeedUpdateWorker.java28
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java20
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java21
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java43
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadStatus.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java39
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java72
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java279
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java22
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceStateManager.java52
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java30
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java60
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java49
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java5
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java22
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/DuckType.java117
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/FeedItemUtil.java38
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/FeedUpdateUtils.java36
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/FeedtitleComparator.java15
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java16
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/Optional.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/QueueSorter.java5
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java21
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/TimeSpeedConverter.java7
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/comparator/SearchResultValueComparator.java27
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/download/AutoUpdateManager.java70
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/exception/RxJavaErrorHandlerSetup.java24
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/ExternalMedia.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/MediaPlayerError.java8
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java62
-rwxr-xr-xcore/src/main/res/drawable-hdpi/ic_baseline_question_answer_white_24dp.pngbin187 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_cast_disabled_light.pngbin770 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_cast_light.pngbin975 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_cast_off_light.pngbin867 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_cast_on_0_light.pngbin961 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_cast_on_1_light.pngbin979 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_cast_on_2_light.pngbin976 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_cast_on_light.pngbin982 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_close_light.pngbin493 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_format_list_bulleted_grey600_24dp.pngbin492 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_format_list_bulleted_white_24dp.pngbin459 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_forum_grey600_24dp.pngbin601 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_media_cast_disconnect.pngbin2355 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_pause_light.pngbin191 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_play_light.pngbin562 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_stat_antenna_default.pngbin541 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_stat_authentication.pngbin371 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-ldpi/ic_stat_antenna_default.pngbin259 -> 0 bytes
-rwxr-xr-xcore/src/main/res/drawable-mdpi/ic_baseline_question_answer_white_24dp.pngbin139 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_cast_disabled_light.pngbin536 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_cast_light.pngbin693 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_cast_off_light.pngbin635 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_cast_on_0_light.pngbin684 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_cast_on_1_light.pngbin696 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_cast_on_2_light.pngbin690 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_cast_on_light.pngbin694 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_close_light.pngbin379 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_format_list_bulleted_grey600_24dp.pngbin423 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_format_list_bulleted_white_24dp.pngbin406 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_forum_grey600_24dp.pngbin488 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_media_cast_disconnect.pngbin1467 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_pause_light.pngbin280 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_play_light.pngbin447 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_stat_antenna_default.pngbin349 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_stat_authentication.pngbin244 -> 0 bytes
-rwxr-xr-xcore/src/main/res/drawable-xhdpi/ic_baseline_question_answer_white_24dp.pngbin212 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_cast_disabled_light.pngbin976 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_cast_light.pngbin1328 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_cast_off_light.pngbin1161 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_cast_on_0_light.pngbin1286 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_cast_on_1_light.pngbin1308 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_cast_on_2_light.pngbin1309 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_cast_on_light.pngbin1331 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_close_light.pngbin526 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_format_list_bulleted_grey600_24dp.pngbin504 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_format_list_bulleted_white_24dp.pngbin462 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_forum_grey600_24dp.pngbin602 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_media_cast_disconnect.pngbin4496 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_pause_light.pngbin221 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_play_light.pngbin678 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_stat_antenna_default.pngbin783 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_stat_authentication.pngbin418 -> 0 bytes
-rwxr-xr-xcore/src/main/res/drawable-xxhdpi/ic_baseline_question_answer_white_24dp.pngbin276 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_cast_disabled_light.pngbin1429 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_cast_light.pngbin1952 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_cast_off_light.pngbin1679 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_cast_on_0_light.pngbin1832 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_cast_on_1_light.pngbin1893 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_cast_on_2_light.pngbin1910 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_cast_on_light.pngbin1944 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_close_light.pngbin673 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_format_list_bulleted_grey600_24dp.pngbin631 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_format_list_bulleted_white_24dp.pngbin594 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_forum_grey600_24dp.pngbin766 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_media_cast_disconnect.pngbin7096 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_pause_light.pngbin317 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_play_light.pngbin955 -> 0 bytes
-rwxr-xr-xcore/src/main/res/drawable-xxhdpi/ic_stat_authentication.pngbin848 -> 0 bytes
-rwxr-xr-xcore/src/main/res/drawable-xxxhdpi/ic_baseline_question_answer_white_24db.pngbin310 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxxhdpi/ic_close_light.pngbin805 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxxhdpi/ic_format_list_bulleted_grey600_24dp.pngbin738 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxxhdpi/ic_format_list_bulleted_white_24dp.pngbin666 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxxhdpi/ic_forum_grey600_24dp.pngbin900 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxxhdpi/ic_pause_light.pngbin400 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxxhdpi/ic_play_light.pngbin1190 -> 0 bytes
-rw-r--r--core/src/main/res/drawable/ic_antenna.xml6
-rw-r--r--core/src/main/res/drawable/ic_chat_grey600.xml5
-rw-r--r--core/src/main/res/drawable/ic_chat_white.xml5
-rw-r--r--core/src/main/res/drawable/ic_fab_edit_black.xml5
-rw-r--r--core/src/main/res/drawable/ic_fab_edit_white.xml (renamed from core/src/main/res/drawable/ic_fab_edit.xml)0
-rw-r--r--core/src/main/res/drawable/ic_notification.pngbin3887 -> 0 bytes
-rw-r--r--core/src/main/res/drawable/ic_notification_cast_off.xml5
-rw-r--r--core/src/main/res/drawable/ic_notification_fast_forward.xml5
-rw-r--r--core/src/main/res/drawable/ic_notification_fast_rewind.xml5
-rw-r--r--core/src/main/res/drawable/ic_notification_key.xml6
-rw-r--r--core/src/main/res/drawable/ic_notification_pause.xml5
-rw-r--r--core/src/main/res/drawable/ic_notification_play.xml5
-rw-r--r--core/src/main/res/drawable/ic_notification_skip.xml5
-rw-r--r--core/src/main/res/drawable/ic_playback_speed_dark.xml8
-rw-r--r--core/src/main/res/drawable/ic_playback_speed_white.xml8
-rw-r--r--core/src/main/res/drawable/ic_questionmark_grey600.xml5
-rw-r--r--core/src/main/res/drawable/ic_questionmark_white.xml5
-rw-r--r--core/src/main/res/drawable/ic_stream_white.xml5
-rw-r--r--core/src/main/res/drawable/ic_warning_red.xml5
-rw-r--r--core/src/main/res/drawable/line.xml12
-rw-r--r--core/src/main/res/drawable/line_drawable.xml9
-rw-r--r--core/src/main/res/drawable/thumb.xml11
-rw-r--r--core/src/main/res/drawable/thumb_drawable.xml9
-rw-r--r--core/src/main/res/drawable/white_circle.xml11
-rw-r--r--core/src/main/res/values-ca/strings.xml55
-rw-r--r--core/src/main/res/values-cs-rCZ/strings.xml67
-rw-r--r--core/src/main/res/values-da/strings.xml54
-rw-r--r--core/src/main/res/values-de/strings.xml107
-rw-r--r--core/src/main/res/values-el/strings.xml43
-rw-r--r--core/src/main/res/values-es/strings.xml94
-rw-r--r--core/src/main/res/values-et/strings.xml17
-rw-r--r--core/src/main/res/values-fa/strings.xml40
-rw-r--r--core/src/main/res/values-fi/strings.xml687
-rw-r--r--core/src/main/res/values-fr/strings.xml114
-rw-r--r--core/src/main/res/values-gl-rES/strings.xml96
-rw-r--r--core/src/main/res/values-hi-rIN/strings.xml34
-rw-r--r--core/src/main/res/values-hu/strings.xml69
-rw-r--r--core/src/main/res/values-in/strings.xml (renamed from core/src/main/res/values-id/strings.xml)0
-rw-r--r--core/src/main/res/values-it/strings.xml148
-rw-r--r--core/src/main/res/values-iw-rIL/strings.xml94
-rw-r--r--core/src/main/res/values-ja/strings.xml94
-rw-r--r--core/src/main/res/values-land/styles.xml6
-rw-r--r--core/src/main/res/values-large/dimens.xml1
-rw-r--r--core/src/main/res/values-lt/strings.xml55
-rw-r--r--core/src/main/res/values-nb/strings.xml49
-rw-r--r--core/src/main/res/values-nl/strings.xml106
-rw-r--r--core/src/main/res/values-pl-rPL/strings.xml65
-rw-r--r--core/src/main/res/values-pt-rBR/strings.xml82
-rw-r--r--core/src/main/res/values-pt/strings.xml96
-rw-r--r--core/src/main/res/values-ru/strings.xml158
-rw-r--r--core/src/main/res/values-sv-rSE/strings.xml79
-rw-r--r--core/src/main/res/values-tr/strings.xml53
-rw-r--r--core/src/main/res/values-uk-rUA/strings.xml58
-rw-r--r--core/src/main/res/values-v16/styles.xml8
-rw-r--r--core/src/main/res/values-v19/colors.xml1
-rw-r--r--core/src/main/res/values-zh-rCN/strings.xml196
-rw-r--r--core/src/main/res/values/arrays.xml10
-rw-r--r--core/src/main/res/values/attrs.xml6
-rw-r--r--core/src/main/res/values/colors.xml10
-rw-r--r--core/src/main/res/values/dimens.xml3
-rw-r--r--core/src/main/res/values/integers.xml1
-rw-r--r--core/src/main/res/values/strings.xml61
-rw-r--r--core/src/main/res/values/styles.xml51
-rw-r--r--core/src/play/java/de/danoeh/antennapod/core/ClientConfig.java17
-rw-r--r--core/src/play/java/de/danoeh/antennapod/core/cast/CastManager.java4
-rw-r--r--core/src/play/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceFlavorHelper.java31
-rw-r--r--gradle/wrapper/gradle-wrapper.properties2
310 files changed, 4929 insertions, 3995 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 7446862c6..b6a6ba78e 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -1,39 +1,103 @@
version: 2
jobs:
- build:
+ test-debug:
docker:
- image: circleci/android:api-28
-
working_directory: ~/AntennaPod
-
environment:
GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx1536m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError"'
_JAVA_OPTIONS: "-Xms256m -Xmx1280m"
-
steps:
- checkout
-
- restore_cache:
keys:
- v1-android-{{ checksum "build.gradle" }}
- # fallback to using the latest cache if no exact match is found
- v1-android-
+ - run:
+ name: Build debug
+ command: ./gradlew assembleDebug -PdisablePreDex
+ - run:
+ name: Execute debug unit tests
+ command: ./gradlew :core:testPlayDebugUnitTest -PdisablePreDex
+ - save_cache:
+ paths:
+ - ~/.android
+ - ~/.gradle
+ - ~/android
+ key: v1-android-{{ checksum "build.gradle" }}
+ test-release:
+ docker:
+ - image: circleci/android:api-28
+ working_directory: ~/AntennaPod
+ environment:
+ GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx1536m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError"'
+ _JAVA_OPTIONS: "-Xms256m -Xmx1280m"
+ steps:
+ - checkout
+ - restore_cache:
+ keys:
+ - v1-android-{{ checksum "build.gradle" }}
+ - v1-android-
+ - run:
+ name: Create temporary release keystore
+ command: keytool -noprompt -genkey -v -keystore "app/keystore" -alias alias -storepass password -keypass password -keyalg RSA -validity 10 -dname "CN=antennapod.org, OU=dummy, O=dummy, L=dummy, S=dummy, C=US"
- run:
- # To build release, we need to create a temporary keystore that can be used to sign the app
- command: |
- keytool -noprompt -genkey -v -keystore "app/keystore" -alias alias -storepass password -keypass password -keyalg RSA -validity 10 -dname "CN=antennapod.org, OU=dummy, O=dummy, L=dummy, S=dummy, C=US"
- ./gradlew assembleRelease :core:testPlayReleaseUnitTest -PdisablePreDex
- no_output_timeout: 1800
-
- - store_artifacts:
- path: app/build/outputs/apk
- destination: apks
+ name: Build release
+ command: ./gradlew assembleRelease -PdisablePreDex
+ - run:
+ name: Execute release unit tests
+ command: ./gradlew :core:testPlayReleaseUnitTest -PdisablePreDex
+ - save_cache:
+ paths:
+ - ~/.android
+ - ~/.gradle
+ - ~/android
+ key: v1-android-{{ checksum "build.gradle" }}
+ build-androidtest:
+ docker:
+ - image: circleci/android:api-28
+ working_directory: ~/AntennaPod
+ environment:
+ GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx1536m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError"'
+ _JAVA_OPTIONS: "-Xms256m -Xmx1280m"
+ steps:
+ - checkout
+ - restore_cache:
+ keys:
+ - v1-android-{{ checksum "build.gradle" }}
+ - v1-android-
+ - run:
+ name: Build integration tests
+ command: ./gradlew :app:assemblePlayDebugAndroidTest -PdisablePreDex
- save_cache:
paths:
- ~/.android
- ~/.gradle
- ~/android
key: v1-android-{{ checksum "build.gradle" }}
+
+ checkstyle:
+ docker:
+ - image: circleci/android:api-28
+ working_directory: ~/AntennaPod
+ steps:
+ - checkout
+ - run:
+ name: Checkstyle
+ command: ./gradlew checkstyle
+
+workflows:
+ version: 2
+
+ unit-tests:
+ jobs:
+ - test-debug
+ - test-release
+ - build-androidtest
+
+ static-analysis:
+ jobs:
+ - checkstyle
diff --git a/.tx/.gitignore b/.tx/.gitignore
new file mode 100644
index 000000000..01b481584
--- /dev/null
+++ b/.tx/.gitignore
@@ -0,0 +1,2 @@
+antennapod.description
+antennapod.shortdescription
diff --git a/.tx/antennapod.description/pt_translation b/.tx/antennapod.description/pt_translation
deleted file mode 100644
index a5d85c553..000000000
--- a/.tx/antennapod.description/pt_translation
+++ /dev/null
@@ -1,43 +0,0 @@
-O AntennaPod é um gestor de podcasts que lhe permite aceder a milhões de podcasts, gratuitos ou pagos, a partir de diversas fontes tais como as estações BBC, NPR e CNN. A adição, importação e exportação de fontes é muito fácil através da base de dados iTunes ou gPodder, ficheiros OPML ou fontes RSS. Poupe tempo, economize bateria e dados móveis através dos mecanismos de controlo de descargas de episódios (possibilidade de especificar intervalos ou horas para as descargas e redes Wifi) e de eliminação de episódios (de acordo com as suas preferências).<br>
-Mas ainda mais importante: pode descarregar, emitir ou colocar episódios na lista de reprodução ao seu gosto, pode utilizar velocidades variáveis de reprodução, tem suporte a capítulos e um temporizador. Pode também mostrar o seu apreço aos criadores dos episódios através do serviço Flattr.
-
-Criado por entusiastas de podcasts, o AntennaPod é livre em todos os sentidos da palavra: open source, gratuito e sem publicidade.
-
-<b>Funcionalidades:</b><br>
-Importação, organização e reprodução<br>
-&#8226; Adicione e importe fontes existentes nos diretórios iTunes e gPodder.net, ficheiros OPML e ligações ATOM e RSS<br>
-&#8226; Gestão de podcasts através do widget, barra de notificações e controlos de auriculares ou auscultadores<br>
-&#8226; Velocidade variável de reprodução, suporte a capítulos (MP3, VorbisComment e Podlove), memorização da posição de reprodução e um temporizador avançado (agite para repor, baixar e aumentar o volume)<br>
-&#8226; Acesso a fontes e episódios protegidos por palavra-passe<br>
-&#8226; Possibilidade de subscrever fontes paginadas (www.podlove.org/paged-feeds)
-
-Monitorização, partilha e suporte<br>
-&#8226; Monitorize os seus podcasts preferidos marcando-os como favoritos<br>
-&#8226; Localize um episódio através do histórico de reprodução ou através de uma pesquisa (títulos e notas)<br>
-&#8226; Partilhe episódios e fontes nas redes sociais, por e-mail, no diretório gPodder.net ou através de ficheiros OPML<br>
-&#8226; Ajude os criadores de conteúdos através do serviço Flattr
-
-Controlo do sistema<br>
-&#8226; Controle todas as descargas automáticas: escolha as fontes, exclua redes móveis, especifique as redes Wi-Fi, indique se o telefone deve estar a ser carregado e defina as horas ou intervalos das descargas<br>
-&#8226; Faça a gestão do armazenamento através da cache de episódios, da eliminação inteligente (de acordo com os seus favoritos e estado de reprodução) e selecionado a localização de armazenamento<br>
-&#8226; Utilize o AntennaPod no seu idioma (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br>
-&#8226; Adapte-se ao seu ambiente através dos temas claro ou escuro<br>
-&#8226; Salvaguarde as suas subscrições com a integração gPodder.net ou através da exportação OPML
-
-<b>Integre a comunidade do AntennaPod!</b><br>
-O AntennaPod é desenvolvido por voluntários. Você também pode contribuir na programação ou reportando os erros encontrados!
-
-O GitHub é o local certo para os pedidos de funcionalidades, relatórios de erros e contributos:<br>
-https://www.github.com/AntennaPod/AntennaPod
-
-O nosso grupo Google é o local certo para partilhar ideias e agradecer aos nossos voluntários:<br>
-https://groups.google.com/forum/#!forum/antennapod
-
-Tem alguma questão ou comentário a fazer?
-https://twitter.com/@AntennaPod
-
-O Transifex é o local no qual pode ajudar a traduzir a aplicação:<br>
-https://www.transifex.com/antennapod/antennapod
-
-Junte-se ao nosso programa Beta para obter as funcionalidades mais recentes:<br>
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file
diff --git a/.tx/antennapod.shortdescription/pt_translation b/.tx/antennapod.shortdescription/pt_translation
deleted file mode 100644
index c558abaca..000000000
--- a/.tx/antennapod.shortdescription/pt_translation
+++ /dev/null
@@ -1 +0,0 @@
-Gestor e reprodutor de podcasts simples, flexível e open souce \ No newline at end of file
diff --git a/.tx/config b/.tx/config
index 110f2ba71..ea1c0ccef 100644
--- a/.tx/config
+++ b/.tx/config
@@ -24,7 +24,7 @@ trans.gl = core/src/main/res/values-gl-rES/strings.xml
trans.he_IL = core/src/main/res/values-iw-rIL/strings.xml
trans.hi_IN = core/src/main/res/values-hi-rIN/strings.xml
trans.hu = core/src/main/res/values-hu/strings.xml
-trans.id = core/src/main/res/values-id/strings.xml
+trans.id = core/src/main/res/values-in/strings.xml
trans.it_IT = core/src/main/res/values-it/strings.xml
trans.is = core/src/main/res/values-is-rIS/strings.xml
trans.ja = core/src/main/res/values-ja/strings.xml
@@ -70,10 +70,13 @@ trans.el = app/src/main/play/listings/el-GR/full-description.txt
trans.es = app/src/main/play/listings/es-ES/full-description.txt
trans.et = app/src/main/play/listings/et/full-description.txt
trans.fa = app/src/main/play/listings/fa/full-description.txt
+trans.fi = app/src/main/play/listings/fi-FI/full-description.txt
trans.fr = app/src/main/play/listings/fr-FR/full-description.txt
trans.gl = app/src/main/play/listings/gl-ES/full-description.txt
trans.hi_IN = app/src/main/play/listings/hi-IN/full-description.txt
+trans.he_IL = app/src/main/play/listings/iw-IL/full-description.txt
trans.hu = app/src/main/play/listings/hu-HU/full-description.txt
+trans.id = app/src/main/play/listings/id/full-description.txt
trans.it_IT = app/src/main/play/listings/it-IT/full-description.txt
trans.iw = app/src/main/play/listings/iw-IL/full-description.txt
trans.ja = app/src/main/play/listings/ja-JP/full-description.txt
@@ -107,10 +110,13 @@ trans.el = app/src/main/play/listings/el-GR/short-description.txt
trans.es = app/src/main/play/listings/es-ES/short-description.txt
trans.et = app/src/main/play/listings/et/short-description.txt
trans.fa = app/src/main/play/listings/fa/short-description.txt
+trans.fi = app/src/main/play/listings/fi-FI/short-description.txt
trans.fr = app/src/main/play/listings/fr-FR/short-description.txt
trans.gl = app/src/main/play/listings/gl-ES/short-description.txt
trans.hi_IN = app/src/main/play/listings/hi-IN/short-description.txt
+trans.he_IL = app/src/main/play/listings/iw-IL/short-description.txt
trans.hu = app/src/main/play/listings/hu-HU/short-description.txt
+trans.id = app/src/main/play/listings/id/short-description.txt
trans.it_IT = app/src/main/play/listings/it-IT/short-description.txt
trans.iw = app/src/main/play/listings/iw-IL/short-description.txt
trans.ja = app/src/main/play/listings/ja-JP/short-description.txt
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1e966b997..fb429f026 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,17 @@
Change Log
==========
+Version 1.7.3
+-------------
+* Display episode image on widget (by @brad)
+* Added checkbox to keep queue sorted (by @damoasda)
+* New UI for "Add podcast" screen (by @ByteHamster)
+* Added batch editing to the queue (by @ByteHamster)
+* Added option to adapt remaining time to playback speed (by @CedricCabessa)
+* Removed broken Flattr integration (by @ByteHamster)
+* Added filter to "All episodes" list (by @jhunnius)
+* Tons of bug fixes and performance improvements
+
Version 1.7.2
-------------
* Added configurable behavior of the back button
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 6cc7ae30e..c333a44b1 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -6,6 +6,7 @@ Alexander Terczka
Alexei Bendebury
Ali
alifeflow
+alimemonzx
amhokies
Anders Bo Rasmussen
Anderson Mesquita
@@ -13,8 +14,10 @@ Andrew Gaul
Andrey Krutov
Anthony Lieuallen
axq
+bhlee
Borjan Tchakaloff
brad
+Brad Pitcher
Burt Wiley Snyder
ByteHamster
Cameron Banga
@@ -23,6 +26,7 @@ Christopher Szucko
Cj Malone
Colin Willson
Cédric Cabessa
+damoasda
Danial Klimkin
Daniel Oeh
David Carver
@@ -48,9 +52,11 @@ Humberto Fraga
InsidE
James Falcon
Jan Niehusmann
+Jan-Peter von Hunnius
Jatin Kumar
Jens Klingenberg
Jens Müller
+Joe Stein
Johan Liesén
Kaligule
Katrin Leinweber
@@ -93,6 +99,7 @@ qkolj
Raghul
Raghul Jagannathan
recalculated
+rezanejati
Ross Harrison
Sam Lee
Sam Whited
@@ -109,6 +116,7 @@ Simon Schubert
Soso Tughushi
Spencer Visick
Stefan Mitrik
+Stephen Kitt
Terence Eden
Tim Butram
Tobias Preuss
@@ -121,6 +129,7 @@ Udi Finkelstein
VarunBarad
volhol
Volker Hollich
+Wagubi Brian
WangYun
William Seemann
ydinath
@@ -136,47 +145,48 @@ Bulgarian: solusitor
Catalan: dvd1985, exort12, javiercoll, lambdani, marcmetallextrem, xc70
Catalan (Spain): 00c0c0, javiercoll
Chinese: dillonbecker, RainSlide, xukeek, yangyang
-Chinese (China): bebeauties38, domingos86, dudeG, ErlichLiu, Felix2yu, gaohongyuan, Guaidaodl, Huck0, iconteral, jhxie, kavdx, kyleehee, linxiangyu, molisiye, owen8877, RainSlide, stellaxuyi, tupunco, wi24rd, wongsyrone, xukeek, yangyang, yiqiok, YogaGuru
+Chinese (China): bebeauties38, domingos86, dudeG, ErlichLiu, Felix2yu, gaohongyuan, Guaidaodl, Huck0, iconteral, JayYoung, jhxie, kavdx, kyleehee, linxiangyu, molisiye, owen8877, RainSlide, Sak94664, spice2wolf, stellaxuyi, tupunco, wi24rd, wongsyrone, xukeek, yangyang, yiqiok, YogaGuru
Chinese (Taiwan): gugod, nigelinux, pggdt, ymhuang0808
Czech (Czech Republic): elich, Hanzmeister, mcepl, petnek, svetlemodry
Danish: CasperHN, jhertel
Dutch: e2jk, glotzbach, rwv, Vistaus
English: mfietz, sterylmreep
Estonian: Eraser
-Finnish: danieloeh
-French: cactux, ChaoticMind, clombion, e2jk, lacouture, Matth78, mfietz, Poussinou, PRIMOKORN, repat, Sioul, sterylmreep, TacoTheDank, Tilwa, vcariven, whenrow
+Finnish: danieloeh, elguitar, Sahtor
+French: cactux, ChaoticMind, clombion, e2jk, lacouture, LouFex, Matth78, mfietz, Poussinou, PRIMOKORN, repat, Sioul, sterylmreep, TacoTheDank, Tilwa, vcariven, whenrow
Galician: antiparvos, pikamoku, Raichely
-German: 112358, altegedanken, barilla, benedikt.g, bitsunited, Buggi, ceving, ChaoticMind, Chaquotay, dab0015, dadosch, DerSilly, die_otto, DJaeger, elkangaroo, enz, fidel, finsterwalder, Foso, GNi33, hightower5, HolgerJeromin, kalei, lohmann, LostInWeb, mfietz, nilso, repat, SAPlayer, schafia, Schroedingberg, sevenmaster, sucaml, Teaspoon, theonlytruth, weltenwort, Wyrrrd, ypid
+German: 112358, altegedanken, barilla, benedikt.g, bitsunited, Buggi, ceving, ChaoticMind, Chaquotay, dab0015, dadosch, DerSilly, die_otto, DJaeger, elkangaroo, enz, fidel, finsterwalder, Foso, GNi33, hightower5, HolgerJeromin, kalei, lohmann, LostInWeb, mfietz, moasda, nilso, repat, SAPlayer, schafia, Schroedingberg, sevenmaster, sucaml, Teaspoon, theonlytruth, weltenwort, Wyrrrd, ypid
Greek: antonist, danieloeh, hua2016s, MSavoritias, pavlosv
Hebrew (Israel): amir.dafnyman, E1i9, mongoose4004, pinkasey, rellieberman, Yaron, הלוי11
Hindi (India): ankitiitb1069, Isaasu, nmabhinandan, purple.coder, siddhusengar
-Hungarian: glatz.balazs, lna91, marthynw, naren93, tszauer, ttyborg42
+Hungarian: glatz.balazs, hurrikan, lna91, marthynw, naren93, tszauer, ttyborg42
Icelandic: marthjod
-Indonesian: jff, luke137, rezafaiza, silvanael16
+Indonesian: jff, levirs565, luke137, rezafaiza, silvanael16
Italian: aalex70, allin, apanontin, Bonnee, giuseppep, Guybrush88, marco_pag, neonsoftware, sevenmaster, theloca95
-Italian (Italy): aalex70, allin, apanontin, Bonnee, buongiorgio, giuseppep, Guybrush88, m.chinni, neonsoftware, nixxo, sevenmaster, theloca95
+Italian (Italy): aalex70, allin, apanontin, Bonnee, buongiorgio, giuseppep, Guybrush88, m.chinni, neonsoftware, niccord, nixxo, sevenmaster, theloca95
Japanese: Naofumi, RACER1, sh3llc4t, TranslatorG
Kannada (India): thejeshgn
-Korean: changwoo, seungrye, skcha
+Korean: changwoo, libliboom, seungrye, skcha
Korean (South Korea): changwoo, seungrye
Lithuanian: naglis
Macedonian: krisfremen
-Malayalam: rashivkp
+Malayalam: rashivkp, rubenroy
Norwegian: timbast
Norwegian Bokmål: corkie, danieloeh, heraldo
Norwegian Bokmål (Norway): corkie, heraldo, kongk, timbast
-Persian: ahangarha, F7D
+Persian: ahangarha, F7D, sinamoghaddas
Polish: Iwangelion, maniexx, mateossh, mfloryan
Polish (Poland): d6210809, hiro2020, Iwangelion, lomapur, mandlus, maniexx, Mephistofeles, shark103, tyle
Portuguese: andersonvom, domingos86, emansije, smarquespt
Portuguese (Brazil): alexupits, alysonborges, andersonvom, arua, caioau, carlo_valente, castrors, deandreamatias, edman, Firmino, jackmiras, Junin, lipefire, lluccia, lucasmotacr, mbaltar, rogervezaro, RubeensVinicius, SamWilliam, silvanael16
Romanian (Romania): corneliu.e, fuzzmz, ralienpp
-Russian (Russia): astra1, btimofeev, Duke_Raven, GaynullinDima, MegMasters98, mercutiy, null, overmind88, s.chebotar, shams4real, skvheadless, un_logic, whereisthetea, zhenya97
+Russian (Russia): astra1, btimofeev, Duke_Raven, gammja, GaynullinDima, MegMasters98, mercutiy, null, overmind88, PtilopsisLeucotis, s.chebotar, shams4real, skvheadless, un_logic, Vladryyu, whereisthetea, zhenya97
Slovenian (Slovenia): panter23
Spanish: AleksSyntek, andersonvom, coperfix, deandreamatias, domingos86, dvd1985, Fitoschido, frandavid100, hard_ware, javiercoll, Juanmuto, lambdani, LatinSuD, leogrignafini, palopezv, TacoTheDank, tres.14159, wakutiteo
Spanish (Spain): andersonvom, dvd1985, e2jk, frandavid100, hard_ware, palopezv, Raichely, TacoTheDank
+Swahili: kmtra
Swahili (Kenya): BonfaceKilz
-Swedish (Sweden): albin.brantin, Bio, bpnilsson, ChaoticMind, jony08, nilso, SharpMelon, TwoD
+Swedish (Sweden): albin.brantin, Bio, bpnilsson, ChaoticMind, jony08, nilso, SharpMelon, TiloWiklund, TwoD
Telugu: Isaasu, veeven
Turkish: basarancaner, brsata, Erdy, golcuk, overbite, Slsdem
Ukrainian (Ukraine): older, paul_sm, sergiyr, zhenya97
diff --git a/app/build.gradle b/app/build.gradle
index 46b2e01d7..3996d7ba5 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,10 +1,9 @@
plugins {
- id('com.github.triplet.play') version '2.2.0'
+ id('com.android.application')
+ id('com.getkeepsafe.dexcount')
+ id('com.github.triplet.play') version '2.3.0' apply false
}
-apply plugin: "com.android.application"
-apply plugin: 'com.getkeepsafe.dexcount'
-
import org.apache.tools.ant.filters.ReplaceTokens
android {
@@ -19,8 +18,8 @@ android {
// "1.2.3-SNAPSHOT" -> 1020300
// "1.2.3-RC4" -> 1020304
// "1.2.3" -> 1020395
- versionCode 1070296
- versionName "1.7.2b"
+ versionCode 1070396
+ versionName "1.7.3b"
testApplicationId "de.test.antennapod"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
generatedDensities = []
@@ -173,9 +172,9 @@ dependencies {
implementation "com.github.AntennaPod:AntennaPod-AudioPlayer:$audioPlayerVersion"
implementation 'com.github.mfietz:fyydlin:v0.4.2'
- implementation 'com.github.ByteHamster:SearchPreference:v1.2.6'
- implementation "org.awaitility:awaitility:$awaitilityVersion"
+ implementation 'com.github.ByteHamster:SearchPreference:v1.3.0'
+ androidTestImplementation "org.awaitility:awaitility:$awaitilityVersion"
androidTestImplementation 'com.nanohttpd:nanohttpd-webserver:2.1.1'
androidTestImplementation "com.jayway.android.robotium:robotium-solo:$robotiumSoloVersion"
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
@@ -185,18 +184,12 @@ dependencies {
androidTestImplementation 'com.android.support.test:rules:1.0.2'
}
-play {
- track = 'alpha'
-
- if (project.hasProperty("antennaPodServiceAccountEmail")) {
+if (project.hasProperty("antennaPodServiceAccountEmail")) {
+ apply plugin: 'com.github.triplet.play'
+ play {
+ track = 'alpha'
serviceAccountEmail = antennaPodServiceAccountEmail
- } else {
- serviceAccountEmail = '522080222319-compute@developer.gserviceaccount.com'
- }
- if (project.hasProperty("antennaPodPk12File")) {
serviceAccountCredentials = file(antennaPodPk12File)
- } else {
- serviceAccountCredentials = file('../serviceaccount-c3d7d0f61387.p12')
}
}
diff --git a/app/src/androidTest/java/de/test/antennapod/EspressoTestUtils.java b/app/src/androidTest/java/de/test/antennapod/EspressoTestUtils.java
index 50109c71a..9e86275fc 100644
--- a/app/src/androidTest/java/de/test/antennapod/EspressoTestUtils.java
+++ b/app/src/androidTest/java/de/test/antennapod/EspressoTestUtils.java
@@ -1,6 +1,7 @@
package de.test.antennapod;
import android.content.Context;
+import android.content.SharedPreferences;
import android.support.annotation.StringRes;
import android.support.test.InstrumentationRegistry;
import android.support.test.espresso.PerformException;
@@ -12,6 +13,10 @@ import android.support.test.espresso.util.HumanReadables;
import android.support.test.espresso.util.TreeIterables;
import android.view.View;
import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.activity.MainActivity;
+import de.danoeh.antennapod.core.storage.PodDBAdapter;
+import de.danoeh.antennapod.dialog.RatingDialog;
+import de.danoeh.antennapod.fragment.QueueFragment;
import org.hamcrest.Matcher;
import java.io.File;
@@ -74,7 +79,7 @@ public class EspressoTestUtils {
/**
* Clear all app databases
*/
- public static void clearAppData() {
+ public static void clearPreferences() {
File root = InstrumentationRegistry.getTargetContext().getFilesDir().getParentFile();
String[] sharedPreferencesFileNames = new File(root, "shared_prefs").list();
for (String fileName : sharedPreferencesFileNames) {
@@ -84,6 +89,31 @@ public class EspressoTestUtils {
}
}
+ public static void makeNotFirstRun() {
+ InstrumentationRegistry.getTargetContext().getSharedPreferences(MainActivity.PREF_NAME, Context.MODE_PRIVATE)
+ .edit()
+ .putBoolean(MainActivity.PREF_IS_FIRST_LAUNCH, false)
+ .commit();
+
+ RatingDialog.init(InstrumentationRegistry.getTargetContext());
+ RatingDialog.saveRated();
+ }
+
+ public static void setLastNavFragment(String tag) {
+ InstrumentationRegistry.getTargetContext().getSharedPreferences(MainActivity.PREF_NAME, Context.MODE_PRIVATE)
+ .edit()
+ .putString(MainActivity.PREF_LAST_FRAGMENT_TAG, tag)
+ .commit();
+ }
+
+ public static void clearDatabase() {
+ PodDBAdapter.init(InstrumentationRegistry.getTargetContext());
+ PodDBAdapter.deleteDatabase();
+ PodDBAdapter adapter = PodDBAdapter.getInstance();
+ adapter.open();
+ adapter.close();
+ }
+
public static void clickPreference(@StringRes int title) {
onView(withId(R.id.list)).perform(
RecyclerViewActions.actionOnItem(hasDescendant(withText(title)),
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 63ea697e9..d1ca25ad3 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
@@ -64,15 +64,11 @@ public class PlaybackServiceMediaPlayerTest {
@Before
public void setUp() throws Exception {
assertionError = null;
- EspressoTestUtils.clearAppData();
- final Context context = InstrumentationRegistry.getTargetContext();
+ EspressoTestUtils.clearPreferences();
+ EspressoTestUtils.makeNotFirstRun();
+ EspressoTestUtils.clearDatabase();
- // create new database
- PodDBAdapter.init(context);
- PodDBAdapter.deleteDatabase();
- PodDBAdapter adapter = PodDBAdapter.getInstance();
- adapter.open();
- adapter.close();
+ final Context context = InstrumentationRegistry.getTargetContext();
httpServer = new HTTPBin();
httpServer.start();
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 d013ab9cf..0c65bb2e6 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java
@@ -5,8 +5,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.test.InstrumentationRegistry;
-import android.support.test.espresso.intent.Intents;
-import android.support.test.rule.ActivityTestRule;
+import android.support.test.espresso.intent.rule.IntentsTestRule;
import android.support.test.runner.AndroidJUnit4;
import com.robotium.solo.Solo;
import com.robotium.solo.Timeout;
@@ -29,7 +28,6 @@ import static android.support.test.InstrumentationRegistry.getInstrumentation;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.contrib.ActivityResultMatchers.hasResultCode;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static de.test.antennapod.EspressoTestUtils.clickPreference;
import static de.test.antennapod.EspressoTestUtils.openNavDrawer;
@@ -45,47 +43,28 @@ public class MainActivityTest {
private Solo solo;
private UITestUtils uiTestUtils;
- private SharedPreferences prefs;
@Rule
- public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class, false, false);
+ public IntentsTestRule<MainActivity> mActivityRule = new IntentsTestRule<>(MainActivity.class, false, false);
@Before
public void setUp() throws IOException {
- // override first launch preference
- // do this BEFORE calling getActivity()!
- EspressoTestUtils.clearAppData();
- prefs = InstrumentationRegistry.getContext()
- .getSharedPreferences(MainActivity.PREF_NAME, Context.MODE_PRIVATE);
- prefs.edit().putBoolean(MainActivity.PREF_IS_FIRST_LAUNCH, false).commit();
+ EspressoTestUtils.clearPreferences();
+ EspressoTestUtils.makeNotFirstRun();
+ EspressoTestUtils.clearDatabase();
mActivityRule.launchActivity(new Intent());
- Intents.init();
- Context context = mActivityRule.getActivity();
- uiTestUtils = new UITestUtils(context);
+ uiTestUtils = new UITestUtils(InstrumentationRegistry.getTargetContext());
uiTestUtils.setup();
- // create new database
- PodDBAdapter.init(context);
- PodDBAdapter.deleteDatabase();
- PodDBAdapter adapter = PodDBAdapter.getInstance();
- adapter.open();
- adapter.close();
-
- RatingDialog.init(context);
- RatingDialog.saveRated();
-
solo = new Solo(getInstrumentation(), mActivityRule.getActivity());
}
@After
public void tearDown() throws Exception {
uiTestUtils.tearDown();
- solo.finishOpenedActivities();
- Intents.release();
PodDBAdapter.deleteDatabase();
- prefs.edit().clear().commit();
}
@Test
@@ -93,13 +72,10 @@ public class MainActivityTest {
uiTestUtils.addHostedFeedData();
final Feed feed = uiTestUtils.hostedFeeds.get(0);
openNavDrawer();
- solo.clickOnText(solo.getString(R.string.add_feed_label));
+ onView(withText(R.string.add_feed_label)).perform(click());
solo.enterText(1, feed.getDownload_url());
- solo.clickOnButton(solo.getString(R.string.confirm_label));
- solo.waitForActivity(OnlineFeedViewActivity.class);
- solo.waitForView(R.id.butSubscribe);
- assertEquals(solo.getString(R.string.subscribe_label), solo.getButton(0).getText().toString());
- solo.clickOnButton(0);
+ onView(withText(R.string.confirm_label)).perform(click());
+ onView(withText(R.string.subscribe_label)).perform(click());
assertTrue(solo.waitForText(solo.getString(R.string.open_podcast), 0, Timeout.getLargeTimeout(), false));
}
@@ -119,7 +95,6 @@ public class MainActivityTest {
onView(withText(R.string.confirm_label)).perform(click());
solo.goBackToActivity(MainActivity.class.getSimpleName());
- solo.goBack(); // Close nav drawer
solo.goBack();
assertEquals(solo.getString(R.string.subscriptions_label), getActionbarTitle());
}
@@ -132,7 +107,6 @@ public class MainActivityTest {
clickPreference(R.string.pref_back_button_behavior_title);
onView(withText(R.string.back_button_open_drawer)).perform(click());
solo.goBackToActivity(MainActivity.class.getSimpleName());
- solo.goBack(); // Close nav drawer
solo.goBack();
assertTrue(((MainActivity)solo.getCurrentActivity()).isDrawerOpen());
}
@@ -145,7 +119,6 @@ public class MainActivityTest {
clickPreference(R.string.pref_back_button_behavior_title);
onView(withText(R.string.back_button_double_tap)).perform(click());
solo.goBackToActivity(MainActivity.class.getSimpleName());
- solo.goBack(); // Close nav drawer
solo.goBack();
solo.goBack();
assertThat(mActivityRule.getActivityResult(), hasResultCode(Activity.RESULT_CANCELED));
@@ -159,7 +132,6 @@ public class MainActivityTest {
clickPreference(R.string.pref_back_button_behavior_title);
onView(withText(R.string.back_button_show_prompt)).perform(click());
solo.goBackToActivity(MainActivity.class.getSimpleName());
- solo.goBack(); // Close nav drawer
solo.goBack();
onView(withText(R.string.yes)).perform(click());
Thread.sleep(100);
@@ -174,7 +146,6 @@ public class MainActivityTest {
clickPreference(R.string.pref_back_button_behavior_title);
onView(withText(R.string.back_button_default)).perform(click());
solo.goBackToActivity(MainActivity.class.getSimpleName());
- solo.goBack(); // Close nav drawer
solo.goBack();
assertThat(mActivityRule.getActivityResult(), hasResultCode(Activity.RESULT_CANCELED));
}
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 0ed62010b..548843636 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/NavigationDrawerTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/NavigationDrawerTest.java
@@ -4,13 +4,11 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.test.InstrumentationRegistry;
+import android.support.test.espresso.ViewInteraction;
import android.support.test.espresso.contrib.DrawerActions;
-import android.support.test.espresso.intent.Intents;
-import android.support.test.filters.FlakyTest;
-import android.support.test.rule.ActivityTestRule;
+import android.support.test.espresso.intent.rule.IntentsTestRule;
import android.support.test.runner.AndroidJUnit4;
-import android.widget.ListView;
-import com.robotium.solo.Solo;
+import android.view.View;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.activity.PreferenceActivity;
@@ -23,6 +21,7 @@ import de.danoeh.antennapod.fragment.EpisodesFragment;
import de.danoeh.antennapod.fragment.PlaybackHistoryFragment;
import de.danoeh.antennapod.fragment.QueueFragment;
import de.test.antennapod.EspressoTestUtils;
+import org.hamcrest.Matcher;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@@ -34,20 +33,20 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import static android.support.test.InstrumentationRegistry.getInstrumentation;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.action.ViewActions.longClick;
+import static android.support.test.espresso.action.ViewActions.scrollTo;
import static android.support.test.espresso.intent.Intents.intended;
import static android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent;
import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
-import static de.test.antennapod.NthMatcher.first;
import static de.test.antennapod.EspressoTestUtils.waitForView;
+import static de.test.antennapod.NthMatcher.first;
import static junit.framework.TestCase.assertTrue;
+import static org.hamcrest.Matchers.allOf;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
/**
* User interface tests for MainActivity drawer
@@ -55,49 +54,24 @@ import static org.junit.Assert.fail;
@RunWith(AndroidJUnit4.class)
public class NavigationDrawerTest {
- private Solo solo;
private UITestUtils uiTestUtils;
- private SharedPreferences prefs;
@Rule
- public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class, false, false);
+ public IntentsTestRule<MainActivity> mActivityRule = new IntentsTestRule<>(MainActivity.class, false, false);
@Before
public void setUp() throws IOException {
- // override first launch preference
- // do this BEFORE calling getActivity()!
- EspressoTestUtils.clearAppData();
- prefs = InstrumentationRegistry.getContext()
- .getSharedPreferences(MainActivity.PREF_NAME, Context.MODE_PRIVATE);
- prefs.edit().putBoolean(MainActivity.PREF_IS_FIRST_LAUNCH, false).commit();
-
- mActivityRule.launchActivity(new Intent());
-
- Intents.init();
- Context context = mActivityRule.getActivity();
- uiTestUtils = new UITestUtils(context);
+ uiTestUtils = new UITestUtils(InstrumentationRegistry.getTargetContext());
uiTestUtils.setup();
- // create new database
- PodDBAdapter.init(context);
- PodDBAdapter.deleteDatabase();
- PodDBAdapter adapter = PodDBAdapter.getInstance();
- adapter.open();
- adapter.close();
-
- RatingDialog.init(context);
- RatingDialog.saveRated();
-
- solo = new Solo(getInstrumentation(), mActivityRule.getActivity());
+ EspressoTestUtils.clearPreferences();
+ EspressoTestUtils.makeNotFirstRun();
+ EspressoTestUtils.clearDatabase();
}
@After
public void tearDown() throws Exception {
uiTestUtils.tearDown();
- solo.finishOpenedActivities();
- Intents.release();
- PodDBAdapter.deleteDatabase();
- prefs.edit().clear().commit();
}
private void openNavDrawer() {
@@ -105,69 +79,66 @@ public class NavigationDrawerTest {
onView(withId(R.id.drawer_layout)).perform(DrawerActions.open());
}
+ private ViewInteraction onDrawerItem(Matcher<View> viewMatcher) {
+ return onView(allOf(viewMatcher, withId(R.id.txtvTitle)));
+ }
+
@Test
- @FlakyTest
public void testClickNavDrawer() throws Exception {
uiTestUtils.addLocalFeedData(false);
-
- setHiddenDrawerItems(new ArrayList<>());
+ UserPreferences.setHiddenDrawerItems(new ArrayList<>());
+ mActivityRule.launchActivity(new Intent());
+ MainActivity activity = mActivityRule.getActivity();
// queue
openNavDrawer();
- solo.clickOnText(solo.getString(R.string.queue_label));
- solo.waitForView(R.id.recyclerView);
- assertEquals(solo.getString(R.string.queue_label), getActionbarTitle());
+ onDrawerItem(withText(R.string.queue_label)).perform(click());
+ onView(isRoot()).perform(waitForView(withId(R.id.recyclerView), 1000));
+ assertEquals(activity.getString(R.string.queue_label), activity.getSupportActionBar().getTitle());
// episodes
openNavDrawer();
- solo.clickOnText(solo.getString(R.string.episodes_label));
- solo.waitForView(android.R.id.list);
- assertEquals(solo.getString(R.string.episodes_label), getActionbarTitle());
+ onDrawerItem(withText(R.string.episodes_label)).perform(click());
+ onView(isRoot()).perform(waitForView(withId(android.R.id.list), 1000));
+ assertEquals(activity.getString(R.string.episodes_label), activity.getSupportActionBar().getTitle());
// Subscriptions
openNavDrawer();
- solo.clickOnText(solo.getString(R.string.subscriptions_label));
- solo.waitForView(R.id.subscriptions_grid);
- assertEquals(solo.getString(R.string.subscriptions_label), getActionbarTitle());
+ onDrawerItem(withText(R.string.subscriptions_label)).perform(click());
+ onView(isRoot()).perform(waitForView(withId(R.id.subscriptions_grid), 1000));
+ assertEquals(activity.getString(R.string.subscriptions_label), activity.getSupportActionBar().getTitle());
// downloads
openNavDrawer();
- solo.clickOnText(solo.getString(R.string.downloads_label));
- solo.waitForView(android.R.id.list);
- assertEquals(solo.getString(R.string.downloads_label), getActionbarTitle());
+ onDrawerItem(withText(R.string.downloads_label)).perform(click());
+ onView(isRoot()).perform(waitForView(withId(android.R.id.list), 1000));
+ assertEquals(activity.getString(R.string.downloads_label), activity.getSupportActionBar().getTitle());
// playback history
openNavDrawer();
- solo.clickOnText(solo.getString(R.string.playback_history_label));
- solo.waitForView(android.R.id.list);
- assertEquals(solo.getString(R.string.playback_history_label), getActionbarTitle());
+ onDrawerItem(withText(R.string.playback_history_label)).perform(click());
+ onView(isRoot()).perform(waitForView(withId(android.R.id.list), 1000));
+ assertEquals(activity.getString(R.string.playback_history_label), activity.getSupportActionBar().getTitle());
// add podcast
openNavDrawer();
- solo.clickOnText(solo.getString(R.string.add_feed_label));
- solo.waitForView(R.id.txtvFeedurl);
- assertEquals(solo.getString(R.string.add_feed_label), getActionbarTitle());
+ onDrawerItem(withText(R.string.add_feed_label)).perform(click());
+ onView(isRoot()).perform(waitForView(withId(R.id.txtvFeedurl), 1000));
+ assertEquals(activity.getString(R.string.add_feed_label), activity.getSupportActionBar().getTitle());
// podcasts
- ListView list = (ListView) solo.getView(R.id.nav_list);
for (int i = 0; i < uiTestUtils.hostedFeeds.size(); i++) {
Feed f = uiTestUtils.hostedFeeds.get(i);
openNavDrawer();
- solo.scrollListToLine(list, i);
- solo.clickOnText(f.getTitle());
- solo.waitForView(android.R.id.list);
- assertEquals("", getActionbarTitle());
+ onDrawerItem(withText(f.getTitle())).perform(scrollTo(), click());
+ onView(isRoot()).perform(waitForView(withId(android.R.id.list), 1000));
+ assertEquals("", activity.getSupportActionBar().getTitle());
}
}
- private String getActionbarTitle() {
- return ((MainActivity) solo.getCurrentActivity()).getSupportActionBar().getTitle().toString();
- }
-
-
@Test
- @FlakyTest
public void testGoToPreferences() {
+ mActivityRule.launchActivity(new Intent());
openNavDrawer();
onView(withText(R.string.settings_label)).perform(click());
intended(hasComponent(PreferenceActivity.class.getName()));
@@ -175,9 +146,10 @@ public class NavigationDrawerTest {
@Test
public void testDrawerPreferencesHideSomeElements() {
- setHiddenDrawerItems(new ArrayList<>());
+ UserPreferences.setHiddenDrawerItems(new ArrayList<>());
+ mActivityRule.launchActivity(new Intent());
openNavDrawer();
- onView(first(withText(R.string.queue_label))).perform(longClick());
+ onDrawerItem(withText(R.string.queue_label)).perform(longClick());
onView(withText(R.string.episodes_label)).perform(click());
onView(withText(R.string.playback_history_label)).perform(click());
onView(withText(R.string.confirm_label)).perform(click());
@@ -191,7 +163,8 @@ public class NavigationDrawerTest {
@Test
public void testDrawerPreferencesUnhideSomeElements() {
List<String> hidden = Arrays.asList(PlaybackHistoryFragment.TAG, DownloadsFragment.TAG);
- setHiddenDrawerItems(hidden);
+ UserPreferences.setHiddenDrawerItems(hidden);
+ mActivityRule.launchActivity(new Intent());
openNavDrawer();
onView(first(withText(R.string.queue_label))).perform(longClick());
@@ -208,7 +181,8 @@ public class NavigationDrawerTest {
@Test
public void testDrawerPreferencesHideAllElements() {
- setHiddenDrawerItems(new ArrayList<>());
+ UserPreferences.setHiddenDrawerItems(new ArrayList<>());
+ mActivityRule.launchActivity(new Intent());
String[] titles = mActivityRule.getActivity().getResources().getStringArray(R.array.nav_drawer_titles);
openNavDrawer();
@@ -227,7 +201,8 @@ public class NavigationDrawerTest {
@Test
public void testDrawerPreferencesHideCurrentElement() {
- setHiddenDrawerItems(new ArrayList<>());
+ UserPreferences.setHiddenDrawerItems(new ArrayList<>());
+ mActivityRule.launchActivity(new Intent());
openNavDrawer();
onView(withText(R.string.downloads_label)).perform(click());
openNavDrawer();
@@ -240,14 +215,4 @@ public class NavigationDrawerTest {
assertEquals(1, hidden.size());
assertTrue(hidden.contains(DownloadsFragment.TAG));
}
-
- private void setHiddenDrawerItems(List<String> items) {
- UserPreferences.setHiddenDrawerItems(items);
- try {
- mActivityRule.runOnUiThread(() -> mActivityRule.getActivity().updateNavDrawer());
- } catch (Throwable throwable) {
- throwable.printStackTrace();
- fail();
- }
- }
}
diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java
index 6b41ad0ea..22959917d 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java
@@ -52,12 +52,11 @@ public class PlaybackSonicTest {
@Before
public void setUp() throws Exception {
- EspressoTestUtils.clearAppData();
+ EspressoTestUtils.clearPreferences();
+ EspressoTestUtils.makeNotFirstRun();
+ EspressoTestUtils.clearDatabase();
context = InstrumentationRegistry.getTargetContext();
- PodDBAdapter.init(context);
- PodDBAdapter.deleteDatabase();
-
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs.edit()
.clear()
@@ -71,11 +70,6 @@ public class PlaybackSonicTest {
uiTestUtils = new UITestUtils(context);
uiTestUtils.setup();
-
- // create database
- PodDBAdapter adapter = PodDBAdapter.getInstance();
- adapter.open();
- adapter.close();
}
@After
@@ -122,7 +116,7 @@ public class PlaybackSonicTest {
solo.clickOnText(solo.getString(R.string.all_episodes_short_label));
getInstrumentation().waitForIdleSync();
- final List<FeedItem> episodes = DBReader.getRecentlyPublishedEpisodes(10);
+ final List<FeedItem> episodes = DBReader.getRecentlyPublishedEpisodes(0, 10);
assertTrue(solo.waitForView(solo.getView(R.id.butSecondaryAction)));
solo.clickOnView(solo.getView(R.id.butSecondaryAction));
@@ -241,7 +235,7 @@ public class PlaybackSonicTest {
setContinuousPlaybackPreference(followQueue);
uiTestUtils.addLocalFeedData(true);
DBWriter.clearQueue().get();
- final List<FeedItem> episodes = DBReader.getRecentlyPublishedEpisodes(10);
+ final List<FeedItem> episodes = DBReader.getRecentlyPublishedEpisodes(0, 10);
startLocalPlayback();
long mediaId = episodes.get(0).getMedia().getId();
diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java
index 099549a69..b302bcc91 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java
@@ -114,7 +114,7 @@ public class PlaybackTest {
solo.waitForText(solo.getString(R.string.all_episodes_short_label));
solo.clickOnText(solo.getString(R.string.all_episodes_short_label));
- final List<FeedItem> episodes = DBReader.getRecentlyPublishedEpisodes(10);
+ final List<FeedItem> episodes = DBReader.getRecentlyPublishedEpisodes(0, 10);
assertTrue(solo.waitForView(solo.getView(R.id.butSecondaryAction)));
solo.clickOnView(solo.getView(R.id.butSecondaryAction));
@@ -231,7 +231,7 @@ public class PlaybackTest {
setContinuousPlaybackPreference(followQueue);
uiTestUtils.addLocalFeedData(true);
DBWriter.clearQueue().get();
- final List<FeedItem> episodes = DBReader.getRecentlyPublishedEpisodes(10);
+ final List<FeedItem> episodes = DBReader.getRecentlyPublishedEpisodes(0, 10);
startLocalPlayback();
long mediaId = episodes.get(0).getMedia().getId();
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 4b2dc75a9..1063ac90a 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java
@@ -49,7 +49,7 @@ public class PreferencesTest {
@Before
public void setUp() {
- EspressoTestUtils.clearAppData();
+ EspressoTestUtils.clearPreferences();
mActivityRule.launchActivity(new Intent());
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mActivityRule.getActivity());
prefs.edit().putBoolean(UserPreferences.PREF_ENABLE_AUTODL, true).commit();
diff --git a/app/src/androidTest/java/de/test/antennapod/ui/QueueFragmentTest.java b/app/src/androidTest/java/de/test/antennapod/ui/QueueFragmentTest.java
new file mode 100644
index 000000000..d1023dd9e
--- /dev/null
+++ b/app/src/androidTest/java/de/test/antennapod/ui/QueueFragmentTest.java
@@ -0,0 +1,58 @@
+package de.test.antennapod.ui;
+
+import android.content.Intent;
+import android.support.test.espresso.Espresso;
+import android.support.test.espresso.intent.rule.IntentsTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.activity.MainActivity;
+import de.danoeh.antennapod.fragment.QueueFragment;
+import de.test.antennapod.EspressoTestUtils;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+/**
+ * User interface tests for queue fragment
+ */
+@RunWith(AndroidJUnit4.class)
+public class QueueFragmentTest {
+
+ @Rule
+ public IntentsTestRule<MainActivity> mActivityRule = new IntentsTestRule<>(MainActivity.class, false, false);
+
+ @Before
+ public void setUp() {
+ EspressoTestUtils.clearPreferences();
+ EspressoTestUtils.makeNotFirstRun();
+ EspressoTestUtils.clearDatabase();
+ EspressoTestUtils.setLastNavFragment(QueueFragment.TAG);
+ mActivityRule.launchActivity(new Intent());
+ }
+
+ @Test
+ public void testLockEmptyQueue() {
+ onView(withContentDescription(R.string.lock_queue)).perform(click());
+ onView(withContentDescription(R.string.unlock_queue)).perform(click());
+ }
+
+ @Test
+ public void testSortEmptyQueue() {
+ Espresso.openContextualActionModeOverflowMenu();
+ onView(withText(R.string.sort)).perform(click());
+ onView(withText(R.string.random)).perform(click());
+ }
+
+ @Test
+ public void testKeepEmptyQueueSorted() {
+ Espresso.openContextualActionModeOverflowMenu();
+ onView(withText(R.string.sort)).perform(click());
+ onView(withText(R.string.keep_sorted)).perform(click());
+ }
+}
diff --git a/app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java b/app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java
index 20c54cb15..905c65c34 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java
@@ -59,7 +59,7 @@ class UITestUtils {
public void setup() throws IOException {
destDir = new File(context.getFilesDir(), "test/UITestUtils");
- destDir.mkdir();
+ destDir.mkdirs();
hostedFeedDir = new File(destDir, "hostedFeeds");
hostedFeedDir.mkdir();
hostedMediaDir = new File(destDir, "hostedMediaDir");
diff --git a/app/src/androidTest/java/de/test/antennapod/util/service/download/HTTPBin.java b/app/src/androidTest/java/de/test/antennapod/util/service/download/HTTPBin.java
index 3d8417bf6..4158fd31c 100644
--- a/app/src/androidTest/java/de/test/antennapod/util/service/download/HTTPBin.java
+++ b/app/src/androidTest/java/de/test/antennapod/util/service/download/HTTPBin.java
@@ -72,20 +72,6 @@ public class HTTPBin extends NanoHTTPD {
return servedFiles.size() - 1;
}
- /**
- * Removes the file with the given ID from the server.
- *
- * @return True if a file was removed, false otherwise
- */
- public synchronized boolean removeFile(int id) {
- if (id < 0) throw new IllegalArgumentException("ID < 0");
- if (id >= servedFiles.size()) {
- return false;
- } else {
- return servedFiles.remove(id) != null;
- }
- }
-
public synchronized File accessFile(int id) {
if (id < 0 || id >= servedFiles.size()) {
return null;
diff --git a/app/src/free/java/de/danoeh/antennapod/activity/CastEnabledActivity.java b/app/src/free/java/de/danoeh/antennapod/activity/CastEnabledActivity.java
index 79d7e02f2..519d4c61b 100644
--- a/app/src/free/java/de/danoeh/antennapod/activity/CastEnabledActivity.java
+++ b/app/src/free/java/de/danoeh/antennapod/activity/CastEnabledActivity.java
@@ -7,212 +7,9 @@ import android.support.v7.app.AppCompatActivity;
* network.
*/
public abstract class CastEnabledActivity extends AppCompatActivity {
-// implements SharedPreferences.OnSharedPreferenceChangeListener {
public static final String TAG = "CastEnabledActivity";
-// protected CastManager castManager;
-// protected SwitchableMediaRouteActionProvider mediaRouteActionProvider;
-// private final CastButtonVisibilityManager castButtonVisibilityManager = new CastButtonVisibilityManager();
-//
-// @Override
-// protected void onCreate(Bundle savedInstanceState) {
-// super.onCreate(savedInstanceState);
-//
-// PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).
-// registerOnSharedPreferenceChangeListener(this);
-//
-// castManager = CastManager.getInstance();
-// castManager.addCastConsumer(castConsumer);
-// castButtonVisibilityManager.setPrefEnabled(UserPreferences.isCastEnabled());
-// onCastConnectionChanged(castManager.isConnected());
-// }
-//
-// @Override
-// protected void onDestroy() {
-// PreferenceManager.getDefaultSharedPreferences(getApplicationContext())
-// .unregisterOnSharedPreferenceChangeListener(this);
-// castManager.removeCastConsumer(castConsumer);
-// super.onDestroy();
-// }
-//
-// @Override
-// @CallSuper
-// public boolean onCreateOptionsMenu(Menu menu) {
-// super.onCreateOptionsMenu(menu);
-// getMenuInflater().inflate(R.menu.cast_enabled, menu);
-// castButtonVisibilityManager.setMenu(menu);
-// return true;
-// }
-//
-// @Override
-// @CallSuper
-// public boolean onPrepareOptionsMenu(Menu menu) {
-// super.onPrepareOptionsMenu(menu);
-// mediaRouteActionProvider = castManager
-// .addMediaRouterButton(menu.findItem(R.id.media_route_menu_item));
-// mediaRouteActionProvider.setEnabled(castButtonVisibilityManager.shouldEnable());
-// return true;
-// }
-//
-// @Override
-// protected void onResume() {
-// super.onResume();
-// castButtonVisibilityManager.setResumed(true);
-// }
-//
-// @Override
-// protected void onPause() {
-// super.onPause();
-// castButtonVisibilityManager.setResumed(false);
-// }
-//
-// @Override
-// public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
-// if (UserPreferences.PREF_CAST_ENABLED.equals(key)) {
-// boolean newValue = UserPreferences.isCastEnabled();
-// Log.d(TAG, "onSharedPreferenceChanged(), isCastEnabled set to " + newValue);
-// castButtonVisibilityManager.setPrefEnabled(newValue);
-// // PlaybackService has its own listener, so if it's active we don't have to take action here.
-// if (!newValue && !PlaybackService.isRunning) {
-// CastManager.getInstance().disconnect();
-// }
-// }
-// }
-//
-// CastConsumer castConsumer = new DefaultCastConsumer() {
-// @Override
-// public void onApplicationConnected(ApplicationMetadata appMetadata, String sessionId, boolean wasLaunched) {
-// onCastConnectionChanged(true);
-// }
-//
-// @Override
-// public void onDisconnected() {
-// onCastConnectionChanged(false);
-// }
-// };
-//
-// private void onCastConnectionChanged(boolean connected) {
-// if (connected) {
-// castButtonVisibilityManager.onConnected();
-// setVolumeControlStream(AudioManager.USE_DEFAULT_STREAM_TYPE);
-// } else {
-// castButtonVisibilityManager.onDisconnected();
-// setVolumeControlStream(AudioManager.STREAM_MUSIC);
-// }
-// }
-//
-// /**
-// * Should be called by any activity or fragment for which the cast button should be shown.
-// *
-// * @param showAsAction refer to {@link MenuItem#setShowAsAction(int)}
-// */
public final void requestCastButton(int showAsAction) {
// no-op
}
-
-// private class CastButtonVisibilityManager {
-// private volatile boolean prefEnabled = false;
-// private volatile boolean viewRequested = false;
-// private volatile boolean resumed = false;
-// private volatile boolean connected = false;
-// private volatile int showAsAction = MenuItem.SHOW_AS_ACTION_IF_ROOM;
-// private Menu menu;
-//
-// public synchronized void setPrefEnabled(boolean newValue) {
-// if (prefEnabled != newValue && resumed && (viewRequested || connected)) {
-// if (newValue) {
-// castManager.incrementUiCounter();
-// } else {
-// castManager.decrementUiCounter();
-// }
-// }
-// prefEnabled = newValue;
-// if (mediaRouteActionProvider != null) {
-// mediaRouteActionProvider.setEnabled(prefEnabled && (viewRequested || connected));
-// }
-// }
-//
-// public synchronized void setResumed(boolean newValue) {
-// if (resumed == newValue) {
-// Log.e(TAG, "resumed should never change to the same value");
-// return;
-// }
-// resumed = newValue;
-// if (prefEnabled && (viewRequested || connected)) {
-// if (resumed) {
-// castManager.incrementUiCounter();
-// } else {
-// castManager.decrementUiCounter();
-// }
-// }
-// }
-//
-// public synchronized void setViewRequested(boolean newValue) {
-// if (viewRequested != newValue && resumed && prefEnabled && !connected) {
-// if (newValue) {
-// castManager.incrementUiCounter();
-// } else {
-// castManager.decrementUiCounter();
-// }
-// }
-// viewRequested = newValue;
-// if (mediaRouteActionProvider != null) {
-// mediaRouteActionProvider.setEnabled(prefEnabled && (viewRequested || connected));
-// }
-// }
-//
-// public synchronized void setConnected(boolean newValue) {
-// if (connected != newValue && resumed && prefEnabled && !prefEnabled) {
-// if (newValue) {
-// castManager.incrementUiCounter();
-// } else {
-// castManager.decrementUiCounter();
-// }
-// }
-// connected = newValue;
-// if (mediaRouteActionProvider != null) {
-// mediaRouteActionProvider.setEnabled(prefEnabled && (viewRequested || connected));
-// }
-// }
-//
-// public synchronized boolean shouldEnable() {
-// return prefEnabled && viewRequested;
-// }
-//
-// public void setMenu(Menu menu) {
-// setViewRequested(false);
-// showAsAction = MenuItem.SHOW_AS_ACTION_IF_ROOM;
-// this.menu = menu;
-// setShowAsAction();
-// }
-//
-// public void requestCastButton(int showAsAction) {
-// setViewRequested(true);
-// this.showAsAction = showAsAction;
-// setShowAsAction();
-// }
-//
-// public void onConnected() {
-// setConnected(true);
-// setShowAsAction();
-// }
-//
-// public void onDisconnected() {
-// setConnected(false);
-// setShowAsAction();
-// }
-//
-// private void setShowAsAction() {
-// if (menu == null) {
-// Log.d(TAG, "setShowAsAction() without a menu");
-// return;
-// }
-// MenuItem item = menu.findItem(R.id.media_route_menu_item);
-// if (item == null) {
-// Log.e(TAG, "setShowAsAction(), but cast button not inflated");
-// return;
-// }
-// MenuItemCompat.setShowAsAction(item, connected? MenuItem.SHOW_AS_ACTION_ALWAYS : showAsAction);
-// }
-// }
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 73af654e9..c2c6f53c5 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -36,7 +36,7 @@
android:usesCleartextTraffic="true"
android:logo="@mipmap/ic_launcher">
<meta-data android:name="com.google.android.gms.car.notification.SmallIcon"
- android:resource="@drawable/ic_notification" />
+ android:resource="@drawable/ic_antenna" />
<meta-data
android:name="com.google.android.backup.api_key"
android:value="AEdPqrEAAAAI3a05VToCTlqBymJrbFGaKQMvF-bBAuLsOdavBA"/>
@@ -209,6 +209,13 @@
android:name=".activity.OpmlFeedChooserActivity"
android:label="@string/opml_import_label">
</activity>
+ <activity
+ android:name=".activity.BugReportActivity"
+ android:label="@string/bug_report_title">
+ <meta-data
+ android:name="android.support.PARENT_ACTIVITY"
+ android:value="de.danoeh.antennapod.activity.PreferenceActivity"/>
+ </activity>
<activity
android:name=".activity.VideoplayerActivity"
diff --git a/app/src/main/java/de/danoeh/antennapod/CrashReportWriter.java b/app/src/main/java/de/danoeh/antennapod/CrashReportWriter.java
index ea2166674..061ea9ae2 100644
--- a/app/src/main/java/de/danoeh/antennapod/CrashReportWriter.java
+++ b/app/src/main/java/de/danoeh/antennapod/CrashReportWriter.java
@@ -9,6 +9,9 @@ import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
import de.danoeh.antennapod.core.preferences.UserPreferences;
@@ -32,13 +35,7 @@ public class CrashReportWriter implements Thread.UncaughtExceptionHandler {
PrintWriter out = null;
try {
out = new PrintWriter(new FileWriter(path));
- out.println("[ Environment ]");
- out.println("Android version: " + Build.VERSION.RELEASE);
- out.println("OS version: " + System.getProperty("os.version"));
- out.println("AntennaPod version: " + BuildConfig.VERSION_NAME);
- out.println("Model: " + Build.MODEL);
- out.println("Device: " + Build.DEVICE);
- out.println("Product: " + Build.PRODUCT);
+ out.println(getSystemInfo());
out.println();
out.println("[ StackTrace ]");
ex.printStackTrace(out);
@@ -49,4 +46,15 @@ public class CrashReportWriter implements Thread.UncaughtExceptionHandler {
}
defaultHandler.uncaughtException(thread, ex);
}
+
+ public static String getSystemInfo() {
+ return "[ Environment ]" +
+ "\nAndroid version: " + Build.VERSION.RELEASE +
+ "\nOS version: " + System.getProperty("os.version") +
+ "\nAntennaPod version: " + BuildConfig.VERSION_NAME +
+ "\nModel: " + Build.MODEL +
+ "\nDevice: " + Build.DEVICE +
+ "\nProduct: " + Build.PRODUCT +
+ "\nTime: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(new Date()) + "\n";
+ }
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java
index 1bcdada44..821e2f347 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java
@@ -15,6 +15,7 @@ import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.LinearLayout;
+import de.danoeh.antennapod.core.util.IntentUtils;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
@@ -57,8 +58,7 @@ public class AboutActivity extends AppCompatActivity {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("http")) {
- Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
- startActivity(browserIntent);
+ IntentUtils.openInBrowser(AboutActivity.this, url);
return true;
} else {
url = url.replace("file:///android_asset/", "");
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java
index 2bcd7a461..07c970197 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java
@@ -7,6 +7,8 @@ import android.util.Log;
import android.view.View;
import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.Locale;
import java.util.concurrent.atomic.AtomicBoolean;
import de.danoeh.antennapod.core.feed.MediaType;
@@ -58,11 +60,13 @@ public class AudioplayerActivity extends MediaplayerInfoActivity {
}
if (controller == null) {
butPlaybackSpeed.setVisibility(View.GONE);
+ txtvPlaybackSpeed.setVisibility(View.GONE);
return;
}
updatePlaybackSpeedButtonText();
ViewCompat.setAlpha(butPlaybackSpeed, controller.canSetPlaybackSpeed() ? 1.0f : 0.5f);
butPlaybackSpeed.setVisibility(View.VISIBLE);
+ txtvPlaybackSpeed.setVisibility(View.VISIBLE);
}
@Override
@@ -72,21 +76,15 @@ public class AudioplayerActivity extends MediaplayerInfoActivity {
}
if (controller == null) {
butPlaybackSpeed.setVisibility(View.GONE);
+ txtvPlaybackSpeed.setVisibility(View.GONE);
return;
}
float speed = 1.0f;
if(controller.canSetPlaybackSpeed()) {
- try {
- // we can only retrieve the playback speed from the controller/playback service
- // once mediaplayer has been initialized
- speed = Float.parseFloat(UserPreferences.getPlaybackSpeed());
- } catch (NumberFormatException e) {
- Log.e(TAG, Log.getStackTraceString(e));
- UserPreferences.setPlaybackSpeed(String.valueOf(speed));
- }
+ speed = UserPreferences.getPlaybackSpeed();
}
- String speedStr = new DecimalFormat("0.00x").format(speed);
- butPlaybackSpeed.setText(speedStr);
+ String speedStr = new DecimalFormat("0.00").format(speed);
+ txtvPlaybackSpeed.setText(speedStr);
}
@Override
@@ -105,7 +103,9 @@ public class AudioplayerActivity extends MediaplayerInfoActivity {
}
if (controller.canSetPlaybackSpeed()) {
String[] availableSpeeds = UserPreferences.getPlaybackSpeedArray();
- String currentSpeed = UserPreferences.getPlaybackSpeed();
+ DecimalFormatSymbols format = new DecimalFormatSymbols(Locale.US);
+ format.setDecimalSeparator('.');
+ String currentSpeed = new DecimalFormat("0.00", format).format(UserPreferences.getPlaybackSpeed());
// Provide initial value in case the speed list has changed
// out from under us
@@ -139,6 +139,7 @@ public class AudioplayerActivity extends MediaplayerInfoActivity {
return true;
});
butPlaybackSpeed.setVisibility(View.VISIBLE);
+ txtvPlaybackSpeed.setVisibility(View.VISIBLE);
}
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/BugReportActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/BugReportActivity.java
new file mode 100644
index 000000000..7df973f9b
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/activity/BugReportActivity.java
@@ -0,0 +1,55 @@
+package de.danoeh.antennapod.activity;
+
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.design.widget.Snackbar;
+import android.support.v7.app.AppCompatActivity;
+import android.widget.TextView;
+import de.danoeh.antennapod.CrashReportWriter;
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.util.IntentUtils;
+import org.apache.commons.io.IOUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.charset.Charset;
+
+/**
+ * Displays the 'crash report' screen
+ */
+public class BugReportActivity extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ setTheme(UserPreferences.getTheme());
+ super.onCreate(savedInstanceState);
+ getSupportActionBar().setDisplayShowHomeEnabled(true);
+ setContentView(R.layout.bug_report);
+
+ TextView crashDetailsText = findViewById(R.id.crash_report_logs);
+
+ try {
+ File crashFile = CrashReportWriter.getFile();
+ String crashReportContent = IOUtils.toString(new FileInputStream(crashFile), Charset.forName("UTF-8"));
+ crashDetailsText.setText(crashReportContent);
+ } catch (IOException e) {
+ e.printStackTrace();
+ crashDetailsText.setText("No crash report recorded\n" + CrashReportWriter.getSystemInfo());
+ }
+
+ 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);
+ ClipData clip = ClipData.newPlainText(getString(R.string.bug_report_title), crashDetailsText.getText());
+ clipboard.setPrimaryClip(clip);
+ Snackbar.make(findViewById(android.R.id.content), R.string.copied_to_clipboard, Snackbar.LENGTH_SHORT).show();
+ });
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java
index 871e9c279..c60c7b769 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java
@@ -49,6 +49,7 @@ public class CastplayerActivity extends MediaplayerInfoActivity {
super.setupGUI();
if (butPlaybackSpeed != null) {
butPlaybackSpeed.setVisibility(View.GONE);
+ txtvPlaybackSpeed.setVisibility(View.GONE);
}
// if (butCastDisconnect != null) {
// butCastDisconnect.setOnClickListener(v -> castManager.disconnect());
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 102d30bcf..b028f7983 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
@@ -2,6 +2,7 @@ package de.danoeh.antennapod.activity;
import android.annotation.TargetApi;
import android.app.ProgressDialog;
+import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
@@ -10,6 +11,7 @@ import android.database.DataSetObserver;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
+import android.support.annotation.NonNull;
import android.support.annotation.VisibleForTesting;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
@@ -32,9 +34,11 @@ import android.widget.Toast;
import com.bumptech.glide.Glide;
-import de.danoeh.antennapod.preferences.PreferenceUpgrader;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.Validate;
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
import java.util.List;
@@ -43,7 +47,6 @@ import de.danoeh.antennapod.adapter.NavListAdapter;
import de.danoeh.antennapod.core.asynctask.FeedRemover;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.event.MessageEvent;
-import de.danoeh.antennapod.core.event.ProgressEvent;
import de.danoeh.antennapod.core.event.QueueEvent;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.Feed;
@@ -56,25 +59,22 @@ 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.StorageUtils;
-import de.danoeh.antennapod.core.util.gui.NotificationUtils;
import de.danoeh.antennapod.dialog.RatingDialog;
import de.danoeh.antennapod.dialog.RenameFeedDialog;
import de.danoeh.antennapod.fragment.AddFeedFragment;
import de.danoeh.antennapod.fragment.DownloadsFragment;
import de.danoeh.antennapod.fragment.EpisodesFragment;
import de.danoeh.antennapod.fragment.ExternalPlayerFragment;
-import de.danoeh.antennapod.fragment.ItemlistFragment;
+import de.danoeh.antennapod.fragment.FeedItemlistFragment;
import de.danoeh.antennapod.fragment.PlaybackHistoryFragment;
import de.danoeh.antennapod.fragment.QueueFragment;
import de.danoeh.antennapod.fragment.SubscriptionFragment;
import de.danoeh.antennapod.menuhandler.NavDrawerActivity;
+import de.danoeh.antennapod.preferences.PreferenceUpgrader;
import io.reactivex.Observable;
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;
/**
* The activity that is shown when the user launches the app.
@@ -88,13 +88,13 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
public static final String PREF_NAME = "MainActivityPrefs";
public static final String PREF_IS_FIRST_LAUNCH = "prefMainActivityIsFirstLaunch";
- private static final String PREF_LAST_FRAGMENT_TAG = "prefMainActivityLastFragmentTag";
+ public static final String PREF_LAST_FRAGMENT_TAG = "prefMainActivityLastFragmentTag";
public static final String EXTRA_NAV_TYPE = "nav_type";
public static final String EXTRA_NAV_INDEX = "nav_index";
public static final String EXTRA_FRAGMENT_TAG = "fragment_tag";
public static final String EXTRA_FRAGMENT_ARGS = "fragment_args";
- public static final String EXTRA_FEED_ID = "fragment_feed_id";
+ private static final String EXTRA_FEED_ID = "fragment_feed_id";
private static final String SAVE_BACKSTACK_COUNT = "backstackCount";
private static final String SAVE_TITLE = "title";
@@ -128,6 +128,14 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
private long lastBackButtonPressTime = 0;
+ @NonNull
+ public static Intent getIntentToOpenFeed(@NonNull Context context, long feedId) {
+ Intent intent = new Intent(context.getApplicationContext(), MainActivity.class);
+ intent.putExtra(MainActivity.EXTRA_FEED_ID, feedId);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ return intent;
+ }
+
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(UserPreferences.getNoTitleTheme());
@@ -233,6 +241,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
private void checkFirstLaunch() {
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);
// for backward compatibility, we only change defaults for fresh installs
@@ -240,7 +249,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean(PREF_IS_FIRST_LAUNCH, false);
- edit.commit();
+ edit.apply();
}
}
@@ -337,7 +346,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
}
public void loadFeedFragmentById(long feedId, Bundle args) {
- Fragment fragment = ItemlistFragment.newInstance(feedId);
+ Fragment fragment = FeedItemlistFragment.newInstance(feedId);
if(args != null) {
fragment.setArguments(args);
}
@@ -778,25 +787,6 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
}
@Subscribe(threadMode = ThreadMode.MAIN)
- public void onEventMainThread(ProgressEvent event) {
- Log.d(TAG, "onEvent(" + event + ")");
- switch(event.action) {
- case START:
- pd = new ProgressDialog(this);
- pd.setMessage(event.message);
- pd.setIndeterminate(true);
- pd.setCancelable(false);
- pd.show();
- break;
- case END:
- if(pd != null) {
- pd.dismiss();
- }
- break;
- }
- }
-
- @Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(MessageEvent event) {
Log.d(TAG, "onEvent(" + event + ")");
View parentLayout = findViewById(R.id.drawer_layout);
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 3946400a4..b1269b833 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java
@@ -22,8 +22,6 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
-import android.widget.Button;
-import android.widget.CheckBox;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
@@ -35,16 +33,14 @@ import com.bumptech.glide.Glide;
import com.joanzapata.iconify.IconDrawable;
import com.joanzapata.iconify.fonts.FontAwesomeIcons;
-import java.util.Locale;
-
import de.danoeh.antennapod.R;
+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.MediaType;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
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.util.Consumer;
import de.danoeh.antennapod.core.util.Converter;
@@ -62,12 +58,15 @@ import de.danoeh.antennapod.core.util.playback.MediaPlayerError;
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.SleepTimerDialog;
-import de.danoeh.antennapod.dialog.VariableSpeedDialog;
import io.reactivex.Observable;
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;
/**
@@ -79,9 +78,6 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
private static final String PREFS = "MediaPlayerActivityPreferences";
private static final String PREF_SHOW_TIME_LEFT = "showTimeLeft";
private static final int REQUEST_CODE_STORAGE = 42;
- private static final float PLAYBACK_SPEED_STEP = 0.05f;
- private static final float DEFAULT_MIN_PLAYBACK_SPEED = 0.5f;
- private static final float DEFAULT_MAX_PLAYBACK_SPEED = 2.5f;
PlaybackController controller;
@@ -202,6 +198,11 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
};
}
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ public void onEventMainThread(PlaybackPositionEvent event) {
+ onPositionObserverUpdate();
+ }
+
private static TextView getTxtvFFFromActivity(MediaplayerActivity activity) {
return activity.txtvFF;
}
@@ -282,6 +283,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
controller.init();
loadMediaInfo();
onPositionObserverUpdate();
+ EventBus.getDefault().register(this);
}
@Override
@@ -294,6 +296,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
if (disposable != null) {
disposable.dispose();
}
+ EventBus.getDefault().unregister(this);
super.onStop();
}
@@ -330,6 +333,8 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
Playable media = controller.getMedia();
boolean isFeedMedia = media != null && (media instanceof FeedMedia);
+ menu.findItem(R.id.open_feed_item).setVisible(isFeedMedia); // FeedMedia implies it belongs to a Feed
+
boolean hasWebsiteLink = ( getWebsiteLinkWithFallback(media) != null );
menu.findItem(R.id.visit_website_item).setVisible(hasWebsiteLink);
@@ -365,7 +370,8 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
menu.findItem(R.id.audio_controls).setIcon(new IconDrawable(this,
FontAwesomeIcons.fa_sliders).color(textColor).actionBarSize());
} else {
- menu.findItem(R.id.audio_controls).setVisible(false);
+ menu.findItem(R.id.audio_controls).setIcon(new IconDrawable(this,
+ FontAwesomeIcons.fa_sliders).color(0xffffffff).actionBarSize());
}
return true;
@@ -396,29 +402,24 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
return true;
} else {
if (media != null) {
+ final @Nullable FeedItem feedItem = getFeedItem(media); // some options option requires FeedItem
switch (item.getItemId()) {
case R.id.add_to_favorites_item:
- if(media instanceof FeedMedia) {
- FeedItem feedItem = ((FeedMedia)media).getItem();
- if(feedItem != null) {
- DBWriter.addFavoriteItem(feedItem);
- isFavorite = true;
- invalidateOptionsMenu();
- Toast.makeText(this, R.string.added_to_favorites, Toast.LENGTH_SHORT)
- .show();
- }
+ if (feedItem != null) {
+ DBWriter.addFavoriteItem(feedItem);
+ isFavorite = true;
+ invalidateOptionsMenu();
+ Toast.makeText(this, R.string.added_to_favorites, Toast.LENGTH_SHORT)
+ .show();
}
break;
case R.id.remove_from_favorites_item:
- if(media instanceof FeedMedia) {
- FeedItem feedItem = ((FeedMedia)media).getItem();
- if(feedItem != null) {
- DBWriter.removeFavoriteItem(feedItem);
- isFavorite = false;
- invalidateOptionsMenu();
- Toast.makeText(this, R.string.removed_from_favorites, Toast.LENGTH_SHORT)
- .show();
- }
+ if (feedItem != null) {
+ DBWriter.removeFavoriteItem(feedItem);
+ isFavorite = false;
+ invalidateOptionsMenu();
+ Toast.makeText(this, R.string.removed_from_favorites, Toast.LENGTH_SHORT)
+ .show();
}
break;
case R.id.disable_sleeptimer_item:
@@ -451,171 +452,37 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
}
break;
case R.id.audio_controls:
- MaterialDialog dialog = new MaterialDialog.Builder(this)
- .title(R.string.audio_controls)
- .customView(R.layout.audio_controls, true)
- .neutralText(R.string.close_label)
- .onNeutral((dialog1, which) -> {
- final SeekBar left = (SeekBar) dialog1.findViewById(R.id.volume_left);
- final SeekBar right = (SeekBar) dialog1.findViewById(R.id.volume_right);
- UserPreferences.setVolume(left.getProgress(), right.getProgress());
- })
- .show();
- final SeekBar barPlaybackSpeed = (SeekBar) dialog.findViewById(R.id.playback_speed);
- final Button butDecSpeed = (Button) dialog.findViewById(R.id.butDecSpeed);
- butDecSpeed.setOnClickListener(v -> {
- if(controller != null && controller.canSetPlaybackSpeed()) {
- barPlaybackSpeed.setProgress(barPlaybackSpeed.getProgress() - 1);
- } else {
- VariableSpeedDialog.showGetPluginDialog(this);
- }
- });
- final Button butIncSpeed = (Button) dialog.findViewById(R.id.butIncSpeed);
- butIncSpeed.setOnClickListener(v -> {
- if(controller != null && controller.canSetPlaybackSpeed()) {
- barPlaybackSpeed.setProgress(barPlaybackSpeed.getProgress() + 1);
- } else {
- VariableSpeedDialog.showGetPluginDialog(this);
- }
- });
-
- final TextView txtvPlaybackSpeed = (TextView) dialog.findViewById(R.id.txtvPlaybackSpeed);
- float currentSpeed = 1.0f;
- try {
- currentSpeed = Float.parseFloat(UserPreferences.getPlaybackSpeed());
- } catch (NumberFormatException e) {
- Log.e(TAG, Log.getStackTraceString(e));
- UserPreferences.setPlaybackSpeed(String.valueOf(currentSpeed));
- }
-
- String[] availableSpeeds = UserPreferences.getPlaybackSpeedArray();
- final float minPlaybackSpeed = availableSpeeds.length > 1 ?
- Float.valueOf(availableSpeeds[0]) : DEFAULT_MIN_PLAYBACK_SPEED;
- float maxPlaybackSpeed = availableSpeeds.length > 1 ?
- Float.valueOf(availableSpeeds[availableSpeeds.length - 1]) : DEFAULT_MAX_PLAYBACK_SPEED;
- int progressMax = (int) ((maxPlaybackSpeed - minPlaybackSpeed) / PLAYBACK_SPEED_STEP);
- barPlaybackSpeed.setMax(progressMax);
-
- txtvPlaybackSpeed.setText(String.format("%.2fx", currentSpeed));
- barPlaybackSpeed.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- if(controller != null && controller.canSetPlaybackSpeed()) {
- float playbackSpeed = progress * PLAYBACK_SPEED_STEP + minPlaybackSpeed;
- controller.setPlaybackSpeed(playbackSpeed);
- String speedPref = String.format(Locale.US, "%.2f", playbackSpeed);
- UserPreferences.setPlaybackSpeed(speedPref);
- String speedStr = String.format("%.2fx", playbackSpeed);
- txtvPlaybackSpeed.setText(speedStr);
- } else if(fromUser) {
- float speed = Float.valueOf(UserPreferences.getPlaybackSpeed());
- barPlaybackSpeed.post(() -> barPlaybackSpeed.setProgress(
- (int) ((speed - minPlaybackSpeed) / PLAYBACK_SPEED_STEP)));
- }
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- if(controller != null && !controller.canSetPlaybackSpeed()) {
- VariableSpeedDialog.showGetPluginDialog(MediaplayerActivity.this);
- }
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- }
- });
- barPlaybackSpeed.setProgress((int) ((currentSpeed - minPlaybackSpeed) / PLAYBACK_SPEED_STEP));
-
- final SeekBar barLeftVolume = (SeekBar) dialog.findViewById(R.id.volume_left);
- barLeftVolume.setProgress(UserPreferences.getLeftVolumePercentage());
- final SeekBar barRightVolume = (SeekBar) dialog.findViewById(R.id.volume_right);
- barRightVolume.setProgress(UserPreferences.getRightVolumePercentage());
- final CheckBox stereoToMono = (CheckBox) dialog.findViewById(R.id.stereo_to_mono);
- stereoToMono.setChecked(UserPreferences.stereoToMono());
- if (controller != null && !controller.canDownmix()) {
- stereoToMono.setEnabled(false);
- String sonicOnly = getString(R.string.sonic_only);
- stereoToMono.setText(stereoToMono.getText() + " [" + sonicOnly + "]");
- }
-
- if (UserPreferences.useExoplayer()) {
- barRightVolume.setEnabled(false);
- }
-
- final CheckBox skipSilence = (CheckBox) dialog.findViewById(R.id.skipSilence);
- skipSilence.setChecked(UserPreferences.isSkipSilence());
- if (!UserPreferences.useExoplayer()) {
- skipSilence.setEnabled(false);
- String exoplayerOnly = getString(R.string.exoplayer_only);
- skipSilence.setText(skipSilence.getText() + " [" + exoplayerOnly + "]");
+ boolean isPlayingVideo = controller.getMedia().getMediaType() == MediaType.VIDEO;
+ PlaybackControlsDialog dialog = PlaybackControlsDialog.newInstance(isPlayingVideo);
+ dialog.show(getSupportFragmentManager(), "playback_controls");
+ break;
+ case R.id.open_feed_item:
+ if (feedItem != null) {
+ Intent intent = MainActivity.getIntentToOpenFeed(this, feedItem.getFeedId());
+ startActivity(intent);
}
- skipSilence.setOnCheckedChangeListener((buttonView, isChecked) -> {
- UserPreferences.setSkipSilence(isChecked);
- controller.setSkipSilence(isChecked);
- });
-
- barLeftVolume.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- controller.setVolume(
- Converter.getVolumeFromPercentage(progress),
- Converter.getVolumeFromPercentage(barRightVolume.getProgress()));
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- }
- });
- barRightVolume.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- controller.setVolume(
- Converter.getVolumeFromPercentage(barLeftVolume.getProgress()),
- Converter.getVolumeFromPercentage(progress));
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- }
- });
- stereoToMono.setOnCheckedChangeListener((buttonView, isChecked) -> {
- UserPreferences.stereoToMono(isChecked);
- if (controller != null) {
- controller.setDownmix(isChecked);
- }
- });
break;
case R.id.visit_website_item:
- Uri uri = Uri.parse(getWebsiteLinkWithFallback(media));
- startActivity(new Intent(Intent.ACTION_VIEW, uri));
+ IntentUtils.openInBrowser(MediaplayerActivity.this, getWebsiteLinkWithFallback(media));
break;
case R.id.share_link_item:
- if (media instanceof FeedMedia) {
- ShareUtils.shareFeedItemLink(this, ((FeedMedia) media).getItem());
+ if (feedItem != null) {
+ ShareUtils.shareFeedItemLink(this, feedItem);
}
break;
case R.id.share_download_url_item:
- if (media instanceof FeedMedia) {
- ShareUtils.shareFeedItemDownloadLink(this, ((FeedMedia) media).getItem());
+ if (feedItem != null) {
+ ShareUtils.shareFeedItemDownloadLink(this, feedItem);
}
break;
case R.id.share_link_with_position_item:
- if (media instanceof FeedMedia) {
- ShareUtils.shareFeedItemLink(this, ((FeedMedia) media).getItem(), true);
+ if (feedItem != null) {
+ ShareUtils.shareFeedItemLink(this, feedItem, true);
}
break;
case R.id.share_download_url_with_position_item:
- if (media instanceof FeedMedia) {
- ShareUtils.shareFeedItemDownloadLink(this, ((FeedMedia) media).getItem(), true);
+ if (feedItem != null) {
+ ShareUtils.shareFeedItemDownloadLink(this, feedItem, true);
}
break;
case R.id.share_file:
@@ -666,9 +533,10 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
return;
}
- int currentPosition = TimeSpeedConverter.convert(controller.getPosition());
- int duration = TimeSpeedConverter.convert(controller.getDuration());
- int remainingTime = TimeSpeedConverter.convert(
+ TimeSpeedConverter converter = new TimeSpeedConverter(controller.getCurrentPlaybackSpeedMultiplier());
+ int currentPosition = converter.convert(controller.getPosition());
+ int duration = converter.convert(controller.getDuration());
+ int remainingTime = converter.convert(
controller.getDuration() - controller.getPosition());
Log.d(TAG, "currentPosition " + Converter.getDurationStringLong(currentPosition));
if (currentPosition == PlaybackService.INVALID_TIME ||
@@ -780,7 +648,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
}
}
- static public void showSkipPreference(Activity activity, SkipDirection direction) {
+ public static void showSkipPreference(Activity activity, SkipDirection direction) {
int checked = 0;
int skipSecs = direction.getPrefSkipSeconds();
final int[] values = activity.getResources().getIntArray(R.array.seek_delta_values);
@@ -824,14 +692,15 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
return;
}
+ TimeSpeedConverter converter = new TimeSpeedConverter(controller.getCurrentPlaybackSpeedMultiplier());
String length;
if (showTimeLeft) {
- int remainingTime = TimeSpeedConverter.convert(
+ int remainingTime = converter.convert(
media.getDuration() - media.getPosition());
length = "-" + Converter.getDurationStringLong(remainingTime);
} else {
- int duration = TimeSpeedConverter.convert(media.getDuration());
+ int duration = converter.convert(media.getDuration());
length = Converter.getDurationStringLong(duration);
}
txtvLength.setText(length);
@@ -935,7 +804,8 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
prog = controller.onSeekBarProgressChanged(seekBar, progress, fromUser, txtvPosition);
if (showTimeLeft && prog != 0) {
int duration = controller.getDuration();
- int timeLeft = TimeSpeedConverter.convert(duration - (int) (prog * duration));
+ TimeSpeedConverter converter = new TimeSpeedConverter(controller.getCurrentPlaybackSpeedMultiplier());
+ int timeLeft = converter.convert(duration - (int) (prog * duration));
String length = "-" + Converter.getDurationStringLong(timeLeft);
txtvLength.setText(length);
}
@@ -956,11 +826,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
}
private void checkFavorite() {
- Playable playable = controller.getMedia();
- if (!(playable instanceof FeedMedia)) {
- return;
- }
- FeedItem feedItem = ((FeedMedia) playable).getItem();
+ FeedItem feedItem = getFeedItem(controller.getMedia());
if (feedItem == null) {
return;
}
@@ -1015,4 +881,13 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
}
}
}
+
+ @Nullable
+ private static FeedItem getFeedItem(@Nullable Playable playable) {
+ if ((playable != null) && (playable instanceof FeedMedia)) {
+ return ((FeedMedia)playable).getItem();
+ } else {
+ return null;
+ }
+ }
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java
index 4fec1cfc5..234962a8d 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java
@@ -26,6 +26,7 @@ import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ListView;
+import android.widget.TextView;
import android.widget.Toast;
import com.viewpagerindicator.CirclePageIndicator;
@@ -92,7 +93,8 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
NavListAdapter.SUBSCRIPTION_LIST_TAG
};
- Button butPlaybackSpeed;
+ ImageButton butPlaybackSpeed;
+ TextView txtvPlaybackSpeed;
ImageButton butCastDisconnect;
private DrawerLayout drawerLayout;
private NavListAdapter navAdapter;
@@ -120,7 +122,6 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
disposable.dispose();
}
EventDistributor.getInstance().unregister(contentUpdate);
- EventBus.getDefault().unregister(this);
saveCurrentFragment();
}
@@ -173,7 +174,6 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
protected void onStart() {
super.onStart();
EventDistributor.getInstance().register(contentUpdate);
- EventBus.getDefault().register(this);
loadData();
}
@@ -258,6 +258,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
});
butPlaybackSpeed = findViewById(R.id.butPlaybackSpeed);
+ txtvPlaybackSpeed = findViewById(R.id.txtvPlaybackSpeed);
butCastDisconnect = findViewById(R.id.butCastDisconnect);
pager = findViewById(R.id.pager);
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 a0c449275..732570d8a 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
@@ -32,8 +32,6 @@ import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
-import de.danoeh.antennapod.core.feed.VolumeReductionSetting;
-import de.danoeh.antennapod.core.glide.FastBlurTransformation;
import org.apache.commons.lang3.StringUtils;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -55,7 +53,9 @@ import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedPreferences;
+import de.danoeh.antennapod.core.feed.VolumeReductionSetting;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
+import de.danoeh.antennapod.core.glide.FastBlurTransformation;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadRequest;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
@@ -443,11 +443,9 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
subscribeButton.setOnClickListener(v -> {
if(feedInFeedlist(feed)) {
- Intent intent = new Intent(OnlineFeedViewActivity.this, MainActivity.class);
// feed.getId() is always 0, we have to retrieve the id from the feed list from
// the database
- intent.putExtra(MainActivity.EXTRA_FEED_ID, getFeedId(feed));
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ Intent intent = MainActivity.getIntentToOpenFeed(this, getFeedId(feed));
startActivity(intent);
} else {
Feed f = new Feed(selectedDownloadUrl, null, feed.getTitle());
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
index 2eff33339..9eb181edc 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
@@ -1,6 +1,7 @@
package de.danoeh.antennapod.adapter;
import android.os.Build;
+import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
@@ -23,10 +24,12 @@ import android.widget.TextView;
import com.joanzapata.iconify.Iconify;
import java.lang.ref.WeakReference;
+import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.actionbutton.ItemActionButton;
+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.storage.DownloadRequester;
@@ -50,6 +53,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
private final boolean showOnlyNewEpisodes;
private FeedItem selectedItem;
+ private Holder currentlyPlayingItem = null;
private final int playingBackGroundColor;
private final int normalBackGroundColor;
@@ -165,8 +169,9 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
holder.progress.setVisibility(View.INVISIBLE);
}
- if(media.isCurrentlyPlaying()) {
+ if (media.isCurrentlyPlaying()) {
holder.container.setBackgroundColor(playingBackGroundColor);
+ currentlyPlayingItem = holder;
} else {
holder.container.setBackgroundColor(normalBackGroundColor);
}
@@ -196,6 +201,22 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
.load();
}
+ @Override
+ public void onBindViewHolder(@NonNull Holder holder, int pos, List<Object> payload) {
+ onBindViewHolder(holder, pos);
+
+ if (holder == currentlyPlayingItem && payload.size() == 1 && payload.get(0) instanceof PlaybackPositionEvent) {
+ PlaybackPositionEvent event = (PlaybackPositionEvent) payload.get(0);
+ holder.progress.setProgress((int) (100.0 * event.getPosition() / event.getDuration()));
+ }
+ }
+
+ public void notifyCurrentlyPlayingItemChanged(PlaybackPositionEvent event) {
+ if (currentlyPlayingItem != null && currentlyPlayingItem.getAdapterPosition() != RecyclerView.NO_POSITION) {
+ notifyItemChanged(currentlyPlayingItem.getAdapterPosition(), event);
+ }
+ }
+
@Nullable
public FeedItem getSelectedItem() {
return selectedItem;
@@ -262,7 +283,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
FeedItem item = itemAccess.getItem(getAdapterPosition());
MenuInflater inflater = mainActivityRef.get().getMenuInflater();
- inflater.inflate(R.menu.allepisodes_context, menu);
+ inflater.inflate(R.menu.feeditemlist_context, menu);
if (item != null) {
menu.setHeaderTitle(item.getTitle());
@@ -277,9 +298,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
item1.setVisible(visible);
}
};
- FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item, true, null);
-
- contextMenuInterface.setItemVisibility(R.id.remove_new_flag_item, item.isNew());
+ FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item);
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
index cd636af43..98d55dd97 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
@@ -100,14 +100,6 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter {
String pubDateStr = DateUtils.formatAbbrev(context, item.getPubDate());
holder.pubDate.setText(pubDateStr);
- FeedItem.State state = item.getState();
- if (state == FeedItem.State.PLAYING && PlaybackService.isRunning) {
- holder.butSecondary.setEnabled(false);
- holder.butSecondary.setAlpha(0.5f);
- } else {
- holder.butSecondary.setEnabled(true);
- holder.butSecondary.setAlpha(1.0f);
- }
holder.butSecondary.setFocusable(false);
holder.butSecondary.setTag(item);
holder.butSecondary.setOnClickListener(secondaryActionListener);
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java
index b85d1d35d..b0ee87b7e 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java
@@ -1,7 +1,6 @@
package de.danoeh.antennapod.adapter;
import android.content.Context;
-import android.support.v4.content.ContextCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -15,20 +14,15 @@ import de.danoeh.antennapod.core.service.download.DownloadRequest;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.service.download.Downloader;
import de.danoeh.antennapod.core.util.Converter;
-import de.danoeh.antennapod.core.util.ThemeUtils;
public class DownloadlistAdapter extends BaseAdapter {
- private static final int SELECTION_NONE = -1;
-
- private int selectedItemIndex;
private final ItemAccess itemAccess;
private final Context context;
public DownloadlistAdapter(Context context,
ItemAccess itemAccess) {
super();
- this.selectedItemIndex = SELECTION_NONE;
this.context = context;
this.itemAccess = itemAccess;
}
@@ -74,13 +68,6 @@ public class DownloadlistAdapter extends BaseAdapter {
holder = (Holder) convertView.getTag();
}
- if (position == selectedItemIndex) {
- convertView.setBackgroundColor(ContextCompat.getColor(convertView.getContext(),
- ThemeUtils.getSelectionBackgroundColor()));
- } else {
- convertView.setBackgroundResource(0);
- }
-
holder.title.setText(request.getTitle());
holder.progbar.setIndeterminate(request.getSoFar() <= 0);
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
index a365b1b2e..463ad10a0 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
@@ -13,15 +13,18 @@ import android.widget.BaseAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
+import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.actionbutton.ItemActionButton;
+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.MediaType;
import de.danoeh.antennapod.core.storage.DownloadRequester;
+import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.DateUtils;
import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.ThemeUtils;
@@ -34,15 +37,13 @@ public class FeedItemlistAdapter extends BaseAdapter {
private final ItemAccess itemAccess;
private final Context context;
private final boolean showFeedtitle;
- private final int selectedItemIndex;
/** true if played items should be made partially transparent */
private final boolean makePlayedItemsTransparent;
-
- private static final int SELECTION_NONE = -1;
-
private final int playingBackGroundColor;
private final int normalBackGroundColor;
+ private int currentlyPlayingItem = -1;
+
public FeedItemlistAdapter(Context context,
ItemAccess itemAccess,
boolean showFeedtitle,
@@ -51,7 +52,6 @@ public class FeedItemlistAdapter extends BaseAdapter {
this.context = context;
this.itemAccess = itemAccess;
this.showFeedtitle = showFeedtitle;
- this.selectedItemIndex = SELECTION_NONE;
this.makePlayedItemsTransparent = makePlayedItemsTransparent;
playingBackGroundColor = ThemeUtils.getColorFromAttr(context, R.attr.currently_playing_background);
@@ -112,12 +112,6 @@ public class FeedItemlistAdapter extends BaseAdapter {
if (!(getItemViewType(position) == Adapter.IGNORE_ITEM_VIEW_TYPE)) {
convertView.setVisibility(View.VISIBLE);
- if (position == selectedItemIndex) {
- convertView.setBackgroundColor(ContextCompat.getColor(convertView.getContext(),
- ThemeUtils.getSelectionBackgroundColor()));
- } else {
- convertView.setBackgroundResource(0);
- }
StringBuilder buffer = new StringBuilder(item.getTitle());
if (showFeedtitle) {
@@ -187,8 +181,9 @@ public class FeedItemlistAdapter extends BaseAdapter {
}
typeDrawables.recycle();
- if(media.isCurrentlyPlaying()) {
+ if (media.isCurrentlyPlaying()) {
holder.container.setBackgroundColor(playingBackGroundColor);
+ currentlyPlayingItem = position;
} else {
holder.container.setBackgroundColor(normalBackGroundColor);
}
@@ -206,6 +201,19 @@ public class FeedItemlistAdapter extends BaseAdapter {
return convertView;
}
+ public void notifyCurrentlyPlayingItemChanged(PlaybackPositionEvent event, ListView listView) {
+ if (currentlyPlayingItem != -1 && currentlyPlayingItem < getCount()) {
+ View view = listView.getChildAt(currentlyPlayingItem
+ - listView.getFirstVisiblePosition() + listView.getHeaderViewsCount());
+ if (view == null) {
+ return;
+ }
+ Holder holder = (Holder) view.getTag();
+ holder.episodeProgress.setProgress((int) (100.0 * event.getPosition() / event.getDuration()));
+ holder.lenSize.setText(Converter.getDurationStringLong(event.getDuration() - event.getPosition()));
+ }
+ }
+
static class Holder {
LinearLayout container;
TextView title;
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 c10bb7638..8d469c7a6 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java
@@ -1,6 +1,7 @@
package de.danoeh.antennapod.adapter;
import android.content.Context;
+import android.os.Build;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -51,6 +52,17 @@ public class FeedItemlistDescriptionAdapter extends ArrayAdapter<FeedItem> {
.replaceAll("\\s+", " ")
.trim();
holder.description.setText(description);
+
+ final int MAX_LINES_COLLAPSED = 3;
+ holder.description.setMaxLines(MAX_LINES_COLLAPSED);
+ holder.description.setOnClickListener(v -> {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
+ && holder.description.getMaxLines() > MAX_LINES_COLLAPSED) {
+ holder.description.setMaxLines(MAX_LINES_COLLAPSED);
+ } else {
+ holder.description.setMaxLines(2000);
+ }
+ });
}
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 382abfb32..148b36d21 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
@@ -1,7 +1,7 @@
package de.danoeh.antennapod.adapter;
-import android.content.Context;
import android.os.Build;
+import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.MotionEventCompat;
@@ -25,9 +25,11 @@ import android.widget.TextView;
import com.joanzapata.iconify.Iconify;
+import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import org.apache.commons.lang3.ArrayUtils;
import java.lang.ref.WeakReference;
+import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
@@ -58,6 +60,7 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
private boolean locked;
private FeedItem selectedItem;
+ private ViewHolder currentlyPlayingItem = null;
private final int playingBackGroundColor;
private final int normalBackGroundColor;
@@ -94,6 +97,18 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
});
}
+ @Override
+ public void onBindViewHolder(@NonNull ViewHolder holder, int pos, List<Object> payload) {
+ onBindViewHolder(holder, pos);
+
+ if (holder == currentlyPlayingItem && payload.size() == 1 && payload.get(0) instanceof PlaybackPositionEvent) {
+ PlaybackPositionEvent event = (PlaybackPositionEvent) payload.get(0);
+ holder.progressBar.setProgress((int) (100.0 * event.getPosition() / event.getDuration()));
+ holder.progressLeft.setText(Converter.getDurationStringLong(event.getPosition()));
+ holder.progressRight.setText(Converter.getDurationStringLong(event.getDuration()));
+ }
+ }
+
@Nullable
public FeedItem getSelectedItem() {
return selectedItem;
@@ -109,6 +124,12 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
return itemAccess.getCount();
}
+ public void notifyCurrentlyPlayingItemChanged(PlaybackPositionEvent event) {
+ if (currentlyPlayingItem != null && currentlyPlayingItem.getAdapterPosition() != RecyclerView.NO_POSITION) {
+ notifyItemChanged(currentlyPlayingItem.getAdapterPosition(), event);
+ }
+ }
+
public class ViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener,
View.OnCreateContextMenuListener,
@@ -169,7 +190,8 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
FeedItem item = itemAccess.getItem(getAdapterPosition());
MenuInflater inflater = mainActivity.get().getMenuInflater();
- inflater.inflate(R.menu.queue_context, menu);
+ inflater.inflate(R.menu.queue_context, menu); // queue-specific menu items
+ inflater.inflate(R.menu.feeditemlist_context, menu); // generic menu items for item feeds
if (item != null) {
menu.setHeaderTitle(item.getTitle());
@@ -184,7 +206,18 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
item1.setVisible(visible);
}
};
- FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item, true, itemAccess.getQueueIds());
+
+ FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item,
+ R.id.skip_episode_item); // Skip Episode is not useful in Queue, so hide it.
+ // Queue-specific menu preparation
+ final boolean keepSorted = UserPreferences.isQueueKeepSorted();
+ final LongList queueAccess = itemAccess.getQueueIds();
+ if (queueAccess.size() == 0 || queueAccess.get(0) == item.getId() || keepSorted) {
+ contextMenuInterface.setItemVisibility(R.id.move_to_top_item, false);
+ }
+ if (queueAccess.size() == 0 || queueAccess.get(queueAccess.size()-1) == item.getId() || keepSorted) {
+ contextMenuInterface.setItemVisibility(R.id.move_to_bottom_item, false);
+ }
}
@Override
@@ -276,6 +309,7 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
if(media.isCurrentlyPlaying()) {
container.setBackgroundColor(playingBackGroundColor);
+ currentlyPlayingItem = this;
} else {
container.setBackgroundColor(normalBackGroundColor);
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java
index 763dcb57d..e0fb65c61 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java
@@ -14,13 +14,11 @@ import com.bumptech.glide.Glide;
import java.lang.ref.WeakReference;
-import com.bumptech.glide.request.RequestOptions;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.feed.Feed;
-import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.fragment.AddFeedFragment;
-import de.danoeh.antennapod.fragment.ItemlistFragment;
+import de.danoeh.antennapod.fragment.FeedItemlistFragment;
import jp.shts.android.library.TriangleLabelView;
/**
@@ -142,7 +140,7 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI
if (position == getAddTilePosition()) {
mainActivityRef.get().loadChildFragment(new AddFeedFragment());
} else {
- Fragment fragment = ItemlistFragment.newInstance(getItemId(position));
+ Fragment fragment = FeedItemlistFragment.newInstance(getItemId(position));
mainActivityRef.get().loadChildFragment(fragment);
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/ItemActionButton.java b/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/ItemActionButton.java
index da5ebf6e1..6dbeccfc9 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/ItemActionButton.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/ItemActionButton.java
@@ -20,12 +20,12 @@ public abstract class ItemActionButton {
}
@StringRes
- abstract public int getLabel();
+ public abstract int getLabel();
@AttrRes
- abstract public int getDrawable();
+ public abstract int getDrawable();
- abstract public void onClick(Context context);
+ public abstract void onClick(Context context);
public int getVisibility() {
return View.VISIBLE;
diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/DocumentFileExportWorker.java b/app/src/main/java/de/danoeh/antennapod/asynctask/DocumentFileExportWorker.java
new file mode 100644
index 000000000..0e9572a82
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/asynctask/DocumentFileExportWorker.java
@@ -0,0 +1,72 @@
+package de.danoeh.antennapod.asynctask;
+
+import android.content.Context;
+import android.net.Uri;
+import android.support.annotation.NonNull;
+import android.support.v4.provider.DocumentFile;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+
+import de.danoeh.antennapod.core.export.ExportWriter;
+import de.danoeh.antennapod.core.storage.DBReader;
+import de.danoeh.antennapod.core.util.LangUtils;
+import io.reactivex.Observable;
+
+/**
+ * Writes an OPML file into the user selected export directory in the background.
+ */
+public class DocumentFileExportWorker {
+
+ private final @NonNull ExportWriter exportWriter;
+ private @NonNull Context context;
+ private @NonNull Uri outputFileUri;
+
+ public DocumentFileExportWorker(@NonNull ExportWriter exportWriter, @NonNull Context context, @NonNull Uri outputFileUri) {
+ this.exportWriter = exportWriter;
+ this.context = context;
+ this.outputFileUri = outputFileUri;
+ }
+
+ public Observable<DocumentFile> exportObservable() {
+ DocumentFile output = DocumentFile.fromSingleUri(context, outputFileUri);
+ return Observable.create(subscriber -> {
+ OutputStream outputStream = null;
+ OutputStreamWriter writer = null;
+ try {
+ Uri uri = output.getUri();
+ if (uri == null) {
+ throw new FileNotFoundException("Export file not found.");
+ }
+ outputStream = context.getContentResolver().openOutputStream(uri);
+ if (outputStream == null) {
+ throw new IOException();
+ }
+ writer = new OutputStreamWriter(outputStream, LangUtils.UTF_8);
+ exportWriter.writeDocument(DBReader.getFeedList(), writer);
+ subscriber.onNext(output);
+ } catch (IOException e) {
+ subscriber.onError(e);
+ } finally {
+ if (writer != null) {
+ try {
+ writer.close();
+ } catch (IOException e) {
+ subscriber.onError(e);
+ }
+ }
+ if (outputStream != null) {
+ try {
+ outputStream.close();
+ } catch (IOException e) {
+ subscriber.onError(e);
+ }
+ }
+ subscriber.onComplete();
+ }
+ });
+ }
+
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java b/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java
index eb70d8e0b..c3f5d898c 100644
--- a/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java
+++ b/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java
@@ -35,6 +35,6 @@ public class PlaybackServiceCallbacksImpl implements PlaybackServiceCallbacks {
@Override
public int getNotificationIconResource(Context context) {
- return R.drawable.ic_stat_antenna_default;
+ return R.drawable.ic_antenna;
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/ChooseDataFolderDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/ChooseDataFolderDialog.java
index c185a5557..4cfa7e870 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/ChooseDataFolderDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/ChooseDataFolderDialog.java
@@ -9,7 +9,7 @@ import de.danoeh.antennapod.adapter.DataFolderAdapter;
public class ChooseDataFolderDialog {
- public static abstract class RunnableWithString implements Runnable {
+ public abstract static class RunnableWithString implements Runnable {
public RunnableWithString() {
super();
}
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 bb47f8baa..ed35495fa 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
@@ -3,7 +3,6 @@ package de.danoeh.antennapod.dialog;
import android.app.AlertDialog;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
-import android.os.Build;
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
@@ -13,7 +12,6 @@ import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.util.ArrayMap;
-import android.support.v4.view.ViewCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
@@ -168,7 +166,8 @@ public class EpisodesApplyActionFragment extends Fragment {
return true;
});
- for(FeedItem episode : episodes) {
+ titles.clear();
+ for (FeedItem episode : episodes) {
titles.add(episode.getTitle());
}
@@ -205,10 +204,6 @@ public class EpisodesApplyActionFragment extends Fragment {
return true;
});
- if (Build.VERSION.SDK_INT == 23 || Build.VERSION.SDK_INT == 24) {
- ViewCompat.setElevation(view.findViewById(R.id.fabSDScrollCtr), 8);
- }
-
showSpeedDialIfAnyChecked();
return view;
@@ -221,7 +216,13 @@ public class EpisodesApplyActionFragment extends Fragment {
}
private void showSpeedDialIfAnyChecked() {
- mSpeedDialView.setVisibility(checkedIds.size() > 0 ? View.VISIBLE : View.GONE);
+ if (checkedIds.size() > 0) {
+ if (!mSpeedDialView.isShown()) {
+ mSpeedDialView.show();
+ }
+ } else {
+ mSpeedDialView.hide(); // hide() also handles UI, e.g., overlay properly.
+ }
}
@Override
@@ -245,10 +246,13 @@ public class EpisodesApplyActionFragment extends Fragment {
// Prepare icon for select toggle button
int[] icon = new int[1];
+ @StringRes int titleResId;
if (checkedIds.size() == episodes.size()) {
icon[0] = R.attr.ic_select_none;
+ titleResId = R.string.deselect_all_label;
} else {
icon[0] = R.attr.ic_select_all;
+ titleResId = R.string.select_all_label;
}
TypedArray a = getActivity().obtainStyledAttributes(icon);
@@ -256,6 +260,7 @@ public class EpisodesApplyActionFragment extends Fragment {
a.recycle();
mSelectToggle.setIcon(iconDrawable);
+ mSelectToggle.setTitle(titleResId);
}
@Override
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/FilterDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/FilterDialog.java
new file mode 100644
index 000000000..607084c42
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/FilterDialog.java
@@ -0,0 +1,62 @@
+package de.danoeh.antennapod.dialog;
+
+import android.content.Context;
+import android.support.v7.app.AlertDialog;
+import android.text.TextUtils;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.feed.FeedItemFilter;
+
+public abstract class FilterDialog {
+
+ protected FeedItemFilter filter;
+ protected Context context;
+
+ public FilterDialog(Context context, FeedItemFilter feedItemFilter) {
+ this.context = context;
+ this.filter = feedItemFilter;
+ }
+
+ 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()));
+
+ // make sure we have no empty strings in the filter list
+ for (String filterValue : filterValues) {
+ if (TextUtils.isEmpty(filterValue)) {
+ filterValues.remove(filterValue);
+ }
+ }
+
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ if (filterValues.contains(value)) {
+ checkedItems[i] = 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) -> {
+ updateFilter(filterValues);
+ });
+ builder.setNegativeButton(R.string.cancel_label, null);
+ builder.create().show();
+ }
+
+ protected abstract void updateFilter(Set<String> filterValues);
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java
new file mode 100644
index 000000000..e8c7520b7
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java
@@ -0,0 +1,214 @@
+package de.danoeh.antennapod.dialog;
+
+import android.app.Dialog;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.DialogFragment;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import com.afollestad.materialdialogs.MaterialDialog;
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.util.Converter;
+import de.danoeh.antennapod.core.util.playback.PlaybackController;
+
+import java.util.Locale;
+
+public class PlaybackControlsDialog extends DialogFragment {
+ private static final float PLAYBACK_SPEED_STEP = 0.05f;
+ private static final float DEFAULT_MIN_PLAYBACK_SPEED = 0.5f;
+ private static final float DEFAULT_MAX_PLAYBACK_SPEED = 2.5f;
+ private static final String ARGUMENT_IS_PLAYING_VIDEO = "isPlayingVideo";
+
+ private PlaybackController controller;
+ private MaterialDialog dialog;
+ private boolean isPlayingVideo;
+
+ public static PlaybackControlsDialog newInstance(boolean isPlayingVideo) {
+ Bundle arguments = new Bundle();
+ arguments.putBoolean(ARGUMENT_IS_PLAYING_VIDEO, isPlayingVideo);
+ PlaybackControlsDialog dialog = new PlaybackControlsDialog();
+ dialog.setArguments(arguments);
+ return dialog;
+ }
+
+ public PlaybackControlsDialog() {
+ // Empty constructor required for DialogFragment
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ controller = new PlaybackController(getActivity(), false);
+ controller.init();
+ setupUi();
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ controller.release();
+ controller = null;
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ isPlayingVideo = getArguments() != null && getArguments().getBoolean(ARGUMENT_IS_PLAYING_VIDEO);
+
+ dialog = new MaterialDialog.Builder(getContext())
+ .title(R.string.audio_controls)
+ .customView(R.layout.audio_controls, true)
+ .neutralText(R.string.close_label)
+ .onNeutral((dialog1, which) -> {
+ final SeekBar left = (SeekBar) dialog1.findViewById(R.id.volume_left);
+ final SeekBar right = (SeekBar) dialog1.findViewById(R.id.volume_right);
+ UserPreferences.setVolume(left.getProgress(), right.getProgress());
+ }).build();
+ return dialog;
+ }
+
+ private void setupUi() {
+ final SeekBar barPlaybackSpeed = (SeekBar) dialog.findViewById(R.id.playback_speed);
+ final Button butDecSpeed = (Button) dialog.findViewById(R.id.butDecSpeed);
+ butDecSpeed.setOnClickListener(v -> {
+ if (controller != null && controller.canSetPlaybackSpeed()) {
+ barPlaybackSpeed.setProgress(barPlaybackSpeed.getProgress() - 1);
+ } else {
+ VariableSpeedDialog.showGetPluginDialog(getContext());
+ }
+ });
+ final Button butIncSpeed = (Button) dialog.findViewById(R.id.butIncSpeed);
+ butIncSpeed.setOnClickListener(v -> {
+ if (controller != null && controller.canSetPlaybackSpeed()) {
+ barPlaybackSpeed.setProgress(barPlaybackSpeed.getProgress() + 1);
+ } else {
+ VariableSpeedDialog.showGetPluginDialog(getContext());
+ }
+ });
+
+ final TextView txtvPlaybackSpeed = (TextView) dialog.findViewById(R.id.txtvPlaybackSpeed);
+ float currentSpeed = getCurrentSpeed();
+
+ String[] availableSpeeds = UserPreferences.getPlaybackSpeedArray();
+ final float minPlaybackSpeed = availableSpeeds.length > 1 ?
+ Float.valueOf(availableSpeeds[0]) : DEFAULT_MIN_PLAYBACK_SPEED;
+ float maxPlaybackSpeed = availableSpeeds.length > 1 ?
+ Float.valueOf(availableSpeeds[availableSpeeds.length - 1]) : DEFAULT_MAX_PLAYBACK_SPEED;
+ int progressMax = (int) ((maxPlaybackSpeed - minPlaybackSpeed) / PLAYBACK_SPEED_STEP);
+ barPlaybackSpeed.setMax(progressMax);
+
+ txtvPlaybackSpeed.setText(String.format("%.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 * PLAYBACK_SPEED_STEP + minPlaybackSpeed;
+ controller.setPlaybackSpeed(playbackSpeed);
+ String speedPref = String.format(Locale.US, "%.2f", playbackSpeed);
+
+ if (isPlayingVideo) {
+ UserPreferences.setVideoPlaybackSpeed(speedPref);
+ } else {
+ UserPreferences.setPlaybackSpeed(speedPref);
+ }
+
+ String speedStr = String.format("%.2fx", playbackSpeed);
+ txtvPlaybackSpeed.setText(speedStr);
+ } else if (fromUser) {
+ float speed = getCurrentSpeed();
+ barPlaybackSpeed.post(() -> barPlaybackSpeed.setProgress(
+ (int) ((speed - minPlaybackSpeed) / PLAYBACK_SPEED_STEP)));
+ }
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ if (controller != null && !controller.canSetPlaybackSpeed()) {
+ VariableSpeedDialog.showGetPluginDialog(getContext());
+ }
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+ });
+ barPlaybackSpeed.setProgress((int) ((currentSpeed - minPlaybackSpeed) / PLAYBACK_SPEED_STEP));
+
+ final SeekBar barLeftVolume = (SeekBar) dialog.findViewById(R.id.volume_left);
+ barLeftVolume.setProgress(UserPreferences.getLeftVolumePercentage());
+ final SeekBar barRightVolume = (SeekBar) dialog.findViewById(R.id.volume_right);
+ barRightVolume.setProgress(UserPreferences.getRightVolumePercentage());
+ final CheckBox stereoToMono = (CheckBox) dialog.findViewById(R.id.stereo_to_mono);
+ stereoToMono.setChecked(UserPreferences.stereoToMono());
+ if (controller != null && !controller.canDownmix()) {
+ stereoToMono.setEnabled(false);
+ String sonicOnly = getString(R.string.sonic_only);
+ stereoToMono.setText(stereoToMono.getText() + " [" + sonicOnly + "]");
+ }
+
+ if (UserPreferences.useExoplayer()) {
+ barRightVolume.setEnabled(false);
+ }
+
+ final CheckBox skipSilence = (CheckBox) dialog.findViewById(R.id.skipSilence);
+ skipSilence.setChecked(UserPreferences.isSkipSilence());
+ if (!UserPreferences.useExoplayer()) {
+ skipSilence.setEnabled(false);
+ String exoplayerOnly = getString(R.string.exoplayer_only);
+ skipSilence.setText(skipSilence.getText() + " [" + exoplayerOnly + "]");
+ }
+ skipSilence.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ UserPreferences.setSkipSilence(isChecked);
+ controller.setSkipSilence(isChecked);
+ });
+
+ barLeftVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ controller.setVolume(
+ Converter.getVolumeFromPercentage(progress),
+ Converter.getVolumeFromPercentage(barRightVolume.getProgress()));
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+ });
+ barRightVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ controller.setVolume(
+ Converter.getVolumeFromPercentage(barLeftVolume.getProgress()),
+ Converter.getVolumeFromPercentage(progress));
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+ });
+ stereoToMono.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ UserPreferences.stereoToMono(isChecked);
+ if (controller != null) {
+ controller.setDownmix(isChecked);
+ }
+ });
+ }
+
+ private float getCurrentSpeed() {
+ if (isPlayingVideo) {
+ return UserPreferences.getVideoPlaybackSpeed();
+ }
+ return UserPreferences.getPlaybackSpeed();
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/RatingDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/RatingDialog.java
index 24656ed29..5969963f2 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/RatingDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/RatingDialog.java
@@ -15,6 +15,7 @@ import java.lang.ref.WeakReference;
import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.util.IntentUtils;
public class RatingDialog {
@@ -59,14 +60,10 @@ public class RatingDialog {
private static void rateNow() {
Context context = mContext.get();
- if(context == null) {
+ if (context == null) {
return;
}
- final String appPackage = "de.danoeh.antennapod";
- final Uri uri = Uri.parse("https://play.google.com/store/apps/details?id=" + appPackage);
- Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- context.startActivity(intent);
+ IntentUtils.openInBrowser(context, "https://play.google.com/store/apps/details?id=de.danoeh.antennapod");
saveRated();
}
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 cf9a2907b..bf3faf89a 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java
@@ -32,6 +32,7 @@ public class VariableSpeedDialog {
public static void showDialog(final Context context) {
if (org.antennapod.audio.MediaPlayer.isPrestoLibraryInstalled(context)
|| UserPreferences.useSonic()
+ || UserPreferences.useExoplayer()
|| Build.VERSION.SDK_INT >= 23) {
showSpeedSelectorDialog(context);
} else {
diff --git a/app/src/main/java/de/danoeh/antennapod/discovery/CombinedSearcher.java b/app/src/main/java/de/danoeh/antennapod/discovery/CombinedSearcher.java
index 18d65a03c..e34d8539c 100644
--- a/app/src/main/java/de/danoeh/antennapod/discovery/CombinedSearcher.java
+++ b/app/src/main/java/de/danoeh/antennapod/discovery/CombinedSearcher.java
@@ -24,7 +24,7 @@ public class CombinedSearcher implements PodcastSearcher {
public CombinedSearcher(Context context) {
addProvider(new FyydPodcastSearcher(), 1.f);
addProvider(new ItunesPodcastSearcher(context), 1.f);
- addProvider(new GpodnetPodcastSearcher(), 0.6f);
+ //addProvider(new GpodnetPodcastSearcher(), 0.6f);
}
private void addProvider(PodcastSearcher provider, float priority) {
diff --git a/app/src/main/java/de/danoeh/antennapod/discovery/ItunesTopListLoader.java b/app/src/main/java/de/danoeh/antennapod/discovery/ItunesTopListLoader.java
index bc9133258..79ccd9532 100644
--- a/app/src/main/java/de/danoeh/antennapod/discovery/ItunesTopListLoader.java
+++ b/app/src/main/java/de/danoeh/antennapod/discovery/ItunesTopListLoader.java
@@ -33,16 +33,12 @@ public class ItunesTopListLoader {
OkHttpClient client = AntennapodHttpClient.getHttpClient();
String feedString;
try {
- try {
- feedString = getTopListFeed(client, lang, limit);
- } catch (IOException e) {
- feedString = getTopListFeed(client, "us", limit);
- }
- List<PodcastSearchResult> podcasts = parseFeed(feedString);
- emitter.onSuccess(podcasts);
- } catch (IOException | JSONException e) {
- emitter.onError(e);
+ feedString = getTopListFeed(client, lang, limit);
+ } catch (IOException e) {
+ feedString = getTopListFeed(client, "us", limit);
}
+ List<PodcastSearchResult> podcasts = parseFeed(feedString);
+ emitter.onSuccess(podcasts);
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
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 35bcaa76e..3ef010f88 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java
@@ -70,11 +70,8 @@ public class AddFeedFragment extends Fragment {
combinedFeedSearchBox = root.findViewById(R.id.combinedFeedSearchBox);
combinedFeedSearchBox.setOnEditorActionListener((v, actionId, event) -> {
- if (actionId == EditorInfo.IME_ACTION_SEARCH) {
- performSearch();
- return true;
- }
- return false;
+ performSearch();
+ return true;
});
}
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 62d798cf6..bb52b26b7 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
@@ -1,18 +1,9 @@
package de.danoeh.antennapod.fragment;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.SharedPreferences;
import android.os.Bundle;
-import android.os.Handler;
import android.support.annotation.NonNull;
-import android.support.design.widget.Snackbar;
-import android.support.v4.app.Fragment;
-import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.SearchView;
-import android.support.v7.widget.SimpleItemAnimator;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -20,231 +11,50 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ProgressBar;
-import android.widget.Toast;
-
-import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
-
-import org.greenrobot.eventbus.EventBus;
-import org.greenrobot.eventbus.Subscribe;
-import org.greenrobot.eventbus.ThreadMode;
-
-import java.util.ArrayList;
-import java.util.List;
-
+import com.joanzapata.iconify.Iconify;
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.adapter.AllEpisodesRecycleAdapter;
-import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
-import de.danoeh.antennapod.core.event.DownloadEvent;
-import de.danoeh.antennapod.core.event.DownloaderUpdate;
-import de.danoeh.antennapod.core.event.FeedItemEvent;
-import de.danoeh.antennapod.core.feed.EventDistributor;
-import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
-import de.danoeh.antennapod.core.feed.FeedMedia;
-import de.danoeh.antennapod.core.preferences.UserPreferences;
-import de.danoeh.antennapod.core.service.download.DownloadRequest;
-import de.danoeh.antennapod.core.service.download.DownloadService;
-import de.danoeh.antennapod.core.service.download.Downloader;
+import de.danoeh.antennapod.core.feed.FeedItemFilter;
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.DownloadRequester;
-import de.danoeh.antennapod.core.util.FeedItemUtil;
-import de.danoeh.antennapod.core.util.LongList;
-import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
-import de.danoeh.antennapod.menuhandler.MenuItemUtils;
-import de.danoeh.antennapod.view.EmptyViewHandler;
+import de.danoeh.antennapod.dialog.FilterDialog;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
-import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
+import java.util.List;
+import java.util.Set;
+
/**
- * Shows unread or recently published episodes
+ * Like 'EpisodesFragment' except that it only shows new episodes and
+ * supports swiping to mark as read.
*/
-public class AllEpisodesFragment extends Fragment {
+public class AllEpisodesFragment extends EpisodesListFragment {
public static final String TAG = "AllEpisodesFragment";
+ private static final String PREF_NAME = "PrefAllEpisodesFragment";
- private static final int EVENTS = EventDistributor.FEED_LIST_UPDATE |
- EventDistributor.UNREAD_ITEMS_UPDATE |
- EventDistributor.PLAYER_STATUS_UPDATE;
-
- private static final int RECENT_EPISODES_LIMIT = 150;
- private static final String DEFAULT_PREF_NAME = "PrefAllEpisodesFragment";
- private static final String PREF_SCROLL_POSITION = "scroll_position";
- private static final String PREF_SCROLL_OFFSET = "scroll_offset";
-
- RecyclerView recyclerView;
- AllEpisodesRecycleAdapter listAdapter;
- private ProgressBar progLoading;
- EmptyViewHandler emptyView;
-
- @NonNull
- List<FeedItem> episodes = new ArrayList<>();
- @NonNull
- private List<Downloader> downloaderList = new ArrayList<>();
-
- private boolean isUpdatingFeeds;
- boolean isMenuInvalidationAllowed = false;
-
- Disposable disposable;
- private LinearLayoutManager layoutManager;
-
- boolean showOnlyNewEpisodes() {
- return false;
- }
-
- String getPrefName() {
- return DEFAULT_PREF_NAME;
- }
-
- @Override
- public void onStart() {
- super.onStart();
- setHasOptionsMenu(true);
- EventDistributor.getInstance().register(contentUpdate);
- EventBus.getDefault().register(this);
- loadItems();
- }
-
- @Override
- public void onResume() {
- super.onResume();
- registerForContextMenu(recyclerView);
- }
-
- @Override
- public void onPause() {
- super.onPause();
- saveScrollPosition();
- unregisterForContextMenu(recyclerView);
- }
-
- @Override
- public void onStop() {
- super.onStop();
- EventBus.getDefault().unregister(this);
- EventDistributor.getInstance().unregister(contentUpdate);
- if (disposable != null) {
- disposable.dispose();
- }
- }
-
- private void saveScrollPosition() {
- int firstItem = layoutManager.findFirstVisibleItemPosition();
- View firstItemView = layoutManager.findViewByPosition(firstItem);
- float topOffset;
- if (firstItemView == null) {
- topOffset = 0;
- } else {
- topOffset = firstItemView.getTop();
- }
+ private static final int EPISODES_PER_PAGE = 150;
+ private static final int VISIBLE_EPISODES_SCROLL_THRESHOLD = 5;
+ private static int page = 1;
- SharedPreferences prefs = getActivity().getSharedPreferences(getPrefName(), Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putInt(PREF_SCROLL_POSITION, firstItem);
- editor.putFloat(PREF_SCROLL_OFFSET, topOffset);
- editor.commit();
- }
-
- private void restoreScrollPosition() {
- SharedPreferences prefs = getActivity().getSharedPreferences(getPrefName(), Context.MODE_PRIVATE);
- int position = prefs.getInt(PREF_SCROLL_POSITION, 0);
- float offset = prefs.getFloat(PREF_SCROLL_OFFSET, 0.0f);
- if (position > 0 || offset > 0) {
- layoutManager.scrollToPositionWithOffset(position, (int) offset);
- // restore once, then forget
- SharedPreferences.Editor editor = prefs.edit();
- editor.putInt(PREF_SCROLL_POSITION, 0);
- editor.putFloat(PREF_SCROLL_OFFSET, 0.0f);
- editor.commit();
- }
- }
-
- private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker =
- () -> DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds();
+ private static FeedItemFilter feedItemFilter = new FeedItemFilter("");
@Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- if (!isAdded()) {
- return;
- }
- super.onCreateOptionsMenu(menu, inflater);
- inflater.inflate(R.menu.episodes, menu);
-
- MenuItem searchItem = menu.findItem(R.id.action_search);
- final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
- MenuItemUtils.adjustTextColor(getActivity(), sv);
- sv.setQueryHint(getString(R.string.search_hint));
- sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
- @Override
- public boolean onQueryTextSubmit(String s) {
- sv.clearFocus();
- ((MainActivity) requireActivity()).loadChildFragment(SearchFragment.newInstance(s));
- return true;
- }
-
- @Override
- public boolean onQueryTextChange(String s) {
- return false;
- }
- });
- isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker);
+ protected boolean showOnlyNewEpisodes() {
+ return false;
}
@Override
- public void onPrepareOptionsMenu(Menu menu) {
- super.onPrepareOptionsMenu(menu);
- MenuItem markAllRead = menu.findItem(R.id.mark_all_read_item);
- if (markAllRead != null) {
- markAllRead.setVisible(!showOnlyNewEpisodes() && !episodes.isEmpty());
- }
- MenuItem removeAllNewFlags = menu.findItem(R.id.remove_all_new_flags_item);
- if (removeAllNewFlags != null) {
- removeAllNewFlags.setVisible(showOnlyNewEpisodes() && !episodes.isEmpty());
- }
+ protected String getPrefName() {
+ return PREF_NAME;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (!super.onOptionsItemSelected(item)) {
switch (item.getItemId()) {
- case R.id.refresh_item:
- List<Feed> feeds = ((MainActivity) getActivity()).getFeeds();
- if (feeds != null) {
- DBTasks.refreshAllFeeds(getActivity(), feeds);
- }
- return true;
- case R.id.mark_all_read_item:
- ConfirmationDialog markAllReadConfirmationDialog = new ConfirmationDialog(getActivity(),
- R.string.mark_all_read_label,
- R.string.mark_all_read_confirmation_msg) {
-
- @Override
- public void onConfirmButtonPressed(DialogInterface dialog) {
- dialog.dismiss();
- DBWriter.markAllItemsRead();
- Toast.makeText(getActivity(), R.string.mark_all_read_msg, Toast.LENGTH_SHORT).show();
- }
- };
- markAllReadConfirmationDialog.createNewDialog().show();
- return true;
- case R.id.remove_all_new_flags_item:
- ConfirmationDialog removeAllNewFlagsConfirmationDialog = new ConfirmationDialog(getActivity(),
- R.string.remove_all_new_flags_label,
- R.string.remove_all_new_flags_confirmation_msg) {
-
- @Override
- public void onConfirmButtonPressed(DialogInterface dialog) {
- dialog.dismiss();
- DBWriter.removeAllNewFlags();
- Toast.makeText(getActivity(), R.string.removed_all_new_flags_msg, Toast.LENGTH_SHORT).show();
- }
- };
- removeAllNewFlagsConfirmationDialog.createNewDialog().show();
+ case R.id.filter_items:
+ showFilterDialog();
return true;
default:
return false;
@@ -252,250 +62,105 @@ public class AllEpisodesFragment extends Fragment {
} else {
return true;
}
-
- }
-
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- Log.d(TAG, "onContextItemSelected() called with: " + "item = [" + item + "]");
- if (!getUserVisibleHint()) {
- return false;
- }
- if (!isVisible()) {
- return false;
- }
- if (item.getItemId() == R.id.share_item) {
- return true; // avoids that the position is reset when we need it in the submenu
- }
-
- if (listAdapter.getSelectedItem() == null) {
- Log.i(TAG, "Selected item or listAdapter was null, ignoring selection");
- return super.onContextItemSelected(item);
- }
- FeedItem selectedItem = listAdapter.getSelectedItem();
-
- // Remove new flag contains UI logic specific to All/New/FavoriteSegments,
- // e.g., Undo with Snackbar,
- // and is handled by this class rather than the generic FeedItemMenuHandler
- // Undo is useful for Remove new flag, given there is no UI to undo it otherwise,
- // i.e., there is context menu item for Mark as new
- if (R.id.remove_new_flag_item == item.getItemId()) {
- removeNewFlagWithUndo(selectedItem);
- return true;
- }
-
- return FeedItemMenuHandler.onMenuItemClicked(getActivity(), item.getItemId(), selectedItem);
}
@NonNull
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- super.onCreateView(inflater, container, savedInstanceState);
- View root = inflater.inflate(R.layout.all_episodes_fragment, container, false);
-
- layoutManager = new LinearLayoutManager(getActivity());
- recyclerView = root.findViewById(android.R.id.list);
- recyclerView.setLayoutManager(layoutManager);
- recyclerView.setHasFixedSize(true);
- recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getActivity()).build());
- recyclerView.setVisibility(View.GONE);
-
- RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator();
- if (animator instanceof SimpleItemAnimator) {
- ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
- }
-
- progLoading = root.findViewById(R.id.progLoading);
- progLoading.setVisibility(View.VISIBLE);
-
- emptyView = new EmptyViewHandler(getContext());
- emptyView.attachToRecyclerView(recyclerView);
- emptyView.setIcon(R.attr.feed);
- emptyView.setTitle(R.string.no_all_episodes_head_label);
- emptyView.setMessage(R.string.no_all_episodes_label);
-
- createRecycleAdapter(recyclerView, emptyView);
- emptyView.hide();
+ View root = super.onCreateView(inflater, container, savedInstanceState);
- return root;
- }
+ recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
- private void onFragmentLoaded(List<FeedItem> episodes) {
- this.episodes = episodes;
- listAdapter.notifyDataSetChanged();
+ /* Total number of episodes after last load */
+ private int previousTotalEpisodes = 0;
- if (episodes.size() == 0) {
- createRecycleAdapter(recyclerView, emptyView);
- }
-
- restoreScrollPosition();
- requireActivity().invalidateOptionsMenu();
- }
+ /* True if loading more episodes is still in progress */
+ private boolean isLoadingMore = true;
- /**
- * Currently, we need to recreate the list adapter in order to be able to undo last item via the
- * snackbar. See #3084 for details.
- */
- private void createRecycleAdapter(RecyclerView recyclerView, EmptyViewHandler emptyViewHandler) {
- MainActivity mainActivity = (MainActivity) getActivity();
- listAdapter = new AllEpisodesRecycleAdapter(mainActivity, itemAccess, showOnlyNewEpisodes());
- listAdapter.setHasStableIds(true);
- recyclerView.setAdapter(listAdapter);
- emptyViewHandler.updateAdapter(listAdapter);
- }
-
- private final AllEpisodesRecycleAdapter.ItemAccess itemAccess = new AllEpisodesRecycleAdapter.ItemAccess() {
-
- @Override
- public int getCount() {
- return episodes.size();
- }
-
- @Override
- public FeedItem getItem(int position) {
- if (0 <= position && position < episodes.size()) {
- return episodes.get(position);
- }
- return null;
- }
-
- @Override
- public LongList getItemsIds() {
- LongList ids = new LongList(episodes.size());
- for (FeedItem episode : episodes) {
- ids.add(episode.getId());
- }
- return ids;
- }
-
- @Override
- public int getItemDownloadProgressPercent(FeedItem item) {
- for (Downloader downloader : downloaderList) {
- DownloadRequest downloadRequest = downloader.getDownloadRequest();
- if (downloadRequest.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA
- && downloadRequest.getFeedfileId() == item.getMedia().getId()) {
- return downloadRequest.getProgressPercent();
+ @Override
+ public void onScrolled(RecyclerView recyclerView, int deltaX, int deltaY) {
+ super.onScrolled(recyclerView, deltaX, deltaY);
+
+ int visibleEpisodeCount = recyclerView.getChildCount();
+ int totalEpisodeCount = recyclerView.getLayoutManager().getItemCount();
+ int firstVisibleEpisode = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition();
+
+ /* Determine if loading more episodes has finished */
+ if (isLoadingMore) {
+ if (totalEpisodeCount > previousTotalEpisodes) {
+ isLoadingMore = false;
+ previousTotalEpisodes = totalEpisodeCount;
+ }
}
- }
- return 0;
- }
- @Override
- public boolean isInQueue(FeedItem item) {
- return item != null && item.isTagged(FeedItem.TAG_QUEUE);
- }
+ /* Determine if the user scrolled to the bottom and loading more episodes is not already in progress */
+ if (!isLoadingMore && (totalEpisodeCount - visibleEpisodeCount)
+ <= (firstVisibleEpisode + VISIBLE_EPISODES_SCROLL_THRESHOLD)) {
- @Override
- public LongList getQueueIds() {
- LongList queueIds = new LongList();
- for (FeedItem item : episodes) {
- if (item.isTagged(FeedItem.TAG_QUEUE)) {
- queueIds.add(item.getId());
+ /* The end of the list has been reached. Load more data. */
+ page++;
+ loadMoreItems();
+ isLoadingMore = true;
}
}
- return queueIds;
- }
-
- };
+ });
- @Subscribe(threadMode = ThreadMode.MAIN)
- public void onEventMainThread(FeedItemEvent event) {
- Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
- for (FeedItem item : event.items) {
- int pos = FeedItemUtil.indexOfItemWithId(episodes, item.getId());
- if (pos >= 0) {
- episodes.remove(pos);
- if (shouldUpdatedItemRemainInList(item)) {
- episodes.add(pos, item);
- listAdapter.notifyItemChanged(pos);
- } else {
- listAdapter.notifyItemRemoved(pos);
- }
- }
- }
+ return root;
}
- protected boolean shouldUpdatedItemRemainInList(FeedItem item) {
- return true;
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ super.onCreateOptionsMenu(menu, inflater);
+ menu.findItem(R.id.filter_items).setVisible(true);
+ menu.findItem(R.id.mark_all_read_item).setVisible(!episodes.isEmpty());
}
- @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
- public void onEventMainThread(DownloadEvent event) {
- Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
- DownloaderUpdate update = event.update;
- downloaderList = update.downloaders;
- if (isMenuInvalidationAllowed && isUpdatingFeeds != update.feedIds.length > 0) {
- requireActivity().invalidateOptionsMenu();
- }
- if (update.mediaIds.length > 0) {
- for (long mediaId : update.mediaIds) {
- int pos = FeedItemUtil.indexOfItemWithMediaId(episodes, mediaId);
- if (pos >= 0) {
- listAdapter.notifyItemChanged(pos);
- }
- }
- }
- }
+ @Override
+ protected void onFragmentLoaded(List<FeedItem> episodes) {
+ super.onFragmentLoaded(episodes);
- private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
- @Override
- public void update(EventDistributor eventDistributor, Integer arg) {
- if ((arg & EVENTS) != 0) {
- loadItems();
- if (isUpdatingFeeds != updateRefreshMenuItemChecker.isRefreshing()) {
- requireActivity().invalidateOptionsMenu();
- }
- }
+ if (feedItemFilter.getValues().length > 0) {
+ txtvInformation.setText("{fa-info-circle} " + this.getString(R.string.filtered_label));
+ Iconify.addIcons(txtvInformation);
+ txtvInformation.setVisibility(View.VISIBLE);
+ } else {
+ txtvInformation.setVisibility(View.GONE);
}
- };
+ }
- void loadItems() {
+ private void loadMoreItems() {
if (disposable != null) {
disposable.dispose();
}
- disposable = Observable.fromCallable(this::loadData)
+ disposable = Observable.fromCallable(this::loadMoreData)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(data -> {
progLoading.setVisibility(View.GONE);
- onFragmentLoaded(data);
+ episodes.addAll(data);
+ onFragmentLoaded(episodes);
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
- @NonNull
- List<FeedItem> loadData() {
- return DBReader.getRecentlyPublishedEpisodes(RECENT_EPISODES_LIMIT);
- }
-
- void removeNewFlagWithUndo(FeedItem item) {
- if (item == null) {
- return;
- }
-
- Log.d(TAG, "removeNewFlagWithUndo(" + item.getId() + ")");
- if (disposable != null) {
- disposable.dispose();
- }
- // we're marking it as unplayed since the user didn't actually play it
- // but they don't want it considered 'NEW' anymore
- DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId());
-
- final Handler h = new Handler(getActivity().getMainLooper());
- final Runnable r = () -> {
- FeedMedia media = item.getMedia();
- if (media != null && media.hasAlmostEnded() && UserPreferences.isAutoDelete()) {
- DBWriter.deleteFeedMediaOfItem(getActivity(), media.getId());
+ private void showFilterDialog() {
+ FilterDialog filterDialog = new FilterDialog(getContext(), feedItemFilter) {
+ @Override
+ protected void updateFilter(Set<String> filterValues) {
+ feedItemFilter = new FeedItemFilter(filterValues.toArray(new String[filterValues.size()]));
+ loadItems();
}
};
- Snackbar snackbar = Snackbar.make(getView(), getString(R.string.removed_new_flag_label),
- Snackbar.LENGTH_LONG);
- snackbar.setAction(getString(R.string.undo), v -> {
- DBWriter.markItemPlayed(FeedItem.NEW, item.getId());
- // don't forget to cancel the thing that's going to remove the media
- h.removeCallbacks(r);
- });
- snackbar.show();
- h.postDelayed(r, (int) Math.ceil(snackbar.getDuration() * 1.05f));
+ filterDialog.openDialog();
+ }
+
+ @NonNull
+ @Override
+ protected List<FeedItem> loadData() {
+ return feedItemFilter.filter( DBReader.getRecentlyPublishedEpisodes(0, page * EPISODES_PER_PAGE));
+ }
+
+ List<FeedItem> loadMoreData() {
+ return feedItemFilter.filter( DBReader.getRecentlyPublishedEpisodes((page - 1) * EPISODES_PER_PAGE, EPISODES_PER_PAGE));
}
}
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 4bebfe4c9..bb8f4df9a 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java
@@ -87,11 +87,10 @@ public class ChaptersFragment extends ListFragment {
controller = null;
}
- private void scrollTo(int position) {
- getListView().setSelection(position);
- }
-
private int getCurrentChapter(Playable media) {
+ if (media == null || media.getChapters() == null || media.getChapters().size() == 0 || controller == null) {
+ return -1;
+ }
int currentPosition = controller.getPosition();
List<Chapter> chapters = media.getChapters();
@@ -126,8 +125,10 @@ public class ChaptersFragment extends ListFragment {
if (adapter != null) {
adapter.setMedia(media);
adapter.notifyDataSetChanged();
- if (media != null && media.getChapters() != null && media.getChapters().size() != 0) {
- scrollTo(getCurrentChapter(media));
+
+ int positionOfCurrentChapter = getCurrentChapter(media);
+ if (positionOfCurrentChapter != -1) {
+ getListView().setSelection(positionOfCurrentChapter);
}
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java
index 0610bfd24..ca21df661 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java
@@ -79,7 +79,7 @@ public class EpisodesFragment extends Fragment {
public static class EpisodesPagerAdapter extends FragmentPagerAdapter {
private final Resources resources;
- private final AllEpisodesFragment[] fragments = {
+ private final EpisodesListFragment[] fragments = {
new NewEpisodesFragment(),
new AllEpisodesFragment(),
new FavoriteEpisodesFragment()
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java
new file mode 100644
index 000000000..b6e3d14dd
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java
@@ -0,0 +1,445 @@
+package de.danoeh.antennapod.fragment;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.Fragment;
+import android.support.v4.view.MenuItemCompat;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.SearchView;
+import android.support.v7.widget.SimpleItemAnimator;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
+
+import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.activity.MainActivity;
+import de.danoeh.antennapod.adapter.AllEpisodesRecycleAdapter;
+import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
+import de.danoeh.antennapod.core.event.DownloadEvent;
+import de.danoeh.antennapod.core.event.DownloaderUpdate;
+import de.danoeh.antennapod.core.event.FeedItemEvent;
+import de.danoeh.antennapod.core.feed.EventDistributor;
+import de.danoeh.antennapod.core.feed.FeedItem;
+import de.danoeh.antennapod.core.feed.FeedMedia;
+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.DBWriter;
+import de.danoeh.antennapod.core.storage.DownloadRequester;
+import de.danoeh.antennapod.core.util.FeedItemUtil;
+import de.danoeh.antennapod.core.util.LongList;
+import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
+import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
+import de.danoeh.antennapod.menuhandler.MenuItemUtils;
+import de.danoeh.antennapod.view.EmptyViewHandler;
+import io.reactivex.Observable;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.schedulers.Schedulers;
+
+/**
+ * Shows unread or recently published episodes
+ */
+public abstract class EpisodesListFragment extends Fragment {
+
+ public static final String TAG = "EpisodesListFragment";
+
+ private static final int EVENTS = EventDistributor.FEED_LIST_UPDATE |
+ EventDistributor.UNREAD_ITEMS_UPDATE |
+ EventDistributor.PLAYER_STATUS_UPDATE;
+
+ private static final String DEFAULT_PREF_NAME = "PrefAllEpisodesFragment";
+ private static final String PREF_SCROLL_POSITION = "scroll_position";
+ private static final String PREF_SCROLL_OFFSET = "scroll_offset";
+
+ RecyclerView recyclerView;
+ AllEpisodesRecycleAdapter listAdapter;
+ ProgressBar progLoading;
+ EmptyViewHandler emptyView;
+
+ @NonNull
+ List<FeedItem> episodes = new ArrayList<>();
+ @NonNull
+ private List<Downloader> downloaderList = new ArrayList<>();
+
+ private boolean isUpdatingFeeds;
+ boolean isMenuInvalidationAllowed = false;
+
+ protected Disposable disposable;
+ private LinearLayoutManager layoutManager;
+ protected TextView txtvInformation;
+
+ boolean showOnlyNewEpisodes() {
+ return false;
+ }
+
+ String getPrefName() {
+ return DEFAULT_PREF_NAME;
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ setHasOptionsMenu(true);
+ EventDistributor.getInstance().register(contentUpdate);
+ EventBus.getDefault().register(this);
+ loadItems();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ registerForContextMenu(recyclerView);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ saveScrollPosition();
+ unregisterForContextMenu(recyclerView);
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ EventBus.getDefault().unregister(this);
+ EventDistributor.getInstance().unregister(contentUpdate);
+ if (disposable != null) {
+ disposable.dispose();
+ }
+ }
+
+ private void saveScrollPosition() {
+ int firstItem = layoutManager.findFirstVisibleItemPosition();
+ View firstItemView = layoutManager.findViewByPosition(firstItem);
+ float topOffset;
+ if (firstItemView == null) {
+ topOffset = 0;
+ } else {
+ topOffset = firstItemView.getTop();
+ }
+
+ SharedPreferences prefs = getActivity().getSharedPreferences(getPrefName(), Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putInt(PREF_SCROLL_POSITION, firstItem);
+ editor.putFloat(PREF_SCROLL_OFFSET, topOffset);
+ editor.apply();
+ }
+
+ private void restoreScrollPosition() {
+ SharedPreferences prefs = getActivity().getSharedPreferences(getPrefName(), Context.MODE_PRIVATE);
+ int position = prefs.getInt(PREF_SCROLL_POSITION, 0);
+ float offset = prefs.getFloat(PREF_SCROLL_OFFSET, 0.0f);
+ if (position > 0 || offset > 0) {
+ layoutManager.scrollToPositionWithOffset(position, (int) offset);
+ // restore once, then forget
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putInt(PREF_SCROLL_POSITION, 0);
+ editor.putFloat(PREF_SCROLL_OFFSET, 0.0f);
+ editor.apply();
+ }
+ }
+
+ private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker =
+ () -> DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds();
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ if (!isAdded()) {
+ return;
+ }
+ super.onCreateOptionsMenu(menu, inflater);
+ inflater.inflate(R.menu.episodes, menu);
+
+ MenuItem searchItem = menu.findItem(R.id.action_search);
+ final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
+ MenuItemUtils.adjustTextColor(getActivity(), sv);
+ sv.setQueryHint(getString(R.string.search_hint));
+ sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+ @Override
+ public boolean onQueryTextSubmit(String s) {
+ sv.clearFocus();
+ ((MainActivity) requireActivity()).loadChildFragment(SearchFragment.newInstance(s));
+ return true;
+ }
+
+ @Override
+ public boolean onQueryTextChange(String s) {
+ return false;
+ }
+ });
+ isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (!super.onOptionsItemSelected(item)) {
+ switch (item.getItemId()) {
+ case R.id.refresh_item:
+ AutoUpdateManager.runImmediate(requireContext());
+ return true;
+ case R.id.mark_all_read_item:
+ ConfirmationDialog markAllReadConfirmationDialog = new ConfirmationDialog(getActivity(),
+ R.string.mark_all_read_label,
+ R.string.mark_all_read_confirmation_msg) {
+
+ @Override
+ public void onConfirmButtonPressed(DialogInterface dialog) {
+ dialog.dismiss();
+ DBWriter.markAllItemsRead();
+ Toast.makeText(getActivity(), R.string.mark_all_read_msg, Toast.LENGTH_SHORT).show();
+ }
+ };
+ markAllReadConfirmationDialog.createNewDialog().show();
+ return true;
+ case R.id.remove_all_new_flags_item:
+ ConfirmationDialog removeAllNewFlagsConfirmationDialog = new ConfirmationDialog(getActivity(),
+ R.string.remove_all_new_flags_label,
+ R.string.remove_all_new_flags_confirmation_msg) {
+
+ @Override
+ public void onConfirmButtonPressed(DialogInterface dialog) {
+ dialog.dismiss();
+ DBWriter.removeAllNewFlags();
+ Toast.makeText(getActivity(), R.string.removed_all_new_flags_msg, Toast.LENGTH_SHORT).show();
+ }
+ };
+ removeAllNewFlagsConfirmationDialog.createNewDialog().show();
+ return true;
+ default:
+ return false;
+ }
+ } else {
+ return true;
+ }
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ Log.d(TAG, "onContextItemSelected() called with: " + "item = [" + item + "]");
+ if (!getUserVisibleHint()) {
+ return false;
+ }
+ if (!isVisible()) {
+ return false;
+ }
+ if (item.getItemId() == R.id.share_item) {
+ return true; // avoids that the position is reset when we need it in the submenu
+ }
+
+ if (listAdapter.getSelectedItem() == null) {
+ Log.i(TAG, "Selected item or listAdapter was null, ignoring selection");
+ return super.onContextItemSelected(item);
+ }
+ FeedItem selectedItem = listAdapter.getSelectedItem();
+
+ return FeedItemMenuHandler.onMenuItemClicked(this, item.getItemId(), selectedItem);
+ }
+
+ @NonNull
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ super.onCreateView(inflater, container, savedInstanceState);
+ View root = inflater.inflate(R.layout.all_episodes_fragment, container, false);
+ txtvInformation = root.findViewById(R.id.txtvInformation);
+
+ layoutManager = new LinearLayoutManager(getActivity());
+ recyclerView = root.findViewById(android.R.id.list);
+ recyclerView.setLayoutManager(layoutManager);
+ recyclerView.setHasFixedSize(true);
+ recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getActivity()).build());
+ recyclerView.setVisibility(View.GONE);
+
+ RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator();
+ if (animator instanceof SimpleItemAnimator) {
+ ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
+ }
+
+ progLoading = root.findViewById(R.id.progLoading);
+ progLoading.setVisibility(View.VISIBLE);
+
+ emptyView = new EmptyViewHandler(getContext());
+ emptyView.attachToRecyclerView(recyclerView);
+ emptyView.setIcon(R.attr.feed);
+ emptyView.setTitle(R.string.no_all_episodes_head_label);
+ emptyView.setMessage(R.string.no_all_episodes_label);
+
+ createRecycleAdapter(recyclerView, emptyView);
+ emptyView.hide();
+
+ return root;
+ }
+
+ protected void onFragmentLoaded(List<FeedItem> episodes) {
+ listAdapter.notifyDataSetChanged();
+
+ if (episodes.size() == 0) {
+ createRecycleAdapter(recyclerView, emptyView);
+ }
+
+ restoreScrollPosition();
+ requireActivity().invalidateOptionsMenu();
+ }
+
+ /**
+ * Currently, we need to recreate the list adapter in order to be able to undo last item via the
+ * snackbar. See #3084 for details.
+ */
+ private void createRecycleAdapter(RecyclerView recyclerView, EmptyViewHandler emptyViewHandler) {
+ MainActivity mainActivity = (MainActivity) getActivity();
+ listAdapter = new AllEpisodesRecycleAdapter(mainActivity, itemAccess, showOnlyNewEpisodes());
+ listAdapter.setHasStableIds(true);
+ recyclerView.setAdapter(listAdapter);
+ emptyViewHandler.updateAdapter(listAdapter);
+ }
+
+ private final AllEpisodesRecycleAdapter.ItemAccess itemAccess = new AllEpisodesRecycleAdapter.ItemAccess() {
+
+ @Override
+ public int getCount() {
+ return episodes.size();
+ }
+
+ @Override
+ public FeedItem getItem(int position) {
+ if (0 <= position && position < episodes.size()) {
+ return episodes.get(position);
+ }
+ return null;
+ }
+
+ @Override
+ public LongList getItemsIds() {
+ LongList ids = new LongList(episodes.size());
+ for (FeedItem episode : episodes) {
+ ids.add(episode.getId());
+ }
+ return ids;
+ }
+
+ @Override
+ public int getItemDownloadProgressPercent(FeedItem item) {
+ for (Downloader downloader : downloaderList) {
+ DownloadRequest downloadRequest = downloader.getDownloadRequest();
+ if (downloadRequest.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA
+ && downloadRequest.getFeedfileId() == item.getMedia().getId()) {
+ return downloadRequest.getProgressPercent();
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean isInQueue(FeedItem item) {
+ return item != null && item.isTagged(FeedItem.TAG_QUEUE);
+ }
+
+ @Override
+ public LongList getQueueIds() {
+ LongList queueIds = new LongList();
+ for (FeedItem item : episodes) {
+ if (item.isTagged(FeedItem.TAG_QUEUE)) {
+ queueIds.add(item.getId());
+ }
+ }
+ return queueIds;
+ }
+
+ };
+
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ public void onEventMainThread(FeedItemEvent event) {
+ Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
+ for (FeedItem item : event.items) {
+ int pos = FeedItemUtil.indexOfItemWithId(episodes, item.getId());
+ if (pos >= 0) {
+ episodes.remove(pos);
+ if (shouldUpdatedItemRemainInList(item)) {
+ episodes.add(pos, item);
+ listAdapter.notifyItemChanged(pos);
+ } else {
+ listAdapter.notifyItemRemoved(pos);
+ }
+ }
+ }
+ }
+
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ public void onEventMainThread(PlaybackPositionEvent event) {
+ if (listAdapter != null) {
+ listAdapter.notifyCurrentlyPlayingItemChanged(event);
+ }
+ }
+
+ protected boolean shouldUpdatedItemRemainInList(FeedItem item) {
+ return true;
+ }
+
+ @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
+ public void onEventMainThread(DownloadEvent event) {
+ Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
+ DownloaderUpdate update = event.update;
+ downloaderList = update.downloaders;
+ if (isMenuInvalidationAllowed && event.hasChangedFeedUpdateStatus(isUpdatingFeeds)) {
+ requireActivity().invalidateOptionsMenu();
+ }
+ if (update.mediaIds.length > 0) {
+ for (long mediaId : update.mediaIds) {
+ int pos = FeedItemUtil.indexOfItemWithMediaId(episodes, mediaId);
+ if (pos >= 0) {
+ listAdapter.notifyItemChanged(pos);
+ }
+ }
+ }
+ }
+
+ private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
+ @Override
+ public void update(EventDistributor eventDistributor, Integer arg) {
+ if ((arg & EVENTS) != 0) {
+ loadItems();
+ if (isUpdatingFeeds != updateRefreshMenuItemChecker.isRefreshing()) {
+ requireActivity().invalidateOptionsMenu();
+ }
+ }
+ }
+ };
+
+ void loadItems() {
+ if (disposable != null) {
+ disposable.dispose();
+ }
+ disposable = Observable.fromCallable(this::loadData)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(data -> {
+ progLoading.setVisibility(View.GONE);
+ episodes = data;
+ onFragmentLoaded(episodes);
+ }, error -> Log.e(TAG, Log.getStackTraceString(error)));
+ }
+
+ @NonNull
+ protected abstract List<FeedItem> loadData();
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
index 348c73b92..9f136490a 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
@@ -18,7 +18,7 @@ import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.core.event.ServiceEvent;
+import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import de.danoeh.antennapod.core.feed.MediaType;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
@@ -28,6 +28,9 @@ 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;
/**
* Fragment which is supposed to be displayed outside of the MediaplayerActivity
@@ -138,6 +141,7 @@ public class ExternalPlayerFragment extends Fragment {
controller = setupPlaybackController();
controller.init();
loadMediaInfo();
+ EventBus.getDefault().register(this);
}
@Override
@@ -147,6 +151,12 @@ public class ExternalPlayerFragment extends Fragment {
controller.release();
controller = null;
}
+ EventBus.getDefault().unregister(this);
+ }
+
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ public void onEventMainThread(PlaybackPositionEvent event) {
+ onPositionObserverUpdate();
}
@Override
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 bb029b731..536ebd468 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java
@@ -7,6 +7,7 @@ import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.view.LayoutInflater;
+import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
@@ -25,7 +26,7 @@ import de.danoeh.antennapod.core.storage.DBWriter;
* Like 'EpisodesFragment' except that it only shows favorite episodes and
* supports swiping to remove from favorites.
*/
-public class FavoriteEpisodesFragment extends AllEpisodesFragment {
+public class FavoriteEpisodesFragment extends EpisodesListFragment {
private static final String TAG = "FavoriteEpisodesFrag";
private static final String PREF_NAME = "PrefFavoriteEpisodesFragment";
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java
index 0c75af986..8fe0883b2 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java
@@ -29,6 +29,7 @@ import com.bumptech.glide.request.RequestOptions;
import com.joanzapata.iconify.Iconify;
import com.joanzapata.iconify.widget.IconTextView;
+import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import org.apache.commons.lang3.Validate;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -79,7 +80,7 @@ import io.reactivex.schedulers.Schedulers;
* Displays a list of FeedItems.
*/
@SuppressLint("ValidFragment")
-public class ItemlistFragment extends ListFragment {
+public class FeedItemlistFragment extends ListFragment {
private static final String TAG = "ItemlistFragment";
private static final int EVENTS = EventDistributor.UNREAD_ITEMS_UPDATE
@@ -120,8 +121,8 @@ public class ItemlistFragment extends ListFragment {
* @param feedId The id of the feed to show
* @return the newly created instance of an ItemlistFragment
*/
- public static ItemlistFragment newInstance(long feedId) {
- ItemlistFragment i = new ItemlistFragment();
+ public static FeedItemlistFragment newInstance(long feedId) {
+ FeedItemlistFragment i = new FeedItemlistFragment();
Bundle b = new Bundle();
b.putLong(ARGUMENT_FEED_ID, feedId);
i.setArguments(b);
@@ -195,6 +196,21 @@ public class ItemlistFragment extends ListFragment {
final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
MenuItemUtils.adjustTextColor(getActivity(), sv);
sv.setQueryHint(getString(R.string.search_hint));
+ searchItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
+ @Override
+ public boolean onMenuItemActionExpand(MenuItem item) {
+ menu.findItem(R.id.filter_items).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+ menu.findItem(R.id.episode_actions).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+ menu.findItem(R.id.refresh_item).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+ return true;
+ }
+
+ @Override
+ public boolean onMenuItemActionCollapse(MenuItem item) {
+ getActivity().invalidateOptionsMenu();
+ return true;
+ }
+ });
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String s) {
@@ -308,7 +324,7 @@ public class ItemlistFragment extends ListFragment {
contextMenu = menu;
lastMenuInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
- FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item, true, null);
+ FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item);
}
@Override
@@ -325,7 +341,7 @@ public class ItemlistFragment extends ListFragment {
return super.onContextItemSelected(item);
}
- return FeedItemMenuHandler.onMenuItemClicked(getActivity(), item.getItemId(), selectedItem);
+ return FeedItemMenuHandler.onMenuItemClicked(this, item.getItemId(), selectedItem);
}
@Override
@@ -375,14 +391,21 @@ public class ItemlistFragment extends ListFragment {
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
DownloaderUpdate update = event.update;
downloaderList = update.downloaders;
- if (isUpdatingFeed != event.update.feedIds.length > 0) {
+ if (event.hasChangedFeedUpdateStatus(isUpdatingFeed)) {
updateProgressBarVisibility();
}
- if(adapter != null && update.mediaIds.length > 0) {
+ if (adapter != null && update.mediaIds.length > 0) {
adapter.notifyDataSetChanged();
}
}
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ public void onEventMainThread(PlaybackPositionEvent event) {
+ if (adapter != null) {
+ adapter.notifyCurrentlyPlayingItemChanged(event, getListView());
+ }
+ }
+
private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@Override
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
index 5cf2c5eeb..bfca90b2a 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
@@ -96,13 +96,7 @@ public class ItemDescriptionFragment extends Fragment {
if (Timeline.isTimecodeLink(url)) {
onTimecodeLinkSelected(url);
} else {
- Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
- try {
- startActivity(intent);
- } catch (ActivityNotFoundException e) {
- e.printStackTrace();
- return true;
- }
+ IntentUtils.openInBrowser(getContext(), url);
}
return true;
}
@@ -159,11 +153,7 @@ public class ItemDescriptionFragment extends Fragment {
if (selectedURL != null) {
switch (item.getItemId()) {
case R.id.open_in_browser_item:
- Uri uri = Uri.parse(selectedURL);
- final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- if(IntentUtils.isCallable(getActivity(), intent)) {
- getActivity().startActivity(intent);
- }
+ IntentUtils.openInBrowser(getContext(), selectedURL);
break;
case R.id.share_url_item:
ShareUtils.shareLink(getActivity(), selectedURL);
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 432ada44e..9395b0994 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
@@ -55,7 +55,6 @@ import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.Downloader;
-import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DBWriter;
@@ -211,10 +210,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
webvDescription.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
- Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
- if(IntentUtils.isCallable(getActivity(), intent)) {
- startActivity(intent);
- }
+ IntentUtils.openInBrowser(getContext(), url);
return true;
}
});
@@ -336,10 +332,10 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
inflater.inflate(R.menu.feeditem_options, menu);
popupMenu = menu;
if (item.hasMedia()) {
- FeedItemMenuHandler.onPrepareMenu(popupMenuInterface, item, true, null);
+ FeedItemMenuHandler.onPrepareMenu(popupMenuInterface, item);
} else {
// these are already available via button1 and button2
- FeedItemMenuHandler.onPrepareMenu(popupMenuInterface, item, true, null,
+ FeedItemMenuHandler.onPrepareMenu(popupMenuInterface, item,
R.id.mark_read_item, R.id.visit_website_item);
}
}
@@ -351,7 +347,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
openPodcast();
return true;
default:
- return FeedItemMenuHandler.onMenuItemClicked(getActivity(), menuItem.getItemId(), item);
+ return FeedItemMenuHandler.onMenuItemClicked(this, menuItem.getItemId(), item);
}
}
@@ -446,15 +442,6 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
}
}
- FeedItem.State state = item.getState();
- if (butAction2Text == R.string.delete_label && state == FeedItem.State.PLAYING && PlaybackService.isRunning) {
- butAction2.setEnabled(false);
- butAction2.setAlpha(0.5f);
- } else {
- butAction2.setEnabled(true);
- butAction2.setAlpha(1.0f);
- }
-
if(butAction1Icon != null && butAction1Text != 0) {
butAction1.setText(butAction1Icon +"\u0020\u0020" + getActivity().getString(butAction1Text));
Iconify.addIcons(butAction1);
@@ -494,11 +481,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
if (selectedURL != null) {
switch (item.getItemId()) {
case R.id.open_in_browser_item:
- Uri uri = Uri.parse(selectedURL);
- final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- if(IntentUtils.isCallable(getActivity(), intent)) {
- getActivity().startActivity(intent);
- }
+ IntentUtils.openInBrowser(getContext(), selectedURL);
break;
case R.id.share_url_item:
ShareUtils.shareLink(getActivity(), selectedURL);
@@ -543,7 +526,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
}
private void openPodcast() {
- Fragment fragment = ItemlistFragment.newInstance(item.getFeedId());
+ Fragment fragment = FeedItemlistFragment.newInstance(item.getFeedId());
((MainActivity)getActivity()).loadChildFragment(fragment);
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java
index 1bf907aee..07667118d 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java
@@ -5,6 +5,7 @@ import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.LayoutInflater;
+import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
@@ -14,12 +15,13 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.AllEpisodesRecycleAdapter;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.storage.DBReader;
+import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
/**
* Like 'EpisodesFragment' except that it only shows new episodes and
* supports swiping to mark as read.
*/
-public class NewEpisodesFragment extends AllEpisodesFragment {
+public class NewEpisodesFragment extends EpisodesListFragment {
public static final String TAG = "NewEpisodesFragment";
private static final String PREF_NAME = "PrefNewEpisodesFragment";
@@ -39,6 +41,12 @@ public class NewEpisodesFragment extends AllEpisodesFragment {
return item.isNew();
}
+ @Override
+ public void onPrepareOptionsMenu(Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+ menu.findItem(R.id.remove_all_new_flags_item).setVisible(!episodes.isEmpty());
+ }
+
@NonNull
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@@ -55,7 +63,7 @@ public class NewEpisodesFragment extends AllEpisodesFragment {
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
AllEpisodesRecycleAdapter.Holder holder = (AllEpisodesRecycleAdapter.Holder) viewHolder;
- removeNewFlagWithUndo(holder.getFeedItem());
+ FeedItemMenuHandler.removeNewFlagWithUndo(NewEpisodesFragment.this, holder.getFeedItem());
}
@Override
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 0fe413954..ff1e9a28e 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
@@ -7,6 +7,7 @@ import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.view.MenuItemCompat;
+import android.support.v7.app.AlertDialog;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SearchView;
@@ -19,11 +20,17 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.CheckBox;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
+import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
import java.util.List;
import de.danoeh.antennapod.R;
@@ -35,14 +42,12 @@ import de.danoeh.antennapod.core.event.DownloaderUpdate;
import de.danoeh.antennapod.core.event.FeedItemEvent;
import de.danoeh.antennapod.core.event.QueueEvent;
import de.danoeh.antennapod.core.feed.EventDistributor;
-import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadService;
import de.danoeh.antennapod.core.service.download.Downloader;
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.DownloadRequester;
import de.danoeh.antennapod.core.util.Converter;
@@ -50,18 +55,15 @@ import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.QueueSorter;
import de.danoeh.antennapod.core.util.SortOrder;
+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 io.reactivex.Observable;
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 static de.danoeh.antennapod.dialog.EpisodesApplyActionFragment.ACTION_DELETE;
import static de.danoeh.antennapod.dialog.EpisodesApplyActionFragment.ACTION_REMOVE_FROM_QUEUE;
@@ -91,10 +93,12 @@ public class QueueFragment extends Fragment {
private static final String PREFS = "QueueFragment";
private static final String PREF_SCROLL_POSITION = "scroll_position";
private static final String PREF_SCROLL_OFFSET = "scroll_offset";
+ private static final String PREF_SHOW_LOCK_WARNING = "show_lock_warning";
private Disposable disposable;
private LinearLayoutManager layoutManager;
private ItemTouchHelper itemTouchHelper;
+ private SharedPreferences prefs;
@Override
@@ -102,6 +106,7 @@ public class QueueFragment extends Fragment {
super.onCreate(savedInstanceState);
setRetainInstance(true);
setHasOptionsMenu(true);
+ prefs = getActivity().getSharedPreferences(PREFS, Context.MODE_PRIVATE);
}
@Override
@@ -196,8 +201,8 @@ public class QueueFragment extends Fragment {
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
DownloaderUpdate update = event.update;
downloaderList = update.downloaders;
- if (isUpdatingFeeds != update.feedIds.length > 0) {
- getActivity().supportInvalidateOptionsMenu();
+ if (event.hasChangedFeedUpdateStatus(isUpdatingFeeds)) {
+ getActivity().invalidateOptionsMenu();
}
if (recyclerAdapter != null && update.mediaIds.length > 0) {
for (long mediaId : update.mediaIds) {
@@ -209,6 +214,13 @@ public class QueueFragment extends Fragment {
}
}
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ public void onEventMainThread(PlaybackPositionEvent event) {
+ if (recyclerAdapter != null) {
+ recyclerAdapter.notifyCurrentlyPlayingItemChanged(event);
+ }
+ }
+
private void saveScrollPosition() {
int firstItem = layoutManager.findFirstVisibleItemPosition();
View firstItemView = layoutManager.findViewByPosition(firstItem);
@@ -219,15 +231,13 @@ public class QueueFragment extends Fragment {
topOffset = firstItemView.getTop();
}
- SharedPreferences prefs = getActivity().getSharedPreferences(PREFS, Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putInt(PREF_SCROLL_POSITION, firstItem);
- editor.putFloat(PREF_SCROLL_OFFSET, topOffset);
- editor.commit();
+ prefs.edit()
+ .putInt(PREF_SCROLL_POSITION, firstItem)
+ .putFloat(PREF_SCROLL_OFFSET, topOffset)
+ .apply();
}
private void restoreScrollPosition() {
- SharedPreferences prefs = getActivity().getSharedPreferences(PREFS, Context.MODE_PRIVATE);
int position = prefs.getInt(PREF_SCROLL_POSITION, 0);
float offset = prefs.getFloat(PREF_SCROLL_OFFSET, 0.0f);
if (position > 0 || offset > 0) {
@@ -299,25 +309,10 @@ public class QueueFragment extends Fragment {
if (!super.onOptionsItemSelected(item)) {
switch (item.getItemId()) {
case R.id.queue_lock:
- boolean newLockState = !UserPreferences.isQueueLocked();
- UserPreferences.setQueueLocked(newLockState);
- getActivity().supportInvalidateOptionsMenu();
- if (recyclerAdapter != null) {
- recyclerAdapter.setLocked(newLockState);
- }
- if (newLockState) {
- Snackbar.make(getActivity().findViewById(R.id.content), R.string
- .queue_locked, Snackbar.LENGTH_SHORT).show();
- } else {
- Snackbar.make(getActivity().findViewById(R.id.content), R.string
- .queue_unlocked, Snackbar.LENGTH_SHORT).show();
- }
+ toggleQueueLock();
return true;
case R.id.refresh_item:
- List<Feed> feeds = ((MainActivity) getActivity()).getFeeds();
- if (feeds != null) {
- DBTasks.refreshAllFeeds(getActivity(), feeds);
- }
+ AutoUpdateManager.runImmediate(requireContext());
return true;
case R.id.clear_queue:
// make sure the user really wants to clear the queue
@@ -378,8 +373,10 @@ public class QueueFragment extends Fragment {
if (keepSortedNew) {
SortOrder sortOrder = UserPreferences.getQueueKeepSortedOrder();
QueueSorter.sort(sortOrder, true);
- recyclerAdapter.setLocked(true);
- } else {
+ if (recyclerAdapter != null) {
+ recyclerAdapter.setLocked(true);
+ }
+ } else if (recyclerAdapter != null) {
recyclerAdapter.setLocked(UserPreferences.isQueueLocked());
}
getActivity().invalidateOptionsMenu();
@@ -392,6 +389,48 @@ public class QueueFragment extends Fragment {
}
}
+ private void toggleQueueLock() {
+ boolean isLocked = UserPreferences.isQueueLocked();
+ if (isLocked) {
+ setQueueLocked(false);
+ } else {
+ boolean shouldShowLockWarning = prefs.getBoolean(PREF_SHOW_LOCK_WARNING, true);
+ if (!shouldShowLockWarning) {
+ setQueueLocked(true);
+ } else {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+ builder.setTitle(R.string.lock_queue);
+ builder.setMessage(R.string.queue_lock_warning);
+
+ View view = View.inflate(getContext(), R.layout.checkbox_do_not_show_again, null);
+ CheckBox checkDoNotShowAgain = view.findViewById(R.id.checkbox_do_not_show_again);
+ builder.setView(view);
+
+ builder.setPositiveButton(R.string.lock_queue, (dialog, which) -> {
+ prefs.edit().putBoolean(PREF_SHOW_LOCK_WARNING, !checkDoNotShowAgain.isChecked()).apply();
+ setQueueLocked(true);
+ });
+ builder.setNegativeButton(R.string.cancel_label, null);
+ builder.show();
+ }
+ }
+ }
+
+ private void setQueueLocked(boolean locked) {
+ UserPreferences.setQueueLocked(locked);
+ getActivity().supportInvalidateOptionsMenu();
+ if (recyclerAdapter != null) {
+ recyclerAdapter.setLocked(locked);
+ }
+ if (locked) {
+ Snackbar.make(getActivity().findViewById(R.id.content), R.string
+ .queue_locked, Snackbar.LENGTH_SHORT).show();
+ } else {
+ Snackbar.make(getActivity().findViewById(R.id.content), R.string
+ .queue_unlocked, Snackbar.LENGTH_SHORT).show();
+ }
+ }
+
/**
* This method is called if the user clicks on a sort order menu item.
*
@@ -428,7 +467,7 @@ public class QueueFragment extends Fragment {
DBWriter.moveQueueItemToBottom(selectedItem.getId(), true);
return true;
default:
- return FeedItemMenuHandler.onMenuItemClicked(getActivity(), item.getItemId(), selectedItem);
+ return FeedItemMenuHandler.onMenuItemClicked(this, item.getItemId(), selectedItem);
}
}
@@ -503,7 +542,7 @@ public class QueueFragment extends Fragment {
@Override
public boolean isLongPressDragEnabled() {
- return !UserPreferences.isQueueLocked();
+ return false;
}
@Override
@@ -596,7 +635,7 @@ public class QueueFragment extends Fragment {
String info = queue.size() + getString(R.string.episodes_suffix);
if(queue.size() > 0) {
long timeLeft = 0;
- float playbackSpeed = Float.valueOf(UserPreferences.getPlaybackSpeed());
+ float playbackSpeed = UserPreferences.getPlaybackSpeed();
for(FeedItem item : queue) {
if(item.getMedia() != null) {
timeLeft +=
@@ -604,7 +643,7 @@ public class QueueFragment extends Fragment {
/ playbackSpeed);
}
}
- info += " \u2022 ";
+ info += " • ";
info += getString(R.string.time_left_label);
info += Converter.getDurationStringLocalized(getActivity(), timeLeft);
}
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 15c6052a9..ed315050b 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java
@@ -25,19 +25,28 @@ import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.SubscriptionsAdapter;
import de.danoeh.antennapod.core.asynctask.FeedRemover;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
+import de.danoeh.antennapod.core.event.DownloadEvent;
+import de.danoeh.antennapod.core.event.DownloaderUpdate;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
+import de.danoeh.antennapod.core.service.download.DownloadService;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
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.FeedItemUtil;
import de.danoeh.antennapod.core.util.IntentUtils;
+import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
import de.danoeh.antennapod.dialog.RenameFeedDialog;
+import de.danoeh.antennapod.menuhandler.MenuItemUtils;
import io.reactivex.Observable;
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;
/**
* Fragment for displaying feed subscriptions
@@ -56,6 +65,7 @@ public class SubscriptionFragment extends Fragment {
private SubscriptionsAdapter subscriptionAdapter;
private int mPosition = -1;
+ private boolean isUpdatingFeeds = false;
private Disposable disposable;
private SharedPreferences prefs;
@@ -89,6 +99,8 @@ public class SubscriptionFragment extends Fragment {
menu.findItem(R.id.subscription_num_columns_3).setChecked(columns == 3);
menu.findItem(R.id.subscription_num_columns_4).setChecked(columns == 4);
menu.findItem(R.id.subscription_num_columns_5).setChecked(columns == 5);
+
+ isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker);
}
@Override
@@ -97,6 +109,9 @@ public class SubscriptionFragment extends Fragment {
return true;
}
switch (item.getItemId()) {
+ case R.id.refresh_item:
+ AutoUpdateManager.runImmediate(requireContext());
+ return true;
case R.id.subscription_num_columns_2:
setColumnNumber(2);
return true;
@@ -136,6 +151,7 @@ public class SubscriptionFragment extends Fragment {
public void onStart() {
super.onStart();
EventDistributor.getInstance().register(contentUpdate);
+ EventBus.getDefault().register(this);
loadSubscriptions();
}
@@ -143,6 +159,7 @@ public class SubscriptionFragment extends Fragment {
public void onStop() {
super.onStop();
EventDistributor.getInstance().unregister(contentUpdate);
+ EventBus.getDefault().unregister(this);
if(disposable != null) {
disposable.dispose();
}
@@ -278,6 +295,17 @@ public class SubscriptionFragment extends Fragment {
}
};
+ @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 final SubscriptionsAdapter.ItemAccess itemAccess = new SubscriptionsAdapter.ItemAccess() {
@Override
public int getCount() {
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 a04615a00..d0c209326 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,29 +1,41 @@
package de.danoeh.antennapod.fragment.preferences;
+import android.Manifest;
import android.app.Activity;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
+import android.os.Build;
import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.content.ContextCompat;
import android.support.v7.preference.CheckBoxPreference;
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceFragmentCompat;
import android.support.v7.preference.PreferenceScreen;
import android.util.Log;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.core.preferences.UserPreferences;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+
public class AutoDownloadPreferencesFragment extends PreferenceFragmentCompat {
private static final String TAG = "AutoDnldPrefFragment";
+
+ private static final int LOCATION_PERMISSION_REQUEST_CODE = 1;
+ private static final String PREF_KEY_LOCATION_PERMISSION_REQUEST_PROMPT = "prefAutoDownloadWifiFilterAndroid10PermissionPrompt";
+
private CheckBoxPreference[] selectedNetworks;
+ private Preference prefPermissionRequestPromptOnAndroid10 = null;
+
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.preferences_autodownload);
@@ -175,10 +187,65 @@ public class AutoDownloadPreferencesFragment extends PreferenceFragmentCompat {
}
private void setSelectedNetworksEnabled(boolean b) {
+ if (showPermissionRequestPromptOnAndroid10IfNeeded(b)) {
+ return;
+ }
+
if (selectedNetworks != null) {
for (Preference p : selectedNetworks) {
p.setEnabled(b);
}
}
}
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ if (requestCode != LOCATION_PERMISSION_REQUEST_CODE) {
+ return;
+ }
+ if (permissions.length > 0 && permissions[0].equals(Manifest.permission.ACCESS_FINE_LOCATION) &&
+ grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ buildAutodownloadSelectedNetworksPreference();
+ }
+ }
+
+ private boolean showPermissionRequestPromptOnAndroid10IfNeeded(boolean wifiFilterEnabled) {
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
+ return false;
+ }
+
+ // Cases Android 10(Q) or later
+ if (prefPermissionRequestPromptOnAndroid10 != null) {
+ getPreferenceScreen().removePreference(prefPermissionRequestPromptOnAndroid10);
+ prefPermissionRequestPromptOnAndroid10 = null;
+ }
+
+ if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION)
+ == PackageManager.PERMISSION_GRANTED) {
+ return false;
+ }
+
+ // Case location permission not yet granted, permission-specific UI is needed
+ if (!wifiFilterEnabled) {
+ // Don't show the UI when WiFi filter disabled.
+ // it still return true, so that the caller knows
+ // it does not have required permission, and will not invoke codes that require so.
+ return true;
+ }
+
+ Preference pref = new Preference(requireActivity());
+ pref.setKey(PREF_KEY_LOCATION_PERMISSION_REQUEST_PROMPT);
+ pref.setTitle(R.string.autodl_wifi_filter_permission_title);
+ pref.setSummary(R.string.autodl_wifi_filter_permission_message);
+ pref.setIcon(R.drawable.ic_warning_red);
+ pref.setOnPreferenceClickListener(preference -> {
+ requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_PERMISSION_REQUEST_CODE);
+ return true;
+ });
+ pref.setPersistent(false);
+ getPreferenceScreen().addPreference(pref);
+ prefPermissionRequestPromptOnAndroid10 = pref;
+ return true;
+ }
+
}
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 701d21ce0..9f36e1355 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
@@ -1,27 +1,21 @@
package de.danoeh.antennapod.fragment.preferences;
import android.content.ActivityNotFoundException;
-import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.net.Uri;
-import android.os.Build;
import android.os.Bundle;
-import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.preference.PreferenceFragmentCompat;
import android.util.Log;
import android.widget.Toast;
import com.bytehamster.lib.preferencesearch.SearchConfiguration;
import com.bytehamster.lib.preferencesearch.SearchPreference;
-import de.danoeh.antennapod.CrashReportWriter;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.AboutActivity;
+import de.danoeh.antennapod.activity.BugReportActivity;
import de.danoeh.antennapod.activity.PreferenceActivity;
import de.danoeh.antennapod.activity.StatisticsActivity;
-
-import java.util.List;
+import de.danoeh.antennapod.core.util.IntentUtils;
public class MainPreferencesFragment extends PreferenceFragmentCompat {
private static final String TAG = "MainPreferencesFragment";
@@ -31,9 +25,9 @@ public class MainPreferencesFragment extends PreferenceFragmentCompat {
private static final String PREF_SCREEN_NETWORK = "prefScreenNetwork";
private static final String PREF_SCREEN_INTEGRATIONS = "prefScreenIntegrations";
private static final String PREF_SCREEN_STORAGE = "prefScreenStorage";
- private static final String PREF_KNOWN_ISSUES = "prefKnownIssues";
private static final String PREF_FAQ = "prefFaq";
- private static final String PREF_SEND_CRASH_REPORT = "prefSendCrashReport";
+ private static final String PREF_VIEW_MAILING_LIST = "prefViewMailingList";
+ private static final String PREF_SEND_BUG_REPORT = "prefSendBugReport";
private static final String STATISTICS = "statistics";
private static final String PREF_ABOUT = "prefAbout";
@@ -78,49 +72,20 @@ public class MainPreferencesFragment extends PreferenceFragmentCompat {
return true;
}
);
- findPreference(PREF_KNOWN_ISSUES).setOnPreferenceClickListener(preference -> {
- openInBrowser("https://github.com/AntennaPod/AntennaPod/labels/bug");
+ findPreference(PREF_FAQ).setOnPreferenceClickListener(preference -> {
+ IntentUtils.openInBrowser(getContext(), "https://antennapod.org/faq.html");
return true;
});
- findPreference(PREF_FAQ).setOnPreferenceClickListener(preference -> {
- openInBrowser("http://antennapod.org/faq.html");
+ findPreference(PREF_VIEW_MAILING_LIST).setOnPreferenceClickListener(preference -> {
+ IntentUtils.openInBrowser(getContext(), "https://groups.google.com/forum/#!forum/antennapod");
return true;
});
- findPreference(PREF_SEND_CRASH_REPORT).setOnPreferenceClickListener(preference -> {
- Context context = getActivity().getApplicationContext();
- Intent emailIntent = new Intent(Intent.ACTION_SEND);
- emailIntent.setType("text/plain");
- emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{"Martin.Fietz@gmail.com"});
- emailIntent.putExtra(Intent.EXTRA_SUBJECT, "AntennaPod Crash Report");
- emailIntent.putExtra(Intent.EXTRA_TEXT, "Please describe what you were doing when the app crashed");
- // the attachment
- Uri fileUri = FileProvider.getUriForFile(context, context.getString(R.string.provider_authority),
- CrashReportWriter.getFile());
- emailIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
- emailIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- String intentTitle = getActivity().getString(R.string.send_email);
- if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
- List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(emailIntent, PackageManager.MATCH_DEFAULT_ONLY);
- for (ResolveInfo resolveInfo : resInfoList) {
- String packageName = resolveInfo.activityInfo.packageName;
- context.grantUriPermission(packageName, fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
- }
- }
- getActivity().startActivity(Intent.createChooser(emailIntent, intentTitle));
+ findPreference(PREF_SEND_BUG_REPORT).setOnPreferenceClickListener(preference -> {
+ startActivity(new Intent(getActivity(), BugReportActivity.class));
return true;
});
}
- private void openInBrowser(String url) {
- try {
- Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
- startActivity(myIntent);
- } catch (ActivityNotFoundException e) {
- Toast.makeText(getActivity(), R.string.pref_no_browser_found, Toast.LENGTH_LONG).show();
- Log.e(TAG, Log.getStackTraceString(e));
- }
- }
-
private void setupSearch() {
SearchPreference searchPreference = (SearchPreference) findPreference("searchPreference");
SearchConfiguration config = searchPreference.getSearchConfiguration();
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/StoragePreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/StoragePreferencesFragment.java
index b4226b546..e36476c6f 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/StoragePreferencesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/StoragePreferencesFragment.java
@@ -4,6 +4,7 @@ import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
+import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -13,13 +14,16 @@ import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.FileProvider;
+import android.support.v4.provider.DocumentFile;
import android.support.v7.app.AlertDialog;
import android.support.v7.preference.PreferenceFragmentCompat;
import android.util.Log;
+
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.DirectoryChooserActivity;
import de.danoeh.antennapod.activity.ImportExportActivity;
import de.danoeh.antennapod.activity.OpmlImportFromPathActivity;
+import de.danoeh.antennapod.asynctask.DocumentFileExportWorker;
import de.danoeh.antennapod.asynctask.ExportWorker;
import de.danoeh.antennapod.core.export.ExportWriter;
import de.danoeh.antennapod.core.export.html.HtmlWriter;
@@ -45,6 +49,12 @@ public class StoragePreferencesFragment extends PreferenceFragmentCompat {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE };
private static final int PERMISSION_REQUEST_EXTERNAL_STORAGE = 41;
+ private static final int CHOOSE_OPML_EXPORT_PATH = 1;
+ private static final String DEFAULT_OPML_OUTPUT_NAME = "antennapod-feeds.opml";
+ private static final String CONTENT_TYPE_OPML = "text/x-opml";
+ private static final int CHOOSE_HTML_EXPORT_PATH = 2;
+ private static final String DEFAULT_HTML_OUTPUT_NAME = "antennapod-feeds.html";
+ private static final String CONTENT_TYPE_HTML = "text/html";
private Disposable disposable;
@Override
@@ -59,6 +69,14 @@ public class StoragePreferencesFragment extends PreferenceFragmentCompat {
setDataFolderText();
}
+ @Override
+ public void onStop() {
+ super.onStop();
+ if (disposable != null) {
+ disposable.dispose();
+ }
+ }
+
private void setupStorageScreen() {
final Activity activity = getActivity();
@@ -69,9 +87,16 @@ public class StoragePreferencesFragment extends PreferenceFragmentCompat {
}
);
findPreference(PREF_OPML_EXPORT).setOnPreferenceClickListener(
- preference -> export(new OpmlWriter()));
+ preference -> {
+ openOpmlExportPathPicker();
+ return true;
+ }
+ );
findPreference(PREF_HTML_EXPORT).setOnPreferenceClickListener(
- preference -> export(new HtmlWriter()));
+ preference -> {
+ openHtmlExportPathPicker();
+ return true;
+ });
findPreference(PREF_OPML_IMPORT).setOnPreferenceClickListener(
preference -> {
activity.startActivity(new Intent(activity, OpmlImportFromPathActivity.class));
@@ -129,52 +154,65 @@ public class StoragePreferencesFragment extends PreferenceFragmentCompat {
}
private boolean export(ExportWriter exportWriter) {
+ return export(exportWriter, null);
+ }
+
+ private boolean export(ExportWriter exportWriter, final Uri uri) {
Context context = getActivity();
final ProgressDialog progressDialog = new ProgressDialog(context);
progressDialog.setMessage(context.getString(R.string.exporting_label));
progressDialog.setIndeterminate(true);
progressDialog.show();
- final AlertDialog.Builder alert = new AlertDialog.Builder(context)
- .setNeutralButton(android.R.string.ok, (dialog, which) -> dialog.dismiss());
- Observable<File> observable = new ExportWorker(exportWriter).exportObservable();
- disposable = observable.subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(output -> {
- alert.setTitle(R.string.export_success_title);
- String message = context.getString(R.string.export_success_sum, output.toString());
- alert.setMessage(message);
- alert.setPositiveButton(R.string.send_label, (dialog, which) -> {
+ if (uri == null) {
+ Observable<File> observable = new ExportWorker(exportWriter).exportObservable();
+ disposable = observable.subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(output -> {
Uri fileUri = FileProvider.getUriForFile(context.getApplicationContext(),
context.getString(R.string.provider_authority), output);
- Intent sendIntent = new Intent(Intent.ACTION_SEND);
- sendIntent.putExtra(Intent.EXTRA_SUBJECT,
- context.getResources().getText(R.string.opml_export_label));
- sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
- sendIntent.setType("text/plain");
- sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
- List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(sendIntent, PackageManager.MATCH_DEFAULT_ONLY);
- for (ResolveInfo resolveInfo : resInfoList) {
- String packageName = resolveInfo.activityInfo.packageName;
- context.grantUriPermission(packageName, fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
- }
- }
- context.startActivity(Intent.createChooser(sendIntent,
- context.getResources().getText(R.string.send_label)));
- });
- alert.create().show();
- }, error -> {
- alert.setTitle(R.string.export_error_label);
- alert.setMessage(error.getMessage());
- alert.show();
- }, progressDialog::dismiss);
+ showExportSuccessDialog(context.getString(R.string.export_success_sum, output.toString()), fileUri);
+ }, this::showExportErrorDialog, progressDialog::dismiss);
+ } else {
+ Observable<DocumentFile> observable = new DocumentFileExportWorker(exportWriter, context, uri).exportObservable();
+ disposable = observable.subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(output -> {
+ showExportSuccessDialog(context.getString(R.string.export_success_sum, output.getUri()), output.getUri());
+ }, this::showExportErrorDialog, progressDialog::dismiss);
+ }
return true;
}
- public void unsubscribeExportSubscription() {
- if (disposable != null) {
- disposable.dispose();
- }
+ private void showExportSuccessDialog(final String message, final Uri streamUri) {
+ final AlertDialog.Builder alert = new AlertDialog.Builder(getContext())
+ .setNeutralButton(android.R.string.ok, (dialog, which) -> dialog.dismiss());
+ alert.setTitle(R.string.export_success_title);
+ alert.setMessage(message);
+ alert.setPositiveButton(R.string.send_label, (dialog, which) -> {
+ Intent sendIntent = new Intent(Intent.ACTION_SEND);
+ sendIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.opml_export_label));
+ sendIntent.putExtra(Intent.EXTRA_STREAM, streamUri);
+ sendIntent.setType("text/plain");
+ sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
+ List<ResolveInfo> resInfoList = getContext().getPackageManager()
+ .queryIntentActivities(sendIntent, PackageManager.MATCH_DEFAULT_ONLY);
+ for (ResolveInfo resolveInfo : resInfoList) {
+ String packageName = resolveInfo.activityInfo.packageName;
+ getContext().grantUriPermission(packageName, streamUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ }
+ }
+ getContext().startActivity(Intent.createChooser(sendIntent, getString(R.string.send_label)));
+ });
+ alert.create().show();
+ }
+
+ private void showExportErrorDialog(final Throwable error) {
+ final AlertDialog.Builder alert = new AlertDialog.Builder(getContext())
+ .setNeutralButton(android.R.string.ok, (dialog, which) -> dialog.dismiss());
+ alert.setTitle(R.string.export_error_label);
+ alert.setMessage(error.getMessage());
+ alert.show();
}
@SuppressLint("NewApi")
@@ -184,22 +222,22 @@ public class StoragePreferencesFragment extends PreferenceFragmentCompat {
String dir = data.getStringExtra(DirectoryChooserActivity.RESULT_SELECTED_DIR);
File path;
- if(dir != null) {
+ if (dir != null) {
path = new File(dir);
} else {
path = getActivity().getExternalFilesDir(null);
}
String message = null;
- final Context context= getActivity().getApplicationContext();
- if(!path.exists()) {
+ final Context context = getActivity().getApplicationContext();
+ if (!path.exists()) {
message = String.format(context.getString(R.string.folder_does_not_exist_error), dir);
- } else if(!path.canRead()) {
+ } else if (!path.canRead()) {
message = String.format(context.getString(R.string.folder_not_readable_error), dir);
- } else if(!path.canWrite()) {
+ } else if (!path.canWrite()) {
message = String.format(context.getString(R.string.folder_not_writable_error), dir);
}
- if(message == null) {
+ if (message == null) {
Log.d(TAG, "Setting data folder: " + dir);
UserPreferences.setDataFolder(dir);
setDataFolderText();
@@ -210,6 +248,16 @@ public class StoragePreferencesFragment extends PreferenceFragmentCompat {
ab.show();
}
}
+
+ if (resultCode == Activity.RESULT_OK && requestCode == CHOOSE_OPML_EXPORT_PATH) {
+ Uri uri = data.getData();
+ export(new OpmlWriter(), uri);
+ }
+
+ if (resultCode == Activity.RESULT_OK && requestCode == CHOOSE_HTML_EXPORT_PATH) {
+ Uri uri = data.getData();
+ export(new HtmlWriter(), uri);
+ }
}
private void setDataFolderText() {
@@ -231,6 +279,50 @@ public class StoragePreferencesFragment extends PreferenceFragmentCompat {
activity.startActivityForResult(intent, DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED);
}
+ private void openOpmlExportPathPicker() {
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ Intent intentPickAction = new Intent(Intent.ACTION_CREATE_DOCUMENT)
+ .addCategory(Intent.CATEGORY_OPENABLE)
+ .setType(CONTENT_TYPE_OPML)
+ .putExtra(Intent.EXTRA_TITLE, DEFAULT_OPML_OUTPUT_NAME);
+
+ // Creates an implicit intent to launch a file manager which lets
+ // the user choose a specific directory to export to.
+ try {
+ startActivityForResult(intentPickAction, CHOOSE_OPML_EXPORT_PATH);
+ return;
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "No activity found. Should never happen...");
+ }
+ }
+
+ // If we are using a SDK lower than API 21 or the implicit intent failed
+ // fallback to the legacy export process
+ export(new OpmlWriter());
+ }
+
+ private void openHtmlExportPathPicker() {
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ Intent intentPickAction = new Intent(Intent.ACTION_CREATE_DOCUMENT)
+ .addCategory(Intent.CATEGORY_OPENABLE)
+ .setType(CONTENT_TYPE_HTML)
+ .putExtra(Intent.EXTRA_TITLE, DEFAULT_HTML_OUTPUT_NAME);
+
+ // Creates an implicit intent to launch a file manager which lets
+ // the user choose a specific directory to export to.
+ try {
+ startActivityForResult(intentPickAction, CHOOSE_HTML_EXPORT_PATH);
+ return;
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "No activity found. Should never happen...");
+ }
+ }
+
+ // If we are using a SDK lower than API 21 or the implicit intent failed
+ // fallback to the legacy export process
+ export(new HtmlWriter());
+ }
+
private void showChooseDataFolderDialog() {
ChooseDataFolderDialog.showDialog(
getActivity(), new ChooseDataFolderDialog.RunnableWithString() {
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 156657a00..add62b480 100644
--- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
+++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
@@ -3,7 +3,10 @@ package de.danoeh.antennapod.menuhandler;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
-import android.support.annotation.Nullable;
+import android.os.Handler;
+import android.support.annotation.NonNull;
+import android.support.design.widget.Snackbar;
+import android.support.v4.app.Fragment;
import android.util.Log;
import android.widget.Toast;
@@ -18,7 +21,6 @@ import de.danoeh.antennapod.core.service.playback.PlaybackService;
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.core.util.LongList;
import de.danoeh.antennapod.core.util.ShareUtils;
/**
@@ -51,35 +53,21 @@ public class FeedItemMenuHandler {
* @param mi An instance of MenuInterface that the method uses to change a
* MenuItem's visibility
* @param selectedItem The FeedItem for which the menu is supposed to be prepared
- * @param showExtendedMenu True if MenuItems that let the user share information about
- * the FeedItem and visit its website should be set visible. This
- * parameter should be set to false if the menu space is limited.
- * @param queueAccess Used for testing if the queue contains the selected item; only used for
- * move to top/bottom in the queue
* @return Returns true if selectedItem is not null.
*/
public static boolean onPrepareMenu(MenuInterface mi,
- FeedItem selectedItem,
- boolean showExtendedMenu,
- @Nullable LongList queueAccess) {
+ FeedItem selectedItem) {
if (selectedItem == null) {
return false;
}
boolean hasMedia = selectedItem.getMedia() != null;
boolean isPlaying = hasMedia && selectedItem.getState() == FeedItem.State.PLAYING;
- boolean keepSorted = UserPreferences.isQueueKeepSorted();
if (!isPlaying) {
mi.setItemVisibility(R.id.skip_episode_item, false);
}
boolean isInQueue = selectedItem.isTagged(FeedItem.TAG_QUEUE);
- if (queueAccess == null || queueAccess.size() == 0 || queueAccess.get(0) == selectedItem.getId() || keepSorted) {
- mi.setItemVisibility(R.id.move_to_top_item, false);
- }
- if (queueAccess == null || queueAccess.size() == 0 || queueAccess.get(queueAccess.size()-1) == selectedItem.getId() || keepSorted) {
- mi.setItemVisibility(R.id.move_to_bottom_item, false);
- }
if (!isInQueue) {
mi.setItemVisibility(R.id.remove_from_queue_item, false);
}
@@ -87,12 +75,12 @@ public class FeedItemMenuHandler {
mi.setItemVisibility(R.id.add_to_queue_item, false);
}
- if (!showExtendedMenu || !ShareUtils.hasLinkToShare(selectedItem)) {
+ if (!ShareUtils.hasLinkToShare(selectedItem)) {
mi.setItemVisibility(R.id.visit_website_item, false);
mi.setItemVisibility(R.id.share_link_item, false);
mi.setItemVisibility(R.id.share_link_with_position_item, false);
}
- if (!showExtendedMenu || !hasMedia || selectedItem.getMedia().getDownload_url() == null) {
+ if (!hasMedia || selectedItem.getMedia().getDownload_url() == null) {
mi.setItemVisibility(R.id.share_download_url_item, false);
mi.setItemVisibility(R.id.share_download_url_with_position_item, false);
}
@@ -104,6 +92,7 @@ public class FeedItemMenuHandler {
boolean fileDownloaded = hasMedia && selectedItem.getMedia().fileExists();
mi.setItemVisibility(R.id.share_file, fileDownloaded);
+ mi.setItemVisibility(R.id.remove_new_flag_item, selectedItem.isNew());
if (selectedItem.isPlayed()) {
mi.setItemVisibility(R.id.mark_read_item, false);
} else {
@@ -114,7 +103,7 @@ public class FeedItemMenuHandler {
mi.setItemVisibility(R.id.reset_position, false);
}
- if(!UserPreferences.isEnableAutodownload()) {
+ if(!UserPreferences.isEnableAutodownload() || fileDownloaded) {
mi.setItemVisibility(R.id.activate_auto_download, false);
mi.setItemVisibility(R.id.deactivate_auto_download, false);
} else if(selectedItem.getAutoDownload()) {
@@ -141,10 +130,8 @@ public class FeedItemMenuHandler {
*/
public static boolean onPrepareMenu(MenuInterface mi,
FeedItem selectedItem,
- boolean showExtendedMenu,
- LongList queueAccess,
int... excludeIds) {
- boolean rc = onPrepareMenu(mi, selectedItem, showExtendedMenu, queueAccess);
+ boolean rc = onPrepareMenu(mi, selectedItem);
if (rc && excludeIds != null) {
for (int id : excludeIds) {
mi.setItemVisibility(id, false);
@@ -153,8 +140,16 @@ public class FeedItemMenuHandler {
return rc;
}
- public static boolean onMenuItemClicked(Context context, int menuItemId,
- FeedItem selectedItem) {
+ /**
+ * Default menu handling for the given FeedItem.
+ *
+ * A Fragment instance, (rather than the more generic Context), is needed as a parameter
+ * to support some UI operations, e.g., creating a Snackbar.
+ */
+ public static boolean onMenuItemClicked(@NonNull Fragment fragment, int menuItemId,
+ @NonNull FeedItem selectedItem) {
+
+ @NonNull Context context = fragment.requireContext();
switch (menuItemId) {
case R.id.skip_episode_item:
IntentUtils.sendLocalBroadcast(context, PlaybackService.ACTION_SKIP_CURRENT_EPISODE);
@@ -162,6 +157,9 @@ public class FeedItemMenuHandler {
case R.id.remove_item:
DBWriter.deleteFeedMediaOfItem(context, selectedItem.getMedia().getId());
break;
+ case R.id.remove_new_flag_item:
+ removeNewFlagWithUndo(fragment, selectedItem);
+ break;
case R.id.mark_read_item:
selectedItem.setPlayed(true);
DBWriter.markItemPlayed(selectedItem, FeedItem.PLAYED, false);
@@ -216,14 +214,7 @@ public class FeedItemMenuHandler {
DBWriter.setFeedItemAutoDownload(selectedItem, false);
break;
case R.id.visit_website_item:
- Uri uri = Uri.parse(FeedItemUtil.getLinkWithFallback(selectedItem));
- Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- if(IntentUtils.isCallable(context, intent)) {
- context.startActivity(intent);
- } else {
- Toast.makeText(context, context.getString(R.string.download_error_malformed_url),
- Toast.LENGTH_SHORT).show();
- }
+ IntentUtils.openInBrowser(context, FeedItemUtil.getLinkWithFallback(selectedItem));
break;
case R.id.share_link_item:
ShareUtils.shareFeedItemLink(context, selectedItem);
@@ -249,4 +240,39 @@ public class FeedItemMenuHandler {
return true;
}
+ /**
+ * Remove new flag with additional UI logic to allow undo with Snackbar.
+ *
+ * Undo is useful for Remove new flag, given there is no UI to undo it otherwise
+ * ,i.e., there is (context) menu item for add new flag
+ */
+ public static void removeNewFlagWithUndo(@NonNull Fragment fragment, FeedItem item) {
+ if (item == null) {
+ return;
+ }
+
+ Log.d(TAG, "removeNewFlagWithUndo(" + item.getId() + ")");
+ // we're marking it as unplayed since the user didn't actually play it
+ // but they don't want it considered 'NEW' anymore
+ DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId());
+
+ final Handler h = new Handler(fragment.requireContext().getMainLooper());
+ final Runnable r = () -> {
+ FeedMedia media = item.getMedia();
+ if (media != null && media.hasAlmostEnded() && UserPreferences.isAutoDelete()) {
+ DBWriter.deleteFeedMediaOfItem(fragment.requireContext(), media.getId());
+ }
+ };
+
+ Snackbar snackbar = Snackbar.make(fragment.getView(), fragment.getString(R.string.removed_new_flag_label),
+ Snackbar.LENGTH_LONG);
+ snackbar.setAction(fragment.getString(R.string.undo), v -> {
+ DBWriter.markItemPlayed(FeedItem.NEW, item.getId());
+ // don't forget to cancel the thing that's going to remove the media
+ h.removeCallbacks(r);
+ });
+ snackbar.show();
+ h.postDelayed(r, (int) Math.ceil(snackbar.getDuration() * 1.05f));
+ }
+
}
diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java
index 0928cfd62..dbb3b6e7b 100644
--- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java
+++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java
@@ -20,11 +20,13 @@ import java.util.Set;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.feed.Feed;
+import de.danoeh.antennapod.core.feed.FeedItemFilter;
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.util.IntentUtils;
import de.danoeh.antennapod.core.util.ShareUtils;
+import de.danoeh.antennapod.dialog.FilterDialog;
/**
* Handles interactions with the FeedItemMenu.
@@ -84,14 +86,7 @@ public class FeedMenuHandler {
conDialog.createNewDialog().show();
break;
case R.id.visit_website_item:
- Uri uri = Uri.parse(selectedFeed.getLink());
- Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- if(IntentUtils.isCallable(context, intent)) {
- context.startActivity(intent);
- } else {
- Toast.makeText(context, context.getString(R.string.download_error_malformed_url),
- Toast.LENGTH_SHORT).show();
- }
+ IntentUtils.openInBrowser(context, selectedFeed.getLink());
break;
case R.id.share_link_item:
ShareUtils.shareFeedlink(context, selectedFeed);
@@ -105,42 +100,15 @@ public class FeedMenuHandler {
return true;
}
- private static void showFilterDialog(final Context context, final Feed feed) {
- 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> filter = new HashSet<>(Arrays.asList(feed.getItemFilter().getValues()));
- Iterator<String> it = filter.iterator();
- while(it.hasNext()) {
- // make sure we have no empty strings in the filter list
- if(TextUtils.isEmpty(it.next())) {
- it.remove();
- }
- }
- for(int i=0; i < values.length; i++) {
- String value = values[i];
- if(filter.contains(value)) {
- checkedItems[i] = true;
+ private static void showFilterDialog(Context context, Feed selectedFeed) {
+ FilterDialog filterDialog = new FilterDialog(context, selectedFeed.getItemFilter()) {
+ @Override
+ protected void updateFilter(Set<String> filterValues) {
+ selectedFeed.setItemFilter(filterValues.toArray(new String[filterValues.size()]));
+ DBWriter.setFeedItemsFilter(selectedFeed.getId(), filterValues);
}
- }
-
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(R.string.filter);
- builder.setMultiChoiceItems(items, checkedItems, (dialog, which, isChecked) -> {
- if (isChecked) {
- filter.add(values[which]);
- } else {
- filter.remove(values[which]);
- }
- });
- builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
- feed.setItemFilter(filter.toArray(new String[filter.size()]));
- DBWriter.setFeedItemsFilter(feed.getId(), filter);
- });
- builder.setNegativeButton(R.string.cancel_label, null);
- builder.create().show();
+ };
+ filterDialog.openDialog();
}
-
}
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 e56703598..6392d0535 100644
--- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java
+++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java
@@ -3,27 +3,31 @@ package de.danoeh.antennapod.preferences;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
+
import de.danoeh.antennapod.BuildConfig;
+import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
import de.danoeh.antennapod.core.util.gui.NotificationUtils;
public class PreferenceUpgrader {
- private static final String PREF_CONFIGURED_VERSION = "configuredVersion";
- private static final String PREF_NAME = "PreferenceUpgrader";
+ private static final String PREF_CONFIGURED_VERSION = "version_code";
+ private static final String PREF_NAME = "app_version";
private static SharedPreferences prefs;
public static void checkUpgrades(Context context) {
prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences upgraderPrefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
- int oldVersion = upgraderPrefs.getInt(PREF_CONFIGURED_VERSION, 1070200);
+ int oldVersion = upgraderPrefs.getInt(PREF_CONFIGURED_VERSION, -1);
int newVersion = BuildConfig.VERSION_CODE;
if (oldVersion != newVersion) {
NotificationUtils.createChannels(context);
+ AutoUpdateManager.restartUpdateAlarm();
- upgraderPrefs.edit().putInt(PREF_CONFIGURED_VERSION, newVersion).apply();
upgrade(oldVersion);
+ upgraderPrefs.edit().putInt(PREF_CONFIGURED_VERSION, newVersion).apply();
}
}
@@ -41,12 +45,8 @@ public class PreferenceUpgrader {
}
}
if (oldVersion < 1070300) {
- UserPreferences.restartUpdateAlarm();
-
- if (UserPreferences.getMediaPlayer().equals("builtin")) {
- prefs.edit().putString(UserPreferences.PREF_MEDIA_PLAYER,
- UserPreferences.PREF_MEDIA_PLAYER_EXOPLAYER).apply();
- }
+ prefs.edit().putString(UserPreferences.PREF_MEDIA_PLAYER,
+ UserPreferences.PREF_MEDIA_PLAYER_EXOPLAYER).apply();
if (prefs.getBoolean("prefEnableAutoDownloadOnMobile", false)) {
UserPreferences.setAllowMobileAutoDownload(true);
@@ -65,5 +65,13 @@ public class PreferenceUpgrader {
break;
}
}
+ if (oldVersion < 1070400) {
+ int theme = UserPreferences.getTheme();
+ if (theme == R.style.Theme_AntennaPod_Light) {
+ prefs.edit().putString(UserPreferences.PREF_THEME, "system").apply();
+ }
+
+ UserPreferences.setQueueLocked(false);
+ }
}
}
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 03958508d..5fa6588d9 100644
--- a/app/src/main/java/de/danoeh/antennapod/spa/SPAUtil.java
+++ b/app/src/main/java/de/danoeh/antennapod/spa/SPAUtil.java
@@ -46,7 +46,7 @@ public class SPAUtil {
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(PREF_HAS_QUERIED_SP_APPS, true);
- editor.commit();
+ editor.apply();
return true;
} else {
@@ -63,7 +63,7 @@ public class SPAUtil {
SharedPreferences.Editor editor = PreferenceManager
.getDefaultSharedPreferences(c.getApplicationContext()).edit();
editor.putBoolean(PREF_HAS_QUERIED_SP_APPS, false);
- editor.commit();
+ editor.apply();
}
}
}
diff --git a/app/src/main/play/listings/de-DE/full-description.txt b/app/src/main/play/listings/de-DE/full-description.txt
index f312ea559..c49417c3e 100644
--- a/app/src/main/play/listings/de-DE/full-description.txt
+++ b/app/src/main/play/listings/de-DE/full-description.txt
@@ -1,12 +1,12 @@
AntennaPod ist ein Podcast-Manager und -Player, der dir unmittelbar Zugriff auf Millionen von freien und bezahlten Podcasts ermöglicht, angefangen von unabhängigen Podcastern zu großen Rundfunkanstalten oder Hörfunksendern wie BBC, NPR und CNN. Abonniere, importiere und exportiere deine Feeds mühelos mit Hilfe des iTunes-Verzeichnisses, OPML-Dateien oder einfachen RSS-URLs. Reduziere Aufwand, Stromverbrauch und Datenverbrauch durch die Kontrolle der Downloads (bestimmte Uhrzeiten, Intervalle, WiFi-Netze) und des Löschens (basierend auf deinen Favoriten und weiteren Einstellungen).
-Aber am wichtigsten: Downloade, streame oder füge Episoden zur Abspielliste hinzu und genieße sie mit einstellbarer Abspielgeschwindigkeit, Unterstützung von Kapiteln und Schlummerfunktion. Mit Flattr kannst du den Podcastern sogar deine Wertschätzung zeigen.
+Aber am wichtigsten: Downloade, streame oder füge Episoden zur Abspielliste hinzu und genieße sie mit einstellbarer Abspielgeschwindigkeit, Unterstützung von Kapiteln und Schlummerfunktion.
AntennaPod ist, von Podcast-Enthusiasten gemacht, frei im Sinne des Wortes: Open Source, keine Kosten, keine Werbung.
<b>Alle Funktionen:</b><br>
IMPORTIERE, ORGANISIERE UND HÖRE<br>
&#8226; Importiere oder füge Feeds über das iTunes und gPodder.net Verzeichnis, OMPL Dateien und RSS oder Atom Links hinzu.
-&#8226; Bediene die Wiedergabe von überall: Homescreen-Widget, Benachrichtigung und Koopfhörer- und Bluetooth-Bedienelementen<br>
+&#8226; Bediene die Wiedergabe von überall: Startbildschirm-Widget, Benachrichtigung und Kopfhörer- und Bluetooth-Bedienelemente<br>
&#8226; Genieße das Zuhören auf deine Art mit einstellbarer Abspielgeschwindigkeit, der Unterstützung von Kapiteln (MP3, OGG, Podlove) und ausgereifter Schlummerfunktion (durch Schütteln zurücksetzen, Lautstärke verringern und Geschwindigkeit verlangsamen)
&#8226; Greife auf Passwort-geschützte Feeds und Episoden zu<br>
&#8226; Nutze den Vorteil von Paged Feeds (http://www.podlove.org/paged-feeds)
@@ -15,9 +15,8 @@ ORDNE, TEILE & GENIEßE
&#8226; Bleib an den Besten der Besten dran, indem Du Episoden als Favoriten markierst<br>
&#8226; Finde Episoden durch die Liste zuletzt gespielter Episoden oder durch Suche in Titel und Shownotes
&#8226; Teile Episoden and Feeds über soziale Medien, E-Mail, den gPodder.net-Dienst oder als OPML-Export
-&#8226; Unterstütze die Autoren von Inhalten mit Flattr (inklusive automatischem Flattren)
-STEUER DAS SYSTEM<br>
+STEUERE DAS SYSTEM<br>
&#8226; Kontrolliere automatisches Herunterladen: Wähle Feeds aus, schließe mobile Netze aus, suche bestimmte WiFi-Netze aus, setze voraus, dass das Smartphone geladen wird und lege Zeitpunkte oder Intervalle fest<br>
&#8226; Verwalte deinen Speicherplatz durch das Festlegen der Anzahl gespeicherter Episoden, schlaues Löschen und durch Auswahl des Speicherortes<br>
&#8226; Benutze AntennaPod in deiner Sprache (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br>
diff --git a/app/src/main/play/listings/de-DE/title.txt b/app/src/main/play/listings/de-DE/title.txt
new file mode 100644
index 000000000..31552f353
--- /dev/null
+++ b/app/src/main/play/listings/de-DE/title.txt
@@ -0,0 +1 @@
+AntennaPod \ No newline at end of file
diff --git a/app/src/main/play/listings/en-US/graphics/icon/icon_play.png b/app/src/main/play/listings/en-US/graphics/icon/icon_play.png
new file mode 100644
index 000000000..824346d21
--- /dev/null
+++ b/app/src/main/play/listings/en-US/graphics/icon/icon_play.png
Binary files differ
diff --git a/app/src/main/play/listings/es-ES/full-description.txt b/app/src/main/play/listings/es-ES/full-description.txt
new file mode 100644
index 000000000..8c5cba745
--- /dev/null
+++ b/app/src/main/play/listings/es-ES/full-description.txt
@@ -0,0 +1,42 @@
+AntennaPod es un reproductor y administrador de pódcast que te da acceso instantáneo a millones de pódcast gratuitos y de pago, desde editores independientes a grandes editoriales como la BBC, NPR y CNN. Añade, importa y exporta tus fuentes sin complicaciones usando la base de datos de pódcast de iTunes, archivos OPML o las URL de tipo RSS. Ahorra esfuerzo, energía de la batería y uso de datos móviles con potentes controles de automatización para descargar episodios (especifica horarios, intervalos y redes wifi) y elimina episodios (según tus favoritos y la configuración de retardo).<br>
+Y lo que es más importante: Descarga, escucha en stream, o añade la cola episodios y disfrútalos como quieras con velocidad de reproducción ajustable, soporte para capítulos y temporizador de sueño.
+
+Creado por entusiastas del pódcast, AntennaPod es libre en todos los sentidos: código abierto, gratuito y sin publicidad.
+
+<b>Todas las características:</b><br>
+IMPORTAR, ORGANIZAR Y REPRODUCIR<br>
+&#8226; Añade e importa fuentes mediante los directorios de iTunes y gPodder.net, archivos OPML y enlaces RSS o Atom<br>
+&#8226; Administra la reproducción desde cualquier parte: control en pantalla de inicio, notificación del sistema y controles de auricular y bluetooth<br>
+&#8226; Disfruta escuchando a tu manera con velocidad de reproducción ajustable, soporte de capítulos (MP3, VorbisComment y Podlove), recordatorio del punto de reproducción y el temporizador de sueño avanzado (agita para restablecer, bajar el volumen y disminuir la velocidad de reproducción)<br>
+&#8226; Accede a fuentes y episodios protegidos con contraseña<br>
+&#8226; Aprovecha las fuentes paginadas (www.podlove.org/paged-feeds)
+
+MANTÉN UN SEGUIMIENTO, COMPARTE Y APRECIA
+&#8226; Haz un seguimiento de lo mejor de lo mejor marcando episodios como favoritos<br>
+&#8226; Encuentra ese episodio a través del historial de reproducción o por búsqueda (títulos y notas de episodios)<br>
+&#8226; Comparte episodios y fuentes a través de las avanzadas redes sociales y opciones de correo electrónico, los servicios de gPodder.net y la exportación OPML<br>
+
+CONTROLA EL SISTEMA<br>
+&#8226; Controla las descargas automáticas: elige las fuentes, excluye las redes móviles, selecciona redes wifi específicas, o solo cuando el teléfono se esté cargando y establece horarios o intervalos<br>
+&#8226; Administra el almacenamiento configurando la cantidad de episodios almacenados, el borrado inteligente (según tus favoritos y el estado de reproducción) y selecciona tu ubicación preferida<br>
+&#8226; Usa AntennaPod en tu idioma (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br>
+&#8226; Adáptate a tu entorno usando el tema claro u oscuro<br>
+&#8226; Haz una copia de seguridad de tus suscripciones con la integración de gPodder.net y la exportación OPML
+
+<b>¡Únete a la comunidad AntennaPod!</b><br>
+AntennaPod está en continuo desarrollo por voluntarios. ¡Tú también puedes contribuir, con tu código o con tus comentarios!
+
+GitHub es el sitio que debes visitar para solicitar características nuevas, reportar fallos y contribuir con código<br>
+https://www.github.com/AntennaPod/AntennaPod
+
+Nuestro Grupo de Google es el sitio para compartir tus ideas, momentos favoritos de tus pódcast y tu gratitud a los voluntarios:<br>
+https://groups.google.com/forum/#!forum/antennapod
+
+¿Tienes una pregunta o quieres darnos tu opinión?
+https://twitter.com/@AntennaPod
+
+Transifex es el sitio para ayudar con las traducciones:<br>
+https://www.transifex.com/antennapod/antennapod
+
+Echa un vistazo a nuestro programa de pruebas Beta y ser el primero en usar las nuevas características:<br>
+https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file
diff --git a/app/src/main/play/listings/es-ES/short-description.txt b/app/src/main/play/listings/es-ES/short-description.txt
new file mode 100644
index 000000000..cc94d9c22
--- /dev/null
+++ b/app/src/main/play/listings/es-ES/short-description.txt
@@ -0,0 +1 @@
+Reproductor y gestor de pódcast fácil de usar, flexible y de código abierto \ No newline at end of file
diff --git a/app/src/main/play/listings/es-ES/title.txt b/app/src/main/play/listings/es-ES/title.txt
new file mode 100644
index 000000000..31552f353
--- /dev/null
+++ b/app/src/main/play/listings/es-ES/title.txt
@@ -0,0 +1 @@
+AntennaPod \ No newline at end of file
diff --git a/app/src/main/play/listings/fr-FR/full-description.txt b/app/src/main/play/listings/fr-FR/full-description.txt
index 372e1da60..5c69f3892 100644
--- a/app/src/main/play/listings/fr-FR/full-description.txt
+++ b/app/src/main/play/listings/fr-FR/full-description.txt
@@ -1,5 +1,5 @@
-AntennaPod est un lecteur et gestionnaire de podcast permettant l'accès à des millions de podcast gratuits ou payants produit aussi bien par des podcasters indépendants que de gros éditeurs comme la BBC, NPR ou CNN. Ajoutez, importez et exportez leurs flux facilement à partir d'ITunes, de fichiers OPML ou simplement à partir de liens RSS. Gagnez du temps, préservez votre batterie et consommation internet grâce à une automatisation puissante des téléchargements (date, fréquence, choix du réseau WiFi, etc...) et des suppressions d’épisodes écoutés (selon vos critères)<br>
-Avant tout : téléchargez, streamez ou ajoutez à la liste de lecture vos épisodes et écoutez les comme vous voulez grâce au réglage de vitesse de lecture, au support des chapitres et au minuteur d'arrêt. Vous pouvez même montrer votre appréciation aux créateurs de contenu avec notre intégration de Flattr.
+AntennaPod est un lecteur de podcast permettant l'accès à des millions de podcast gratuits ou payants produit aussi bien par des podcasters indépendants que des éditeurs professionnels comme la BBC, NPR ou CNN. Ajoutez, importez et exportez leurs flux facilement à partir d'ITunes, de fichiers OPML ou simplement à partir de liens RSS. Economisez votre temps, votre batterie et votre consommation de données grâce à l'automatisation des téléchargements (date, fréquence, choix du réseau WiFi, etc...) et de la suppression des épisodes (selon vos critères)<br>
+Avant tout : téléchargez, streamez ou ajoutez à la liste de lecture vos épisodes et écoutez les comme vous voulez grâce au réglage de vitesse de lecture, au support des chapitres et au minuteur d'arrêt.
Conçu par des fans de podcast, AntennaPod est gratuit dans tous les sens du terme : open source, gratuit et sans publicité.
@@ -15,7 +15,6 @@ SUIVEZ, PARTAGEZ & PROFITEZ<br>
&#8226; Marquer les meilleurs épisodes en tant que favoris<br>
&#8226; Retrouvez un épisode à partir de l'historique de lecture ou en recherchant parmi les titres et commentaires des épisodes précédents<br>
&#8226; Partagez vos épisodes et flux sur les réseaux sociaux, par email, sur gPodder.net ou en les exportant au format OPML<br>
-&#8226; Soutenez les créateurs de contenu avec l'intégration à Flattr et la possibilité de flatter automatiquement
CONTRÔLER LE SYSTÈME<br>
&#8226; Prenez le contrôle en automatisant vos téléchargements : choix des flux, restriction de la connexion mobile, sélection du réseau WIFI à utiliser, uniquement durant la recharge et spécifiez la fréquence de mise à jour vous-même<br>
diff --git a/app/src/main/play/listings/fr-FR/short-description.txt b/app/src/main/play/listings/fr-FR/short-description.txt
index 61c3c7e20..7143385e1 100644
--- a/app/src/main/play/listings/fr-FR/short-description.txt
+++ b/app/src/main/play/listings/fr-FR/short-description.txt
@@ -1 +1 @@
-Un lecteur et gestionnaire de podcast facile à utiliser et flexible \ No newline at end of file
+Un lecteur de podcast facile à utiliser et flexible \ No newline at end of file
diff --git a/app/src/main/play/listings/fr-FR/title.txt b/app/src/main/play/listings/fr-FR/title.txt
new file mode 100644
index 000000000..31552f353
--- /dev/null
+++ b/app/src/main/play/listings/fr-FR/title.txt
@@ -0,0 +1 @@
+AntennaPod \ No newline at end of file
diff --git a/app/src/main/play/listings/gl-ES/full-description.txt b/app/src/main/play/listings/gl-ES/full-description.txt
index c275c1fc2..2acaf65f7 100644
--- a/app/src/main/play/listings/gl-ES/full-description.txt
+++ b/app/src/main/play/listings/gl-ES/full-description.txt
@@ -1,5 +1,5 @@
AntenaPod é un xestor de podcast e reprodutor que lle da acceso a millóns de podcast tanto gratuítos como de pagamento, desde podcasters independentes a grandes productores como BBC, NPR e CNN. Engada, importe e exporte as súas fontes de xeito doado utilizando a base de datos de iTunes, ficheiros OPML ou URLs RSS. Aforre traballo, enerxía da batería e datos móbiles co sistema automatizado de control das descargas de episodios (indicando horario, intervalos e redes WiFi) e borrando episodios (baseado nos seus favoritos e axustes de retardo).<br>
-Mais o máis importante: Descargue, envíe ou poña na cola os episodios e disfrúteos do xeito en que máis lle conveña, axustando a velocidade de reprodución, xestión de capítulos e apagado automático. Poderá tamén mostrarlle aos creadores canto lle gustan os seus contidos gracias a integración con Flattr.
+O máis importante: Descarga, reproduce ou pon en cola os episodios e desfrútaos do xeito en que máis che conveña axustando a velocidade de reprodución, o soporte de capítulos e o apagado programable.
Escrito por namorados dos podcast, AntennaPod é gratuíto e libre: open source, sen custos, sen publicidade.
@@ -15,7 +15,6 @@ SIGA, COMPARTA E VALORE <br>
&#8226; Garde o melloriño de cada casa marcando episodios como favoritos<br>
&#8226; Atope ese episodio especial no historial de reprodución ou buscando (títulos e notas do episodio)<br>
&#8226; Comparta episodios e fontes a través das opcións de redes sociais e correro electrónico, os servizos de gPodder.net e exportando a OPML<br>
-&#8226; Axude aos creadores de contido coa integración con Flattr incluíndo o flattring automático
CONTROL DO SISTEMA <br>
&#8226; Tome control sobre as descargas automáticas: escolla fontes, exclúa redes móbiles, redes WIFI concretas, requerir que o móbil esté a cargar e horarios e intervalos<br>
diff --git a/app/src/main/play/listings/gl-ES/title.txt b/app/src/main/play/listings/gl-ES/title.txt
new file mode 100644
index 000000000..31552f353
--- /dev/null
+++ b/app/src/main/play/listings/gl-ES/title.txt
@@ -0,0 +1 @@
+AntennaPod \ No newline at end of file
diff --git a/app/src/main/play/listings/it-IT/title.txt b/app/src/main/play/listings/it-IT/title.txt
new file mode 100644
index 000000000..31552f353
--- /dev/null
+++ b/app/src/main/play/listings/it-IT/title.txt
@@ -0,0 +1 @@
+AntennaPod \ No newline at end of file
diff --git a/.tx/antennapod.description/he_IL_translation b/app/src/main/play/listings/iw-IL/full-description.txt
index 4ccee5452..58895c50e 100644
--- a/.tx/antennapod.description/he_IL_translation
+++ b/app/src/main/play/listings/iw-IL/full-description.txt
@@ -1,5 +1,5 @@
היישומון אנטנה־פּוֹד הוא נגן ומנהל פודקאסטים שמעניק לך גישה ישירה למיליונים של פודקאסטים בחינם ובתשלום, החל ממגישי פודקאסטים עצמאיים ועד למפיצים גדולים כגון BBC,‏ NPR ו־CNN. ניתן להוסיף, לייבא ולייצא את ההזנות שלהם בקלות יחסית באמצעות מסד נתוני הפודקאסטים של iTunes, קובצי OPML או כתובות של RSS. מאפשר לך לחסוך במאמץ, סוללה ותקשורת נתונים עם פקדי אוטומציה להורדה של פרקים (לפי זמנים, הפרשי זמן ורשתות אלחוטיות) ומחיקה של פרקים (על בסיס הגדרות המועדפים וההשהיה שלך).<br>
-אבל הכי חשוב: ניתן להוריד, להזרים או לסדר רשימות של פרקים וליהנות מהם בכל דרך שמתאימה לך עם מהירויות נגינה משתנות, תמיכה במקטעים ומתזמן שינה. ניתן אפילו להביע את חיבתך ליוצרי התוכן עם שילוב של Flattr ביישומון.
+אבל הכי חשוב: ניתן להוריד, להזרים או לסדר רשימות של פרקים וליהנות מהם בכל דרך שמתאימה לך עם מהירויות נגינה משתנות, תמיכה במקטעים ומתזמן שינה
מיוצרת על ידי חובבי פודקאסטים, אנטנהפוד הינה תוכנה חינמית בכל מובן המילה: קוד פתוח, ללא עלות וללא פרסומות.
@@ -15,7 +15,6 @@
&#8226; מעקב אחר הטובים שבטובים על ידי סימון פרקים כמועדפים<br>
&#8226; ניתן לאתר פרק אחד דרך היסטוריית הנגינה או על ידי חיפוש (כותרות והערות פרק)<br>
&#8226; ניתן לשתף פרקים והזנות דרך אפשרויות מתקדמות ברשתות חברתיות ודוא״ל, שירותי gPodder.net ודרך ייצוא OPML<br>
-&#8226; ניתן לתמוך בעורכי תוכן עם שילוב של Flattr לתוך המערכת לרבות תרומה אוטומטית
שליטה במערכת<br>
&#8226; ניתן לשלוט על הורדה אוטומטית: לבחור הזנות, להחריג רשתות סלולריות, לבחור רשתות אלחוטיות מסוימות, לדרוש מהטלפון להיות בטעינה ולהגדיר מועדים או מרווחי זמן<br>
diff --git a/.tx/antennapod.shortdescription/he_IL_translation b/app/src/main/play/listings/iw-IL/short-description.txt
index 34ffefafc..34ffefafc 100644
--- a/.tx/antennapod.shortdescription/he_IL_translation
+++ b/app/src/main/play/listings/iw-IL/short-description.txt
diff --git a/app/src/main/play/listings/iw-IL/title.txt b/app/src/main/play/listings/iw-IL/title.txt
new file mode 100644
index 000000000..31552f353
--- /dev/null
+++ b/app/src/main/play/listings/iw-IL/title.txt
@@ -0,0 +1 @@
+AntennaPod \ No newline at end of file
diff --git a/app/src/main/play/listings/ja-JP/full-description.txt b/app/src/main/play/listings/ja-JP/full-description.txt
index b85f6787e..4dc50f57e 100644
--- a/app/src/main/play/listings/ja-JP/full-description.txt
+++ b/app/src/main/play/listings/ja-JP/full-description.txt
@@ -1,5 +1,5 @@
AntennaPodは、独自のポッドキャスターから、BBC、NPR、CNNなどの大規模な放送まで、数百万の無料や有料ポッドキャストに瞬時にアクセスすることができる、ポッドキャストマネージャーおよびプレーヤーです。フィードは手間のかからないiTunesのPodcastのデータベース、OPMLファイルや簡単なRSSのURLを使用して追加、インポート、エクスポートします。エピソードのダウンロード (時間、間隔およびWiFiネットワークを指定) とエピソードの削除 (お気に入りと遅延設定に基づいて) をするために強力な自動コントロールで、手間、バッテリ消費、モバイルデータ使用量を節約します。<br>
-しかし最も重要なこと: エピソードをダウンロード、ストリーム再生、またはキューに入れて、そして再生速度の調整、チャプターのサポート、スリープタイマーで好きなように楽しんでください。Flattr統合でコンテンツ作成者にあなたの愛を示すことができます。
+しかし最も重要なこと: エピソードをダウンロード、ストリーム再生、またはキューに入れて、そして再生速度の調整、チャプターのサポート、スリープタイマーで好きなように楽しんでください。
ポッドキャスト愛好家が作成した AntennaPod はすべての意味でフリー自由です: オープンソース、コスト不要、広告はありません。
@@ -15,7 +15,6 @@ AntennaPodは、独自のポッドキャスターから、BBC、NPR、CNNなど
&#8226; エピソードをお気に入りとしてマークして、一番の中の一番を保存してください<br>
&#8226; 再生履歴から、または検索 (タイトルとショーノート) して目的のエピソードを見つけてください<br>
&#8226; 高度なソーシャルメディアとメールオプション、gPodder.netサービス、OPMLエクスポートからエピソードやフィードを共有してください<br>
-&#8226; 自動Flattrを含むFlattrの統合でコンテンツクリエイターをサポートします
システムのコントロール
&#8226; 自動ダウンロードの制御: フィードを選択、モバイルネットワークを除外、特定のWiFiネットワークを選択、電話を充電する必要、時間や間隔を設定<br>
diff --git a/app/src/main/play/listings/ja-JP/title.txt b/app/src/main/play/listings/ja-JP/title.txt
new file mode 100644
index 000000000..31552f353
--- /dev/null
+++ b/app/src/main/play/listings/ja-JP/title.txt
@@ -0,0 +1 @@
+AntennaPod \ No newline at end of file
diff --git a/app/src/main/play/listings/nl-NL/full-description.txt b/app/src/main/play/listings/nl-NL/full-description.txt
index 6c6ef1e8a..518745f17 100644
--- a/app/src/main/play/listings/nl-NL/full-description.txt
+++ b/app/src/main/play/listings/nl-NL/full-description.txt
@@ -1,5 +1,5 @@
Met AntennaPod speel en beheer je al je podcasts en krijg je directe toegang tot duizenden gratis en betaalde podcasts - van onafhankelijke makers tot grote merken zoals BBC, CNN en NPO. Via de iTunes-databank, OPML-bestanden en simpele RSS-linkjes voeg je deze podcasts gemakkelijk toe. Dankzij simpele maar slimme automatische controle van het downloaden en verwijderen van afleveringen bespaar je de accu, hoef je je favoriete podcast niet meer handmatig te volgen en verbruik je geen onnodige mobiele gegevens.<br>
-Maar belangrijker: Met een handige wachtrij, aanpasbare afspeelsnelheden, ondersteuning van hoofdstukken en een slaap timer luister je naar podcasts op de manier die jij prettig vindt. Je kunt zelfs je liefde voor de makers uiten met onze Flattr-integratie.
+Maar belangrijker: download, stream of voeg afleveringen toe aan de wachtrij en geniet ervan! Je hebt beschikking over afspeelsnelheden, hoofdstukondersteuning en een slaaptimer.
Gemaakt door podcast-enthousiastelingen, AntennaPod is vrij in de breedste zin van het woord: vrij van advertenties, open source en gratis.
@@ -15,7 +15,6 @@ DEEL & WAARDEER<br>
&#8226; Hou het beste van het beste bij door afleveringen als favoriet te markeren<br>
&#8226; Vindt die ene aflevering terug in de afspeelgeschiedenis of door te zoeken (in titels, shownotes en makers)<br>
&#8226; Deel podcasts en afleveringen via uitgebreide opties voor sociale media, WhatsApp, email en gPodder.net<br>
-&#8226; Steun makers met Flattr-integratie, inclusief auto-Flattr
HOUD DE CONTROLE
&#8226; Beheer automatische downloads: kies je podcasts, sluit mobiele netwerken uit, selecteer specifieke WiFi-verbindingen, eis dat de telefoon wordt opgeladen and bepaal tijden of intervals<br>
diff --git a/app/src/main/play/listings/nl-NL/title.txt b/app/src/main/play/listings/nl-NL/title.txt
new file mode 100644
index 000000000..31552f353
--- /dev/null
+++ b/app/src/main/play/listings/nl-NL/title.txt
@@ -0,0 +1 @@
+AntennaPod \ No newline at end of file
diff --git a/app/src/main/play/listings/sv-SE/full-description.txt b/app/src/main/play/listings/sv-SE/full-description.txt
new file mode 100644
index 000000000..d46fdafdc
--- /dev/null
+++ b/app/src/main/play/listings/sv-SE/full-description.txt
@@ -0,0 +1,42 @@
+AntennaPod är en podcasthanterare och spelare som ger dig omedelbar tillgång till miljoner av gratis och betalda podcasts, från oberoende podcastare till stora publiceringshus så som BBC, NPR och CNN. Lägg till, importera och exportera enkelt deras flöden med iTunes podcastdatabas, OPML-filer eller vanliga RSS URL:er. Spara möda, batterikraft och mobildata med kraftfulla automatiseringskontroller för nedladdning (välj tider, intervall och WiFi-nätverk) och borttagning av episoder (baserat på dina favoriter och fördröjningsinställningar).
+Men viktigast av allt: Ladda ner, strömma eller köa episoder och avnjut dem på det sätt du gillar med justerbar uppspelningshastighet, kapitelstöd och insomningstimer.
+
+Gjord av podcastenthusiaster, AntennaPod är fri i alla ordets bemärkelser: öppen källkod, inga kostnader, ingen reklam.
+
+<b>Alla funktioner:</b><br>
+IMPORTERA, ORGANISERA OCH SPELA<br>
+&#8226; Lägg till och importera flöden via iTunes och gPodder.net, OPML filer och RSS eller Atom länkar<br>
+&#8226; Hantera uppspelningen från vartsomhelst: hemskärmswidget, aviseringsfältet och hörlurs/bluetoth-kontroller<br>
+&#8226; Njut av att lyssna på ditt sätt med justerbar uppspelningshastighet, kapitelstöd (MP4, VorbisComment och Podlove), ihågkommen uppspelningsposition och en avancerad sömntimer (skaka för återställaning, sänk volymen och sänk hastigheten)<br>
+&#8226; Kom åt lösenordsskyddade flöden och episoder<br>
+&#8226; Dra nytta av siduppdelade flöden (www.podlove.ord/paged-feeds)
+
+SPÅRA, DELA & UPPSKATTA<br>
+&#8226; Håll ordning på de bästa av de bästa med favoritmarkering av episoder<br>
+&#8226; Hitta just den där episoden i uppspelningshistoriken eller genom sökning (titel och shownotes)<br>
+&#8226; Dela episoder och flöden med avancerade vald för social media och och email, tjänsten gPodder.net och via OPML export<br>
+
+KONTROLLERA SYSTEMET<br>
+&#8226; Ta kontroll över automatisk nedladdning: välj flöden, exkludera mobilnätverk, välj specifika WiFi nätverk, kräv att telefonen är inkopplad för laddning och sätt tider eller intervall för körning<br>
+&#8226; Hantera lagringsutrymme genom att välja antalet cachade episoder, smart borttagning (baserat på dina favoriter och uppspelningsstatus) och välj den lagringsplats du föredrar<br>
+&#8226; Använd AntennaPod på ditt språk (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br>
+&#8226; Anpassa till din omgivning med det ljusa och mörka temat<br>
+&#8226; Ta backup av dina prenumerationer med integreringen av gPodder.net och OPML exportering
+
+<b>Gå med i AntennaPods gemenskap!</b><br>
+AntennaPod är under aktiv utveckling av volontärer. Du kan också bidra, med kod eller kommentarer!
+
+GitHub är platsen att gå till för att be om funktioner, skapa buggrapporter eller bidra med kod:<br>
+https://www.github.com/AntennaPod/AntennaPod
+
+Vår Google Group är platsen för att dela idéer, dina favoritögonblick med podcasting och din uppskattning till volontärerna:<br>
+https://groups.google.com/forum/#!forum/antennapod
+
+Har du frågor eller vill ge feedback?
+https://twitter.com/@AntennaPod
+
+Transifex är platsen att gå till för att hjälpa till med översättningen:<br>
+https://www.transifex.com/antennapod/antennapod
+
+Kolla in vårat Beta Testing program för att få de senaste funktionerna först:<br>
+https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file
diff --git a/app/src/main/play/listings/sv-SE/short-description.txt b/app/src/main/play/listings/sv-SE/short-description.txt
new file mode 100644
index 000000000..2273fc5e4
--- /dev/null
+++ b/app/src/main/play/listings/sv-SE/short-description.txt
@@ -0,0 +1 @@
+Användarvänlig och flexibel podcasthanterare och spelare med öppen källkod \ No newline at end of file
diff --git a/app/src/main/play/listings/sv-SE/title.txt b/app/src/main/play/listings/sv-SE/title.txt
new file mode 100644
index 000000000..31552f353
--- /dev/null
+++ b/app/src/main/play/listings/sv-SE/title.txt
@@ -0,0 +1 @@
+AntennaPod \ No newline at end of file
diff --git a/app/src/main/play/listings/zh-CN/full-description.txt b/app/src/main/play/listings/zh-CN/full-description.txt
new file mode 100644
index 000000000..a39b43eee
--- /dev/null
+++ b/app/src/main/play/listings/zh-CN/full-description.txt
@@ -0,0 +1,42 @@
+AntennaPod 是一款播客管理器和播放器,可让您即时收听数百万免费和付费的播客,从独立播客到大型出版商如BBC,NPR和CNN;使用 iTunes 播客数据库,OPML文件或简单的RSS URL轻松添加,导入和导出 feeds ;通过强大的自动化控制功能节省工作量,电池电量和移动数据使用情况,以便下载剧集(指定时间,间隔和 WiFi 网络)和删除剧集(根据您的收藏和延迟设置)。
+但最重要的是:下载,串流或安排节目并用可调节回放速度,章节支持和睡眠定时器以您喜欢的方式享受它们。
+
+AntennaPod由播客爱好者开发,在任意方面上都是自由的:开源,免费,无广告。
+
+<b>所有功能:</b><br>
+导入、整理与播放<br>
+&#8226; 通过 iTunes、gPodder.net、OPML 文件、RSS 或 Atom 链接添加和导入订阅
+&#8226;从任意地点管理回放:主屏widget,系统通知,耳塞和蓝牙控制装置
+&#8226;借助可调节回放速度,章节支持(Mp3、Vorbis注释和Podlove),记忆的回放位置和一个高级的睡眠定时器 (摇动设备来重置、调低音量并减慢回放)以您自己的方式享受收听播客节目
+#8226; 访问受密码保护的 feeds 和剧集
+&#8226; 充分利用分页 feeds (www.podlove.org/paged-feeds)
+
+保持更新,分享&欣赏
+&#8226; 通过将剧集标记为收藏来追踪最佳的剧集
+&#8226; 通过回放历史或搜索(标题和节目笔记)找到您需要的那期节目
+&#8226; 通过高级社交媒体和电邮选项,gPodder.net服务和导出OPML文件来分享节目和源
+
+一切尽在掌控<br>
+&#8226; 控制自动下载:选择源,排除移动网络,选择特定无线网络,要求手机充电并设定次数或间隔
+&#8226; 通过设定缓存节目的数量管理存储,智能删除(基于您的喜好和播放状态)并选择您偏好的存储位置
+&#8226; 使用对应您的语言的 AntennaPod (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br>
+&#8226; 使用浅色和深色主题以适应您的环境
+&#8226; 使用 gPodder.net 集成功能和 OPML 导出以备份您的订阅
+
+<b>加入 AntennaPod 社区!</b><br>
+志愿者正在积极开发 AntennaPod 。您也可以通过代码或评论做出贡献!
+
+GitHub 是申请增加功能,报告错误和贡献代码的地方:
+https://www.github.com/AntennaPod/AntennaPod
+
+对于所有志愿者来说,我们的谷歌社群是分享你的创意,收藏的播客瞬间和表达感激的地方:
+https://groups.google.com/forum/#!forum/antennapod
+
+抱有疑问或者想要向我们提供反馈?
+https://twitter.com/@AntennaPod
+
+Transifex 是与翻译者帮助项目的网站:
+https://www.transifex.com/antennapod/antennapod
+
+查看我们的测试程序以获得最新的功能列表:
+https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file
diff --git a/app/src/main/play/listings/zh-CN/short-description.txt b/app/src/main/play/listings/zh-CN/short-description.txt
index ab28b4df7..e6072fcf3 100644
--- a/app/src/main/play/listings/zh-CN/short-description.txt
+++ b/app/src/main/play/listings/zh-CN/short-description.txt
@@ -1 +1 @@
-简单易用、灵活的开源播客管理工具与播放器 \ No newline at end of file
+易用、灵活的开源播客管理工具与播放器 \ No newline at end of file
diff --git a/app/src/main/play/listings/zh-CN/title.txt b/app/src/main/play/listings/zh-CN/title.txt
new file mode 100644
index 000000000..31552f353
--- /dev/null
+++ b/app/src/main/play/listings/zh-CN/title.txt
@@ -0,0 +1 @@
+AntennaPod \ No newline at end of file
diff --git a/app/src/main/play/release-notes/en-US/default.txt b/app/src/main/play/release-notes/en-US/default.txt
index 7c1b36539..11371852d 100644
--- a/app/src/main/play/release-notes/en-US/default.txt
+++ b/app/src/main/play/release-notes/en-US/default.txt
@@ -4,4 +4,5 @@
- Added batch editing to the queue (by @ByteHamster)
- Added option to adapt remaining time to playback speed (by @CedricCabessa)
- Removed broken Flattr integration (by @ByteHamster)
-- Tons of bug fixes and performance improvements (by @andersonvom, @archibishop, @ByteHamster, @gaul, @jas14)
+- Added filter to "All episodes" list (by @jhunnius)
+- Tons of bug fixes and performance improvements
diff --git a/app/src/main/res/layout/addfeed.xml b/app/src/main/res/layout/addfeed.xml
index 011aa4c8b..a7f7d9f12 100644
--- a/app/src/main/res/layout/addfeed.xml
+++ b/app/src/main/res/layout/addfeed.xml
@@ -10,6 +10,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
+ android:focusableInTouchMode="true"
android:padding="8dp">
<android.support.v7.widget.CardView
@@ -27,6 +28,8 @@
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
+ android:layout_marginLeft="8dp"
+ android:layout_marginRight="8dp"
android:contentDescription="@string/search_podcast_hint"
app:srcCompat="?attr/action_search"
android:scaleType="center"/>
@@ -39,8 +42,10 @@
android:inputType="text"
android:imeOptions="actionSearch"
android:importantForAutofill="no"
- android:layout_marginLeft="8dp"
+ android:layout_marginStart="0dp"
+ android:layout_marginLeft="0dp"
android:layout_marginRight="8dp"
+ android:layout_marginEnd="8dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:hint="@string/search_podcast_hint"
@@ -109,16 +114,17 @@
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:padding="8dp"
android:layout_gravity="center_horizontal"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/advanced_search"
- android:layout_width="96dp"
+ android:layout_width="120dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
- android:padding="16dp"
+ android:padding="8dp"
android:background="?android:attr/selectableItemBackground">
<ImageView
@@ -127,8 +133,7 @@
android:contentDescription="@string/advanced_search"
app:srcCompat="?attr/action_search"
android:scaleType="center"
- android:layout_marginBottom="4dp"
- android:tint="?android:attr/textColorPrimary"/>
+ android:layout_marginBottom="4dp"/>
<TextView
android:layout_width="match_parent"
@@ -140,11 +145,11 @@
<LinearLayout
android:id="@+id/btn_opml_import"
- android:layout_width="96dp"
+ android:layout_width="120dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
- android:padding="16dp"
+ android:padding="8dp"
android:background="?android:attr/selectableItemBackground">
<ImageView
@@ -153,8 +158,7 @@
android:contentDescription="@string/opml_import_label"
app:srcCompat="?attr/av_download"
android:scaleType="center"
- android:layout_marginBottom="4dp"
- android:tint="?android:attr/textColorPrimary"/>
+ android:layout_marginBottom="4dp"/>
<TextView
android:layout_width="match_parent"
diff --git a/app/src/main/res/layout/all_episodes_fragment.xml b/app/src/main/res/layout/all_episodes_fragment.xml
index 89f900a1f..53636c2b6 100644
--- a/app/src/main/res/layout/all_episodes_fragment.xml
+++ b/app/src/main/res/layout/all_episodes_fragment.xml
@@ -1,19 +1,37 @@
<?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"
+ android:layout_height="match_parent">
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
+ <TextView
+ android:id="@+id/txtvInformation"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:paddingTop="2dp"
+ android:paddingBottom="2dp"
+ android:visibility="gone"
+ tools:text="(i) Information" />
<android.support.v7.widget.RecyclerView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ 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:scrollbarStyle="outsideOverlay"
+ app:fastScrollEnabled="true"
+ app:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
+ app:fastScrollHorizontalTrackDrawable="@drawable/line_drawable"
+ app:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
+ app:fastScrollVerticalTrackDrawable="@drawable/line_drawable"
tools:itemCount="13"
tools:listitem="@layout/new_episodes_listitem" />
@@ -21,12 +39,13 @@
android:id="@+id/progLoading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center"
+ android:gravity="center"
android:indeterminateOnly="true"
android:visibility="gone"
+ android:layout_centerInParent="true"
tools:visibility="gone"
tools:layout_width="match_parent"
tools:layout_height="64dp"
tools:background="@android:color/holo_red_light"/>
-</FrameLayout> \ No newline at end of file
+</RelativeLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/bug_report.xml b/app/src/main/res/layout/bug_report.xml
new file mode 100644
index 000000000..e97e85265
--- /dev/null
+++ b/app/src/main/res/layout/bug_report.xml
@@ -0,0 +1,28 @@
+<?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:padding="16dp">
+ <Button
+ android:id="@+id/btn_open_bug_tracker"
+ android:text="@string/open_bug_tracker"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+
+ <Button
+ android:id="@+id/btn_copy_log"
+ android:text="@string/copy_to_clipboard"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+
+ <TextView
+ android:layout_marginTop="8dp"
+ android:id="@+id/crash_report_logs"
+ android:textIsSelectable="true"
+ android:textSize="12sp"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"/>
+
+</LinearLayout>
diff --git a/app/src/main/res/layout/checkbox_do_not_show_again.xml b/app/src/main/res/layout/checkbox_do_not_show_again.xml
new file mode 100644
index 000000000..15f26e8b4
--- /dev/null
+++ b/app/src/main/res/layout/checkbox_do_not_show_again.xml
@@ -0,0 +1,17 @@
+<?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="vertical"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp">
+
+ <CheckBox
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/checkbox_do_not_show_again"
+ android:text="@string/checkbox_do_not_show_again"/>
+
+</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/downloaded_episodeslist_item.xml b/app/src/main/res/layout/downloaded_episodeslist_item.xml
index 65a08251f..3f8065466 100644
--- a/app/src/main/res/layout/downloaded_episodeslist_item.xml
+++ b/app/src/main/res/layout/downloaded_episodeslist_item.xml
@@ -17,7 +17,7 @@
android:layout_marginTop="@dimen/listitem_threeline_verticalpadding"
android:contentDescription="@string/cover_label"
android:scaleType="centerCrop"
- tools:src="@drawable/ic_stat_antenna_default"
+ tools:src="@drawable/ic_antenna"
tools:background="@android:color/holo_green_dark"/>
diff --git a/app/src/main/res/layout/episodes_apply_action_fragment.xml b/app/src/main/res/layout/episodes_apply_action_fragment.xml
index 984e960d8..ad453afbe 100644
--- a/app/src/main/res/layout/episodes_apply_action_fragment.xml
+++ b/app/src/main/res/layout/episodes_apply_action_fragment.xml
@@ -29,17 +29,14 @@
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
- android:elevation="@dimen/sd_close_elevation"
- tools:ignore="UnusedAttribute">
- <!-- android:elevation:
- 1. Needs to match the speed dial's minimal elevation,
- or the speed dial can't be clicked at all
- -->
+ android:elevation="@dimen/sd_open_elevation"
+ tools:ignore="UnusedAttribute" >
+
<com.leinardi.android.speeddial.SpeedDialView
android:id="@+id/fabSD"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- app:sdMainFabClosedSrc="@drawable/ic_fab_edit"
+ app:sdMainFabClosedSrc="?attr/batch_edit_fab_icon"
app:sdOverlayLayout="@id/fabSDOverlay"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
diff --git a/app/src/main/res/layout/feeditem_fragment.xml b/app/src/main/res/layout/feeditem_fragment.xml
index 78c0b3b16..b047b3da0 100644
--- a/app/src/main/res/layout/feeditem_fragment.xml
+++ b/app/src/main/res/layout/feeditem_fragment.xml
@@ -36,7 +36,8 @@
android:layout_marginBottom="16dp"
android:contentDescription="@string/cover_label"
android:gravity="center_vertical"
- tools:src="@drawable/ic_stat_antenna_default"
+ android:foreground="?attr/selectableItemBackground"
+ tools:src="@drawable/ic_antenna"
tools:background="@android:color/holo_green_dark" />
<TextView
@@ -47,6 +48,7 @@
android:layout_alignTop="@id/imgvCover"
android:layout_toRightOf="@id/imgvCover"
android:layout_toEndOf="@id/imgvCover"
+ android:foreground="?attr/selectableItemBackground"
tools:text="Podcast title"
tools:background="@android:color/holo_green_dark" />
diff --git a/app/src/main/res/layout/feeditemlist_header.xml b/app/src/main/res/layout/feeditemlist_header.xml
index e1f451e9e..596135d88 100644
--- a/app/src/main/res/layout/feeditemlist_header.xml
+++ b/app/src/main/res/layout/feeditemlist_header.xml
@@ -27,7 +27,7 @@
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:contentDescription="@string/cover_label"
- tools:src="@drawable/ic_stat_antenna_default"
+ tools:src="@drawable/ic_antenna"
tools:background="@android:color/holo_green_dark"/>
<ImageButton
diff --git a/app/src/main/res/layout/gpodnet_podcast_listitem.xml b/app/src/main/res/layout/gpodnet_podcast_listitem.xml
index 27a8bbdca..6e02fa090 100644
--- a/app/src/main/res/layout/gpodnet_podcast_listitem.xml
+++ b/app/src/main/res/layout/gpodnet_podcast_listitem.xml
@@ -23,7 +23,7 @@
android:contentDescription="@string/cover_label"
android:cropToPadding="true"
android:scaleType="fitXY"
- tools:src="@drawable/ic_stat_antenna_default"
+ tools:src="@drawable/ic_antenna"
tools:background="@android:color/holo_green_dark" />
<LinearLayout
diff --git a/app/src/main/res/layout/itunes_podcast_listitem.xml b/app/src/main/res/layout/itunes_podcast_listitem.xml
index 4848563b1..b2411c5df 100644
--- a/app/src/main/res/layout/itunes_podcast_listitem.xml
+++ b/app/src/main/res/layout/itunes_podcast_listitem.xml
@@ -25,7 +25,7 @@
android:cropToPadding="true"
android:scaleType="fitXY"
tools:background="@android:color/holo_green_dark"
- tools:src="@drawable/ic_stat_antenna_default" />
+ tools:src="@drawable/ic_antenna" />
<LinearLayout
android:layout_width="match_parent"
diff --git a/app/src/main/res/layout/mediaplayerinfo_activity.xml b/app/src/main/res/layout/mediaplayerinfo_activity.xml
index a6427e985..c4217db54 100644
--- a/app/src/main/res/layout/mediaplayerinfo_activity.xml
+++ b/app/src/main/res/layout/mediaplayerinfo_activity.xml
@@ -155,11 +155,11 @@
android:layout_marginTop="-8dp"
android:gravity="center"
android:text="30"
- android:textSize="10sp"
+ android:textSize="12sp"
android:textColor="?android:attr/textColorSecondary"
android:clickable="false"/>
- <Button
+ <ImageButton
android:id="@+id/butPlaybackSpeed"
android:layout_width="@dimen/audioplayer_playercontrols_length"
android:layout_height="@dimen/audioplayer_playercontrols_length"
@@ -167,13 +167,28 @@
android:layout_toStartOf="@id/butRev"
android:background="?attr/selectableItemBackground"
android:contentDescription="@string/set_playback_speed_label"
- android:src="?attr/av_fast_forward"
- android:textSize="@dimen/text_size_medium"
- android:textAllCaps="false"
- android:maxLines="1"
+ android:src="?attr/av_speed"
+ android:scaleType="fitCenter"
+ tools:src="@drawable/ic_playback_speed_white"
tools:visibility="gone"
tools:background="@android:color/holo_green_dark" />
+ <TextView
+ android:id="@+id/txtvPlaybackSpeed"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/butPlaybackSpeed"
+ android:layout_alignLeft="@id/butPlaybackSpeed"
+ android:layout_alignStart="@id/butPlaybackSpeed"
+ android:layout_alignRight="@id/butPlaybackSpeed"
+ android:layout_alignEnd="@id/butPlaybackSpeed"
+ android:layout_marginTop="-8dp"
+ android:gravity="center"
+ android:text="1.00"
+ android:textSize="12sp"
+ android:textColor="?android:attr/textColorSecondary"
+ android:clickable="false"/>
+
<ImageButton
android:id="@+id/butCastDisconnect"
android:layout_width="@dimen/audioplayer_playercontrols_length"
@@ -216,7 +231,7 @@
android:layout_marginTop="-8dp"
android:gravity="center"
android:text="30"
- android:textSize="10sp"
+ android:textSize="12sp"
android:textColor="?android:attr/textColorSecondary"
android:clickable="false"/>
diff --git a/app/src/main/res/layout/nav_feedlistitem.xml b/app/src/main/res/layout/nav_feedlistitem.xml
index 816870d1c..52833b3cd 100644
--- a/app/src/main/res/layout/nav_feedlistitem.xml
+++ b/app/src/main/res/layout/nav_feedlistitem.xml
@@ -25,7 +25,7 @@
android:scaleType="centerCrop"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
- tools:src="@drawable/ic_stat_antenna_default"
+ tools:src="@drawable/ic_antenna"
tools:background="@android:color/holo_green_dark"/>
<TextView
diff --git a/app/src/main/res/layout/queue_listitem.xml b/app/src/main/res/layout/queue_listitem.xml
index 6b41b68d5..1dcc34bce 100644
--- a/app/src/main/res/layout/queue_listitem.xml
+++ b/app/src/main/res/layout/queue_listitem.xml
@@ -51,7 +51,7 @@
android:layout_height="@dimen/thumbnail_length_queue_item"
android:layout_centerVertical="true"
android:contentDescription="@string/cover_label"
- tools:src="@drawable/ic_stat_antenna_default"
+ tools:src="@drawable/ic_antenna"
tools:background="@android:color/holo_green_dark"/>
</RelativeLayout>
diff --git a/app/src/main/res/layout/searchlist_item.xml b/app/src/main/res/layout/searchlist_item.xml
index 50374c737..4a055fea9 100644
--- a/app/src/main/res/layout/searchlist_item.xml
+++ b/app/src/main/res/layout/searchlist_item.xml
@@ -18,7 +18,7 @@
android:layout_marginStart="@dimen/listitem_threeline_horizontalpadding"
android:contentDescription="@string/cover_label"
android:scaleType="centerCrop"
- tools:src="@drawable/ic_stat_antenna_default"
+ tools:src="@drawable/ic_antenna"
tools:background="@android:color/holo_green_dark"/>
<LinearLayout
diff --git a/app/src/main/res/layout/statistics_listitem.xml b/app/src/main/res/layout/statistics_listitem.xml
index b186add9e..f52aa73e0 100644
--- a/app/src/main/res/layout/statistics_listitem.xml
+++ b/app/src/main/res/layout/statistics_listitem.xml
@@ -23,7 +23,7 @@
android:scaleType="centerCrop"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
- tools:src="@drawable/ic_stat_antenna_default"
+ tools:src="@drawable/ic_antenna"
tools:background="@android:color/holo_green_dark"/>
<TextView
diff --git a/app/src/main/res/menu/allepisodes_context.xml b/app/src/main/res/menu/allepisodes_context.xml
deleted file mode 100644
index 907bc9334..000000000
--- a/app/src/main/res/menu/allepisodes_context.xml
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-
- <item
- android:id="@id/skip_episode_item"
- android:menuCategory="container"
- android:title="@string/skip_episode_label" />
-
-
- <item
- android:id="@+id/remove_new_flag_item"
- android:menuCategory="container"
- android:title="@string/remove_new_flag_label" />
-
- <item
- android:id="@+id/mark_read_item"
- android:menuCategory="container"
- android:title="@string/mark_read_label" />
- <item
- android:id="@+id/mark_unread_item"
- android:menuCategory="container"
- android:title="@string/mark_unread_label" />
-
- <item
- android:id="@+id/add_to_queue_item"
- android:menuCategory="container"
- android:title="@string/add_to_queue_label" />
- <item
- android:id="@+id/remove_from_queue_item"
- android:menuCategory="container"
- android:title="@string/remove_from_queue_label" />
- <item
- android:id="@+id/add_to_favorites_item"
- android:menuCategory="container"
- android:title="@string/add_to_favorite_label" />
- <item
- android:id="@+id/remove_from_favorites_item"
- android:menuCategory="container"
- android:title="@string/remove_from_favorite_label" />
- <item
- android:id="@+id/reset_position"
- android:menuCategory="container"
- android:title="@string/reset_position" />
-
- <item
- android:id="@+id/activate_auto_download"
- android:menuCategory="container"
- android:title="@string/activate_auto_download" />
- <item
- android:id="@+id/deactivate_auto_download"
- android:menuCategory="container"
- android:title="@string/deactivate_auto_download" />
-
- <item
- android:id="@+id/visit_website_item"
- android:menuCategory="container"
- android:title="@string/visit_website_label" />
- <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>
- </item>
-</menu> \ No newline at end of file
diff --git a/app/src/main/res/menu/episodes.xml b/app/src/main/res/menu/episodes.xml
index 23c8f862a..1e1aa8f56 100644
--- a/app/src/main/res/menu/episodes.xml
+++ b/app/src/main/res/menu/episodes.xml
@@ -18,10 +18,19 @@
android:icon="?attr/navigation_refresh"/>
<item
+ android:id="@+id/filter_items"
+ android:icon="?attr/ic_filter"
+ android:menuCategory="container"
+ android:title="@string/filter"
+ android:visible="false"
+ custom:showAsAction="ifRoom"/>
+
+ <item
android:id="@+id/mark_all_read_item"
android:title="@string/mark_all_read_label"
android:menuCategory="container"
custom:showAsAction="collapseActionView"
+ android:visible="false"
android:icon="?attr/navigation_accept"/>
<item
@@ -29,6 +38,7 @@
android:title="@string/remove_all_new_flags_label"
android:menuCategory="container"
custom:showAsAction="collapseActionView"
+ android:visible="false"
android:icon="?attr/navigation_accept"/>
</menu>
diff --git a/app/src/main/res/menu/feedinfo.xml b/app/src/main/res/menu/feedinfo.xml
index 300068007..f20d679a5 100644
--- a/app/src/main/res/menu/feedinfo.xml
+++ b/app/src/main/res/menu/feedinfo.xml
@@ -11,7 +11,7 @@
<item
android:id="@+id/share_link_item"
custom:showAsAction="collapseActionView"
- android:title="@string/share_link_label">
+ android:title="@string/share_website_url_label">
</item>
<item
android:id="@+id/share_download_url_item"
diff --git a/app/src/main/res/menu/feeditem_options.xml b/app/src/main/res/menu/feeditem_options.xml
index 0801b79a1..e415ff85a 100644
--- a/app/src/main/res/menu/feeditem_options.xml
+++ b/app/src/main/res/menu/feeditem_options.xml
@@ -9,6 +9,11 @@
</item>
<item
+ android:id="@+id/remove_new_flag_item"
+ custom:showAsAction="collapseActionView"
+ android:title="@string/remove_new_flag_label" />
+
+ <item
android:id="@+id/mark_read_item"
custom:showAsAction="collapseActionView"
android:title="@string/mark_read_label">
diff --git a/app/src/main/res/menu/feeditemlist_context.xml b/app/src/main/res/menu/feeditemlist_context.xml
index df13cb027..6e4966206 100644
--- a/app/src/main/res/menu/feeditemlist_context.xml
+++ b/app/src/main/res/menu/feeditemlist_context.xml
@@ -8,6 +8,11 @@
android:title="@string/skip_episode_label" />
<item
+ android:id="@+id/remove_new_flag_item"
+ android:menuCategory="container"
+ android:title="@string/remove_new_flag_label" />
+
+ <item
android:id="@+id/mark_read_item"
android:menuCategory="container"
android:title="@string/mark_read_label" />
diff --git a/app/src/main/res/menu/feedlist.xml b/app/src/main/res/menu/feedlist.xml
index e62fc9d36..4144c392f 100644
--- a/app/src/main/res/menu/feedlist.xml
+++ b/app/src/main/res/menu/feedlist.xml
@@ -33,7 +33,7 @@
<item
android:id="@+id/action_search"
android:icon="?attr/action_search"
- custom:showAsAction="always"
+ custom:showAsAction="always|collapseActionView"
custom:actionViewClass="android.support.v7.widget.SearchView"
android:title="@string/search_label"/>
@@ -49,7 +49,7 @@
android:id="@+id/share_link_item"
android:menuCategory="container"
custom:showAsAction="collapseActionView"
- android:title="@string/share_link_label">
+ android:title="@string/share_website_url_label">
</item>
<item
android:id="@+id/share_download_url_item"
diff --git a/app/src/main/res/menu/mediaplayer.xml b/app/src/main/res/menu/mediaplayer.xml
index 44d511ee4..055951760 100644
--- a/app/src/main/res/menu/mediaplayer.xml
+++ b/app/src/main/res/menu/mediaplayer.xml
@@ -35,6 +35,14 @@
</item>
<item
+ android:id="@+id/open_feed_item"
+ android:icon="?attr/feed"
+ custom:showAsAction="collapseActionView"
+ android:title="@string/open_podcast"
+ android:visible="false">
+ </item>
+
+ <item
android:id="@+id/visit_website_item"
android:icon="?attr/location_web_site"
custom:showAsAction="collapseActionView"
diff --git a/app/src/main/res/menu/queue_context.xml b/app/src/main/res/menu/queue_context.xml
index e1c3e6216..522e712e2 100644
--- a/app/src/main/res/menu/queue_context.xml
+++ b/app/src/main/res/menu/queue_context.xml
@@ -11,77 +11,6 @@
android:id="@+id/move_to_bottom_item"
android:menuCategory="container"
android:title="@string/move_to_bottom_label" />
+ <!-- rest of the menu items can be found in the generic feeditemlist_context.xml -->
- <item
- android:id="@+id/mark_read_item"
- android:menuCategory="container"
- android:title="@string/mark_read_label" />
-
- <item
- android:id="@+id/mark_unread_item"
- android:menuCategory="container"
- android:title="@string/mark_unread_label" />
-
- <item
- android:id="@+id/remove_from_queue_item"
- android:menuCategory="container"
- android:title="@string/remove_from_queue_label" />
- <item
- android:id="@+id/remove_item"
- android:menuCategory="container"
- android:title="@string/delete_label" />
-
- <item
- android:id="@+id/add_to_favorites_item"
- android:menuCategory="container"
- android:title="@string/add_to_favorite_label" />
- <item
- android:id="@+id/remove_from_favorites_item"
- android:menuCategory="container"
- android:title="@string/remove_from_favorite_label" />
- <item
- android:id="@+id/reset_position"
- android:menuCategory="container"
- android:title="@string/reset_position" />
-
- <item
- android:id="@+id/activate_auto_download"
- android:menuCategory="container"
- android:title="@string/activate_auto_download" />
- <item
- android:id="@+id/deactivate_auto_download"
- android:menuCategory="container"
- android:title="@string/deactivate_auto_download" />
-
- <item
- android:id="@+id/visit_website_item"
- android:menuCategory="container"
- android:title="@string/visit_website_label" />
- <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>
- </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 f39e0ac97..1780592d5 100644
--- a/app/src/main/res/menu/subscriptions.xml
+++ b/app/src/main/res/menu/subscriptions.xml
@@ -3,6 +3,13 @@
xmlns:custom="http://schemas.android.com/apk/res-auto">
<item
+ android:id="@+id/refresh_item"
+ android:title="@string/refresh_label"
+ android:menuCategory="container"
+ custom:showAsAction="always"
+ android:icon="?attr/navigation_refresh"/>
+
+ <item
android:id="@+id/subscription_num_columns"
android:title="@string/subscription_num_columns"
custom:showAsAction="never">
diff --git a/app/src/main/res/values-w300dp/dimens-fabspeeddial.xml b/app/src/main/res/values-w300dp/dimens-fabspeeddial.xml
index e531395c0..1b90da786 100644
--- a/app/src/main/res/values-w300dp/dimens-fabspeeddial.xml
+++ b/app/src/main/res/values-w300dp/dimens-fabspeeddial.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
-<resources>
+<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">240dp</dimen>
+ <dimen name="sd_label_max_width" tools:ignore="MissingDefaultResource">240dp</dimen>
</resources>
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
index f45847e54..37707ead6 100644
--- a/app/src/main/res/xml/preferences.xml
+++ b/app/src/main/res/xml/preferences.xml
@@ -1,9 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
- xmlns:android="http://schemas.android.com/apk/res/android">
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:search="http://schemas.android.com/apk/res-auto">
<com.bytehamster.lib.preferencesearch.SearchPreference
- android:key="searchPreference" />
+ android:key="searchPreference"
+ search:textHint="@string/preference_search_hint"
+ search:textNoResults="@string/preference_search_no_results"
+ search:textClearHistory="@string/preference_search_clear_history" />
<Preference
android:key="prefScreenInterface"
@@ -39,16 +43,14 @@
<Preference
android:key="prefFaq"
android:title="@string/pref_faq"
- android:icon="?attr/ic_question_answer" />
-
+ android:icon="?attr/ic_questionmark" />
<Preference
- android:key="prefKnownIssues"
- android:title="@string/pref_known_issues"
- android:icon="?attr/ic_known_issues" />
+ android:key="prefViewMailingList"
+ android:title="@string/view_mailing_list"
+ android:icon="?attr/ic_chat" />
<Preference
- android:key="prefSendCrashReport"
- android:title="@string/crash_report_title"
- android:summary="@string/crash_report_sum"
+ android:key="prefSendBugReport"
+ android:title="@string/bug_report_title"
android:icon="?attr/ic_bug" />
<Preference
android:key="prefAbout"
diff --git a/app/src/main/res/xml/preferences_user_interface.xml b/app/src/main/res/xml/preferences_user_interface.xml
index 1d970a5f7..c48e9adc8 100644
--- a/app/src/main/res/xml/preferences_user_interface.xml
+++ b/app/src/main/res/xml/preferences_user_interface.xml
@@ -10,7 +10,7 @@
android:title="@string/pref_set_theme_title"
android:key="prefTheme"
android:summary="@string/pref_set_theme_sum"
- android:defaultValue="0"
+ android:defaultValue="system"
app:useStockLayout="true"/>
<Preference
android:key="prefHiddenDrawerItems"
diff --git a/app/src/main/templates/about.html b/app/src/main/templates/about.html
index 05d1b6e28..fd70ab549 100644
--- a/app/src/main/templates/about.html
+++ b/app/src/main/templates/about.html
@@ -83,7 +83,8 @@
Created by Daniel Oeh<br />
Copyright &copy; 2012-@year@<br />
AntennaPod Contributors <a href="CONTRIBUTORS.txt">(View)</a><br />
-Licensed under the MIT License <a href="LICENSE.txt">(View)</a>
+Licensed under the MIT License <a href="LICENSE.txt">(View)</a><br />
+Privacy Policy <a href="https://antennapod.org/privacy.html">(View)</a>
</div>
<h1>Used libraries</h1>
@@ -104,6 +105,11 @@ by Google, licensed under the Apache 2.0 license <a href="LICENSE_APACHE-2.0.txt
</div>
<div class="card">
+ <h2>Floating Action Button Speed Dial <a href="https://github.com/leinardi/FloatingActionButtonSpeedDial">(Link)</a></h2>
+ by Roberto Leinardi, licensed under the Apache 2.0 license <a href="LICENSE_APACHE-2.0.txt">(View)</a>
+</div>
+
+<div class="card">
<h2>Glide <a href="https://github.com/bumptech/glide/">(Link)</a></h2>
licensed under the Simplified BSD license <a href="LICENSE_GLIDE.txt">(View)</a>
</div>
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 87304b3d6..caca8a6e3 100644
--- a/app/src/play/java/de/danoeh/antennapod/activity/CastEnabledActivity.java
+++ b/app/src/play/java/de/danoeh/antennapod/activity/CastEnabledActivity.java
@@ -29,17 +29,34 @@ public abstract class CastEnabledActivity extends AppCompatActivity
implements SharedPreferences.OnSharedPreferenceChangeListener {
public static final String TAG = "CastEnabledActivity";
- protected CastManager castManager;
- protected SwitchableMediaRouteActionProvider mediaRouteActionProvider;
+ private CastConsumer castConsumer;
+ private CastManager castManager;
+
+ private SwitchableMediaRouteActionProvider mediaRouteActionProvider;
private final CastButtonVisibilityManager castButtonVisibilityManager = new CastButtonVisibilityManager();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ if (!CastManager.isInitialized()) {
+ return;
+ }
+
PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).
registerOnSharedPreferenceChangeListener(this);
+ castConsumer = new DefaultCastConsumer() {
+ @Override
+ public void onApplicationConnected(ApplicationMetadata appMetadata, String sessionId, boolean wasLaunched) {
+ onCastConnectionChanged(true);
+ }
+
+ @Override
+ public void onDisconnected() {
+ onCastConnectionChanged(false);
+ }
+ };
castManager = CastManager.getInstance();
castManager.addCastConsumer(castConsumer);
castButtonVisibilityManager.setPrefEnabled(UserPreferences.isCastEnabled());
@@ -48,6 +65,10 @@ public abstract class CastEnabledActivity extends AppCompatActivity
@Override
protected void onDestroy() {
+ if (!CastManager.isInitialized()) {
+ super.onDestroy();
+ return;
+ }
PreferenceManager.getDefaultSharedPreferences(getApplicationContext())
.unregisterOnSharedPreferenceChangeListener(this);
castManager.removeCastConsumer(castConsumer);
@@ -58,6 +79,9 @@ public abstract class CastEnabledActivity extends AppCompatActivity
@CallSuper
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
+ if (!CastManager.isInitialized()) {
+ return true;
+ }
getMenuInflater().inflate(R.menu.cast_enabled, menu);
castButtonVisibilityManager.setMenu(menu);
return true;
@@ -67,6 +91,10 @@ public abstract class CastEnabledActivity extends AppCompatActivity
@CallSuper
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
+ if (!CastManager.isInitialized()) {
+ return true;
+ }
+
MenuItem mediaRouteButton = menu.findItem(R.id.media_route_menu_item);
if (mediaRouteButton == null) {
Log.wtf(TAG, "MediaRoute item could not be found on the menu!", new Exception());
@@ -83,15 +111,22 @@ public abstract class CastEnabledActivity extends AppCompatActivity
@Override
protected void onResume() {
super.onResume();
+ if (!CastManager.isInitialized()) {
+ return;
+ }
castButtonVisibilityManager.setResumed(true);
}
@Override
protected void onPause() {
super.onPause();
+ if (!CastManager.isInitialized()) {
+ return;
+ }
castButtonVisibilityManager.setResumed(false);
}
+
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (UserPreferences.PREF_CAST_ENABLED.equals(key)) {
@@ -105,18 +140,6 @@ public abstract class CastEnabledActivity extends AppCompatActivity
}
}
- CastConsumer castConsumer = new DefaultCastConsumer() {
- @Override
- public void onApplicationConnected(ApplicationMetadata appMetadata, String sessionId, boolean wasLaunched) {
- onCastConnectionChanged(true);
- }
-
- @Override
- public void onDisconnected() {
- onCastConnectionChanged(false);
- }
- };
-
private void onCastConnectionChanged(boolean connected) {
if (connected) {
castButtonVisibilityManager.onConnected();
@@ -133,6 +156,9 @@ public abstract class CastEnabledActivity extends AppCompatActivity
* @param showAsAction refer to {@link MenuItem#setShowAsAction(int)}
*/
public final void requestCastButton(int showAsAction) {
+ if (!CastManager.isInitialized()) {
+ return;
+ }
castButtonVisibilityManager.requestCastButton(showAsAction);
}
diff --git a/app/src/play/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java b/app/src/play/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java
index c9d52df0c..0e69da61e 100644
--- a/app/src/play/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java
+++ b/app/src/play/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java
@@ -1,8 +1,13 @@
package de.danoeh.antennapod.preferences;
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.support.v7.app.AlertDialog;
+
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
+import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.fragment.preferences.PlaybackPreferencesFragment;
@@ -18,6 +23,7 @@ public class PreferenceControllerFlavorHelper {
final int googlePlayServicesCheck = GoogleApiAvailability.getInstance()
.isGooglePlayServicesAvailable(ui.getActivity());
if (googlePlayServicesCheck == ConnectionResult.SUCCESS) {
+ displayRestartRequiredDialog(ui.requireContext());
return true;
} else {
GoogleApiAvailability.getInstance()
@@ -29,4 +35,13 @@ public class PreferenceControllerFlavorHelper {
return true;
});
}
+
+ private static void displayRestartRequiredDialog(@NonNull Context context) {
+ AlertDialog.Builder dialog = new AlertDialog.Builder(context);
+ dialog.setTitle(android.R.string.dialog_alert_title);
+ dialog.setMessage(R.string.pref_restart_required);
+ dialog.setPositiveButton(android.R.string.ok, null);
+ dialog.setCancelable(false);
+ dialog.show();
+ }
}
diff --git a/artwork/feature-graphic.svg b/artwork/feature-graphic.svg
index 69e7902ec..c8ed16012 100644
--- a/artwork/feature-graphic.svg
+++ b/artwork/feature-graphic.svg
@@ -14,9 +14,9 @@
viewBox="0 0 270.93333 132.29167"
version="1.1"
id="svg8"
- inkscape:version="0.92.2 2405546, 2018-03-11"
+ inkscape:version="0.92.4 5da689c313, 2019-01-14"
sodipodi:docname="feature-graphic.svg"
- inkscape:export-filename="../app/src/main/play/en-US/listing/featureGraphic/feature-graphic.png"
+ inkscape:export-filename="/tmp/antennapod.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
<defs
@@ -28,18 +28,18 @@
borderopacity="1"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="0.62493324"
- inkscape:cx="475.1951"
- inkscape:cy="288.63643"
+ inkscape:zoom="0.31246662"
+ inkscape:cx="546.85547"
+ inkscape:cy="197.36023"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
- inkscape:window-width="1600"
- inkscape:window-height="835"
+ inkscape:window-width="1676"
+ inkscape:window-height="982"
inkscape:window-x="0"
- inkscape:window-y="0"
- inkscape:window-maximized="1"
+ inkscape:window-y="30"
+ inkscape:window-maximized="0"
borderlayer="true"
inkscape:showpageshadow="false" />
<metadata
@@ -50,7 +50,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
+ <dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
@@ -60,59 +60,65 @@
id="layer1"
transform="translate(0,-164.70832)">
<path
- style="fill:#42a5f5;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M 241.57724,93.688693 153.83631,322.70237 129.26786,237.27975 Z"
- id="path4549"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccc" />
- <path
- style="fill:#90caf9;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 129.26786,237.27975 v 0 l 77.66392,-84.70466 -101.47643,-10.54534 z"
- id="path4547"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccc" />
- <path
- style="fill:#64b5f6;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 111.88095,149.96725 v 0 L 179.16071,374.10712 67.657738,209.68749 Z"
- id="path4545"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccc" />
- <path
- style="fill:#0277bd;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M -5.2916667,329.12796 -5.6696427,217.24701 127.37797,308.71725 Z"
- id="path4537"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccc" />
- <path
- style="fill:#90caf9;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 71.059523,210.44344 -3.401785,-0.75595 -79.741849,5.15409 173.172371,131.21195 z"
- id="path4539"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccc" />
- <path
- style="fill:#2196f3;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m -5.6696427,217.24701 v 0 L 71.059523,210.44344 110.36905,157.90475 -14.363095,139.00594 Z"
- id="path4541"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccccc" />
- <path
- style="fill:#2196f3;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 293.68749,172.26785 -76.35118,94.87201 58.5863,58.9643 z"
- id="path4553"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccc" />
- <path
- style="fill:#64b5f6;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M 184.64136,236.90177 378.4505,95.09124 217.33631,267.13986 Z"
- id="path4555"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccc" />
- <path
- style="fill:#1976d2;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 216.58035,147.69939 77.48513,10.58333 -109.42412,78.61905 z"
- id="path4557"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccc" />
+ style="fill:#42a5f5;fill-opacity:1;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 755.81836 -67.398438 L 488.57227 274.28516 L 579.80078 591.48633 L 583.5957 591.48633 L 836.03125 -67.398438 L 755.81836 -67.398438 z "
+ transform="matrix(0.26458333,0,0,0.26458333,0,164.70832)"
+ id="path4549" />
+ <path
+ style="fill:#90caf9;fill-opacity:1;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 366.28125 -67.398438 L 488.57227 274.28516 L 802.67383 -67.398438 L 366.28125 -67.398438 z "
+ transform="matrix(0.26458333,0,0,0.26458333,0,164.70832)"
+ id="path4547" />
+ <path
+ style="fill:#0277bd;fill-opacity:1;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 1232.6035 -67.398438 L 1099.5723 82.640625 L 1016.1719 591.48633 L 1272.8418 591.48633 L 1272.8418 -67.398438 L 1232.6035 -67.398438 z "
+ transform="matrix(0.26458333,0,0,0.26458333,0,164.70832)"
+ id="path4537-2" />
+ <path
+ style="fill:#2196f3;fill-opacity:1;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 1110 28.572266 L 821.42773 387.14258 L 1024.4629 591.48633 L 1044.9961 591.48633 L 1110 28.572266 z "
+ transform="matrix(0.26458333,0,0,0.26458333,0,164.70832)"
+ id="path4553" />
+ <path
+ style="fill:#64b5f6;fill-opacity:1;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 1162.877 -67.398438 L 697.85742 272.85742 L 821.42773 387.14258 L 1247.082 -67.398438 L 1162.877 -67.398438 z "
+ transform="matrix(0.26458333,0,0,0.26458333,0,164.70832)"
+ id="path4555" />
+ <path
+ style="fill:#1565c0;fill-opacity:1;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.60962572"
+ d="M 697.85742 272.85742 L 583.23438 591.48633 L 1047.2734 591.48633 L 697.85742 272.85742 z "
+ transform="matrix(0.26458333,0,0,0.26458333,0,164.70832)"
+ id="path4551" />
+ <path
+ style="fill:#64b5f6;fill-opacity:1;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 422.85742 -55.714844 L 255.71484 170 L 541.55078 591.48633 L 617.12695 591.48633 L 422.85742 -55.714844 z "
+ transform="matrix(0.26458333,0,0,0.26458333,0,164.70832)"
+ id="path4545" />
+ <path
+ style="fill:#42a5f5;fill-opacity:1;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M -246.42578 20.019531 L -246.42578 591.48633 L -21.724609 591.48633 L -45.671875 175.87891 L -246.42578 20.019531 z "
+ transform="matrix(0.26458333,0,0,0.26458333,0,164.70832)"
+ id="path4549-3" />
+ <path
+ style="fill:#0277bd;fill-opacity:1;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M -45.671875 189.48047 L -166.46875 591.48633 L 500.89258 591.48633 L -45.671875 189.48047 z "
+ transform="matrix(0.26458333,0,0,0.26458333,0,164.70832)"
+ id="path4537" />
+ <path
+ style="fill:#90caf9;fill-opacity:1;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 255.71484 170 L -45.671875 189.48047 L 484.89258 591.48633 L 546.49219 591.48633 L 268.57227 172.85742 L 255.71484 170 z "
+ transform="matrix(0.26458333,0,0,0.26458333,0,164.70832)"
+ id="path4539" />
+ <path
+ style="fill:#2196f3;fill-opacity:1;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M -246.42578 -67.398438 L -246.42578 204.35742 L 268.57227 172.85742 L 434.69922 -67.398438 L -246.42578 -67.398438 z "
+ transform="matrix(0.26458333,0,0,0.26458333,0,164.70832)"
+ id="path4541" />
+ <path
+ style="fill:#1976d2;fill-opacity:1;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 819.36914 -67.398438 L 697.85742 272.85742 L 1168.3574 -67.398438 L 819.36914 -67.398438 z "
+ transform="matrix(0.26458333,0,0,0.26458333,0,164.70832)"
+ id="path4557" />
<path
id="path4603"
d="m 131.14882,195.24411 c -6.94441,0 -12.5,5.55559 -12.5,12.5 v 9.72225 a 4.1666667,4.1666667 0 0 0 4.16667,4.16667 h 4.16666 V 210.5219 h -5.55553 v -2.77779 a 9.722222,9.722222 0 0 1 9.7222,-9.72221 9.722222,9.722222 0 0 1 9.72226,9.72221 v 2.77779 h -5.55559 v 11.11113 h 4.16666 a 4.1666667,4.1666667 0 0 0 4.16667,-4.16667 v -9.72225 c 0,-6.94441 -5.59722,-12.5 -12.5,-12.5 z"
@@ -134,12 +140,6 @@
inkscape:connector-curvature="0"
style="opacity:0.5;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.47058702" />
<path
- style="fill:#1565c0;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.60962572"
- d="m 184.64136,236.90177 87.50149,77.8631 -118.30654,7.9375 z"
- id="path4551"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccc" />
- <path
id="path4636"
d="m 227.91014,264.36965 v -4.8611 a 1.3888889,1.3888889 0 0 0 -1.38887,-1.38887 H 209.8546 a 1.3888889,1.3888889 0 0 0 -1.38892,1.38887 v 13.88893 a 1.3888889,1.3888889 0 0 0 1.38892,1.38887 h 16.66667 a 1.3888889,1.3888889 0 0 0 1.38887,-1.38887 v -4.86116 l 5.55554,5.55559 v -15.27779 z"
inkscape:connector-curvature="0"
diff --git a/build.gradle b/build.gradle
index 2d917f31f..87a335dcc 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,7 +5,7 @@ buildscript {
mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.3.0'
+ classpath 'com.android.tools.build:gradle:3.5.0'
classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.8.5'
}
}
@@ -57,8 +57,8 @@ project.ext {
iconifyVersion = "2.2.2"
jsoupVersion = "1.11.2"
materialDialogsVersion = "0.9.0.2"
- okhttpVersion = "3.9.0"
- okioVersion = "1.14.0"
+ okhttpVersion = "3.12.5"
+ okioVersion = "1.17.4"
recyclerviewFlexibledividerVersion = "1.4.0"
robotiumSoloVersion = "5.6.3"
rxAndroidVersion = "2.1.0"
@@ -82,3 +82,14 @@ wrapper {
def doFreeBuild() {
return hasProperty("freeBuild")
}
+
+apply plugin: "checkstyle"
+checkstyle {
+ toolVersion '8.24'
+}
+
+task checkstyle(type: Checkstyle) {
+ classpath = files()
+ source "${project.rootDir}"
+ exclude("**/gen/**")
+}
diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml
new file mode 100644
index 000000000..0a5b47eb8
--- /dev/null
+++ b/config/checkstyle/checkstyle.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+<!DOCTYPE module PUBLIC
+ "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
+ "https://checkstyle.org/dtds/configuration_1_3.dtd">
+<module name = "Checker">
+ <property name="charset" value="UTF-8"/>
+
+ <property name="severity" value="error"/>
+
+ <property name="fileExtensions" value="java, xml"/>
+
+ <module name="TreeWalker">
+ <module name="OuterTypeFilename"/>
+ <module name="AvoidEscapedUnicodeCharacters">
+ <property name="allowEscapesForControlCharacters" value="true"/>
+ <property name="allowByTailComment" value="true"/>
+ <property name="allowNonPrintableEscapes" value="true"/>
+ </module>
+ <module name="AvoidStarImport"/>
+ <module name="OneTopLevelClass"/>
+ <module name="NoLineWrap"/>
+ <module name="EmptyBlock">
+ <property name="option" value="TEXT"/>
+ <property name="tokens"
+ value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
+ </module>
+ <module name="OneStatementPerLine"/>
+ <module name="FallThrough"/>
+ <module name="UpperEll"/>
+ <module name="ModifierOrder"/>
+ <module name="PackageName">
+ <property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
+ <message key="name.invalidPattern"
+ value="Package name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <module name="TypeName">
+ <message key="name.invalidPattern"
+ value="Type name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <module name="CatchParameterName">
+ <property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
+ <message key="name.invalidPattern"
+ value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <module name="ClassTypeParameterName">
+ <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
+ <message key="name.invalidPattern"
+ value="Class type name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <module name="MethodTypeParameterName">
+ <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
+ <message key="name.invalidPattern"
+ value="Method type name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <module name="InterfaceTypeParameterName">
+ <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
+ <message key="name.invalidPattern"
+ value="Interface type name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <module name="NoFinalizer"/>
+ <module name="GenericWhitespace">
+ <message key="ws.followed"
+ value="GenericWhitespace ''{0}'' is followed by whitespace."/>
+ <message key="ws.preceded"
+ value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
+ <message key="ws.illegalFollow"
+ value="GenericWhitespace ''{0}'' should followed by whitespace."/>
+ <message key="ws.notPreceded"
+ value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
+ </module>
+ <module name="AnnotationLocation">
+ <property name="id" value="AnnotationLocationMostCases"/>
+ <property name="tokens"
+ value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
+ </module>
+ <module name="AnnotationLocation">
+ <property name="id" value="AnnotationLocationVariables"/>
+ <property name="tokens" value="VARIABLE_DEF"/>
+ <property name="allowSamelineMultipleAnnotations" value="true"/>
+ </module>
+ </module>
+</module>
diff --git a/core/build.gradle b/core/build.gradle
index 133f1b262..8614d5589 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -76,7 +76,6 @@ dependencies {
annotationProcessor "org.greenrobot:eventbus-annotation-processor:$eventbusVersion"
implementation "io.reactivex.rxjava2:rxandroid:$rxAndroidVersion"
implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion"
- implementation "org.awaitility:awaitility:$awaitilityVersion"
implementation "com.google.android.exoplayer:exoplayer:$exoPlayerVersion"
implementation "com.github.AntennaPod:AntennaPod-AudioPlayer:$audioPlayerVersion"
@@ -92,6 +91,7 @@ dependencies {
System.out.println("core: free build hack, skipping some dependencies")
}
+ testImplementation "org.awaitility:awaitility:$awaitilityVersion"
testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-core:1.10.19'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
diff --git a/core/src/free/java/de/danoeh/antennapod/core/ClientConfig.java b/core/src/free/java/de/danoeh/antennapod/core/ClientConfig.java
index c17376639..03ce82140 100644
--- a/core/src/free/java/de/danoeh/antennapod/core/ClientConfig.java
+++ b/core/src/free/java/de/danoeh/antennapod/core/ClientConfig.java
@@ -7,6 +7,7 @@ import de.danoeh.antennapod.core.preferences.SleepTimerPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.danoeh.antennapod.core.util.NetworkUtils;
+import de.danoeh.antennapod.core.util.exception.RxJavaErrorHandlerSetup;
/**
* Stores callbacks for core classes like Services, DB classes etc. and other configuration variables.
@@ -34,7 +35,7 @@ public class ClientConfig {
private static boolean initialized = false;
public static synchronized void initialize(Context context) {
- if(initialized) {
+ if (initialized) {
return;
}
PodDBAdapter.init(context);
@@ -42,6 +43,7 @@ public class ClientConfig {
PlaybackPreferences.init(context);
NetworkUtils.init(context);
SleepTimerPreferences.init(context);
+ RxJavaErrorHandlerSetup.setupRxJavaErrorHandler();
initialized = true;
}
diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml
index 3b6edae42..7d84bdddb 100644
--- a/core/src/main/AndroidManifest.xml
+++ b/core/src/main/AndroidManifest.xml
@@ -9,6 +9,11 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.VIBRATE" />
+ <!-- ACCESS_FINE_LOCATION is needed only on Android 10+,
+ for Automatic Download Wifi filter's UI, which uses
+ WifiManager.WifiManager.getConfiguredNetworks()
+ -->
+ <uses-permission-sdk-23 android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
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 124fd3e64..24a71ec96 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
@@ -25,4 +25,8 @@ public class DownloadEvent {
"update=" + update +
'}';
}
+
+ public boolean hasChangedFeedUpdateStatus(boolean oldStatus) {
+ return oldStatus != update.feedIds.length > 0;
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java
deleted file mode 100644
index 4a591c996..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package de.danoeh.antennapod.core.event;
-
-import de.danoeh.antennapod.core.feed.FeedMedia;
-
-public class FeedMediaEvent {
-
- public enum Action {
- UPDATE
- }
-
- private final Action action;
- private final FeedMedia media;
-
- private FeedMediaEvent(Action action, FeedMedia media) {
- this.action = action;
- this.media = media;
- }
-
- public static FeedMediaEvent update(FeedMedia media) {
- return new FeedMediaEvent(Action.UPDATE, media);
- }
-
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/PlaybackPositionEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/PlaybackPositionEvent.java
new file mode 100644
index 000000000..3327d8a02
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/event/PlaybackPositionEvent.java
@@ -0,0 +1,19 @@
+package de.danoeh.antennapod.core.event;
+
+public class PlaybackPositionEvent {
+ private final int position;
+ private final int duration;
+
+ public PlaybackPositionEvent(int position, int duration) {
+ this.position = position;
+ this.duration = duration;
+ }
+
+ public int getPosition() {
+ return position;
+ }
+
+ public int getDuration() {
+ return duration;
+ }
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/ProgressEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/ProgressEvent.java
deleted file mode 100644
index 3769d6bb1..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/event/ProgressEvent.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package de.danoeh.antennapod.core.event;
-
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
-
-public class ProgressEvent {
-
- public enum Action {
- START, END
- }
-
- public final Action action;
- public final String message;
-
- private ProgressEvent(Action action, String message) {
- this.action = action;
- this.message = message;
- }
-
- public static ProgressEvent start(String message) {
- return new ProgressEvent(Action.START, message);
- }
-
- public static ProgressEvent end() {
- return new ProgressEvent(Action.END, null);
- }
-
- @Override
- public String toString() {
- return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
- .append("action", action)
- .append("message", message)
- .toString();
- }
-
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java
index b75e1630c..bb34e2c0f 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java
@@ -21,8 +21,12 @@ import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
import de.danoeh.antennapod.core.service.download.HttpDownloader;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.util.NetworkUtils;
-import okhttp3.*;
-import okhttp3.internal.http.RealResponseBody;
+import okhttp3.Interceptor;
+import okhttp3.OkHttpClient;
+import okhttp3.Protocol;
+import okhttp3.Request;
+import okhttp3.Response;
+import okhttp3.ResponseBody;
/**
* @see com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader
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 dfe056f14..f2c0c8fe3 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
@@ -4,7 +4,12 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
+import android.util.Log;
import de.danoeh.antennapod.core.feed.EventDistributor;
+import de.danoeh.antennapod.core.feed.FeedMedia;
+import de.danoeh.antennapod.core.feed.MediaType;
+import de.danoeh.antennapod.core.service.playback.PlayerStatus;
+import de.danoeh.antennapod.core.util.playback.Playable;
/**
* Provides access to preferences set by the playback service. A private
@@ -19,35 +24,35 @@ public class PlaybackPreferences implements SharedPreferences.OnSharedPreference
* Contains the feed id of the currently playing item if it is a FeedMedia
* object.
*/
- public static final String PREF_CURRENTLY_PLAYING_FEED_ID = "de.danoeh.antennapod.preferences.lastPlayedFeedId";
+ private static final String PREF_CURRENTLY_PLAYING_FEED_ID = "de.danoeh.antennapod.preferences.lastPlayedFeedId";
/**
* Contains the id of the currently playing FeedMedia object or
* NO_MEDIA_PLAYING if the currently playing media is no FeedMedia object.
*/
- public static final String PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID = "de.danoeh.antennapod.preferences.lastPlayedFeedMediaId";
+ private static final String PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID = "de.danoeh.antennapod.preferences.lastPlayedFeedMediaId";
/**
* Type of the media object that is currently being played. This preference
* is set to NO_MEDIA_PLAYING after playback has been completed and is set
* as soon as the 'play' button is pressed.
*/
- public static final String PREF_CURRENTLY_PLAYING_MEDIA = "de.danoeh.antennapod.preferences.currentlyPlayingMedia";
+ private static final String PREF_CURRENTLY_PLAYING_MEDIA = "de.danoeh.antennapod.preferences.currentlyPlayingMedia";
/**
* True if last played media was streamed.
*/
- public static final String PREF_CURRENT_EPISODE_IS_STREAM = "de.danoeh.antennapod.preferences.lastIsStream";
+ private static final String PREF_CURRENT_EPISODE_IS_STREAM = "de.danoeh.antennapod.preferences.lastIsStream";
/**
* True if last played media was a video.
*/
- public static final String PREF_CURRENT_EPISODE_IS_VIDEO = "de.danoeh.antennapod.preferences.lastIsVideo";
+ private static final String PREF_CURRENT_EPISODE_IS_VIDEO = "de.danoeh.antennapod.preferences.lastIsVideo";
/**
* The current player status as int.
*/
- public static final String PREF_CURRENT_PLAYER_STATUS = "de.danoeh.antennapod.preferences.currentPlayerStatus";
+ private static final String PREF_CURRENT_PLAYER_STATUS = "de.danoeh.antennapod.preferences.currentPlayerStatus";
/**
* Value of PREF_CURRENTLY_PLAYING_MEDIA if no media is playing.
@@ -87,10 +92,6 @@ public class PlaybackPreferences implements SharedPreferences.OnSharedPreference
}
}
- public static long getLastPlayedFeedId() {
- return prefs.getLong(PREF_CURRENTLY_PLAYING_FEED_ID, -1);
- }
-
public static long getCurrentlyPlayingMedia() {
return prefs.getLong(PREF_CURRENTLY_PLAYING_MEDIA, NO_MEDIA_PLAYING);
}
@@ -111,4 +112,60 @@ public class PlaybackPreferences implements SharedPreferences.OnSharedPreference
return prefs.getInt(PREF_CURRENT_PLAYER_STATUS, PLAYER_STATUS_OTHER);
}
+ public static void writeNoMediaPlaying() {
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putLong(PREF_CURRENTLY_PLAYING_MEDIA, NO_MEDIA_PLAYING);
+ editor.putLong(PREF_CURRENTLY_PLAYING_FEED_ID, NO_MEDIA_PLAYING);
+ editor.putLong(PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID, NO_MEDIA_PLAYING);
+ editor.putInt(PREF_CURRENT_PLAYER_STATUS, PLAYER_STATUS_OTHER);
+ editor.apply();
+ }
+
+ public static void writeMediaPlaying(Playable playable, PlayerStatus playerStatus, boolean stream) {
+ Log.d(TAG, "Writing playback preferences");
+ SharedPreferences.Editor editor = prefs.edit();
+
+ if (playable == null) {
+ writeNoMediaPlaying();
+ } else {
+ editor.putLong(PREF_CURRENTLY_PLAYING_MEDIA, playable.getPlayableType());
+ editor.putBoolean(PREF_CURRENT_EPISODE_IS_STREAM, stream);
+ editor.putBoolean(PREF_CURRENT_EPISODE_IS_VIDEO, playable.getMediaType() == MediaType.VIDEO);
+ if (playable instanceof FeedMedia) {
+ FeedMedia fMedia = (FeedMedia) playable;
+ editor.putLong(PREF_CURRENTLY_PLAYING_FEED_ID, fMedia.getItem().getFeed().getId());
+ editor.putLong(PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID, fMedia.getId());
+ } else {
+ editor.putLong(PREF_CURRENTLY_PLAYING_FEED_ID, NO_MEDIA_PLAYING);
+ editor.putLong(PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID, NO_MEDIA_PLAYING);
+ }
+ playable.writeToPreferences(editor);
+ }
+ editor.putInt(PREF_CURRENT_PLAYER_STATUS, getCurrentPlayerStatusAsInt(playerStatus));
+
+ editor.apply();
+ }
+
+ public static void writePlayerStatus(PlayerStatus playerStatus) {
+ Log.d(TAG, "Writing player status playback preferences");
+
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putInt(PREF_CURRENT_PLAYER_STATUS, getCurrentPlayerStatusAsInt(playerStatus));
+ editor.apply();
+ }
+
+ private static int getCurrentPlayerStatusAsInt(PlayerStatus playerStatus) {
+ int playerStatusAsInt;
+ switch (playerStatus) {
+ case PLAYING:
+ playerStatusAsInt = PLAYER_STATUS_PLAYING;
+ break;
+ case PAUSED:
+ playerStatusAsInt = PLAYER_STATUS_PAUSED;
+ break;
+ default:
+ playerStatusAsInt = PLAYER_STATUS_OTHER;
+ }
+ return playerStatusAsInt;
+ }
}
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 8d8c6e65d..787e32ccc 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
@@ -2,6 +2,7 @@ package de.danoeh.antennapod.core.preferences;
import android.content.Context;
import android.content.SharedPreferences;
+import android.content.res.Configuration;
import android.preference.PreferenceManager;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
@@ -109,6 +110,7 @@ public class UserPreferences {
public static final String PREF_MEDIA_PLAYER = "prefMediaPlayer";
public static final String PREF_MEDIA_PLAYER_EXOPLAYER = "exoplayer";
private static final String PREF_PLAYBACK_SPEED = "prefPlaybackSpeed";
+ private static final String PREF_VIDEO_PLAYBACK_SPEED = "prefVideoPlaybackSpeed";
public static final String PREF_PLAYBACK_SKIP_SILENCE = "prefSkipSilence";
private static final String PREF_FAST_FORWARD_SECS = "prefFastForwardSecs";
private static final String PREF_REWIND_SECS = "prefRewindSecs";
@@ -163,7 +165,7 @@ public class UserPreferences {
* @return R.style.Theme_AntennaPod_Light or R.style.Theme_AntennaPod_Dark
*/
public static int getTheme() {
- return readThemeValue(prefs.getString(PREF_THEME, "0"));
+ return readThemeValue(prefs.getString(PREF_THEME, "system"));
}
public static int getNoTitleTheme() {
@@ -319,8 +321,24 @@ public class UserPreferences {
return prefs.getBoolean(PREF_DELETE_REMOVES_FROM_QUEUE, false);
}
- public static String getPlaybackSpeed() {
- return prefs.getString(PREF_PLAYBACK_SPEED, "1.00");
+ public static float getPlaybackSpeed() {
+ try {
+ return Float.parseFloat(prefs.getString(PREF_PLAYBACK_SPEED, "1.00"));
+ } catch (NumberFormatException e) {
+ Log.e(TAG, Log.getStackTraceString(e));
+ UserPreferences.setPlaybackSpeed("1.00");
+ return 1.0f;
+ }
+ }
+
+ public static float getVideoPlaybackSpeed() {
+ try {
+ return Float.parseFloat(prefs.getString(PREF_VIDEO_PLAYBACK_SPEED, "1.00"));
+ } catch (NumberFormatException e) {
+ Log.e(TAG, Log.getStackTraceString(e));
+ UserPreferences.setVideoPlaybackSpeed("1.00");
+ return 1.0f;
+ }
}
public static boolean isSkipSilence() {
@@ -415,9 +433,9 @@ public class UserPreferences {
defaultValue.add("images");
Set<String> allowed = prefs.getStringSet(PREF_MOBILE_UPDATE, defaultValue);
if (allow) {
- allowed.remove(type);
- } else {
allowed.add(type);
+ } else {
+ allowed.remove(type);
}
prefs.edit().putStringSet(PREF_MOBILE_UPDATE, allowed).apply();
}
@@ -559,6 +577,12 @@ public class UserPreferences {
.apply();
}
+ public static void setVideoPlaybackSpeed(String speed) {
+ prefs.edit()
+ .putString(PREF_VIDEO_PLAYBACK_SPEED, speed)
+ .apply();
+ }
+
public static void setSkipSilence(boolean skipSilence) {
prefs.edit()
.putBoolean(PREF_PLAYBACK_SKIP_SILENCE, skipSilence)
@@ -598,7 +622,7 @@ public class UserPreferences {
.apply();
// when updating with an interval, we assume the user wants
// to update *now* and then every 'hours' interval thereafter.
- restartUpdateAlarm();
+ AutoUpdateManager.restartUpdateAlarm();
}
/**
@@ -608,7 +632,7 @@ public class UserPreferences {
prefs.edit()
.putString(PREF_UPDATE_INTERVAL, hourOfDay + ":" + minute)
.apply();
- restartUpdateAlarm();
+ AutoUpdateManager.restartUpdateAlarm();
}
public static void disableAutoUpdate() {
@@ -649,14 +673,18 @@ public class UserPreferences {
}
private static int readThemeValue(String valueFromPrefs) {
- switch (Integer.parseInt(valueFromPrefs)) {
- case 0:
+ switch (valueFromPrefs) {
+ case "0":
return R.style.Theme_AntennaPod_Light;
- case 1:
+ case "1":
return R.style.Theme_AntennaPod_Dark;
- case 2:
+ case "2":
return R.style.Theme_AntennaPod_TrueBlack;
default:
+ int nightMode = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
+ if (nightMode == Configuration.UI_MODE_NIGHT_YES) {
+ return R.style.Theme_AntennaPod_Dark;
+ }
return R.style.Theme_AntennaPod_Light;
}
}
@@ -854,26 +882,6 @@ public class UserPreferences {
return getUpdateTimeOfDay().length == 2;
}
- public static void restartUpdateAlarm() {
- if (isAutoUpdateDisabled()) {
- AutoUpdateManager.disableAutoUpdate();
- } else if (isAutoUpdateTimeOfDay()) {
- int[] timeOfDay = getUpdateTimeOfDay();
- Log.d(TAG, "timeOfDay: " + Arrays.toString(timeOfDay));
- AutoUpdateManager.restartUpdateTimeOfDayAlarm(timeOfDay[0], timeOfDay[1]);
- } else {
- long milliseconds = getUpdateInterval();
- AutoUpdateManager.restartUpdateIntervalAlarm(milliseconds);
- }
- }
-
- /**
- * Reads episode cache size as it is saved in the episode_cache_size_values array.
- */
- public static int readEpisodeCacheSize(String valueFromPrefs) {
- return readEpisodeCacheSizeInternal(valueFromPrefs);
- }
-
/**
* Evaluates whether Cast support (Chromecast, Audio Cast, etc) is enabled on the preferences.
*/
diff --git a/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java b/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java
index 126f12247..af0a0d426 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java
@@ -6,8 +6,7 @@ import android.content.Intent;
import android.util.Log;
import de.danoeh.antennapod.core.ClientConfig;
-import de.danoeh.antennapod.core.preferences.UserPreferences;
-import de.danoeh.antennapod.core.util.FeedUpdateUtils;
+import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
/**
* Refreshes all feeds when it receives an intent
@@ -20,7 +19,8 @@ public class FeedUpdateReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Received intent");
ClientConfig.initialize(context);
- FeedUpdateUtils.startAutoUpdate(context, null);
+
+ AutoUpdateManager.runOnce();
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedUpdateWorker.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedUpdateWorker.java
index efdb96dc1..87c18227b 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedUpdateWorker.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedUpdateWorker.java
@@ -2,17 +2,23 @@ package de.danoeh.antennapod.core.service;
import android.content.Context;
import android.support.annotation.NonNull;
+import android.util.Log;
+
import androidx.work.Worker;
import androidx.work.WorkerParameters;
+
import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.preferences.UserPreferences;
-import de.danoeh.antennapod.core.util.FeedUpdateUtils;
-import org.awaitility.Awaitility;
-
-import java.util.concurrent.atomic.AtomicBoolean;
+import de.danoeh.antennapod.core.storage.DBTasks;
+import de.danoeh.antennapod.core.util.NetworkUtils;
+import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
public class FeedUpdateWorker extends Worker {
+ private static final String TAG = "FeedUpdateWorker";
+
+ public static final String PARAM_RUN_ONCE = "runOnce";
+
public FeedUpdateWorker(@NonNull Context context, @NonNull WorkerParameters params) {
super(context, params);
}
@@ -20,16 +26,20 @@ public class FeedUpdateWorker extends Worker {
@Override
@NonNull
public Result doWork() {
+ final boolean isRunOnce = getInputData().getBoolean(PARAM_RUN_ONCE, false);
+ Log.d(TAG, "doWork() : isRunOnce = " + isRunOnce);
ClientConfig.initialize(getApplicationContext());
- AtomicBoolean finished = new AtomicBoolean(false);
- FeedUpdateUtils.startAutoUpdate(getApplicationContext(), () -> finished.set(true));
- Awaitility.await().until(finished::get);
+ if (NetworkUtils.networkAvailable() && NetworkUtils.isFeedRefreshAllowed()) {
+ DBTasks.refreshAllFeeds(getApplicationContext());
+ } else {
+ Log.d(TAG, "Blocking automatic update: no wifi available / no mobile updates allowed");
+ }
- if (UserPreferences.isAutoUpdateTimeOfDay()) {
+ if (!isRunOnce && UserPreferences.isAutoUpdateTimeOfDay()) {
// WorkManager does not allow to set specific time for repeated tasks.
// We repeatedly schedule a OneTimeWorkRequest instead.
- UserPreferences.restartUpdateAlarm();
+ AutoUpdateManager.restartUpdateAlarm();
}
return Result.success();
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 b26d3011d..abb1d0c0b 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
@@ -23,7 +23,9 @@ import com.bumptech.glide.request.RequestOptions;
import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.core.R;
+import de.danoeh.antennapod.core.feed.MediaType;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.receiver.MediaButtonReceiver;
import de.danoeh.antennapod.core.receiver.PlayerWidget;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
@@ -69,9 +71,7 @@ public class PlayerWidgetJobService extends SafeJobIntentService {
}
synchronized (waitUsingService) {
- if (playbackService != null) {
- updateViews();
- }
+ updateViews();
}
if (playbackService != null) {
@@ -145,9 +145,12 @@ public class PlayerWidgetJobService extends SafeJobIntentService {
String progressString;
if (playbackService != null) {
- progressString = getProgressString(playbackService.getCurrentPosition(), playbackService.getDuration());
+ progressString = getProgressString(playbackService.getCurrentPosition(),
+ playbackService.getDuration(), playbackService.getCurrentPlaybackSpeed());
} else {
- progressString = getProgressString(media.getPosition(), media.getDuration());
+ float speed = media.getMediaType() == MediaType.VIDEO ?
+ UserPreferences.getVideoPlaybackSpeed() : UserPreferences.getPlaybackSpeed();
+ progressString = getProgressString(media.getPosition(), media.getDuration(), speed);
}
if (progressString != null) {
@@ -211,10 +214,11 @@ public class PlayerWidgetJobService extends SafeJobIntentService {
return PendingIntent.getBroadcast(this, 0, startingIntent, 0);
}
- private String getProgressString(int position, int duration) {
+ private String getProgressString(int position, int duration, float speed) {
if (position > 0 && duration > 0) {
- position = TimeSpeedConverter.convert(position);
- duration = TimeSpeedConverter.convert(duration);
+ TimeSpeedConverter converter = new TimeSpeedConverter(speed);
+ position = converter.convert(position);
+ duration = converter.convert(duration);
return Converter.getDurationStringLong(position) + " / "
+ Converter.getDurationStringLong(duration);
} else {
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 97007a214..04a6d5882 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
@@ -16,7 +16,9 @@ import java.net.Socket;
import java.net.SocketAddress;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
@@ -28,6 +30,8 @@ import javax.net.ssl.X509TrustManager;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBWriter;
+import okhttp3.CipherSuite;
+import okhttp3.ConnectionSpec;
import okhttp3.Credentials;
import okhttp3.HttpUrl;
import okhttp3.JavaNetCookieJar;
@@ -138,9 +142,24 @@ public class AntennapodHttpClient {
});
}
}
- if(16 <= Build.VERSION.SDK_INT && Build.VERSION.SDK_INT < 21) {
+ if (16 <= Build.VERSION.SDK_INT && Build.VERSION.SDK_INT < 21) {
builder.sslSocketFactory(new CustomSslSocketFactory(), trustManager());
}
+
+ if (Build.VERSION.SDK_INT < 21) {
+ // 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());
+ cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA);
+ cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA);
+
+ ConnectionSpec legacyTls = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
+ .cipherSuites(cipherSuites.toArray(new CipherSuite[0]))
+ .build();
+ builder.connectionSpecs(Arrays.asList(legacyTls, ConnectionSpec.CLEARTEXT));
+ }
+
return builder;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java
index 59222aa11..6fd0468d3 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java
@@ -13,6 +13,7 @@ import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.text.TextUtils;
import android.util.Log;
@@ -191,10 +192,8 @@ public class DownloadService extends Service {
handleFailedDownload(status, downloader.getDownloadRequest());
if (type == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
- long id = status.getFeedfileId();
- FeedMedia media = DBReader.getFeedMedia(id);
- FeedItem item;
- if (media == null || (item = media.getItem()) == null) {
+ FeedItem item = getFeedItemFromId(status.getFeedfileId());
+ if (item == null) {
return;
}
boolean httpNotFound = status.getReason() == DownloadError.ERROR_HTTP_DATA_ERROR
@@ -214,9 +213,8 @@ public class DownloadService extends Service {
// if FeedMedia download has been canceled, fake FeedItem update
// so that lists reload that it
if (status.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
- FeedMedia media = DBReader.getFeedMedia(status.getFeedfileId());
- FeedItem item;
- if (media == null || (item = media.getItem()) == null) {
+ FeedItem item = getFeedItemFromId(status.getFeedfileId());
+ if (item == null) {
return;
}
EventBus.getDefault().post(FeedItemEvent.updated(item));
@@ -387,6 +385,12 @@ public class DownloadService extends Service {
Downloader d = getDownloader(url);
if (d != null) {
d.cancel();
+ DownloadRequester.getInstance().removeDownload(d.getDownloadRequest());
+
+ FeedItem item = getFeedItemFromId(d.getDownloadRequest().getFeedfileId());
+ if (item != null) {
+ EventBus.getDefault().post(FeedItemEvent.updated(item));
+ }
} else {
Log.e(TAG, "Could not cancel download with url " + url);
}
@@ -547,7 +551,7 @@ public class DownloadService extends Service {
.setContentText(getText(R.string.authentication_notification_msg))
.setStyle(new NotificationCompat.BigTextStyle().bigText(getText(R.string.authentication_notification_msg)
+ ": " + resourceTitle))
- .setSmallIcon(R.drawable.ic_stat_authentication)
+ .setSmallIcon(R.drawable.ic_notification_key)
.setAutoCancel(true)
.setContentIntent(ClientConfig.downloadServiceCallbacks.getAuthentificationNotificationContentIntent(DownloadService.this, downloadRequest));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
@@ -579,6 +583,16 @@ public class DownloadService extends Service {
syncExecutor.execute(new FailedDownloadHandler(status, request));
}
+ @Nullable
+ private FeedItem getFeedItemFromId(long id) {
+ FeedMedia media = DBReader.getFeedMedia(id);
+ if (media != null) {
+ return media.getItem();
+ } else {
+ return null;
+ }
+ }
+
/**
* Takes a single Feed, parses the corresponding file and refreshes
* information in the manager
@@ -1059,7 +1073,13 @@ public class DownloadService extends Service {
private final Runnable postDownloaderTask = new Runnable() {
@Override
public void run() {
- List<Downloader> list = Collections.unmodifiableList(downloads);
+ List<Downloader> runningDownloads = new ArrayList<>();
+ for (Downloader downloader : downloads) {
+ if (!downloader.cancelled) {
+ runningDownloads.add(downloader);
+ }
+ }
+ List<Downloader> list = Collections.unmodifiableList(runningDownloads);
EventBus.getDefault().postSticky(DownloadEvent.refresh(list));
postHandler.postDelayed(postDownloaderTask, 1500);
}
@@ -1077,7 +1097,10 @@ public class DownloadService extends Service {
private static String compileNotificationString(List<Downloader> downloads) {
List<String> lines = new ArrayList<>(downloads.size());
for (Downloader downloader : downloads) {
- StringBuilder line = new StringBuilder("\u2022 ");
+ if (downloader.cancelled) {
+ continue;
+ }
+ StringBuilder line = new StringBuilder("• ");
DownloadRequest request = downloader.getDownloadRequest();
switch (request.getFeedfileType()) {
case Feed.FEEDFILETYPE_FEED:
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadStatus.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadStatus.java
index 5debc6d05..d88eb63f4 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadStatus.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadStatus.java
@@ -193,10 +193,6 @@ public class DownloadStatus {
this.cancelled = true;
}
- public void setCompletionDate(Date completionDate) {
- this.completionDate = (Date) completionDate.clone();
- }
-
public void setId(long id) {
this.id = id;
}
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 f20525f73..556aad573 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
@@ -22,28 +22,51 @@ import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
+import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
+import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
import com.google.android.exoplayer2.util.Util;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+import io.reactivex.Observable;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.Disposable;
import org.antennapod.audio.MediaPlayer;
import de.danoeh.antennapod.core.util.playback.IPlayer;
+import java.util.concurrent.TimeUnit;
public class ExoPlayerWrapper implements IPlayer {
private final Context mContext;
+ private final Disposable bufferingUpdateDisposable;
private SimpleExoPlayer mExoPlayer;
private MediaSource mediaSource;
private MediaPlayer.OnSeekCompleteListener audioSeekCompleteListener;
private MediaPlayer.OnCompletionListener audioCompletionListener;
private MediaPlayer.OnErrorListener audioErrorListener;
+ private MediaPlayer.OnBufferingUpdateListener bufferingUpdateListener;
+
ExoPlayerWrapper(Context context) {
mContext = context;
mExoPlayer = createPlayer();
+
+ bufferingUpdateDisposable = Observable.interval(2, TimeUnit.SECONDS)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(aLong -> {
+ if (bufferingUpdateListener != null) {
+ bufferingUpdateListener.onBufferingUpdate(null, mExoPlayer.getBufferedPercentage());
+ }
+ });
}
private SimpleExoPlayer createPlayer() {
+ DefaultLoadControl.Builder loadControl = new DefaultLoadControl.Builder();
+ loadControl.setBufferDurationsMs(30000, 120000,
+ DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS,
+ DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS);
+ loadControl.setBackBuffer(UserPreferences.getRewindSecs() * 1000 + 500, true);
SimpleExoPlayer p = ExoPlayerFactory.newSimpleInstance(mContext, new DefaultRenderersFactory(mContext),
- new DefaultTrackSelector(), new DefaultLoadControl());
+ new DefaultTrackSelector(), loadControl.createDefaultLoadControl());
p.setSeekParameters(SeekParameters.PREVIOUS_SYNC);
p.addListener(new Player.EventListener() {
@Override
@@ -148,12 +171,14 @@ public class ExoPlayerWrapper implements IPlayer {
@Override
public void release() {
+ bufferingUpdateDisposable.dispose();
if (mExoPlayer != null) {
mExoPlayer.release();
}
audioSeekCompleteListener = null;
audioCompletionListener = null;
audioErrorListener = null;
+ bufferingUpdateListener = null;
}
@Override
@@ -180,8 +205,12 @@ public class ExoPlayerWrapper implements IPlayer {
@Override
public void setDataSource(String s) throws IllegalArgumentException, IllegalStateException {
- DataSource.Factory dataSourceFactory =
- new DefaultDataSourceFactory(mContext, Util.getUserAgent(mContext, mContext.getPackageName()), null);
+ DefaultHttpDataSourceFactory httpDataSourceFactory = new DefaultHttpDataSourceFactory(
+ Util.getUserAgent(mContext, mContext.getPackageName()), null,
+ DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
+ DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS,
+ true);
+ DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(mContext, null, httpDataSourceFactory);
ExtractorMediaSource.Factory f = new ExtractorMediaSource.Factory(dataSourceFactory);
mediaSource = f.createMediaSource(Uri.parse(s));
}
@@ -247,4 +276,8 @@ public class ExoPlayerWrapper implements IPlayer {
}
return mExoPlayer.getVideoFormat().height;
}
+
+ void setOnBufferingUpdateListener(MediaPlayer.OnBufferingUpdateListener bufferingUpdateListener) {
+ this.bufferingUpdateListener = bufferingUpdateListener;
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java
index 5153dcddb..fe8db4e11 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java
@@ -12,8 +12,6 @@ import android.util.Log;
import android.util.Pair;
import android.view.SurfaceHolder;
-import de.danoeh.antennapod.core.feed.FeedMedia;
-import de.danoeh.antennapod.core.feed.FeedPreferences;
import org.antennapod.audio.MediaPlayer;
import java.io.File;
@@ -27,12 +25,15 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock;
+import de.danoeh.antennapod.core.feed.FeedMedia;
+import de.danoeh.antennapod.core.feed.FeedPreferences;
import de.danoeh.antennapod.core.feed.MediaType;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.util.RewindAfterPauseUtils;
import de.danoeh.antennapod.core.util.playback.AudioPlayer;
import de.danoeh.antennapod.core.util.playback.IPlayer;
import de.danoeh.antennapod.core.util.playback.Playable;
+import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
import de.danoeh.antennapod.core.util.playback.VideoPlayer;
/**
@@ -308,14 +309,11 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
Log.d(TAG, "Audiofocus successfully requested");
Log.d(TAG, "Resuming/Starting playback");
acquireWifiLockIfNecessary();
- float speed = 1.0f;
- try {
- speed = Float.parseFloat(UserPreferences.getPlaybackSpeed());
- } catch(NumberFormatException e) {
- Log.e(TAG, Log.getStackTraceString(e));
- UserPreferences.setPlaybackSpeed(String.valueOf(speed));
+ if (media.getMediaType() == MediaType.VIDEO) {
+ setPlaybackParams(UserPreferences.getVideoPlaybackSpeed(), UserPreferences.isSkipSilence());
+ } else {
+ setPlaybackParams(UserPreferences.getPlaybackSpeed(), UserPreferences.isSkipSilence());
}
- setPlaybackParams(speed, UserPreferences.isSkipSilence());
float leftVolume = UserPreferences.getLeftVolume();
float rightVolume = UserPreferences.getRightVolume();
@@ -361,13 +359,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
setPlayerStatus(PlayerStatus.PAUSED, media, getPosition());
if (abandonFocus) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- AudioFocusRequest.Builder builder = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
- .setOnAudioFocusChangeListener(audioFocusChangeListener);
- audioManager.abandonAudioFocusRequest(builder.build());
- } else {
- audioManager.abandonAudioFocus(audioFocusChangeListener);
- }
+ abandonAudioFocus();
pausedBecauseOfTransientAudiofocusLoss = false;
}
if (stream && reinit) {
@@ -381,6 +373,16 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
});
}
+ private void abandonAudioFocus() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ AudioFocusRequest.Builder builder = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
+ .setOnAudioFocusChangeListener(audioFocusChangeListener);
+ audioManager.abandonAudioFocusRequest(builder.build());
+ } else {
+ audioManager.abandonAudioFocus(audioFocusChangeListener);
+ }
+ }
+
/**
* Prepares media player for playback if the service is in the INITALIZED
* state.
@@ -609,11 +611,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
*/
@Override
public boolean canSetSpeed() {
- boolean retVal = false;
- if (mediaPlayer != null && media != null && media.getMediaType() == MediaType.AUDIO) {
- retVal = (mediaPlayer).canSetSpeed();
- }
- return retVal;
+ return mediaPlayer != null && mediaPlayer.canSetSpeed();
}
/**
@@ -622,13 +620,11 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
*/
private void setSpeedSyncAndSkipSilence(float speed, boolean skipSilence) {
playerLock.lock();
- if (media != null && media.getMediaType() == MediaType.AUDIO) {
- if (mediaPlayer.canSetSpeed()) {
- Log.d(TAG, "Playback speed was set to " + speed);
- callback.playbackSpeedChanged(speed);
- }
- mediaPlayer.setPlaybackParams(speed, skipSilence);
+ if (mediaPlayer.canSetSpeed()) {
+ Log.d(TAG, "Playback speed was set to " + speed);
+ callback.playbackSpeedChanged(speed);
}
+ mediaPlayer.setPlaybackParams(speed, skipSilence);
playerLock.unlock();
}
@@ -861,6 +857,19 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
@Override
public void onAudioFocusChange(final int focusChange) {
+ if (!PlaybackService.isRunning) {
+ abandonAudioFocus();
+ Log.d(TAG, "onAudioFocusChange: PlaybackService is no longer running");
+ if (focusChange == AudioManager.AUDIOFOCUS_GAIN && pausedBecauseOfTransientAudiofocusLoss) {
+ new PlaybackServiceStarter(context, getPlayable())
+ .startWhenPrepared(true)
+ .streamIfLastWasStream()
+ .callEvenIfRunning(false)
+ .start();
+ }
+ return;
+ }
+
executor.submit(() -> {
playerLock.lock();
@@ -934,13 +943,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
mediaPlayer.reset();
}
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- AudioFocusRequest.Builder builder = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
- .setOnAudioFocusChangeListener(audioFocusChangeListener);
- audioManager.abandonAudioFocusRequest(builder.build());
- } else {
- audioManager.abandonAudioFocus(audioFocusChangeListener);
- }
+ abandonAudioFocus();
final Playable currentMedia = media;
Playable nextMedia = null;
@@ -1040,6 +1043,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
ExoPlayerWrapper ap = (ExoPlayerWrapper) mp;
ap.setOnCompletionListener(audioCompletionListener);
ap.setOnSeekCompleteListener(audioSeekCompleteListener);
+ ap.setOnBufferingUpdateListener(audioBufferingUpdateListener);
ap.setOnErrorListener(audioErrorListener);
} else {
Log.w(TAG, "Unknown media player: " + mp);
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 d90a86bab..f8990328f 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
@@ -45,10 +45,12 @@ import com.bumptech.glide.request.target.Target;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.event.MessageEvent;
+import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import de.danoeh.antennapod.core.event.ServiceEvent;
import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.Feed;
@@ -74,6 +76,9 @@ import de.danoeh.antennapod.core.util.gui.NotificationUtils;
import de.danoeh.antennapod.core.util.playback.ExternalMedia;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
+import io.reactivex.Observable;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.Disposable;
import org.greenrobot.eventbus.EventBus;
/**
@@ -99,6 +104,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
*/
public static final String EXTRA_SHOULD_STREAM = "extra.de.danoeh.antennapod.core.service.shouldStream";
public static final String EXTRA_ALLOW_STREAM_THIS_TIME = "extra.de.danoeh.antennapod.core.service.allowStream";
+ public static final String EXTRA_ALLOW_STREAM_ALWAYS = "extra.de.danoeh.antennapod.core.service.allowStreamAlways";
/**
* True if playback should be started immediately after media has been
* prepared.
@@ -203,10 +209,6 @@ public class PlaybackService extends MediaBrowserServiceCompat {
*/
public static boolean isRunning = false;
/**
- * Is true if service has received a valid start command.
- */
- public static boolean started = false;
- /**
* Is true if the service was running, but paused due to headphone disconnect
*/
private static boolean transientPause = false;
@@ -221,6 +223,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
private PlaybackServiceMediaPlayer mediaPlayer;
private PlaybackServiceTaskManager taskManager;
private PlaybackServiceFlavorHelper flavorHelper;
+ private PlaybackServiceStateManager stateManager;
+ private Disposable positionEventTimer;
/**
* Used for Lollipop notifications, Android Wear, and Android Auto.
@@ -275,8 +279,9 @@ public class PlaybackService extends MediaBrowserServiceCompat {
Log.d(TAG, "Service created.");
isRunning = true;
+ stateManager = new PlaybackServiceStateManager(this);
PlaybackServiceNotificationBuilder notificationBuilder = new PlaybackServiceNotificationBuilder(this);
- startForeground(NOTIFICATION_ID, notificationBuilder.build());
+ stateManager.startForeground(NOTIFICATION_ID, notificationBuilder.build());
registerReceiver(autoStateUpdated, new IntentFilter("com.google.android.gms.car.media.STATUS"));
registerReceiver(headsetDisconnected, new IntentFilter(Intent.ACTION_HEADSET_PLUG));
@@ -336,13 +341,12 @@ public class PlaybackService extends MediaBrowserServiceCompat {
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "Service is about to be destroyed");
- stopForeground(true);
+ stateManager.stopForeground(!UserPreferences.isPersistNotify());
isRunning = false;
- started = false;
currentMediaType = MediaType.UNKNOWN;
- PreferenceManager.getDefaultSharedPreferences(this)
- .unregisterOnSharedPreferenceChangeListener(prefListener);
+ cancelPositionObserver();
+ PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(prefListener);
if (mediaSession != null) {
mediaSession.release();
}
@@ -359,11 +363,6 @@ public class PlaybackService extends MediaBrowserServiceCompat {
mediaPlayer.shutdown();
taskManager.shutdown();
}
-
- private void stopService() {
- stopForeground(true);
- stopSelf();
- }
@Override
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, Bundle rootHints) {
@@ -457,42 +456,66 @@ public class PlaybackService extends MediaBrowserServiceCompat {
super.onStartCommand(intent, flags, startId);
Log.d(TAG, "OnStartCommand called");
+
+ if (!stateManager.isInForeground()) {
+ PlaybackServiceNotificationBuilder notificationBuilder = new PlaybackServiceNotificationBuilder(this);
+ if (mediaPlayer != null && getPlayable() != null) {
+ notificationBuilder.addMetadata(getPlayable(), mediaSession.getSessionToken(), getStatus(), isCasting);
+ if (notificationBuilder.isIconCached(getPlayable())) {
+ notificationBuilder.loadIcon(getPlayable());
+ }
+ }
+ stateManager.startForeground(NOTIFICATION_ID, notificationBuilder.build());
+ }
+
+ NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
+ notificationManager.cancel(NOTIFICATION_ID_STREAMING);
+
final int keycode = intent.getIntExtra(MediaButtonReceiver.EXTRA_KEYCODE, -1);
final boolean castDisconnect = intent.getBooleanExtra(EXTRA_CAST_DISCONNECT, false);
Playable playable = intent.getParcelableExtra(EXTRA_PLAYABLE);
if (keycode == -1 && playable == null && !castDisconnect) {
Log.e(TAG, "PlaybackService was started with no arguments");
- stopService();
+ stateManager.stopService();
return Service.START_NOT_STICKY;
}
if ((flags & Service.START_FLAG_REDELIVERY) != 0) {
Log.d(TAG, "onStartCommand is a redelivered intent, calling stopForeground now.");
- stopForeground(true);
+ stateManager.stopForeground(true);
} else {
if (keycode != -1) {
Log.d(TAG, "Received media button event");
boolean handled = handleKeycode(keycode, true);
- if (!handled) {
- stopService();
+ if (!handled && !stateManager.hasReceivedValidStartCommand()) {
+ stateManager.stopService();
return Service.START_NOT_STICKY;
}
} else if (!flavorHelper.castDisconnect(castDisconnect) && playable != null) {
- started = true;
+ stateManager.validStartCommandWasReceived();
boolean stream = intent.getBooleanExtra(EXTRA_SHOULD_STREAM, true);
boolean allowStreamThisTime = intent.getBooleanExtra(EXTRA_ALLOW_STREAM_THIS_TIME, false);
+ boolean allowStreamAlways = intent.getBooleanExtra(EXTRA_ALLOW_STREAM_ALWAYS, false);
boolean startWhenPrepared = intent.getBooleanExtra(EXTRA_START_WHEN_PREPARED, false);
boolean prepareImmediately = intent.getBooleanExtra(EXTRA_PREPARE_IMMEDIATELY, false);
sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, 0);
//If the user asks to play External Media, the casting session, if on, should end.
flavorHelper.castDisconnect(playable instanceof ExternalMedia);
- if (playable instanceof FeedMedia) {
- playable = DBReader.getFeedMedia(((FeedMedia) playable).getId());
+ if (allowStreamAlways) {
+ UserPreferences.setAllowMobileStreaming(true);
}
if (stream && !NetworkUtils.isStreamingAllowed() && !allowStreamThisTime) {
displayStreamingNotAllowedNotification(intent);
- writePlaybackPreferencesNoMediaPlaying();
- stopService();
+ PlaybackPreferences.writeNoMediaPlaying();
+ stateManager.stopService();
+ return Service.START_NOT_STICKY;
+ }
+ if (playable instanceof FeedMedia) {
+ playable = DBReader.getFeedMedia(((FeedMedia) playable).getId());
+ }
+ if (playable == null) {
+ Log.d(TAG, "Playable was not found. Stopping service.");
+ stateManager.stopService();
return Service.START_NOT_STICKY;
}
mediaPlayer.playMediaObject(playable, stream, startWhenPrepared, prepareImmediately);
@@ -506,23 +529,40 @@ public class PlaybackService extends MediaBrowserServiceCompat {
}
private void displayStreamingNotAllowedNotification(Intent originalIntent) {
- Intent intent = new Intent(originalIntent);
- intent.putExtra(EXTRA_ALLOW_STREAM_THIS_TIME, true);
- PendingIntent pendingIntent;
+ Intent intentAllowThisTime = new Intent(originalIntent);
+ intentAllowThisTime.setAction(EXTRA_ALLOW_STREAM_THIS_TIME);
+ intentAllowThisTime.putExtra(EXTRA_ALLOW_STREAM_THIS_TIME, true);
+ PendingIntent pendingIntentAllowThisTime;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
- pendingIntent = PendingIntent.getForegroundService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ pendingIntentAllowThisTime = PendingIntent.getForegroundService(this, 0, intentAllowThisTime, PendingIntent.FLAG_UPDATE_CURRENT);
} else {
- pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ pendingIntentAllowThisTime = PendingIntent.getService(this, 0, intentAllowThisTime, PendingIntent.FLAG_UPDATE_CURRENT);
+ }
+
+ Intent intentAlwaysAllow = new Intent(intentAllowThisTime);
+ intentAlwaysAllow.setAction(EXTRA_ALLOW_STREAM_ALWAYS);
+ intentAlwaysAllow.putExtra(EXTRA_ALLOW_STREAM_ALWAYS, true);
+ PendingIntent pendingIntentAlwaysAllow;
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
+ pendingIntentAlwaysAllow = PendingIntent.getForegroundService(this, 0, intentAlwaysAllow, PendingIntent.FLAG_UPDATE_CURRENT);
+ } else {
+ pendingIntentAlwaysAllow = PendingIntent.getService(this, 0, intentAlwaysAllow, PendingIntent.FLAG_UPDATE_CURRENT);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NotificationUtils.CHANNEL_ID_USER_ACTION)
- .setSmallIcon(R.drawable.stat_notify_sync_error)
+ .setSmallIcon(R.drawable.ic_stream_white)
.setContentTitle(getString(R.string.confirm_mobile_streaming_notification_title))
.setContentText(getString(R.string.confirm_mobile_streaming_notification_message))
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(getString(R.string.confirm_mobile_streaming_notification_message)))
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
- .setContentIntent(pendingIntent)
+ .setContentIntent(pendingIntentAllowThisTime)
+ .addAction(R.drawable.ic_stream_white,
+ getString(R.string.stream_label),
+ pendingIntentAllowThisTime)
+ .addAction(R.drawable.ic_stream_white,
+ getString(R.string.confirm_mobile_streaming_button_always),
+ pendingIntentAlwaysAllow)
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(NOTIFICATION_ID_STREAMING, builder.build());
@@ -540,7 +580,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
case KeyEvent.KEYCODE_HEADSETHOOK:
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
if (status == PlayerStatus.PLAYING) {
- mediaPlayer.pause(!UserPreferences.isPersistNotify(), true);
+ mediaPlayer.pause(!UserPreferences.isPersistNotify(), false);
} else if (status == PlayerStatus.PAUSED || status == PlayerStatus.PREPARED) {
mediaPlayer.resume();
} else if (status == PlayerStatus.PREPARING) {
@@ -564,7 +604,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
return true;
case KeyEvent.KEYCODE_MEDIA_PAUSE:
if (status == PlayerStatus.PLAYING) {
- mediaPlayer.pause(!UserPreferences.isPersistNotify(), true);
+ mediaPlayer.pause(!UserPreferences.isPersistNotify(), false);
}
return true;
@@ -598,10 +638,9 @@ public class PlaybackService extends MediaBrowserServiceCompat {
case KeyEvent.KEYCODE_MEDIA_STOP:
if (status == PlayerStatus.PLAYING) {
mediaPlayer.pause(true, true);
- started = false;
}
- stopForeground(true); // gets rid of persistent notification
+ stateManager.stopForeground(true); // gets rid of persistent notification
return true;
default:
Log.d(TAG, "Unhandled key code: " + keycode);
@@ -617,10 +656,10 @@ public class PlaybackService extends MediaBrowserServiceCompat {
Playable playable = Playable.PlayableUtils.createInstanceFromPreferences(getApplicationContext());
if (playable != null) {
mediaPlayer.playMediaObject(playable, false, true, true);
- started = true;
+ stateManager.validStartCommandWasReceived();
PlaybackService.this.updateMediaSessionMetadata(playable);
} else {
- stopService();
+ stateManager.stopService();
}
}
@@ -637,7 +676,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
mediaPlayer.pause(true, false);
mediaPlayer.resetVideoSurface();
setupNotification(getPlayable());
- stopForeground(!UserPreferences.isPersistNotify());
+ stateManager.stopForeground(!UserPreferences.isPersistNotify());
}
private final PlaybackServiceTaskManager.PSTMCallback taskManagerCallback = new PlaybackServiceTaskManager.PSTMCallback() {
@@ -692,7 +731,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
updateMediaSession(newInfo.playerStatus);
switch (newInfo.playerStatus) {
case INITIALIZED:
- writePlaybackPreferences();
+ PlaybackPreferences.writeMediaPlaying(mediaPlayer.getPSMPInfo().playable,
+ mediaPlayer.getPSMPInfo().playerStatus, mediaPlayer.isStreaming());
break;
case PREPARED:
@@ -707,9 +747,10 @@ public class PlaybackService extends MediaBrowserServiceCompat {
setupNotification(newInfo);
} else if (!UserPreferences.isPersistNotify() && !isCasting) {
// remove notification on pause
- stopForeground(true);
+ stateManager.stopForeground(true);
}
- writePlayerStatusPlaybackPreferences();
+ cancelPositionObserver();
+ PlaybackPreferences.writePlayerStatus(mediaPlayer.getPlayerStatus());
break;
case STOPPED:
@@ -718,9 +759,10 @@ public class PlaybackService extends MediaBrowserServiceCompat {
break;
case PLAYING:
- writePlayerStatusPlaybackPreferences();
+ PlaybackPreferences.writePlayerStatus(mediaPlayer.getPlayerStatus());
setupNotification(newInfo);
- started = true;
+ setupPositionUpdater();
+ stateManager.validStartCommandWasReceived();
// set sleep timer if auto-enabled
if (newInfo.oldPlayerStatus != null && newInfo.oldPlayerStatus != PlayerStatus.SEEKING &&
SleepTimerPreferences.autoEnable() && !sleepTimerActive()) {
@@ -730,8 +772,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
break;
case ERROR:
- writePlaybackPreferencesNoMediaPlaying();
- stopService();
+ PlaybackPreferences.writeNoMediaPlaying();
+ stateManager.stopService();
break;
}
@@ -744,7 +786,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
@Override
public void shouldStop() {
- stopService();
+ setupNotification(getPlayable()); // Stops foreground if not playing
}
@Override
@@ -792,8 +834,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
mediaPlayer.pause(true, false);
}
sendNotificationBroadcast(NOTIFICATION_TYPE_ERROR, what);
- writePlaybackPreferencesNoMediaPlaying();
- stopService();
+ PlaybackPreferences.writeNoMediaPlaying();
+ stateManager.stopService();
return true;
}
@@ -877,8 +919,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
.startWhenPrepared(true)
.shouldStream(true)
.getIntent());
- writePlaybackPreferencesNoMediaPlaying();
- stopService();
+ PlaybackPreferences.writeNoMediaPlaying();
+ stateManager.stopService();
return null;
}
return nextItem.getMedia();
@@ -892,9 +934,9 @@ public class PlaybackService extends MediaBrowserServiceCompat {
Log.d(TAG, "Playback ended");
if (stopPlaying) {
taskManager.cancelPositionSaver();
- writePlaybackPreferencesNoMediaPlaying();
+ PlaybackPreferences.writeNoMediaPlaying();
if (!isCasting) {
- stopForeground(true);
+ stateManager.stopForeground(true);
}
}
if (mediaType == null) {
@@ -998,101 +1040,6 @@ public class PlaybackService extends MediaBrowserServiceCompat {
EventBus.getDefault().post(new MessageEvent(getString(R.string.sleep_timer_disabled_label)));
}
- private void writePlaybackPreferencesNoMediaPlaying() {
- SharedPreferences.Editor editor = PreferenceManager
- .getDefaultSharedPreferences(getApplicationContext()).edit();
- editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_MEDIA,
- PlaybackPreferences.NO_MEDIA_PLAYING);
- editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
- PlaybackPreferences.NO_MEDIA_PLAYING);
- editor.putLong(
- PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID,
- PlaybackPreferences.NO_MEDIA_PLAYING);
- editor.putInt(
- PlaybackPreferences.PREF_CURRENT_PLAYER_STATUS,
- PlaybackPreferences.PLAYER_STATUS_OTHER);
- editor.commit();
- }
-
- private int getCurrentPlayerStatusAsInt(PlayerStatus playerStatus) {
- int playerStatusAsInt;
- switch (playerStatus) {
- case PLAYING:
- playerStatusAsInt = PlaybackPreferences.PLAYER_STATUS_PLAYING;
- break;
- case PAUSED:
- playerStatusAsInt = PlaybackPreferences.PLAYER_STATUS_PAUSED;
- break;
- default:
- playerStatusAsInt = PlaybackPreferences.PLAYER_STATUS_OTHER;
- }
- return playerStatusAsInt;
- }
-
- private void writePlaybackPreferences() {
- Log.d(TAG, "Writing playback preferences");
-
- SharedPreferences.Editor editor = PreferenceManager
- .getDefaultSharedPreferences(getApplicationContext()).edit();
- PlaybackServiceMediaPlayer.PSMPInfo info = mediaPlayer.getPSMPInfo();
- MediaType mediaType = mediaPlayer.getCurrentMediaType();
- boolean stream = mediaPlayer.isStreaming();
- int playerStatus = getCurrentPlayerStatusAsInt(info.playerStatus);
-
- if (info.playable != null) {
- editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_MEDIA,
- info.playable.getPlayableType());
- editor.putBoolean(
- PlaybackPreferences.PREF_CURRENT_EPISODE_IS_STREAM,
- stream);
- editor.putBoolean(
- PlaybackPreferences.PREF_CURRENT_EPISODE_IS_VIDEO,
- mediaType == MediaType.VIDEO);
- if (info.playable instanceof FeedMedia) {
- FeedMedia fMedia = (FeedMedia) info.playable;
- editor.putLong(
- PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
- fMedia.getItem().getFeed().getId());
- editor.putLong(
- PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID,
- fMedia.getId());
- } else {
- editor.putLong(
- PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
- PlaybackPreferences.NO_MEDIA_PLAYING);
- editor.putLong(
- PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID,
- PlaybackPreferences.NO_MEDIA_PLAYING);
- }
- info.playable.writeToPreferences(editor);
- } else {
- editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_MEDIA,
- PlaybackPreferences.NO_MEDIA_PLAYING);
- editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
- PlaybackPreferences.NO_MEDIA_PLAYING);
- editor.putLong(
- PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID,
- PlaybackPreferences.NO_MEDIA_PLAYING);
- }
- editor.putInt(
- PlaybackPreferences.PREF_CURRENT_PLAYER_STATUS, playerStatus);
-
- editor.commit();
- }
-
- private void writePlayerStatusPlaybackPreferences() {
- Log.d(TAG, "Writing player status playback preferences");
-
- SharedPreferences.Editor editor = PreferenceManager
- .getDefaultSharedPreferences(getApplicationContext()).edit();
- int playerStatus = getCurrentPlayerStatusAsInt(mediaPlayer.getPlayerStatus());
-
- editor.putInt(
- PlaybackPreferences.PREF_CURRENT_PLAYER_STATUS, playerStatus);
-
- editor.commit();
- }
-
private void sendNotificationBroadcast(int type, int code) {
Intent intent = new Intent(ACTION_PLAYER_NOTIFICATION);
intent.putExtra(EXTRA_NOTIFICATION_TYPE, type);
@@ -1226,7 +1173,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
builder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI, imageLocation);
}
}
- if (!Thread.currentThread().isInterrupted() && started) {
+ if (!Thread.currentThread().isInterrupted() && stateManager.hasReceivedValidStartCommand()) {
mediaSession.setSessionActivity(PendingIntent.getActivity(this, 0,
PlaybackService.getPlayerActivityIntent(this),
PendingIntent.FLAG_UPDATE_CURRENT));
@@ -1262,8 +1209,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
}
if (playable == null) {
Log.d(TAG, "setupNotification: playable is null" + Log.getStackTraceString(new Exception()));
- if (!started) {
- stopService();
+ if (!stateManager.hasReceivedValidStartCommand()) {
+ stateManager.stopService();
}
return;
}
@@ -1274,8 +1221,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
if (mediaPlayer == null) {
Log.d(TAG, "notificationSetupTask: mediaPlayer is null");
- if (!started) {
- stopService();
+ if (!stateManager.hasReceivedValidStartCommand()) {
+ stateManager.stopService();
}
return;
}
@@ -1287,20 +1234,20 @@ public class PlaybackService extends MediaBrowserServiceCompat {
if (!notificationBuilder.isIconCached(playable)) {
// To make sure that the notification is shown instantly
notificationBuilder.loadDefaultIcon();
- startForeground(NOTIFICATION_ID, notificationBuilder.build());
+ stateManager.startForeground(NOTIFICATION_ID, notificationBuilder.build());
}
notificationBuilder.loadIcon(playable);
- if (!Thread.currentThread().isInterrupted() && started) {
+ if (!Thread.currentThread().isInterrupted() && stateManager.hasReceivedValidStartCommand()) {
Notification notification = notificationBuilder.build();
if (playerStatus == PlayerStatus.PLAYING ||
playerStatus == PlayerStatus.PREPARING ||
playerStatus == PlayerStatus.SEEKING ||
isCasting) {
- startForeground(NOTIFICATION_ID, notification);
+ stateManager.startForeground(NOTIFICATION_ID, notification);
} else {
- stopForeground(false);
+ stateManager.stopForeground(false);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotificationManager.notify(NOTIFICATION_ID, notification);
}
@@ -1489,7 +1436,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
@Override
public void onReceive(Context context, Intent intent) {
if (TextUtils.equals(intent.getAction(), ACTION_SHUTDOWN_PLAYBACK_SERVICE)) {
- stopService();
+ stateManager.stopService();
}
}
@@ -1663,6 +1610,24 @@ public class PlaybackService extends MediaBrowserServiceCompat {
return mediaPlayer.getVideoSize();
}
+ private void setupPositionUpdater() {
+ if (positionEventTimer != null) {
+ positionEventTimer.dispose();
+ }
+
+ Log.d(TAG, "Setting up position observer");
+ positionEventTimer = Observable.interval(1, TimeUnit.SECONDS)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(aLong ->
+ EventBus.getDefault().post(new PlaybackPositionEvent(getCurrentPosition(), getDuration())));
+ }
+
+ private void cancelPositionObserver() {
+ if (positionEventTimer != null) {
+ positionEventTimer.dispose();
+ }
+ }
+
private final MediaSessionCompat.Callback sessionCallback = new MediaSessionCompat.Callback() {
private static final String TAG = "MediaSessionCompat";
@@ -1856,7 +1821,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
PlaybackService.this.setupNotification(info);
} else if (!UserPreferences.isPersistNotify()) {
- PlaybackService.this.stopForeground(true);
+ stateManager.stopForeground(true);
}
}
}
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 9a1e8e7ef..1a13fe5a7 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
@@ -5,6 +5,7 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.NotificationCompat;
import android.support.v4.media.session.MediaSessionCompat;
@@ -114,7 +115,7 @@ public class PlaybackServiceNotificationBuilder extends NotificationCompat.Build
stopCastingIntent.putExtra(PlaybackService.EXTRA_CAST_DISCONNECT, true);
PendingIntent stopCastingPendingIntent = PendingIntent.getService(context,
numActions, stopCastingIntent, PendingIntent.FLAG_UPDATE_CURRENT);
- addAction(R.drawable.ic_media_cast_disconnect,
+ addAction(R.drawable.ic_notification_cast_off,
context.getString(R.string.cast_disconnect_label),
stopCastingPendingIntent);
numActions++;
@@ -123,7 +124,7 @@ public class PlaybackServiceNotificationBuilder extends NotificationCompat.Build
// always let them rewind
PendingIntent rewindButtonPendingIntent = getPendingIntentForMediaAction(
KeyEvent.KEYCODE_MEDIA_REWIND, numActions);
- addAction(android.R.drawable.ic_media_rew, context.getString(R.string.rewind_label), rewindButtonPendingIntent);
+ addAction(R.drawable.ic_notification_fast_rewind, context.getString(R.string.rewind_label), rewindButtonPendingIntent);
if (UserPreferences.showRewindOnCompactNotification()) {
compactActionList.add(numActions);
}
@@ -132,14 +133,14 @@ public class PlaybackServiceNotificationBuilder extends NotificationCompat.Build
if (playerStatus == PlayerStatus.PLAYING) {
PendingIntent pauseButtonPendingIntent = getPendingIntentForMediaAction(
KeyEvent.KEYCODE_MEDIA_PAUSE, numActions);
- addAction(android.R.drawable.ic_media_pause, //pause action
+ 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);
- addAction(android.R.drawable.ic_media_play, //play action
+ addAction(R.drawable.ic_notification_play, //play action
context.getString(R.string.play_label),
playButtonPendingIntent);
compactActionList.add(numActions++);
@@ -148,7 +149,7 @@ public class PlaybackServiceNotificationBuilder extends NotificationCompat.Build
// ff follows play, then we have skip (if it's present)
PendingIntent ffButtonPendingIntent = getPendingIntentForMediaAction(
KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, numActions);
- addAction(android.R.drawable.ic_media_ff, context.getString(R.string.fast_forward_label), ffButtonPendingIntent);
+ addAction(R.drawable.ic_notification_fast_forward, context.getString(R.string.fast_forward_label), ffButtonPendingIntent);
if (UserPreferences.showFastForwardOnCompactNotification()) {
compactActionList.add(numActions);
}
@@ -157,7 +158,7 @@ public class PlaybackServiceNotificationBuilder extends NotificationCompat.Build
if (UserPreferences.isFollowQueue()) {
PendingIntent skipButtonPendingIntent = getPendingIntentForMediaAction(
KeyEvent.KEYCODE_MEDIA_NEXT, numActions);
- addAction(android.R.drawable.ic_media_next,
+ addAction(R.drawable.ic_notification_skip,
context.getString(R.string.skip_episode_label),
skipButtonPendingIntent);
if (UserPreferences.showSkipOnCompactNotification()) {
@@ -177,8 +178,13 @@ public class PlaybackServiceNotificationBuilder extends NotificationCompat.Build
private PendingIntent getPendingIntentForMediaAction(int keycodeValue, int requestCode) {
Intent intent = new Intent(context, PlaybackService.class);
+ intent.setAction("MediaCode" + keycodeValue);
intent.putExtra(MediaButtonReceiver.EXTRA_KEYCODE, keycodeValue);
- return PendingIntent .getService(context, requestCode,
- intent, PendingIntent.FLAG_UPDATE_CURRENT);
+
+ if (Build.VERSION.SDK_INT >= 26) {
+ return PendingIntent.getForegroundService(context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ } else {
+ return PendingIntent.getService(context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ }
}
} \ No newline at end of file
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceStateManager.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceStateManager.java
new file mode 100644
index 000000000..18c8fa51f
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceStateManager.java
@@ -0,0 +1,52 @@
+package de.danoeh.antennapod.core.service.playback;
+
+import android.app.Notification;
+import android.app.Service;
+import android.os.Build;
+
+class PlaybackServiceStateManager {
+ private final PlaybackService playbackService;
+
+ private volatile boolean isInForeground = false;
+ private volatile boolean hasReceivedValidStartCommand = false;
+
+ PlaybackServiceStateManager(PlaybackService playbackService) {
+ this.playbackService = playbackService;
+ }
+
+ void startForeground(int notificationId, Notification notification) {
+ playbackService.startForeground(notificationId, notification);
+ isInForeground = true;
+ }
+
+ void stopService() {
+ stopForeground(true);
+ playbackService.stopSelf();
+ }
+
+ void stopForeground(boolean removeNotification) {
+ if (isInForeground) {
+ if (Build.VERSION.SDK_INT < 24) {
+ playbackService.stopForeground(removeNotification);
+ } else if (removeNotification) {
+ playbackService.stopForeground(Service.STOP_FOREGROUND_REMOVE);
+ } else {
+ playbackService.stopForeground(Service.STOP_FOREGROUND_DETACH);
+ }
+ }
+ isInForeground = false;
+ hasReceivedValidStartCommand = false;
+ }
+
+ boolean isInForeground() {
+ return isInForeground;
+ }
+
+ boolean hasReceivedValidStartCommand() {
+ return hasReceivedValidStartCommand;
+ }
+
+ void validStartCommandWasReceived() {
+ this.hasReceivedValidStartCommand = true;
+ }
+}
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 19faa5aed..70d3ba9dd 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
@@ -418,17 +418,18 @@ public final class DBReader {
/**
* Loads a list of FeedItems sorted by pubDate in descending order.
*
+ * @param offset The first episode that should be loaded.
* @param limit The maximum number of episodes that should be loaded.
*/
@NonNull
- public static List<FeedItem> getRecentlyPublishedEpisodes(int limit) {
- Log.d(TAG, "getRecentlyPublishedEpisodes() called with: " + "limit = [" + limit + "]");
+ public static List<FeedItem> getRecentlyPublishedEpisodes(int offset, int limit) {
+ Log.d(TAG, "getRecentlyPublishedEpisodes() called with: " + "offset = [" + offset + "]" + " limit = [" + limit + "]" );
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
Cursor cursor = null;
try {
- cursor = adapter.getRecentlyPublishedItemsCursor(limit);
+ cursor = adapter.getRecentlyPublishedItemsCursor(offset, limit);
List<FeedItem> items = extractItemlistFromCursor(adapter, cursor);
loadAdditionalFeedItemListData(items);
return items;
@@ -830,15 +831,14 @@ public final class DBReader {
* Searches the DB for a FeedMedia of the given id.
*
* @param mediaId The id of the object
- * @return The found object
+ * @return The found object, or null if it does not exist
*/
+ @Nullable
public static FeedMedia getFeedMedia(final long mediaId) {
PodDBAdapter adapter = PodDBAdapter.getInstance();
-
adapter.open();
- Cursor mediaCursor = null;
- try {
- mediaCursor = adapter.getSingleFeedMediaCursor(mediaId);
+
+ try (Cursor mediaCursor = adapter.getSingleFeedMediaCursor(mediaId)) {
if (!mediaCursor.moveToFirst()) {
return null;
}
@@ -846,19 +846,13 @@ public final class DBReader {
int indexFeedItem = mediaCursor.getColumnIndex(PodDBAdapter.KEY_FEEDITEM);
long itemId = mediaCursor.getLong(indexFeedItem);
FeedMedia media = FeedMedia.fromCursor(mediaCursor);
- if (media != null) {
- FeedItem item = getFeedItem(itemId);
- if (item != null) {
- media.setItem(item);
- item.setMedia(media);
- }
+ FeedItem item = getFeedItem(itemId);
+ if (item != null) {
+ media.setItem(item);
+ item.setMedia(media);
}
return media;
-
} finally {
- if (mediaCursor != null) {
- mediaCursor.close();
- }
adapter.close();
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java
index e68bff16e..4c15f5f00 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java
@@ -3,7 +3,7 @@ package de.danoeh.antennapod.core.storage;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
-import android.support.annotation.Nullable;
+import android.os.Looper;
import android.util.Log;
import java.util.ArrayList;
@@ -144,58 +144,36 @@ public final class DBTasks {
private static final AtomicBoolean isRefreshing = new AtomicBoolean(false);
/**
- * Refreshes a given list of Feeds in a separate Thread. This method might ignore subsequent calls if it is still
+ * Refreshes all feeds.
+ * It must not be from the main thread.
+ * This method might ignore subsequent calls if it is still
* enqueuing Feeds for download from a previous call
*
* @param context Might be used for accessing the database
- * @param feeds List of Feeds that should be refreshed.
*/
- public static void refreshAllFeeds(final Context context, final List<Feed> feeds) {
- refreshAllFeeds(context, feeds, null);
- }
-
- /**
- * Refreshes a given list of Feeds in a separate Thread. This method might ignore subsequent calls if it is still
- * enqueuing Feeds for download from a previous call
- *
- * @param context Might be used for accessing the database
- * @param feeds List of Feeds that should be refreshed.
- * @param callback Called after everything was added enqueued for download. Might be null.
- */
- public static void refreshAllFeeds(final Context context, final List<Feed> feeds, @Nullable Runnable callback) {
+ public static void refreshAllFeeds(final Context context) {
if (!isRefreshing.compareAndSet(false, true)) {
Log.d(TAG, "Ignoring request to refresh all feeds: Refresh lock is locked");
return;
}
- new Thread(() -> {
- if (feeds != null) {
- refreshFeeds(context, feeds);
- } else {
- refreshFeeds(context, DBReader.getFeedList());
- }
- isRefreshing.set(false);
+ if (Looper.myLooper() == Looper.getMainLooper()) {
+ throw new IllegalStateException("DBTasks.refreshAllFeeds() must not be called from the main thread.");
+ }
- SharedPreferences prefs = context.getSharedPreferences(PREF_NAME, MODE_PRIVATE);
- prefs.edit().putLong(PREF_LAST_REFRESH, System.currentTimeMillis()).apply();
+ refreshFeeds(context, DBReader.getFeedList());
+ isRefreshing.set(false);
- if (ClientConfig.gpodnetCallbacks.gpodnetEnabled()) {
- GpodnetSyncService.sendSyncIntent(context);
- }
- // Note: automatic download of episodes will be done but not here.
- // Instead it is done after all feeds have been refreshed (asynchronously),
- // in DownloadService.onDestroy()
- // See Issue #2577 for the details of the rationale
+ SharedPreferences prefs = context.getSharedPreferences(PREF_NAME, MODE_PRIVATE);
+ prefs.edit().putLong(PREF_LAST_REFRESH, System.currentTimeMillis()).apply();
- if (callback != null) {
- callback.run();
- }
- }).start();
- }
-
- public static long getLastRefreshAllFeedsTimeMillis(final Context context) {
- SharedPreferences prefs = context.getSharedPreferences(DBTasks.PREF_NAME, MODE_PRIVATE);
- return prefs.getLong(DBTasks.PREF_LAST_REFRESH, 0);
+ if (ClientConfig.gpodnetCallbacks.gpodnetEnabled()) {
+ GpodnetSyncService.sendSyncIntent(context);
+ }
+ // Note: automatic download of episodes will be done but not here.
+ // Instead it is done after all feeds have been refreshed (asynchronously),
+ // in DownloadService.onDestroy()
+ // See Issue #2577 for the details of the rationale
}
/**
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
index 7d525a376..4f0ee70ef 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
@@ -108,23 +108,11 @@ public class DBWriter {
adapter.setMedia(media);
adapter.close();
- // If media is currently being played, change playback
- // type to 'stream' and shutdown playback service
- SharedPreferences prefs = PreferenceManager
- .getDefaultSharedPreferences(context);
- if (PlaybackPreferences.getCurrentlyPlayingMedia() == FeedMedia.PLAYABLE_TYPE_FEEDMEDIA) {
- if (media.getId() == PlaybackPreferences
- .getCurrentlyPlayingFeedMediaId()) {
- SharedPreferences.Editor editor = prefs.edit();
- editor.putBoolean(
- PlaybackPreferences.PREF_CURRENT_EPISODE_IS_STREAM,
- true);
- editor.commit();
- }
- if (PlaybackPreferences.getCurrentlyPlayingFeedMediaId() == media.getId()) {
- IntentUtils.sendLocalBroadcast(context, PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE);
- }
+ if (media.getId() == PlaybackPreferences.getCurrentlyPlayingFeedMediaId()) {
+ PlaybackPreferences.writeNoMediaPlaying();
+ IntentUtils.sendLocalBroadcast(context, PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE);
}
+
// Gpodder: queue delete action for synchronization
if(GpodnetPreferences.loggedIn()) {
FeedItem item = media.getItem();
@@ -150,23 +138,9 @@ public class DBWriter {
public static Future<?> deleteFeed(final Context context, final long feedId) {
return dbExec.submit(() -> {
DownloadRequester requester = DownloadRequester.getInstance();
- SharedPreferences prefs = PreferenceManager
- .getDefaultSharedPreferences(context
- .getApplicationContext());
final Feed feed = DBReader.getFeed(feedId);
if (feed != null) {
- if (PlaybackPreferences.getCurrentlyPlayingMedia() == FeedMedia.PLAYABLE_TYPE_FEEDMEDIA
- && PlaybackPreferences.getLastPlayedFeedId() == feed
- .getId()) {
- IntentUtils.sendLocalBroadcast(context, PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putLong(
- PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
- -1);
- editor.commit();
- }
-
// delete stored media files and mark them as read
List<FeedItem> queue = DBReader.getQueue();
List<FeedItem> removed = new ArrayList<>();
@@ -175,19 +149,12 @@ public class DBWriter {
}
for (FeedItem item : feed.getItems()) {
- if(queue.remove(item)) {
+ if (queue.remove(item)) {
removed.add(item);
}
- if (item.getState() == FeedItem.State.PLAYING && PlaybackService.isRunning) {
- context.stopService(new Intent(context, PlaybackService.class));
- }
- if (item.getMedia() != null
- && item.getMedia().isDownloaded()) {
- File mediaFile = new File(item.getMedia()
- .getFile_url());
- mediaFile.delete();
- } else if (item.getMedia() != null
- && requester.isDownloadingFile(item.getMedia())) {
+ if (item.getMedia() != null && item.getMedia().isDownloaded()) {
+ deleteFeedMediaSynchronous(context, item.getMedia());
+ } else if (item.getMedia() != null && requester.isDownloadingFile(item.getMedia())) {
requester.cancelDownload(context, item.getMedia());
}
}
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 892a4675a..9c48f31dd 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
@@ -34,7 +34,6 @@ import de.danoeh.antennapod.core.util.URLChecker;
public class DownloadRequester {
private static final String TAG = "DownloadRequester";
- public static final String IMAGE_DOWNLOADPATH = "images/";
private static final String FEED_DOWNLOADPATH = "cache/";
private static final String MEDIA_DOWNLOADPATH = "media/";
@@ -274,10 +273,6 @@ public class DownloadRequester {
return item.getDownload_url() != null && downloads.containsKey(item.getDownload_url());
}
- public synchronized DownloadRequest getDownload(String downloadUrl) {
- return downloads.get(downloadUrl);
- }
-
/**
* Checks if feedfile with the given download url is in the downloads list
*/
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 566c280eb..04accecd0 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
@@ -28,8 +28,6 @@ import java.util.Collections;
import java.util.List;
import java.util.Set;
-import de.danoeh.antennapod.core.R;
-import de.danoeh.antennapod.core.event.ProgressEvent;
import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
@@ -38,7 +36,6 @@ import de.danoeh.antennapod.core.feed.FeedPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.util.LongIntMap;
-import org.greenrobot.eventbus.EventBus;
// TODO Remove media column from feeditem table
@@ -55,16 +52,10 @@ public class PodDBAdapter {
*/
private static final int IN_OPERATOR_MAXIMUM = 800;
- /**
- * Maximum number of entries per search request.
- */
- public static final int SEARCH_LIMIT = 30;
-
// Key-constants
public static final String KEY_ID = "id";
public static final String KEY_TITLE = "title";
public static final String KEY_CUSTOM_TITLE = "custom_title";
- public static final String KEY_NAME = "name";
public static final String KEY_LINK = "link";
public static final String KEY_DESCRIPTION = "description";
public static final String KEY_FILE_URL = "file_url";
@@ -1024,8 +1015,8 @@ public class PodDBAdapter {
return db.rawQuery(query, null);
}
- public final Cursor getRecentlyPublishedItemsCursor(int limit) {
- return db.query(TABLE_NAME_FEED_ITEMS, FEEDITEM_SEL_FI_SMALL, null, null, null, null, KEY_PUBDATE + " DESC LIMIT " + limit);
+ public final Cursor getRecentlyPublishedItemsCursor(int offset, int limit) {
+ return db.query(TABLE_NAME_FEED_ITEMS, FEEDITEM_SEL_FI_SMALL, null, null, null, null, KEY_PUBDATE + " DESC LIMIT " + offset + ", " + limit);
}
public Cursor getDownloadedItemsCursor() {
@@ -1404,13 +1395,6 @@ public class PodDBAdapter {
return db.rawQuery(query, null);
}
-
- public static final int IDX_FEEDSTATISTICS_FEED = 0;
- public static final int IDX_FEEDSTATISTICS_NUM_ITEMS = 1;
- public static final int IDX_FEEDSTATISTICS_NEW_ITEMS = 2;
- public static final int IDX_FEEDSTATISTICS_LATEST_EPISODE = 3;
- public static final int IDX_FEEDSTATISTICS_IN_PROGRESS_EPISODES = 4;
-
/**
* Select number of items, new items, the date of the latest episode and the number of episodes in progress. The result
* is sorted by the title of the feed.
@@ -1495,11 +1479,9 @@ public class PodDBAdapter {
@Override
public void onUpgrade(final SQLiteDatabase db, final int oldVersion,
final int newVersion) {
- EventBus.getDefault().post(ProgressEvent.start(context.getString(R.string.progress_upgrading_database)));
Log.w("DBAdapter", "Upgrading from version " + oldVersion + " to "
+ newVersion + ".");
DBUpgrader.upgrade(db, oldVersion, newVersion);
- EventBus.getDefault().post(ProgressEvent.end());
}
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/DuckType.java b/core/src/main/java/de/danoeh/antennapod/core/util/DuckType.java
deleted file mode 100644
index 69dc38895..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/util/DuckType.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/* Adapted from: http://thinking-in-code.blogspot.com/2008/11/duck-typing-in-java-using-dynamic.html */
-
-package de.danoeh.antennapod.core.util;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-
-import de.danoeh.antennapod.core.BuildConfig;
-
-/**
- * Allows "duck typing" or dynamic invocation based on method signature rather
- * than type hierarchy. In other words, rather than checking whether something
- * IS-a duck, check whether it WALKS-like-a duck or QUACKS-like a duck.
- *
- * To use first use the coerce static method to indicate the object you want to
- * do Duck Typing for, then specify an interface to the to method which you want
- * to coerce the type to, e.g:
- *
- * public interface Foo { void aMethod(); } class Bar { ... public void
- * aMethod() { ... } ... } Bar bar = ...; Foo foo =
- * DuckType.coerce(bar).to(Foo.class); foo.aMethod();
- *
- *
- */
-public class DuckType {
-
- private final Object objectToCoerce;
-
- private DuckType(Object objectToCoerce) {
- this.objectToCoerce = objectToCoerce;
- }
-
- private class CoercedProxy implements InvocationHandler {
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- Method delegateMethod = findMethodBySignature(method);
- assert delegateMethod != null;
- return delegateMethod.invoke(DuckType.this.objectToCoerce, args);
- }
- }
-
- /**
- * Specify the duck typed object to coerce.
- *
- * @param object
- * the object to coerce
- * @return
- */
- public static DuckType coerce(Object object) {
- return new DuckType(object);
- }
-
- /**
- * Coerce the Duck Typed object to the given interface providing it
- * implements all the necessary methods.
- *
- * @param
- * @param iface
- * @return an instance of the given interface that wraps the duck typed
- * class
- * @throws ClassCastException
- * if the object being coerced does not implement all the
- * methods in the given interface.
- */
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public <T> T to(Class iface) {
- if (BuildConfig.DEBUG && !iface.isInterface()) throw new AssertionError("cannot coerce object to a class, must be an interface");
- if (isA(iface)) {
- return (T) iface.cast(objectToCoerce);
- }
- if (quacksLikeA(iface)) {
- return generateProxy(iface);
- }
- throw new ClassCastException("Could not coerce object of type " + objectToCoerce.getClass() + " to " + iface);
- }
-
- @SuppressWarnings("rawtypes")
- private boolean isA(Class iface) {
- return objectToCoerce.getClass().isInstance(iface);
- }
-
- /**
- * Determine whether the duck typed object can be used with the given
- * interface.
- *
- * @param Type
- * of the interface to check.
- * @param iface
- * Interface class to check
- * @return true if the object will support all the methods in the interface,
- * false otherwise.
- */
- @SuppressWarnings("rawtypes")
- private boolean quacksLikeA(Class iface) {
- for (Method method : iface.getMethods()) {
- if (findMethodBySignature(method) == null) {
- return false;
- }
- }
- return true;
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- private <T> T generateProxy(Class iface) {
- return (T) Proxy.newProxyInstance(iface.getClassLoader(), new Class[] { iface }, new CoercedProxy());
- }
-
- private Method findMethodBySignature(Method method) {
- try {
- return objectToCoerce.getClass().getMethod(method.getName(), method.getParameterTypes());
- } catch (NoSuchMethodException e) {
- return null;
- }
- }
-
-} \ No newline at end of file
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/FeedItemUtil.java b/core/src/main/java/de/danoeh/antennapod/core/util/FeedItemUtil.java
index 826c06822..a8206d3bd 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/FeedItemUtil.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/FeedItemUtil.java
@@ -7,19 +7,6 @@ import de.danoeh.antennapod.core.feed.FeedItem;
public class FeedItemUtil {
private FeedItemUtil(){}
- public static int indexOfItemWithDownloadUrl(List<FeedItem> items, String downloadUrl) {
- if(items == null) {
- return -1;
- }
- for(int i=0; i < items.size(); i++) {
- FeedItem item = items.get(i);
- if(item.hasMedia() && item.getMedia().getDownload_url().equals(downloadUrl)) {
- return i;
- }
- }
- return -1;
- }
-
public static int indexOfItemWithId(List<FeedItem> items, long id) {
for(int i=0; i < items.size(); i++) {
FeedItem item = items.get(i);
@@ -40,17 +27,6 @@ public class FeedItemUtil {
return -1;
}
- public static long[] getIds(FeedItem... items) {
- if(items == null || items.length == 0) {
- return new long[0];
- }
- long[] result = new long[items.length];
- for(int i=0; i < items.length; i++) {
- result[i] = items[i].getId();
- }
- return result;
- }
-
public static long[] getIds(List<FeedItem> items) {
if(items == null || items.size() == 0) {
return new long[0];
@@ -62,20 +38,6 @@ public class FeedItemUtil {
return result;
}
- public static boolean containsAnyId(List<FeedItem> items, long[] ids) {
- if(items == null || items.size() == 0) {
- return false;
- }
- for(FeedItem item : items) {
- for(long id : ids) {
- if(item.getId() == id) {
- return true;
- }
- }
- }
- return false;
- }
-
/**
* Get the link for the feed item for the purpose of Share. It fallbacks to
* use the feed's link if the named feed item has no link.
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/FeedUpdateUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/FeedUpdateUtils.java
deleted file mode 100644
index b425687ae..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/util/FeedUpdateUtils.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package de.danoeh.antennapod.core.util;
-
-import android.content.Context;
-import android.util.Log;
-
-import org.awaitility.core.ConditionTimeoutException;
-
-import java.util.concurrent.TimeUnit;
-
-import de.danoeh.antennapod.core.storage.DBTasks;
-
-import static org.awaitility.Awaitility.with;
-
-public class FeedUpdateUtils {
- private static final String TAG = "FeedUpdateUtils";
-
- private FeedUpdateUtils() {}
-
- public static void startAutoUpdate(Context context, Runnable callback) {
- // the network check is blocking for possibly a long time: so run the logic
- // in a separate thread to prevent the code blocking the callers
- final Runnable runnable = () -> {
- try {
- with().pollInterval(1, TimeUnit.SECONDS)
- .await()
- .atMost(10, TimeUnit.SECONDS)
- .until(() -> NetworkUtils.networkAvailable() && NetworkUtils.isFeedRefreshAllowed());
- DBTasks.refreshAllFeeds(context, null, callback);
- } catch (ConditionTimeoutException ignore) {
- Log.d(TAG, "Blocking automatic update: no wifi available / no mobile updates allowed");
- }
- };
- new Thread(runnable).start();
- }
-
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/FeedtitleComparator.java b/core/src/main/java/de/danoeh/antennapod/core/util/FeedtitleComparator.java
deleted file mode 100644
index 29d095cd2..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/util/FeedtitleComparator.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package de.danoeh.antennapod.core.util;
-
-import java.util.Comparator;
-
-import de.danoeh.antennapod.core.feed.Feed;
-
-/** Compares the title of two feeds for sorting. */
-class FeedtitleComparator implements Comparator<Feed> {
-
- @Override
- public int compare(Feed lhs, Feed rhs) {
- return lhs.getTitle().compareToIgnoreCase(rhs.getTitle());
- }
-
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java
index e81ab47ed..656b518bf 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java
@@ -1,13 +1,20 @@
package de.danoeh.antennapod.core.util;
+import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.util.Log;
+import android.widget.Toast;
+import de.danoeh.antennapod.core.R;
import java.util.List;
public class IntentUtils {
+ private static final String TAG = "IntentUtils";
+
private IntentUtils(){}
/*
@@ -28,4 +35,13 @@ public class IntentUtils {
context.sendBroadcast(new Intent(action).setPackage(context.getPackageName()));
}
+ public static void openInBrowser(Context context, String url) {
+ try {
+ Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+ context.startActivity(myIntent);
+ } catch (ActivityNotFoundException e) {
+ Toast.makeText(context, R.string.pref_no_browser_found, Toast.LENGTH_LONG).show();
+ Log.e(TAG, Log.getStackTraceString(e));
+ }
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/Optional.java b/core/src/main/java/de/danoeh/antennapod/core/util/Optional.java
index 0fe11ec53..37f12c01c 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/Optional.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/Optional.java
@@ -77,7 +77,7 @@ public final class Optional<T> {
* @param <T> Type of the non-existent value
* @return an empty {@code Optional}
*/
- public static<T> Optional<T> empty() {
+ public static <T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/QueueSorter.java b/core/src/main/java/de/danoeh/antennapod/core/util/QueueSorter.java
index 37172d042..0c21ca393 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/QueueSorter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/QueueSorter.java
@@ -164,7 +164,7 @@ public class QueueSorter {
Collections.sort(feedItems, itemComparator);
if (spread == 0) {
spread = feedItems.size();
- } else if (feedItems.size() % spread != 0){
+ } else if (spread % feedItems.size() != 0){
spread *= feedItems.size();
}
}
@@ -180,6 +180,9 @@ public class QueueSorter {
Map<Long, List<FeedItem>> spreadItems = new HashMap<>();
for (List<FeedItem> feedItems : feeds) {
long thisSpread = spread / feedItems.size();
+ if (thisSpread == 0) {
+ thisSpread = 1;
+ }
// Starting from 0 ensures we front-load, so the queue starts with one episode from
// each feed in the queue
long itemSpread = 0;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java
index 14f091249..1da7a5c50 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java
@@ -3,30 +3,11 @@ package de.danoeh.antennapod.core.util;
import android.content.Context;
import android.support.annotation.AttrRes;
import android.support.annotation.ColorInt;
-import android.util.Log;
import android.util.TypedValue;
-import de.danoeh.antennapod.core.R;
-import de.danoeh.antennapod.core.preferences.UserPreferences;
-
public class ThemeUtils {
- private ThemeUtils(){}
-
- private static final String TAG = "ThemeUtils";
+ private ThemeUtils() {
- public static int getSelectionBackgroundColor() {
- int theme = UserPreferences.getTheme();
- if (theme == R.style.Theme_AntennaPod_Dark) {
- return R.color.selection_background_color_dark;
- } else if (theme == R.style.Theme_AntennaPod_TrueBlack){
- return R.color.selection_background_color_trueblack;
- } else if (theme == R.style.Theme_AntennaPod_Light) {
- return R.color.selection_background_color_light;
- } else {
- Log.e(TAG,
- "getSelectionBackgroundColor could not match the current theme to any color!");
- return R.color.selection_background_color_light;
- }
}
public static @ColorInt int getColorFromAttr(Context context, @AttrRes int attr) {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/TimeSpeedConverter.java b/core/src/main/java/de/danoeh/antennapod/core/util/TimeSpeedConverter.java
index 5fea8238b..5d44c14b8 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/TimeSpeedConverter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/TimeSpeedConverter.java
@@ -3,18 +3,19 @@ package de.danoeh.antennapod.core.util;
import de.danoeh.antennapod.core.preferences.UserPreferences;
public class TimeSpeedConverter {
- private TimeSpeedConverter() {
+ private final float speed;
+ public TimeSpeedConverter(float speed) {
+ this.speed = speed;
}
/** Convert millisecond according to the current playback speed
* @param time: time to convert
* @return converted time (can be < 0 if time is < 0)
*/
- public static int convert(int time) {
+ public int convert(int time) {
boolean timeRespectsSpeed = UserPreferences.timeRespectsSpeed();
if (time > 0 && timeRespectsSpeed) {
- float speed = Float.parseFloat(UserPreferences.getPlaybackSpeed());
return (int)(time / speed);
}
return time;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/SearchResultValueComparator.java b/core/src/main/java/de/danoeh/antennapod/core/util/comparator/SearchResultValueComparator.java
deleted file mode 100644
index 56a684475..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/SearchResultValueComparator.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package de.danoeh.antennapod.core.util.comparator;
-
-import java.util.Comparator;
-
-import de.danoeh.antennapod.core.feed.FeedItem;
-import de.danoeh.antennapod.core.feed.SearchResult;
-
-public class SearchResultValueComparator implements Comparator<SearchResult> {
-
- /**
- * Compare items based, first, on where they were found (ie. title, chapters, or show notes).
- * If they were found in the same section, then compare based on the title, in lexicographic
- * order. This is still not ideal since, for example, "#12 Example A" would be considered
- * before "#8 Example B" due to the fact that "8" has a larger unicode value than "1"
- */
- @Override
- public int compare(SearchResult lhs, SearchResult rhs) {
- int value = rhs.getValue() - lhs.getValue();
- if (value == 0 && lhs.getComponent() instanceof FeedItem && rhs.getComponent() instanceof FeedItem) {
- String lhsTitle = ((FeedItem) lhs.getComponent()).getTitle();
- String rhsTitle = ((FeedItem) rhs.getComponent()).getTitle();
- return lhsTitle.compareTo(rhsTitle);
- }
- return value;
- }
-
-}
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 412b150fa..ebeec058d 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
@@ -1,21 +1,29 @@
package de.danoeh.antennapod.core.util.download;
+import android.content.Context;
+import android.support.annotation.NonNull;
import android.util.Log;
+
import androidx.work.Constraints;
+import androidx.work.Data;
import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.ExistingWorkPolicy;
import androidx.work.NetworkType;
import androidx.work.OneTimeWorkRequest;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;
-import de.danoeh.antennapod.core.preferences.UserPreferences;
-import de.danoeh.antennapod.core.service.FeedUpdateWorker;
+import java.util.Arrays;
import java.util.Calendar;
import java.util.concurrent.TimeUnit;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.service.FeedUpdateWorker;
+import de.danoeh.antennapod.core.storage.DBTasks;
+
public class AutoUpdateManager {
- private static final String WORK_ID_FEED_UPDATE = FeedUpdateWorker.class.getName();
+ private static final String WORK_ID_FEED_UPDATE = "de.danoeh.antennapod.core.service.FeedUpdateWorker";
+ private static final String WORK_ID_FEED_UPDATE_ONCE = WORK_ID_FEED_UPDATE + "Once";
private static final String TAG = "AutoUpdateManager";
private AutoUpdateManager() {
@@ -23,9 +31,25 @@ public class AutoUpdateManager {
}
/**
+ * Start / restart periodic auto feed refresh
+ */
+ public static void restartUpdateAlarm() {
+ if (UserPreferences.isAutoUpdateDisabled()) {
+ disableAutoUpdate();
+ } else if (UserPreferences.isAutoUpdateTimeOfDay()) {
+ int[] timeOfDay = UserPreferences.getUpdateTimeOfDay();
+ Log.d(TAG, "timeOfDay: " + Arrays.toString(timeOfDay));
+ restartUpdateTimeOfDayAlarm(timeOfDay[0], timeOfDay[1]);
+ } else {
+ long milliseconds = UserPreferences.getUpdateInterval();
+ restartUpdateIntervalAlarm(milliseconds);
+ }
+ }
+
+ /**
* Sets the interval in which the feeds are refreshed automatically
*/
- public static void restartUpdateIntervalAlarm(long intervalMillis) {
+ private static void restartUpdateIntervalAlarm(long intervalMillis) {
Log.d(TAG, "Restarting update alarm.");
PeriodicWorkRequest workRequest = new PeriodicWorkRequest.Builder(FeedUpdateWorker.class,
@@ -40,7 +64,7 @@ public class AutoUpdateManager {
/**
* Sets time of day the feeds are refreshed automatically
*/
- public static void restartUpdateTimeOfDayAlarm(int hoursOfDay, int minute) {
+ private static void restartUpdateTimeOfDayAlarm(int hoursOfDay, int minute) {
Log.d(TAG, "Restarting update alarm.");
Calendar now = Calendar.getInstance();
@@ -60,6 +84,41 @@ public class AutoUpdateManager {
WorkManager.getInstance().enqueueUniqueWork(WORK_ID_FEED_UPDATE, ExistingWorkPolicy.REPLACE, workRequest);
}
+ /**
+ * Run auto feed refresh once in background, as soon as what OS scheduling allows.
+ *
+ * Callers from UI should use {@link #runImmediate(Context)}, as it will guarantee
+ * the refresh be run immediately.
+ */
+ public static void runOnce() {
+ Log.d(TAG, "Run auto update once, as soon as OS allows.");
+
+ OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(FeedUpdateWorker.class)
+ .setConstraints(getConstraints())
+ .setInitialDelay(0L, TimeUnit.MILLISECONDS)
+ .setInputData(new Data.Builder()
+ .putBoolean(FeedUpdateWorker.PARAM_RUN_ONCE, true)
+ .build()
+ )
+ .build();
+
+ WorkManager.getInstance().enqueueUniqueWork(WORK_ID_FEED_UPDATE_ONCE, ExistingWorkPolicy.REPLACE, workRequest);
+
+ }
+
+ /**
+ /**
+ * Run auto feed refresh once in background immediately, using its own thread.
+ *
+ * Callers where the additional threads is not suitable should use {@link #runOnce()}
+ */
+ public static void runImmediate(@NonNull Context context) {
+ Log.d(TAG, "Run auto update immediately in background.");
+ new Thread(() -> {
+ DBTasks.refreshAllFeeds(context.getApplicationContext());
+ }, "ManualRefreshAllFeeds").start();
+ }
+
public static void disableAutoUpdate() {
WorkManager.getInstance().cancelUniqueWork(WORK_ID_FEED_UPDATE);
}
@@ -74,4 +133,5 @@ public class AutoUpdateManager {
}
return constraints.build();
}
+
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/exception/RxJavaErrorHandlerSetup.java b/core/src/main/java/de/danoeh/antennapod/core/util/exception/RxJavaErrorHandlerSetup.java
new file mode 100644
index 000000000..223104d2e
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/exception/RxJavaErrorHandlerSetup.java
@@ -0,0 +1,24 @@
+package de.danoeh.antennapod.core.util.exception;
+
+import android.util.Log;
+import io.reactivex.exceptions.UndeliverableException;
+import io.reactivex.plugins.RxJavaPlugins;
+
+public class RxJavaErrorHandlerSetup {
+
+ private RxJavaErrorHandlerSetup() {
+
+ }
+
+ public static void setupRxJavaErrorHandler() {
+ RxJavaPlugins.setErrorHandler(e -> {
+ if (e instanceof UndeliverableException) {
+ // Probably just disposed because the fragment was left
+ Log.d("RxJavaErrorHandler", "Ignored exception: " + Log.getStackTraceString(e));
+ return;
+ }
+ Thread.currentThread().getUncaughtExceptionHandler()
+ .uncaughtException(Thread.currentThread(), e);
+ });
+ }
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java b/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java
index d22d08e09..a3f747e09 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java
@@ -72,7 +72,7 @@ public class ChapterReader extends ID3Reader {
String decodedLink = URLDecoder.decode(link.toString(), "UTF-8");
currentChapter.setLink(decodedLink);
Log.d(TAG, "Found link: " + currentChapter.getLink());
- } catch (IllegalArgumentException _iae) {
+ } catch (IllegalArgumentException iae) {
Log.w(TAG, "Bad URL found in ID3 data");
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/ExternalMedia.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/ExternalMedia.java
index 645bae5f3..9b644c3ba 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/ExternalMedia.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/ExternalMedia.java
@@ -182,7 +182,7 @@ public class ExternalMedia implements Playable {
editor.putLong(PREF_LAST_PLAYED_TIME, timestamp);
position = newPosition;
lastPlayedTime = timestamp;
- editor.commit();
+ editor.apply();
}
@Override
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/MediaPlayerError.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/MediaPlayerError.java
index b04c02075..32d37a67e 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/MediaPlayerError.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/MediaPlayerError.java
@@ -16,10 +16,16 @@ public class MediaPlayerError {
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
resId = R.string.playback_error_server_died;
break;
+ case MediaPlayer.MEDIA_ERROR_UNSUPPORTED:
+ resId = R.string.playback_error_unsupported;
+ break;
+ case MediaPlayer.MEDIA_ERROR_TIMED_OUT:
+ resId = R.string.playback_error_timeout;
+ break;
default:
resId = R.string.playback_error_unknown;
break;
}
- return context.getString(resId);
+ return context.getString(resId) + " (" + code + ")";
}
}
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 6191d4491..1456ebd8d 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
@@ -21,11 +21,10 @@ import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
-import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.core.R;
+import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import de.danoeh.antennapod.core.event.ServiceEvent;
import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.FeedMedia;
@@ -54,7 +53,7 @@ import org.greenrobot.eventbus.ThreadMode;
* Communicates with the playback service. GUI classes should use this class to
* control playback instead of communicating with the PlaybackService directly.
*/
-public abstract class PlaybackController {
+public class PlaybackController {
private static final String TAG = "PlaybackController";
@@ -69,9 +68,6 @@ public abstract class PlaybackController {
private final ScheduledThreadPoolExecutor schedExecutor;
private static final int SCHED_EX_POOLSIZE = 1;
- private MediaPositionObserver positionObserver;
- private ScheduledFuture<?> positionObserverFuture;
-
private boolean mediaInfoLoaded = false;
private boolean released = false;
private boolean initialized = false;
@@ -177,7 +173,6 @@ public abstract class PlaybackController {
} catch (IllegalArgumentException e) {
// ignore
}
- cancelPositionObserver();
schedExecutor.shutdownNow();
media = null;
released = true;
@@ -210,7 +205,7 @@ public abstract class PlaybackController {
.observeOn(AndroidSchedulers.mainThread())
.subscribe(optionalIntent -> {
boolean bound = false;
- if (!PlaybackService.started) {
+ if (!PlaybackService.isRunning) {
if (optionalIntent.isPresent()) {
Log.d(TAG, "Calling start service");
ContextCompat.startForegroundService(activity, optionalIntent.get());
@@ -254,29 +249,6 @@ public abstract class PlaybackController {
.getIntent());
}
-
-
- private void setupPositionObserver() {
- if (positionObserverFuture == null ||
- positionObserverFuture.isCancelled() ||
- positionObserverFuture.isDone()) {
-
- Log.d(TAG, "Setting up position observer");
- positionObserver = new MediaPositionObserver();
- positionObserverFuture = schedExecutor.scheduleWithFixedDelay(
- positionObserver, MediaPositionObserver.WAITING_INTERVALL,
- MediaPositionObserver.WAITING_INTERVALL,
- TimeUnit.MILLISECONDS);
- }
- }
-
- private void cancelPositionObserver() {
- if (positionObserverFuture != null) {
- boolean result = positionObserverFuture.cancel(true);
- Log.d(TAG, "PositionObserver cancelled. Result: " + result);
- }
- }
-
private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if(service instanceof PlaybackService.LocalBinder) {
@@ -337,7 +309,6 @@ public abstract class PlaybackController {
onBufferUpdate(progress);
break;
case PlaybackService.NOTIFICATION_TYPE_RELOAD:
- cancelPositionObserver();
mediaInfoLoaded = false;
queryService();
onReloadNotification(intent.getIntExtra(
@@ -447,7 +418,6 @@ public abstract class PlaybackController {
case PAUSED:
clearStatusMsg();
checkMediaInfoLoaded();
- cancelPositionObserver();
onPositionObserverUpdate();
updatePlayButtonAppearance(playResource, playText);
if (!PlaybackService.isCasting() &&
@@ -463,7 +433,6 @@ public abstract class PlaybackController {
onAwaitingVideoSurface();
setScreenOn(true);
}
- setupPositionObserver();
updatePlayButtonAppearance(pauseResource, pauseText);
break;
case PREPARING:
@@ -567,7 +536,8 @@ public abstract class PlaybackController {
if (fromUser && playbackService != null && media != null) {
float prog = progress / ((float) seekBar.getMax());
int duration = media.getDuration();
- int position = TimeSpeedConverter.convert((int) (prog * duration));
+ TimeSpeedConverter converter = new TimeSpeedConverter(playbackService.getCurrentPlaybackSpeed());
+ int position = converter.convert((int) (prog * duration));
txtvPosition.setText(Converter.getDurationStringLong(position));
return prog;
}
@@ -580,7 +550,6 @@ public abstract class PlaybackController {
*/
public void onSeekBarStartTrackingTouch(SeekBar seekBar) {
// interrupt position Observer, restart later
- cancelPositionObserver();
}
/**
@@ -589,7 +558,6 @@ public abstract class PlaybackController {
public void onSeekBarStopTrackingTouch(SeekBar seekBar, float prog) {
if (playbackService != null && media != null) {
playbackService.seekTo((int) (prog * media.getDuration()));
- setupPositionObserver();
}
}
@@ -719,6 +687,7 @@ public abstract class PlaybackController {
public boolean canSetPlaybackSpeed() {
return org.antennapod.audio.MediaPlayer.isPrestoLibraryInstalled(activity.getApplicationContext())
|| UserPreferences.useSonic()
+ || UserPreferences.useExoplayer()
|| Build.VERSION.SDK_INT >= 23
|| (playbackService != null && playbackService.canSetSpeed());
}
@@ -726,6 +695,8 @@ public abstract class PlaybackController {
public void setPlaybackSpeed(float speed) {
if (playbackService != null) {
playbackService.setSpeed(speed);
+ } else {
+ onPlaybackSpeedChange();
}
}
public void setSkipSilence(boolean skipSilence) {
@@ -741,7 +712,7 @@ public abstract class PlaybackController {
}
public float getCurrentPlaybackSpeedMultiplier() {
- if (canSetPlaybackSpeed()) {
+ if (playbackService != null && canSetPlaybackSpeed()) {
return playbackService.getCurrentPlaybackSpeed();
} else {
return -1;
@@ -832,19 +803,4 @@ public abstract class PlaybackController {
}
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
-
- /**
- * Refreshes the current position of the media file that is playing.
- */
- public class MediaPositionObserver implements Runnable {
-
- static final int WAITING_INTERVALL = 1000;
-
- @Override
- public void run() {
- if (playbackService != null && playbackService.getStatus() == PlayerStatus.PLAYING) {
- activity.runOnUiThread(PlaybackController.this::onPositionObserverUpdate);
- }
- }
- }
}
diff --git a/core/src/main/res/drawable-hdpi/ic_baseline_question_answer_white_24dp.png b/core/src/main/res/drawable-hdpi/ic_baseline_question_answer_white_24dp.png
deleted file mode 100755
index 67924a5a2..000000000
--- a/core/src/main/res/drawable-hdpi/ic_baseline_question_answer_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_cast_disabled_light.png b/core/src/main/res/drawable-hdpi/ic_cast_disabled_light.png
deleted file mode 100644
index c0a55d555..000000000
--- a/core/src/main/res/drawable-hdpi/ic_cast_disabled_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_cast_light.png b/core/src/main/res/drawable-hdpi/ic_cast_light.png
deleted file mode 100644
index b0c581a0e..000000000
--- a/core/src/main/res/drawable-hdpi/ic_cast_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_cast_off_light.png b/core/src/main/res/drawable-hdpi/ic_cast_off_light.png
deleted file mode 100644
index 5f3c0179c..000000000
--- a/core/src/main/res/drawable-hdpi/ic_cast_off_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_cast_on_0_light.png b/core/src/main/res/drawable-hdpi/ic_cast_on_0_light.png
deleted file mode 100644
index e872693a4..000000000
--- a/core/src/main/res/drawable-hdpi/ic_cast_on_0_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_cast_on_1_light.png b/core/src/main/res/drawable-hdpi/ic_cast_on_1_light.png
deleted file mode 100644
index d8be1ebc6..000000000
--- a/core/src/main/res/drawable-hdpi/ic_cast_on_1_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_cast_on_2_light.png b/core/src/main/res/drawable-hdpi/ic_cast_on_2_light.png
deleted file mode 100644
index 27cda9e9d..000000000
--- a/core/src/main/res/drawable-hdpi/ic_cast_on_2_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_cast_on_light.png b/core/src/main/res/drawable-hdpi/ic_cast_on_light.png
deleted file mode 100644
index 4ee525875..000000000
--- a/core/src/main/res/drawable-hdpi/ic_cast_on_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_close_light.png b/core/src/main/res/drawable-hdpi/ic_close_light.png
deleted file mode 100644
index 93187e450..000000000
--- a/core/src/main/res/drawable-hdpi/ic_close_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_format_list_bulleted_grey600_24dp.png b/core/src/main/res/drawable-hdpi/ic_format_list_bulleted_grey600_24dp.png
deleted file mode 100644
index 3668c9a00..000000000
--- a/core/src/main/res/drawable-hdpi/ic_format_list_bulleted_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_format_list_bulleted_white_24dp.png b/core/src/main/res/drawable-hdpi/ic_format_list_bulleted_white_24dp.png
deleted file mode 100644
index a1a2c5b68..000000000
--- a/core/src/main/res/drawable-hdpi/ic_format_list_bulleted_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_forum_grey600_24dp.png b/core/src/main/res/drawable-hdpi/ic_forum_grey600_24dp.png
deleted file mode 100644
index da5398d15..000000000
--- a/core/src/main/res/drawable-hdpi/ic_forum_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_media_cast_disconnect.png b/core/src/main/res/drawable-hdpi/ic_media_cast_disconnect.png
deleted file mode 100644
index 700c116e5..000000000
--- a/core/src/main/res/drawable-hdpi/ic_media_cast_disconnect.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_pause_light.png b/core/src/main/res/drawable-hdpi/ic_pause_light.png
deleted file mode 100644
index 0c505d1c8..000000000
--- a/core/src/main/res/drawable-hdpi/ic_pause_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_play_light.png b/core/src/main/res/drawable-hdpi/ic_play_light.png
deleted file mode 100644
index 7957dff5b..000000000
--- a/core/src/main/res/drawable-hdpi/ic_play_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_stat_antenna_default.png b/core/src/main/res/drawable-hdpi/ic_stat_antenna_default.png
deleted file mode 100644
index af99f4b3b..000000000
--- a/core/src/main/res/drawable-hdpi/ic_stat_antenna_default.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_stat_authentication.png b/core/src/main/res/drawable-hdpi/ic_stat_authentication.png
deleted file mode 100644
index 398dffa4b..000000000
--- a/core/src/main/res/drawable-hdpi/ic_stat_authentication.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-ldpi/ic_stat_antenna_default.png b/core/src/main/res/drawable-ldpi/ic_stat_antenna_default.png
deleted file mode 100644
index ddf545c0b..000000000
--- a/core/src/main/res/drawable-ldpi/ic_stat_antenna_default.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_baseline_question_answer_white_24dp.png b/core/src/main/res/drawable-mdpi/ic_baseline_question_answer_white_24dp.png
deleted file mode 100755
index e87df752e..000000000
--- a/core/src/main/res/drawable-mdpi/ic_baseline_question_answer_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_cast_disabled_light.png b/core/src/main/res/drawable-mdpi/ic_cast_disabled_light.png
deleted file mode 100644
index 7940a0332..000000000
--- a/core/src/main/res/drawable-mdpi/ic_cast_disabled_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_cast_light.png b/core/src/main/res/drawable-mdpi/ic_cast_light.png
deleted file mode 100644
index 1f5bec20b..000000000
--- a/core/src/main/res/drawable-mdpi/ic_cast_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_cast_off_light.png b/core/src/main/res/drawable-mdpi/ic_cast_off_light.png
deleted file mode 100644
index 963db27d4..000000000
--- a/core/src/main/res/drawable-mdpi/ic_cast_off_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_cast_on_0_light.png b/core/src/main/res/drawable-mdpi/ic_cast_on_0_light.png
deleted file mode 100644
index a90d9e305..000000000
--- a/core/src/main/res/drawable-mdpi/ic_cast_on_0_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_cast_on_1_light.png b/core/src/main/res/drawable-mdpi/ic_cast_on_1_light.png
deleted file mode 100644
index bb2cf30bf..000000000
--- a/core/src/main/res/drawable-mdpi/ic_cast_on_1_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_cast_on_2_light.png b/core/src/main/res/drawable-mdpi/ic_cast_on_2_light.png
deleted file mode 100644
index 3ed59e55b..000000000
--- a/core/src/main/res/drawable-mdpi/ic_cast_on_2_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_cast_on_light.png b/core/src/main/res/drawable-mdpi/ic_cast_on_light.png
deleted file mode 100644
index 713427b97..000000000
--- a/core/src/main/res/drawable-mdpi/ic_cast_on_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_close_light.png b/core/src/main/res/drawable-mdpi/ic_close_light.png
deleted file mode 100644
index 2c52c9b0f..000000000
--- a/core/src/main/res/drawable-mdpi/ic_close_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_format_list_bulleted_grey600_24dp.png b/core/src/main/res/drawable-mdpi/ic_format_list_bulleted_grey600_24dp.png
deleted file mode 100644
index 726eae499..000000000
--- a/core/src/main/res/drawable-mdpi/ic_format_list_bulleted_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_format_list_bulleted_white_24dp.png b/core/src/main/res/drawable-mdpi/ic_format_list_bulleted_white_24dp.png
deleted file mode 100644
index 0cc401dff..000000000
--- a/core/src/main/res/drawable-mdpi/ic_format_list_bulleted_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_forum_grey600_24dp.png b/core/src/main/res/drawable-mdpi/ic_forum_grey600_24dp.png
deleted file mode 100644
index d3bcfe7b6..000000000
--- a/core/src/main/res/drawable-mdpi/ic_forum_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_media_cast_disconnect.png b/core/src/main/res/drawable-mdpi/ic_media_cast_disconnect.png
deleted file mode 100644
index 767f420df..000000000
--- a/core/src/main/res/drawable-mdpi/ic_media_cast_disconnect.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_pause_light.png b/core/src/main/res/drawable-mdpi/ic_pause_light.png
deleted file mode 100644
index 6218a774f..000000000
--- a/core/src/main/res/drawable-mdpi/ic_pause_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_play_light.png b/core/src/main/res/drawable-mdpi/ic_play_light.png
deleted file mode 100644
index 1e0ccaf80..000000000
--- a/core/src/main/res/drawable-mdpi/ic_play_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_stat_antenna_default.png b/core/src/main/res/drawable-mdpi/ic_stat_antenna_default.png
deleted file mode 100644
index 41fd20655..000000000
--- a/core/src/main/res/drawable-mdpi/ic_stat_antenna_default.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_stat_authentication.png b/core/src/main/res/drawable-mdpi/ic_stat_authentication.png
deleted file mode 100644
index 550b56b33..000000000
--- a/core/src/main/res/drawable-mdpi/ic_stat_authentication.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_baseline_question_answer_white_24dp.png b/core/src/main/res/drawable-xhdpi/ic_baseline_question_answer_white_24dp.png
deleted file mode 100755
index 731f89c83..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_baseline_question_answer_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_cast_disabled_light.png b/core/src/main/res/drawable-xhdpi/ic_cast_disabled_light.png
deleted file mode 100644
index fbb3e062c..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_cast_disabled_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_cast_light.png b/core/src/main/res/drawable-xhdpi/ic_cast_light.png
deleted file mode 100644
index f2713e20e..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_cast_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_cast_off_light.png b/core/src/main/res/drawable-xhdpi/ic_cast_off_light.png
deleted file mode 100644
index f4f8aaea8..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_cast_off_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_cast_on_0_light.png b/core/src/main/res/drawable-xhdpi/ic_cast_on_0_light.png
deleted file mode 100644
index 247fc95ba..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_cast_on_0_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_cast_on_1_light.png b/core/src/main/res/drawable-xhdpi/ic_cast_on_1_light.png
deleted file mode 100644
index ecf4b4723..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_cast_on_1_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_cast_on_2_light.png b/core/src/main/res/drawable-xhdpi/ic_cast_on_2_light.png
deleted file mode 100644
index 60e3afa5d..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_cast_on_2_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_cast_on_light.png b/core/src/main/res/drawable-xhdpi/ic_cast_on_light.png
deleted file mode 100644
index 40ce9d4f2..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_cast_on_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_close_light.png b/core/src/main/res/drawable-xhdpi/ic_close_light.png
deleted file mode 100644
index 49faa429a..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_close_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_format_list_bulleted_grey600_24dp.png b/core/src/main/res/drawable-xhdpi/ic_format_list_bulleted_grey600_24dp.png
deleted file mode 100644
index 322adb6e0..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_format_list_bulleted_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_format_list_bulleted_white_24dp.png b/core/src/main/res/drawable-xhdpi/ic_format_list_bulleted_white_24dp.png
deleted file mode 100644
index c25860017..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_format_list_bulleted_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_forum_grey600_24dp.png b/core/src/main/res/drawable-xhdpi/ic_forum_grey600_24dp.png
deleted file mode 100644
index ac6876140..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_forum_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_media_cast_disconnect.png b/core/src/main/res/drawable-xhdpi/ic_media_cast_disconnect.png
deleted file mode 100644
index 740867129..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_media_cast_disconnect.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_pause_light.png b/core/src/main/res/drawable-xhdpi/ic_pause_light.png
deleted file mode 100644
index 40cd79f14..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_pause_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_play_light.png b/core/src/main/res/drawable-xhdpi/ic_play_light.png
deleted file mode 100644
index 33f6a5919..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_play_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_stat_antenna_default.png b/core/src/main/res/drawable-xhdpi/ic_stat_antenna_default.png
deleted file mode 100644
index 30431ed6a..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_stat_antenna_default.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_stat_authentication.png b/core/src/main/res/drawable-xhdpi/ic_stat_authentication.png
deleted file mode 100644
index e83cbc333..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_stat_authentication.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_baseline_question_answer_white_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_baseline_question_answer_white_24dp.png
deleted file mode 100755
index 255b82707..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_baseline_question_answer_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_cast_disabled_light.png b/core/src/main/res/drawable-xxhdpi/ic_cast_disabled_light.png
deleted file mode 100644
index e94df3889..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_cast_disabled_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_cast_light.png b/core/src/main/res/drawable-xxhdpi/ic_cast_light.png
deleted file mode 100644
index c5722a6eb..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_cast_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_cast_off_light.png b/core/src/main/res/drawable-xxhdpi/ic_cast_off_light.png
deleted file mode 100644
index 92ac67b34..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_cast_off_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_cast_on_0_light.png b/core/src/main/res/drawable-xxhdpi/ic_cast_on_0_light.png
deleted file mode 100644
index 2742fcb4a..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_cast_on_0_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_cast_on_1_light.png b/core/src/main/res/drawable-xxhdpi/ic_cast_on_1_light.png
deleted file mode 100644
index 405178e64..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_cast_on_1_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_cast_on_2_light.png b/core/src/main/res/drawable-xxhdpi/ic_cast_on_2_light.png
deleted file mode 100644
index dfe52428d..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_cast_on_2_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_cast_on_light.png b/core/src/main/res/drawable-xxhdpi/ic_cast_on_light.png
deleted file mode 100644
index 7e69a0864..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_cast_on_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_close_light.png b/core/src/main/res/drawable-xxhdpi/ic_close_light.png
deleted file mode 100644
index be519bfcb..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_close_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_format_list_bulleted_grey600_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_format_list_bulleted_grey600_24dp.png
deleted file mode 100644
index 87f8073ea..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_format_list_bulleted_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_format_list_bulleted_white_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_format_list_bulleted_white_24dp.png
deleted file mode 100644
index da3433c61..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_format_list_bulleted_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_forum_grey600_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_forum_grey600_24dp.png
deleted file mode 100644
index 7a3204693..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_forum_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_media_cast_disconnect.png b/core/src/main/res/drawable-xxhdpi/ic_media_cast_disconnect.png
deleted file mode 100644
index 2d2ec9035..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_media_cast_disconnect.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_pause_light.png b/core/src/main/res/drawable-xxhdpi/ic_pause_light.png
deleted file mode 100644
index a36d4d11e..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_pause_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_play_light.png b/core/src/main/res/drawable-xxhdpi/ic_play_light.png
deleted file mode 100644
index b1424874a..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_play_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_stat_authentication.png b/core/src/main/res/drawable-xxhdpi/ic_stat_authentication.png
deleted file mode 100755
index 965fabc57..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_stat_authentication.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxxhdpi/ic_baseline_question_answer_white_24db.png b/core/src/main/res/drawable-xxxhdpi/ic_baseline_question_answer_white_24db.png
deleted file mode 100755
index 0d697e0f9..000000000
--- a/core/src/main/res/drawable-xxxhdpi/ic_baseline_question_answer_white_24db.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxxhdpi/ic_close_light.png b/core/src/main/res/drawable-xxxhdpi/ic_close_light.png
deleted file mode 100644
index 679c2a4d5..000000000
--- a/core/src/main/res/drawable-xxxhdpi/ic_close_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxxhdpi/ic_format_list_bulleted_grey600_24dp.png b/core/src/main/res/drawable-xxxhdpi/ic_format_list_bulleted_grey600_24dp.png
deleted file mode 100644
index c56590fe0..000000000
--- a/core/src/main/res/drawable-xxxhdpi/ic_format_list_bulleted_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxxhdpi/ic_format_list_bulleted_white_24dp.png b/core/src/main/res/drawable-xxxhdpi/ic_format_list_bulleted_white_24dp.png
deleted file mode 100644
index 5deea3286..000000000
--- a/core/src/main/res/drawable-xxxhdpi/ic_format_list_bulleted_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxxhdpi/ic_forum_grey600_24dp.png b/core/src/main/res/drawable-xxxhdpi/ic_forum_grey600_24dp.png
deleted file mode 100644
index 0ae33696b..000000000
--- a/core/src/main/res/drawable-xxxhdpi/ic_forum_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxxhdpi/ic_pause_light.png b/core/src/main/res/drawable-xxxhdpi/ic_pause_light.png
deleted file mode 100644
index 7de2ef4ed..000000000
--- a/core/src/main/res/drawable-xxxhdpi/ic_pause_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxxhdpi/ic_play_light.png b/core/src/main/res/drawable-xxxhdpi/ic_play_light.png
deleted file mode 100644
index 4428c8477..000000000
--- a/core/src/main/res/drawable-xxxhdpi/ic_play_light.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable/ic_antenna.xml b/core/src/main/res/drawable/ic_antenna.xml
new file mode 100644
index 000000000..9fcfab000
--- /dev/null
+++ b/core/src/main/res/drawable/ic_antenna.xml
@@ -0,0 +1,6 @@
+<vector android:height="24dp" android:viewportHeight="12.7"
+ android:viewportWidth="12.7" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillAlpha="1" android:fillColor="#ffffff"
+ android:pathData="m6.0631,0.4728v0.3274c1.1582,0.0249 1.911,0.4225 2.5991,1.1189 0.6881,0.6964 1.0924,1.7043 1.1125,2.9246h0.3211c0.0078,-1.3792 -0.5291,-2.4905 -1.1981,-3.1576C8.2288,1.019 7.3415,0.4734 6.0631,0.4728ZM6.0631,1.4283v0.3453c0.859,0.0361 1.3465,0.2123 1.9398,0.8081 0.5933,0.5957 0.843,1.3669 0.8598,2.2621L9.2029,4.8438c-0.0088,-1.2333 -0.5414,-2.0907 -0.9568,-2.5047 -0.4154,-0.4139 -0.9948,-0.9065 -2.183,-0.9108zM6.0625,2.4323 L6.0631,2.7495c0.3968,0.007 0.8308,0.1395 1.2089,0.5642 0.3781,0.4247 0.495,1.0244 0.51,1.53h0.3255c-0.0016,-0.669 -0.2787,-1.3891 -0.6153,-1.747 -0.3366,-0.358 -0.7368,-0.6621 -1.4298,-0.6645zM6.0906,3.7766c-0.4059,0.0002 -0.7349,0.3294 -0.7347,0.7353 0.0001,0.2677 0.1459,0.5142 0.3804,0.6434l-3.0102,6.2227 0.5151,0.3351 0.607,-1.2485 5.3821,1.5453 0.083,0.1609 0.5732,-0.2508 -3.4927,-6.7397c0.2624,-0.1189 0.4311,-0.3802 0.4315,-0.6683 0.0002,-0.4059 -0.3287,-0.7352 -0.7347,-0.7353zM6.065,5.8631 L6.5929,6.8882 5.2882,7.4761zM6.6976,7.0918 L7.6065,8.8561 5.137,7.8016zM5.0259,8.0199 L7.611,9.1184 4.0314,10.0854zM7.8395,9.3086 L9.081,11.7201 4.1489,10.3069z"
+ android:strokeAlpha="1" android:strokeColor="#00000000" android:strokeWidth="0.32680494"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_chat_grey600.xml b/core/src/main/res/drawable/ic_chat_grey600.xml
new file mode 100644
index 000000000..ebae2dbed
--- /dev/null
+++ b/core/src/main/res/drawable/ic_chat_grey600.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp"
+ android:viewportHeight="24.0" android:viewportWidth="24.0"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#FF757575" android:pathData="M21,6h-2v9L6,15v2c0,0.55 0.45,1 1,1h11l4,4L22,7c0,-0.55 -0.45,-1 -1,-1zM17,12L17,3c0,-0.55 -0.45,-1 -1,-1L3,2c-0.55,0 -1,0.45 -1,1v14l4,-4h10c0.55,0 1,-0.45 1,-1z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_chat_white.xml b/core/src/main/res/drawable/ic_chat_white.xml
new file mode 100644
index 000000000..45691c525
--- /dev/null
+++ b/core/src/main/res/drawable/ic_chat_white.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp"
+ android:viewportHeight="24.0" android:viewportWidth="24.0"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#FFFFFFFF" android:pathData="M21,6h-2v9L6,15v2c0,0.55 0.45,1 1,1h11l4,4L22,7c0,-0.55 -0.45,-1 -1,-1zM17,12L17,3c0,-0.55 -0.45,-1 -1,-1L3,2c-0.55,0 -1,0.45 -1,1v14l4,-4h10c0.55,0 1,-0.45 1,-1z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_fab_edit_black.xml b/core/src/main/res/drawable/ic_fab_edit_black.xml
new file mode 100644
index 000000000..a9fec7080
--- /dev/null
+++ b/core/src/main/res/drawable/ic_fab_edit_black.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp"
+ android:viewportHeight="24.0" android:viewportWidth="24.0"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#FF000000" android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_fab_edit.xml b/core/src/main/res/drawable/ic_fab_edit_white.xml
index cb2e394b0..cb2e394b0 100644
--- a/core/src/main/res/drawable/ic_fab_edit.xml
+++ b/core/src/main/res/drawable/ic_fab_edit_white.xml
diff --git a/core/src/main/res/drawable/ic_notification.png b/core/src/main/res/drawable/ic_notification.png
deleted file mode 100644
index 8bd22b54a..000000000
--- a/core/src/main/res/drawable/ic_notification.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable/ic_notification_cast_off.xml b/core/src/main/res/drawable/ic_notification_cast_off.xml
new file mode 100644
index 000000000..63a21fbe2
--- /dev/null
+++ b/core/src/main/res/drawable/ic_notification_cast_off.xml
@@ -0,0 +1,5 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp" android:viewportHeight="24.0"
+ android:viewportWidth="24.0" android:width="24dp">
+ <path android:fillColor="#FFFFFFFF" android:pathData="M1.6,1.27L0.25,2.75L1.41,3.8C1.16,4.13 1,4.55 1,5V8H3V5.23L18.2,19H14V21H20.41L22.31,22.72L23.65,21.24M6.5,3L8.7,5H21V16.14L23,17.95V5C23,3.89 22.1,3 21,3M1,10V12A9,9 0 0,1 10,21H12C12,14.92 7.08,10 1,10M1,14V16A5,5 0 0,1 6,21H8A7,7 0 0,0 1,14M1,18V21H4A3,3 0 0,0 1,18Z" />
+</vector> \ No newline at end of file
diff --git a/core/src/main/res/drawable/ic_notification_fast_forward.xml b/core/src/main/res/drawable/ic_notification_fast_forward.xml
new file mode 100644
index 000000000..bf564977c
--- /dev/null
+++ b/core/src/main/res/drawable/ic_notification_fast_forward.xml
@@ -0,0 +1,5 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp" android:viewportHeight="24.0"
+ android:viewportWidth="24.0" android:width="24dp">
+ <path android:fillColor="#FFFFFFFF" android:pathData="M4,18l8.5,-6L4,6v12zM13,6v12l8.5,-6L13,6z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_notification_fast_rewind.xml b/core/src/main/res/drawable/ic_notification_fast_rewind.xml
new file mode 100644
index 000000000..847159cc5
--- /dev/null
+++ b/core/src/main/res/drawable/ic_notification_fast_rewind.xml
@@ -0,0 +1,5 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp" android:viewportHeight="24.0"
+ android:viewportWidth="24.0" android:width="24dp">
+ <path android:fillColor="#FFFFFFFF" android:pathData="M11,18L11,6l-8.5,6 8.5,6zM11.5,12l8.5,6L20,6l-8.5,6z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_notification_key.xml b/core/src/main/res/drawable/ic_notification_key.xml
new file mode 100644
index 000000000..c8a817eeb
--- /dev/null
+++ b/core/src/main/res/drawable/ic_notification_key.xml
@@ -0,0 +1,6 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp" android:viewportHeight="24.0"
+ android:viewportWidth="24.0" android:width="24dp">
+ <path android:fillColor="#FFFFFFFF"
+ android:pathData="M12.65,10C11.83,7.67 9.61,6 7,6c-3.31,0 -6,2.69 -6,6s2.69,6 6,6c2.61,0 4.83,-1.67 5.65,-4H17v4h4v-4h2v-4H12.65zM7,14c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_notification_pause.xml b/core/src/main/res/drawable/ic_notification_pause.xml
new file mode 100644
index 000000000..d46efb2f5
--- /dev/null
+++ b/core/src/main/res/drawable/ic_notification_pause.xml
@@ -0,0 +1,5 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp" android:viewportHeight="24.0"
+ android:viewportWidth="24.0" android:width="24dp">
+ <path android:fillColor="#FFFFFFFF" android:pathData="M6,19h4L10,5L6,5v14zM14,5v14h4L18,5h-4z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_notification_play.xml b/core/src/main/res/drawable/ic_notification_play.xml
new file mode 100644
index 000000000..d571460c6
--- /dev/null
+++ b/core/src/main/res/drawable/ic_notification_play.xml
@@ -0,0 +1,5 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp" android:viewportHeight="24.0"
+ android:viewportWidth="24.0" android:width="24dp">
+ <path android:fillColor="#FFFFFFFF" android:pathData="M8,5v14l11,-7z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_notification_skip.xml b/core/src/main/res/drawable/ic_notification_skip.xml
new file mode 100644
index 000000000..0c65448cc
--- /dev/null
+++ b/core/src/main/res/drawable/ic_notification_skip.xml
@@ -0,0 +1,5 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp" android:viewportHeight="24.0"
+ android:viewportWidth="24.0" android:width="24dp">
+ <path android:fillColor="#FFFFFFFF" android:pathData="M6,18l8.5,-6L6,6v12zM16,6v12h2V6h-2z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_playback_speed_dark.xml b/core/src/main/res/drawable/ic_playback_speed_dark.xml
new file mode 100644
index 000000000..7c7d1cf8c
--- /dev/null
+++ b/core/src/main/res/drawable/ic_playback_speed_dark.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:width="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path android:fillColor="#FF757575" android:pathData="M 12,14.888154 A 2.2284437,2.2284437 0 0 1 9.7715563,12.659711 c 0,-0.831952 0.4531167,-1.559911 1.1142217,-1.938746 L 18.098507,6.5463469 13.990743,13.66251 C 13.619336,14.390469 12.869093,14.888154 12,14.888154 m 0,-9.6565888 c 1.344494,0 2.599851,0.3714073 3.691789,0.9805151 L 14.131878,7.110886 C 13.485629,6.858329 12.742815,6.7171943 12,6.7171943 A 5.9425165,5.9425165 0 0 0 6.0574835,12.659711 c 0,1.64162 0.661105,3.127249 1.7381861,4.196902 h 0.00743 c 0.2896977,0.289697 0.2896977,0.757671 0,1.047369 -0.2896977,0.289697 -0.7650991,0.289697 -1.0547967,0.0075 v 0 C 5.4038067,16.566915 4.5718544,14.709879 4.5718544,12.659711 A 7.4281456,7.4281456 0 0 1 12,5.2315652 m 7.428145,7.4281458 c 0,2.050168 -0.831952,3.907204 -2.176446,5.251699 v 0 c -0.289698,0.282269 -0.757671,0.282269 -1.047369,-0.0075 -0.289697,-0.289698 -0.289697,-0.757671 0,-1.047368 v 0 c 1.077082,-1.077082 1.738186,-2.555282 1.738186,-4.196902 0,-0.742815 -0.141134,-1.48563 -0.401119,-2.154163 l 0.898805,-1.5599106 c 0.616537,1.1142216 0.987943,2.3621496 0.987943,3.7140736 z" />
+</vector> \ No newline at end of file
diff --git a/core/src/main/res/drawable/ic_playback_speed_white.xml b/core/src/main/res/drawable/ic_playback_speed_white.xml
new file mode 100644
index 000000000..cc6af0d55
--- /dev/null
+++ b/core/src/main/res/drawable/ic_playback_speed_white.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="48dp"
+ android:width="48dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path android:fillColor="#ffffffff" android:pathData="M 12,14.888154 A 2.2284437,2.2284437 0 0 1 9.7715563,12.659711 c 0,-0.831952 0.4531167,-1.559911 1.1142217,-1.938746 L 18.098507,6.5463469 13.990743,13.66251 C 13.619336,14.390469 12.869093,14.888154 12,14.888154 m 0,-9.6565888 c 1.344494,0 2.599851,0.3714073 3.691789,0.9805151 L 14.131878,7.110886 C 13.485629,6.858329 12.742815,6.7171943 12,6.7171943 A 5.9425165,5.9425165 0 0 0 6.0574835,12.659711 c 0,1.64162 0.661105,3.127249 1.7381861,4.196902 h 0.00743 c 0.2896977,0.289697 0.2896977,0.757671 0,1.047369 -0.2896977,0.289697 -0.7650991,0.289697 -1.0547967,0.0075 v 0 C 5.4038067,16.566915 4.5718544,14.709879 4.5718544,12.659711 A 7.4281456,7.4281456 0 0 1 12,5.2315652 m 7.428145,7.4281458 c 0,2.050168 -0.831952,3.907204 -2.176446,5.251699 v 0 c -0.289698,0.282269 -0.757671,0.282269 -1.047369,-0.0075 -0.289697,-0.289698 -0.289697,-0.757671 0,-1.047368 v 0 c 1.077082,-1.077082 1.738186,-2.555282 1.738186,-4.196902 0,-0.742815 -0.141134,-1.48563 -0.401119,-2.154163 l 0.898805,-1.5599106 c 0.616537,1.1142216 0.987943,2.3621496 0.987943,3.7140736 z" />
+</vector> \ No newline at end of file
diff --git a/core/src/main/res/drawable/ic_questionmark_grey600.xml b/core/src/main/res/drawable/ic_questionmark_grey600.xml
new file mode 100644
index 000000000..0907fcdec
--- /dev/null
+++ b/core/src/main/res/drawable/ic_questionmark_grey600.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp"
+ android:viewportHeight="24.0" android:viewportWidth="24.0"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#FF757575" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,19h-2v-2h2v2zM15.07,11.25l-0.9,0.92C13.45,12.9 13,13.5 13,15h-2v-0.5c0,-1.1 0.45,-2.1 1.17,-2.83l1.24,-1.26c0.37,-0.36 0.59,-0.86 0.59,-1.41 0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2L8,9c0,-2.21 1.79,-4 4,-4s4,1.79 4,4c0,0.88 -0.36,1.68 -0.93,2.25z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_questionmark_white.xml b/core/src/main/res/drawable/ic_questionmark_white.xml
new file mode 100644
index 000000000..69b42fef8
--- /dev/null
+++ b/core/src/main/res/drawable/ic_questionmark_white.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp"
+ android:viewportHeight="24.0" android:viewportWidth="24.0"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#FFFFFFFF" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,19h-2v-2h2v2zM15.07,11.25l-0.9,0.92C13.45,12.9 13,13.5 13,15h-2v-0.5c0,-1.1 0.45,-2.1 1.17,-2.83l1.24,-1.26c0.37,-0.36 0.59,-0.86 0.59,-1.41 0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2L8,9c0,-2.21 1.79,-4 4,-4s4,1.79 4,4c0,0.88 -0.36,1.68 -0.93,2.25z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_stream_white.xml b/core/src/main/res/drawable/ic_stream_white.xml
new file mode 100644
index 000000000..3c59bbad7
--- /dev/null
+++ b/core/src/main/res/drawable/ic_stream_white.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp"
+ android:viewportHeight="24.0" android:viewportWidth="24.0"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#FFFFFFFF" android:pathData="M12,5c-3.87,0 -7,3.13 -7,7h2c0,-2.76 2.24,-5 5,-5s5,2.24 5,5h2c0,-3.87 -3.13,-7 -7,-7zM13,14.29c0.88,-0.39 1.5,-1.26 1.5,-2.29 0,-1.38 -1.12,-2.5 -2.5,-2.5S9.5,10.62 9.5,12c0,1.02 0.62,1.9 1.5,2.29v3.3L7.59,21 9,22.41l3,-3 3,3L16.41,21 13,17.59v-3.3zM12,1C5.93,1 1,5.93 1,12h2c0,-4.97 4.03,-9 9,-9s9,4.03 9,9h2c0,-6.07 -4.93,-11 -11,-11z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_warning_red.xml b/core/src/main/res/drawable/ic_warning_red.xml
new file mode 100644
index 000000000..475a41bbb
--- /dev/null
+++ b/core/src/main/res/drawable/ic_warning_red.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="#FF0000"
+ android:viewportHeight="24.0" android:viewportWidth="24.0"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#FF000000" android:pathData="M1,21h22L12,2 1,21zM13,18h-2v-2h2v2zM13,14h-2v-4h2v4z"/>
+</vector>
diff --git a/core/src/main/res/drawable/line.xml b/core/src/main/res/drawable/line.xml
new file mode 100644
index 000000000..1d5362840
--- /dev/null
+++ b/core/src/main/res/drawable/line.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+
+ <solid android:color="#33666666"/>
+
+ <padding
+ android:top="10dp"
+ android:left="10dp"
+ android:right="10dp"
+ android:bottom="10dp"/>
+</shape>
diff --git a/core/src/main/res/drawable/line_drawable.xml b/core/src/main/res/drawable/line_drawable.xml
new file mode 100644
index 000000000..503179b12
--- /dev/null
+++ b/core/src/main/res/drawable/line_drawable.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/line"/>
+
+ <item
+ android:drawable="@drawable/line"/>
+</selector>
diff --git a/core/src/main/res/drawable/thumb.xml b/core/src/main/res/drawable/thumb.xml
new file mode 100644
index 000000000..0416c8be9
--- /dev/null
+++ b/core/src/main/res/drawable/thumb.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+
+ <padding
+ android:paddingLeft="22dp"
+ android:paddingRight="22dp" />
+
+ <solid android:color="#99666666" />
+
+</shape>
diff --git a/core/src/main/res/drawable/thumb_drawable.xml b/core/src/main/res/drawable/thumb_drawable.xml
new file mode 100644
index 000000000..37e7c4896
--- /dev/null
+++ b/core/src/main/res/drawable/thumb_drawable.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/thumb"/>
+
+ <item
+ android:drawable="@drawable/thumb"/>
+</selector>
diff --git a/core/src/main/res/drawable/white_circle.xml b/core/src/main/res/drawable/white_circle.xml
deleted file mode 100644
index 597b70a2d..000000000
--- a/core/src/main/res/drawable/white_circle.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval" >
-
- <solid android:color="@color/white" />
-
- <size
- android:height="4dp"
- android:width="4dp" />
-
-</shape> \ No newline at end of file
diff --git a/core/src/main/res/values-ca/strings.xml b/core/src/main/res/values-ca/strings.xml
index 6cc1fa9c9..bc0bbfa3c 100644
--- a/core/src/main/res/values-ca/strings.xml
+++ b/core/src/main/res/values-ca/strings.xml
@@ -111,9 +111,6 @@
<string name="mark_all_read_msg">S\'han marcat tots els episodis com a llegits</string>
<string name="mark_all_read_confirmation_msg">Si us plau confirma que vols marcar tots els episodis com reproduits.</string>
<string name="mark_all_read_feed_confirmation_msg">Si us plau, confirmeu que voleu marcar tots els episodis d\'aquest podcast com a reproduïts.</string>
- <string name="remove_all_new_flags_label">Marca tot com a llegit</string>
- <string name="removed_all_new_flags_msg">Marcar tots episodis com a visualitzats</string>
- <string name="remove_all_new_flags_confirmation_msg">Si us plau confirma que vols marcar tots els episodis com vistos.</string>
<string name="show_info_label">Mostra informació</string>
<string name="show_feed_settings_label">Mostrar configuració del podcast</string>
<string name="feed_info_label">Informació del podcast</string>
@@ -153,8 +150,6 @@
<string name="remove_label">Suprimeix</string>
<string name="delete_label">Esborrar</string>
<string name="delete_failed">No s\'ha pogut esborrar el fitxer. Reiniciar el dispositiu pot ajudar.</string>
- <string name="remove_new_flag_label">Marcar com a visualitzat</string>
- <string name="removed_new_flag_label">Marcat com a vist</string>
<string name="mark_read_label">Marca com a llegit</string>
<string name="marked_as_read_label">Marcats com llegits</string>
<string name="mark_unread_label">Marca com a pendent</string>
@@ -166,7 +161,6 @@
<string name="remove_from_favorite_label">Suprimeix de preferits</string>
<string name="removed_from_favorites">S\'ha suprimit de preferits</string>
<string name="visit_website_label">Visita el lloc web</string>
- <string name="support_label">Comparteix amb Flattr</string>
<string name="skip_episode_label">Omet l\'episodi</string>
<string name="activate_auto_download">Activa baixades automàtiques</string>
<string name="deactivate_auto_download">Desactiva les baixades automàtiques</string>
@@ -252,32 +246,6 @@
<string name="ascending">Ascendent</string>
<string name="descending">Descendent</string>
<string name="clear_queue_confirmation_msg">Si us plau, confirma que vols suprimir tots els episodis de la cua</string>
- <!--Flattr-->
- <string name="flattr_auth_label">Inici de sessió a Flattr</string>
- <string name="flattr_auth_explanation">Premeu el botó per iniciar el procés d\'autenticació. Quan s\'obri la pantalla d\'inici de sessió de Flattr al vostre navegador, introduïu les vostres credencials i concediu a AntennaPod els permisos de compartir mitjançant Flattr. En finalitzar el procés, tornareu automàticament a aquesta pantalla.</string>
- <string name="authenticate_label">Autenticació</string>
- <string name="return_home_label">Torna a l\'inici</string>
- <string name="flattr_auth_success">L\'autenticació ha acabat correctament. Ja podeu compartir amb Flattr des de l\'aplicació.</string>
- <string name="no_flattr_token_title">No s\'ha trobat cap testimoni Flattr</string>
- <string name="no_flattr_token_notification_msg">Sembla que el compte flattr no està vinculat amb AntennaPod. Toqueu aquí per autenticar-vos.</string>
- <string name="no_flattr_token_msg">Sembla que el vostre compte de Flattr no està vinculat amb AntennaPod. Podeu connectar el vostre compte Flattr amb AntennaPod per a compartir continguts des de l\'aplicació, o bé accediu a la plana web de Flattr i compartiu els continguts des d\'allà.</string>
- <string name="authenticate_now_label">Autentica</string>
- <string name="action_forbidden_title">L\'acció no és permesa</string>
- <string name="action_forbidden_msg">AntennaPod no té permisos per executar aquesta acció. És possible que el testimoni d\'accés de Flattr per a AntennaPod hagi estat revocat. Podeu tornar-vos a autenticar amb el servei de Flattr, o podeu visitar el web del contingut directament.</string>
- <string name="access_revoked_title">L\'accés ha estat revocat</string>
- <string name="access_revoked_info">El testimoni d\'accés a Flattr de l\'AntennaPod s\'ha revocat correctament. Per completar el procés, heu de suprimir aquesta aplicació de la llista d\'aplicacions aprovades que trobareu a l\'apartat de configuració del compte de la plana web de Flattr.</string>
- <!--Flattr-->
- <string name="flattr_click_success">S\'ha compartit una cosa per Flattr!</string>
- <string name="flattr_click_success_count">S\'han compartit %d coses per Flattr!</string>
- <string name="flattr_click_success_queue">Compartit per Flattr: %s.</string>
- <string name="flattr_click_failure_count">No s\'han pogut compartir %d coses per Flattr!</string>
- <string name="flattr_click_failure">No s\'ha compartit per Flattr: %s.</string>
- <string name="flattr_click_enqueued">Es compartirà per Flattr després</string>
- <string name="flattring_thing">%s s\'està compartint per Flattr</string>
- <string name="flattring_label">AntennaPod està compartint per Flattr</string>
- <string name="flattrd_label">AntennaPod ha compartit per Flattr</string>
- <string name="flattrd_failed_label">AntennaPod no ha pogut compartir per Flattr</string>
- <string name="flattr_retrieving_status">S\'estan recuperant les coses compartides per Flattr</string>
<!--Variable Speed-->
<string name="download_plugin_label">Baixa el connector</string>
<string name="no_playback_plugin_title">Connector no instal·lat</string>
@@ -286,8 +254,8 @@
<string name="enable_sonic">Activa Sonic</string>
<!--Empty list labels-->
<string name="no_feeds_label">Encara no us heu subscrit a cap podcast.</string>
- <string name="no_chapters_label">Aquest episodi no té capítols</string>
<string name="no_shownotes_label">Aquest episodi no té notes.</string>
+ <string name="no_chapters_label">Aquest episodi no té capítols</string>
<!--Preferences-->
<string name="storage_pref">Emmagatzematge</string>
<string name="project_pref">Projecte</string>
@@ -295,15 +263,12 @@
<string name="about_pref">Quant a</string>
<string name="queue_label">Cua</string>
<string name="integrations_label">Integracions</string>
- <string name="flattr_label">Flattr</string>
- <string name="flattr_summary">Servei de micropagaments</string>
<string name="automation">Automatització</string>
<string name="download_pref_details">Detalls</string>
<string name="import_export_pref">Importa/Exporta</string>
<string name="appearance">Aparença</string>
<string name="external_elements">Elements externs</string>
<string name="interruptions">Interrupcions</string>
- <string name="buttons">Botons de control de reproducció</string>
<string name="media_player">Reproductor multimèdia</string>
<string name="pref_episode_cleanup_title">Neteja l\'episodi</string>
<string name="pref_episode_cleanup_summary">Els episodis que no es troben a la cua i no són preferits seran candidats a ser suprimits si l\'Auto Descàrrega necessita espai per a nous episodis</string>
@@ -339,17 +304,7 @@
<string name="pref_unpauseOnHeadsetReconnect_title">Connexió d\'auriculars</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Connexió de bluetooth</string>
<string name="pref_mobileUpdate_title">Actualitzacions sobre xarxes mòbils</string>
- <string name="pref_mobileUpdate_sum">Permet actualitzacions a través de xarxes mòbils.</string>
<string name="refreshing_label">S\'està actualitzant</string>
- <string name="flattr_settings_label">Configuració de Flattr</string>
- <string name="pref_flattr_auth_title">Inici de sessió Flattr</string>
- <string name="pref_flattr_auth_sum">Inicieu sessió al vostre compte Flattr per compartir continguts directament des de l\'aplicació.</string>
- <string name="pref_flattr_this_app_title">Recolza aquesta aplicació amb Flattr</string>
- <string name="pref_flattr_this_app_sum">Doneu suport al desenvolupament d\'AntennaPod compartint l\'aplicació a través de Flattr. Gràcies!</string>
- <string name="pref_revokeAccess_title">Revoca l\'accés</string>
- <string name="pref_revokeAccess_sum">Revoqueu el permís d\'accés d\'aquesta aplicació al vostre compte Flattr.</string>
- <string name="pref_auto_flattr_title">Flattr automàtic</string>
- <string name="pref_auto_flattr_sum">Configura la compartició automàtica per Flattr</string>
<string name="user_interface_label">Interfície d\'usuari</string>
<string name="pref_set_theme_title">Selecciona el tema</string>
<string name="pref_nav_drawer_title">Personalitza el calaix de navegació</string>
@@ -439,11 +394,6 @@
<string name="pref_videoBehavior_sum">Comportament a l\'abandonar la reproducció d\'un vídeo</string>
<string name="stop_playback">Atura reproducció</string>
<string name="continue_playback">Continuar reproducció d\'audio</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">Activa la compartició automàtica per Flattr</string>
- <string name="auto_flattr_after_percent">Comparteix per Flattr l\'episodi en haver-ne reproduït el %d per cent</string>
- <string name="auto_flattr_ater_beginning">Comparteix per Flattr l\'episodi en haver-ne iniciat la reproducció</string>
- <string name="auto_flattr_ater_end">Comparteix per Flattr l\'episodi en acabar-se\'n la reproducció</string>
<!--Search-->
<string name="search_hint">Cerca episodis</string>
<string name="found_in_shownotes_label">Troba a les notes dels canals</string>
@@ -587,9 +537,10 @@
<string name="progress_upgrading_database">Actualitzant la base de dades</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">S\'estan important les subscripcions des de les apps de propòsit únic...</string>
+ <!--Add podcast fragment-->
<string name="search_itunes_label">Cerca a iTunes</string>
- <string name="filter">Filtra</string>
<string name="search_fyyd_label">Cerca a fyyd</string>
+ <string name="filter">Filtra</string>
<!--Episodes apply actions-->
<string name="all_label">Tot</string>
<string name="selected_all_label">Selecciona tots els episodis</string>
diff --git a/core/src/main/res/values-cs-rCZ/strings.xml b/core/src/main/res/values-cs-rCZ/strings.xml
index cb784ec6a..9ce2f074b 100644
--- a/core/src/main/res/values-cs-rCZ/strings.xml
+++ b/core/src/main/res/values-cs-rCZ/strings.xml
@@ -102,14 +102,17 @@
<string name="podcastdirectories_label">Najít podcast v seznamu</string>
<string name="podcastdirectories_descr">Nové podcasty můžete hledat pomocí iTunes nebo fyyd, nebo hledat na gpodder.net podle jména, kategorie či popularity.</string>
<string name="browse_gpoddernet_label">Prohledávat gpodder.net</string>
+ <string name="discover_more">více »</string>
<!--Actions on feeds-->
<string name="mark_all_read_label">Označit vše jako poslechnuté</string>
<string name="mark_all_read_msg">Všechny epizody označeny jako poslechnuté</string>
<string name="mark_all_read_confirmation_msg">Potvrďte prosím, že chcete označit všechny vybrané epizody jako poslechnuté.</string>
- <string name="remove_all_new_flags_label">Označit vše jako zobrazené</string>
- <string name="remove_all_new_flags_confirmation_msg">Potvrďte prosím, že chcete označit všechny epizody jako shlédnuté.</string>
<string name="show_info_label">Informace o zdroji</string>
+ <string name="rename_feed_label">Přejmenovat podcast</string>
+ <string name="remove_feed_label">Odstranit podcast</string>
<string name="share_label">Sdílet</string>
+ <string name="share_link_label">Sdílet URL epizody</string>
+ <string name="share_file_label">Sdílet soubor</string>
<string name="share_feed_url_label">Sdílet URL kanálu</string>
<string name="hide_episodes_title">Skrýt epizody</string>
<string name="hide_unplayed_episodes_label">Neposlechnuté</string>
@@ -131,7 +134,7 @@
<string name="stream_label">Vysílat</string>
<string name="remove_label">Odstranit</string>
<string name="delete_label">Smazat</string>
- <string name="removed_new_flag_label">Označit jako shlédnuté</string>
+ <string name="delete_episode_label">Smazat epizodu</string>
<string name="mark_read_label">Označit jako poslechnuté</string>
<string name="marked_as_read_label">Označeno jako poslechnuté</string>
<string name="mark_unread_label">Označit jako neposlechnuté</string>
@@ -143,7 +146,6 @@
<string name="remove_from_favorite_label">Odebrat z obíbených</string>
<string name="removed_from_favorites">Odebráno z oblíbených</string>
<string name="visit_website_label">Navštívit stránku</string>
- <string name="support_label">Flattrovat</string>
<string name="skip_episode_label">Přeskočit epizodu</string>
<string name="activate_auto_download">Aktivovat automatické stahování</string>
<string name="deactivate_auto_download">Deaktivovat automatické stahování</string>
@@ -154,6 +156,7 @@
<string name="download_failed">selhalo</string>
<string name="download_pending">Čeká na stažení</string>
<string name="download_running">Probíhá stahování</string>
+ <string name="download_error_details">Detaily</string>
<string name="download_error_device_not_found">Úložné zařízení nenalezeno</string>
<string name="download_error_insufficient_space">Nedostatek volného místa</string>
<string name="download_error_file_error">Souborová chyba</string>
@@ -222,35 +225,13 @@
<string name="date">Datum</string>
<string name="duration">Délka</string>
<string name="episode_title">Název epizody</string>
+ <string name="feed_title">Jméno podcastu</string>
+ <string name="random">Náhodné</string>
<string name="ascending">Vzestupně</string>
<string name="descending">Sestupně</string>
<string name="clear_queue_confirmation_msg">Potvrďte prosím, že chcete vyčistit tuto frontu a VŠECHNY v ní obsažené epizody</string>
- <!--Flattr-->
- <string name="flattr_auth_label">Flattr přihlášení</string>
- <string name="flattr_auth_explanation">Stiskněte následující tlačítko pro spuštění autentizačního procesu. Budete přesměrováni na přihlašovací obrazovku flattru a vyzváni k potvrzení udělení práv pro použití flattru aplikací AntennaPod. Po udělení práv se automaticky vrátíte na tuto obrazovku.</string>
- <string name="authenticate_label">Přihlásit</string>
- <string name="return_home_label">Návrat domů</string>
- <string name="flattr_auth_success">Úspěšně přihlášen. Nyní můžete využít flattru přímo v aplikaci. </string>
- <string name="no_flattr_token_title">Nenalezen Flattr token</string>
- <string name="no_flattr_token_notification_msg">Váš flattr účet není propojen s AntennaPod. Pro ověření tapněte sem.</string>
- <string name="no_flattr_token_msg">Váš flattr učet není napojen do AntenaPodu. Můžete buďto napojit váš flattr účet do AntennaPodu a využít flattru přímo v aplikaci a nebo použít flattr přímo na webových stránkách zdroje v prohlížeči. </string>
- <string name="authenticate_now_label">Přihlásit</string>
- <string name="action_forbidden_title">Akce zakázána</string>
- <string name="action_forbidden_msg">AntennaPod nemá oprávnění pro tuto akci. Důvodem může být revokování přístupového tokenu AntennaPodu k vašemu účtu. Přístup můžete obnovit nebo využít prohlížeče k návštěvě stránky zdroje.</string>
- <string name="access_revoked_title">Přístup ukončen</string>
- <string name="access_revoked_info">Úspěšně revokován přístup AntennPodu k vašemu účtu. Pro dokončení tohoto procesu je ještě zapotřebí na stránkách flattru odebrat z vašeho účtu AntennaPod ze seznamu povolených aplikací.</string>
- <!--Flattr-->
- <string name="flattr_click_success">Flattrován jeden příspěvek!</string>
- <string name="flattr_click_success_count">Flattrováno %d příspěvků!</string>
- <string name="flattr_click_success_queue">Flattrován: %s.</string>
- <string name="flattr_click_failure_count">Selhalo flattrování %d příspěvků!</string>
- <string name="flattr_click_failure">Neflattrováno: %s.</string>
- <string name="flattr_click_enqueued">Příspěvek bude flattrován později</string>
- <string name="flattring_thing">Flattruji %s</string>
- <string name="flattring_label">AntennaPod flattruje</string>
- <string name="flattrd_label">AntennaPod flattroval</string>
- <string name="flattrd_failed_label">AntennaPod flattr selhal</string>
- <string name="flattr_retrieving_status">Získávání flattrovaných příspěvků</string>
+ <string name="sort_old_to_new">Od nejstaršího po nejnovější</string>
+ <string name="sort_new_to_old">Od nejnovějšího po nejstarší</string>
<!--Variable Speed-->
<string name="download_plugin_label">Stáhnout modul</string>
<string name="no_playback_plugin_title">Modul není nainstalován</string>
@@ -258,15 +239,16 @@
<string name="set_playback_speed_label">Rychlosti přehrávání</string>
<string name="enable_sonic">Povolit Sonic</string>
<!--Empty list labels-->
- <string name="no_chapters_label">Tato epizoda nemá žádné kapitoly.</string>
<string name="no_shownotes_label">Tato epizoda neobsahuje žádné poznámky.</string>
+ <string name="no_chapters_label">Tato epizoda nemá žádné kapitoly.</string>
<!--Preferences-->
<string name="storage_pref">Úložiště</string>
<string name="project_pref">Projekt</string>
<string name="other_pref">Ostatní</string>
<string name="about_pref">O aplikaci</string>
<string name="queue_label">Fronta</string>
- <string name="flattr_label">Flattr</string>
+ <string name="import_export_pref">Importovat/Exportovat</string>
+ <string name="appearance">Vzhled</string>
<string name="pref_episode_cleanup_title">Vyčistit epizody</string>
<string name="pref_episode_cleanup_summary">Epizody, které nejsou ve frontě a nejsou označeny za oblíbené by mělo být možné smazat, pokud bude funkce automatického stahování potřebovat místo pro nové epizody</string>
<string name="pref_pauseOnDisconnect_sum">Při odpojení sluchátek nebo bluetooth připojení pozastavit přehrávání.</string>
@@ -297,17 +279,7 @@
<string name="pref_unpauseOnHeadsetReconnect_title">Sluchátka připojena</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Bluetooth připojeno</string>
<string name="pref_mobileUpdate_title">Mobilní aktualizace</string>
- <string name="pref_mobileUpdate_sum">Povolit aktualizace pomocí mobilního připojení</string>
<string name="refreshing_label">Obnovuji</string>
- <string name="flattr_settings_label">Nastavení Flattr</string>
- <string name="pref_flattr_auth_title">Flattr přihlášení</string>
- <string name="pref_flattr_auth_sum">Přihlásit se k flattr účtu a umožnit flattrování přímo z aplikace.</string>
- <string name="pref_flattr_this_app_title">Flattrovat tuto aplikaci</string>
- <string name="pref_flattr_this_app_sum">Podpořit vývoj AntennaPodu na flatteru. Děkujeme!</string>
- <string name="pref_revokeAccess_title">Odebrat přístup</string>
- <string name="pref_revokeAccess_sum">Odebere aplikaci přístupová práva k vašemu flattr účtu.</string>
- <string name="pref_auto_flattr_title">Automatický Flattr</string>
- <string name="pref_auto_flattr_sum">Nastavit automatické flattrování</string>
<string name="user_interface_label">Uživatelské rozhraní</string>
<string name="pref_set_theme_title">Vybrat motiv</string>
<string name="pref_nav_drawer_title">Upravit navigační panel</string>
@@ -381,11 +353,6 @@
<string name="pref_cast_title">Chromecast podpora</string>
<string name="pref_cast_message_play_flavor">Povolit podporu vzdáleného přehrávání médií na Cast přístrojích (jako třeba Chromecast, Audio Speakers nebo Android TV)</string>
<string name="pref_cast_message_free_flavor">Chromecast vyžaduje proprietární knihovny třetích stran, které jsou vypnuty v této verzi AntennaPod</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">Povolit automatické flattrování</string>
- <string name="auto_flattr_after_percent">Flattrovat díl jakmile bude odehráno %d procent</string>
- <string name="auto_flattr_ater_beginning">Flattrovat díl po začátku přehrávání</string>
- <string name="auto_flattr_ater_end">Flattrovat díl po konci přehrávání</string>
<!--Search-->
<string name="search_hint">Hledat epizody</string>
<string name="found_in_shownotes_label">Nalezeno v poznámkách pořadu</string>
@@ -531,9 +498,10 @@
<string name="progress_upgrading_database">Probíhá aktualizace databáze</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Importuji odběry z jednoúčelových aplikací...</string>
+ <!--Add podcast fragment-->
<string name="search_itunes_label">Prohledat iTunes</string>
- <string name="filter">Filtr</string>
<string name="search_fyyd_label">Prohledat fyyd</string>
+ <string name="filter">Filtr</string>
<!--Episodes apply actions-->
<string name="all_label">Vše</string>
<string name="selected_all_label">Vybrány všechny epizody</string>
@@ -589,6 +557,8 @@
<string name="proxy_port_invalid_error">Neplatný port</string>
<!--Subscriptions fragment-->
<!--Database import/export-->
+ <string name="label_import">Importovat</string>
+ <string name="label_export">Expotovat</string>
<!--Casting-->
<string name="cast_media_route_menu_title">Přehrát na...</string>
<string name="cast_disconnect_label">Odpojit sezení vysílání</string>
@@ -606,4 +576,5 @@
<string name="cast_failed_receiver_player_error">Přijímač zaznamenal závažnou chybu</string>
<string name="cast_failed_media_error_skipping">Chyba přehrávání médií. Přeskakuji...</string>
<!--Notification channels-->
+ <string name="notification_channel_downloading">Stahuji</string>
</resources>
diff --git a/core/src/main/res/values-da/strings.xml b/core/src/main/res/values-da/strings.xml
index 5420eb5c9..a474a5153 100644
--- a/core/src/main/res/values-da/strings.xml
+++ b/core/src/main/res/values-da/strings.xml
@@ -109,9 +109,6 @@
<string name="mark_all_read_label">Marker alle som afspillet</string>
<string name="mark_all_read_msg">Marker alle udsendelser som afspillet</string>
<string name="mark_all_read_confirmation_msg">Bekræft venligst at du ønsker at markere alle udsendelser som værende afspillet.</string>
- <string name="remove_all_new_flags_label">Marker alle som set</string>
- <string name="removed_all_new_flags_msg">Markeret alle udsendelser som set</string>
- <string name="remove_all_new_flags_confirmation_msg">Bekræft venligst at du ønsker at markere alle udsendelser som set.</string>
<string name="show_info_label">Vis information</string>
<string name="feed_info_label">Podcast-info</string>
<string name="rename_feed_label">Omdøb podcast</string>
@@ -148,8 +145,6 @@
<string name="remove_label">Fjern</string>
<string name="delete_label">Slet</string>
<string name="delete_failed">Kan ikke slette fil. En genstart af enheden vil sandsynligvis hjælpe.</string>
- <string name="remove_new_flag_label">Markér som set</string>
- <string name="removed_new_flag_label">Markeret som set</string>
<string name="mark_read_label">Marker som læst</string>
<string name="marked_as_read_label">Markeret som afspillet</string>
<string name="mark_unread_label">Marker som uafspillet</string>
@@ -161,7 +156,6 @@
<string name="remove_from_favorite_label">Fjern fra foretrukne</string>
<string name="removed_from_favorites">Fjernet fra foretrukne</string>
<string name="visit_website_label">Besøg webside</string>
- <string name="support_label">Flattr dette</string>
<string name="skip_episode_label">Spring udsendelse over</string>
<string name="activate_auto_download">Slå Automatisk overførsel til</string>
<string name="deactivate_auto_download">Slå Automatisk overførsel fra</string>
@@ -246,32 +240,6 @@
<string name="ascending">Stigende</string>
<string name="descending">Faldende</string>
<string name="clear_queue_confirmation_msg">Bekræft venligst at du vil rydde ALLE udsendelser fra køen</string>
- <!--Flattr-->
- <string name="flattr_auth_label">Log ind på Flattr</string>
- <string name="flattr_auth_explanation">Tryk på knappen nedenfor for at starte godkendelsesprocessen. Du vil blive ført til flattr\'s log ind-side i din browser og bedt om at give AntennaPod tilladelse til at flattre emner. Efter at du har givet tilladelsen, vil du automatisk vende tilbage til denne side.</string>
- <string name="authenticate_label">Godkend</string>
- <string name="return_home_label">Gå tilbage hjem</string>
- <string name="flattr_auth_success">Godkendelse lykkedes! Du kan nu flattre ting inde fra appen.</string>
- <string name="no_flattr_token_title">Ingen flattr-polet (token) fundet</string>
- <string name="no_flattr_token_notification_msg">Din flattr-konto ser ikke ud til at være forbundet med AntennaPod. Tryk her for at forbinde.</string>
- <string name="no_flattr_token_msg">Din flattr konto ser ikke ud til at være forbundet til AntennaPod. Du kan enten forbinde din konto til AntennaPod for at flattre emner inde fra appen, eller du kan besøge websiden for det du vil flattre for at gøre det dér.</string>
- <string name="authenticate_now_label">Godkend</string>
- <string name="action_forbidden_title">Handling ikke tilladt</string>
- <string name="action_forbidden_msg">AntennaPod har ikke tilladelse til denne handling. Årsagen kunne være at adgangspoletten for AntennaPod til din konto er blevet tilbagekaldt. Du kan enten godkende igen eller alternativt besøge websiden for det du vil flattre.</string>
- <string name="access_revoked_title">Adgang tilbagekaldt</string>
- <string name="access_revoked_info">Du har nu tilbagekaldt AntennaPods adgangspolet (\'access token\') til din konto. For at fuldføre processen skal du fjerne denne app fra listen over godkendte applikationer i dine kontoindstillinger på flattr\'s hjemmeside.</string>
- <!--Flattr-->
- <string name="flattr_click_success">Flattret en ting!</string>
- <string name="flattr_click_success_count">Flattret %d ting!</string>
- <string name="flattr_click_success_queue">Flattr\'et: %s.</string>
- <string name="flattr_click_failure_count">Det lykkedes ikke at flattre %d ting!</string>
- <string name="flattr_click_failure">Ikke flattr\'et: %s.</string>
- <string name="flattr_click_enqueued">Tingen vil blive flattret senere</string>
- <string name="flattring_thing">Flattr\'er %s</string>
- <string name="flattring_label">AntennaPod flattrer</string>
- <string name="flattrd_label">AntennaPod har flattr\'et</string>
- <string name="flattrd_failed_label">AntennaPod-flattring mislykkedes</string>
- <string name="flattr_retrieving_status">Henter flattrede ting</string>
<!--Variable Speed-->
<string name="download_plugin_label">Hent plugin</string>
<string name="no_playback_plugin_title">Plugin er ikke installeret</string>
@@ -280,8 +248,8 @@
<string name="enable_sonic">Slå Sonic til</string>
<!--Empty list labels-->
<string name="no_feeds_label">Du har ikke abonneret på nogen podcasts endnu.</string>
- <string name="no_chapters_label">Denne udsendelse har ingen kapitler.</string>
<string name="no_shownotes_label">Denne udsendelse har ingen beskrivelse.</string>
+ <string name="no_chapters_label">Denne udsendelse har ingen kapitler.</string>
<!--Preferences-->
<string name="storage_pref">Lagring</string>
<string name="project_pref">Projekt</string>
@@ -289,8 +257,6 @@
<string name="about_pref">Om</string>
<string name="queue_label">Kø</string>
<string name="integrations_label">Integrerede tjenester</string>
- <string name="flattr_label">Flattr</string>
- <string name="flattr_summary">Mikrobetalingstjeneste</string>
<string name="automation">Automatisering</string>
<string name="download_pref_details">Detaljer</string>
<string name="import_export_pref">Import/eksport</string>
@@ -331,17 +297,7 @@
<string name="pref_unpauseOnHeadsetReconnect_title">Tilslutning af hovedtelefoner igen</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Bluetooth forbundet igen</string>
<string name="pref_mobileUpdate_title">Mobile opdateringer</string>
- <string name="pref_mobileUpdate_sum">Tillad opdateringer over mobildataforbindelsen</string>
<string name="refreshing_label">Opdaterer</string>
- <string name="flattr_settings_label">Flattr-indstillinger</string>
- <string name="pref_flattr_auth_title">Log ind på Flattr</string>
- <string name="pref_flattr_auth_sum">Log ind på din flattr-konto for at flattre emner direkte fra appen.</string>
- <string name="pref_flattr_this_app_title">Flattr denne app</string>
- <string name="pref_flattr_this_app_sum">Støt udviklingen af AntennaPod ved at flattre den. Tak!</string>
- <string name="pref_revokeAccess_title">Tilbagekald adgang</string>
- <string name="pref_revokeAccess_sum">Tilbagekald adgangstilladelsen til din flattr-konto fra denne app.</string>
- <string name="pref_auto_flattr_title">Automatisk flattring</string>
- <string name="pref_auto_flattr_sum">Konfigurer automatisk flattring</string>
<string name="user_interface_label">Brugergrænseflade</string>
<string name="pref_set_theme_title">Vælg tema</string>
<string name="pref_nav_drawer_title">Tilpas navigationspanel</string>
@@ -440,11 +396,6 @@
<string name="double_tap_toast">Tryk på tilbageknappen igen for at afslutte</string>
<string name="back_button_go_to_page">Gå til side ...</string>
<string name="back_button_go_to_page_title">Vælg side</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">Aktiver automatisk flattring</string>
- <string name="auto_flattr_after_percent">Flattr udsendelser så snart %d procent er blevet afspillet</string>
- <string name="auto_flattr_ater_beginning">Flattr udsendelse når afspilning starter</string>
- <string name="auto_flattr_ater_end">Flattr udsendelse når afspilning slutter</string>
<!--Search-->
<string name="search_hint">Søg efter udsendelser</string>
<string name="found_in_shownotes_label">Fundet i beskrivelse</string>
@@ -588,9 +539,10 @@
<string name="progress_upgrading_database">Opgraderer databasen</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Importerer abonnementer fra enkeltformålsapps…</string>
+ <!--Add podcast fragment-->
<string name="search_itunes_label">Søg i iTunes</string>
- <string name="filter">Filtrér</string>
<string name="search_fyyd_label">Søg i fyyd</string>
+ <string name="filter">Filtrér</string>
<!--Episodes apply actions-->
<string name="all_label">Alle</string>
<string name="selected_all_label">Markerede alle udsendelser</string>
diff --git a/core/src/main/res/values-de/strings.xml b/core/src/main/res/values-de/strings.xml
index f05b03fc4..d191f4059 100644
--- a/core/src/main/res/values-de/strings.xml
+++ b/core/src/main/res/values-de/strings.xml
@@ -49,7 +49,7 @@
<!--Webview actions-->
<string name="open_in_browser_label">Im Browser öffnen</string>
<string name="copy_url_label">URL kopieren</string>
- <string name="share_url_label">Teile URL</string>
+ <string name="share_url_label">URL teilen</string>
<string name="copied_url_msg">URL wurde in die Zwischenablage kopiert.</string>
<string name="go_to_position_label">Gehe zu dieser Position</string>
<!--Playback history-->
@@ -111,14 +111,16 @@
<string name="podcastdirectories_label">Podcast in Verzeichnis finden</string>
<string name="podcastdirectories_descr">Für neue Podcasts kannst du iTunes oder fyyd durchsuchen, oder gpodder.net nach Name, Kategorie oder Popularität durchstöbern</string>
<string name="browse_gpoddernet_label">gpodder.net durchsuchen</string>
+ <string name="discover">Entdecken</string>
+ <string name="discover_more">mehr »</string>
<!--Actions on feeds-->
<string name="mark_all_read_label">Alle als gespielt markieren</string>
<string name="mark_all_read_msg">Alle Episoden als gespielt markiert</string>
<string name="mark_all_read_confirmation_msg">Bitte bestätige, dass alle Episoden als gespielt markiert werden sollen.</string>
<string name="mark_all_read_feed_confirmation_msg">Bitte bestätige, dass alle Episoden in diesem Feed als gespielt markiert werden sollen.</string>
- <string name="remove_all_new_flags_label">Alle als gesehen markieren</string>
- <string name="removed_all_new_flags_msg">Alle Episoden als gesehen markiert</string>
- <string name="remove_all_new_flags_confirmation_msg">Bitte bestätige, dass alle Episoden als gesehen markiert werden sollen.</string>
+ <string name="remove_all_new_flags_label">Alle \"neu\"-Markierungen entfernen</string>
+ <string name="removed_all_new_flags_msg">Alle \"neu\"-Markierungen entfernt</string>
+ <string name="remove_all_new_flags_confirmation_msg">Bitte bestätige, dass du die \"neu\"-Markierung aller Episoden entfernen willst.</string>
<string name="show_info_label">Informationen anzeigen</string>
<string name="show_feed_settings_label">Zeige Feed-Einstellungen</string>
<string name="feed_info_label">Feed-Informationen</string>
@@ -169,8 +171,8 @@
<item quantity="one">%d Episode gelöscht.</item>
<item quantity="other">%d Episoden gelöscht.</item>
</plurals>
- <string name="remove_new_flag_label">Als gelesen markieren</string>
- <string name="removed_new_flag_label">Als gesehen markiert</string>
+ <string name="remove_new_flag_label">\"Neu\"-Markierung entfernen</string>
+ <string name="removed_new_flag_label">\"Neu\"-Markierung entfernt</string>
<string name="mark_read_label">Als gespielt markieren</string>
<string name="marked_as_read_label">Als gespielt markiert</string>
<plurals name="marked_read_batch_label">
@@ -190,7 +192,7 @@
</plurals>
<string name="remove_from_queue_label">Aus der Abspielliste entfernen</string>
<plurals name="removed_from_queue_batch_label">
- <item quantity="one">%dEpisode aus der Abspielliste entfernt. </item>
+ <item quantity="one">%d Episode aus der Abspielliste entfernt. </item>
<item quantity="other">%d Episoden aus der Abspielliste entfernt.</item>
</plurals>
<string name="add_to_favorite_label">Zu Favoriten hinzufügen</string>
@@ -198,7 +200,6 @@
<string name="remove_from_favorite_label">Aus Favoriten entfernen</string>
<string name="removed_from_favorites">Aus Favoriten entfernt</string>
<string name="visit_website_label">Webseite besuchen</string>
- <string name="support_label">Flattrn</string>
<string name="skip_episode_label">Episode überspringen</string>
<string name="activate_auto_download">Automatischen Download aktivieren</string>
<string name="deactivate_auto_download">Automatischen Download deaktivieren</string>
@@ -250,6 +251,9 @@
<string name="confirm_mobile_download_dialog_title">Mobilen Download bestätigen</string>
<string name="confirm_mobile_download_dialog_message_not_in_queue">Das Herunterladen über die mobile Datenverbindung ist in den Einstellungen deaktiviert.\n\nVorübergehend erlauben oder nur zur Abspielliste hinzufügen?\n\n<small>Deine Entscheidung wird für 10 Minuten gespeichert.</small></string>
<string name="confirm_mobile_download_dialog_message">Das Herunterladen über die mobile Datenverbindung ist in den Einstellungen deaktiviert.\n\nVorübergehend erlauben?\n\n<small>Deine Entscheidung wird für 10 Minuten gespeichert.</small></string>
+ <string name="confirm_mobile_streaming_notification_title">Mobiles Streamen bestätigen</string>
+ <string name="confirm_mobile_streaming_notification_message">Streamen über mobile Datenverbindung ist in den Einstellungen deaktiviert. Tippen, um trotzdem zu streamen.</string>
+ <string name="confirm_mobile_streaming_button_always">Immer erlauben</string>
<string name="confirm_mobile_download_dialog_only_add_to_queue">Zur Abspielliste hinzufügen</string>
<string name="confirm_mobile_download_dialog_enable_temporarily">Vorübergehend erlauben</string>
<!--Mediaplayer messages-->
@@ -259,6 +263,8 @@
<string name="player_ready_msg">Fertig</string>
<string name="player_seeking_msg">Spule</string>
<string name="playback_error_server_died">Server ist offline</string>
+ <string name="playback_error_unsupported">Dateityp nicht unterstützt</string>
+ <string name="playback_error_timeout">Zeitüberschreitung</string>
<string name="playback_error_unknown">Unbekannter Fehler</string>
<string name="no_media_playing_label">Keine Medienwiedergabe</string>
<string name="player_buffering_msg">Puffert</string>
@@ -276,7 +282,7 @@
<string name="move_to_top_label">Zum Anfang verschieben</string>
<string name="move_to_bottom_label">Zum Ende verschieben</string>
<string name="sort">Sortieren</string>
- <string name="keep_sorted">Automatisch sortieren</string>
+ <string name="keep_sorted">Sortiert halten</string>
<string name="date">Datum</string>
<string name="duration">Dauer</string>
<string name="episode_title">Episodentitel</string>
@@ -286,34 +292,8 @@
<string name="ascending">Aufsteigend</string>
<string name="descending">Absteigend</string>
<string name="clear_queue_confirmation_msg">Bitte bestätige, dass ALLE Episoden aus der Abspielliste entfernt werden sollen</string>
- <string name="sort_new_to_old">Neu bis alt</string>
- <string name="sort_old_to_new">Alt bis neu</string>
- <!--Flattr-->
- <string name="flattr_auth_label">Flattr Anmeldung</string>
- <string name="flattr_auth_explanation">Drücke den Button unten, um den Authentifizierungsprozess zu starten. Du wirst zur Flattr-Anmeldeseite weitergeleitet. Hier wirst du gefragt, AntennaPod die Erlaubnis zu geben, Dinge zu flattrn. Nachdem du die Erlaubnis erteilt hast, kehrst du automatisch zu diesem Bildschirm zurück.</string>
- <string name="authenticate_label">Authentifizieren</string>
- <string name="return_home_label">Zur Hauptseite zurückkehren</string>
- <string name="flattr_auth_success">Die Authentifizierung war erfolgreich! Du kannst nun in der Anwendung Flattr verwenden.</string>
- <string name="no_flattr_token_title">Kein Flattr Token gefunden</string>
- <string name="no_flattr_token_notification_msg">Dein Flattr Account scheint nicht mit AntennaPod verbunden zu sein. Tippe hier zum authentifizieren.</string>
- <string name="no_flattr_token_msg">Dein Flattr Account scheint nicht mit AntennaPod verbunden zu sein. Du kannst entweder deinen Account mit AntennaPod verbinden, um direkt in der Anwendung Flattr zu verwenden, oder du kannst die Flattr-Seite der Sache im Netz besuchen.</string>
- <string name="authenticate_now_label">Authentifizieren</string>
- <string name="action_forbidden_title">Aktion verboten</string>
- <string name="action_forbidden_msg">AntennaPod besitzt keine Erlaubnis für diese Aktion. Der Grund dafür könnte sein, dass AntennaPods Zugangstoken aufgehoben worden ist. Du kannst dich entweder erneut authentifizieren oder die Flattr-Seite der Sache im Web besuchen.</string>
- <string name="access_revoked_title">Zugriff widerrufen</string>
- <string name="access_revoked_info">Du hast AntennaPod das Zugangstoken zu deinem Account entzogen. Um diesen Prozess abzuschließen, musst du diese Anwendung aus der Liste der zugelassenen Anwendungen in deinen Account Einstellungen auf der Flattr Webseite entfernen.</string>
- <!--Flattr-->
- <string name="flattr_click_success">Eine Sache wurde geflattrt!</string>
- <string name="flattr_click_success_count">%d Sachen wurden geflattrt!</string>
- <string name="flattr_click_success_queue">Geflattrt: %s</string>
- <string name="flattr_click_failure_count">Flattrn von %d Sachen fehlgeschlagen!</string>
- <string name="flattr_click_failure">Nicht geflattrt: %s</string>
- <string name="flattr_click_enqueued">Sache wird später geflattrt</string>
- <string name="flattring_thing">Flattrt: %s</string>
- <string name="flattring_label">AntennaPod flattrt</string>
- <string name="flattrd_label">AntennaPod hat geflattrt</string>
- <string name="flattrd_failed_label">AntennaPod Flattrn fehlgeschlagen</string>
- <string name="flattr_retrieving_status">Rufe geflattrte Sachen ab</string>
+ <string name="sort_old_to_new">Alt zu neu</string>
+ <string name="sort_new_to_old">Neu zu alt</string>
<!--Variable Speed-->
<string name="download_plugin_label">Plugin herunterladen</string>
<string name="no_playback_plugin_title">Plugin nicht installiert</string>
@@ -324,7 +304,6 @@
<string name="no_items_header_label">Leere Abspielliste</string>
<string name="no_items_label">Du kannst Episoden hinzufügen, indem du sie herunterlädst oder sie lange antippst und \"Zur Abspielliste hinzufügen\" auswählst.</string>
<string name="no_feeds_label">Du hast noch keine Feeds abonniert.</string>
- <string name="no_chapters_label">Diese Episode hat keine Kapitel.</string>
<string name="no_shownotes_label">Episode hat keine Shownotizen.</string>
<string name="no_run_downloads_head_label">Keine laufenden Downloads</string>
<string name="no_run_downloads_label">Du kannst Episoden auf der Podcast-Seite herunterladen.</string>
@@ -340,6 +319,8 @@
<string name="no_new_episodes_label">Wenn neue Episoden veröffentlicht werden, erscheinen sie hier.</string>
<string name="no_fav_episodes_head_label">Keine Favoriten</string>
<string name="no_fav_episodes_label">Du kannst Episoden als Favorit markieren, indem du sie lange antippst.</string>
+ <string name="no_chapters_head_label">Keine Kapitel</string>
+ <string name="no_chapters_label">Diese Episode hat keine Kapitel.</string>
<!--Preferences-->
<string name="storage_pref">Speicher</string>
<string name="project_pref">Projekt</string>
@@ -347,8 +328,6 @@
<string name="about_pref">Über</string>
<string name="queue_label">Abspielliste</string>
<string name="integrations_label">Einbindungen</string>
- <string name="flattr_label">Flattr</string>
- <string name="flattr_summary">Micropayment-Dienst</string>
<string name="automation">Automatisierung</string>
<string name="download_pref_details">Details</string>
<string name="import_export_pref">Import/Export</string>
@@ -356,7 +335,10 @@
<string name="appearance">Erscheinungsbild</string>
<string name="external_elements">Externe Elemente</string>
<string name="interruptions">Unterbrechungen</string>
- <string name="buttons">Buttons zur Steuerung der Wiedergabe</string>
+ <string name="playback_control">Wiedergabesteurung</string>
+ <string name="preference_search_hint">Suchen…</string>
+ <string name="preference_search_no_results">Keine Ergebnisse</string>
+ <string name="preference_search_clear_history">Verlauf leeren</string>
<string name="media_player">Medienabspieler</string>
<string name="pref_episode_cleanup_title">Automatisches Löschen</string>
<string name="pref_episode_cleanup_summary">Episoden, die weder in der Abspielliste noch Favoriten sind, können gelöscht werden, wenn beim automatischen Herunterladen Speicherplatz für neue Episoden gebraucht wird</string>
@@ -393,20 +375,13 @@
<string name="pref_unpauseOnHeadsetReconnect_title">Kopfhörer wieder eingesteckt</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Bluetooth wieder verbunden</string>
<string name="pref_mobileUpdate_title">Mobile Aktualisierungen</string>
- <string name="pref_mobileUpdate_sum">Erlaube Aktualisierungen über die mobile Datenverbindung</string>
- <string name="pref_mobileUpdate_nothing">Nichts</string>
- <string name="pref_mobileUpdate_images">Nur Bilder</string>
- <string name="pref_mobileUpdate_everything">Alles</string>
+ <string name="pref_mobileUpdate_sum">Auswählen, was über mobile Daten erlaubt sein soll</string>
+ <string name="pref_mobileUpdate_refresh">Podcasts aktualisieren</string>
+ <string name="pref_mobileUpdate_images">Titelbilder</string>
+ <string name="pref_mobileUpdate_auto_download">Automatisches Herunterladen</string>
+ <string name="pref_mobileUpdate_episode_download">Episoden herunterladen</string>
+ <string name="pref_mobileUpdate_streaming">Streamen</string>
<string name="refreshing_label">Aktualisiere</string>
- <string name="flattr_settings_label">Flattr Einstellungen</string>
- <string name="pref_flattr_auth_title">Flattr Anmeldung</string>
- <string name="pref_flattr_auth_sum">Melde dich mit deinem Flattr Account an, um direkt in der Anwendung zu flattrn.</string>
- <string name="pref_flattr_this_app_title">Flattr diese Anwendung</string>
- <string name="pref_flattr_this_app_sum">Unterstütze die Entwicklung von AntennaPod mit Flattr. Danke!</string>
- <string name="pref_revokeAccess_title">Zugriff entziehen</string>
- <string name="pref_revokeAccess_sum">Entziehe dieser Anwendung die Zugriffserlaubnis für deinen Flattr Account.</string>
- <string name="pref_auto_flattr_title">Automatisches Flattrn</string>
- <string name="pref_auto_flattr_sum">Automatisches Flattrn konfigurieren</string>
<string name="user_interface_label">Benutzeroberfläche</string>
<string name="pref_set_theme_title">Theme auswählen</string>
<string name="pref_nav_drawer_title">Seitenleiste anpassen</string>
@@ -428,6 +403,7 @@
<string name="pref_automatic_download_on_battery_sum">Automatische Downloads auch erlauben, wenn die Batterie nicht geladen wird</string>
<string name="pref_parallel_downloads_title">Parallele Downloads</string>
<string name="pref_episode_cache_title">Episodenspeicher</string>
+ <string name="pref_episode_cache_summary">Gesamtzahl an Episoden, die auf dem Gerät gespeichert werden. Automatisches Herunterladen wird pausiert, wenn diese Anzahl erreicht ist.</string>
<string name="pref_theme_title_light">Hell</string>
<string name="pref_theme_title_dark">Dunkel</string>
<string name="pref_theme_title_trueblack">Schwarz (für AMOLED)</string>
@@ -446,13 +422,15 @@
<string name="pref_gpodnet_full_sync_title">Jetzt komplett synchronisieren</string>
<string name="pref_gpodnet_full_sync_sum">Kompletten Abonnement- und Episoden-Status mit gpodder.net synchronisieren.</string>
<string name="pref_gpodnet_sync_sum_last_sync_line">Letzter Synchronisierungsversuch: %1$s (%2$s)</string>
- <string name="pref_gpodnet_sync_started">Synchronisation starten</string>
+ <string name="pref_gpodnet_sync_started">Synchronisation gestartet</string>
<string name="pref_gpodnet_full_sync_started">Komplette Synchronisierung gestartet</string>
<string name="pref_gpodnet_login_status"><![CDATA[Eingeloggt als <i>%1$s</i> mit dem Gerät <i>%2$s</i>]]></string>
<string name="pref_gpodnet_notifications_title">Zeige Benachrichtungen bei Synchronisierungsfehlern</string>
<string name="pref_gpodnet_notifications_sum">Diese Einstellung gilt nicht für Authentifizierungsfehler.</string>
<string name="pref_playback_speed_title">Wiedergabegeschwindigkeiten</string>
<string name="pref_playback_speed_sum">Lege die verfügbaren Werte für die Veränderung der Wiedergabeschwindigkeit fest</string>
+ <string name="pref_playback_time_respects_speed_title">Medieninfo an Abspielgeschwindigkeit anpassen</string>
+ <string name="pref_playback_time_respects_speed_sum">Abspielposition und Dauer werden auf Abspielgeschwindigkeit angepasst</string>
<string name="pref_fast_forward">Vorspulzeit</string>
<string name="pref_fast_forward_sum">Passe an, wie viele Sekunden vorgespult wird, wenn die entsprechende Hardware-Taste gedrückt wird</string>
<string name="pref_rewind">Rückspulzeit</string>
@@ -512,11 +490,6 @@
<string name="back_button_go_to_page_title">Seite auswählen</string>
<string name="pref_delete_removes_from_queue_title">Löschen entfernt aus Abspielliste</string>
<string name="pref_delete_removes_from_queue_sum">Entferne Episoden automatisch aus der Abspielliste, wenn sie gelöscht werden.</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">Automatisches Flattrn aktivieren</string>
- <string name="auto_flattr_after_percent">Flattr eine Episode, sobald %d Prozent gespielt worden sind</string>
- <string name="auto_flattr_ater_beginning">Flattr Episode, sobald die Wiedergabe beginnt</string>
- <string name="auto_flattr_ater_end">Flattr Episode, sobald die Wiedergabe endet</string>
<!--Search-->
<string name="search_hint">Suche nach Episoden</string>
<string name="found_in_shownotes_label">In Shownotizen gefunden</string>
@@ -610,12 +583,14 @@
<string name="gpodnetsync_error_descr">Ein Fehler ist beim Synchronisieren aufgetreten:\u0020</string>
<string name="gpodnetsync_pref_report_successful">Erfolgreich</string>
<string name="gpodnetsync_pref_report_failed">Fehlgeschlagen</string>
+ <string name="gpodnetsync_username_characters_error">Benutzernamen dürfen nur Buchstaben, Zahlen, Bindestriche und Unterstriche enthalten.</string>
<!--Directory chooser-->
<string name="selected_folder_label">Ausgewählter Ordner:</string>
<string name="create_folder_label">Neuer Ordner</string>
<string name="choose_data_directory">Datenordner auswählen</string>
<string name="choose_data_directory_message">Bitte wähle eine Basis für deinen Datenordner. AntennaPod erstellt automatisch die richtigen Unterverzeichnisse.</string>
<string name="choose_data_directory_permission_rationale">Zugriff auf den externen Speicher wird benötigt, um den Datenordner zu ändern</string>
+ <string name="choose_data_directory_available_space">%1$s von %2$s frei</string>
<string name="create_folder_msg">Neuen Ordner mit Namen \"%1$s\" erstellen?</string>
<string name="create_folder_success">Neuer Ordner angelegt</string>
<string name="create_folder_error_no_write_access">Kann in diesem Ordner nicht schreiben</string>
@@ -642,7 +617,7 @@
<string name="media_type_audio_label">Audio</string>
<string name="media_type_video_label">Video</string>
<string name="navigate_upwards_label">Nach oben navigieren</string>
- <string name="status_downloading_label">Episode wird gerade heruntergeladen</string>
+ <string name="status_downloading_label">Episode wird heruntergeladen</string>
<string name="in_queue_label">Episode befindet sich in der Abspielliste</string>
<string name="drag_handle_content_description">Ziehe, um die Position dieses Objekts zu verändern</string>
<string name="load_next_page_label">Nächste Seite laden</string>
@@ -656,13 +631,18 @@
<string name="episode_filters_exclude">Ausschließen</string>
<string name="episode_filters_hint">Einzelne Wörter\n\"Mehrere Wörter\"</string>
<string name="keep_updated">Aktuell halten</string>
+ <string name="keep_updated_summary">Diesen Podcast beim (automatischen) Aktualisieren einschließen</string>
+ <string name="auto_download_disabled_globally">Automatisches Herunterladen ist in den Einstellungen deaktiviert</string>
<!--Progress information-->
<string name="progress_upgrading_database">Datenbank wird aktualisiert</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Importiere Abonnements aus Single-Purpose Apps</string>
+ <!--Add podcast fragment-->
+ <string name="search_podcast_hint">Podcast suchen…</string>
<string name="search_itunes_label">iTunes durchsuchen</string>
- <string name="filter">Filtern</string>
<string name="search_fyyd_label">fyyd durchsuchen</string>
+ <string name="advanced_search">Erweiterte Suche</string>
+ <string name="filter">Filtern</string>
<!--Episodes apply actions-->
<string name="all_label">Alle</string>
<string name="selected_all_label">Alle Episoden ausgewählt</string>
@@ -746,10 +726,11 @@
<!--Notification channels-->
<string name="notification_channel_user_action">Handlung notwendig</string>
<string name="notification_channel_user_action_description">Wird gezeigt, wenn deine Handlung notwendig ist, zum Beispiel wenn du ein Passwort eingeben musst.</string>
- <string name="notification_channel_downloading">Lädt herunter</string>
+ <string name="notification_channel_downloading">Herunterladen</string>
<string name="notification_channel_downloading_description">Wird gezeigt beim Herunterladen.</string>
<string name="notification_channel_playing">Jetzt spielt</string>
<string name="notification_channel_playing_description">Erlaubt es, die Wiedergabe zu steuern. Dies ist die Hauptbenachrichtigung, die du siehst, während ein Podcast abgespielt wird.</string>
<string name="notification_channel_error">Fehler</string>
<string name="notification_channel_error_description">Wird gezeigt, wenn etwas schief gegangen ist, etwa wenn das Herunterladen oder die gpodder-Synchronisierung fehlschlägt.</string>
+ <string name="import_bad_file">Invalide/beschädigte Datei</string>
</resources>
diff --git a/core/src/main/res/values-el/strings.xml b/core/src/main/res/values-el/strings.xml
index 2e1c6cd33..e5a319740 100644
--- a/core/src/main/res/values-el/strings.xml
+++ b/core/src/main/res/values-el/strings.xml
@@ -100,7 +100,6 @@
<string name="add_to_favorite_label">Προσθήκη στα Αγαπημένα</string>
<string name="remove_from_favorite_label">Προσθήκη από τα Αγαπημένα</string>
<string name="visit_website_label">Επισκεφθείτε την ιστοσελίδα</string>
- <string name="support_label">Flattr αυτό</string>
<string name="skip_episode_label">Μετάβαση επεισοδίων</string>
<string name="activate_auto_download">Ενεργοποίηση Αυτόματης Λήψης</string>
<string name="deactivate_auto_download">Απενεργοποίηση Αυτόματης Λήψης</string>
@@ -161,32 +160,6 @@
<string name="ascending">Αύξουσα</string>
<string name="descending">Φθίνουσα</string>
<string name="clear_queue_confirmation_msg">Παρακαλούμε επιβεβαιώστε ότι θέλετε να διαγράψετε την ουρά όλων των επεισοδίων σε αυτό</string>
- <!--Flattr-->
- <string name="flattr_auth_label">Flattr σύνδεση </string>
- <string name="flattr_auth_explanation">Πατήστε το κουμπί παρακάτω για να ξεκινήσει η διαδικασία ελέγχου ταυτότητας. Θα πρέπει να διαβιβάζονται στην οθόνη σύνδεσης Flattr στον browser σας και να σας ζητηθεί να δώσει AntennaPod την άδεια να Flattr πράγματα. Αφού έχετε δώσει την άδεια, θα επιστρέψετε σε αυτήν την οθόνη αυτόματα.</string>
- <string name="authenticate_label">Έλεγχος</string>
- <string name="return_home_label">Επιστροφή στην αρχική σελίδα</string>
- <string name="flattr_auth_success">Έλεγχος ταυτότητας ήταν επιτυχής! Μπορείτε τώρα να Flattr πράγματα μέσα από την εφαρμογή.</string>
- <string name="no_flattr_token_title">Δεν βρέθηκε Flattr διακριτικό</string>
- <string name="no_flattr_token_notification_msg">Ο Flattr λογαριασμός σας δεν φαίνεται να συνδέεται με το AntennaPod. Πατήστε εδώ για να επικυρωθει.</string>
- <string name="no_flattr_token_msg">Ο Flattr λογαριασμός σας δεν φαίνεται να συνδέεται με το AntennaPod. Μπορείτε είτε να συνδέσετε το λογαριασμό σας στο AntennaPod να Flattr πράγματα μέσα από την εφαρμογή ή μπορείτε να επισκεφθείτε την ιστοσελίδα του πράγματος για Flattr εκεί</string>
- <string name="authenticate_now_label">Έλεγχος</string>
- <string name="action_forbidden_title">Δράση απαγορεύεται</string>
- <string name="action_forbidden_msg">Το AntennaPod δεν έχει άδεια για τη δράση αυτή. Ο λόγος ειναι οτι θα μπορούσε να είναι ότι το διακριτικό πρόσβασης του AntennaPod στο λογαριασμό σας έχει ανακληθεί. Μπορείτε να κανετε εκ νέου τον ελεγχο ταυτοποιησης ή επισκεφθείτε την ιστοσελίδα του πράγματος.</string>
- <string name="access_revoked_title">Πρόσβαση ανακαλείται</string>
- <string name="access_revoked_info">Έχετε ανακαλέσει επιτυχώς διακριτικό πρόσβασης AntennaPod στον λογαριασμό σας. Για να ολοκληρωθεί η διαδικασία, θα πρέπει να αφαιρέσετε αυτή η εφαρμογή από τον κατάλογο των εγκεκριμένων αιτήσεων στις ρυθμίσεις του λογαριασμού σας στην Flattr ιστοσελίδα.</string>
- <!--Flattr-->
- <string name="flattr_click_success">Flattr\'ed ένα πράγμα!</string>
- <string name="flattr_click_success_count">Flattr\'ed%d πράγματα!</string>
- <string name="flattr_click_success_queue">Flattr\'ed: %s.</string>
- <string name="flattr_click_failure_count">Αποτυχία Flattr%d πράγματα!</string>
- <string name="flattr_click_failure">Οχι flattr\'ed: %s.</string>
- <string name="flattr_click_enqueued">Πράγμα θα flattr\'ed αργότερα</string>
- <string name="flattring_thing">Flattring %s</string>
- <string name="flattring_label">Το AntennaPod είναι flattring</string>
- <string name="flattrd_label">Το AntennaPod έχει flattr\'ed</string>
- <string name="flattrd_failed_label">AntennaPod Flattr απέτυχε</string>
- <string name="flattr_retrieving_status">Ανάκτηση flattr\'ed πραγμάτων</string>
<!--Variable Speed-->
<string name="download_plugin_label">Λήψη Πρόσθετου</string>
<string name="no_playback_plugin_title">Το Πρόσθετο δεν είναι εγκατεστημένο</string>
@@ -196,7 +169,6 @@
<string name="other_pref">Άλλα</string>
<string name="about_pref">Σχετικά με</string>
<string name="queue_label">Σειρά αναμονής</string>
- <string name="flattr_label">Flattr</string>
<string name="pref_unpauseOnHeadsetReconnect_sum">Συνέχιση της αναπαραγωγής, όταν τα ακουστικά επανασυνδέονται</string>
<string name="pref_followQueue_sum">Μετάβαση στο επόμενο στοιχείο σειράς αναμονής όταν η αναπαραγωγή ολοκληρωθεί</string>
<string name="pref_auto_delete_sum">Διαγραφή επεισοδίων όταν η αναπαραγωγή ολοκληρωθεί</string>
@@ -205,16 +177,7 @@
<string name="network_pref">Δίκτυο</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Λήψη αρχείων πολυμέσων μόνο μέσω WiFi</string>
<string name="pref_downloadMediaOnWifiOnly_title">WiFi λυψη πολυμεσων</string>
- <string name="pref_mobileUpdate_sum">Να επιτρέπονται ενημερώσεις μέσω της σύνδεσης δεδομένων κινητής τηλεφωνίας</string>
<string name="refreshing_label">Ανανεωση</string>
- <string name="flattr_settings_label">Flattr Ρυθμισεις</string>
- <string name="pref_flattr_auth_title">Flattr Συνδεση</string>
- <string name="pref_flattr_auth_sum">Συνδεθείτε στον Flattr λογαριασμό σας για να Flattr πράγματα απευθείας από την εφαρμογή.</string>
- <string name="pref_flattr_this_app_sum">Υποστήριξη της ανάπτυξης του AntennaPod flattring αυτό. Ευχαριστούμε!</string>
- <string name="pref_revokeAccess_title">Ανάκληση πρόσβασης</string>
- <string name="pref_revokeAccess_sum">Ανακληση της άδειας πρόσβασης στον Flattr λογαριασμό για αυτη την εφαρμογή.</string>
- <string name="pref_auto_flattr_title">Αυτόματο Flattr</string>
- <string name="pref_auto_flattr_sum">Διαμόρφωση αυτόματου flattring</string>
<string name="user_interface_label">Περιβάλλον χρήστη</string>
<string name="pref_set_theme_sum">Αλλαγή της εμφάνισης του AntennaPod.</string>
<string name="pref_automatic_download_sum">Ρύθμιση της αυτόματης λήψης των επεισοδίων.</string>
@@ -243,11 +206,6 @@
<string name="pref_queueAddToFront_sum">Προσθήκη νέων επεισοδίων στο μπροστινό μέρος της ουράς.</string>
<string name="pref_queueAddToFront_title">Τοποθέτηση στην Αρχή της Ουράς</string>
<string name="experimental_pref">Πειραματικό</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">Ενεργοποίηση αυτόματου flattring</string>
- <string name="auto_flattr_after_percent">Flattr επεισόδιο συντομότερο απο %d τοις εκατό έχει παιχτεί</string>
- <string name="auto_flattr_ater_beginning">Flattr επεισόδιο όταν αρχίζει η αναπαραγωγή</string>
- <string name="auto_flattr_ater_end">Flattr επεισόδιο όταν ολοκληρωθεί η αναπαραγωγή του</string>
<!--Search-->
<string name="found_in_chapters_label">Βρέθηκε σε κεφάλαια</string>
<string name="search_status_no_results">Δεν βρέθηκαν αποτελέσματα</string>
@@ -341,6 +299,7 @@
<!--Progress information-->
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Εισαγωγή εγγραφών από εφαρμογές και μονο...</string>
+ <!--Add podcast fragment-->
<string name="search_itunes_label">iTunes Αναζήτηση</string>
<!--Episodes apply actions-->
<string name="all_label">Όλα</string>
diff --git a/core/src/main/res/values-es/strings.xml b/core/src/main/res/values-es/strings.xml
index 1a60a20b0..01ee726de 100644
--- a/core/src/main/res/values-es/strings.xml
+++ b/core/src/main/res/values-es/strings.xml
@@ -111,14 +111,16 @@
<string name="podcastdirectories_label">Buscar pódcast en el directorio</string>
<string name="podcastdirectories_descr">Para nuevos pódcast, puede buscar en iTunes o fyyd, o explorar en gpodder.net por nombre, categoría o popularidad.</string>
<string name="browse_gpoddernet_label">Explorar en gpodder.net</string>
+ <string name="discover">Descubrir</string>
+ <string name="discover_more">más »</string>
<!--Actions on feeds-->
<string name="mark_all_read_label">Marcar todos como reproducidos</string>
<string name="mark_all_read_msg">Marcados todos los episodios como reproducidos</string>
<string name="mark_all_read_confirmation_msg">Confirme que quiere marcar todos los episodios como reproducidos.</string>
<string name="mark_all_read_feed_confirmation_msg">Confirme que quiere marcar todos los episodios de este pódcast como reproducidos.</string>
- <string name="remove_all_new_flags_label">Marcar todos como vistos</string>
- <string name="removed_all_new_flags_msg">Marcados todos los episodios como vistos</string>
- <string name="remove_all_new_flags_confirmation_msg">Confirme que quiere marcar todos los episodios como vistos.</string>
+ <string name="remove_all_new_flags_label">Eliminar todas las marcas \"nuevo\"</string>
+ <string name="removed_all_new_flags_msg">Eliminadas todas las marcas \"nuevo\"</string>
+ <string name="remove_all_new_flags_confirmation_msg">Por favor, confirma que quieres eliminar las marcas \"nuevo\" de todos los episodios.</string>
<string name="show_info_label">Información del programa</string>
<string name="show_feed_settings_label">Mostrar ajustes del pódcast</string>
<string name="feed_info_label">Información del pódcast</string>
@@ -169,8 +171,8 @@
<item quantity="one">%depisodio borrado.</item>
<item quantity="other">%depisodios borrados.</item>
</plurals>
- <string name="remove_new_flag_label">Marcar como visto</string>
- <string name="removed_new_flag_label">Marcado como visto</string>
+ <string name="remove_new_flag_label">Eliminar marca \"nuevo\"</string>
+ <string name="removed_new_flag_label">Eliminada marca \"nuevo\"</string>
<string name="mark_read_label">Marcar como reproducido</string>
<string name="marked_as_read_label">Marcado como reproducido</string>
<plurals name="marked_read_batch_label">
@@ -198,7 +200,6 @@
<string name="remove_from_favorite_label">Eliminar de favoritos</string>
<string name="removed_from_favorites">Eliminado de favoritos</string>
<string name="visit_website_label">Visitar el sitio web</string>
- <string name="support_label">Añadir a Flattr</string>
<string name="skip_episode_label">Omitir episodio</string>
<string name="activate_auto_download">Activar descarga automática</string>
<string name="deactivate_auto_download">Desactivar descarga automática</string>
@@ -250,6 +251,9 @@
<string name="confirm_mobile_download_dialog_title">Confirmar descarga por red móvil</string>
<string name="confirm_mobile_download_dialog_message_not_in_queue">Se desactivaron las descargas por red de datos móviles en la configuración.\n\nPuede elegir entre añadir el episodio a la cola o permitir las descargas temporalmente.\n\n<small>Se recordará su elección durante 10 minutos.</small></string>
<string name="confirm_mobile_download_dialog_message">Se desactivaron las descargas por red de datos móviles en la configuración.\n\n¿Quiere permitir las descargas temporalmente?\n\n<small>Se recordará su elección durante 10 minutos.</small></string>
+ <string name="confirm_mobile_streaming_notification_title">Confirmar streaming por red móvil</string>
+ <string name="confirm_mobile_streaming_notification_message">El streaming sobre datos móviles está deshabilitado en los ajustes. Toca para hacer el streaming de todas formas.</string>
+ <string name="confirm_mobile_streaming_button_always">Permitir siempre</string>
<string name="confirm_mobile_download_dialog_only_add_to_queue">Añadir a la cola</string>
<string name="confirm_mobile_download_dialog_enable_temporarily">Permitir temporalmente</string>
<!--Mediaplayer messages-->
@@ -259,6 +263,8 @@
<string name="player_ready_msg">Listo</string>
<string name="player_seeking_msg">Buscando</string>
<string name="playback_error_server_died">El servidor está inactivo</string>
+ <string name="playback_error_unsupported">Tipo de medio no soportado</string>
+ <string name="playback_error_timeout">Tiempo de espera agotado</string>
<string name="playback_error_unknown">Error desconocido</string>
<string name="no_media_playing_label">No hay medios en reproducción</string>
<string name="player_buffering_msg">Almacenando</string>
@@ -276,6 +282,7 @@
<string name="move_to_top_label">Mover al principio</string>
<string name="move_to_bottom_label">Mover al final</string>
<string name="sort">Ordenar</string>
+ <string name="keep_sorted">Mantener ordenado</string>
<string name="date">Fecha</string>
<string name="duration">Duración</string>
<string name="episode_title">Título del episodio</string>
@@ -285,32 +292,8 @@
<string name="ascending">Ascendente</string>
<string name="descending">Descendente</string>
<string name="clear_queue_confirmation_msg">Confirme que quiere borrar TODOS los episodios de la cola</string>
- <!--Flattr-->
- <string name="flattr_auth_label">Identificarse en Flattr</string>
- <string name="flattr_auth_explanation">Pulse el botón inferior para iniciar el proceso de autenticación. Su navegador abrirá la pantalla de inicio de sesión en Flattr y le preguntará si quiere conceder permiso a AntennaPod para valorar. Tras concederlo, volverá a esta pantalla automáticamente.</string>
- <string name="authenticate_label">Autenticarse</string>
- <string name="return_home_label">Volver al inicio</string>
- <string name="flattr_auth_success">Autenticación exitosa. Ya puede valorar en Flattr desde la aplicación.</string>
- <string name="no_flattr_token_title">No se ha encontrado el token de Flattr</string>
- <string name="no_flattr_token_notification_msg">Parece que su cuenta de Flattr no está conectada con AntennaPod. Toque aquí para autenticarse.</string>
- <string name="no_flattr_token_msg">Su cuenta de Flattr no está conectada con AntennaPod. Puede conectarla con AntennaPod para valorar dentro de la aplicación o puede visitar la página web de Flattr para valorar desde allí.</string>
- <string name="authenticate_now_label">Autenticarse</string>
- <string name="action_forbidden_title">Acción prohibida</string>
- <string name="action_forbidden_msg">AntennaPod no tiene permiso para realizar esta acción. La razón puede ser que se haya revocado el token de acceso de AntennaPod en su cuenta. Puede reautenticarse o visitar la página web.</string>
- <string name="access_revoked_title">Acceso revocado</string>
- <string name="access_revoked_info">Ha revocado el token de acceso de AntennaPod a su cuenta. Para completar el proceso debe eliminar esta aplicación de la lista de aplicaciones aprobadas en los ajustes de la web de Flattr.</string>
- <!--Flattr-->
- <string name="flattr_click_success">Ha valorado con Flattr un elemento.</string>
- <string name="flattr_click_success_count">Ha valorado con Flattr %d elementos.</string>
- <string name="flattr_click_success_queue">valorado con Flattr: %s.</string>
- <string name="flattr_click_failure_count">No se pudieron valorar con Flattr %d elementos.</string>
- <string name="flattr_click_failure">No se ha valorado con Flattr: %s.</string>
- <string name="flattr_click_enqueued">Se valorará con Flattr más tarde</string>
- <string name="flattring_thing">Valorando con Flattr a %s</string>
- <string name="flattring_label">AntennaPod está valorando con Flattr</string>
- <string name="flattrd_label">AntennaPod ha valorado con Flattr</string>
- <string name="flattrd_failed_label">AntennaPod falló al valorar con Flattr</string>
- <string name="flattr_retrieving_status">Obteniendo lista de valoraciones con Flattr</string>
+ <string name="sort_old_to_new">Nuevo a viejo</string>
+ <string name="sort_new_to_old">Viejo a nuevo</string>
<!--Variable Speed-->
<string name="download_plugin_label">Descargar complemento</string>
<string name="no_playback_plugin_title">Complemento no instalado</string>
@@ -321,7 +304,6 @@
<string name="no_items_header_label">Sin episodios en la cola</string>
<string name="no_items_label">Añada un episodio descargándolo o presione prolongadamente un episodio y seleccione \"Añadir a la cola\".</string>
<string name="no_feeds_label">No se ha suscrito a ningún pódcast.</string>
- <string name="no_chapters_label">Este episodio no tiene capítulos.</string>
<string name="no_shownotes_label">Este episodio no tiene notas del programa.</string>
<string name="no_run_downloads_head_label">No hay descargas en ejecución</string>
<string name="no_run_downloads_label">Puede descargar episodios en la pantalla de detalles del pódcast.</string>
@@ -337,6 +319,8 @@
<string name="no_new_episodes_label">Cuando lleguen nuevos episodios, aparecerán aquí.</string>
<string name="no_fav_episodes_head_label">Sin episodios favoritos</string>
<string name="no_fav_episodes_label">Puede añadir episodios a los favoritos presionándolos durante un tiempo prolongado.</string>
+ <string name="no_chapters_head_label">Sin capítulos</string>
+ <string name="no_chapters_label">Este episodio no tiene capítulos.</string>
<!--Preferences-->
<string name="storage_pref">Almacenamiento</string>
<string name="project_pref">Proyecto</string>
@@ -344,8 +328,6 @@
<string name="about_pref">Acerca de</string>
<string name="queue_label">Cola</string>
<string name="integrations_label">Integraciones</string>
- <string name="flattr_label">Flattr</string>
- <string name="flattr_summary">Servicio de micropagos</string>
<string name="automation">Automatización</string>
<string name="download_pref_details">Detalles</string>
<string name="import_export_pref">Importar/Exportar</string>
@@ -353,7 +335,10 @@
<string name="appearance">Apariencia</string>
<string name="external_elements">Elementos externos</string>
<string name="interruptions">Interrupciones</string>
- <string name="buttons">Botones de control</string>
+ <string name="playback_control">Control de reproducción</string>
+ <string name="preference_search_hint">Buscar...</string>
+ <string name="preference_search_no_results">Sin resultados</string>
+ <string name="preference_search_clear_history">Borrar historial</string>
<string name="media_player">Reproductor multimedia</string>
<string name="pref_episode_cleanup_title">Limpieza de episodios</string>
<string name="pref_episode_cleanup_summary">Los episodios que no estén en la cola ni en favoritos pueden eliminarse si la descarga automática necesita espacio para nuevos episodios</string>
@@ -390,20 +375,13 @@
<string name="pref_unpauseOnHeadsetReconnect_title">Reconectar con los auriculares</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Reconectar con Bluetooth</string>
<string name="pref_mobileUpdate_title">Actualizaciones por red móvil</string>
- <string name="pref_mobileUpdate_sum">Permitir actualizaciones por la red de datos móvil</string>
- <string name="pref_mobileUpdate_nothing">Nada</string>
- <string name="pref_mobileUpdate_images">Solo imágenes</string>
- <string name="pref_mobileUpdate_everything">Todo</string>
+ <string name="pref_mobileUpdate_sum">Seleccionar lo que se debe permitir descargar con datos móviles</string>
+ <string name="pref_mobileUpdate_refresh">Actualizar fuente</string>
+ <string name="pref_mobileUpdate_images">Imágenes de portada</string>
+ <string name="pref_mobileUpdate_auto_download">Auto descargar</string>
+ <string name="pref_mobileUpdate_episode_download">Descarga de episodio</string>
+ <string name="pref_mobileUpdate_streaming">Streaming</string>
<string name="refreshing_label">Actualizando</string>
- <string name="flattr_settings_label">Ajustes de Flattr</string>
- <string name="pref_flattr_auth_title">Identificarse en Flattr</string>
- <string name="pref_flattr_auth_sum">Identifíquese en Flattr para valorar cosas directamente desde la aplicación</string>
- <string name="pref_flattr_this_app_title">Valorar en Flattr esta aplicación</string>
- <string name="pref_flattr_this_app_sum">Apoye el desarrollo de AntennaPod valorándola en Flattr. ¡Gracias!</string>
- <string name="pref_revokeAccess_title">Revocar acceso</string>
- <string name="pref_revokeAccess_sum">Revocar el acceso de esta aplicación en su cuenta de Flattr.</string>
- <string name="pref_auto_flattr_title">Flattr automático</string>
- <string name="pref_auto_flattr_sum">Configurar Flattr automático</string>
<string name="user_interface_label">Interfaz de usuario</string>
<string name="pref_set_theme_title">Elegir un tema</string>
<string name="pref_nav_drawer_title">Personalizar el cajón de navegación</string>
@@ -425,6 +403,7 @@
<string name="pref_automatic_download_on_battery_sum">Permitir la descarga automática cuando la batería no se esté cargando</string>
<string name="pref_parallel_downloads_title">Descargas paralelas</string>
<string name="pref_episode_cache_title">Almacenamiento de episodios</string>
+ <string name="pref_episode_cache_summary">Número total de episodios cacheados en el dispositivo. La descarga automática se suspenderá si se alcanza este número.</string>
<string name="pref_theme_title_light">Claro</string>
<string name="pref_theme_title_dark">Oscuro</string>
<string name="pref_theme_title_trueblack">Negro (para AMOLED)</string>
@@ -450,6 +429,8 @@
<string name="pref_gpodnet_notifications_sum">Este ajuste no afecta a los errores de autenticación.</string>
<string name="pref_playback_speed_title">Velocidades de reproducción</string>
<string name="pref_playback_speed_sum">Personalice las velocidades disponibles en la reproducción de audio a velocidad variable</string>
+ <string name="pref_playback_time_respects_speed_title">Ajustar la información del medio según la velocidad de reproducción</string>
+ <string name="pref_playback_time_respects_speed_sum">La posición y duración están adaptadas a la velocidad de reproducción</string>
<string name="pref_fast_forward">Intervalo de avance</string>
<string name="pref_fast_forward_sum">Personalice el número de segundos que avanzará cuando se pulsa el botón de avance</string>
<string name="pref_rewind">Intervalo de retroceso</string>
@@ -509,11 +490,6 @@
<string name="back_button_go_to_page_title">Seleccionar página</string>
<string name="pref_delete_removes_from_queue_title">Eliminar quita de la cola</string>
<string name="pref_delete_removes_from_queue_sum">Quitar automáticamente un episodio de la cola cuando se elimina.</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">Habilitar Flattr automático</string>
- <string name="auto_flattr_after_percent">Valorar con Flattr el episodio cuando se haya reproducido el %d por ciento</string>
- <string name="auto_flattr_ater_beginning">Valorar con Flattr el episodio al comenzar la reproducción</string>
- <string name="auto_flattr_ater_end">Valorar con Flattr el episodio al terminar la reproducción</string>
<!--Search-->
<string name="search_hint">Buscar episodios</string>
<string name="found_in_shownotes_label">Encontrado en las notas del programa</string>
@@ -607,12 +583,14 @@
<string name="gpodnetsync_error_descr">Ocurrió un error de sincronización:\u0020</string>
<string name="gpodnetsync_pref_report_successful">Exitoso</string>
<string name="gpodnetsync_pref_report_failed">Fallido</string>
+ <string name="gpodnetsync_username_characters_error">Los nombres de usuario solo pueden contener legras, dígitos, guiones medios y guiones bajos.</string>
<!--Directory chooser-->
<string name="selected_folder_label">Carpeta seleccionada</string>
<string name="create_folder_label">Crear carpeta</string>
<string name="choose_data_directory">Elegir carpeta de datos</string>
<string name="choose_data_directory_message">Elija la raíz de la carpeta de datos. AntennaPod creará los subdirectorios apropiados.</string>
<string name="choose_data_directory_permission_rationale">Necesita acceso al almacenamiento externo para cambiar la carpeta de datos</string>
+ <string name="choose_data_directory_available_space">%1$s de %2$s libre</string>
<string name="create_folder_msg">¿Crear carpeta con nombre \"%1$s\"?</string>
<string name="create_folder_success">Carpeta nueva creada</string>
<string name="create_folder_error_no_write_access">No se puede escribir en esta carpeta</string>
@@ -653,13 +631,18 @@
<string name="episode_filters_exclude">Excluir</string>
<string name="episode_filters_hint">Palabras sueltas \n\"múltiples palabras\"</string>
<string name="keep_updated">Mantener actualizado</string>
+ <string name="keep_updated_summary">Incluir esta fuente cuando se (auto-)refresquen todas las fuentes</string>
+ <string name="auto_download_disabled_globally">La descarga automática está deshabilitada en las preferencias generales de AntennaPod</string>
<!--Progress information-->
<string name="progress_upgrading_database">Actualizando la base de datos</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Importando suscripciones de aplicaciones de uso específico…</string>
+ <!--Add podcast fragment-->
+ <string name="search_podcast_hint">Buscar podcast...</string>
<string name="search_itunes_label">Buscar en iTunes</string>
- <string name="filter">Filtro</string>
<string name="search_fyyd_label">Buscar en fyyd</string>
+ <string name="advanced_search">Búsqueda avanzada</string>
+ <string name="filter">Filtro</string>
<!--Episodes apply actions-->
<string name="all_label">Todos</string>
<string name="selected_all_label">Todos los episodios seleccionados</string>
@@ -749,4 +732,5 @@
<string name="notification_channel_playing_description">Permite controlar la reproducción. Es la notificación principal que se ve mientras se reproduce un pódcast.</string>
<string name="notification_channel_error">Errores</string>
<string name="notification_channel_error_description">Muestra si algo salió mal, por ejemplo, si falla la descarga o la sincronización de gpodder</string>
+ <string name="import_bad_file">Archivo inválido/corrupto</string>
</resources>
diff --git a/core/src/main/res/values-et/strings.xml b/core/src/main/res/values-et/strings.xml
index 44c9f749b..5188d5366 100644
--- a/core/src/main/res/values-et/strings.xml
+++ b/core/src/main/res/values-et/strings.xml
@@ -91,7 +91,6 @@
<!--Actions on feeds-->
<string name="mark_all_read_label">Märgi kuulatuks</string>
<string name="mark_all_read_msg">Märgi kõik saated esitatuks</string>
- <string name="remove_all_new_flags_label">Märgi kõik nähtuks</string>
<string name="show_info_label">Näita infot</string>
<string name="share_label">Jaga...</string>
<string name="share_file_label">Jaga faili</string>
@@ -116,7 +115,6 @@
<string name="stream_label">Voogedastusena</string>
<string name="remove_label">Eemalda</string>
<string name="delete_label">Kustuta</string>
- <string name="removed_new_flag_label">Märgitud nähtuks</string>
<string name="mark_read_label">Märgi esitatuks</string>
<string name="marked_as_read_label">Märgitud kuulatuks</string>
<string name="mark_unread_label">Märgitud kui kuulamata</string>
@@ -201,28 +199,20 @@
<string name="episode_title">Saate pealkiri</string>
<string name="ascending">Kasvavalt</string>
<string name="descending">Kahanevalt</string>
- <!--Flattr-->
- <string name="authenticate_label">Autendi</string>
- <string name="return_home_label">Tagasi koju</string>
- <string name="authenticate_now_label">Autendi</string>
- <string name="action_forbidden_title">Tegevus on keelatud</string>
- <string name="access_revoked_title">Ligipääs on eemaldatud</string>
- <!--Flattr-->
<!--Variable Speed-->
<string name="download_plugin_label">Laadi plugin alla</string>
<string name="no_playback_plugin_title">Pluginat pole paigaldatud</string>
<string name="set_playback_speed_label">Esitamise kiirused</string>
<string name="enable_sonic">Luba Sonicu kasutamine</string>
<!--Empty list labels-->
- <string name="no_chapters_label">Saatel pole peatükke.</string>
<string name="no_shownotes_label">Sellel saatel pole mingeid märkusi.</string>
+ <string name="no_chapters_label">Saatel pole peatükke.</string>
<!--Preferences-->
<string name="storage_pref">Salvestusruum</string>
<string name="project_pref">Projekt</string>
<string name="other_pref">Muud</string>
<string name="about_pref">Info</string>
<string name="queue_label">Järjekord</string>
- <string name="flattr_label">Flattr</string>
<string name="pref_episode_cleanup_title">Saadete kustutamien</string>
<string name="pref_followQueue_sum">Kui saade lõpeb, siis esita kohe järgmine järjekorras olev saade.</string>
<string name="pref_auto_delete_sum">Kustuta saated, kui need on kuulatud</string>
@@ -245,10 +235,7 @@
<string name="pref_unpauseOnHeadsetReconnect_title">Kõrvaklappide uuesti ühendamine</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Bloetoothi uuesti ühendamin</string>
<string name="pref_mobileUpdate_title">Uuendamine üle andmeside</string>
- <string name="pref_mobileUpdate_sum">Luba uuendamised kasutades mobiilset andmesidet</string>
<string name="refreshing_label">Värskendamine</string>
- <string name="flattr_settings_label">Flattri seaded</string>
- <string name="pref_revokeAccess_title">Eemalda ligipääs</string>
<string name="user_interface_label">Kasutajalidies</string>
<string name="pref_set_theme_title">Vali teema</string>
<string name="pref_nav_drawer_title">Kohanda peamenüüd</string>
@@ -301,7 +288,6 @@
<string name="pref_known_issues">Teadaolevad probleemid</string>
<string name="pref_no_browser_found">Veebilehitsejat ei leitud.</string>
<string name="pref_cast_title">Chromecasti tugi</string>
- <!--Auto-Flattr dialog-->
<!--Search-->
<string name="search_hint">Otsi saateid</string>
<string name="found_in_shownotes_label">Leitud saate märkmetest</string>
@@ -426,6 +412,7 @@
<!--Progress information-->
<string name="progress_upgrading_database">Andmebaasi uuendamine</string>
<!--AntennaPodSP-->
+ <!--Add podcast fragment-->
<string name="search_itunes_label">Otsi iTunest</string>
<string name="filter">Filter</string>
<!--Episodes apply actions-->
diff --git a/core/src/main/res/values-fa/strings.xml b/core/src/main/res/values-fa/strings.xml
index bc530d4de..4ee401f6e 100644
--- a/core/src/main/res/values-fa/strings.xml
+++ b/core/src/main/res/values-fa/strings.xml
@@ -21,8 +21,8 @@
<string name="playback_history_label">تاریخچه پخش</string>
<string name="gpodnet_main_label">gpodder.net</string>
<string name="gpodnet_summary">هم‌گام‌سازی با دیگر دستگاه‌ها</string>
- <string name="gpodnet_auth_label">gpodder.net Login</string>
- <string name="free_space_label">%1$s free </string>
+ <string name="gpodnet_auth_label">gpodder.net ورود</string>
+ <string name="free_space_label">%1$s تخفیف </string>
<string name="episode_cache_full_title">ظرفیت حافظه پنهان تکمیل شده است</string>
<string name="episode_cache_full_message">حد مجاز تکمیل شده است . شما می توانید اندازه حافظه پنهان را در تنظیمات افزایش دهید.</string>
<string name="synchronizing">در حال هم‌گام‌سازی</string>
@@ -66,6 +66,7 @@
<string name="cover_label">تصویر</string>
<string name="error_label">خطا</string>
<string name="error_msg_prefix">یک خطا رخ داد:</string>
+ <string name="needs_storage_permission">برای انجام فرایند دسترسی با حافظه نیازمند است</string>
<string name="refresh_label">تازه کردن</string>
<string name="external_storage_error_msg">هیچ فضای ذخیره سازی خارجی موجود نیست لطفا مطمئن شوید که کارت حافظه به درستی نصب شده است تا برنامه بتواند به درستی کار کند.</string>
<string name="chapters_label">فصل ها</string>
@@ -88,15 +89,20 @@
<string name="parallel_downloads_suffix">\u0020بارگیری هم‌زمان</string>
<string name="feed_auto_download_global">پیش فرض جهانی</string>
<string name="feed_auto_download_always">همیشه</string>
- <string name="feed_auto_download_never">Never</string>
+ <string name="feed_auto_download_never">هیچگاه</string>
<string name="send_label">ارسال...</string>
<string name="episode_cleanup_never">هرگز</string>
<string name="episode_cleanup_queue_removal">وقتی که در صف نیست</string>
<string name="episode_cleanup_after_listening">بعد از تمام شدن</string>
+ <plurals name="episode_cleanup_hours_after_listening">
+ <item quantity="one">۱ ساعت پس از پایان</item>
+ <item quantity="other">%d ساعت پس از پایان</item>
+ </plurals>
<plurals name="episode_cleanup_days_after_listening">
<item quantity="one">%dروز بعد از اتمام</item>
<item quantity="other">%dروز بعد از اتمام</item>
</plurals>
+ <string name="num_selected_label">%d انتخاب شده</string>
<!--'Add Feed' Activity labels-->
<string name="feedurl_label">Feed URL</string>
<string name="etxtFeedurlHint">www.example.com/feed</string>
@@ -108,8 +114,7 @@
<string name="mark_all_read_label">علامت گذاری همه به عنوان پخش شده</string>
<string name="mark_all_read_msg">همه قسمت‌ها به عنوان پخش شده علامت‌گذاری شد</string>
<string name="mark_all_read_confirmation_msg">لطفا تأیید کنید که می‌خواهید تمام قسمت‌ها را به عنوان پخش شده علامت بزنید.</string>
- <string name="remove_all_new_flags_label">علامت گذاری همه به عنوان دیده شده</string>
- <string name="remove_all_new_flags_confirmation_msg">لطفا تأیید کنید که می‌خواهید تمام قسمت‌ها را به عنوان دیده شده علامت بزنید.</string>
+ <string name="mark_all_read_feed_confirmation_msg">لطفا تأیید کنید که میخواهید تمام قسمتهای این پادکست را بعنوان پخش شده علامت بزنید.</string>
<string name="show_info_label">نمایش اطلاعات</string>
<string name="show_feed_settings_label">نمایش تنظیمات پادکست</string>
<string name="feed_info_label">اطلاعات پادکست</string>
@@ -118,13 +123,18 @@
<string name="remove_feed_label">پاک‌کردن پادکست</string>
<string name="share_label">اشتراک گذاری...</string>
<string name="share_link_label">هم‌رسانی نشانی پادکست</string>
+ <string name="share_link_with_position_label">اشتراک گذاری URL قسمت با موقعیت پخش</string>
<string name="share_file_label">اشتراک گذاری فایل</string>
<string name="share_feed_url_label">اشتراک گذاری URL خوراک </string>
<string name="share_item_url_label">هم‌رسانی نشانی پرونده رسانه</string>
+ <string name="share_item_url_with_position_label">اشتراک گذاری URL فایل قسمت با موقعیت پخش</string>
+ <string name="feed_delete_confirmation_msg">لطفا تأیید کنید که میخواهید پادکست \"%1$s\" و تمام قسمتهای آن که دانلود کرده اید را حذف کنید.</string>
<string name="feed_remover_msg">در حال پاک‌کردن پادکست</string>
<string name="load_complete_feed">تازه‌سازی تمام پادکست</string>
<string name="hide_episodes_title">پنهان کردن قسمت‌ها</string>
<string name="batch_edit">ویرایش گروهی</string>
+ <string name="select_all_above">انتخاب همه بالایی ها</string>
+ <string name="select_all_below">انتخاب همه پایینی ها</string>
<string name="hide_unplayed_episodes_label">پخش نشده</string>
<string name="hide_paused_episodes_label">متوقف شد</string>
<string name="hide_played_episodes_label">پخش شد</string>
@@ -133,10 +143,16 @@
<string name="hide_downloaded_episodes_label">بارگیری شده</string>
<string name="hide_not_downloaded_episodes_label">بارگیری نشده</string>
<string name="hide_has_media_label">دارای رسانه</string>
+ <string name="hide_is_favorite_label">مورد علاقه</string>
<string name="filtered_label">فیلتر شده</string>
+ <string name="refresh_failed_msg">{fa-exclamation-circle} آخرین تازه‌سازی ناموفق بود</string>
<string name="open_podcast">باز کردن پادکست</string>
<!--actions on feeditems-->
<string name="download_label">بارگیری</string>
+ <plurals name="downloading_batch_label">
+ <item quantity="one">بارگیری %dقسمت.</item>
+ <item quantity="other">بارگیری %d قسمت.</item>
+ </plurals>
<string name="play_label">پخش</string>
<string name="pause_label">مکث</string>
<string name="stop_label">توقف</string>
@@ -144,8 +160,11 @@
<string name="remove_label">حذف</string>
<string name="delete_label">حذف</string>
<string name="delete_failed">فایل حذف نشد.! راه اندازی مجدد دستگاه می تواند کمک کند.</string>
- <string name="remove_episode_lable">پاک کردن قسمت</string>
- <string name="removed_new_flag_label">علامت گذاری به عنوان دیده شده</string>
+ <string name="delete_episode_label">حذف قسمت</string>
+ <plurals name="deleted_episode_batch_label">
+ <item quantity="one">%d قسمت حذف شد.</item>
+ <item quantity="other">%d قسمت حذف شد.</item>
+ </plurals>
<string name="mark_read_label">علامت گذاری به عنوان پخش شده</string>
<string name="marked_as_read_label">بعنوان پخش شده علامت گذاری شد</string>
<string name="mark_unread_label">علامت گذاری به عنوان پخش نشده</string>
@@ -212,9 +231,6 @@
<string name="episode_title">عنوان قسمت</string>
<string name="feed_title">عنوان پادکست</string>
<string name="random">تصادفی</string>
- <!--Flattr-->
- <string name="return_home_label">بازگشت به خانه</string>
- <!--Flattr-->
<!--Variable Speed-->
<!--Empty list labels-->
<!--Preferences-->
@@ -227,7 +243,6 @@
<string name="import_export_pref">وارد/صادر کرد</string>
<string name="appearance">نمایش</string>
<string name="external_elements">عناصر خارجی</string>
- <string name="buttons">دکمه‌های کنترل پخش</string>
<string name="media_player">پخش‌کننده رسانه</string>
<string name="pref_auto_delete_title">حذف خودکار</string>
<string name="playback_pref">پخش</string>
@@ -263,7 +278,6 @@
<string name="media_player_builtin">پخش‌کننده پیش‌فرض اندروید</string>
<string name="stop_playback">توقف پخش</string>
<string name="continue_playback">ادامه پخش صدا</string>
- <!--Auto-Flattr dialog-->
<!--Search-->
<string name="search_hint">جستجو برای قسمت‌ها</string>
<string name="search_status_no_results">نتیجه‌ای یافت نشد</string>
@@ -297,11 +311,13 @@
<!--Feed information screen-->
<!--Progress information-->
<!--AntennaPodSP-->
+ <!--Add podcast fragment-->
<!--Episodes apply actions-->
<!--Sort-->
<!--Rating dialog-->
<!--Audio controls-->
<!--proxy settings-->
+ <!--Subscriptions fragment-->
<!--Database import/export-->
<!--Casting-->
<!--<string name="cast_failed_to_connect">Could not connect to the device</string>-->
diff --git a/core/src/main/res/values-fi/strings.xml b/core/src/main/res/values-fi/strings.xml
index 2d9481b84..067761579 100644
--- a/core/src/main/res/values-fi/strings.xml
+++ b/core/src/main/res/values-fi/strings.xml
@@ -1,40 +1,721 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources xmlns:tools="http://schemas.android.com/tools">
<!--Activitiy and fragment titles-->
+ <string name="feed_update_receiver_name">Päivitä tilaukset</string>
+ <string name="feeds_label">Syötteet</string>
+ <string name="statistics_label">Tilastot</string>
+ <string name="add_feed_label">Lisää Podcast</string>
+ <string name="episodes_label">Jaksot</string>
+ <string name="all_episodes_short_label">Kaikki</string>
+ <string name="new_episodes_label">Uusi</string>
+ <string name="favorite_episodes_label">Suosikit</string>
+ <string name="new_label">Uusi</string>
+ <string name="settings_label">Asetukset</string>
+ <string name="downloads_label">Lataukset</string>
+ <string name="downloads_running_label">Ajossa</string>
+ <string name="downloads_completed_label">Valmis</string>
+ <string name="downloads_log_label">Logi</string>
+ <string name="subscriptions_label">Tilaukset</string>
+ <string name="subscriptions_list_label">Tilauslista</string>
+ <string name="cancel_download_label">Peruuta\nLataus</string>
+ <string name="playback_history_label">Soittohistoria</string>
+ <string name="gpodnet_main_label">gpodder.net</string>
+ <string name="gpodnet_summary">Synkronoi toisiin laitteisiin</string>
+ <string name="gpodnet_auth_label">gpodder.net Kirjautuminen</string>
+ <string name="free_space_label">%1$s vapaa</string>
+ <string name="episode_cache_full_title">Jaksojen välimuisti täynnä</string>
+ <string name="episode_cache_full_message">Jaksojen välimuistin rajoitus on ylitetty. Voit lisätä välimuistin kokoa Asetuksissa.</string>
+ <string name="synchronizing">Synkronoi...</string>
<!--Statistics fragment-->
+ <string name="total_time_listened_to_podcasts">Podcasteja soitettu yhteensä:</string>
+ <string name="statistics_details_dialog">%1$d jakso %2$d:sta aloitettu.\n\nSoitettu %3$s jaksoa %4$s:sta.</string>
+ <string name="statistics_mode">Tilastointitila</string>
+ <string name="statistics_mode_normal">Laske oikeasti soitettu aikamäärä. Uudelleensoitto lasketaan kahdesti, mutta soitetuksi merkattua ei lasketa.</string>
+ <string name="statistics_mode_count_all">Laske yhteen kaikki soitetuksi merketatut podcastit</string>
+ <string name="statistics_speed_not_counted">Huomio: Soittonopeutta ei lasketa mukaan.</string>
<!--Main activity-->
+ <string name="drawer_open">Avaa menu</string>
+ <string name="drawer_close">Sulje menu</string>
+ <string name="drawer_preferences">Hyllyasetukset</string>
+ <string name="drawer_feed_order_unplayed_episodes">Järjestä kertojen mukaan</string>
+ <string name="drawer_feed_order_alphabetical">Järjestä aakkosellisesti</string>
+ <string name="drawer_feed_order_last_update">Järjestä julkaisupäivän mukaan</string>
+ <string name="drawer_feed_order_most_played">Järjestä soitettujen jaksojen mukaan</string>
+ <string name="drawer_feed_counter_new_unplayed">Uusia ja soittamattomia jaksoja</string>
+ <string name="drawer_feed_counter_new">Uusia jaksoja</string>
+ <string name="drawer_feed_counter_unplayed">Soittamattomia jaksoja</string>
+ <string name="drawer_feed_counter_downloaded">Ladattuja jaksoja</string>
+ <string name="drawer_feed_counter_none">Ei yhtään</string>
<!--Webview actions-->
+ <string name="open_in_browser_label">Avaa selaimessa</string>
+ <string name="copy_url_label">Kopioi URL</string>
+ <string name="share_url_label">Jaa URL</string>
+ <string name="copied_url_msg">Kopioitiin URL leikepöydälle</string>
+ <string name="go_to_position_label">Mene tähän aikamerkkiin</string>
<!--Playback history-->
+ <string name="clear_history_label">Tyhjennä historia</string>
<!--Other-->
+ <string name="confirm_label">Varmistus</string>
+ <string name="cancel_label">Peruuta</string>
+ <string name="yes">Kyllä</string>
+ <string name="no">Ei</string>
+ <string name="reset">Resetoi</string>
+ <string name="author_label">Tekijä(t)</string>
+ <string name="language_label">Kieli</string>
+ <string name="url_label">URL</string>
+ <string name="podcast_settings_label">Asetukset</string>
+ <string name="cover_label">Kuva</string>
+ <string name="error_label">Virhe</string>
+ <string name="error_msg_prefix">Tapahtui virhe:</string>
+ <string name="needs_storage_permission">Tallennustilan valtuutus tarvitaan tähän operaatioon.</string>
+ <string name="refresh_label">Päivitä</string>
+ <string name="external_storage_error_msg">Ulkoista tallennustilaa ei ole saatavilla. Varmista että ulkoinen tallennustila on aktivoitu, jotta sovellus voi toimia oikeellisesti.</string>
+ <string name="chapters_label">Kappaleet</string>
+ <string name="chapter_duration">Kesto: %1$s</string>
+ <string name="shownotes_label">Jaksomuistio</string>
+ <string name="description_label">Kuvaus</string>
+ <string name="most_recent_prefix">Uusin jakso:\u0020</string>
+ <string name="episodes_suffix">\u0020jaksoa</string>
+ <string name="length_prefix">Kesto:\u0020</string>
+ <string name="size_prefix">Koko:\u0020</string>
+ <string name="processing_label">Prosessoi</string>
+ <string name="loading_label">Lataa...</string>
+ <string name="save_username_password_label">Tallenna käyttäjätunnus ja salasana</string>
+ <string name="close_label">Sulje</string>
+ <string name="retry_label">Yritä uudelleen</string>
+ <string name="auto_download_label">Lataa automaattisesti</string>
+ <string name="auto_download_apply_to_items_title">Aseta edellisiin jaksoihin</string>
+ <string name="auto_download_apply_to_items_message">Uusi <i>Automaattinen lataus</i> asetus tullaan asettamaan uusiin jaksoihin.\nHaluatko asettaa myös aikaisemmin julkaistuihin jaksoihin?</string>
+ <string name="auto_delete_label">Auto deletoi jakso</string>
+ <string name="parallel_downloads_suffix">\u0020yhtäaikaiset lataukset</string>
+ <string name="feed_auto_download_global">Globaali oletus</string>
+ <string name="feed_auto_download_always">Aina</string>
+ <string name="feed_auto_download_never">Ei koskaan</string>
+ <string name="send_label">Lähetä...</string>
+ <string name="episode_cleanup_never">Ei koskaan</string>
+ <string name="episode_cleanup_queue_removal">Kun ei jonossa</string>
+ <string name="episode_cleanup_after_listening">Lopetuksen jälkeen</string>
+ <plurals name="episode_cleanup_hours_after_listening">
+ <item quantity="one">1 hour after finishing</item>
+ <item quantity="other">%d tuntia lopetuksen jälkeen</item>
+ </plurals>
+ <plurals name="episode_cleanup_days_after_listening">
+ <item quantity="one">1 päivä lataamisen jälkeen</item>
+ <item quantity="other">%d päivää lataamisen jälkeen</item>
+ </plurals>
+ <string name="num_selected_label">%d valittu</string>
<!--'Add Feed' Activity labels-->
+ <string name="feedurl_label">Syöte URL</string>
+ <string name="etxtFeedurlHint">www.example.com/feed</string>
+ <string name="txtvfeedurl_label">Lisää podcast URL</string>
+ <string name="podcastdirectories_label">Etsi podcast hakemistosta</string>
+ <string name="podcastdirectories_descr">Voit etsiä uusia podcasteja iTunes tai fyyd hakemistosta tai selata gpodder.net nimen, kategorian tai suosittujen mukaan.</string>
+ <string name="browse_gpoddernet_label">Selaa gpodder.net</string>
+ <string name="discover">Löydä</string>
+ <string name="discover_more">lisää »</string>
<!--Actions on feeds-->
+ <string name="mark_all_read_label">Merkkaa kaikki soitetuksi</string>
+ <string name="mark_all_read_msg">Merkkaa kaikki episodit soitetuiksi</string>
+ <string name="mark_all_read_confirmation_msg">Varmista että haluat merkata kaikki jaksot soitetuiksi</string>
+ <string name="mark_all_read_feed_confirmation_msg">Varmista että haluat merkata tämän podcastin kaikki jaksot soitetuksi</string>
+ <string name="remove_all_new_flags_label">Poista kaikki \"uusi\" liput</string>
+ <string name="removed_all_new_flags_msg">Poistettiin kaikki \"uusi\" liput</string>
+ <string name="remove_all_new_flags_confirmation_msg">Varmista että haluat poistaa kaikki \"uusi\" liput kaikista jaksoista.</string>
+ <string name="show_info_label">Näytä informaatio</string>
+ <string name="show_feed_settings_label">Näytä podcastin asetukset</string>
+ <string name="feed_info_label">Podcastin info</string>
+ <string name="feed_settings_label">Podcastin asetukset</string>
+ <string name="rename_feed_label">Uudelleennimeä podcast </string>
+ <string name="remove_feed_label">Poista podcast</string>
+ <string name="share_label">Jaa...</string>
+ <string name="share_link_label">Jaa jakson URL</string>
+ <string name="share_link_with_position_label">Jaa jakson URL soittoajan kanssa</string>
+ <string name="share_file_label">Jaa tietodosto</string>
+ <string name="share_feed_url_label">Jaa syötteen URL</string>
+ <string name="share_item_url_label">Jaa Media tiedoston URL</string>
+ <string name="share_item_url_with_position_label">Jaa Media tiedoston URL soittoajan kanssa</string>
+ <string name="feed_delete_confirmation_msg">Varmista, että haluat poistaa podcastin \"%1$s\" ja KAIKKI sen jaksot (mukaanlukien ladatut jaksot).</string>
+ <string name="feed_remover_msg">Poistetaan podcast</string>
+ <string name="load_complete_feed">Päivitä podcast</string>
+ <string name="hide_episodes_title">Piilota jaksoja</string>
+ <string name="batch_edit">Batch editoi</string>
+ <string name="select_all_above">Valitse kaikki yllä</string>
+ <string name="select_all_below">Valitse kaikki alla</string>
+ <string name="hide_unplayed_episodes_label">Soittamaton</string>
+ <string name="hide_paused_episodes_label">Pause</string>
+ <string name="hide_played_episodes_label">Soitettu</string>
+ <string name="hide_queued_episodes_label">Jonossa</string>
+ <string name="hide_not_queued_episodes_label">Ei jonossa</string>
+ <string name="hide_downloaded_episodes_label">Ladattu</string>
+ <string name="hide_not_downloaded_episodes_label">Ei ladattu</string>
+ <string name="hide_has_media_label">Sisältää mediaa</string>
+ <string name="hide_is_favorite_label">On suosikki</string>
+ <string name="filtered_label">Filteröity</string>
+ <string name="refresh_failed_msg">{fa-exclamation-circle} Viimeisin päivitys epäonnistui</string>
+ <string name="open_podcast">Avaa podcast</string>
<!--actions on feeditems-->
+ <string name="download_label">Lataa</string>
+ <plurals name="downloading_batch_label">
+ <item quantity="one">Lataa %d jakso</item>
+ <item quantity="other">Lataa %d jaksoja.</item>
+ </plurals>
+ <string name="play_label">Soita</string>
+ <string name="pause_label">Pause</string>
+ <string name="stop_label">Stop</string>
+ <string name="stream_label">Striimaa</string>
+ <string name="remove_label">Poista</string>
+ <string name="delete_label">Deletoi</string>
+ <string name="delete_failed">Ei voida poistaa tiedostoa. Laitteen uudelleenkäynnistys saattaa auttaa.</string>
+ <string name="delete_episode_label">Deletoi jakso</string>
+ <plurals name="deleted_episode_batch_label">
+ <item quantity="one">%d jakso deletoitu.</item>
+ <item quantity="other">%d jaksoa deletoitu.</item>
+ </plurals>
+ <string name="remove_new_flag_label">Poista \"uusi\" lippu</string>
+ <string name="removed_new_flag_label">Poistettiin \"uusi\" lippu</string>
+ <string name="mark_read_label">Merkitse soitetuksi</string>
+ <string name="marked_as_read_label">Merkattu soitetuksi</string>
+ <plurals name="marked_read_batch_label">
+ <item quantity="one">%d jakso merkattu soitetuksi.</item>
+ <item quantity="other">%d jaksoa merkattu soitetuksi</item>
+ </plurals>
+ <string name="mark_unread_label">Merkkaa soittamattomaksi</string>
+ <plurals name="marked_unread_batch_label">
+ <item quantity="one">%d jakso merkattu soittamattomaksi.</item>
+ <item quantity="other">%d jaksoa merkattu soittamattomaksi.</item>
+ </plurals>
+ <string name="add_to_queue_label">Lisää jonoon</string>
+ <string name="added_to_queue_label">Lisätty jonoon</string>
+ <plurals name="added_to_queue_batch_label">
+ <item quantity="one">%d jakso lisätty jonoon.</item>
+ <item quantity="other">%d jaksoa lisätty jonoon.</item>
+ </plurals>
+ <string name="remove_from_queue_label">Poista jonosta</string>
+ <plurals name="removed_from_queue_batch_label">
+ <item quantity="one">%d jakso poistettu jonosta.</item>
+ <item quantity="other">%d jaksoa poistettu jonosta.</item>
+ </plurals>
+ <string name="add_to_favorite_label">Lisää suosikkeihin</string>
+ <string name="added_to_favorites">Lisätty suosikkeihin</string>
+ <string name="remove_from_favorite_label">Poista suosikeista</string>
+ <string name="removed_from_favorites">Poistettu suosikeista</string>
+ <string name="visit_website_label">Selaa Web-sivustoa</string>
+ <string name="skip_episode_label">Skippaa jakso</string>
+ <string name="activate_auto_download">Aktivoi autolataukset</string>
+ <string name="deactivate_auto_download">Deaktivoi automaattinen lataus</string>
+ <string name="reset_position">Resetoi soittoaika</string>
+ <string name="removed_item">Asia poistettu</string>
<!--Download messages and labels-->
+ <string name="download_successful">onnistui</string>
+ <string name="download_failed">epäonnistui</string>
+ <string name="download_pending">Lataus odottamassa</string>
+ <string name="download_running">Lataamassa</string>
+ <string name="download_error_details">Tiedot</string>
+ <string name="download_error_details_message">%1$s \n\nTiedoston URL:\n%2$s</string>
+ <string name="download_error_device_not_found">Tallennuslaitetta ei löytynyt</string>
+ <string name="download_error_insufficient_space">Ei tarpeeksi tilaa</string>
+ <string name="download_error_file_error">Tiedostovirhe</string>
+ <string name="download_error_http_data_error">HTTP Data virhe</string>
+ <string name="download_error_error_unknown">Odottamaton virhe</string>
+ <string name="download_error_parser_exception">Parserin virhe</string>
+ <string name="download_error_unsupported_type">Ei tuettu tiedostotyyppi</string>
+ <string name="download_error_connection_error">Yhteysongelma</string>
+ <string name="download_error_unknown_host">Tuntematon Host</string>
+ <string name="download_error_unauthorized">Autentikaatio virhe</string>
+ <string name="download_error_file_type_type">Tiedostotyyppivirhe</string>
+ <string name="download_error_forbidden">Ei sallittu</string>
+ <string name="cancel_all_downloads_label">Peruuta kaikki lataukset</string>
+ <string name="download_canceled_msg">Lataus peruutettu</string>
+ <string name="download_canceled_autodownload_enabled_msg">Lataus peruutettu\nPoistettu <i>Automaattinen lataus</i> tälle tiedolle </string>
+ <string name="download_report_title">Lataukset valmistuivat virhe(ide)n kanssa</string>
+ <string name="download_report_content_title">Latausraportti</string>
+ <string name="download_error_malformed_url">Huonosti koostettu URL</string>
+ <string name="download_error_io_error">IO virhe</string>
+ <string name="download_error_request_error">Pyyntövirhe</string>
+ <string name="download_error_db_access">Tietokannan pääsyvirhe</string>
+ <plurals name="downloads_left">
+ <item quantity="one">%d lataus jäljellä</item>
+ <item quantity="other">%d latausta jäljellä</item>
+ </plurals>
+ <string name="downloads_processing">Prosessoi latauksia</string>
+ <string name="download_notification_title">Lataa podcastin tietoja</string>
+ <string name="download_report_content">%1$d latausta onnistui, %2$d epäonnistui</string>
+ <string name="download_log_title_unknown">Tuntematon otsikko</string>
+ <string name="download_type_feed">Syöte</string>
+ <string name="download_type_media">Mediatiedosto</string>
+ <string name="download_type_image">Kuva</string>
+ <string name="download_request_error_dialog_message_prefix">Tiedoston latauksen aikana tapahtui virhe:\u0020</string>
+ <string name="null_value_podcast_error">Ei voida näyttää olematonta podcastia</string>
+ <string name="authentication_notification_title">Vaaditaan autentikaatio</string>
+ <string name="authentication_notification_msg">Pyytämäsi resurssi vaatii käyttäjätunnuksen ja salasanan</string>
+ <string name="confirm_mobile_download_dialog_title">Varmista mobiililataus</string>
+ <string name="confirm_mobile_download_dialog_message_not_in_queue">Lataaminen mobiilidatayhteydellä on estettu asetuksissa.\n\nVoit lisätä yhden jakson jonoon tai sallia lataamisen väliaikaisesti.\n\n<small>Valinta muistetaan 10 minuutin ajan.</small></string>
+ <string name="confirm_mobile_download_dialog_message">Lataamienn mobiilidatayhteydellä on estettu asetuksissa.\n\nHaluatko sallia lataamisen väliaikaisesti?\n\n<small>Valinta muistetaan 10 minuutin ajan.</small></string>
+ <string name="confirm_mobile_download_dialog_only_add_to_queue">Lisää jonoon</string>
+ <string name="confirm_mobile_download_dialog_enable_temporarily">Salli väliaikaisesti</string>
<!--Mediaplayer messages-->
+ <string name="player_error_msg">Virhe!</string>
+ <string name="player_stopped_msg">Media ei soi</string>
+ <string name="player_preparing_msg">Valmistelee</string>
+ <string name="player_ready_msg">Valmis</string>
+ <string name="player_seeking_msg">Hakee</string>
+ <string name="playback_error_server_died">Palvelin tipahti</string>
+ <string name="playback_error_unknown">Tuntematon virhe</string>
+ <string name="no_media_playing_label">Media ei soi</string>
+ <string name="player_buffering_msg">Bufferoi</string>
+ <string name="player_go_to_picture_in_picture">Kuva-kuvassa-tila</string>
+ <string name="playbackservice_notification_title">Soittaa podcastia</string>
+ <string name="unknown_media_key">AntennaPod - Tuntematon media avain: %1$d</string>
<!--Queue operations-->
- <!--Flattr-->
- <!--Flattr-->
+ <string name="lock_queue">Lukitse jono</string>
+ <string name="unlock_queue">Avaa jono</string>
+ <string name="queue_locked">Jono lukittu</string>
+ <string name="queue_unlocked">Jono avattu</string>
+ <string name="clear_queue_label">Tyhjennä jono</string>
+ <string name="undo">Peruuta</string>
+ <string name="removed_from_queue">Aihe poistettu</string>
+ <string name="move_to_top_label">Siirrä ylimmäiseksi</string>
+ <string name="move_to_bottom_label">Siirrä alimmaikseksi</string>
+ <string name="sort">Lajittele</string>
+ <string name="date">Päivä</string>
+ <string name="duration">Kesto</string>
+ <string name="episode_title">Jakson otsikko</string>
+ <string name="feed_title">Podcastin otsikko</string>
+ <string name="random">Sekalainen</string>
+ <string name="smart_shuffle">Älykäs sekoitus</string>
+ <string name="ascending">Nouseva</string>
+ <string name="descending">Laskeva</string>
+ <string name="clear_queue_confirmation_msg">Varmista että haluat tyhjentää jonon KAIKISTA jaksoista</string>
+ <string name="sort_old_to_new">Vanhasta uuteen</string>
+ <string name="sort_new_to_old">Uudesta vanhaan</string>
<!--Variable Speed-->
+ <string name="download_plugin_label">Lataa plugin</string>
+ <string name="no_playback_plugin_title">Plugin ei asennettu</string>
+ <string name="no_playback_plugin_or_sonic_msg">Muuttuvan soittonopeuden toiminnassa suosittelemme sisäänrakennettua Sonic mediaplayer [Android 4.1+].\n\nVaihtoehtoisesti voit ladata kolmannen osapuolen pluginin <i>Prestissimo</i> Play Storesta.\nOngelmat Prestissimossa eivät ole AntennaPod vastuulla ja tulisi raportoida pluginin tekijöille.</string>
+ <string name="set_playback_speed_label">Soittonopeudet</string>
+ <string name="enable_sonic">Aloita Sonic</string>
<!--Empty list labels-->
+ <string name="no_items_header_label">Ei jaksoja jonossa</string>
+ <string name="no_items_label">Lisää jakso lataamalla ja painamalla pitkään jaksoa ja valitse \"Lisää jonoon\".</string>
+ <string name="no_feeds_label">Et ole tilannut yhtään podcastia vielä.</string>
+ <string name="no_shownotes_label">Jaksolla ei ole jaksomuistiota</string>
+ <string name="no_run_downloads_head_label">Ei latauksia</string>
+ <string name="no_run_downloads_label">Voit ladata jakson podcastin lisätietosivulla.</string>
+ <string name="no_comp_downloads_head_label">Ei ladattuja jaksoja</string>
+ <string name="no_comp_downloads_label">Voit ladata jakson podcastin listätietosivulla.</string>
+ <string name="no_log_downloads_head_label">Ei latauksien logia</string>
+ <string name="no_log_downloads_label">Latauslogi ilmestyy tänne kun se on saatavilla.</string>
+ <string name="no_history_head_label">Ei historiaa</string>
+ <string name="no_history_label">Jakson kuuntelun jälkeen se ilmestyy tänne.</string>
+ <string name="no_all_episodes_head_label">Ei jaksoja</string>
+ <string name="no_all_episodes_label">Kun lisää podcastin sen jaksot näkyvät täällä.</string>
+ <string name="no_new_episodes_head_label">Ei uusia jaksoja</string>
+ <string name="no_new_episodes_label">Kun uusia jaksoja ilmestyy ne näkyvät täällä.</string>
+ <string name="no_fav_episodes_head_label">Ei suosikkijaksoja</string>
+ <string name="no_fav_episodes_label">Voit lisätä jaksoja suosikkeihin painamalla niitä pitkään.</string>
+ <string name="no_chapters_head_label">Ei kappaleita</string>
+ <string name="no_chapters_label">Jaksolla ei ole kappaleita.</string>
<!--Preferences-->
- <!--Auto-Flattr dialog-->
+ <string name="storage_pref">Tallennus</string>
+ <string name="project_pref">Projekti</string>
+ <string name="other_pref">Muuta</string>
+ <string name="about_pref">Tietoja</string>
+ <string name="queue_label">Jono</string>
+ <string name="integrations_label">Integraatiot</string>
+ <string name="automation">Automaatio</string>
+ <string name="download_pref_details">Tietoja</string>
+ <string name="import_export_pref">Tuo/Vie</string>
+ <string name="import_export_search_keywords">backup, palautus</string>
+ <string name="appearance">Näkymä</string>
+ <string name="external_elements">Ulkoiset elementit</string>
+ <string name="interruptions">Keskeytykset</string>
+ <string name="playback_control">Soiton kontrollit</string>
+ <string name="media_player">Mediasoitto</string>
+ <string name="pref_episode_cleanup_title">Jakson siivous</string>
+ <string name="pref_episode_cleanup_summary">Jaksot, jotka eivät ole jonossa ja eivät ole suosikkeja tulisi olla valmiita poistoon jos Automaattiinen lataus tarvitsee tilaa uusille jaksoille</string>
+ <string name="pref_pauseOnDisconnect_sum">Pysäytä soitto kun kuulokkeet tai bluetooth katkaistaan</string>
+ <string name="pref_unpauseOnHeadsetReconnect_sum">Jatka soittoa kun kuulokkeet yhdistetään uudestaan</string>
+ <string name="pref_unpauseOnBluetoothReconnect_sum">Jatka soittoa kun bluetooth yhdistyy uudestaan</string>
+ <string name="pref_hardwareForwardButtonSkips_title">Seuraava nappi skippaa</string>
+ <string name="pref_hardwareForwardButtonSkips_sum">Kun painetaan seuraava nappia bluetooth-laitteessa, hyppää seuraavaan jaksoon etuhaun sijasta.</string>
+ <string name="pref_hardwarePreviousButtonRestarts_title">Edellinen nappi uudelleenaloittaa</string>
+ <string name="pref_hardwarePreviousButtonRestarts_sum">Kun painetaan edellinen nappia, uudelleenkäynnistä nykyinen jakso takaisinhaun sijasta</string>
+ <string name="pref_followQueue_sum">Hyppää seuraavaan jonossa kun soitto valmistuu</string>
+ <string name="pref_auto_delete_sum">Deletoi jakso kun soitto valmistuu</string>
+ <string name="pref_auto_delete_title">Autodeletoi</string>
+ <string name="pref_smart_mark_as_played_sum">Merkkaa jaksot soitetuiksi jos tietty määrä sekunteja soittoajasta on vielä jäljellä</string>
+ <string name="pref_smart_mark_as_played_title">Älykäs soitetuksi merkkaus</string>
+ <string name="pref_skip_keeps_episodes_sum">Säilytä jaksot kun ne skiptaaan</string>
+ <string name="pref_skip_keeps_episodes_title">Säilytä skiptatut jaksot</string>
+ <string name="pref_favorite_keeps_episodes_sum">Säilytä jaksot jotka on merkattu suosikeiksi</string>
+ <string name="pref_favorite_keeps_episodes_title">Säilytä suosikkijaksot</string>
+ <string name="playback_pref">Soitto</string>
+ <string name="network_pref">Verkko</string>
+ <string name="pref_autoUpdateIntervallOrTime_title">Päivitysintervalli tai ajankohta</string>
+ <string name="pref_autoUpdateIntervallOrTime_sum">Aseta intervalli tai ajankohta kun syötteet päivitetään automaattisesti</string>
+ <string name="pref_autoUpdateIntervallOrTime_message">Voit asettaa <i>intervallin</i> kuten \"joka 2 tuntia\", asettaa tietyn <i>ajankohdan</i> kuten \"7:00 AM\" tai <i>disabloida</i> automaattiset päivitykset.\n\n<small>Huomio: Päivitysajankohdat ovat epätarkkoja. Saatat huomata lyhyen välin.</small></string>
+ <string name="pref_autoUpdateIntervallOrTime_Disable">Disabloi</string>
+ <string name="pref_autoUpdateIntervallOrTime_Interval">Aseta intervalli</string>
+ <string name="pref_autoUpdateIntervallOrTime_TimeOfDay">Aseta ajankohta</string>
+ <string name="pref_autoUpdateIntervallOrTime_every">joka %1$s</string>
+ <string name="pref_autoUpdateIntervallOrTime_at">aika %1$s</string>
+ <string name="pref_downloadMediaOnWifiOnly_sum">Lataa mediatiedostot vain WiFin kautta</string>
+ <string name="pref_followQueue_title">Jatkuva soitto</string>
+ <string name="pref_downloadMediaOnWifiOnly_title">WiFi medialataus</string>
+ <string name="pref_pauseOnHeadsetDisconnect_title">Kuulokkeiden irrotus</string>
+ <string name="pref_unpauseOnHeadsetReconnect_title">Kuulokkeiden uudelleenyhdistyminen</string>
+ <string name="pref_unpauseOnBluetoothReconnect_title">Bluetooth uudelleenyhdistyminen</string>
+ <string name="pref_mobileUpdate_title">Mobiilipäivitykset</string>
+ <string name="refreshing_label">Päivittää</string>
+ <string name="user_interface_label">Käyttöliittymä</string>
+ <string name="pref_set_theme_title">Valitse teema</string>
+ <string name="pref_nav_drawer_title">Kustomoi navogointihylly</string>
+ <string name="pref_nav_drawer_sum">Kustomoi näkymä navigointihyllyssä</string>
+ <string name="pref_nav_drawer_items_title">Aseta navigointihyllyn asiat</string>
+ <string name="pref_nav_drawer_items_sum">Vaihda navigointihyllyssä esiintyviä asioita.</string>
+ <string name="pref_nav_drawer_feed_order_title">Aseta tilauksien järjestys</string>
+ <string name="pref_nav_drawer_feed_order_sum">Vaihda tilauksiesi järjestystä</string>
+ <string name="pref_nav_drawer_feed_counter_title">Aseta tilauksien laskuri</string>
+ <string name="pref_nav_drawer_feed_counter_sum">Vaihta tilauksien laskurin näyttämää informaatiota. Tämä vaikuttaa tilauksien järjestykseen jos \"Tilausjärjestys\" on asetettu \"Laskuri\".</string>
+ <string name="pref_set_theme_sum">Vaihda AntennaPodin näkymää</string>
+ <string name="pref_automatic_download_title">Automaattinen lataus</string>
+ <string name="pref_automatic_download_sum">Aseta jaksojen automaattinen lataus</string>
+ <string name="pref_autodl_wifi_filter_title">Aseta Wi-Fi filtteri</string>
+ <string name="pref_autodl_wifi_filter_sum">Salli automaatiset lataukset vain sallittujen Wi-Fi verkkojen kautta.</string>
+ <string name="pref_autodl_allow_on_mobile_title">Lataa mobiiilidatayhteydellä</string>
+ <string name="pref_autodl_allow_on_mobile_sum">Salli automaattinen lataus mobiilitdatayhteyden kautta</string>
+ <string name="pref_automatic_download_on_battery_title">Lataa kun ei ladata akkua</string>
+ <string name="pref_automatic_download_on_battery_sum">Salli automaattiset lataukset kun akku ei ole latautumassa</string>
+ <string name="pref_parallel_downloads_title">Yhtäaikaiset lataukset</string>
+ <string name="pref_episode_cache_title">Jaksojen välimuisti</string>
+ <string name="pref_episode_cache_summary">Ladattuja jaksoja yhteensä välimuistissa tällä laitteella. Automaattinen lataaminen pysäytetään jos tämä raja ylittyy.</string>
+ <string name="pref_theme_title_light">Vaalea</string>
+ <string name="pref_theme_title_dark">Tumma</string>
+ <string name="pref_theme_title_trueblack">Musta (AMOLED valmis)</string>
+ <string name="pref_episode_cache_unlimited">Ei rajoitettu</string>
+ <string name="pref_update_interval_hours_plural">tuntia</string>
+ <string name="pref_update_interval_hours_singular">tunti</string>
+ <string name="pref_update_interval_hours_manual">Manuaalinen</string>
+ <string name="pref_gpodnet_authenticate_title">Sisäänkirjautuminen</string>
+ <string name="pref_gpodnet_authenticate_sum">Kirjaudu gpodder.net tililläsi jotta voit synkronoida tilauksesi.</string>
+ <string name="pref_gpodnet_logout_title">Kirjaudu ulos</string>
+ <string name="pref_gpodnet_logout_toast">Uloskirjautuminen onnistui</string>
+ <string name="pref_gpodnet_setlogin_information_title">Vaihda kirjautumistietoja</string>
+ <string name="pref_gpodnet_setlogin_information_sum">Vaihda kirjautumistietoja gpodder.net tiliisi.</string>
+ <string name="pref_gpodnet_sync_changes_title">Synkronoi muutokset nyt</string>
+ <string name="pref_gpodnet_sync_changes_sum">Synkronoi tilaukset ja jaksojen tilojen muutokset gpodder.net.</string>
+ <string name="pref_gpodnet_full_sync_title">Täysi synkronointi nyt</string>
+ <string name="pref_gpodnet_full_sync_sum">Synkronoi kaikki tilaukset ja jaksojen tilastot gpodder.net</string>
+ <string name="pref_gpodnet_sync_sum_last_sync_line">Viimeisin synkronointiyritys: %1$s (%2$s)</string>
+ <string name="pref_gpodnet_sync_started">Synkronointi aloitettu</string>
+ <string name="pref_gpodnet_full_sync_started">Täysi synkronointi aloitettu</string>
+ <string name="pref_gpodnet_login_status"><![CDATA[Kirjauduttu <i>%1$s</i> laitteella <i>%2$s</i>]]></string>
+ <string name="pref_gpodnet_notifications_title">Näytä synkronointivirheet ilmoituksissa</string>
+ <string name="pref_gpodnet_notifications_sum">Tämä asetus ei vaikuta autentikointivirheisiin.</string>
+ <string name="pref_playback_speed_title">Soittonopeudet</string>
+ <string name="pref_playback_speed_sum">Kustomoi muuttuvia soittonopeuksia</string>
+ <string name="pref_playback_time_respects_speed_title">Mukauta mediatietoja soiton nopeuteen</string>
+ <string name="pref_playback_time_respects_speed_sum">Näytetty aika ja kesto mukautuvat soiton nopeuteen</string>
+ <string name="pref_fast_forward">Seuraava skippaa aikaa</string>
+ <string name="pref_fast_forward_sum">Kustomoi sekunnit jonka verran skipataaan kun painat Seuraava nappia.</string>
+ <string name="pref_rewind">Edellinen skippaa aikaa</string>
+ <string name="pref_rewind_sum">kustomoi sekunnit jonka verran hypätään takaisin kun painat Edellinen nappia.</string>
+ <string name="pref_gpodnet_sethostname_title">Aseta hostname</string>
+ <string name="pref_gpodnet_sethostname_use_default_host">Käytä oletusporttia</string>
+ <string name="pref_expandNotify_title">Korkea ilmoitusprioriteetti</string>
+ <string name="pref_expandNotify_sum">Tämä laajentaa ilmoituksen näyttämään soittonapit</string>
+ <string name="pref_persistNotify_title">Pysyvät soittokontrollit</string>
+ <string name="pref_persistNotify_sum">Säilytä ilmoitus ja lukituskuvan kontrollit kun soitto on pysäytetty.</string>
+ <string name="pref_compact_notification_buttons_title">Aseta lukituskuvan napit</string>
+ <string name="pref_compact_notification_buttons_sum">Vaihda lukituskuvan soittonapit. Soitto/Pause napit on aina mukana.</string>
+ <string name="pref_compact_notification_buttons_dialog_title">Valitse maksimi %1$d asioita</string>
+ <string name="pref_compact_notification_buttons_dialog_error">Voit valita vain maksimissaan %1$d asioita.</string>
+ <string name="pref_lockscreen_background_title">Aseta lukitusruudun taustakuva</string>
+ <string name="pref_lockscreen_background_sum">Aseta lukitusruudun taustakuva nykyisen jakson kuvaan. Tämä kuva näkyy kolmannen osapuolen sovelluksissa.</string>
+ <string name="pref_showDownloadReport_title">Näytä latausraportti</string>
+ <string name="pref_showDownloadReport_sum">Jos lataus epäonnistuu, generoi raportti joka näyttää virheen tiedot.</string>
+ <string name="pref_expand_notify_unsupport_toast">Android versiot ennen 4.1 eivät tue laajenettuja ilmoituksia.</string>
+ <string name="pref_queueAddToFront_sum">Lisää uusia jaksoja jonon eteen.</string>
+ <string name="pref_queueAddToFront_title">Lisää jonon eteen.</string>
+ <string name="pref_smart_mark_as_played_disabled">Poissa käytöstä</string>
+ <string name="pref_image_cache_size_title">Kuvan välimuistin koko</string>
+ <string name="pref_image_cache_size_sum">Tallennusmedian välimuistin koko kuville.</string>
+ <string name="crash_report_title">Kaatumisen raportti</string>
+ <string name="crash_report_sum">Lähetä uusin kaatumisraportti emaililla</string>
+ <string name="send_email">Lähteä email</string>
+ <string name="experimental_pref">Kokeellinen</string>
+ <string name="pref_media_player_message">Valitse mediasovellus jolla soitetaan tiedostot</string>
+ <string name="pref_current_value">Nykyinen arvo: %1$s</string>
+ <string name="pref_proxy_title">Proxy</string>
+ <string name="pref_proxy_sum">Aseta verkkoproxy</string>
+ <string name="pref_faq">FAQ</string>
+ <string name="pref_known_issues">Tunnetut ongelmat</string>
+ <string name="pref_no_browser_found">Selainta ei löydetty</string>
+ <string name="pref_cast_title">Chromecast-tuki</string>
+ <string name="pref_cast_message_play_flavor">Aseta ulkoisten mediaohjelmien soitto Cast laitteilla (kuten Chromecast, Audio Speakers tai Android TV)</string>
+ <string name="pref_cast_message_free_flavor">Chromecast tarvitsee kolmannen osapuolen suljettuja kirjastoja, jotka on poistettu tässä AntennaPodissa.</string>
+ <string name="pref_enqueue_downloaded_title">Lisää ladatut jonoon</string>
+ <string name="pref_enqueue_downloaded_summary">Lisää ladatut jaksot jonoon</string>
+ <string name="media_player_builtin">Sisäänrakennettu Android-soitto</string>
+ <string name="pref_skip_silence_title">Skippaa tyhjät kohdat audiossa</string>
+ <string name="pref_videoBehavior_title">Video sulkiessa</string>
+ <string name="pref_videoBehavior_sum">Kun suljetaan videon soitto</string>
+ <string name="stop_playback">Lopeta soitto</string>
+ <string name="continue_playback">Jatka audion soittoa</string>
+ <string name="behavior">Toiminta</string>
+ <string name="pref_back_button_behavior_title">Takaisin napin toiminta</string>
+ <string name="pref_back_button_behavior_sum">Vaihda Takaisin napin toiminta</string>
+ <string name="back_button_default">Oletus</string>
+ <string name="back_button_open_drawer">Avaa navigaatiohylly</string>
+ <string name="back_button_double_tap">Tuplanaputa sulkemiseen</string>
+ <string name="back_button_show_prompt">Varmista poistuminen</string>
+ <string name="close_prompt">Haluatko varmasti sulkea AntennaPodin?</string>
+ <string name="double_tap_toast">Napauta Takaisin nappia sulkemiseen</string>
+ <string name="back_button_go_to_page">Mene sivulle...</string>
+ <string name="back_button_go_to_page_title">Valitse sivu</string>
+ <string name="pref_delete_removes_from_queue_title">Deletointi poistaa jonosta</string>
+ <string name="pref_delete_removes_from_queue_sum">Poista jakso automaattisesti jonosta kun se deletoidaan.</string>
<!--Search-->
+ <string name="search_hint">Etsi jaksoja</string>
+ <string name="found_in_shownotes_label">Löydetty jaksomuistiosta</string>
+ <string name="found_in_chapters_label">Löydetty kappaleista</string>
+ <string name="found_in_authors_label">Löydetty tekijöistä</string>
+ <string name="found_in_feeds_label">Löydetty podcasteista</string>
+ <string name="search_status_no_results">Ei löydetty tuloksia</string>
+ <string name="search_label">Etsi</string>
+ <string name="found_in_title_label">Löydetty otsikoista</string>
+ <string name="no_results_for_query">Ei löydetty tuloksia \"%1$s\"</string>
<!--OPML import and export-->
+ <string name="opml_import_txtv_button_lable">OPML tiedostot mahdollistavat podcastien siirron podcasterista toiseen.</string>
+ <string name="opml_import_option">Valinta %1$d</string>
+ <string name="opml_import_explanation_1">Valitse täydellinen tiedostopolku tietojärjestelmästä</string>
+ <string name="opml_import_explanation_2">Käytä ulkopuolisia sovelluksia kuten Dropbox, Google Drive tai suosikki tiedostomanageria OPML tiedoston avaamiseen.</string>
+ <string name="opml_import_explanation_3">Monet sovellukset kuten Google Mail, Dropbox, Google Drive ja useimmat tiedostomanagerit <i>avaavat</i> OPML tiedostoja <i>kanssa</i> AntennaPodiin.</string>
+ <string name="start_import_label">Aloita tuonti</string>
+ <string name="opml_import_label">OPML tuonti</string>
+ <string name="opml_directory_error">VIRHE!</string>
+ <string name="reading_opml_label">Lukee OPML tiedostoa</string>
+ <string name="opml_reader_error">Virhe lukiessa OPML dokumenttia:</string>
+ <string name="opml_import_error_no_file">Ei tiedostoa valittuna!</string>
+ <string name="select_all_label">Valitse kaikki</string>
+ <string name="deselect_all_label">Poista valinta kaikista</string>
+ <string name="select_options_label">Valitse...</string>
+ <string name="choose_file_from_filesystem">Tiedostojärjestelmästä</string>
+ <string name="choose_file_from_external_application">Ulkoinen sovellus</string>
+ <string name="opml_export_label">OPML vienti</string>
+ <string name="html_export_label">HTML vienti</string>
+ <string name="exporting_label">Vienti...</string>
+ <string name="export_error_label">Vientivirhe</string>
+ <string name="export_success_title">Vienti onnistunut</string>
+ <string name="export_success_sum">Viety tiedosto on kirjoitettu:\n\n%1$s</string>
+ <string name="opml_import_ask_read_permission">Pääsy ulkoiseen solvellukseen tarvitaan OPML tiedoston lukemiseen</string>
<!--Sleep timer-->
+ <string name="set_sleeptimer_label">Aseta uniajastin</string>
+ <string name="disable_sleeptimer_label">Lopeta uniajastin</string>
+ <string name="enter_time_here_label">Aseta aika</string>
+ <string name="sleep_timer_label">Uniajastin</string>
+ <string name="time_left_label">Aikaa jäljellä:\u0020</string>
+ <string name="time_dialog_invalid_input">Väärä syöte. Ajan tulee olla numero</string>
+ <string name="timer_about_to_expire_label"><b>Kun ajastin on loppumassa:</b></string>
+ <string name="shake_to_reset_label">Ravista ajan resetointiin</string>
+ <string name="timer_vibration_label">Väristä</string>
+ <string name="time_seconds">sekuntia</string>
+ <string name="time_minutes">minuuttia</string>
+ <string name="time_hours">tuntia</string>
+ <plurals name="time_seconds_quantified">
+ <item quantity="one">1 sekunti</item>
+ <item quantity="other">%d sekuntia</item>
+ </plurals>
+ <plurals name="time_minutes_quantified">
+ <item quantity="one">1 minuutti</item>
+ <item quantity="other">%d minuuttia</item>
+ </plurals>
+ <plurals name="time_hours_quantified">
+ <item quantity="one">1 tunti</item>
+ <item quantity="other">%d tuntia</item>
+ </plurals>
+ <string name="auto_enable_label">Auto-asetus</string>
+ <string name="sleep_timer_enabled_label">Uniajastin asetettu</string>
+ <string name="sleep_timer_disabled_label">Uniajastin poistettu</string>
<!--gpodder.net-->
+ <string name="gpodnet_taglist_header">KATEGORIAT</string>
+ <string name="gpodnet_toplist_header">TOP PODCASTIT</string>
+ <string name="gpodnet_suggestions_header">EHDOTUKSET</string>
+ <string name="gpodnet_search_hint">Etsi gpodder.net</string>
+ <string name="gpodnetauth_login_title">Sisäänkirjautuminen</string>
+ <string name="gpodnetauth_login_descr">Tervetuloa gpodder.net sisäänkirjautumiseen. Kirjoita kirjautumistiedot:</string>
+ <string name="gpodnetauth_login_butLabel">Sisäänkirjautuminen</string>
+ <string name="gpodnetauth_login_register">Jos sinulla ei ole vielä tiliä, voit luoda sen täällä:\nhttps://gpodder.net/register/</string>
+ <string name="username_label">Käyttäjätunnus</string>
+ <string name="password_label">Salasana</string>
+ <string name="gpodnetauth_device_title">Laitevalinta</string>
+ <string name="gpodnetauth_device_descr">Luo uusi laite gpodder.net tiliin tai valitse olemassaoleva laite:</string>
+ <string name="gpodnetauth_device_deviceID">Laite ID:\u0020</string>
+ <string name="gpodnetauth_device_caption">Kuvaus</string>
+ <string name="gpodnetauth_device_butCreateNewDevice">Luo uusi laite</string>
+ <string name="gpodnetauth_device_chooseExistingDevice">Valitse olemassaoleva laite:</string>
+ <string name="gpodnetauth_device_errorEmpty">Laite ID ei saa olla tyhjä</string>
+ <string name="gpodnetauth_device_errorAlreadyUsed">Laite ID on jo käytössä</string>
+ <string name="gpodnetauth_device_caption_errorEmpty">Kuvaus ei saa olla tyhjä</string>
+ <string name="gpodnetauth_device_butChoose">Valitse</string>
+ <string name="gpodnetauth_finish_title">Sisäänkirjautuminen onnistui</string>
+ <string name="gpodnetauth_finish_descr">Onneksi olkoon! Sinun gpodder.net tili on liitetty laitteeseesi. AntennaPod alkaa automaattisesti synkronoimaan gpodder.net tiliisi.</string>
+ <string name="gpodnetauth_finish_butsyncnow">Aloita synkrointi nyt</string>
+ <string name="gpodnetauth_finish_butgomainscreen">Mene pääsivulle</string>
+ <string name="gpodnetsync_auth_error_title">gpodder.net autentikaatiovirhe</string>
+ <string name="gpodnetsync_auth_error_descr">Väärä tunnus tai salasana</string>
+ <string name="gpodnetsync_error_title">gpodder.net synkrointivirhe</string>
+ <string name="gpodnetsync_error_descr">Synkronointivirhe:\u0020</string>
+ <string name="gpodnetsync_pref_report_successful">Onnistui</string>
+ <string name="gpodnetsync_pref_report_failed">Epäonnistui</string>
+ <string name="gpodnetsync_username_characters_error">Käyttäjätunnukset saavat sisältää vain kirjaimia, numeroita, viivoja ja aliviivoja.</string>
<!--Directory chooser-->
+ <string name="selected_folder_label">Valittu hakemisto:</string>
+ <string name="create_folder_label">Luo hakemisto</string>
+ <string name="choose_data_directory">Valitse datahakemisto</string>
+ <string name="choose_data_directory_message">Valitse datahakemiston juuri. AntennaPod luo tarvittavat alihakemistot</string>
+ <string name="choose_data_directory_permission_rationale">Pääsy ulkoiseen solvellukseen tarvitaan datahakemiston muuttamiseen</string>
+ <string name="choose_data_directory_available_space">%1$s / %2$s vapaana</string>
+ <string name="create_folder_msg">Luo uusi hakemisto \"%1$s\"?</string>
+ <string name="create_folder_success">Luotiin uusi hakemisto</string>
+ <string name="create_folder_error_no_write_access">Ei voida kirjoittaa hakemistoon</string>
+ <string name="create_folder_error_already_exists">Hakemisto on jo olemassa</string>
+ <string name="create_folder_error">Ei voitu luoda hakemistoa</string>
+ <string name="folder_does_not_exist_error">\"%1$s\" ei ole olemassa</string>
+ <string name="folder_not_readable_error">\"%1$s\" ei voida lukea</string>
+ <string name="folder_not_writable_error">\"%1$s\" ei voida kirjoittaa</string>
+ <string name="folder_not_empty_dialog_title">Hakemisto ei ole tyhjä</string>
+ <string name="folder_not_empty_dialog_msg">Valittu hakemisto ei ole tyhjä. Medialataukset ja muut tiedostot tullaan kirjoittamaan suoraan tähän hakemistoon. Jatketaan?</string>
+ <string name="set_to_default_folder">Valitse oletushakemisto</string>
+ <string name="pref_pausePlaybackForFocusLoss_sum">Pysäytä soitto äänenvoimakkuuden hiljentämisen sijasta kun toinen sovellus haluaa soittaa ääniä.</string>
+ <string name="pref_pausePlaybackForFocusLoss_title">Pysäytä keskeytyksiin</string>
+ <string name="pref_resumeAfterCall_sum">Jatka soittoa kun puhelinkeskustelu päättyy</string>
+ <string name="pref_resumeAfterCall_title">Jatka puhelinsoiton jälkeen</string>
+ <string name="pref_restart_required">AntennaPod täytyy uudelleenkäynnistää tämän asetuksen voimaantuloon.</string>
<!--Online feed view-->
+ <string name="subscribe_label">Tilaa</string>
+ <string name="subscribed_label">Tilattu</string>
+ <string name="downloading_label">Lataa...</string>
<!--Content descriptions for image buttons-->
+ <string name="rewind_label">Kelaa takaisin</string>
+ <string name="fast_forward_label">Hyppää eteen</string>
+ <string name="media_type_audio_label">Audio</string>
+ <string name="media_type_video_label">Video</string>
+ <string name="navigate_upwards_label">Navigoi eteenpäoin</string>
+ <string name="status_downloading_label">Jaksoa ladataan</string>
+ <string name="in_queue_label">Jakso on jonossa</string>
+ <string name="drag_handle_content_description">Raahaa muuttaen tilaa</string>
+ <string name="load_next_page_label">Lataa seuraava sivu</string>
<!--Feed information screen-->
+ <string name="authentication_label">Autentikaatio</string>
+ <string name="authentication_descr">Vaihda käyttäjätunnut ja salasana tälle podcastille ja sen jaksoille.</string>
+ <string name="auto_download_settings_label">Automaattisen latauksen asetukset</string>
+ <string name="episode_filters_label">Jakson filtterit</string>
+ <string name="episode_filters_description">Lista termeistä joilla valitaan jakso automaattiseen lataukseen</string>
+ <string name="episode_filters_include">Sisällytä</string>
+ <string name="episode_filters_exclude">Poista</string>
+ <string name="episode_filters_hint">Yksittäiset sanat \n\"Monta sanaa\"</string>
+ <string name="keep_updated">Pidä päivitettynä</string>
+ <string name="keep_updated_summary">Tämä syöte mukaan kun (auto-) päivität kaikki syötteet</string>
+ <string name="auto_download_disabled_globally">Automaattinen lataaminen on pysäytetty AntennaPodin asetuksissa</string>
<!--Progress information-->
+ <string name="progress_upgrading_database">Päivitetään tietokantaa</string>
<!--AntennaPodSP-->
+ <string name="sp_apps_importing_feeds_msg">Tuodaan tilauksia sovelluksista</string>
+ <!--Add podcast fragment-->
+ <string name="search_podcast_hint">Etsi podcastia...</string>
+ <string name="search_itunes_label">Etsi iTunes:sta</string>
+ <string name="search_fyyd_label">Etsi fyyd:sta</string>
+ <string name="advanced_search">Mukautettu etsintä</string>
+ <string name="filter">Filteri</string>
<!--Episodes apply actions-->
+ <string name="all_label">Kaikki</string>
+ <string name="selected_all_label">Valitse kaikki jaksot</string>
+ <string name="none_label">Ei mitään</string>
+ <string name="deselected_all_label">Poista valinta kaikista</string>
+ <string name="played_label">Soitettu</string>
+ <string name="selected_played_label">Valitut soitetut jaksot</string>
+ <string name="unplayed_label">Soittamattomat</string>
+ <string name="selected_unplayed_label">Valitut soittamattomat jaksot</string>
+ <string name="downloaded_label">Ladattu</string>
+ <string name="selected_downloaded_label">Valittut ladatut jaksot</string>
+ <string name="not_downloaded_label">Ei ladattu</string>
+ <string name="selected_not_downloaded_label">Valitut ei ladatut jaksot</string>
+ <string name="queued_label">Jonossa</string>
+ <string name="selected_queued_label">Valitut jaksot jonossa</string>
+ <string name="not_queued_label">Ei jonossa</string>
+ <string name="selected_not_queued_label">Valitut jaksot ei jonossa</string>
+ <string name="has_media">On media</string>
+ <string name="selected_has_media_label">Valitut jaksot joissa media</string>
<!--Sort-->
+ <string name="sort_title_a_z">Otsikko (A \u2192 Z)</string>
+ <string name="sort_title_z_a">Otsikko (Z \u2192 A)</string>
+ <string name="sort_date_new_old">Aika (Uusi \u2192 Old)</string>
+ <string name="sort_date_old_new">Aika (Vanha \u2192 New)</string>
+ <string name="sort_duration_short_long">Kesto (Lyhyt \u2192 Long)</string>
+ <string name="sort_duration_long_short">Kesto (Pitkä \u2192 Short)</string>
<!--Rating dialog-->
+ <string name="rating_title">Tykkää AntennaPod?</string>
+ <string name="rating_message">Olisimme kiitollisia jos käytä aikaa AntennaPodin arvosteluun.</string>
+ <string name="rating_never_label">Jätä minut rauhaan</string>
+ <string name="rating_later_label">Muistuta minua myöhemmin</string>
+ <string name="rating_now_label">Miksei, tehdään tämä!</string>
<!--Audio controls-->
+ <string name="audio_controls">Audiokontrollit</string>
+ <string name="playback_speed">Soittonopeus</string>
+ <string name="volume">Äänenvoimakkuus</string>
+ <string name="left_short">V</string>
+ <string name="right_short">O</string>
+ <string name="audio_effects">Audioefektit</string>
+ <string name="stereo_to_mono">Downmix: Stereosta mono</string>
+ <string name="sonic_only">Vain Sonic</string>
+ <string name="exoplayer_only">Vain ExoPlayer</string>
<!--proxy settings-->
+ <string name="proxy_type_label">Tyyppi</string>
+ <string name="host_label">Host</string>
+ <string name="port_label">Portti</string>
+ <string name="optional_hint">(Valinnainen)</string>
+ <string name="proxy_test_label">Testi</string>
+ <string name="proxy_checking">Testaa...</string>
+ <string name="proxy_test_successful">Testi onnistui</string>
+ <string name="proxy_test_failed">Testi epäonnistui</string>
+ <string name="proxy_host_empty_error">Host ei voi olla tyhjä</string>
+ <string name="proxy_host_invalid_error">Host ei ole oikea IP osoite tai domain</string>
+ <string name="proxy_port_invalid_error">Portti ei ole oikein</string>
+ <!--Subscriptions fragment-->
+ <string name="subscription_num_columns">Sarakkeiden määrä</string>
<!--Database import/export-->
+ <string name="import_export">Tietokannan tuonti/vienti</string>
+ <string name="import_export_warning">Tämä kokeellinen toiminto voi siirtää tilauksesi ja soitetut jaksot toiseen laitteeseen.\n\nViedyt tietokannat voidaan tuoda ainoastaan samaan versioon AntennaPodista. Muuten toiminto voi johtaa odottamattoman käyttäytymiseen.\n\nTuonnin jälkeen jaksot saattavat näkyä ladattuna vaikka niitä ei ole ladattu. Paina soittonappia, jotta AntennaPod tunnistaa tämän.</string>
+ <string name="label_import">Tuonti</string>
+ <string name="label_export">Vienti</string>
+ <string name="import_select_file">Valitse tiedosto tuontiin</string>
+ <string name="export_ok">Vienti onnistui.</string>
+ <string name="import_ok">Tuonti onnistui.\n\nPaina OK uudelleenkäynnistääksesi AntennaPod</string>
<!--Casting-->
+ <string name="cast_media_route_menu_title">Soita...</string>
+ <string name="cast_disconnect_label">Irrota cast sessio</string>
+ <string name="cast_not_castable">Media ei voida toistaa cast laitteen kanssa</string>
+ <string name="cast_failed_to_play">Epäonnistui soittaa mediaa</string>
+ <string name="cast_failed_to_stop">Epäonnistui lopettaa soitto</string>
+ <string name="cast_failed_to_pause">Epäonnistui median pause</string>
<!--<string name="cast_failed_to_connect">Could not connect to the device</string>-->
+ <string name="cast_failed_setting_volume">Epäonnistui asettaa äänenvoimakkuus</string>
+ <string name="cast_failed_no_connection">Yhteyttä cast laitteeseen ei löydy</string>
+ <string name="cast_failed_no_connection_trans">Yhteys cast laitteeseen menetetty. Sovelllus yrittää muodostaa yhteyden, jos mahdollista. Odota muutama sekunti ja yritä uudelleen.</string>
+ <string name="cast_failed_perform_action">Epäonnistui suorittaa toiminto</string>
+ <string name="cast_failed_status_request">Epäonnistui synkronoida cast laitteeseen</string>
+ <string name="cast_failed_seek">Epäonnistui löytää uusi osoite cast laitteelta</string>
+ <string name="cast_failed_receiver_player_error">Vastaanotinlaiteessa on vakava virhe</string>
+ <string name="cast_failed_media_error_skipping">Virhe mediasoitossa. Skipataan...</string>
<!--Notification channels-->
+ <string name="notification_channel_user_action">Tarvitaan valinta</string>
+ <string name="notification_channel_user_action_description">Näytetään jos toiminta tarvitaan, esimerkiksi jos tarvitset uuden salasanan.</string>
+ <string name="notification_channel_downloading">Ladataan</string>
+ <string name="notification_channel_downloading_description">Näytetään kun ladataan.</string>
+ <string name="notification_channel_playing">Soittaa nyt</string>
+ <string name="notification_channel_playing_description">Sallii soiton kontrollit. Tämä on pääilmoitus, jonka näet kun podcast soitetaan.</string>
+ <string name="notification_channel_error">Virheet</string>
+ <string name="notification_channel_error_description">Näytetään kun jotain meni vikaan, esimerkiksi jos lataus tai gpodder synkronointi epäonnistui.</string>
+ <string name="import_bad_file">Rikkinäinen/Korruptoitunut tiedosto</string>
</resources>
diff --git a/core/src/main/res/values-fr/strings.xml b/core/src/main/res/values-fr/strings.xml
index 00ecc8ad3..d5225a656 100644
--- a/core/src/main/res/values-fr/strings.xml
+++ b/core/src/main/res/values-fr/strings.xml
@@ -6,7 +6,7 @@
<string name="statistics_label">Statistiques</string>
<string name="add_feed_label">Ajouter un podcast</string>
<string name="episodes_label">Episodes</string>
- <string name="all_episodes_short_label">Tout</string>
+ <string name="all_episodes_short_label">Tous</string>
<string name="new_episodes_label">Nouveaux</string>
<string name="favorite_episodes_label">Favoris</string>
<string name="new_label">Nouveau</string>
@@ -83,7 +83,7 @@
<string name="save_username_password_label">Sauvegarder votre identifiant et votre mot de passe</string>
<string name="close_label">Fermer</string>
<string name="retry_label">Réessayer</string>
- <string name="auto_download_label">Télécharger automatiquement à l\'avenir</string>
+ <string name="auto_download_label">Télécharger automatiquement</string>
<string name="auto_download_apply_to_items_title">Appliquer aux épisodes précédents</string>
<string name="auto_download_apply_to_items_message">Le nouveau paramètre <i>Téléchargement Automatique</i> sera automatiquement appliqué sur chaque nouvel épisode.\nVoulez-vous faire de même avec les épisodes précédents ?</string>
<string name="auto_delete_label">Suppression automatique de l\'épisode</string>
@@ -111,14 +111,16 @@
<string name="podcastdirectories_label">Trouver un podcast</string>
<string name="podcastdirectories_descr">Pour de nouveaux podcasts vous pouvez chercher iTunes ou fyyd ou parcourir gpodder.net par nom, catégorie ou popularité.</string>
<string name="browse_gpoddernet_label">Chercher sur gpodder.net</string>
+ <string name="discover">Découvrir</string>
+ <string name="discover_more">plus »</string>
<!--Actions on feeds-->
<string name="mark_all_read_label">Marquer tous les épisodes comme lus</string>
<string name="mark_all_read_msg">Tous les épisodes ont été marqués comme lus</string>
<string name="mark_all_read_confirmation_msg">Confirmer le marquage de tous les épisode comme lus</string>
<string name="mark_all_read_feed_confirmation_msg">Confirmer le marquage de tous les épisodes de ce podcast comme lus</string>
- <string name="remove_all_new_flags_label">Marquer tous les épisodes comme vus</string>
- <string name="removed_all_new_flags_msg">Tous les épisodes ont été marqués vus</string>
- <string name="remove_all_new_flags_confirmation_msg">Merci de confirmer que vous voulez marquer tous les épisodes comme vus.</string>
+ <string name="remove_all_new_flags_label">Ne plus rien considérer nouveau</string>
+ <string name="removed_all_new_flags_msg">Les statuts \"nouveau\" ont été supprimés</string>
+ <string name="remove_all_new_flags_confirmation_msg">Confirmer que vous ne voulez plus d\'épisodes apparaissant comme \"nouveau\".</string>
<string name="show_info_label">Voir les détails</string>
<string name="show_feed_settings_label">Paramètres du podcast...</string>
<string name="feed_info_label">Infos du podcast</string>
@@ -169,8 +171,8 @@
<item quantity="one">%d épisode supprimé.</item>
<item quantity="other">%d épisodes supprimés.</item>
</plurals>
- <string name="remove_new_flag_label">Marquer comme vu</string>
- <string name="removed_new_flag_label">Marqué comme vu</string>
+ <string name="remove_new_flag_label">Ne plus considérer nouveau</string>
+ <string name="removed_new_flag_label">Le statut \"nouveau\" a été supprimé</string>
<string name="mark_read_label">Marquer comme lu</string>
<string name="marked_as_read_label">Les épisodes ont été marqués comme lus</string>
<plurals name="marked_read_batch_label">
@@ -198,7 +200,6 @@
<string name="remove_from_favorite_label">Supprimer des Favoris</string>
<string name="removed_from_favorites">Supprimer des Favoris</string>
<string name="visit_website_label">Visiter le site</string>
- <string name="support_label">Flattr ça!</string>
<string name="skip_episode_label">Passer cet épisode</string>
<string name="activate_auto_download">Activer téléchargement automatique</string>
<string name="deactivate_auto_download">Désactiver téléchargement automatique</string>
@@ -250,6 +251,9 @@
<string name="confirm_mobile_download_dialog_title">Confirmer le téléchargement mobile</string>
<string name="confirm_mobile_download_dialog_message_not_in_queue">Le téléchargement avec la connexion mobile est désactivé dans les options.\n\nVous pouvez choisir d\'ajouter seulement l\'épisode à la liste de lecture ou vous pouvez autoriser temporairement le téléchargement.\n\n<small>Votre choix sera retenu pour les 10 prochaines minutes.</small></string>
<string name="confirm_mobile_download_dialog_message">Le téléchargement avec la connexion mobile est désactivé dans les options.\n\nVoulez-vous autoriser temporairement le téléchargement?\n\n<small>Votre choix sera retenu pour les 10 prochaines minutes.</small></string>
+ <string name="confirm_mobile_streaming_notification_title">Toucher pour autoriser le streaming avec la connexion mobile</string>
+ <string name="confirm_mobile_streaming_notification_message">Le streaming avec la connexion mobile est désactivé dans les paramètres. Toucher pour streamer quand même.</string>
+ <string name="confirm_mobile_streaming_button_always">Toujours autoriser</string>
<string name="confirm_mobile_download_dialog_only_add_to_queue">Rajouter à la liste de lecture</string>
<string name="confirm_mobile_download_dialog_enable_temporarily">Autoriser temporairement</string>
<!--Mediaplayer messages-->
@@ -259,6 +263,8 @@
<string name="player_ready_msg">Prêt</string>
<string name="player_seeking_msg">Recherche</string>
<string name="playback_error_server_died">Le serveur ne répond pas</string>
+ <string name="playback_error_unsupported">Format de média non géré</string>
+ <string name="playback_error_timeout">L\'opération a expiré</string>
<string name="playback_error_unknown">Erreur inconnue</string>
<string name="no_media_playing_label">Aucune lecture</string>
<string name="player_buffering_msg">Mise en mémoire</string>
@@ -276,6 +282,7 @@
<string name="move_to_top_label">Déplacer en haut de la liste</string>
<string name="move_to_bottom_label">Déplacer en bas de la liste</string>
<string name="sort">Trier</string>
+ <string name="keep_sorted">Conserver le tri</string>
<string name="date">Date</string>
<string name="duration">Durée</string>
<string name="episode_title">Titre de l\'épisode</string>
@@ -285,32 +292,8 @@
<string name="ascending">Ordre croissant</string>
<string name="descending">Ordre décroissant</string>
<string name="clear_queue_confirmation_msg">Veuillez confirmer que vous voulez bien supprimer TOUS les épisodes de la liste de lecture</string>
- <!--Flattr-->
- <string name="flattr_auth_label">Connecter à Flattr</string>
- <string name="flattr_auth_explanation">Appuyez sur le bouton ci-dessous pour vous authentifier. Voter navigateur va s\'ouvrir et vous serez envoyés vers l\'écran de connexion Flattr afin de donner à AntennaPod la permission de flattr. Une fois fait, vous reviendrez automatiquement à cet écran.</string>
- <string name="authenticate_label">S\'authentifier</string>
- <string name="return_home_label">Retourner à l\'écran d\'accueil</string>
- <string name="flattr_auth_success">L\'authentification a réussi. Vous pouvez maintenant flattr depuis cette application.</string>
- <string name="no_flattr_token_title">Aucun jeton Flattr trouvé.</string>
- <string name="no_flattr_token_notification_msg">Votre compte flattr ne semble pas être connecté à AntennaPod. Cliquer ici pour vous connecter.</string>
- <string name="no_flattr_token_msg">Votre compte Flattr se semble pas être connecté à AntennaPod. Vous pouvez soit connecter votre compte Flattr à AntennaPod pour pouvoir flattr depuis l\'application, ou vous pouvez aller sur le site de ce que vous voulez flattr.</string>
- <string name="authenticate_now_label">S\'authentifier</string>
- <string name="action_forbidden_title">Action interdite</string>
- <string name="action_forbidden_msg">AntennaPod n\'a pas la permission pour cette action. Il est possible que l\'accès à votre compte depuis AntennaPod ait été révoqué. Vous pouvez vous authentifier à nouveau, ou bien visiter le site à Flattrer directement.</string>
- <string name="access_revoked_title">Accès révoqué</string>
- <string name="access_revoked_info">Vous avez révoqué le jeton d\'accès d\'AntennaPod à votre compte. Pour terminer cette opération, vous devez retirer AntennaPod de la liste des applications autorisées sur le site web de Flattr.</string>
- <!--Flattr-->
- <string name="flattr_click_success">Une chose de Flattré !</string>
- <string name="flattr_click_success_count">%d choses de Flattré !</string>
- <string name="flattr_click_success_queue">Flattré : %s.</string>
- <string name="flattr_click_failure_count">Impossible de Flattrer %d choses !</string>
- <string name="flattr_click_failure">Non Flattré : %s.</string>
- <string name="flattr_click_enqueued">Cette chose sera Flattré plus tard</string>
- <string name="flattring_thing">En train de Flattrer %s</string>
- <string name="flattring_label">AntennaPod est en train de Flattrer</string>
- <string name="flattrd_label">AntennaPod a Flattré</string>
- <string name="flattrd_failed_label">Le Flattr d\'AntennaPod a échoué</string>
- <string name="flattr_retrieving_status">Obtention de la liste des choses Flattrées</string>
+ <string name="sort_old_to_new">Ancien à récent</string>
+ <string name="sort_new_to_old">Récent à ancien</string>
<!--Variable Speed-->
<string name="download_plugin_label">Télécharger une extension</string>
<string name="no_playback_plugin_title">Extension non installée</string>
@@ -321,7 +304,6 @@
<string name="no_items_header_label">Aucun épisode dans la liste de lecture</string>
<string name="no_items_label">Pour ajouter un épisode, téléchargez le ou faites une pression longue dessus et taper sur \"Ajouter à la liste de lecture\".</string>
<string name="no_feeds_label">Vous n\'êtes encore abonné à aucun podcast.</string>
- <string name="no_chapters_label">Cet épisode n\'a pas de chapitre.</string>
<string name="no_shownotes_label">Aucune notes pour cet épisode.</string>
<string name="no_run_downloads_head_label">Aucun téléchargement en cours</string>
<string name="no_run_downloads_label">Vous pouvez télécharger des épisodes à partir du détail d\'un podcast.</string>
@@ -337,6 +319,8 @@
<string name="no_new_episodes_label">Quand de nouveaux épisodes seront disponibles ils apparaîtront ici.</string>
<string name="no_fav_episodes_head_label">Aucun épisode favori</string>
<string name="no_fav_episodes_label">Vous pouvez marquer des épisodes comme favoris par une pression longue dessus.</string>
+ <string name="no_chapters_head_label">Pas de chapitres</string>
+ <string name="no_chapters_label">Cet épisode n\'a pas de chapitre.</string>
<!--Preferences-->
<string name="storage_pref">Stockage</string>
<string name="project_pref">Projet</string>
@@ -344,8 +328,6 @@
<string name="about_pref">À propos</string>
<string name="queue_label">Liste de lecture</string>
<string name="integrations_label">Intégrations</string>
- <string name="flattr_label">Flattr</string>
- <string name="flattr_summary">Service de micropaiement</string>
<string name="automation">Automatisation</string>
<string name="download_pref_details">Détails</string>
<string name="import_export_pref">Importation / Exportation</string>
@@ -353,7 +335,10 @@
<string name="appearance">Apparence</string>
<string name="external_elements">Eléments externes</string>
<string name="interruptions">Interruptions</string>
- <string name="buttons">Boutons de lecture</string>
+ <string name="playback_control">Contrôle de lecture</string>
+ <string name="preference_search_hint">Chercher...</string>
+ <string name="preference_search_no_results">Aucun résultat</string>
+ <string name="preference_search_clear_history">Effacer l\'historique</string>
<string name="media_player">Lecteur multimédia</string>
<string name="pref_episode_cleanup_title">Nettoyage des épisodes</string>
<string name="pref_episode_cleanup_summary">Les épisodes qui ne sont pas dans la liste de lecture et qui ne sont pas marqués comme favoris peuvent être supprimés si l\'espace est insuffisant pour le téléchargement automatique de nouveaux épisodes</string>
@@ -389,21 +374,14 @@
<string name="pref_pauseOnHeadsetDisconnect_title">Déconnexion des écouteurs ou du Bluetooth</string>
<string name="pref_unpauseOnHeadsetReconnect_title">Connexion des écouteurs</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Connexion du Bluetooth</string>
- <string name="pref_mobileUpdate_title">Mises à jour mobile</string>
- <string name="pref_mobileUpdate_sum">Autoriser les mises à jour avec la connexion mobile</string>
- <string name="pref_mobileUpdate_nothing">Rien</string>
- <string name="pref_mobileUpdate_images">Seulement les images</string>
- <string name="pref_mobileUpdate_everything">Tout</string>
+ <string name="pref_mobileUpdate_title">Utilisation de la connexion mobile</string>
+ <string name="pref_mobileUpdate_sum">Choisir ce qui est autorisé lorsque la connexion mobile est utilisée</string>
+ <string name="pref_mobileUpdate_refresh">Rafraîchissement des flux</string>
+ <string name="pref_mobileUpdate_images">Récupération des images</string>
+ <string name="pref_mobileUpdate_auto_download">Téléchargement automatique</string>
+ <string name="pref_mobileUpdate_episode_download">Téléchargement d\'épisodes</string>
+ <string name="pref_mobileUpdate_streaming">Streaming</string>
<string name="refreshing_label">Mise à jour en cours</string>
- <string name="flattr_settings_label">Paramètres Flattr</string>
- <string name="pref_flattr_auth_title">Connexion à Flattr</string>
- <string name="pref_flattr_auth_sum">Connectez-vous à votre compte Flattr pour pouvoir flattr directement depuis l\'application.</string>
- <string name="pref_flattr_this_app_title">Flattr cette application</string>
- <string name="pref_flattr_this_app_sum">Encouragez le développement d\'AntennaPod grâce à Flattr. Merci !</string>
- <string name="pref_revokeAccess_title">Révoquer l\'accès</string>
- <string name="pref_revokeAccess_sum">Révoquer la permission d\'accès à votre compte Flattr depuis cette application.</string>
- <string name="pref_auto_flattr_title">Flattr automatique</string>
- <string name="pref_auto_flattr_sum">Configurer les paiements flattr automatiques</string>
<string name="user_interface_label">Interface utilisateur</string>
<string name="pref_set_theme_title">Choisir un thème</string>
<string name="pref_nav_drawer_title">Personnaliser le volet de navigation</string>
@@ -424,7 +402,8 @@
<string name="pref_automatic_download_on_battery_title">Télécharger lorsque l\'appareil n\'est pas en charge</string>
<string name="pref_automatic_download_on_battery_sum">Autoriser le téléchargement automatique quand l\'appareil n\'est pas en train de charger</string>
<string name="pref_parallel_downloads_title">Téléchargements simultanés</string>
- <string name="pref_episode_cache_title">Épisodes stockés localement</string>
+ <string name="pref_episode_cache_title">Nombre d\'épisodes stockés</string>
+ <string name="pref_episode_cache_summary">Nombre maximum d\'épisodes stockés sur l\'appareil. Le téléchargement automatique sera suspendu si ce nombre est atteint.</string>
<string name="pref_theme_title_light">Clair</string>
<string name="pref_theme_title_dark">Sombre</string>
<string name="pref_theme_title_trueblack">Noir (pour écran AMOLED)</string>
@@ -450,6 +429,8 @@
<string name="pref_gpodnet_notifications_sum">Ce paramètre ne s\'applique pas aux erreurs d\'authentification.</string>
<string name="pref_playback_speed_title">Vitesses de lecture</string>
<string name="pref_playback_speed_sum">Définir les vitesses disponibles lors de la lecture audio</string>
+ <string name="pref_playback_time_respects_speed_title">Ajuster les informations en fonction la vitesse de lecture</string>
+ <string name="pref_playback_time_respects_speed_sum">La position et la durée affichée tiendront compte de la vitesse de lecture.</string>
<string name="pref_fast_forward">Durée du saut avant</string>
<string name="pref_fast_forward_sum">Nombre de secondes à sauter quand le bouton \"saut avant\" est pressé</string>
<string name="pref_rewind">Durée du saut arrière</string>
@@ -509,11 +490,6 @@
<string name="back_button_go_to_page_title">Sélectionner une page</string>
<string name="pref_delete_removes_from_queue_title">Supprimer retire de la liste de lecture</string>
<string name="pref_delete_removes_from_queue_sum">Retirer de la liste de lecture les épisodes quand ils sont supprimés.</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">Activer le paiement flattr automatique</string>
- <string name="auto_flattr_after_percent">Lancer un paiement flattr quand %d pourcent de l\'épisode a été lu</string>
- <string name="auto_flattr_ater_beginning">Lancer le paiement flattr d\'un épisode dès que la lecture commence</string>
- <string name="auto_flattr_ater_end">Lancer le paiement flattr d\'un épisode à la fin de la lecture</string>
<!--Search-->
<string name="search_hint">Chercher les épisodes</string>
<string name="found_in_shownotes_label">Trouvé dans les notes d\'épisodes</string>
@@ -580,7 +556,7 @@
<string name="gpodnet_taglist_header">CATEGORIES</string>
<string name="gpodnet_toplist_header">PODCASTS POPULAIRES</string>
<string name="gpodnet_suggestions_header">SUGGESTIONS</string>
- <string name="gpodnet_search_hint">Chercher gpodder.net</string>
+ <string name="gpodnet_search_hint">Chercher sur gpodder.net</string>
<string name="gpodnetauth_login_title">Se connecter</string>
<string name="gpodnetauth_login_descr">Bienvenue dans le processus de connexion à gpodder.net. Premièrement, veuillez entrer vos informations de connexion :</string>
<string name="gpodnetauth_login_butLabel">Connexion</string>
@@ -607,12 +583,14 @@
<string name="gpodnetsync_error_descr">Une erreur est apparue lors de la synchronisation :\u0020</string>
<string name="gpodnetsync_pref_report_successful">Réussie</string>
<string name="gpodnetsync_pref_report_failed">Échoué</string>
+ <string name="gpodnetsync_username_characters_error">Le nom d\'utilisateur ne peut contenir que des lettres, des chiffres, des traits d\'union ou des tirets bas.</string>
<!--Directory chooser-->
<string name="selected_folder_label">Répertoire choisi :</string>
<string name="create_folder_label">Créer répertoire</string>
<string name="choose_data_directory">Choisir le répertoire</string>
<string name="choose_data_directory_message">Choisissez le répertoire où enregistrer les données. AntennaPod créera automatiquement les sous-répertoires nécessaires.</string>
<string name="choose_data_directory_permission_rationale">L\'accès au stockage externe est requis pour changer le répertoire des données</string>
+ <string name="choose_data_directory_available_space">%1$s sur %2$s d\'espace libre</string>
<string name="create_folder_msg">Créer un répertoire nommé \"%1$s\" ?</string>
<string name="create_folder_success">Répertoire créé</string>
<string name="create_folder_error_no_write_access">Impossible d\'écrire dans ce répertoire</string>
@@ -624,7 +602,7 @@
<string name="folder_not_empty_dialog_title">Le répertoire n\'est pas vide</string>
<string name="folder_not_empty_dialog_msg">Le répertoire que vous avez choisi n\'est pas vide. Les fichiers téléchargés seront ajoutés à ce répertoire. Continuer malgré tout ?</string>
<string name="set_to_default_folder">Choisir le répertoire par défaut</string>
- <string name="pref_pausePlaybackForFocusLoss_sum">Pauser la lecture au lieu de baisser le volume quand une autre application joue un son</string>
+ <string name="pref_pausePlaybackForFocusLoss_sum">Mettre en pause la lecture au lieu de baisser le volume quand une autre application joue un son</string>
<string name="pref_pausePlaybackForFocusLoss_title">Mettre en pause lors d\'interruptions</string>
<string name="pref_resumeAfterCall_sum">Reprendre la lecture après un appel téléphonique</string>
<string name="pref_resumeAfterCall_title">Reprendre après appel</string>
@@ -653,13 +631,18 @@
<string name="episode_filters_exclude">Exclure</string>
<string name="episode_filters_hint">Mots uniques \n\"Liste de mots\"</string>
<string name="keep_updated">Maintenir à jour</string>
+ <string name="keep_updated_summary">Inclure ce flux lors de la mise à jour des flux</string>
+ <string name="auto_download_disabled_globally">Le téléchargement automatique n\'est pas activé dans les préférences</string>
<!--Progress information-->
<string name="progress_upgrading_database">Mise à jour de la base de données</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Importation des abonnements à partir d\'applications à usage unique...</string>
+ <!--Add podcast fragment-->
+ <string name="search_podcast_hint">Trouver un podcast...</string>
<string name="search_itunes_label">Chercher sur iTunes</string>
- <string name="filter">Filtrer</string>
<string name="search_fyyd_label">Chercher sur fyyd</string>
+ <string name="advanced_search">Recherche avancée</string>
+ <string name="filter">Filtrer</string>
<!--Episodes apply actions-->
<string name="all_label">Tous</string>
<string name="selected_all_label">Tous les épisodes ont été sélectionné</string>
@@ -675,15 +658,15 @@
<string name="selected_not_downloaded_label">Épisodes non téléchargés sélectionnés</string>
<string name="queued_label">Dans la liste de lecture</string>
<string name="selected_queued_label">Episodes présents dans la liste de lecture sélectionnés</string>
- <string name="not_queued_label">En dehors de la liste de lecture</string>
+ <string name="not_queued_label">Pas dans la liste de lecture</string>
<string name="selected_not_queued_label">Episodes absents de la liste de lecture sélectionnés</string>
- <string name="has_media">A des médias</string>
+ <string name="has_media">Avec média</string>
<string name="selected_has_media_label">Sélectionner les épisodes avec des médias</string>
<!--Sort-->
<string name="sort_title_a_z">Titre (A \u2192 Z)</string>
<string name="sort_title_z_a">Titre (Z \u2192 A)</string>
- <string name="sort_date_new_old">Date (Nouveau \u2192 Ancien)</string>
- <string name="sort_date_old_new">Date (Ancien \u2192 Nouveau)</string>
+ <string name="sort_date_new_old">Date (Récent \u2192 Ancien)</string>
+ <string name="sort_date_old_new">Date (Ancien \u2192 Récent)</string>
<string name="sort_duration_short_long">Durée (Courte \u2192 Longue)</string>
<string name="sort_duration_long_short">Durée (Longue \u2192 Courte)</string>
<!--Rating dialog-->
@@ -749,4 +732,5 @@
<string name="notification_channel_playing_description">Permet de contrôler la lecture. C\'est la notification principale pendant la lecture d\'un podcast.</string>
<string name="notification_channel_error">Erreurs</string>
<string name="notification_channel_error_description">S\'affiche en cas de problème. Par exemple, un téléchargement ou une synchronisation qui échoue.</string>
+ <string name="import_bad_file">Fichier invalide/corrompu</string>
</resources>
diff --git a/core/src/main/res/values-gl-rES/strings.xml b/core/src/main/res/values-gl-rES/strings.xml
index 9897ec272..d3050075e 100644
--- a/core/src/main/res/values-gl-rES/strings.xml
+++ b/core/src/main/res/values-gl-rES/strings.xml
@@ -12,7 +12,7 @@
<string name="new_label">Novo</string>
<string name="settings_label">Axustes</string>
<string name="downloads_label">Descargas</string>
- <string name="downloads_running_label">Funcionando</string>
+ <string name="downloads_running_label">Activas</string>
<string name="downloads_completed_label">Completado</string>
<string name="downloads_log_label">Rexistro</string>
<string name="subscriptions_label">Subscricións</string>
@@ -111,14 +111,16 @@
<string name="podcastdirectories_label">Buscar Podcast nun directorio</string>
<string name="podcastdirectories_descr">Para novos podcasts, pode buscar en iTunes ou fyyd, ou tamén en gpodder.net por nome, categoría ou popularidade.</string>
<string name="browse_gpoddernet_label">Buscar en gpodder.net</string>
+ <string name="discover">Descubrir</string>
+ <string name="discover_more">máis »</string>
<!--Actions on feeds-->
<string name="mark_all_read_label">Marcar todo como reproducido</string>
<string name="mark_all_read_msg">Marcáronse todos como reproducidos</string>
<string name="mark_all_read_confirmation_msg">Por favor confirme que quere marcar todos os episodios como reproducidos.</string>
<string name="mark_all_read_feed_confirmation_msg">Por favor, confirme que quere marcar todos os episodios deste podcast como reproducidos.</string>
- <string name="remove_all_new_flags_label">Marcar como visto</string>
- <string name="removed_all_new_flags_msg">Marcáronse todos os episodios como vistos</string>
- <string name="remove_all_new_flags_confirmation_msg">Por favor confirme que quere marcar todos os episodios como vistos.</string>
+ <string name="remove_all_new_flags_label">Eliminar todas as \"novas\" marcas</string>
+ <string name="removed_all_new_flags_msg">Eliminou todas as \"novas\" marcas</string>
+ <string name="remove_all_new_flags_confirmation_msg">Por favor, confirme que quere eliminar a marca de \"novo\" de todos os episodios.</string>
<string name="show_info_label">Mostrar información</string>
<string name="show_feed_settings_label">Mostrar axustes do podcast</string>
<string name="feed_info_label">Información do podcast</string>
@@ -169,8 +171,8 @@
<item quantity="one">%d episodio eliminado.</item>
<item quantity="other">%d episodios eliminados.</item>
</plurals>
- <string name="remove_new_flag_label">Marcar como visto</string>
- <string name="removed_new_flag_label">Marcar como visto</string>
+ <string name="remove_new_flag_label">Quitar marca \"novo\"</string>
+ <string name="removed_new_flag_label">Eliminouse marca \"novo\"</string>
<string name="mark_read_label">Marcar como reproducido</string>
<string name="marked_as_read_label">Marcado como reproducido</string>
<plurals name="marked_read_batch_label">
@@ -198,7 +200,6 @@
<string name="remove_from_favorite_label">Quitar dos favoritos</string>
<string name="removed_from_favorites">Eliminado dos favoritos</string>
<string name="visit_website_label">Visitar sitio web</string>
- <string name="support_label">Publicar en Flattr</string>
<string name="skip_episode_label">Saltar episodio</string>
<string name="activate_auto_download">Activar a descarga automática</string>
<string name="deactivate_auto_download">Desactivar a descarga automática</string>
@@ -250,6 +251,9 @@
<string name="confirm_mobile_download_dialog_title">Confirme a descarga con datos do móbil</string>
<string name="confirm_mobile_download_dialog_message_not_in_queue">Descargar coa conexión de datos do móbil está desactivada nos axustes.\n\nPode escoller ben só engadir o episodio a cola ou pode permitir a descarga temporalmente.\n\n<small> A súa elección lembrarase durante 10 minutos.</small></string>
<string name="confirm_mobile_download_dialog_message">A descarga con datos móbiles está desactivada nos axustes.\n\nQuere permitir a descarga temporalmente?\n\n <small>A súa decisión lembrarase durante 10 minutos.</small></string>
+ <string name="confirm_mobile_streaming_notification_title">Confirmar retransmisión Móbil</string>
+ <string name="confirm_mobile_streaming_notification_message">Desactivouse nos axustes Retransmitir mediante a conexión de datos. Toque para retransmitir igualmente.</string>
+ <string name="confirm_mobile_streaming_button_always">Permitir sempre</string>
<string name="confirm_mobile_download_dialog_only_add_to_queue">Engadir a cola</string>
<string name="confirm_mobile_download_dialog_enable_temporarily">Permitir temporalmente</string>
<!--Mediaplayer messages-->
@@ -259,6 +263,8 @@
<string name="player_ready_msg">Listo</string>
<string name="player_seeking_msg">Buscando</string>
<string name="playback_error_server_died">Servidor desconectado</string>
+ <string name="playback_error_unsupported">Tipo de ficheiro non soportado</string>
+ <string name="playback_error_timeout">A operación caducou</string>
<string name="playback_error_unknown">Fallo descoñecido</string>
<string name="no_media_playing_label">Non reproducindo</string>
<string name="player_buffering_msg">Almacenando</string>
@@ -276,6 +282,7 @@
<string name="move_to_top_label">Mover arriba</string>
<string name="move_to_bottom_label">Mover abaixo</string>
<string name="sort">Ordenar</string>
+ <string name="keep_sorted">Manter ordenado</string>
<string name="date">Data</string>
<string name="duration">Duración</string>
<string name="episode_title">Título do episodio</string>
@@ -285,32 +292,8 @@
<string name="ascending">Ascendente</string>
<string name="descending">Descendente</string>
<string name="clear_queue_confirmation_msg">Por favor confirme que quere limpar a cola e TODOS os episodios nela</string>
- <!--Flattr-->
- <string name="flattr_auth_label">conectar Flattr</string>
- <string name="flattr_auth_explanation">Pulse o botón inferior para iniciar o proceso de autenticación. Será redireccionado a pantalla de conexión en Flattr no seu navegador e pediralle permiso para que AntennaPod poida acceder. Despois de dar permiso, voltará a esta pantalla de xeito automático.</string>
- <string name="authenticate_label">Autenticar</string>
- <string name="return_home_label">Voltar ao inicio</string>
- <string name="flattr_auth_success">Autenticouse correctamente! Xa pode enviar valoracións a Flattr desde a aplicación.</string>
- <string name="no_flattr_token_title">Non se atopou o testemuño de Flattr</string>
- <string name="no_flattr_token_notification_msg">A súa conta de Flattr non semella estar conectada a AntennaPod. Toque aquí para autenticarse.</string>
- <string name="no_flattr_token_msg">A súa conta de Flattr non semella estar conectada a AntennaPod. Ben pode conectar a súa conta a AntennaPod para interactuar en Flattr desde a aplicación ou ben pode visitar o sitio web do elemento e darlle ao flattr desde alí.</string>
- <string name="authenticate_now_label">Autenticar</string>
- <string name="action_forbidden_title">Acción non permitida</string>
- <string name="action_forbidden_msg">AntennaPod non ten permiso para esta acción. A razón podería ser que o testemuño de acceso de AntennaPod ou a súa conta fosen rexeitados. Pode voltar a autenticarse ou visitar o sitio web do elemento.</string>
- <string name="access_revoked_title">Acceso rexeitado</string>
- <string name="access_revoked_info">Eliminou correctamente o token de acceso de AntennaPod á súa conta. Para completar o proceso deberá eliminar esta aplicación da lista de aplicacións autorizadas nos axustes da súa conta na web de Flattr.</string>
- <!--Flattr-->
- <string name="flattr_click_success">Flateraches algo!</string>
- <string name="flattr_click_success_count">Flateraches %d cousas!</string>
- <string name="flattr_click_success_queue">Flattr\'ed: %s.</string>
- <string name="flattr_click_failure_count">Failed to flattr %d things!</string>
- <string name="flattr_click_failure">Not flattr\'ed: %s.</string>
- <string name="flattr_click_enqueued">A cousa esta será flaterada máis tarde</string>
- <string name="flattring_thing">Flattring %s</string>
- <string name="flattring_label">AntennaPod está enviando a Flattr</string>
- <string name="flattrd_label">AntennaPod enviou a Flattr</string>
- <string name="flattrd_failed_label">Fallou o envío a Flattr</string>
- <string name="flattr_retrieving_status">Obtendo cousas de Flattr</string>
+ <string name="sort_old_to_new">Antigo a novo</string>
+ <string name="sort_new_to_old">Novo a antigo</string>
<!--Variable Speed-->
<string name="download_plugin_label">Descargar engadido</string>
<string name="no_playback_plugin_title">Engadido non instalado</string>
@@ -321,7 +304,6 @@
<string name="no_items_header_label">Sen episodios na cola</string>
<string name="no_items_label">Engada un episodio descargándoo, ou manteña preso un episodio e escolla \"Engadir a cola\".</string>
<string name="no_feeds_label">Aínda non está subscrito a ningún podcast.</string>
- <string name="no_chapters_label">Este episodio non ten capítulos.</string>
<string name="no_shownotes_label">Este episodio non ten notas de episodio.</string>
<string name="no_run_downloads_head_label">Sen descargas activas</string>
<string name="no_run_downloads_label">Pode descargar episodios na pantalla con detalles do episodio.</string>
@@ -337,6 +319,8 @@
<string name="no_new_episodes_label">Cando reciba novos episodios, mostraranse aquí.</string>
<string name="no_fav_episodes_head_label">Sen episodios favoritos</string>
<string name="no_fav_episodes_label">Pode engadir episodios aos favoritos manténdoos pulsados.</string>
+ <string name="no_chapters_head_label">Sen capítulos</string>
+ <string name="no_chapters_label">Este episodio non ten capítulos.</string>
<!--Preferences-->
<string name="storage_pref">Almacenamento</string>
<string name="project_pref">Proxecto</string>
@@ -344,8 +328,6 @@
<string name="about_pref">Sobre</string>
<string name="queue_label">Cola</string>
<string name="integrations_label">Integracións</string>
- <string name="flattr_label">Flattr</string>
- <string name="flattr_summary">Servizo de micropagamentos</string>
<string name="automation">Automatizado</string>
<string name="download_pref_details">Detalles</string>
<string name="import_export_pref">Importar/Exportar</string>
@@ -353,7 +335,10 @@
<string name="appearance">Aspecto</string>
<string name="external_elements">Elementos externos</string>
<string name="interruptions">Interrupcións</string>
- <string name="buttons">Botóns do control de reprodución</string>
+ <string name="playback_control">Control de reprodución</string>
+ <string name="preference_search_hint">Busca....</string>
+ <string name="preference_search_no_results">Sen resultados</string>
+ <string name="preference_search_clear_history">Limpar historial</string>
<string name="media_player">Reprodutor de medios</string>
<string name="pref_episode_cleanup_title">Limpeza de episodios</string>
<string name="pref_episode_cleanup_summary">Os episodios que non están na cola e tampouco son favoritos deberían poder ser candidatos a ser eliminados si a función Descarga Automática precisa espazo para novos episodios.</string>
@@ -390,20 +375,13 @@
<string name="pref_unpauseOnHeadsetReconnect_title">Reconexión de auriculares</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Reconexión bluetooth</string>
<string name="pref_mobileUpdate_title">Actualizacións Móbil</string>
- <string name="pref_mobileUpdate_sum">Permitir actualizacións sobre a rede de datos do móbil</string>
- <string name="pref_mobileUpdate_nothing">Nada</string>
- <string name="pref_mobileUpdate_images">Só imaxes</string>
- <string name="pref_mobileUpdate_everything">Todo</string>
+ <string name="pref_mobileUpdate_sum">Escolla o que estará permitido utilizando conexión de datos do móbil</string>
+ <string name="pref_mobileUpdate_refresh">Actualizar fontes</string>
+ <string name="pref_mobileUpdate_images">Imaxes de portadas</string>
+ <string name="pref_mobileUpdate_auto_download">Descarga automática</string>
+ <string name="pref_mobileUpdate_episode_download">Descarga de episodio</string>
+ <string name="pref_mobileUpdate_streaming">Retransmisión</string>
<string name="refreshing_label">Actualizando</string>
- <string name="flattr_settings_label">Axustes Flattr</string>
- <string name="pref_flattr_auth_title">Conexión Flattr</string>
- <string name="pref_flattr_auth_sum">Conéctese a súa conta Flattr para interactuar desde a aplicación..</string>
- <string name="pref_flattr_this_app_title">Flattr esta App</string>
- <string name="pref_flattr_this_app_sum">Axude ao desenvolvemento de AntennaPod comentandoo en Flattr. Grazas!</string>
- <string name="pref_revokeAccess_title">Retirar acceso</string>
- <string name="pref_revokeAccess_sum">Retirar o permiso de acceso a súa conta Flattr en esta aplicación..</string>
- <string name="pref_auto_flattr_title">Flattr automático</string>
- <string name="pref_auto_flattr_sum">Configure o flattr automático</string>
<string name="user_interface_label">Interface de usuaria</string>
<string name="pref_set_theme_title">Escolla o decorado</string>
<string name="pref_nav_drawer_title">Personalice a Caixa de navegación</string>
@@ -425,6 +403,7 @@
<string name="pref_automatic_download_on_battery_sum">Permitir a descarga automática cando a batería non está a cargar</string>
<string name="pref_parallel_downloads_title">Descargas simultáneas</string>
<string name="pref_episode_cache_title">Caché de episodios</string>
+ <string name="pref_episode_cache_summary">O número total de episodios descargados na caché do dispositivo. A descarga automática suspenderase se se alcanza este número.</string>
<string name="pref_theme_title_light">Claro</string>
<string name="pref_theme_title_dark">Oscuro</string>
<string name="pref_theme_title_trueblack">Negro (listo para AMOLED)</string>
@@ -450,6 +429,8 @@
<string name="pref_gpodnet_notifications_sum">Esta preferencia non se aplica a fallos na autenticación.</string>
<string name="pref_playback_speed_title">Velocidades de reprodución</string>
<string name="pref_playback_speed_sum">Personalice a velocidade variable de reprodución de audio</string>
+ <string name="pref_playback_time_respects_speed_title">Axustar info dos medios a velocidade de reprodución</string>
+ <string name="pref_playback_time_respects_speed_sum">A posición mostrada e a duración están adaptadas a velocidade de reprodución</string>
<string name="pref_fast_forward">Avance rápido Salta tempo</string>
<string name="pref_fast_forward_sum">Personalice o número de segundos a avanzar cando o se pulsa o botón de avance rápido</string>
<string name="pref_rewind">Retroceso Salta tempo</string>
@@ -509,11 +490,6 @@
<string name="back_button_go_to_page_title">Seleccionar páxina</string>
<string name="pref_delete_removes_from_queue_title">Eliminar quita da Cola</string>
<string name="pref_delete_removes_from_queue_sum">Eliminar automáticamente un episodio da cola cando se elimina.</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">Hablitar o flattring automático</string>
- <string name="auto_flattr_after_percent">Flattr o episodio tan pronto como o %d por cento foi reproducido</string>
- <string name="auto_flattr_ater_beginning">Flattr o episodio cando se inicia a reprodución</string>
- <string name="auto_flattr_ater_end">Flattr o episodio cando remata a reprodución</string>
<!--Search-->
<string name="search_hint">Buscar episodios</string>
<string name="found_in_shownotes_label">Atopado nas notas do episodio</string>
@@ -607,12 +583,14 @@
<string name="gpodnetsync_error_descr">Houbo un fallo durante a sincronización:\u0020</string>
<string name="gpodnetsync_pref_report_successful">Con éxito</string>
<string name="gpodnetsync_pref_report_failed">Fallou</string>
+ <string name="gpodnetsync_username_characters_error">Os nomes de usuario só conteñen letras, números e guións medio e baixo.</string>
<!--Directory chooser-->
<string name="selected_folder_label">Cartafol escollido:</string>
<string name="create_folder_label">Crear cartafol</string>
<string name="choose_data_directory">Escoller cartafol de datos</string>
<string name="choose_data_directory_message">Por favor escolla a base do cartafol dos seus datos. AntennaPod creará os subcartafoles axeitados.</string>
<string name="choose_data_directory_permission_rationale">Precísase o acceso ao almacenamento externo para mudar o cartafol de datos</string>
+ <string name="choose_data_directory_available_space">%1$s de %2$s libre</string>
<string name="create_folder_msg">Crear un novo cartafol de nome \"%1$s\"?</string>
<string name="create_folder_success">Novo cartafol creado</string>
<string name="create_folder_error_no_write_access">Non se pode escribir en este cartafol</string>
@@ -653,13 +631,18 @@
<string name="episode_filters_exclude">Excluír</string>
<string name="episode_filters_hint">Palabras simples \n\"Varias palabras\"</string>
<string name="keep_updated">Manter actualizado</string>
+ <string name="keep_updated_summary">Incluír esta fonte ao (auto-)actualizar as fontes</string>
+ <string name="auto_download_disabled_globally">A descarga automática está desactivada nos axustes principais de AntennaPod</string>
<!--Progress information-->
<string name="progress_upgrading_database">Actualizando a base de datos</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Importando as subscricións desde aplicacións de propósito único...</string>
+ <!--Add podcast fragment-->
+ <string name="search_podcast_hint">Buscar podcast...</string>
<string name="search_itunes_label">Buscar en iTunes</string>
- <string name="filter">Filtrado</string>
<string name="search_fyyd_label">Buscar en fyyd</string>
+ <string name="advanced_search">Busca avanzada</string>
+ <string name="filter">Filtrado</string>
<!--Episodes apply actions-->
<string name="all_label">Todo</string>
<string name="selected_all_label">Seleccionar todos os episodios</string>
@@ -749,4 +732,5 @@
<string name="notification_channel_playing_description">Permite controlar a reprodución. Esta é a notificación principal que verá mentras reproduce un podcast.</string>
<string name="notification_channel_error">Fallos</string>
<string name="notification_channel_error_description">Mostrado si algo falla, por exemplo si a descarga ou a sincronización con gpodder fallan.</string>
+ <string name="import_bad_file">Ficheiro non válido/corrupto</string>
</resources>
diff --git a/core/src/main/res/values-hi-rIN/strings.xml b/core/src/main/res/values-hi-rIN/strings.xml
index 3b59e0481..c36f4662d 100644
--- a/core/src/main/res/values-hi-rIN/strings.xml
+++ b/core/src/main/res/values-hi-rIN/strings.xml
@@ -144,8 +144,6 @@
<string name="remove_label"> हटाएँ</string>
<string name="delete_label">डिलीट</string>
<string name="delete_failed">फ़ाइल डिलीट करने में असमर्थ। डिवाइस को रिबूट करने से मदद मिल सकती है।</string>
- <string name="remove_new_flag_label">देखा गया के रूप में चिह्नित करें</string>
- <string name="removed_new_flag_label">देखा गया के रूप में चिह्नित किया गया</string>
<string name="mark_read_label">चलाया गया के रूप में चिह्नित करें</string>
<string name="marked_as_read_label">चलाया गया के रूप में चिह्नित किया गया</string>
<string name="mark_unread_label">नही चलाया गया के रूप में चिह्नित करें</string>
@@ -157,7 +155,6 @@
<string name="remove_from_favorite_label">पसंदीदा सूची से हटाए</string>
<string name="removed_from_favorites">पसंदीदा सूची से हटया गया</string>
<string name="visit_website_label">वेबसाइट पर जाएँ</string>
- <string name="support_label">इसे Flattr करें</string>
<string name="skip_episode_label">एपिसोड छोङें</string>
<string name="activate_auto_download">ऑटो डाउनलोड सक्रिय करें</string>
<string name="deactivate_auto_download">ऑटो डाउनलोड निष्क्रिय करें</string>
@@ -235,24 +232,6 @@
<string name="ascending">आरोही</string>
<string name="descending">अवरोही</string>
<string name="clear_queue_confirmation_msg">कृपया पुष्टि करें कि आप सारे एपिसोड के इस कतार को हटाना चाहते हैं</string>
- <!--Flattr-->
- <string name="flattr_auth_label">Flattr पंजीकरण करें</string>
- <string name="flattr_auth_explanation">प्रमाणीकरण प्रक्रिया शुरू करने के लिए नीचे दिए गए बटन को दबाएं. आपके ब्राउज़र में flattr लॉगिन स्क्रीन को भेजा जाएगा और flattr बातें करने के लिए अनुमति AntennaPod को देने के लिए कहा जाएगा. आपकि अनुमति देने के बाद, आप स्वतः ही इस स्क्रीन में वापस आ जाएगें.</string>
- <string name="authenticate_label">प्रामाणीकरण</string>
- <string name="return_home_label">होम पर लौटें</string>
- <string name="flattr_auth_success">प्रमाणीकरण सफल रहा था! अब आप अनुप्रयोग के भीतर चीजों को flattr कर सकते हैं.</string>
- <string name="no_flattr_token_title">कोई Flattr टोकन नहीं पाया गया</string>
- <string name="no_flattr_token_msg">आपकी flattr खाते का AntennaPod से जुड़ा होना प्रतीत नहीं होता. आप या तो AntennaPod को अपने खाते से कनेक्ट कर सकते हैं अनुप्रयोग के भीतर चीजों को flattr करने के लिए या आप इसे वहाँ flattr करने के लिए वेबसाइट पर जा सकते हैं.</string>
- <string name="authenticate_now_label">प्रामाणीकरण</string>
- <string name="action_forbidden_title">कार्रवाई मना</string>
- <string name="action_forbidden_msg">AntennaPod को इस कार्रवाई के लिए अनुमति नहीं है.इस के लिए कारण हो सकता है की आपके खाते में AntennaPod की पहुँच टोकन को निरस्त किया गया है.आप या तो फिर से प्रमाणित कर सकते हैं या बजाय किसी बात के वेबसाइट पर जा सकते हैं.</string>
- <string name="access_revoked_title">प्रवेश निरस्त किया</string>
- <string name="access_revoked_info">आपने सफलतापूर्वक अपने खाते में AntennaPod पहुँच टोकन निरस्त कर दिया है. इस प्रक्रिया को पूरा करने के लिए, आपको flattr वेबसाइट पर अपने खाते की सेटिंग्स में अनुमोदित आवेदनों की सूची से इस एप्लिकेशन को हटाना होगा.</string>
- <!--Flattr-->
- <string name="flattr_click_success">सफलतापूर्वक यह बात Flattr किया</string>
- <string name="flattr_click_success_count">सफलतापूर्वक %d बातोंको Flattr किया</string>
- <string name="flattr_click_success_queue">Flattr गिनती: %s</string>
- <string name="flattring_label">ऐन्टेनापॉड Flattr कररहा है</string>
<!--Variable Speed-->
<string name="download_plugin_label">प्लगइन डाउनलोड करें</string>
<string name="no_playback_plugin_title">प्लगइन स्थापित नहीं हुआ</string>
@@ -260,15 +239,14 @@
<string name="enable_sonic">सॉनिक सक्षम करे</string>
<!--Empty list labels-->
<string name="no_feeds_label">आपने अभी तक किसी भी पॉडकास्ट को सब्सक्राइब नहीं किया है।</string>
- <string name="no_chapters_label">इस एपिसोड में कोई अध्याय नहीं है।</string>
<string name="no_shownotes_label">इस एपिसोड में कोई शोनोट्स नहीं है।</string>
+ <string name="no_chapters_label">इस एपिसोड में कोई अध्याय नहीं है।</string>
<!--Preferences-->
<string name="storage_pref">स्टोरेज</string>
<string name="project_pref">परियोजना</string>
<string name="other_pref">अन्य</string>
<string name="about_pref">के बारे में</string>
<string name="queue_label">पंक्ति</string>
- <string name="flattr_label">Flattr</string>
<string name="automation">स्वचालन</string>
<string name="download_pref_details">विवरण</string>
<string name="import_export_pref">आयात/निर्यात</string>
@@ -289,15 +267,7 @@
<string name="pref_downloadMediaOnWifiOnly_title">वाईफाई मीडिया डाउनलोड करें</string>
<string name="pref_pauseOnHeadsetDisconnect_title">headphones काटना</string>
<string name="pref_mobileUpdate_title">मोबाइल अपडेट</string>
- <string name="pref_mobileUpdate_sum">मोबाइल डेटा कनेक्शन पर अपडेट करने की अनुमति दें</string>
<string name="refreshing_label">रिफ्रेशिंग</string>
- <string name="flattr_settings_label">Flattr सेटिंग्स</string>
- <string name="pref_flattr_auth_title">Flattr पंजीकरण करें</string>
- <string name="pref_flattr_auth_sum">App से सीधे अपनी बातें flattr करने के लिए अपने flattr खाते में प्रवेश करें.</string>
- <string name="pref_flattr_this_app_title">इस app को Flattr करें</string>
- <string name="pref_flattr_this_app_sum">यह flattring द्वारा AntennaPod के विकास का समर्थन करें. धन्यवाद!</string>
- <string name="pref_revokeAccess_title">उपयोग रद्द</string>
- <string name="pref_revokeAccess_sum">इस अनुप्रयोग के लिए अपने flattr खाते के लिए उपयोग की अनुमति रद्द करें.</string>
<string name="user_interface_label">यूजर इंटरफेस</string>
<string name="pref_set_theme_title">थीम का चयन करें</string>
<string name="pref_set_theme_sum">AntennaPod का प्रकटन बदलें.</string>
@@ -323,7 +293,6 @@
<string name="pref_playback_speed_sum">चर गति ऑडियो प्लेबैक के लिए उपलब्ध गति बनाइए</string>
<string name="pref_gpodnet_sethostname_title">होस्टनाम सेट</string>
<string name="pref_gpodnet_sethostname_use_default_host">डिफ़ॉल्ट होस्ट का प्रयोग करें</string>
- <!--Auto-Flattr dialog-->
<!--Search-->
<string name="found_in_chapters_label">अध्यायों में मिला</string>
<string name="search_status_no_results">कोई परिणाम नहीं मिले</string>
@@ -394,6 +363,7 @@
<!--Feed information screen-->
<!--Progress information-->
<!--AntennaPodSP-->
+ <!--Add podcast fragment-->
<!--Episodes apply actions-->
<!--Sort-->
<!--Rating dialog-->
diff --git a/core/src/main/res/values-hu/strings.xml b/core/src/main/res/values-hu/strings.xml
index 2d848b1cb..706b13b79 100644
--- a/core/src/main/res/values-hu/strings.xml
+++ b/core/src/main/res/values-hu/strings.xml
@@ -25,8 +25,9 @@
<string name="free_space_label">%1$s szabad</string>
<string name="episode_cache_full_title">Epizód tárhely megtelt</string>
<string name="episode_cache_full_message">Az epizódok tárolására megadott maximális tárhely megtelt. A méretét a \"Beállítások\" menüpontban tudod megnövelni.</string>
+ <string name="synchronizing">Szinkronizálás...</string>
<!--Statistics fragment-->
- <string name="total_time_listened_to_podcasts">A lejátszott podcast-ok összideje:</string>
+ <string name="total_time_listened_to_podcasts">A lejátszott podcastok összideje:</string>
<string name="statistics_details_dialog">%1$d-ból %2$d epizód elindítva.\n\n%3$s-ból %4$s lejátszva.</string>
<string name="statistics_mode">Statisztikai módok</string>
<!--Main activity-->
@@ -90,10 +91,15 @@
<string name="episode_cleanup_never">Soha</string>
<string name="episode_cleanup_queue_removal">Ha nincs sorbaállítva</string>
<string name="episode_cleanup_after_listening">Befejezés után</string>
+ <plurals name="episode_cleanup_hours_after_listening">
+ <item quantity="one">befejezés után 1 órával</item>
+ <item quantity="other">befejezés után %d órával</item>
+ </plurals>
<plurals name="episode_cleanup_days_after_listening">
<item quantity="one">1 nappal a befejezés után</item>
<item quantity="other">%d nappal a befejezés után</item>
</plurals>
+ <string name="num_selected_label">%d kiválasztva</string>
<!--'Add Feed' Activity labels-->
<string name="feedurl_label">Idővonal URL</string>
<string name="etxtFeedurlHint">www.example.com/feed</string>
@@ -101,17 +107,24 @@
<string name="podcastdirectories_label">Podcast keresése mappában</string>
<string name="podcastdirectories_descr">Új podcastokat kereshetsz iTunes-on vagy fyyd-en, vagy a gpodder.net-en név, kategória vagy cím alapján.</string>
<string name="browse_gpoddernet_label">gpodder.net böngészése</string>
+ <string name="discover">Felfedezés</string>
<!--Actions on feeds-->
<string name="mark_all_read_label">Az összes megjelölése lejátszottként</string>
<string name="mark_all_read_msg">Az összes epizód lejátszottként megjelölve</string>
<string name="mark_all_read_confirmation_msg">Biztosan megjelölöd az összes epizódot lejátszottként?</string>
- <string name="remove_all_new_flags_label">Az összes megjelölése megnézettként</string>
- <string name="remove_all_new_flags_confirmation_msg">Biztosan megjelölöd az összes epizódott megnézettként?</string>
<string name="show_info_label">Információ mutatása</string>
<string name="feed_settings_label">Podcast beállítások</string>
+ <string name="rename_feed_label">Podcast átnevezése</string>
+ <string name="remove_feed_label">Podcast eltávolítása</string>
<string name="share_label">Megosztás…</string>
+ <string name="share_link_label">Epizód URL megosztása</string>
+ <string name="share_link_with_position_label">Epizód URL megosztása pozícióval</string>
<string name="share_file_label">Fájl megosztása</string>
<string name="share_feed_url_label">Idővonal URL megosztása</string>
+ <string name="share_item_url_label">Médiafájl URL megosztása</string>
+ <string name="share_item_url_with_position_label">Médiafájl URL megosztása pozícióval</string>
+ <string name="feed_delete_confirmation_msg">Kérlek erősítsd meg, hogy törlöd a \"%1$s\" podcastot, az ÖSSZES epizóddal együtt (a letöltötteket is beleértve).</string>
+ <string name="feed_remover_msg">Podcast eltávolítása folyamatban</string>
<string name="hide_episodes_title">Epizódok elrejtése</string>
<string name="hide_unplayed_episodes_label">Nem lejátszott</string>
<string name="hide_paused_episodes_label">Szüneteltetett</string>
@@ -121,21 +134,39 @@
<string name="hide_downloaded_episodes_label">Letöltött</string>
<string name="hide_not_downloaded_episodes_label">Nem letöltött</string>
<string name="hide_has_media_label">További tartalma van</string>
+ <string name="hide_is_favorite_label">Kedvenc</string>
<string name="filtered_label">Szűrt</string>
<string name="refresh_failed_msg">{fa-exclamation-circle} A legutóbbi frissítés sikertelen</string>
<string name="open_podcast">Podcast megnyitása</string>
<!--actions on feeditems-->
<string name="download_label">Letöltés</string>
+ <plurals name="downloading_batch_label">
+ <item quantity="one">%d epizód letöltése.</item>
+ <item quantity="other">%d epizód letöltése.</item>
+ </plurals>
<string name="play_label">Lejátszás</string>
<string name="pause_label">Szüneteltetés</string>
<string name="stop_label">Megállítás</string>
<string name="stream_label">Stream-elés</string>
<string name="remove_label">Eltávolítás</string>
<string name="delete_label">Törlés</string>
- <string name="removed_new_flag_label">Megtekintettként megjelölve</string>
+ <string name="delete_failed">A fájl törlése nem sikerült. Az eszköz újraindítása segíthet a probléma megoldásában.</string>
+ <string name="delete_episode_label">Epizód törlése</string>
+ <plurals name="deleted_episode_batch_label">
+ <item quantity="one">%d epizód törölve. </item>
+ <item quantity="other">%d epizód törölve.</item>
+ </plurals>
<string name="mark_read_label">Jelölés játszottnak</string>
<string name="marked_as_read_label">Lejátszottként megjelölve</string>
+ <plurals name="marked_read_batch_label">
+ <item quantity="one">%d epizód lejátszottként megjelölve. </item>
+ <item quantity="other">%d epizód lejátszottként megjelölve.</item>
+ </plurals>
<string name="mark_unread_label">Jelölés nem játszottnak</string>
+ <plurals name="marked_unread_batch_label">
+ <item quantity="one">%d epizód nem játszottként megjelölve. </item>
+ <item quantity="other">%d epizód nem játszottként megjelölve.</item>
+ </plurals>
<string name="add_to_queue_label">Sorbaállítás</string>
<string name="added_to_queue_label">Hozzáadva a lejátszási sorhoz</string>
<string name="remove_from_queue_label">Eltávolítás lejátszási sorból</string>
@@ -144,7 +175,6 @@
<string name="remove_from_favorite_label">Kedvencekből eltávolítás</string>
<string name="removed_from_favorites">Kedvencekből eltávolítva</string>
<string name="visit_website_label">Honlap megtekintése</string>
- <string name="support_label">Flattr-ezés</string>
<string name="skip_episode_label">Epizód átugrása</string>
<string name="activate_auto_download">Automatikus letöltés bekapcsolása</string>
<string name="deactivate_auto_download">Automatikus letöltés kikapcsolása</string>
@@ -172,7 +202,8 @@
<string name="cancel_all_downloads_label">Az összes letöltés visszavonása</string>
<string name="download_canceled_msg">Letöltés visszavonva</string>
<string name="download_report_title">Letöltés befejeződött, hibák léptek fel</string>
- <string name="download_report_content_title">Jelentés letöltése</string>
+ <string name="download_report_content_title">Letöltési jelentés</string>
+ <string name="download_error_malformed_url">Hibás URL</string>
<string name="download_error_request_error">Lekérési hiba</string>
<string name="download_error_db_access">Adatbázis hozzáférési hiba</string>
<plurals name="downloads_left">
@@ -212,25 +243,25 @@
<string name="date">Dátum</string>
<string name="duration">Hossz</string>
<string name="episode_title">Epizód cím</string>
+ <string name="feed_title">Podcast cím</string>
<string name="ascending">Növekvő</string>
<string name="descending">Csökkenő</string>
- <!--Flattr-->
- <string name="flattr_auth_label">Flattr bejelentkezés</string>
- <string name="access_revoked_title">Hozzáférés megtagadva</string>
- <!--Flattr-->
<!--Variable Speed-->
<string name="download_plugin_label">Kiegészítő letöltése</string>
<string name="no_playback_plugin_title">Kiegészítő nincs telepítve</string>
<string name="set_playback_speed_label">Lejátszási sebesség</string>
<string name="enable_sonic">Sonic engedélyezése</string>
<!--Empty list labels-->
+ <string name="no_history_head_label">Napló üres</string>
<!--Preferences-->
<string name="storage_pref">Tároló</string>
<string name="project_pref">Projekt</string>
<string name="other_pref">Egyebek</string>
<string name="about_pref">Rólam</string>
<string name="queue_label">Lejátszási sor</string>
- <string name="flattr_label">Flattr</string>
+ <string name="download_pref_details">Részletek</string>
+ <string name="import_export_pref">Importálás/exportálás</string>
+ <string name="appearance">Megjelenés</string>
<string name="pref_pauseOnDisconnect_sum">Lejátszás szüneteltetése fejhallgató és bluetooth leválasztásakor</string>
<string name="pref_hardwareForwardButtonSkips_title">Előre gomb átugor</string>
<string name="pref_hardwarePreviousButtonRestarts_title">Előző gomb újraindít</string>
@@ -249,25 +280,24 @@
<string name="pref_unpauseOnHeadsetReconnect_title">Fejhallgató újracsatlakoztatása</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Bluetooth újracsatlakozás</string>
<string name="pref_mobileUpdate_title">Frissítések mobiladat-kapcsolaton</string>
- <string name="pref_mobileUpdate_sum">Frissítések engedélyezése mobiladat-kapcsolaton keresztül</string>
- <string name="flattr_settings_label">Flattr beállítások</string>
- <string name="pref_flattr_auth_title">Flattr bejelentkezés</string>
- <string name="pref_revokeAccess_title">Hozzáférés megvonása</string>
<string name="user_interface_label">Felhasználói felület</string>
<string name="pref_set_theme_title">Téma kiválasztása</string>
<string name="pref_nav_drawer_title">Navigációs fiók testreszabása</string>
<string name="pref_nav_drawer_sum">Navigációs fiók kinézetének testreszabás</string>
- <string name="pref_nav_drawer_items_title">Navigációs fiók elemeinek kiválaasztása</string>
+ <string name="pref_nav_drawer_items_title">Navigációs fiók elemeinek kiválasztása</string>
<string name="pref_set_theme_sum">AntennaPod kinézetének megváltoztatása</string>
- <string name="pref_automatic_download_title">Autómatikus letöltés</string>
- <string name="pref_automatic_download_sum">Epizódok autómatikus letöltésének beállítása</string>
+ <string name="pref_automatic_download_title">Automatikus letöltés</string>
+ <string name="pref_automatic_download_sum">Epizódok automatikus letöltésének beállítása</string>
<string name="pref_autodl_wifi_filter_title">Wi-Fi szűrő beállítása</string>
+ <string name="pref_autodl_allow_on_mobile_title">Letöltés mobiladat-kapcsolaton keresztül</string>
<string name="pref_parallel_downloads_title">Párhuzamos letöltések</string>
<string name="pref_episode_cache_title">Epizód gyorsítótár</string>
<string name="pref_theme_title_light">Világos</string>
<string name="pref_theme_title_dark">Sötét</string>
+ <string name="pref_theme_title_trueblack">Fekete (AMOLED-hez alkalmas)</string>
<string name="pref_update_interval_hours_plural">óra</string>
<string name="pref_update_interval_hours_singular">óra</string>
+ <string name="pref_update_interval_hours_manual">Manuális</string>
<string name="pref_gpodnet_authenticate_title">Bejelentkezés</string>
<string name="pref_gpodnet_authenticate_sum">Jelentkezz be a gpodder.net fiókodba a feliratkozások szinkronizálásához.</string>
<string name="pref_gpodnet_logout_title">Kijelentkezés</string>
@@ -278,6 +308,7 @@
<string name="pref_compact_notification_buttons_title">Zárképernyő gombok beállítása</string>
<string name="pref_lockscreen_background_title">Zárképernyő háttérkép</string>
<string name="pref_lockscreen_background_sum">Zárképernyő háttérkép átállítása az epizód képeként.</string>
+ <string name="pref_showDownloadReport_title">Letöltési jelentés megtekintése</string>
<string name="pref_image_cache_size_title">Kép gyorsítótár mérete</string>
<string name="pref_image_cache_size_sum">Kép gyorsítótár méretének a lemezen</string>
<string name="crash_report_title">Hibajelentés</string>
@@ -288,7 +319,6 @@
<string name="pref_known_issues">Ismert hibák</string>
<string name="pref_no_browser_found">Nem található webböngésző</string>
<string name="pref_cast_title">Chromecast támogatás</string>
- <!--Auto-Flattr dialog-->
<!--Search-->
<string name="search_hint">Epizódok keresése</string>
<string name="search_label">Keresés</string>
@@ -327,6 +357,7 @@
<!--Feed information screen-->
<!--Progress information-->
<!--AntennaPodSP-->
+ <!--Add podcast fragment-->
<string name="search_itunes_label">iTunes keresés</string>
<string name="search_fyyd_label">fyyd keresés</string>
<!--Episodes apply actions-->
diff --git a/core/src/main/res/values-id/strings.xml b/core/src/main/res/values-in/strings.xml
index 2f1ffecea..2f1ffecea 100644
--- a/core/src/main/res/values-id/strings.xml
+++ b/core/src/main/res/values-in/strings.xml
diff --git a/core/src/main/res/values-it/strings.xml b/core/src/main/res/values-it/strings.xml
index d1e1b596f..9ec2ad151 100644
--- a/core/src/main/res/values-it/strings.xml
+++ b/core/src/main/res/values-it/strings.xml
@@ -18,7 +18,7 @@
<string name="subscriptions_label">Sottoscrizioni</string>
<string name="subscriptions_list_label">Elenco sottoscrizioni</string>
<string name="cancel_download_label">Annulla\nil Download</string>
- <string name="playback_history_label">Cronologia delle riproduzioni</string>
+ <string name="playback_history_label">Cronologia riproduzioni</string>
<string name="gpodnet_main_label">gpodder.net</string>
<string name="gpodnet_summary">Sincronizza con altri dispositivi</string>
<string name="gpodnet_auth_label">Accesso a gpodder.net</string>
@@ -111,14 +111,16 @@
<string name="podcastdirectories_label">Trova un podcast nella directory</string>
<string name="podcastdirectories_descr">Per trovare podcasts puoi cercare su iTunes o fyyd, oppure puoi esplorare gpodder.net per nome, categoria oppure popolarità.</string>
<string name="browse_gpoddernet_label">Esplora gpodder.net</string>
+ <string name="discover">Scopri</string>
+ <string name="discover_more">altro »</string>
<!--Actions on feeds-->
<string name="mark_all_read_label">Segna tutti come riprodotti</string>
<string name="mark_all_read_msg">Segnati tutti gli episodi come riprodotti</string>
<string name="mark_all_read_confirmation_msg">Conferma che desideri segnare tutti gli episodi come riprodotti.</string>
<string name="mark_all_read_feed_confirmation_msg">Conferma che desideri segnare come riprodotti tutti gli episodi del podcast.</string>
- <string name="remove_all_new_flags_label">Segna tutti come visti</string>
- <string name="removed_all_new_flags_msg">Segna tutti gli episodi come visti</string>
- <string name="remove_all_new_flags_confirmation_msg">Conferma che desideri segnare tutti gli episodi come visti.</string>
+ <string name="remove_all_new_flags_label">Rimuovi tutti i flag \"nuovo\"</string>
+ <string name="removed_all_new_flags_msg">Flag \"nuovo\" rimossi</string>
+ <string name="remove_all_new_flags_confirmation_msg">Conferma di voler rimuovere tutti i flag \"nuovo\" da tutti gli episodi.</string>
<string name="show_info_label">Informazioni</string>
<string name="show_feed_settings_label">Mostra impostazioni podcast</string>
<string name="feed_info_label">Info podcast</string>
@@ -126,12 +128,12 @@
<string name="rename_feed_label">Rinomina podcast</string>
<string name="remove_feed_label">Rimuovi podcast</string>
<string name="share_label">Condividi...</string>
- <string name="share_link_label">Condividi URL Episodio</string>
+ <string name="share_link_label">Condividi URL episodio</string>
<string name="share_link_with_position_label">Condividi URL dell\'episodio con la posizione</string>
<string name="share_file_label">Condividi il file</string>
<string name="share_feed_url_label">Condividi URL del feed</string>
<string name="share_item_url_label">Condividi URL del media</string>
- <string name="share_item_url_with_position_label">Condividi URL del media come la posizione</string>
+ <string name="share_item_url_with_position_label">Condividi URL del media con la posizione</string>
<string name="feed_delete_confirmation_msg">Conferma di voler eliminare il podcast \"%1$s\" e TUTTI i suoi episodi (compresi quelli scaricati).</string>
<string name="feed_remover_msg">Rimozione del Feed in corso</string>
<string name="load_complete_feed">Aggiorna podcast completo</string>
@@ -169,8 +171,8 @@
<item quantity="one">%d episodio eliminato.</item>
<item quantity="other">%d episodi eliminati.</item>
</plurals>
- <string name="remove_new_flag_label">Segna come visto</string>
- <string name="removed_new_flag_label">Segna come visto</string>
+ <string name="remove_new_flag_label">Rimuovi flag \"nuovo\"</string>
+ <string name="removed_new_flag_label">Flag \"nuovo\" rimosso</string>
<string name="mark_read_label">Segna come riprodotto</string>
<string name="marked_as_read_label">Segnato come riprodotto</string>
<plurals name="marked_read_batch_label">
@@ -198,10 +200,9 @@
<string name="remove_from_favorite_label">Rimuovi dai preferiti</string>
<string name="removed_from_favorites">Rimosso dai Preferiti</string>
<string name="visit_website_label">Visita il sito</string>
- <string name="support_label">Carica questo su Flattr</string>
<string name="skip_episode_label">Salta l\'episodio</string>
- <string name="activate_auto_download">Attiva il Download Automatico</string>
- <string name="deactivate_auto_download">Disattiva il Download Automatico</string>
+ <string name="activate_auto_download">Attiva il download automatico</string>
+ <string name="deactivate_auto_download">Disattiva il download automatico</string>
<string name="reset_position">Azzera la Posizione di Riproduzione</string>
<string name="removed_item">Elemento rimosso</string>
<!--Download messages and labels-->
@@ -227,7 +228,7 @@
<string name="download_canceled_msg">Download annullato</string>
<string name="download_canceled_autodownload_enabled_msg">Download annullato\n<i>Download Automatico</i> disabilitato per questo elemento</string>
<string name="download_report_title">Download completato con un errore (o errori)</string>
- <string name="download_report_content_title">Rapporto del Downoad</string>
+ <string name="download_report_content_title">Rapporto del downoad</string>
<string name="download_error_malformed_url">URL malformato</string>
<string name="download_error_io_error">Errore IO</string>
<string name="download_error_request_error">Errore della richiesta</string>
@@ -250,6 +251,9 @@
<string name="confirm_mobile_download_dialog_title">Conferma il download su cellulare</string>
<string name="confirm_mobile_download_dialog_message_not_in_queue">Il download tramite rete mobile è disattivato nelle impostazioni.\n\nÈ possibile scegliere di aggiungere semplicemente l\'episodio alla coda o consentire temporaneamente il download.\n\n<small>La scelta verrà ricordata per 10 minuti.</small></string>
<string name="confirm_mobile_download_dialog_message">Il download tramite rete mobile è disattivato nelle impostazioni.\n\nVuoi abilitare temporaneamente il download?\n\n<small>La scelta verrà ricordata per 10 minuti.</small></string>
+ <string name="confirm_mobile_streaming_notification_title">Conferma streaming su rete mobile</string>
+ <string name="confirm_mobile_streaming_notification_message">Lo streaming su rete mobile è disattivato nelle impostazioni. Tocca per avviare comunque.</string>
+ <string name="confirm_mobile_streaming_button_always">Consenti sempre</string>
<string name="confirm_mobile_download_dialog_only_add_to_queue">Aggiungi alla coda</string>
<string name="confirm_mobile_download_dialog_enable_temporarily">Consenti temporaneamente</string>
<!--Mediaplayer messages-->
@@ -259,6 +263,8 @@
<string name="player_ready_msg">Pronto</string>
<string name="player_seeking_msg">Ricerca posizione</string>
<string name="playback_error_server_died">Server morto</string>
+ <string name="playback_error_unsupported">Tipo media non supportato</string>
+ <string name="playback_error_timeout">Tempo operazione scaduto</string>
<string name="playback_error_unknown">Errore sconosciuto</string>
<string name="no_media_playing_label">Nessun elemento multimediale in riproduzione</string>
<string name="player_buffering_msg">Buffer in corso</string>
@@ -276,6 +282,7 @@
<string name="move_to_top_label">Sposta all\'inizio</string>
<string name="move_to_bottom_label">Sposta in fondo</string>
<string name="sort">Ordina</string>
+ <string name="keep_sorted">Mantieni ordinato</string>
<string name="date">Per data</string>
<string name="duration">Per durata</string>
<string name="episode_title">Titolo dell\'episodio</string>
@@ -285,32 +292,8 @@
<string name="ascending">In ordine crescente</string>
<string name="descending">In ordine decrescente</string>
<string name="clear_queue_confirmation_msg">Per favore conferma che vuoi rimuovere dalla coda TUTTI gli episodi in essa presenti.</string>
- <!--Flattr-->
- <string name="flattr_auth_label">Accesso a Flattr</string>
- <string name="flattr_auth_explanation">Premi il tasto seguente per iniziare il processo di autenticazione. Sarai trasferito alla pagina di login di flattr sul tuo browser e ti sarà richiesto di garantire ad AntennaPod il permesso di effettuare microdonazioni. Dopo la tua autorizzazione, sarai riportato alla seguente schermata in modo automatico.</string>
- <string name="authenticate_label">Autenticazione</string>
- <string name="return_home_label">Ritorna alla pagina iniziale</string>
- <string name="flattr_auth_success">Autenticazione avvenuta con successo! Adesso puoi microdonare con flattr dall\'interno dell\'app.</string>
- <string name="no_flattr_token_title">Nessun token flattr trovato</string>
- <string name="no_flattr_token_notification_msg">Il tuo account di Flattr non sembra essere collegato ad AntennaPod. Premi qui per autenticarti.</string>
- <string name="no_flattr_token_msg">Il tuo account flattr non sembra essere collegato ad AntennaPod. Potresti collegare il tuo account ad AntennaPod per utilizzare flattr dall\'app oppure puoi visitare il sito per utilizzare flattr direttamente da lì.</string>
- <string name="authenticate_now_label">Autenticati</string>
- <string name="action_forbidden_title">Azione proibita</string>
- <string name="action_forbidden_msg">AntennaPod non ha il permesso di effettuare questa azione. La ragione potrebbe essere che il token di accesso di AntennaPod al tuo account è stato revocato. Puoi eseguire la re-autenticazione o altrimenti visitare il sito web.</string>
- <string name="access_revoked_title">Accesso revocato</string>
- <string name="access_revoked_info">Hai revocato l\'accesso di AntennaPod al tuo account. Al fine di completare il processo devi rimuovere l\'app dalla lista delle applicazioni autorizzare nelle impostazioni del tuo account sul sito di flattr.</string>
- <!--Flattr-->
- <string name="flattr_click_success">Caricata una cosa su Flattr!</string>
- <string name="flattr_click_success_count">Caricate %d cose su Flattr!</string>
- <string name="flattr_click_success_queue">Caricato su Flattr: %s.</string>
- <string name="flattr_click_failure_count">È stato fallito il caricamento su Flattr di %d cose!</string>
- <string name="flattr_click_failure">Non caricato su Flattr: %s.</string>
- <string name="flattr_click_enqueued">La cosa verrà caricata su Flattr più tardi</string>
- <string name="flattring_thing">Caricamento su Flattr di %s in corso</string>
- <string name="flattring_label">AntennaPod sta eseguendo Flattr</string>
- <string name="flattrd_label">AntennaPod ha caricato su Flattr</string>
- <string name="flattrd_failed_label">Caricamento su Flattr di AntennaPod fallito</string>
- <string name="flattr_retrieving_status">Ricezione di cose caricate su Flattr in corso</string>
+ <string name="sort_old_to_new">Dal meno recente</string>
+ <string name="sort_new_to_old">Dal più recente</string>
<!--Variable Speed-->
<string name="download_plugin_label">Scarica plugin</string>
<string name="no_playback_plugin_title">Plugin non installato</string>
@@ -319,8 +302,8 @@
<string name="enable_sonic">Abilita Sonic</string>
<!--Empty list labels-->
<string name="no_items_header_label">Nessun episodio in coda</string>
+ <string name="no_items_label">Aggiungi un episodio scaricandolo o tenendo premuto e selezionando \"Aggiungi alla coda\"</string>
<string name="no_feeds_label">Non sei ancora abbonato a nessun podcast. </string>
- <string name="no_chapters_label">Questo episodio non ha capitoli.</string>
<string name="no_shownotes_label">Questo episodio non ha note.</string>
<string name="no_run_downloads_head_label">Nessun download in corso</string>
<string name="no_run_downloads_label">Puoi scaricare gli episodi dalla vista dettagliata del podcast.</string>
@@ -332,10 +315,12 @@
<string name="no_history_label">Ogni episodio ascoltato apparirà qui.</string>
<string name="no_all_episodes_head_label">Nessun episodio</string>
<string name="no_all_episodes_label">Quando aggiungi un podcast, gli episodi vengono mostrati qui.</string>
- <string name="no_new_episodes_head_label">Nessu nuovo episodio</string>
+ <string name="no_new_episodes_head_label">Nessun nuovo episodio</string>
<string name="no_new_episodes_label">Quando arrivano nuovi episodi, vengono mostrati qui.</string>
<string name="no_fav_episodes_head_label">Nessun episodio preferito</string>
<string name="no_fav_episodes_label">Puoi aggiungere episodi ai preferiti tenendo premuto su di essi.</string>
+ <string name="no_chapters_head_label">Nessun capitolo</string>
+ <string name="no_chapters_label">Questo episodio non ha capitoli.</string>
<!--Preferences-->
<string name="storage_pref">Memoria</string>
<string name="project_pref">Progetto</string>
@@ -343,8 +328,6 @@
<string name="about_pref">Informazioni</string>
<string name="queue_label">Coda</string>
<string name="integrations_label">Integrazioni</string>
- <string name="flattr_label">Flattr</string>
- <string name="flattr_summary">Servizio micropagamenti</string>
<string name="automation">Automazione</string>
<string name="download_pref_details">Dettagli</string>
<string name="import_export_pref">Importa/Esporta</string>
@@ -352,7 +335,10 @@
<string name="appearance">Aspetto</string>
<string name="external_elements">Elementi esterni</string>
<string name="interruptions">Interruzioni</string>
- <string name="buttons">Pulsanti di controllo riproduzione</string>
+ <string name="playback_control">Controllo riproduzione</string>
+ <string name="preference_search_hint">Cerca...</string>
+ <string name="preference_search_no_results">Nessun risultato</string>
+ <string name="preference_search_clear_history">Svuota cronologia</string>
<string name="media_player">Media player</string>
<string name="pref_episode_cleanup_title">Pulizia episodi</string>
<string name="pref_episode_cleanup_summary">Gli episodi che non sono in coda e non sono tra i preferiti potrebbero essere rimossi se i Download Automatici richiedono maggiore spazio.</string>
@@ -360,14 +346,14 @@
<string name="pref_unpauseOnHeadsetReconnect_sum">Riprendi la riproduzione quando vengono riconnesse le cuffie</string>
<string name="pref_unpauseOnBluetoothReconnect_sum">Riprendi la riproduzione quando il Bluetooth si riconnette</string>
<string name="pref_hardwareForwardButtonSkips_title">Il tasto Avanti salta la traccia</string>
- <string name="pref_hardwareForwardButtonSkips_sum">Quando premi il pulsante avanti su un dispositivo bluetooth connesso passa all\'episodio successivo invece di andare avanti veloce</string>
+ <string name="pref_hardwareForwardButtonSkips_sum">Quando viene premuto il tasto Avanti sul dispositivo bluetooth connesso, passa all\'episodio successivo invece di andare avanti veloce</string>
<string name="pref_hardwarePreviousButtonRestarts_title">Il tasto Indietro riavvia la traccia</string>
- <string name="pref_hardwarePreviousButtonRestarts_sum">Quando viene premuto un tasto Indietro fisico, viene riavviata la traccia invece di tornare indietro</string>
+ <string name="pref_hardwarePreviousButtonRestarts_sum">Quando viene premuto il tasto fisico Indietro, viene riavviata la traccia invece di tornare indietro</string>
<string name="pref_followQueue_sum">Passa al prossimo episodio in coda quando viene completata la riproduzione</string>
<string name="pref_auto_delete_sum">Elimina l\'episodio quando viene completata la riproduzione</string>
<string name="pref_auto_delete_title">Elimina automaticamente</string>
<string name="pref_smart_mark_as_played_sum">Contrassegna gli episodi come riprodotti anche se rimangono alcuni secondi da riprodurre</string>
- <string name="pref_smart_mark_as_played_title">Segna come Riprodotto dopo</string>
+ <string name="pref_smart_mark_as_played_title">Marcatura intelligente</string>
<string name="pref_skip_keeps_episodes_sum">Mantieni in coda gli episodi quando vengono saltati</string>
<string name="pref_skip_keeps_episodes_title">Manteni gli episodi saltati</string>
<string name="pref_favorite_keeps_episodes_sum">Mantieni gli episodi quando sono segnati come Preferiti</string>
@@ -383,38 +369,31 @@
<string name="pref_autoUpdateIntervallOrTime_every">ogni %1$s</string>
<string name="pref_autoUpdateIntervallOrTime_at">alle %1$s</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Abilita il download dei media solo tramite WiFi</string>
- <string name="pref_followQueue_title">Riproduzione Continua</string>
+ <string name="pref_followQueue_title">Riproduzione continua</string>
<string name="pref_downloadMediaOnWifiOnly_title">Download dei media su WiFi</string>
<string name="pref_pauseOnHeadsetDisconnect_title">Disconnessione cuffie</string>
<string name="pref_unpauseOnHeadsetReconnect_title">Riconnessione cuffie</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Riconnessione Bluetooth</string>
- <string name="pref_mobileUpdate_title">Aggiornamenti su Reti a Consumo</string>
- <string name="pref_mobileUpdate_sum">Permetti gli aggiornamenti tramite connessione dati mobile</string>
- <string name="pref_mobileUpdate_nothing">Niente</string>
- <string name="pref_mobileUpdate_images">Solo immagini</string>
- <string name="pref_mobileUpdate_everything">Tutto</string>
+ <string name="pref_mobileUpdate_title">Aggiornamenti su rete mobile</string>
+ <string name="pref_mobileUpdate_sum">Seleziona quali operazioni sono consentite su reti mobili a consumo</string>
+ <string name="pref_mobileUpdate_refresh">Aggiornamento feed</string>
+ <string name="pref_mobileUpdate_images">Copertine</string>
+ <string name="pref_mobileUpdate_auto_download">Download automatici</string>
+ <string name="pref_mobileUpdate_episode_download">Download episodi</string>
+ <string name="pref_mobileUpdate_streaming">Streaming</string>
<string name="refreshing_label">Aggiornamento</string>
- <string name="flattr_settings_label">Impostazioni Flattr</string>
- <string name="pref_flattr_auth_title">Flattr sign-in</string>
- <string name="pref_flattr_auth_sum">Collega il tuo account flattr per utilizzare flattr direttamente dall\'app</string>
- <string name="pref_flattr_this_app_title">Supporta con flattr questa app</string>
- <string name="pref_flattr_this_app_sum">Supporta lo sviluppo di AntennaPod tramite flattr. Grazie!</string>
- <string name="pref_revokeAccess_title">Revoca l\'accesso</string>
- <string name="pref_revokeAccess_sum">Revoca il permesso, a questa applicazione, di accedere al tuo account flattr.</string>
- <string name="pref_auto_flattr_title">Flattr automatico</string>
- <string name="pref_auto_flattr_sum">Configura l\'esecuzione automatica di Flattr</string>
<string name="user_interface_label">Interfaccia utente</string>
<string name="pref_set_theme_title">Seleziona un tema</string>
<string name="pref_nav_drawer_title">Personalizza menù di navigazione</string>
<string name="pref_nav_drawer_sum">Personalizza l\'aspetto del menù di navigazione</string>
<string name="pref_nav_drawer_items_title">Seleziona elementi del menù</string>
- <string name="pref_nav_drawer_items_sum">Aggiunti o rimuovi gli elementi che appaiono nel menù laterale.</string>
+ <string name="pref_nav_drawer_items_sum">Aggiungi o rimuovi gli elementi che appaiono nel menù laterale.</string>
<string name="pref_nav_drawer_feed_order_title">Imposta l\'ordine delle sottoscrizioni</string>
<string name="pref_nav_drawer_feed_order_sum">Modifica l\'ordine delle tue sottoscrizioni</string>
<string name="pref_nav_drawer_feed_counter_title">Contatore delle sottoscrizioni</string>
- <string name="pref_nav_drawer_feed_counter_sum">Cambia le informazioni mostrate nel contatore delle sottoscrizioni. Influenza anche l\'ordinamento se l\'Ordine delle Sottoscrizioni è su \'Contatore\' </string>
+ <string name="pref_nav_drawer_feed_counter_sum">Cambia il criterio di calcolo del contatore delle sottoscrizioni. Influenza anche l\'ordinamento se l\'ordine delle sottoscrizioni è impostato su \'Contatore\' .</string>
<string name="pref_set_theme_sum">Cambia l\'aspetto di AntennaPod</string>
- <string name="pref_automatic_download_title">Download Automatico</string>
+ <string name="pref_automatic_download_title">Download automatico</string>
<string name="pref_automatic_download_sum">Configura il download automatico degli episodi</string>
<string name="pref_autodl_wifi_filter_title">Abilita il filtro Wi-Fi</string>
<string name="pref_autodl_wifi_filter_sum">Abilita il download automatico solo per alcune reti Wi-Fi selezionate.</string>
@@ -422,8 +401,9 @@
<string name="pref_autodl_allow_on_mobile_sum">Abilita il download automatico anche tramite la rete mobile.</string>
<string name="pref_automatic_download_on_battery_title">Scarica quando la batteria non è in carica</string>
<string name="pref_automatic_download_on_battery_sum">Permetti il download automatico quando la batteria non è in carica</string>
- <string name="pref_parallel_downloads_title">Download Contemporanei</string>
- <string name="pref_episode_cache_title">Cache degli Episodi</string>
+ <string name="pref_parallel_downloads_title">Download simulanei</string>
+ <string name="pref_episode_cache_title">Cache degli episodi</string>
+ <string name="pref_episode_cache_summary">Numero di episodi scaricati memorizzabili sul dispositivo. I download automatici vengono interrotti se si raggiunge questo valore.</string>
<string name="pref_theme_title_light">Chiaro</string>
<string name="pref_theme_title_dark">Scuro</string>
<string name="pref_theme_title_trueblack">Nero (AMOLED ready)</string>
@@ -449,8 +429,10 @@
<string name="pref_gpodnet_notifications_sum">Non si applica agli errori di autenticazione.</string>
<string name="pref_playback_speed_title">Velocità di riproduzione</string>
<string name="pref_playback_speed_sum">Personalizza le velocità disponibili per la riproduzione audio a velocità variabile</string>
+ <string name="pref_playback_time_respects_speed_title">Adatta info alla velocità di riproduzione</string>
+ <string name="pref_playback_time_respects_speed_sum">La posizione del cursore e la durata si adattano alla velocità di riproduzione scelta.</string>
<string name="pref_fast_forward">Tempo di salto in avanti</string>
- <string name="pref_fast_forward_sum">Personalizza il numero di secondi da saltare in avanti quando si preme il tasto Avanti Veloce</string>
+ <string name="pref_fast_forward_sum">Personalizza il numero di secondi da saltare in avanti quando si preme il tasto Avanti veloce</string>
<string name="pref_rewind">Tempo di salto indietro</string>
<string name="pref_rewind_sum">Personalizza il numero di secondi da saltare indietro quando si preme il tasto Riavvolgi</string>
<string name="pref_gpodnet_sethostname_title">Imposta l\'hostname</string>
@@ -460,19 +442,19 @@
<string name="pref_persistNotify_title">Controlli di riproduzione persistenti</string>
<string name="pref_persistNotify_sum">Mantieni le notifiche e i controlli del blocco dello schermo quando la riproduzione è in pausa.</string>
<string name="pref_compact_notification_buttons_title">Pulsanti su schermata di blocco</string>
- <string name="pref_compact_notification_buttons_sum">Modifica i pulsanti di riproduzione sulla schemata di blocco. Play/Pausa è sempre presente.</string>
+ <string name="pref_compact_notification_buttons_sum">Modifica i pulsanti di riproduzione mostrati nella schermata di blocco. Play/Pausa è sempre presente.</string>
<string name="pref_compact_notification_buttons_dialog_title">Seleziona al massimo %1$d voci</string>
<string name="pref_compact_notification_buttons_dialog_error">Puoi selezionare al massimo %1$d voci.</string>
<string name="pref_lockscreen_background_title">Cambia sfondo della schermata di blocco</string>
<string name="pref_lockscreen_background_sum">Sostituisce l\'immagine della schermata di blocco con quella dell\'episodio in riproduzione. Mostrerà l\'immagine anche in app di terze parti.</string>
- <string name="pref_showDownloadReport_title">Mostra il Rapporto del Download</string>
+ <string name="pref_showDownloadReport_title">Mostra il rapporto del download</string>
<string name="pref_showDownloadReport_sum">Se il download fallisce, genera un report che mostra i dettagli dell\'errore.</string>
<string name="pref_expand_notify_unsupport_toast">Le versioni di Android prima della 4.1 non supportano le notifiche estese.</string>
- <string name="pref_queueAddToFront_sum">Aggiungi un nuovo episodio in testa alla coda.</string>
+ <string name="pref_queueAddToFront_sum">Aggiungi i nuovi episodi in cima alla coda.</string>
<string name="pref_queueAddToFront_title">Aggiungi in cima alla coda</string>
<string name="pref_smart_mark_as_played_disabled">Disabilitato</string>
<string name="pref_image_cache_size_title">Dimensione cache delle immagini</string>
- <string name="pref_image_cache_size_sum">Dimensione cache per le immagini</string>
+ <string name="pref_image_cache_size_sum">Spazio su disco usato per la cache delle immagini.</string>
<string name="crash_report_title">Report dei crash</string>
<string name="crash_report_sum">Invia il report dell\'ultimo crash via e-mail</string>
<string name="send_email">Invia e-mail</string>
@@ -491,13 +473,13 @@
<string name="pref_enqueue_downloaded_summary">Aggiungi gli episodi scaricati alla coda di riproduzione</string>
<string name="media_player_builtin">Player Android integrato</string>
<string name="pref_skip_silence_title">Salta il silenzio audio</string>
- <string name="pref_videoBehavior_title">In uscita dal video</string>
+ <string name="pref_videoBehavior_title">Uscita dal video</string>
<string name="pref_videoBehavior_sum">Comportamento quando si esce dalla riproduzione video</string>
<string name="stop_playback">Interrompi riproduzione</string>
<string name="continue_playback">Continua riproduzione audio</string>
<string name="behavior">Comportamento</string>
<string name="pref_back_button_behavior_title">Comportamento tasto indietro</string>
- <string name="pref_back_button_behavior_sum">Cambia il comportamento del tasto indietro.</string>
+ <string name="pref_back_button_behavior_sum">Cambia il comportamento del tasto indietro</string>
<string name="back_button_default">Predefinito</string>
<string name="back_button_open_drawer">Apri menù di navigazione</string>
<string name="back_button_double_tap">Doppio tap per uscire</string>
@@ -506,13 +488,8 @@
<string name="double_tap_toast">Premi nuovamente il tasto indietro per uscire</string>
<string name="back_button_go_to_page">Vai alla pagina...</string>
<string name="back_button_go_to_page_title">Seleziona pagina</string>
- <string name="pref_delete_removes_from_queue_title">Elimina rimuove dalla Coda</string>
+ <string name="pref_delete_removes_from_queue_title">Rimuovi dalla coda gli eliminati</string>
<string name="pref_delete_removes_from_queue_sum">Rimuovi automaticamente un episodio dalla coda quando viene eliminato.</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">Abilita l\'esecuzione automatica di Flattr</string>
- <string name="auto_flattr_after_percent">Carica l\'episodio su Flattr appena è stato riprodotto al %d percento</string>
- <string name="auto_flattr_ater_beginning">Carica l\'episodio su Flattr appena comincia la riproduzione</string>
- <string name="auto_flattr_ater_end">Carica l\'episodio su Flattr appena finisce la riproduzione</string>
<!--Search-->
<string name="search_hint">Cerca negli episodi</string>
<string name="found_in_shownotes_label">Trovato nelle note dell\'episodio</string>
@@ -606,12 +583,14 @@
<string name="gpodnetsync_error_descr">Rilevato un errore in fase di sincronizzazione:\u0020</string>
<string name="gpodnetsync_pref_report_successful">Eseguito</string>
<string name="gpodnetsync_pref_report_failed">Fallito</string>
+ <string name="gpodnetsync_username_characters_error">Il nome utente può contenere solo lettere, numeri e trattini alti o bassi.</string>
<!--Directory chooser-->
<string name="selected_folder_label">Seleziona la cartella:</string>
<string name="create_folder_label">Crea una cartella</string>
- <string name="choose_data_directory">Scegli la directory per i dati</string>
+ <string name="choose_data_directory">Scegli la cartella per i dati</string>
<string name="choose_data_directory_message">Scegli la base della tua cartella dati. AntennaPod creerà le sottocartelle appropriate.</string>
<string name="choose_data_directory_permission_rationale">E\' necessario accedere alla memoria esterna per cambiare la cartella dei dati</string>
+ <string name="choose_data_directory_available_space">%1$s di %2$s liberi</string>
<string name="create_folder_msg">Crea una nuova directory con nome \"%1$s\"?</string>
<string name="create_folder_success">Crea una nuova directory</string>
<string name="create_folder_error_no_write_access">Impossibile scrivere in questa directory</string>
@@ -652,13 +631,18 @@
<string name="episode_filters_exclude">Escludi</string>
<string name="episode_filters_hint">Parole singole \n\"Parole multiple\"</string>
<string name="keep_updated">Mantieni Aggiornato</string>
+ <string name="keep_updated_summary">Includi nell\'(auto-)aggiornamento di tutti i feed</string>
+ <string name="auto_download_disabled_globally">Il download automatico è disabilitato nelle Impostazioni generali.</string>
<!--Progress information-->
<string name="progress_upgrading_database">Aggiornamento del database</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Importazione di sottoscrizioni da applicazioni monouso in corso...</string>
+ <!--Add podcast fragment-->
+ <string name="search_podcast_hint">Cerca podcast...</string>
<string name="search_itunes_label">Cerca su iTunes</string>
- <string name="filter">Filtro</string>
<string name="search_fyyd_label">Cerca su fyyd</string>
+ <string name="advanced_search">Ricerca avanzata</string>
+ <string name="filter">Filtro</string>
<!--Episodes apply actions-->
<string name="all_label">Tutto</string>
<string name="selected_all_label">Seleziona tutti gli Episodi</string>
@@ -714,6 +698,7 @@
<string name="proxy_host_invalid_error">L\'host non è un IP o un dominio valido</string>
<string name="proxy_port_invalid_error">Porta non valida</string>
<!--Subscriptions fragment-->
+ <string name="subscription_num_columns">Numero di colonne</string>
<!--Database import/export-->
<string name="import_export">Importa/Esporta database</string>
<string name="import_export_warning">Questa funzione sperimentale può essere usata per trasferire le sottoscrizioni e gli episoti completati ad un altro dispositivo.\n\nIl database potrà essere importato solo se si usa la stessa versione di AntennaPod, altrimenti potrebbero generarsi comportamenti anomali.\n\nDopo l\'importazione, gli episodi potrebbero essere mostrati come scaricati anche se non lo sono. Basta premere Play per farli riconoscere ad AntennaPod.</string>
@@ -747,4 +732,5 @@
<string name="notification_channel_playing_description">Permette di controllare la riproduzione. Questa è la principale notifica visibile quando un prodcast è in riproduzione.</string>
<string name="notification_channel_error">Errori</string>
<string name="notification_channel_error_description">Mostrato se qualcosa è andato storto, per esempio se fallisce il download o la sincronizzazione di gpodder.</string>
+ <string name="import_bad_file">File non valido/corrotto</string>
</resources>
diff --git a/core/src/main/res/values-iw-rIL/strings.xml b/core/src/main/res/values-iw-rIL/strings.xml
index d73fdd015..d688b3935 100644
--- a/core/src/main/res/values-iw-rIL/strings.xml
+++ b/core/src/main/res/values-iw-rIL/strings.xml
@@ -115,14 +115,16 @@
<string name="podcastdirectories_label">חפש פודקאסט בספריה</string>
<string name="podcastdirectories_descr">לאיתור פודקאסטים חדשים, ניתן לחפש ב־iTunes או ב־fyyd או לעיין ב־gpodder.net לפי שם, קטגוריה או פופולריות.</string>
<string name="browse_gpoddernet_label">עיון ב־gpodder.net</string>
+ <string name="discover">עיון</string>
+ <string name="discover_more">עוד »</string>
<!--Actions on feeds-->
<string name="mark_all_read_label">לסמן הכול כנוגנו</string>
<string name="mark_all_read_msg">לסמן את כל הפרקים כנוגנו</string>
<string name="mark_all_read_confirmation_msg">נא לאשר שברצונך לסמן את כל הפרקים כנוגנו.</string>
<string name="mark_all_read_feed_confirmation_msg">נא לאשר שברצונך לסמן את הפרקים של הפודקאסט הזה כאילו כבר נוגנו.</string>
- <string name="remove_all_new_flags_label">לסמן הכול כנצפו</string>
- <string name="removed_all_new_flags_msg">כל הפרקים סומנו כאילו כבר נוגנו</string>
- <string name="remove_all_new_flags_confirmation_msg">נא לאשר שברצונך לסמן את כל הפרקים כנצפו.</string>
+ <string name="remove_all_new_flags_label">הסרת כל סימוני „חדש”</string>
+ <string name="removed_all_new_flags_msg">הוסרו כל סימוני „חדש”</string>
+ <string name="remove_all_new_flags_confirmation_msg">נא לאשר שברצונך להסיר את הסימון „חדש” מכל הפרקים.</string>
<string name="show_info_label">הצגת מידע</string>
<string name="show_feed_settings_label">הצגת הגדרות פודקאסט</string>
<string name="feed_info_label">פרטי פודקאסט</string>
@@ -177,8 +179,8 @@
<item quantity="many">%d פרקים נמחקו.</item>
<item quantity="other">%d פרקים נמחקו.</item>
</plurals>
- <string name="remove_new_flag_label">עם סימון כנצפה</string>
- <string name="removed_new_flag_label">סימון כנצפה</string>
+ <string name="remove_new_flag_label">הסרת הסימון „חדש”</string>
+ <string name="removed_new_flag_label">הוסר הסימון „חדש”</string>
<string name="mark_read_label">סימון כנצפה</string>
<string name="marked_as_read_label">סימון כנוגן</string>
<plurals name="marked_read_batch_label">
@@ -214,7 +216,6 @@
<string name="remove_from_favorite_label">הסרה מהמועדפים</string>
<string name="removed_from_favorites">הוסר מהמועדפים</string>
<string name="visit_website_label">ביקור באתר</string>
- <string name="support_label">תרומה עם Flattr</string>
<string name="skip_episode_label">דילוג על פרק</string>
<string name="activate_auto_download">הפעלת הורדה אוטומטית</string>
<string name="deactivate_auto_download">השבתת הורדה אוטומטית</string>
@@ -268,6 +269,9 @@
<string name="confirm_mobile_download_dialog_title">אישור הורדה דרך רשת סלולרית</string>
<string name="confirm_mobile_download_dialog_message_not_in_queue">הורדה דרך חיבור נתונים של רשת סלולרית מושבת דרך ההגדרות.\n\nניתן לבחור בין הוספת הפרק לתור או לאפשר להוריד אותו באופן זמני.\n\n<small>הבחירה שלך תישמר למשך 10 דקות.</small></string>
<string name="confirm_mobile_download_dialog_message">הורדה דרך חיבור נתונים של רשת סלולרית מושבת דרך ההגדרות.\n\nלאפשר את ההורדה באופן זמני?\n\n<small>הבחירה שלך תישמר למשך 10 דקות.</small></string>
+ <string name="confirm_mobile_streaming_notification_title">אישור הזרמה דרך רשת סלולרית</string>
+ <string name="confirm_mobile_streaming_notification_message">הזרמה דרך חיבור רשת סלולרית מושבתת בהגדרות. ניתן לגעת כדי להזרים בכל זאת.</string>
+ <string name="confirm_mobile_streaming_button_always">לאפשר תמיד</string>
<string name="confirm_mobile_download_dialog_only_add_to_queue">הוספה לתור</string>
<string name="confirm_mobile_download_dialog_enable_temporarily">לאפשר לבינתיים</string>
<!--Mediaplayer messages-->
@@ -277,6 +281,8 @@
<string name="player_ready_msg">בהמתנה</string>
<string name="player_seeking_msg">מתבצע איתור</string>
<string name="playback_error_server_died">השרת לא מגיב</string>
+ <string name="playback_error_unsupported">אין תמיכה בסוג המדיה הזה</string>
+ <string name="playback_error_timeout">הזמן שהוקצב לפעולה תם</string>
<string name="playback_error_unknown">שגיאה לא ידועה</string>
<string name="no_media_playing_label">אין מדיה מתנגנת</string>
<string name="player_buffering_msg">החוצץ מתמלא</string>
@@ -294,6 +300,7 @@
<string name="move_to_top_label">העברה למעלה</string>
<string name="move_to_bottom_label">העברה למטה</string>
<string name="sort">מיון</string>
+ <string name="keep_sorted">להשאיר ממוין</string>
<string name="date">תאריך</string>
<string name="duration">משך</string>
<string name="episode_title">כותרת הפרק</string>
@@ -303,32 +310,8 @@
<string name="ascending">בסדר עולה</string>
<string name="descending">בסדר יורד</string>
<string name="clear_queue_confirmation_msg">נא לאשר את פינוי התור מכל הפרקים שבו</string>
- <!--Flattr-->
- <string name="flattr_auth_label">כניסה ל־Fattr</string>
- <string name="flattr_auth_explanation">נא ללחוץ על הכפתור שלמטה כדי להתחיל את תהליך האימות. פעולה זו תעביר אותך למסך הכניסה של Flattr בדפדפן שלך ותופיע בקשה לאפשר לאנטנה־פּוֹד לבצע פעולות ב־Flattr. לאחר מתן ההרשאה, המערכת תחזיר אותך למסך זה אוטומטית.</string>
- <string name="authenticate_label">אימות</string>
- <string name="return_home_label">חזרה למסך הבית</string>
- <string name="flattr_auth_success">האימות הצליח! כעת יש לך אפשרות לתרום עם Flattr מתוך היישומון.</string>
- <string name="no_flattr_token_title">לא נמצא אסימון Flattr</string>
- <string name="no_flattr_token_notification_msg">נראה כי חשבון ה־Flattr שלך אינו מחובר לאנטנה־פּוֹד. יש לגעת כאן לאימות.</string>
- <string name="no_flattr_token_msg">נראה כי חשבון ה־Flattr שלך אינו מחובר לאנטנה־פּוֹד. יש לך אפשרות לחבר את חשבונך לאנטנה־פּוֹד כדי לתרום עם Flattr מתוך היישומון או לבקר באתר של מה שברצונך לתרום לו עם Flattr.</string>
- <string name="authenticate_now_label">אימות</string>
- <string name="action_forbidden_title">הפעולה אסורה</string>
- <string name="action_forbidden_msg">לאנטנה־פּוֹד אין הרשאה לבצע פעולה זו. הסיבה לכך עשויה להיות שאסימון הגישה של אנטנה־פּוֹד לחשבון שלך נשלל. ניתן לאמת מחדש או לבקר באתר המיועד במקום.</string>
- <string name="access_revoked_title">גישה בוטלה</string>
- <string name="access_revoked_info">אסימון הגישה של אנטנה־פוד לחשבונך בוטל. על מנת להשלים את התהליך, אתה צריך להסיר יישום זה מהרשימת היישומים שאושרו בהגדרות החשבונך באתר flattr.</string>
- <!--Flattr-->
- <string name="flattr_click_success">תרמת ב־Flattr!</string>
- <string name="flattr_click_success_count">תרמת ב־Flattr %d פעמים!</string>
- <string name="flattr_click_success_queue">תרומות Flattr: %s.</string>
- <string name="flattr_click_failure_count">התרומה ב־Flattr %d נכשלה!</string>
- <string name="flattr_click_failure">לא נתרם ב־Flattr: %s.</string>
- <string name="flattr_click_enqueued">לתרום ב־Flattr מאוחר יותר</string>
- <string name="flattring_thing">תרומה ב־Flattr %s</string>
- <string name="flattring_label">תרומה ב־Flattr עם אנטנה־פּוֹד</string>
- <string name="flattrd_label">תרומה ב־Flattr עם אנטנה־פּוֹד</string>
- <string name="flattrd_failed_label">התרומה באנטנה־פּוֹד עם Flattr נכשלה</string>
- <string name="flattr_retrieving_status">תרומות Flattr מתקבלות</string>
+ <string name="sort_old_to_new">חדש לישן</string>
+ <string name="sort_new_to_old">ישן לחדש</string>
<!--Variable Speed-->
<string name="download_plugin_label">הורדת תוסף</string>
<string name="no_playback_plugin_title">תוסף לא מותקן</string>
@@ -339,7 +322,6 @@
<string name="no_items_header_label">אין פרקים בתור</string>
<string name="no_items_label">ניתן להוסיף פרק על ידי הורדתו או ללחוץ על פרק לחיצה ארוכה ולבחור ב־„הוספה לתור”.</string>
<string name="no_feeds_label">לא נרשמת לאף פודקאסט עדיין.</string>
- <string name="no_chapters_label">לפרק זה אין פרקים.</string>
<string name="no_shownotes_label">לפרק זה אין הערות פרק.</string>
<string name="no_run_downloads_head_label">אין הורדות פעילו</string>
<string name="no_run_downloads_label">ניתן להוריד פרקים במסך הפרטים של הפודקאסט.</string>
@@ -355,6 +337,8 @@
<string name="no_new_episodes_label">עם הופעת פרקים חדשים, הם יופיעו כאן.</string>
<string name="no_fav_episodes_head_label">אין פרקים מועדפים</string>
<string name="no_fav_episodes_label">ניתן להוסיף פרקים למועדפים בלחיצה ארוכה.</string>
+ <string name="no_chapters_head_label">אין פרקים</string>
+ <string name="no_chapters_label">לפרק זה אין פרקים.</string>
<!--Preferences-->
<string name="storage_pref">אחסון</string>
<string name="project_pref">מיזם</string>
@@ -362,8 +346,6 @@
<string name="about_pref">על אודות</string>
<string name="queue_label">תור</string>
<string name="integrations_label">שילובים</string>
- <string name="flattr_label">Flattr</string>
- <string name="flattr_summary">שירות תשלומים זעירים</string>
<string name="automation">אוטומציה</string>
<string name="download_pref_details">פרטים</string>
<string name="import_export_pref">ייבוא/ייצוא</string>
@@ -371,7 +353,10 @@
<string name="appearance">מראה</string>
<string name="external_elements">רכיבים חיצוניים</string>
<string name="interruptions">הפרעות</string>
- <string name="buttons">כפתורי שליטת נגינה</string>
+ <string name="playback_control">בקרת נגינה</string>
+ <string name="preference_search_hint">חיפוש…</string>
+ <string name="preference_search_no_results">אין תוצאות</string>
+ <string name="preference_search_clear_history">פינוי ההיסטוריה</string>
<string name="media_player">נגן מדיה</string>
<string name="pref_episode_cleanup_title">ניקוי פרקים</string>
<string name="pref_episode_cleanup_summary">פרקים שאינם בתור ואינם במועדפים אמורים לענות לתנאים של הסרה במקרה שההורדה האוטומטית זקוקה למקום לפרקים חדשים</string>
@@ -408,20 +393,13 @@
<string name="pref_unpauseOnHeadsetReconnect_title">חיבור אוזניות מחדש</string>
<string name="pref_unpauseOnBluetoothReconnect_title">חיבור Bluetooth מחדש</string>
<string name="pref_mobileUpdate_title">עדכון דרך רשת סלולרית</string>
- <string name="pref_mobileUpdate_sum">לאפשר עדכונים דרך רשת סלולרית</string>
- <string name="pref_mobileUpdate_nothing">כלום</string>
- <string name="pref_mobileUpdate_images">תמונות בלבד</string>
- <string name="pref_mobileUpdate_everything">הכול</string>
+ <string name="pref_mobileUpdate_sum">לבחור מה מותר דרך חיבור רשת סלולרית</string>
+ <string name="pref_mobileUpdate_refresh">רענון הזנה</string>
+ <string name="pref_mobileUpdate_images">תמונות נושא</string>
+ <string name="pref_mobileUpdate_auto_download">הורדה אוטומטית</string>
+ <string name="pref_mobileUpdate_episode_download">הורדת פרקים</string>
+ <string name="pref_mobileUpdate_streaming">הזרמה</string>
<string name="refreshing_label">מתבצע רענון</string>
- <string name="flattr_settings_label">הגדרות Flattr</string>
- <string name="pref_flattr_auth_title">כניסה ל־Fattr</string>
- <string name="pref_flattr_auth_sum">ניתן להיכנס לחשבון שלך ב־Flattr כדי לתרום ישירות מתוך היישומון.</string>
- <string name="pref_flattr_this_app_title">תרום באמצעות Flattr לאפליקציה זו</string>
- <string name="pref_flattr_this_app_sum">ניתן לתמוך בפיתוח של אנטנה־פּוֹד על ידי תרומה ב־Flattr. תודה!</string>
- <string name="pref_revokeAccess_title">ביטול גישה גישה</string>
- <string name="pref_revokeAccess_sum">שלילת הרשאות הגישה לחשבון ה־Flattr שלך מיישומון זה.</string>
- <string name="pref_auto_flattr_title">תרומות Flattr אוטומטיות</string>
- <string name="pref_auto_flattr_sum">הגדרת תרומות Flattr אוטומטיות</string>
<string name="user_interface_label">מנשק משתמש</string>
<string name="pref_set_theme_title">בחירת ערכת עיצוב</string>
<string name="pref_nav_drawer_title">התאמת מגירת הניווט</string>
@@ -443,6 +421,7 @@
<string name="pref_automatic_download_on_battery_sum">לאפשר הורדה אוטומטית כאשר הסוללה אינה בטעינה</string>
<string name="pref_parallel_downloads_title">הורדות במקביל</string>
<string name="pref_episode_cache_title">מטמון פרקים</string>
+ <string name="pref_episode_cache_summary">המספר הכולל של פרקים שהורדו ונשמרים במכשיר. הורדה אוטומטית תושבת אם הכמות הזאת הושגה.</string>
<string name="pref_theme_title_light">בהיר</string>
<string name="pref_theme_title_dark">כהה</string>
<string name="pref_theme_title_trueblack">שחור (תואם AMOLED)</string>
@@ -468,6 +447,8 @@
<string name="pref_gpodnet_notifications_sum">הגדרה זו אינה חלה על שגיאות אימות.</string>
<string name="pref_playback_speed_title">מהירויות ניגון</string>
<string name="pref_playback_speed_sum">בחירת המהירויות הזמינות למהירות נגינה משתנה</string>
+ <string name="pref_playback_time_respects_speed_title">להתאים את פרטי המדיה למהירות הנגינה</string>
+ <string name="pref_playback_time_respects_speed_sum">המיקום המוצג והמשך מותאמים למהירות הנגינה</string>
<string name="pref_fast_forward">זמן דילוג בהאצה קדימה</string>
<string name="pref_fast_forward_sum">התאמת מספר השניות של הקפיצה קדימה בעת לחיצה על כפתור ההאצה</string>
<string name="pref_rewind">זמן בקפיצה אחורה</string>
@@ -527,11 +508,6 @@
<string name="back_button_go_to_page_title">בחירת עמוד</string>
<string name="pref_delete_removes_from_queue_title">מחיקה מסירה מהתור</string>
<string name="pref_delete_removes_from_queue_sum">הסרת פרק מהתור אוטומטית עם מחיקתו.</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">הפעלת תרומות Flattr אוטומטיות</string>
- <string name="auto_flattr_after_percent">לתרום לפרק כאשר התנגנו %d אחוזים</string>
- <string name="auto_flattr_ater_beginning">לתרום עם Flattr עם תחילת נגינת פרק</string>
- <string name="auto_flattr_ater_end">לתרום עם Flattr עם סיום נגינת פרק</string>
<!--Search-->
<string name="search_hint">חיפוש אחר פרקים</string>
<string name="found_in_shownotes_label">נמצא בהערות הפרק</string>
@@ -631,12 +607,14 @@
<string name="gpodnetsync_error_descr">שגיאה במהלך סינכרון:\u0020</string>
<string name="gpodnetsync_pref_report_successful">מוצלח</string>
<string name="gpodnetsync_pref_report_failed">נכשל</string>
+ <string name="gpodnetsync_username_characters_error">שמות המשתמשים יכולים להכיל אותיות, ספרות, מינוסים וקווים תחתיים בלבד.</string>
<!--Directory chooser-->
<string name="selected_folder_label">תיקייה נבחרת:</string>
<string name="create_folder_label">יצירת תיקייה</string>
<string name="choose_data_directory">בחר תיקיית מידע</string>
<string name="choose_data_directory_message">נא לבחור את בסיס תיקיית הנתונים שלך. תת־התיקיות תיווצרנה על ידי אנטנה־פּוֹד בהתאם.</string>
<string name="choose_data_directory_permission_rationale">נדרשת גישה לאחסון חיצוני כדי לשנות את תיקיית הנתונים</string>
+ <string name="choose_data_directory_available_space">%1$s מתוך %2$s פנויים</string>
<string name="create_folder_msg">ליצור תיקייה חדשה בשם „%1$s”?</string>
<string name="create_folder_success">נוצרה תיקייה חדשה</string>
<string name="create_folder_error_no_write_access">לא ניתן לכתוב לתיקייה זו</string>
@@ -677,13 +655,18 @@
<string name="episode_filters_exclude">להחריג</string>
<string name="episode_filters_hint">מילים בודדות \n\"אוסף מילים\"</string>
<string name="keep_updated">לשמור על עדכניות</string>
+ <string name="keep_updated_summary">לכלול את ההזנה בעת רענון (אוטומטי) של כל ההזנות</string>
+ <string name="auto_download_disabled_globally">הורדה אוטומטית מושבתת בהגדרות הראשיות של אנטנה־פּוֹד</string>
<!--Progress information-->
<string name="progress_upgrading_database">מסד הנתונים משתדרג</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">מתבצע ייבוא מינויים מיישומונים ממוקדי מטרה…</string>
+ <!--Add podcast fragment-->
+ <string name="search_podcast_hint">חיפוש פודקאסט…</string>
<string name="search_itunes_label">חיפוש ב־iTunes</string>
- <string name="filter">מסנן</string>
<string name="search_fyyd_label">בחיפוש ב־fyyd</string>
+ <string name="advanced_search">חיפוש מתקדם</string>
+ <string name="filter">מסנן</string>
<!--Episodes apply actions-->
<string name="all_label">הכול</string>
<string name="selected_all_label">בחירת כל הפרקים</string>
@@ -773,4 +756,5 @@
<string name="notification_channel_playing_description">מאשר לשלוט בנגינה. זאת ההתראה הראשית שמופיעה בעת נגינת פודקאסט.</string>
<string name="notification_channel_error">שגיאות</string>
<string name="notification_channel_error_description">מופיעות אם משהו משתבש, למשל אם הורדה או סנכרון מול gpodder נכשלים.</string>
+ <string name="import_bad_file">קובץ לא תקין/פגום</string>
</resources>
diff --git a/core/src/main/res/values-ja/strings.xml b/core/src/main/res/values-ja/strings.xml
index 0818b7044..5c78ea4c9 100644
--- a/core/src/main/res/values-ja/strings.xml
+++ b/core/src/main/res/values-ja/strings.xml
@@ -109,14 +109,16 @@
<string name="podcastdirectories_label">ディレクトリでポッドキャストを検索</string>
<string name="podcastdirectories_descr">新しいポッドキャストでは、名前、カテゴリー、人気でiTunesやfyydを検索したり、gpodder.netを参照することができます。</string>
<string name="browse_gpoddernet_label">gpodder.netを参照</string>
+ <string name="discover">発見</string>
+ <string name="discover_more">さらに »</string>
<!--Actions on feeds-->
<string name="mark_all_read_label">すべて再生済としてマーク</string>
<string name="mark_all_read_msg">すべてのエピソードを再生済にしました</string>
<string name="mark_all_read_confirmation_msg">再生済としてマークするすべてのエピソードを確認してください。</string>
<string name="mark_all_read_feed_confirmation_msg">再生済としてマークするこのポッドキャストのすべてのエピソードを確認してください。</string>
- <string name="remove_all_new_flags_label">すべて参照済としてマーク</string>
- <string name="removed_all_new_flags_msg">すべてのエピソードを参照済にしました</string>
- <string name="remove_all_new_flags_confirmation_msg">参照済としてマークするすべてのエピソードを確認してください。</string>
+ <string name="remove_all_new_flags_label">すべての \"新規\" フラグを削除</string>
+ <string name="removed_all_new_flags_msg">すべての \"新規\" フラグを削除しました</string>
+ <string name="remove_all_new_flags_confirmation_msg">\"新規\" フラグを削除するすべてのエピソードを確認してください。</string>
<string name="show_info_label">情報を表示</string>
<string name="show_feed_settings_label">ポッドキャスト設定を表示</string>
<string name="feed_info_label">ポッドキャスト情報</string>
@@ -165,8 +167,8 @@
<plurals name="deleted_episode_batch_label">
<item quantity="other">%d エピソードを削除しました。</item>
</plurals>
- <string name="remove_new_flag_label">参照済</string>
- <string name="removed_new_flag_label">参照済としてマーク</string>
+ <string name="remove_new_flag_label">\"新規\" フラグを削除</string>
+ <string name="removed_new_flag_label">\"新規\" フラグを削除しました</string>
<string name="mark_read_label">再生済としてマーク</string>
<string name="marked_as_read_label">再生済としてマークしました</string>
<plurals name="marked_read_batch_label">
@@ -190,7 +192,6 @@
<string name="remove_from_favorite_label">お気に入りから削除</string>
<string name="removed_from_favorites">お気に入りから削除</string>
<string name="visit_website_label">Webサイトを訪問</string>
- <string name="support_label">これをFlattr</string>
<string name="skip_episode_label">エピソードをスキップ</string>
<string name="activate_auto_download">自動ダウンロードを有効にする</string>
<string name="deactivate_auto_download">自動ダウンロードを無効にする</string>
@@ -241,6 +242,9 @@
<string name="confirm_mobile_download_dialog_title">モバイルダウンロードの確認</string>
<string name="confirm_mobile_download_dialog_message_not_in_queue">モバイルデータ接続でのダウンロードは設定で無効になっています。\n\n一時的に有効にするか、またはキューに追加するだけにしますか?\n\n<small>選択は 10 分間記憶されます。</small></string>
<string name="confirm_mobile_download_dialog_message">モバイルデータ接続でのダウンロードは設定で無効になっています。\n\n一時的に有効にしますか?\n\n<small>選択は 10 分間記憶されます。</small></string>
+ <string name="confirm_mobile_streaming_notification_title">モバイルストリーミングの確認</string>
+ <string name="confirm_mobile_streaming_notification_message">モバイルデータ接続を介したストリーミングは設定で無効になっています。 タップするととにかくストリーミングします。</string>
+ <string name="confirm_mobile_streaming_button_always">常に許可</string>
<string name="confirm_mobile_download_dialog_only_add_to_queue">キューに追加するだけ</string>
<string name="confirm_mobile_download_dialog_enable_temporarily">一時的に有効にする</string>
<!--Mediaplayer messages-->
@@ -250,6 +254,8 @@
<string name="player_ready_msg">準備完了</string>
<string name="player_seeking_msg">シーク中</string>
<string name="playback_error_server_died">サーバーがダウンしています</string>
+ <string name="playback_error_unsupported">サポートされていないメディアタイプ</string>
+ <string name="playback_error_timeout">操作がタイムアウトしました</string>
<string name="playback_error_unknown">不明なエラー</string>
<string name="no_media_playing_label">再生するメディアがありません</string>
<string name="player_buffering_msg">バッファー中</string>
@@ -267,6 +273,7 @@
<string name="move_to_top_label">先頭に移動</string>
<string name="move_to_bottom_label">最後に移動</string>
<string name="sort">並べ替え</string>
+ <string name="keep_sorted">ソート順を保持</string>
<string name="date">日付</string>
<string name="duration">継続時間</string>
<string name="episode_title">エピソード タイトル</string>
@@ -276,32 +283,8 @@
<string name="ascending">昇順</string>
<string name="descending">降順</string>
<string name="clear_queue_confirmation_msg">クリアする、キューに含まれるすべてのエピソードを確認してください。</string>
- <!--Flattr-->
- <string name="flattr_auth_label">Flattrにサインイン</string>
- <string name="flattr_auth_explanation">認証処理を開始するには、下のボタンを押します。お使いのブラウザでflattrのログイン画面に転送され、AntennaPodにflattrする許可を与えるように求められます。あなたが許可を与えた後、自動的にこの画面に戻ります。</string>
- <string name="authenticate_label">認証</string>
- <string name="return_home_label">ホームに戻る</string>
- <string name="flattr_auth_success">認証が成功しました! アプリからflattrすることができます。</string>
- <string name="no_flattr_token_title">Flattrのトークンが見つかりません</string>
- <string name="no_flattr_token_notification_msg">あなたのflattrアカウントがAntennaPodに接続していないようです。認証するにはここをタップしてください。</string>
- <string name="no_flattr_token_msg">あなたのflattrアカウントがAntennaPodに接続していないようです。アプリからflattrするためにAntennaPodのアカウントに接続するか、またはflattrするためにWebサイトを訪問してください。</string>
- <string name="authenticate_now_label">認証</string>
- <string name="action_forbidden_title">操作は禁止されています</string>
- <string name="action_forbidden_msg">AntennaPodにこの操作をする権限がありません。あなたのアカウントへのAntennaPodのアクセストークンが取り消されたことが考えられます。あなたは再認証するか、またはその代わりにWebサイトを訪問してください。</string>
- <string name="access_revoked_title">アクセスが取り消されました</string>
- <string name="access_revoked_info">あなたのアカウントへのAntennaPodのアクセストークンを取り消しました。処理を完了するには、flattrのWebサイトで、あなたのアカウント設定で承認されたアプリケーションのリストから、このアプリを削除する必要があります。</string>
- <!--Flattr-->
- <string name="flattr_click_success">1 件Flattrしました!</string>
- <string name="flattr_click_success_count">%d 件Flattrしました!</string>
- <string name="flattr_click_success_queue">Flattrしました: %s.</string>
- <string name="flattr_click_failure_count">Flattrに失敗 %d 件!</string>
- <string name="flattr_click_failure">Flattrしませんでした: %s.</string>
- <string name="flattr_click_enqueued">後でFlattrされます</string>
- <string name="flattring_thing">Flattr中 %s</string>
- <string name="flattring_label">AntennaPod がFlattr中</string>
- <string name="flattrd_label">AntennaPod がFlattrしました</string>
- <string name="flattrd_failed_label">AntennaPod はFlattrに失敗しました</string>
- <string name="flattr_retrieving_status">Flattrの取得中</string>
+ <string name="sort_old_to_new">古いものから新しいもの</string>
+ <string name="sort_new_to_old">新しいものから古いもの</string>
<!--Variable Speed-->
<string name="download_plugin_label">プラグインをダウンロード</string>
<string name="no_playback_plugin_title">プラグイン はインストールされていません</string>
@@ -312,7 +295,6 @@
<string name="no_items_header_label">エピソードはキューにありません</string>
<string name="no_items_label">エピソードをダウンロードして追加するか、エピソードを長押しして \"キューに追加\" を選択してください。</string>
<string name="no_feeds_label">まだポッドキャストを何も購読していません。</string>
- <string name="no_chapters_label">このエピソードにチャプターはありません。</string>
<string name="no_shownotes_label">このエピソードにショーノートはありません。</string>
<string name="no_run_downloads_head_label">実行中のダウンロードはありません</string>
<string name="no_run_downloads_label">ポッドキャスト詳細画面でエピソードをダウンロードできます。</string>
@@ -328,6 +310,8 @@
<string name="no_new_episodes_label">新しいエピソードが届くと、ここに表示されます。</string>
<string name="no_fav_episodes_head_label">お気に入りのエピソードはありません</string>
<string name="no_fav_episodes_label">長押ししてお気に入りにエピソードを追加できます。</string>
+ <string name="no_chapters_head_label">チャプターなし</string>
+ <string name="no_chapters_label">このエピソードにチャプターはありません。</string>
<!--Preferences-->
<string name="storage_pref">ストレージ</string>
<string name="project_pref">プロジェクト</string>
@@ -335,8 +319,6 @@
<string name="about_pref">について</string>
<string name="queue_label">キュー</string>
<string name="integrations_label">統合</string>
- <string name="flattr_label">Flattr</string>
- <string name="flattr_summary">マイクロペイメント サービス</string>
<string name="automation">自動</string>
<string name="download_pref_details">詳細</string>
<string name="import_export_pref">インポート/エクスポート</string>
@@ -344,7 +326,10 @@
<string name="appearance">外観</string>
<string name="external_elements">外部要素</string>
<string name="interruptions">割り込み</string>
- <string name="buttons">再生コントロールボタン</string>
+ <string name="playback_control">再生コントロール</string>
+ <string name="preference_search_hint">検索…</string>
+ <string name="preference_search_no_results">結果はありません</string>
+ <string name="preference_search_clear_history">履歴をクリア</string>
<string name="media_player">メディアプレーヤー</string>
<string name="pref_episode_cleanup_title">エピソード クリーンアップ</string>
<string name="pref_episode_cleanup_summary">キューに含まれておらず、お気に入りではないエピソードは、自動ダウンロードで新しいエピソードのためにスペースが必要な場合、除去の対象になります</string>
@@ -381,20 +366,13 @@
<string name="pref_unpauseOnHeadsetReconnect_title">ヘッドフォン再接続</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Bluetooth再接続</string>
<string name="pref_mobileUpdate_title">モバイル更新</string>
- <string name="pref_mobileUpdate_sum">モバイルデータ接続時に更新を許可します</string>
- <string name="pref_mobileUpdate_nothing">なし</string>
- <string name="pref_mobileUpdate_images">画像のみ</string>
- <string name="pref_mobileUpdate_everything">すべて</string>
+ <string name="pref_mobileUpdate_sum">モバイルデータ接続時に許可するものを選択します</string>
+ <string name="pref_mobileUpdate_refresh">フィード更新</string>
+ <string name="pref_mobileUpdate_images">カバー画像</string>
+ <string name="pref_mobileUpdate_auto_download">自動ダウンロード</string>
+ <string name="pref_mobileUpdate_episode_download">エピソードのダウンロード</string>
+ <string name="pref_mobileUpdate_streaming">ストリーミング</string>
<string name="refreshing_label">更新中</string>
- <string name="flattr_settings_label">Flattr設定</string>
- <string name="pref_flattr_auth_title">Flattrにサインイン</string>
- <string name="pref_flattr_auth_sum">アプリから直接Flattrするため、あなたのFlattrアカウントにサインインしてください。</string>
- <string name="pref_flattr_this_app_title">このアプリをFlattr</string>
- <string name="pref_flattr_this_app_sum">FlattrしてAntennaPodの開発を支援してください。ありがとうございます!</string>
- <string name="pref_revokeAccess_title">アクセスを取り消し</string>
- <string name="pref_revokeAccess_sum">あなたのflattrアカウントへのこのアプリのアクセス許可を取り消します。</string>
- <string name="pref_auto_flattr_title">自動Flattr</string>
- <string name="pref_auto_flattr_sum">自動Flattrを構成</string>
<string name="user_interface_label">インターフェース</string>
<string name="pref_set_theme_title">テーマを選択</string>
<string name="pref_nav_drawer_title">ナビゲーションドロワーをカスタマイズ</string>
@@ -416,6 +394,7 @@
<string name="pref_automatic_download_on_battery_sum">バッテリーを充電していない時に自動ダウンロードを許可します</string>
<string name="pref_parallel_downloads_title">パラレル ダウンロード</string>
<string name="pref_episode_cache_title">エピソードキャッシュ</string>
+ <string name="pref_episode_cache_summary">デバイスにキャッシュされたダウンロード済エピソードの合計数。この数に達すると自動ダウンロードが抑制されます。</string>
<string name="pref_theme_title_light">ライト</string>
<string name="pref_theme_title_dark">ダーク</string>
<string name="pref_theme_title_trueblack">黒 (AMOLED 対応)</string>
@@ -441,6 +420,8 @@
<string name="pref_gpodnet_notifications_sum">この設定は、認証エラーには適用されません。</string>
<string name="pref_playback_speed_title">再生速度</string>
<string name="pref_playback_speed_sum">可変速度音声再生に使用可能な速度をカスタマイズします</string>
+ <string name="pref_playback_time_respects_speed_title">メディア情報を再生速度に調整</string>
+ <string name="pref_playback_time_respects_speed_sum">表示される位置と時間が再生速度に調整されます</string>
<string name="pref_fast_forward">早送りのスキップ時間</string>
<string name="pref_fast_forward_sum">早送りボタンがクリックされたときにジャンプする秒数をカスタマイズします</string>
<string name="pref_rewind">巻き戻しスキップ時間</string>
@@ -500,11 +481,6 @@
<string name="back_button_go_to_page_title">ページの選択</string>
<string name="pref_delete_removes_from_queue_title">キューから削除済を削除</string>
<string name="pref_delete_removes_from_queue_sum">削除した時に、自動的にキューからエピソードを削除します</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">自動Flattrを有効にする</string>
- <string name="auto_flattr_after_percent">%d %再生したらエピソードをFlattr </string>
- <string name="auto_flattr_ater_beginning">再生を開始した時にエピソードをFlattr</string>
- <string name="auto_flattr_ater_end">再生が終了した時にエピソードをFlattr</string>
<!--Search-->
<string name="search_hint">エピソードの検索</string>
<string name="found_in_shownotes_label">ショーノートで見つかりました</string>
@@ -595,12 +571,14 @@
<string name="gpodnetsync_error_descr">同期中にエラーが発生しました:\u0020</string>
<string name="gpodnetsync_pref_report_successful">成功しました</string>
<string name="gpodnetsync_pref_report_failed">失敗しました</string>
+ <string name="gpodnetsync_username_characters_error">ユーザー名には文字、数字、ハイフン、下線のみ含めることができます。</string>
<!--Directory chooser-->
<string name="selected_folder_label">選択したフォルダー:</string>
<string name="create_folder_label">フォルダーを作成</string>
<string name="choose_data_directory">データ フォルダーを選択</string>
<string name="choose_data_directory_message">基本のデータフォルダーを選択してください。 AntennaPodは、適切なサブディレクトリを作成します。</string>
<string name="choose_data_directory_permission_rationale">データフォルダーを変更するために外部ストレージのアクセスが必要です</string>
+ <string name="choose_data_directory_available_space">%1$s / %2$s 空き</string>
<string name="create_folder_msg">名前 \"%1$s\" で新しいフォルダーを作成しますか?</string>
<string name="create_folder_success">新しいフォルダーを作成しました</string>
<string name="create_folder_error_no_write_access">このフォルダーに書き込みできません</string>
@@ -641,13 +619,18 @@
<string name="episode_filters_exclude">含まない</string>
<string name="episode_filters_hint">単一の単語 \n\"複数の 単語\"</string>
<string name="keep_updated">更新済を保持</string>
+ <string name="keep_updated_summary">すべてのフィードを (自動)更新する時にこのフィードを含めます</string>
+ <string name="auto_download_disabled_globally">メインの AntennaPod 設定で自動ダウンロードが無効になっています</string>
<!--Progress information-->
<string name="progress_upgrading_database">データベースをアップグレードしています</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">単一目的のアプリから購読をインポート中…</string>
+ <!--Add podcast fragment-->
+ <string name="search_podcast_hint">ポッドキャストの検索…</string>
<string name="search_itunes_label">iTunes を検索</string>
- <string name="filter">フィルター</string>
<string name="search_fyyd_label">fyydを検索</string>
+ <string name="advanced_search">高度な検索</string>
+ <string name="filter">フィルター</string>
<!--Episodes apply actions-->
<string name="all_label">すべて</string>
<string name="selected_all_label">すべてのエピソードを選択しました</string>
@@ -737,4 +720,5 @@
<string name="notification_channel_playing_description">再生をコントロールできます。これはポッドキャスト再生中のメイン通知です。</string>
<string name="notification_channel_error">エラー</string>
<string name="notification_channel_error_description">ダウンロードや gpodder の同期に失敗した場合など、何か問題が発生した場合に表示されます。</string>
+ <string name="import_bad_file">無効/破損ファイル</string>
</resources>
diff --git a/core/src/main/res/values-land/styles.xml b/core/src/main/res/values-land/styles.xml
deleted file mode 100644
index d964ef3d4..000000000
--- a/core/src/main/res/values-land/styles.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <style name="Theme.MediaPlayer" parent="@style/Theme.AppCompat.Light">
- <item name="android:windowActionBarOverlay">true</item>
- </style>
-</resources> \ No newline at end of file
diff --git a/core/src/main/res/values-large/dimens.xml b/core/src/main/res/values-large/dimens.xml
index 2da283c5b..2d107eef0 100644
--- a/core/src/main/res/values-large/dimens.xml
+++ b/core/src/main/res/values-large/dimens.xml
@@ -4,5 +4,4 @@
<dimen name="thumbnail_length">170dp</dimen>
<dimen name="thumbnail_length_queue_item">64dp</dimen>
<dimen name="thumbnail_length_downloaded_item">64dp</dimen>
- <dimen name="queue_title_text_size">@dimen/text_size_medium</dimen>
</resources> \ No newline at end of file
diff --git a/core/src/main/res/values-lt/strings.xml b/core/src/main/res/values-lt/strings.xml
index 4c70f6f33..6abb40435 100644
--- a/core/src/main/res/values-lt/strings.xml
+++ b/core/src/main/res/values-lt/strings.xml
@@ -113,9 +113,6 @@
<string name="mark_all_read_msg">Visi epizodai pažymėti kaip perklausyti</string>
<string name="mark_all_read_confirmation_msg">Patvirtinkite, jog norite pažymėti visus epizodus kaip perklausytus.</string>
<string name="mark_all_read_feed_confirmation_msg">Patvirtinkite, jog norite pažymėti visus šios tinklalaidės epizodus kaip perklausytus.</string>
- <string name="remove_all_new_flags_label">Pažymėti visus kaip matytus</string>
- <string name="removed_all_new_flags_msg">Pažymėti visus epizodus kaip matytus</string>
- <string name="remove_all_new_flags_confirmation_msg">Patvirtinkite, jog norite pažymėti visus epizodus kaip matytus.</string>
<string name="show_info_label">Rodyti informaciją</string>
<string name="show_feed_settings_label">Rodyti tinklalaidės nustatymus</string>
<string name="feed_info_label">Tinklalaidės informacija</string>
@@ -157,8 +154,6 @@
<string name="remove_label">Pašalinti</string>
<string name="delete_label">Ištrinti</string>
<string name="delete_failed">Nepavyksta ištrinti failo. Įrenginio paleidimas iš naujo gali padėti.</string>
- <string name="remove_new_flag_label">Pažymėti kaip matytą</string>
- <string name="removed_new_flag_label">Pažymėtas kaip matytas</string>
<string name="mark_read_label">Pažymėti kaip perklausytą</string>
<string name="marked_as_read_label">Pažymėtas kaip perklausytas</string>
<string name="mark_unread_label">Pažymėti kaip neperklausytą</string>
@@ -170,7 +165,6 @@
<string name="remove_from_favorite_label">Pašalinti iš mėgiamų</string>
<string name="removed_from_favorites">Pašalintas iš mėgiamų</string>
<string name="visit_website_label">Aplankyti svetainę</string>
- <string name="support_label">Paremti „Flattr“</string>
<string name="skip_episode_label">Praleisti epizodą</string>
<string name="activate_auto_download">Įjungti automatinį atsiuntimą</string>
<string name="deactivate_auto_download">Išjungti automatinį atsiuntimą</string>
@@ -258,32 +252,6 @@
<string name="ascending">Didėjančia tvarka</string>
<string name="descending">Mažėjančia tvarka</string>
<string name="clear_queue_confirmation_msg">Patvirtinkite, jog norite pašalinti VISUS epizodus iš perklausos eilės</string>
- <!--Flattr-->
- <string name="flattr_auth_label">„Flattr“ prisijungimas</string>
- <string name="flattr_auth_explanation">Jei norite pradėti tapatumo nustatymo procesą, paspauskite žemiau esantį mygtuką. Būsite nukreipti į „Flattr“ prisijungimo langą naršyklėje ir paprašyti suteikti „AntennaPod“ programėlei leidimą paremti turinį. Kai suteiksite leidimą, būsite automatiškai sugrąžinti į šį ekraną.</string>
- <string name="authenticate_label">Nustatyti tapatumą</string>
- <string name="return_home_label">Grįžti atgal</string>
- <string name="flattr_auth_success">Tapatumas patvirtintas! Nuo šiol programėlėje galėsite paremti epizodus naudodami „Flattr“ paslaugą.</string>
- <string name="no_flattr_token_title">Nerastas „Flattr“ žetonas</string>
- <string name="no_flattr_token_notification_msg">Panašu, jog Jūsų „Flattr“ paskyra nesusieta su „AntennaPod“. Spustelėkite čia, jei norite nustatyti tapatybę.</string>
- <string name="no_flattr_token_msg">Panašu, jog Jūsų „Flattr“ paskyra nėra susieta su „AntennaPod“. Galite susieti savo paskyrą su „AntennaPod“, jei norite paremti turinį naudodamiesi programėle, arba paremkite elementą apsilankę jo svetainėje.</string>
- <string name="authenticate_now_label">Tikrinti tapatumą</string>
- <string name="action_forbidden_title">Veiksmas uždraustas</string>
- <string name="action_forbidden_msg">„AntennaPod“ neturi leidimo šiam veiksmui atlikti. Gali būti, jog „AntennaPod“ prieigos žetono galiojimas buvo sustabdytas. Galite iš naujo patvirtinti tapatybę arba aplankyti elemento svetainę.</string>
- <string name="access_revoked_title">Prieiga panaikinta</string>
- <string name="access_revoked_info">Sėkmingai sustabdėte „AntennaPod“ prieigos prie Jūsų paskyros žetono galiojimą. Jei norite užbaigti šį procesą, pašalinkite šią programėlę iš patvirtintų programėlių sąrašo paskyros nustatymuose „Flattr“ svetainėje.</string>
- <!--Flattr-->
- <string name="flattr_click_success">Vienas elementas paremtas „Flattr“!</string>
- <string name="flattr_click_success_count">%d elementai paremti „Flattr“!</string>
- <string name="flattr_click_success_queue">Paremta „Flattr“: %s.</string>
- <string name="flattr_click_failure_count">„Flattr“ nepavyko paremti %d elementų!</string>
- <string name="flattr_click_failure">„Flattr“ neparemta: %s.</string>
- <string name="flattr_click_enqueued">Šis elementas bus paremtas „Flattr“ vėliau</string>
- <string name="flattring_thing">Remiama „Flattr“: %s</string>
- <string name="flattring_label">„AntennaPod“ šiuo metu paremia „Flattr“</string>
- <string name="flattrd_label">„AntennaPod“ parama „Flattr“ pavyko</string>
- <string name="flattrd_failed_label">„AntennaPod“ parama „Flattr“ nepavyko</string>
- <string name="flattr_retrieving_status">Nuskaitomi „Flattr“ paremti elementai</string>
<!--Variable Speed-->
<string name="download_plugin_label">Atsiųsti įskiepį</string>
<string name="no_playback_plugin_title">Įskiepis neįdiegtas</string>
@@ -292,8 +260,8 @@
<string name="enable_sonic">Įjungti „Sonic“</string>
<!--Empty list labels-->
<string name="no_feeds_label">Kol kas neprenumeruojate jokios tinklalaidės.</string>
- <string name="no_chapters_label">Šis epizodas neturi skyrių.</string>
<string name="no_shownotes_label">Šis epizodas neturi užrašų.</string>
+ <string name="no_chapters_label">Šis epizodas neturi skyrių.</string>
<!--Preferences-->
<string name="storage_pref">Laikmena</string>
<string name="project_pref">Projektas</string>
@@ -301,15 +269,12 @@
<string name="about_pref">Apie</string>
<string name="queue_label">Eilė</string>
<string name="integrations_label">Integracijos</string>
- <string name="flattr_label">Flattr</string>
- <string name="flattr_summary">Mikromokėjimų paslauga</string>
<string name="automation">Automatizacija</string>
<string name="download_pref_details">Išsamiau</string>
<string name="import_export_pref">Importas/Eksportas</string>
<string name="appearance">Išvaizda</string>
<string name="external_elements">Išoriniai elementai</string>
<string name="interruptions">Pertraukimai</string>
- <string name="buttons">Atkūrimo valdymo mygtukai</string>
<string name="media_player">Medijos grotuvas</string>
<string name="pref_episode_cleanup_title">Epizodų valymas</string>
<string name="pref_episode_cleanup_summary">Epizodai, nesantys eilėje ar tarp mėgiamųjų, gali būti ištrinti automatinio atsiuntimo metu pritrūkus laisvos vietos naujiems epizodams </string>
@@ -346,17 +311,7 @@
<string name="pref_unpauseOnHeadsetReconnect_title">Pakartotinai prijungus ausines</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Pakartotinai prisijungus prie „Bluetooth“</string>
<string name="pref_mobileUpdate_title">Atnaujinimai mobiliuoju internetu</string>
- <string name="pref_mobileUpdate_sum">Leisti atnaujinimus mobiliuoju internetu</string>
<string name="refreshing_label">Atnaujinama</string>
- <string name="flattr_settings_label">„Flattr“ nustatymai</string>
- <string name="pref_flattr_auth_title">„Flattr“ prisijungimas</string>
- <string name="pref_flattr_auth_sum">Prisijunkite prie savo „Flattr“ paskyros ir remkite turinį tiesiai iš programėlės</string>
- <string name="pref_flattr_this_app_title">Paremti šią programėlę per „Flattr“</string>
- <string name="pref_flattr_this_app_sum">Paskatinkite „AntennaPod“ tobulinimą paremdami ją per „Flattr“. Ačiū!</string>
- <string name="pref_revokeAccess_title">Panaikinti prieigą</string>
- <string name="pref_revokeAccess_sum">Panaikinti šios programėlės prieigos prie Jūsų „Flattr“ paskyros leidimą. </string>
- <string name="pref_auto_flattr_title">Automatinis rėmimas per „Flattr“</string>
- <string name="pref_auto_flattr_sum">Konfigūruoti automatinį rėmimą per „Flattr“</string>
<string name="user_interface_label">Vartotojo sąsaja</string>
<string name="pref_set_theme_title">Pasirinkti temą</string>
<string name="pref_nav_drawer_title">Derinti naršymo stalčių</string>
@@ -459,11 +414,6 @@
<string name="double_tap_toast">Jei norite išeiti, dar kartą paspauskite grįžimo mygtuką</string>
<string name="back_button_go_to_page">Eiti į puslapį…</string>
<string name="back_button_go_to_page_title">Pažymėti puslapį</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">Įjungti automatinį rėmimą „Flattr“</string>
- <string name="auto_flattr_after_percent">Paremti epizodą „Flattr“ perklausius %d procentus jo trukmės</string>
- <string name="auto_flattr_ater_beginning">Paremti epizodą „Flattr“ atkūrimui prasidėjus</string>
- <string name="auto_flattr_ater_end">Paremti epizodą „Flattr“ atkūrimui pasibaigus</string>
<!--Search-->
<string name="search_hint">Ieškoti epizodų</string>
<string name="found_in_shownotes_label">Rasta laidos užrašuose</string>
@@ -613,9 +563,10 @@
<string name="progress_upgrading_database">Atnaujinama duomenų bazė</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Įkeliamos prenumeratos iš specializuotų programėlių...</string>
+ <!--Add podcast fragment-->
<string name="search_itunes_label">Ieškoti „iTunes“</string>
- <string name="filter">Filtruoti</string>
<string name="search_fyyd_label">Ieškoti „fyyd“</string>
+ <string name="filter">Filtruoti</string>
<!--Episodes apply actions-->
<string name="all_label">Visi</string>
<string name="selected_all_label">Pažymėti visi epizodai</string>
diff --git a/core/src/main/res/values-nb/strings.xml b/core/src/main/res/values-nb/strings.xml
index c7684322c..da6e1c0ae 100644
--- a/core/src/main/res/values-nb/strings.xml
+++ b/core/src/main/res/values-nb/strings.xml
@@ -103,8 +103,6 @@
<string name="mark_all_read_label">Marker alle som avspilt</string>
<string name="mark_all_read_msg">Marker alle episoder som avspilt</string>
<string name="mark_all_read_confirmation_msg">Vennligst bekreft at du ønsker å markere alle episoder som avspilt.</string>
- <string name="remove_all_new_flags_label">Marker alle som sett</string>
- <string name="remove_all_new_flags_confirmation_msg">Bekreft at du ønsker å markere alle episoder som sett.</string>
<string name="show_info_label">Vis informasjon</string>
<string name="share_label">Del ...</string>
<string name="share_file_label">Del fil</string>
@@ -130,7 +128,6 @@
<string name="remove_label">Fjern</string>
<string name="delete_label">Slett</string>
<string name="delete_failed">Kan ikke slette filen. Omstart av enheten kan hjelpe.</string>
- <string name="removed_new_flag_label">Marker som sett</string>
<string name="mark_read_label">Marker som avspilt</string>
<string name="marked_as_read_label">Marker som avspilt</string>
<string name="mark_unread_label">Marker som ikke avspilt</string>
@@ -142,7 +139,6 @@
<string name="remove_from_favorite_label">Fjern fra favoritter</string>
<string name="removed_from_favorites">Fjernet fra favoritter</string>
<string name="visit_website_label">Besøk nettside</string>
- <string name="support_label">Flattr\'e dette</string>
<string name="skip_episode_label">Skip episode</string>
<string name="activate_auto_download">Aktiver automatisk nedlasting</string>
<string name="deactivate_auto_download">Deaktiver automatisk nedlasting</string>
@@ -218,47 +214,20 @@
<string name="ascending">Økende</string>
<string name="descending">Synkende</string>
<string name="clear_queue_confirmation_msg">Vennligst bekreft at du ønsker å slette ALLE elementer i køen</string>
- <!--Flattr-->
- <string name="flattr_auth_label">Flattr innlogging</string>
- <string name="flattr_auth_explanation">Trykk knappen nedenfor for å starte autentiseringsprosessen. Du vil videresendes til flattr sin innloggsinsskjerm i din nettleser og spurt om å gi AntennaPod tillatelse til å flattr\'e ting. Etter at du har gitt tillatelse blir du returnert hit automatisk.</string>
- <string name="authenticate_label">Autentiser</string>
- <string name="return_home_label">Returner hjem</string>
- <string name="flattr_auth_success">Autentisering fullført! Nå kan du flattr tingene i denne appen.</string>
- <string name="no_flattr_token_title">Flattr-token ikke funnet</string>
- <string name="no_flattr_token_notification_msg">Det virker som at Flattr-kontoen din ikke er sammenkoblet med AntennaPod. Trykk her for å autentisere.</string>
- <string name="no_flattr_token_msg">Det virker ikke som din flattr konto er koblet til AntennaPod. Du kan enten koble kontoen din til AntennaPod for å flattr\'e ting i appen eller du kan besøke nettsiden til tingen for å flattr\'e det der.</string>
- <string name="authenticate_now_label">Autentiser</string>
- <string name="action_forbidden_title">Handling forbudt</string>
- <string name="action_forbidden_msg">AntennaPod har ikke tilgang til denne handlingen. Grunnen kan være at tilgangstokenet til kontoen din er blitt inndratt. Du kan enten re-autentisere eller besøke tjenestens nettsted.</string>
- <string name="access_revoked_title">Tilgang opphevet</string>
- <string name="access_revoked_info">Du har fjernet AntennaPods tilgang til kontoen din. For å fullføre prossessen må du fjerne denne appen fra listen over tillatte apper på flattr-nettsiden.</string>
- <!--Flattr-->
- <string name="flattr_click_success">Flattr\'erte en ting!</string>
- <string name="flattr_click_success_count">Flattret %d ting!</string>
- <string name="flattr_click_success_queue">Flattret: %s.</string>
- <string name="flattr_click_failure_count">Klarte ikke flattre %d ting!</string>
- <string name="flattr_click_failure">Ikke flattret: %s.</string>
- <string name="flattr_click_enqueued">Tingen vil bli flattret senere</string>
- <string name="flattring_thing">Flattrer %s</string>
- <string name="flattring_label">AntennaPod flattrer</string>
- <string name="flattrd_label">AntennaPod har flattret</string>
- <string name="flattrd_failed_label">AntennaPods flattring feilet</string>
- <string name="flattr_retrieving_status">Henter flattrede ting</string>
<!--Variable Speed-->
<string name="download_plugin_label">Last ned programtillegg</string>
<string name="no_playback_plugin_title">Programtillegg er ikke installert</string>
<string name="set_playback_speed_label">Avspillingshastigheter</string>
<string name="enable_sonic">Skru på Sonic</string>
<!--Empty list labels-->
- <string name="no_chapters_label">Denne episoden har ingen kapitler.</string>
<string name="no_shownotes_label">Denne episoden har ingen shownotater</string>
+ <string name="no_chapters_label">Denne episoden har ingen kapitler.</string>
<!--Preferences-->
<string name="storage_pref">Lagring</string>
<string name="project_pref">Prosjekt</string>
<string name="other_pref">Annet</string>
<string name="about_pref">Om</string>
<string name="queue_label">Kø</string>
- <string name="flattr_label">Flattr</string>
<string name="pref_episode_cleanup_title">Episodeopprydding</string>
<string name="pref_pauseOnDisconnect_sum">Sett playback på pause når hodetelefoner eller bluetooth er frakoblet</string>
<string name="pref_unpauseOnHeadsetReconnect_sum">Gjenoppta avspilling når hodetelefoner gjeninnkoples</string>
@@ -290,17 +259,7 @@
<string name="pref_unpauseOnHeadsetReconnect_title">Gjeninnkopling av hodetelefoner</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Blutetooth tilkoblet igjen</string>
<string name="pref_mobileUpdate_title">Mobiloppdateringer</string>
- <string name="pref_mobileUpdate_sum">Tillat oppdateringer over kobling via mobildata</string>
<string name="refreshing_label">Oppdaterer</string>
- <string name="flattr_settings_label">Flattr innstillinger</string>
- <string name="pref_flattr_auth_title">Flattr logg in</string>
- <string name="pref_flattr_auth_sum">Logg på din flattr konto for å flattr ting direkte fra appen.</string>
- <string name="pref_flattr_this_app_title">Flattr denne appen</string>
- <string name="pref_flattr_this_app_sum">Støtt utviklingen av AntennaPod ved å flattr\'e det. Tusen takk!</string>
- <string name="pref_revokeAccess_title">Opphev tilgang</string>
- <string name="pref_revokeAccess_sum">Opphev tilgangstillatelsen til din flattr konto for denne appen.</string>
- <string name="pref_auto_flattr_title">Automatisk Flattr</string>
- <string name="pref_auto_flattr_sum">Konfigurer automatisk flattring</string>
<string name="user_interface_label">Brukergrensesnitt</string>
<string name="pref_set_theme_title">Velg tema</string>
<string name="pref_nav_drawer_title">Skreddersy navigasjonsskuff</string>
@@ -366,11 +325,6 @@
<string name="pref_no_browser_found">Ingen nettleser funnet.</string>
<string name="pref_cast_title">Chromecast støtte</string>
<string name="pref_enqueue_downloaded_summary">Legg til nedlastede episoder i køen</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">Aktiver automatisk flattring</string>
- <string name="auto_flattr_after_percent">Flattre episode så snart %d prosent er avspilt</string>
- <string name="auto_flattr_ater_beginning">Flattre episode når avspillingen starter</string>
- <string name="auto_flattr_ater_end">Flattre episode når avspillingen tar slutt</string>
<!--Search-->
<string name="search_hint">Søk etter episoder</string>
<string name="found_in_chapters_label">Funnet i kapitler</string>
@@ -507,6 +461,7 @@
<string name="progress_upgrading_database">Oppgraderer databasen</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Importerer abbonementer fra enkeltstående applikasjoner ...</string>
+ <!--Add podcast fragment-->
<string name="search_itunes_label">Søk på iTunes</string>
<string name="filter">Filter</string>
<!--Episodes apply actions-->
diff --git a/core/src/main/res/values-nl/strings.xml b/core/src/main/res/values-nl/strings.xml
index 22f9f6045..d406b13e8 100644
--- a/core/src/main/res/values-nl/strings.xml
+++ b/core/src/main/res/values-nl/strings.xml
@@ -31,7 +31,7 @@
<string name="statistics_details_dialog">%1$d van %2$d afleveringen gestart.\n\n%3$s van %4$s afgespeeld.</string>
<string name="statistics_mode">Rekenmethode</string>
<string name="statistics_mode_normal">Bereken de daadwerkelijke speeltijd. Tweemaal afspelen wordt twee keer gerekend; gemarkeerd als \'afgespeeld\' wordt niet meegeteld.</string>
- <string name="statistics_mode_count_all">Duur van de podcasts optellen die gemarkeerd zijn als \'afgespeeld\' zijn</string>
+ <string name="statistics_mode_count_all">Duur van de podcasts optellen die als \'afgespeeld\' gemarkeerd zijn</string>
<string name="statistics_speed_not_counted">Let op: er wordt geen rekening gehouden met de afspeelsnelheid.</string>
<!--Main activity-->
<string name="drawer_open">Menu openen</string>
@@ -111,14 +111,16 @@
<string name="podcastdirectories_label">Podcast zoeken in de gids</string>
<string name="podcastdirectories_descr">Je kunt nieuwe podcasts vinden op naam, categorie of populariteit in de gpodder.net-databank of via iTunes of fyyd.</string>
<string name="browse_gpoddernet_label">Blader door gpodder.net</string>
+ <string name="discover">Ontdekken</string>
+ <string name="discover_more">meer »</string>
<!--Actions on feeds-->
<string name="mark_all_read_label">Alles markeren als afgespeeld</string>
<string name="mark_all_read_msg">Alle afleveringen zijn gemarkeerd als afgespeeld</string>
<string name="mark_all_read_confirmation_msg">Bevestig dat je alle afleveringen wilt markeren als afgespeeld.</string>
<string name="mark_all_read_feed_confirmation_msg">Bevestig dat je alle afleveringen van deze podcast wilt markeren als afgespeeld.</string>
- <string name="remove_all_new_flags_label">Alles markeren als bekeken</string>
- <string name="removed_all_new_flags_msg">Alle afleveringen zijn gemarkeerd als bekeken</string>
- <string name="remove_all_new_flags_confirmation_msg">Bevestig dat je alle afleveringen wilt markeren als bekeken.</string>
+ <string name="remove_all_new_flags_label">Alle labels met \"nieuw\" verwijderen</string>
+ <string name="removed_all_new_flags_msg">Alle labels met \"nieuw\" zijn verwijderd</string>
+ <string name="remove_all_new_flags_confirmation_msg">Bevestig dat je alle labels met \"nieuw\" wilt verwijderen bij alle afleveringen.</string>
<string name="show_info_label">Informatie tonen</string>
<string name="show_feed_settings_label">Podcast-instellingen tonen</string>
<string name="feed_info_label">Podcast-informatie</string>
@@ -126,12 +128,12 @@
<string name="rename_feed_label">Podcastnaam wijzigen</string>
<string name="remove_feed_label">Podcast verwijderen</string>
<string name="share_label">Delen...</string>
- <string name="share_link_label">URL van aflevering delen</string>
- <string name="share_link_with_position_label">URL van aflevering delen, op specifieke positie</string>
+ <string name="share_link_label">URL aflevering</string>
+ <string name="share_link_with_position_label">URL aflevering, met tijdstip</string>
<string name="share_file_label">Bestand delen</string>
- <string name="share_feed_url_label">URL van feed delen</string>
- <string name="share_item_url_label">URL van mediabestand delen</string>
- <string name="share_item_url_with_position_label">URL van mediabestand delen, op specifieke positie</string>
+ <string name="share_feed_url_label">URL podcast</string>
+ <string name="share_item_url_label">URL mediabestand</string>
+ <string name="share_item_url_with_position_label">URL mediabestand delen, met tijdstip</string>
<string name="feed_delete_confirmation_msg">Bevestig dat je de podcast \"%1$s\" en ALLE (ook gedownloade) bijbehorende afleveringen wilt verwijderen.</string>
<string name="feed_remover_msg">Podcast verwijderen</string>
<string name="load_complete_feed">Gehele podcast verversen</string>
@@ -169,8 +171,8 @@
<item quantity="one">%d aflevering verwijderd.</item>
<item quantity="other">%d afleveringen verwijderd.</item>
</plurals>
- <string name="remove_new_flag_label">Markeren als bekeken</string>
- <string name="removed_new_flag_label">Gemarkeerd als bekeken</string>
+ <string name="remove_new_flag_label">Label met \"nieuw\" verwijderen</string>
+ <string name="removed_new_flag_label">Label met \"nieuw\" is verwijderd</string>
<string name="mark_read_label">Markeren als afgespeeld</string>
<string name="marked_as_read_label">Gemarkeerd als afgespeeld</string>
<plurals name="marked_read_batch_label">
@@ -198,7 +200,6 @@
<string name="remove_from_favorite_label">Verwijderen uit favorieten</string>
<string name="removed_from_favorites">Verwijderd uit favorieten</string>
<string name="visit_website_label">Website bezoeken</string>
- <string name="support_label">Flattr dit</string>
<string name="skip_episode_label">Aflevering overslaan</string>
<string name="activate_auto_download">Automatisch downloaden activeren</string>
<string name="deactivate_auto_download">Automatisch downloaden de-activeren</string>
@@ -250,6 +251,9 @@
<string name="confirm_mobile_download_dialog_title">Bevestig downloaden via mobiel internet</string>
<string name="confirm_mobile_download_dialog_message_not_in_queue">Downloaden via mobiel internet is uitgeschakeld in de instellingen.\n\nJe kunt er voor kiezen om de aflevering alleen toe te voegen aan de wachtrij of om downloaden via mobiele internet tijdelijk toe te staan.\n<small>Je keuze wordt 10 minuten onthouden.</small></string>
<string name="confirm_mobile_download_dialog_message">Downloaden via mobiel internet is uitgeschakeld in de instellingen.\n\nWil je dit tijdelijk toestaan?\n<small>Je keuze wordt 10 minuten onthouden.</small></string>
+ <string name="confirm_mobile_streaming_notification_title">Bevestig streamen via mobiel internet</string>
+ <string name="confirm_mobile_streaming_notification_message">Streamen via mobiel internet is uitgeschakeld in de instellingen. Druk om tóch te streamen.</string>
+ <string name="confirm_mobile_streaming_button_always">Altijd toestaan</string>
<string name="confirm_mobile_download_dialog_only_add_to_queue">Toevoegen aan wachtrij</string>
<string name="confirm_mobile_download_dialog_enable_temporarily">Tijdelijk toestaan</string>
<!--Mediaplayer messages-->
@@ -259,6 +263,8 @@
<string name="player_ready_msg">Klaar</string>
<string name="player_seeking_msg">Bezig met zoeken</string>
<string name="playback_error_server_died">Serververbinding verbroken</string>
+ <string name="playback_error_unsupported">Niet-ondersteund bestandstype</string>
+ <string name="playback_error_timeout">Operatie verlopen</string>
<string name="playback_error_unknown">Onbekende fout</string>
<string name="no_media_playing_label">Geen media aan het afspelen</string>
<string name="player_buffering_msg">Bezig met bufferen</string>
@@ -276,6 +282,7 @@
<string name="move_to_top_label">Naar boven verplaatsen</string>
<string name="move_to_bottom_label">Naar beneden verplaatsen</string>
<string name="sort">Sorteren</string>
+ <string name="keep_sorted">Gesorteerd houden</string>
<string name="date">Datum</string>
<string name="duration">Duur</string>
<string name="episode_title">Afleveringstitel</string>
@@ -285,32 +292,8 @@
<string name="ascending">Oplopend</string>
<string name="descending">Aflopend</string>
<string name="clear_queue_confirmation_msg">Bevestig dat je ALLE afleveringen wilt verwijderen uit de wachtrij</string>
- <!--Flattr-->
- <string name="flattr_auth_label">Inloggen op Flattr</string>
- <string name="flattr_auth_explanation">Druk op onderstaande knop om het verificatieproces te starten. Het Flattr-inlogscherm wordt geopend in je browser en je wordt gevraagd om AntennaPod te machtigingen om dingen te Flattr\'en. Daarna keer je automatisch terug naar dit scherm.</string>
- <string name="authenticate_label">Authenticeren</string>
- <string name="return_home_label">Terug naar startscherm</string>
- <string name="flattr_auth_success">Authenticatie geslaagd! Je kunt nu dingen vanuit de app Flattr\'en.</string>
- <string name="no_flattr_token_title">Geen Flattr-toegangssleutel gevonden</string>
- <string name="no_flattr_token_notification_msg">Het lijkt er op dat je Flattr-account niet gekoppeld is aan AntennaPod. Druk hier om te authenticeren.</string>
- <string name="no_flattr_token_msg">Je Flattr-account lijkt niet gekoppeld te zijn aan AntennaPod. Je kunt je account koppelen om dingen vanuit de app te Flattr\'en, of je kunt op de website van het ding terecht om het daar te Flattr\'en.</string>
- <string name="authenticate_now_label">Authenticeren</string>
- <string name="action_forbidden_title">Niet toegestaan</string>
- <string name="action_forbidden_msg">AntennaPod heeft geen toestemming voor deze actie. De reden hiervoor zou kunnen zijn dat de toegangssleutel van AntennaPod voor je account is ingetrokken. Je kunt opnieuw authenticeren, of de website van het ding bezoeken.</string>
- <string name="access_revoked_title">Toegang ingetrokken</string>
- <string name="access_revoked_info">Je heb de toegangssleutel van AntennaPod tot je account ingetrokken. Om het proces te voltooien, moet je deze app verwijderen uit de lijst met goedgekeurde applicaties in je accountinstellingen op de Flattr-website.</string>
- <!--Flattr-->
- <string name="flattr_click_success">Een ding geflattr\'d!</string>
- <string name="flattr_click_success_count">%d dingen geflattr\'d!</string>
- <string name="flattr_click_success_queue">Geflattr\'d: %s.</string>
- <string name="flattr_click_failure_count">Kan %d dingen niet flattr\'n!</string>
- <string name="flattr_click_failure">Niet geflattr\'d: %s.</string>
- <string name="flattr_click_enqueued">Ding wordt later geflattr\'d</string>
- <string name="flattring_thing">Bezig met flattr\'n van%s</string>
- <string name="flattring_label">AntennaPod is aan het flattren</string>
- <string name="flattrd_label">AntennaPod heeft geflattr\'d</string>
- <string name="flattrd_failed_label">AntennaPod-flattr mislukt</string>
- <string name="flattr_retrieving_status">Bezig met ontvangen van geflattr\'de dingen</string>
+ <string name="sort_old_to_new">Oudste eerst</string>
+ <string name="sort_new_to_old">Nieuwste eerst</string>
<!--Variable Speed-->
<string name="download_plugin_label">Plug-in downloaden</string>
<string name="no_playback_plugin_title">Plug-in niet geïnstalleerd</string>
@@ -321,7 +304,6 @@
<string name="no_items_header_label">Geen afleveringen in wachtrij</string>
<string name="no_items_label">Voeg een aflevering toe door deze te downloaden of houd een aflevering lang ingedrukt en kies \'Toevoegen aan wachtrij\'.</string>
<string name="no_feeds_label">Je hebt nog geen abonnement op een podcast.</string>
- <string name="no_chapters_label">Deze aflevering bevat geen hoofdstukken.</string>
<string name="no_shownotes_label">Deze aflevering bevat geen shownotities.</string>
<string name="no_run_downloads_head_label">Geen actieve downloads</string>
<string name="no_run_downloads_label">Je kunt afleveringen downloaden op het podcastinformatiescherm.</string>
@@ -337,6 +319,8 @@
<string name="no_new_episodes_label">Als er nieuwe afleveringen zijn, dan verschijnen ze hier.</string>
<string name="no_fav_episodes_head_label">Geen favoriete afleveringen</string>
<string name="no_fav_episodes_label">Je kunt afleveringen toevoegen aan je favorieten door ze lang ingedrukt te houden.</string>
+ <string name="no_chapters_head_label">Geen hoofdstukken</string>
+ <string name="no_chapters_label">Deze aflevering bevat geen hoofdstukken.</string>
<!--Preferences-->
<string name="storage_pref">Opslag</string>
<string name="project_pref">Project</string>
@@ -344,8 +328,6 @@
<string name="about_pref">Over AntennaPod</string>
<string name="queue_label">Wachtrij</string>
<string name="integrations_label">Integraties</string>
- <string name="flattr_label">Flattr</string>
- <string name="flattr_summary">Dienst voor microbetalingen</string>
<string name="automation">Automatische acties</string>
<string name="download_pref_details">Details</string>
<string name="import_export_pref">Importeren/Exporteren</string>
@@ -353,7 +335,10 @@
<string name="appearance">Uiterlijk</string>
<string name="external_elements">Externe elementen</string>
<string name="interruptions">Onderbrekingen</string>
- <string name="buttons">Knoppen voor afspeelbediening</string>
+ <string name="playback_control">Afspeelbediening</string>
+ <string name="preference_search_hint">Zoeken...</string>
+ <string name="preference_search_no_results">Geen resultaten</string>
+ <string name="preference_search_clear_history">Geschiedenis wissen</string>
<string name="media_player">Mediaspeler</string>
<string name="pref_episode_cleanup_title">Automatisch opschonen</string>
<string name="pref_episode_cleanup_summary">Afleveringen die niet op de wachtrij staan én geen favoriet zijn, mogen verwijderd worden als Automatisch downloaden ruimte nodig heeft voor nieuwe afleveringen</string>
@@ -390,20 +375,13 @@
<string name="pref_unpauseOnHeadsetReconnect_title">Opnieuw aansluiten van hoofdtelefoon</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Opnieuw verbinden met Bluetooth</string>
<string name="pref_mobileUpdate_title">Bijwerken via mobiel internet</string>
- <string name="pref_mobileUpdate_sum">Bijwerken toestaan via mobiele internetverbinding</string>
- <string name="pref_mobileUpdate_nothing">Niets</string>
- <string name="pref_mobileUpdate_images">Alleen afbeeldingen</string>
- <string name="pref_mobileUpdate_everything">Alles</string>
+ <string name="pref_mobileUpdate_sum">Kies wat je wilt toestaan via mobiel internet</string>
+ <string name="pref_mobileUpdate_refresh">Feedverversing</string>
+ <string name="pref_mobileUpdate_images">Omslagafbeeldingen</string>
+ <string name="pref_mobileUpdate_auto_download">Automatisch downloaden</string>
+ <string name="pref_mobileUpdate_episode_download">Hoofdstuk downloaden</string>
+ <string name="pref_mobileUpdate_streaming">Streamen</string>
<string name="refreshing_label">Bezig met verversen...</string>
- <string name="flattr_settings_label">Flattr-instellingen</string>
- <string name="pref_flattr_auth_title">Inloggen op Flattr</string>
- <string name="pref_flattr_auth_sum">Log in op je Flattr-account om dingen vanuit de app te flattr\'en.</string>
- <string name="pref_flattr_this_app_title">Flattr deze app</string>
- <string name="pref_flattr_this_app_sum">Ondersteun de ontwikkeling van AntennaPod door te flattr\'en. Bedankt!</string>
- <string name="pref_revokeAccess_title">Machtiging intrekken</string>
- <string name="pref_revokeAccess_sum">Trek de machtiging van deze app in op je Flattr account.</string>
- <string name="pref_auto_flattr_title">Automatisch flattr\'en</string>
- <string name="pref_auto_flattr_sum">Automatisch flattr\'en instellen</string>
<string name="user_interface_label">Uiterlijk</string>
<string name="pref_set_theme_title">Thema kiezen</string>
<string name="pref_nav_drawer_title">Navigatiemenu aanpassen</string>
@@ -425,6 +403,7 @@
<string name="pref_automatic_download_on_battery_sum">Downloaden toestaan als het apparaat niet wordt opgeladen</string>
<string name="pref_parallel_downloads_title">Gelijktijdige downloads</string>
<string name="pref_episode_cache_title">Afleveringscache</string>
+ <string name="pref_episode_cache_summary">Het totaal aantal gedownloade afleveringen dat moet worden opgeslagen op het apparaat. Automatische downloads worden onderbroken als dit aantal wordt bereikt.</string>
<string name="pref_theme_title_light">Licht</string>
<string name="pref_theme_title_dark">Donker</string>
<string name="pref_theme_title_trueblack">Zwart (geschikt voor AMOLED)</string>
@@ -450,6 +429,8 @@
<string name="pref_gpodnet_notifications_sum">Deze instelling is niet van toepassing op inlogfouten.</string>
<string name="pref_playback_speed_title">Afspeelsnelheden</string>
<string name="pref_playback_speed_sum">Pas de beschikbare snelheden aan voor de variabele audio-afspeelsnelheid</string>
+ <string name="pref_playback_time_respects_speed_title">Media-informatie aanpassen aan afspeelsnelheid</string>
+ <string name="pref_playback_time_respects_speed_sum">Getoonde positie en duur worden aangepast aan de afspeelsnelheid</string>
<string name="pref_fast_forward">Snelheid van vooruitspoelen</string>
<string name="pref_fast_forward_sum">Pas het aantal seconden aan waarmee wordt vooruitgespoeld per druk op de knop</string>
<string name="pref_rewind">Snelheid van terugspoelen</string>
@@ -509,11 +490,6 @@
<string name="back_button_go_to_page_title">Kies een pagina</string>
<string name="pref_delete_removes_from_queue_title">Afleveringen verwijderen uit wachtrij na wissen</string>
<string name="pref_delete_removes_from_queue_sum">Verwijder een aflevering uit de wachtrij als de aflevering in kwestie is verwijderd.</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">Automatisch flattr\'en inschakelen</string>
- <string name="auto_flattr_after_percent">Flattr een aflevering zodra deze %d procent is afgespeeld</string>
- <string name="auto_flattr_ater_beginning">Flattr de aflevering als het afspelen begint</string>
- <string name="auto_flattr_ater_end">Flattr de aflevering als afspelen is gestopt</string>
<!--Search-->
<string name="search_hint">Zoeken naar afleveringen</string>
<string name="found_in_shownotes_label">Gevonden in de shownotities</string>
@@ -607,12 +583,14 @@
<string name="gpodnetsync_error_descr">Er is een fout opgetreden tijdens het synchroniseren:\u0020</string>
<string name="gpodnetsync_pref_report_successful">Voltooid</string>
<string name="gpodnetsync_pref_report_failed">Mislukt</string>
+ <string name="gpodnetsync_username_characters_error">Gebruikersnamen mogen alleen letters, cijfers en (onderliggende) streepjes bevatten.</string>
<!--Directory chooser-->
<string name="selected_folder_label">Gekozen map:</string>
<string name="create_folder_label">Map creëren</string>
<string name="choose_data_directory">Kies de gegevensmap</string>
<string name="choose_data_directory_message">Kies de hoofdmap voor je gegevens. AntennaPod zal de benodigde submappen creëren.</string>
<string name="choose_data_directory_permission_rationale">Toegang tot externe opslag is nodig om de gegevensmap te wijzigen</string>
+ <string name="choose_data_directory_available_space">%1$s van %2$s beschikbaar</string>
<string name="create_folder_msg">Wil je een nieuwe map creëren met de naam \"%1$s\"?</string>
<string name="create_folder_success">Nieuwe map gecreëerd</string>
<string name="create_folder_error_no_write_access">Kan niet schrijven naar map</string>
@@ -653,13 +631,18 @@
<string name="episode_filters_exclude">Uitsluiten</string>
<string name="episode_filters_hint">Losse woorden \n\"Meerdere tussen aanhalingstekens\"</string>
<string name="keep_updated">Bijgewerkt houden</string>
+ <string name="keep_updated_summary">Deze feed meenemen bij het (automatisch) verversen van alle feeds</string>
+ <string name="auto_download_disabled_globally">Automatisch downloaden is uitgeschakeld in de AntennaPod-instellingen</string>
<!--Progress information-->
<string name="progress_upgrading_database">Bezig met upgraden van databank...</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Bezig met importeren van abonnementen uit eenmalige apps...</string>
+ <!--Add podcast fragment-->
+ <string name="search_podcast_hint">Podcast zoeken...</string>
<string name="search_itunes_label">iTunes doorzoeken</string>
- <string name="filter">Filter</string>
<string name="search_fyyd_label">Fyyd doorzoeken</string>
+ <string name="advanced_search">Geavanceerd zoeken</string>
+ <string name="filter">Filter</string>
<!--Episodes apply actions-->
<string name="all_label">Alle</string>
<string name="selected_all_label">Alle afleveringen geselecteerd</string>
@@ -749,4 +732,5 @@
<string name="notification_channel_playing_description">Hiermee kun je het afspelen bedienen. Dit is de voornaamste melding tijdens het afspelen van een podcast.</string>
<string name="notification_channel_error">Foutmeldingen</string>
<string name="notification_channel_error_description">Tonen als er iets is misgegaan, bijvoorbeeld als downloaden of synchroniseren mislukt is.</string>
+ <string name="import_bad_file">Ongeldig/Foutief bestand</string>
</resources>
diff --git a/core/src/main/res/values-pl-rPL/strings.xml b/core/src/main/res/values-pl-rPL/strings.xml
index 7cbe3015a..3ebdbe487 100644
--- a/core/src/main/res/values-pl-rPL/strings.xml
+++ b/core/src/main/res/values-pl-rPL/strings.xml
@@ -7,6 +7,7 @@
<string name="add_feed_label">Dodaj podcast</string>
<string name="episodes_label">Odcinki</string>
<string name="all_episodes_short_label">Wszystkie</string>
+ <string name="new_episodes_label">Nowe</string>
<string name="favorite_episodes_label">Ulubione</string>
<string name="new_label">Nowy</string>
<string name="settings_label">Ustawienia</string>
@@ -104,14 +105,12 @@
<string name="podcastdirectories_label">Znajdź podcast w folderze</string>
<string name="podcastdirectories_descr">Możesz wyszukiwać nowe podcasty ze względu na nazwę, kategorię lub popularność na gpodder.net, Itunes lub fyyd</string>
<string name="browse_gpoddernet_label">Przeglądaj gpodder.net</string>
+ <string name="discover_more">więcej »</string>
<!--Actions on feeds-->
<string name="mark_all_read_label">Oznacz wszystkie jako odtworzone</string>
<string name="mark_all_read_msg">Wszystkie odcinki zaznaczono jako odtworzone</string>
<string name="mark_all_read_confirmation_msg">Proszę potwierdzić, że chcesz oznaczyć wszystkie odcinki jako odtworzone.</string>
<string name="mark_all_read_feed_confirmation_msg">Proszę potwierdzić, że chcesz oznaczyć wszystkie odcinki tego podcastu jako odtworzone.</string>
- <string name="remove_all_new_flags_label">Oznacz wszystkie jako wyświetlone</string>
- <string name="removed_all_new_flags_msg">Oznacz wszystkie odcinki jako wyświetlone</string>
- <string name="remove_all_new_flags_confirmation_msg">Proszę potwierdzić chęć zaznaczenia wszystkich odcinków jako obejrzanych.</string>
<string name="show_info_label">Pokaż informacje</string>
<string name="show_feed_settings_label">Pokaż ustawienia podcastu</string>
<string name="feed_settings_label">Ustawienia podcastu</string>
@@ -137,7 +136,7 @@
<string name="hide_has_media_label">Ma media</string>
<string name="filtered_label">Przefiltrowany</string>
<string name="refresh_failed_msg">{fa-exclamation-circle} Ostatnie odświerzanie nie powiodło się</string>
- <string name="open_podcast">Otwarty Podcast</string>
+ <string name="open_podcast">Otwórz Podcast</string>
<!--actions on feeditems-->
<string name="download_label">Pobierz</string>
<string name="play_label">Odtwórz</string>
@@ -147,8 +146,6 @@
<string name="remove_label">Usuń</string>
<string name="delete_label">Usuń</string>
<string name="delete_failed">Nie można usunąć pliku. Restart urządzenia może w tym pomóc.</string>
- <string name="remove_new_flag_label">Oznacz jako wyświetlone</string>
- <string name="removed_new_flag_label">Oznaczono jako wyświetlone</string>
<string name="mark_read_label">Oznacz jako odtworzone</string>
<string name="marked_as_read_label">Oznaczone jako odtworzone</string>
<string name="mark_unread_label">Oznacz jako nieodtworzone</string>
@@ -160,7 +157,6 @@
<string name="remove_from_favorite_label">Usuń z Ulubionych</string>
<string name="removed_from_favorites">Usunięto z ulubionych</string>
<string name="visit_website_label">Odwiedź stronę</string>
- <string name="support_label">Wspomóż na Flattr</string>
<string name="skip_episode_label">Pomiń odcinek</string>
<string name="activate_auto_download">Włącz automatyczne pobieranie</string>
<string name="deactivate_auto_download">Wyłącz automatyczne pobieranie</string>
@@ -246,32 +242,6 @@
<string name="ascending">Rosnąco</string>
<string name="descending">Malejąco</string>
<string name="clear_queue_confirmation_msg">Potwierdź usunięcie WSZYSTKICH pozycji z kolejki</string>
- <!--Flattr-->
- <string name="flattr_auth_label">Logowanie do Flattr</string>
- <string name="flattr_auth_explanation">Naciśnij przycisk poniżej by zacząć proces autoryzacji. Zostaniesz przekierowany na stronę logowania do flattr w przeglądarce i zostaniesz poproszony o przyznanie zezwolenia AntennaPod-owi na flattr-owanie. Po daniu zezwolenia powrócisz do tej strony automatycznie.</string>
- <string name="authenticate_label">Autoryzacja</string>
- <string name="return_home_label">Wróć do ekranu głównego</string>
- <string name="flattr_auth_success">Autoryzacja się powiodła. Możesz teraz używać flattr w aplikacji.</string>
- <string name="no_flattr_token_title">Nie znaleziono tokenu Flattr</string>
- <string name="no_flattr_token_notification_msg">Twoje konto flattr nie jest połączone z AntennaPod. Naciśnij tutaj aby autoryzować.</string>
- <string name="no_flattr_token_msg">Twoje konto Flattr wydaje się nie być podłączone do AntennaPod. Możesz połączyć konto do AntennaPod by przez program flattr-ować lub możesz odwiedzić stronę wątku by zrobić to tam.</string>
- <string name="authenticate_now_label">Autoryzuj</string>
- <string name="action_forbidden_title">Akcja zabroniona</string>
- <string name="action_forbidden_msg">AntennaPod nie ma zezwolenia na tą akcję. Powodem może być fakt iż dostęp dla AntennaPod do Twojego konta został cofnięty. Możesz ponownie autoryzować aplikację lub odwiedzić stronę. </string>
- <string name="access_revoked_title">Anulowano dostęp</string>
- <string name="access_revoked_info">Odwołałeś dostęp AntennaPod do swojego konta. W celu zakończenia procesu musisz usunąć aplikację z listy aplikacji dozwolonych na koncie Flattr.</string>
- <!--Flattr-->
- <string name="flattr_click_success">Poprawnie z-flattr-owano</string>
- <string name="flattr_click_success_count">Z-flattr-owano %d elementów</string>
- <string name="flattr_click_success_queue">Z-flattr-owano: %s</string>
- <string name="flattr_click_failure_count">Flattr-owanie %d elementów nie powiodło się</string>
- <string name="flattr_click_failure">Flattr-owanie zakończone niepowodzeniem: %s</string>
- <string name="flattr_click_enqueued">Elementy zostaną z-flattr-owane później</string>
- <string name="flattring_thing">Flattr-owanie %s</string>
- <string name="flattring_label">Flattr-uję</string>
- <string name="flattrd_label">AntennaPod z-flattr-owała</string>
- <string name="flattrd_failed_label">Flattr-owanie AntennaPod nie powiodło się</string>
- <string name="flattr_retrieving_status">Wyszukiwanie z-flattr-owanych elementów</string>
<!--Variable Speed-->
<string name="download_plugin_label">Pobierz wtyczkę</string>
<string name="no_playback_plugin_title">Wtyczka nie zainstalowana</string>
@@ -280,17 +250,20 @@
<string name="enable_sonic">Włącz Sonic</string>
<!--Empty list labels-->
<string name="no_feeds_label">Nie subskrybowałeś jeszcze żadnego podcastu.</string>
- <string name="no_chapters_label">Ten odcinek nie ma rozdziałów.</string>
<string name="no_shownotes_label">Ten epizod nie ma notatek.</string>
+ <string name="no_comp_downloads_head_label">Brak pobranych odcinków</string>
+ <string name="no_fav_episodes_head_label">Brak ulubionych odcinków</string>
+ <string name="no_chapters_label">Ten odcinek nie ma rozdziałów.</string>
<!--Preferences-->
<string name="storage_pref">Pamięć</string>
<string name="project_pref">Projekt</string>
<string name="other_pref">Inne</string>
<string name="about_pref">O...</string>
<string name="queue_label">Kolejka</string>
- <string name="flattr_label">Flattr</string>
<string name="download_pref_details">Szczegóły</string>
<string name="appearance">Wygląd</string>
+ <string name="preference_search_no_results">Brak wyników</string>
+ <string name="preference_search_clear_history">Wyczyść historię</string>
<string name="pref_episode_cleanup_title">Usuwanie odcinków</string>
<string name="pref_episode_cleanup_summary">Odcinki niebędące w kolejce i niebędące na liście ulubiobych powinny nadawać się do usunięcia, jeśli Automatyczne Pobieranie potrzebuje miejsca na nowe odcinki.</string>
<string name="pref_pauseOnDisconnect_sum">Wstrzymaj odtwarzanie po rozłączeniu słuchawek lub Bluetooth</string>
@@ -325,17 +298,8 @@
<string name="pref_unpauseOnHeadsetReconnect_title">Słuchawki podłączone ponownie</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Bluetooth podłączony ponownie</string>
<string name="pref_mobileUpdate_title">Aktualizacje mobilne</string>
- <string name="pref_mobileUpdate_sum">Zezwól na aktualizacje poprzez sieć komórkową</string>
+ <string name="pref_mobileUpdate_auto_download">Automatyczne pobieranie</string>
<string name="refreshing_label">Odświeżanie</string>
- <string name="flattr_settings_label">Ustawienia Flattr</string>
- <string name="pref_flattr_auth_title">Logowanie do Flattr</string>
- <string name="pref_flattr_auth_sum">Zaloguj się do konta Flattr aby wspierać twórców bezpośrednio z aplikacji.</string>
- <string name="pref_flattr_this_app_title">Wesprzyj aplikację na Flattr</string>
- <string name="pref_flattr_this_app_sum">Wesprzyj twórcę AntennaPod przez Flattr. Dzięki!</string>
- <string name="pref_revokeAccess_title">Anuluj dostęp</string>
- <string name="pref_revokeAccess_sum">Anuluj dostęp tej aplikacji do konta Flattr </string>
- <string name="pref_auto_flattr_title">Automatyczne wsparcie na Flattr</string>
- <string name="pref_auto_flattr_sum">Skonfiguruj automatyczne flattr-owanie</string>
<string name="user_interface_label">Interfejs użytkownika</string>
<string name="pref_set_theme_title">Wybierz motyw</string>
<string name="pref_nav_drawer_title">Dopasuj panel nawigacyjny</string>
@@ -417,11 +381,9 @@
<string name="pref_cast_message_free_flavor">Chromecast wymagadodatkowych bibliotek, które są zablokowane w tej wersji AntennaPod</string>
<string name="pref_enqueue_downloaded_title">Rzeczy z kolejki pobrane</string>
<string name="pref_enqueue_downloaded_summary">Dodaj pobrane odcinki do kolejki</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">Włącz automatyczne wspieranie na flattr.</string>
- <string name="auto_flattr_after_percent">Z-flattr-uj odcinki odegrane %d procentach.</string>
- <string name="auto_flattr_ater_beginning">Z-flattr-uj odcinek gdy odtawarzanie zostanie rozpoczęte</string>
- <string name="auto_flattr_ater_end">Z-flattr-uj odcinek gdy odtwarzanie zostanie zakończone</string>
+ <string name="behavior">Zachowanie</string>
+ <string name="back_button_default">Domyślne</string>
+ <string name="back_button_open_drawer">Otwórz panel nawigacyjny</string>
<!--Search-->
<string name="search_hint">Szukaj odcinków</string>
<string name="found_in_shownotes_label">Znalezione w notatkach dotyczących show</string>
@@ -570,9 +532,10 @@ https://gpodder.net/register/</string>
<string name="progress_upgrading_database">Aktualizacja bazy danych</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Importowanie subskrybcji z jednozadaniowych aplikacji</string>
+ <!--Add podcast fragment-->
<string name="search_itunes_label">Szukaj w iTunes</string>
- <string name="filter">Filtruj</string>
<string name="search_fyyd_label">Szukaj w fyyd</string>
+ <string name="filter">Filtruj</string>
<!--Episodes apply actions-->
<string name="all_label">Wszystkie</string>
<string name="selected_all_label">Zaznaczono wszystkie odcinki</string>
diff --git a/core/src/main/res/values-pt-rBR/strings.xml b/core/src/main/res/values-pt-rBR/strings.xml
index 76f838bde..7c318c941 100644
--- a/core/src/main/res/values-pt-rBR/strings.xml
+++ b/core/src/main/res/values-pt-rBR/strings.xml
@@ -111,9 +111,6 @@
<string name="mark_all_read_msg">Marcar todos Episódios como reproduzidos</string>
<string name="mark_all_read_confirmation_msg">Por favor, confirme que você deseja marcar todos os episódios como já reproduzidos.</string>
<string name="mark_all_read_feed_confirmation_msg">Favor confirmar que deseja marcar todos os episódios nesse podcast como já ouvidos.</string>
- <string name="remove_all_new_flags_label">Marcar todos como vistos</string>
- <string name="removed_all_new_flags_msg">Todos os episódios marcados como já ouvidos</string>
- <string name="remove_all_new_flags_confirmation_msg">Confirme se deseja marcar todos os episódios como vistos.</string>
<string name="show_info_label">Mostrar informação</string>
<string name="show_feed_settings_label">Exibir configurações do podcast</string>
<string name="feed_info_label">Informações do podcast</string>
@@ -148,6 +145,10 @@
<string name="open_podcast">Abrir Podcast</string>
<!--actions on feeditems-->
<string name="download_label">Download</string>
+ <plurals name="downloading_batch_label">
+ <item quantity="one">Baixar %d episódio.</item>
+ <item quantity="other">Baixar %d episódios.</item>
+ </plurals>
<string name="play_label">Reproduzir</string>
<string name="pause_label">Pausar</string>
<string name="stop_label">Parar</string>
@@ -155,20 +156,38 @@
<string name="remove_label">Remover</string>
<string name="delete_label">Deletar</string>
<string name="delete_failed">Não foi possível deletar o arquivo. Experimente reiniciar o dispositivo.</string>
- <string name="remove_new_flag_label">Marcar como ouvido</string>
- <string name="removed_new_flag_label">Marcar como visto</string>
+ <string name="delete_episode_label">Apagar Episódio</string>
+ <plurals name="deleted_episode_batch_label">
+ <item quantity="one">%d episódio apagado.</item>
+ <item quantity="other">%d episódios apagados.</item>
+ </plurals>
<string name="mark_read_label">Marcar como reproduzido</string>
<string name="marked_as_read_label">Marcado como reproduzido</string>
+ <plurals name="marked_read_batch_label">
+ <item quantity="one">%d episódio marcado como reproduzido.</item>
+ <item quantity="other">%d episódios marcados como reproduzidos.</item>
+ </plurals>
<string name="mark_unread_label">Marcar como não reproduzido</string>
+ <plurals name="marked_unread_batch_label">
+ <item quantity="one">%d episódio marcado como não reproduzido.</item>
+ <item quantity="other">%d episódios marcados como não reproduzidos.</item>
+ </plurals>
<string name="add_to_queue_label">Adicionar à fila</string>
<string name="added_to_queue_label">Adicionado à fila</string>
+ <plurals name="added_to_queue_batch_label">
+ <item quantity="one">%d episódio adicionado à fila.</item>
+ <item quantity="other">%d episódios adicionados à fila.</item>
+ </plurals>
<string name="remove_from_queue_label">Remover da fila</string>
+ <plurals name="removed_from_queue_batch_label">
+ <item quantity="one">%d episódio removido da fila.</item>
+ <item quantity="other">%d episódios removidos da fila.</item>
+ </plurals>
<string name="add_to_favorite_label">Adicionar aos Favoritos</string>
<string name="added_to_favorites">Adicionado aos Favoritos</string>
<string name="remove_from_favorite_label">Remover dos Favoritos</string>
<string name="removed_from_favorites">Removido dos Favoritos</string>
<string name="visit_website_label">Visitar Website</string>
- <string name="support_label">Adicionar ao Flattr</string>
<string name="skip_episode_label">Pular episódio</string>
<string name="activate_auto_download">Ativar download automático </string>
<string name="deactivate_auto_download">Desativar download automático</string>
@@ -254,32 +273,6 @@
<string name="ascending">Crescente</string>
<string name="descending">Decrescente</string>
<string name="clear_queue_confirmation_msg">Por favor confirme que você deseja limpar TODOS episódios da fila</string>
- <!--Flattr-->
- <string name="flattr_auth_label">Logar no Flattr</string>
- <string name="flattr_auth_explanation">Pressione o botão abaixo para iniciar o processo de autenticação. Você será direcionado para a tela de login do Flattr, que pedirá autorização para que o AntennaPod utilize o Flattr. Após conceder a permissão, você retornará a esta tela automaticamente.</string>
- <string name="authenticate_label">Autenticar</string>
- <string name="return_home_label">Retornar ao início</string>
- <string name="flattr_auth_success">Autenticado com sucesso! Agora você poderá utilizar o Flattr de dentro do AntennaPod.</string>
- <string name="no_flattr_token_title">Nenhum token do Flattr encontrado</string>
- <string name="no_flattr_token_notification_msg">Sua conta flattr parece não estar conectada ao AntennaPod. Toque aqui para autenticar.</string>
- <string name="no_flattr_token_msg">Sua conta Flattr não está conectada ao AntennaPod. Você pode conectar sua conta ao AntennaPod para usar o Flattr de dentro da aplicação ou pode visitar o website do feed para usar o Flattr por lá.</string>
- <string name="authenticate_now_label">Autenticar</string>
- <string name="action_forbidden_title">Ação proibida</string>
- <string name="action_forbidden_msg">AntennaPod não tem permissão para esta ação. A permissão de acesso do AntennaPod pode ter sido revogada. Você pode re-autenticar ou visitar o website do feed.</string>
- <string name="access_revoked_title">Acesso revogado</string>
- <string name="access_revoked_info">Você revogou o token de acesso do AntennaPod com sucesso. Para finalizar o processo, você deve remover esta app da lista de aplicativos aprovados nas configurações de sua conta no website do Flattr.</string>
- <!--Flattr-->
- <string name="flattr_click_success">Flattr\'ou alguma coisa!</string>
- <string name="flattr_click_success_count">Flattr\'ou %d coisas!</string>
- <string name="flattr_click_success_queue">Flattr\'ou: %s</string>
- <string name="flattr_click_failure_count">Falou em flattr %d coisas!</string>
- <string name="flattr_click_failure">Não flattr\'ou: %s.</string>
- <string name="flattr_click_enqueued">Coisas que serão flattr\'adas mais tarde</string>
- <string name="flattring_thing">Flattrando %s</string>
- <string name="flattring_label">AntennaPod está flattrando</string>
- <string name="flattrd_label">AntennaPod foi flattr\'ado</string>
- <string name="flattrd_failed_label">AntennaPod flattr falhou</string>
- <string name="flattr_retrieving_status">Recebendo coisas flattr\'adas</string>
<!--Variable Speed-->
<string name="download_plugin_label">Download Plugin</string>
<string name="no_playback_plugin_title">Plugin Não Instalado</string>
@@ -288,8 +281,8 @@
<string name="enable_sonic">Habilitar Sonic</string>
<!--Empty list labels-->
<string name="no_feeds_label">Você ainda não se inscreveu a nenhum podcast.</string>
- <string name="no_chapters_label">Este episódio não possui capítulos</string>
<string name="no_shownotes_label">Este episódio não possui notas.</string>
+ <string name="no_chapters_label">Este episódio não possui capítulos</string>
<!--Preferences-->
<string name="storage_pref">Armazenamento</string>
<string name="project_pref">Projeto</string>
@@ -297,15 +290,12 @@
<string name="about_pref">Sobre</string>
<string name="queue_label">Fila</string>
<string name="integrations_label">Integrações</string>
- <string name="flattr_label">Flattr</string>
- <string name="flattr_summary">Serviço de micropagamento</string>
<string name="automation">Automação</string>
<string name="download_pref_details">Detalhes</string>
<string name="import_export_pref">Importar/Exportar</string>
<string name="appearance">Aparência</string>
<string name="external_elements">Elementos externos</string>
<string name="interruptions">Interrupções</string>
- <string name="buttons">Botões de controle de reprodução</string>
<string name="media_player">Reprodutor de mídia</string>
<string name="pref_episode_cleanup_title">Limpar Episódio</string>
<string name="pref_episode_cleanup_summary">Episódios que não estão na fila e não estão nos favoritos podem ser removidos se o Download Automático precisar de espaço para novos episódios</string>
@@ -342,17 +332,7 @@
<string name="pref_unpauseOnHeadsetReconnect_title">Fones de ouvido reconectados</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Bluetooth reconectado</string>
<string name="pref_mobileUpdate_title">Atualizações via Rede de Dados Celular</string>
- <string name="pref_mobileUpdate_sum">Permite atualizações quando conectado na rede de dados celular</string>
<string name="refreshing_label">Atualizando</string>
- <string name="flattr_settings_label">Configurações do Flattr</string>
- <string name="pref_flattr_auth_title">Logar no Flattr</string>
- <string name="pref_flattr_auth_sum">Loga na sua conta Flattr para utilizá-lo diretamente da aplicação</string>
- <string name="pref_flattr_this_app_title">Registra este aplicativo no Flattr</string>
- <string name="pref_flattr_this_app_sum">Suportar o desenvolvimento do AntennaPod usando o Flattr. Obrigado!</string>
- <string name="pref_revokeAccess_title">Revogar acesso</string>
- <string name="pref_revokeAccess_sum">Cancelar permissão de acesso à sua conta Flattr</string>
- <string name="pref_auto_flattr_title">Flattr automático</string>
- <string name="pref_auto_flattr_sum">Configurar automaticamente com flattr</string>
<string name="user_interface_label">Interface com usuário</string>
<string name="pref_set_theme_title">Selecionar tema</string>
<string name="pref_nav_drawer_title">Customizar Gaveta de Navegação</string>
@@ -440,6 +420,7 @@
<string name="pref_enqueue_downloaded_title">Enfileirar os baixados</string>
<string name="pref_enqueue_downloaded_summary">Adicionar episódios baixados à fila</string>
<string name="media_player_builtin">Reprodutor próprio do Android</string>
+ <string name="pref_skip_silence_title">Pular silêncio no áudio</string>
<string name="pref_videoBehavior_title">Após fechar vídeo</string>
<string name="pref_videoBehavior_sum">Comportamento ao parar a reprodução de vídeo</string>
<string name="stop_playback">Parar a reprodução</string>
@@ -455,11 +436,6 @@
<string name="double_tap_toast">Clique novamente no botão voltar para sair</string>
<string name="back_button_go_to_page">Vá para a página...</string>
<string name="back_button_go_to_page_title">Selecione a página</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">Abilitar automaticamente o flattr</string>
- <string name="auto_flattr_after_percent">Episódio Flattr assim que %d porcento for tocado</string>
- <string name="auto_flattr_ater_beginning">Episódio Flattr quando a repodução iniciar</string>
- <string name="auto_flattr_ater_end">Episódio Flattr quando a reprodução finalizar</string>
<!--Search-->
<string name="search_hint">Buscar por episódios</string>
<string name="found_in_shownotes_label">Encontrados em exibir descrição</string>
@@ -603,9 +579,10 @@
<string name="progress_upgrading_database">Atualizando o banco de dados</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Importando assinaturas de aplicativos de finalidade única...</string>
+ <!--Add podcast fragment-->
<string name="search_itunes_label">Procurar no iTunes</string>
- <string name="filter">Filtrar</string>
<string name="search_fyyd_label">Pesquisar em fyyd</string>
+ <string name="filter">Filtrar</string>
<!--Episodes apply actions-->
<string name="all_label">Todos</string>
<string name="selected_all_label">Selecionar todos Episódios</string>
@@ -647,6 +624,7 @@
<string name="audio_effects">Efeitos Sonoros</string>
<string name="stereo_to_mono">Downmix: Stereo para mono</string>
<string name="sonic_only">Apenas Sonic</string>
+ <string name="exoplayer_only">Somente ExoPlayer</string>
<!--proxy settings-->
<string name="proxy_type_label">Tipo</string>
<string name="host_label">Host</string>
diff --git a/core/src/main/res/values-pt/strings.xml b/core/src/main/res/values-pt/strings.xml
index 3ec88af31..ff9249671 100644
--- a/core/src/main/res/values-pt/strings.xml
+++ b/core/src/main/res/values-pt/strings.xml
@@ -111,14 +111,16 @@
<string name="podcastdirectories_label">Localizar podcasts no diretório</string>
<string name="podcastdirectories_descr">Para novos podcasts, pode pesquisar no iTunes ou no fyyd. Também pode explorar no gpoder.net por nome, categoria ou popularidade.</string>
<string name="browse_gpoddernet_label">Procurar no gPodder.net</string>
+ <string name="discover">Descobrir</string>
+ <string name="discover_more">mais »</string>
<!--Actions on feeds-->
<string name="mark_all_read_label">Marcar tudo como reproduzido</string>
<string name="mark_all_read_msg">Marcar todos os episódios como reproduzidos</string>
<string name="mark_all_read_confirmation_msg">Tem a certeza de que deseja marcar todos os episódios como reproduzidos?</string>
<string name="mark_all_read_feed_confirmation_msg">Tem a certeza de que deseja marcar como reproduzidos todos os episódios deste podcast?</string>
- <string name="remove_all_new_flags_label">Marcar tudo como reproduzido</string>
- <string name="removed_all_new_flags_msg">Marcar todos como reproduzidos</string>
- <string name="remove_all_new_flags_confirmation_msg">Tem a certeza de que deseja marcar todos os episódios como vistos?</string>
+ <string name="remove_all_new_flags_label">Remover todas as marcas \"novo\"</string>
+ <string name="removed_all_new_flags_msg">Todas as marcas \"novo\" foram removidas</string>
+ <string name="remove_all_new_flags_confirmation_msg">Por favor confirme que pretende remover a marca \"novo\" de todos os episódios.</string>
<string name="show_info_label">Mostrar informações</string>
<string name="show_feed_settings_label">Mostrar definições do podcast</string>
<string name="feed_info_label">Informações do podcast</string>
@@ -169,8 +171,8 @@
<item quantity="one">%d episódio eliminado.</item>
<item quantity="other">%d episódios eliminados.</item>
</plurals>
- <string name="remove_new_flag_label">Marcar como reproduzido</string>
- <string name="removed_new_flag_label">Marcar como reproduzido</string>
+ <string name="remove_new_flag_label">Remover a marca \"novo\"</string>
+ <string name="removed_new_flag_label">A marca \"novo\" foi removida</string>
<string name="mark_read_label">Marcar como reproduzido</string>
<string name="marked_as_read_label">Marcado como reproduzido</string>
<plurals name="marked_read_batch_label">
@@ -198,7 +200,6 @@
<string name="remove_from_favorite_label">Remover dos favoritos</string>
<string name="removed_from_favorites">Removido dos favoritos</string>
<string name="visit_website_label">Aceder ao sítio web</string>
- <string name="support_label">Flattr</string>
<string name="skip_episode_label">Ignorar episódio</string>
<string name="activate_auto_download">Ativar descarga automática</string>
<string name="deactivate_auto_download">Desativar descarga automática</string>
@@ -250,6 +251,9 @@
<string name="confirm_mobile_download_dialog_title">Confirmação de descarga</string>
<string name="confirm_mobile_download_dialog_message_not_in_queue">A descarga através de dados móveis está desativada nas definições.\n\nAtivar temporariamente ou apenas adicionar à fila?\n\n<small>A sua decisão será memorizada durante 10 minutos.</small></string>
<string name="confirm_mobile_download_dialog_message">A descarga através de dados móveis está desativada nas definições.\n\nAtivar temporariamente?\n\n<small>A sua decisão será memorizada durante 10 minutos.</small></string>
+ <string name="confirm_mobile_streaming_notification_title">Confirmação de reprodução em dados móveis</string>
+ <string name="confirm_mobile_streaming_notification_message">A reprodução de podcasts através de dados móveis está desativada nas definições. Toque para, ainda assim, reproduzir o podcast.</string>
+ <string name="confirm_mobile_streaming_button_always">Permitir sempre</string>
<string name="confirm_mobile_download_dialog_only_add_to_queue">Apenas adicionados à fila</string>
<string name="confirm_mobile_download_dialog_enable_temporarily">Ativar temporariamente</string>
<!--Mediaplayer messages-->
@@ -259,6 +263,8 @@
<string name="player_ready_msg">Pronto</string>
<string name="player_seeking_msg">A procurar...</string>
<string name="playback_error_server_died">Erro de servidor</string>
+ <string name="playback_error_unsupported">Tipo de ficheiro não suportado</string>
+ <string name="playback_error_timeout">Operação expirada</string>
<string name="playback_error_unknown">Erro desconhecido</string>
<string name="no_media_playing_label">Nada em reprodução</string>
<string name="player_buffering_msg">A processar...</string>
@@ -276,6 +282,7 @@
<string name="move_to_top_label">Mover para o topo</string>
<string name="move_to_bottom_label">Mover para o fundo</string>
<string name="sort">Organização</string>
+ <string name="keep_sorted">Manter ordenação</string>
<string name="date">Data</string>
<string name="duration">Duração</string>
<string name="episode_title">Título do episódio</string>
@@ -285,32 +292,8 @@
<string name="ascending">Crescente</string>
<string name="descending">Decrescente</string>
<string name="clear_queue_confirmation_msg">Tem a certeza de que deseja remover todos os episódios da fila de reprodução?</string>
- <!--Flattr-->
- <string name="flattr_auth_label">Sessão Flattr</string>
- <string name="flattr_auth_explanation">Prima o botão abaixo para iniciar a autenticação. O seu navegador web abrirá o ecrã da sessão flattr e ser-lhe-á solicitada a permissão para o AntennaPod efetuar as alterações. Após ser dada a permissão, voltará novamente a este ecrã.</string>
- <string name="authenticate_label">Autenticar</string>
- <string name="return_home_label">Voltar ao ecrã</string>
- <string name="flattr_auth_success">Autenticação efetuada! Já pode fazer o flattr com a aplicação.</string>
- <string name="no_flattr_token_title">Token flattr não encontrado</string>
- <string name="no_flattr_token_notification_msg">Parece que a sua conta flattr não está integrada ao AntennaPod. Clique aqui para autenticar.</string>
- <string name="no_flattr_token_msg">Parece que a sua conta flattr não está vinculada ao AntennaPod. Pode vincular a sua conta ao AntennaPod ou aceder ao sítio web para fazer o flattr.</string>
- <string name="authenticate_now_label">Autenticar</string>
- <string name="action_forbidden_title">Ação proibida</string>
- <string name="action_forbidden_msg">O AntennaPod não possui as permissões para esta ação. É possível que o token de acesso ao flattr via AntennaPod tenha sido revogado. Pode efetuar nova autenticação ou aceder ao sítio web do item.</string>
- <string name="access_revoked_title">Acesso revogado</string>
- <string name="access_revoked_info">Você revogou o token de acesso do AntennaPod à sua conta. Para concluir o processo, tem que remover esta aplicação da lista de aplicações presentes nas definições de conta no sítio web do flattr.</string>
- <!--Flattr-->
- <string name="flattr_click_success">Flattr de um item!</string>
- <string name="flattr_click_success_count">Flattr de %d itens!</string>
- <string name="flattr_click_success_queue">Flattr: %s</string>
- <string name="flattr_click_failure_count">Falha ao efetuar flattr de %d itens!</string>
- <string name="flattr_click_failure">Não flattr: %s.</string>
- <string name="flattr_click_enqueued">O flattr deste item será feito mais tarde</string>
- <string name="flattring_thing">Flattring %s</string>
- <string name="flattring_label">O AntennaPod está a flattring</string>
- <string name="flattrd_label">O AntennaPod fez o flattr</string>
- <string name="flattrd_failed_label">O AntennaPod não fez o flattr</string>
- <string name="flattr_retrieving_status">A obter itens com flattr</string>
+ <string name="sort_old_to_new">Antigo para novo</string>
+ <string name="sort_new_to_old">Novo para antigo</string>
<!--Variable Speed-->
<string name="download_plugin_label">Descarregar extra</string>
<string name="no_playback_plugin_title">Extra não instalado</string>
@@ -321,7 +304,6 @@
<string name="no_items_header_label">Não existem episódios na fila</string>
<string name="no_items_label">Pode adicionar um episódio se o descarregar ou com um toque longo no episódio e escolher \"Adicionar à fila\".</string>
<string name="no_feeds_label">Ainda não tem quaisquer podcasts subscritos.</string>
- <string name="no_chapters_label">Este episódio não tem capítulos.</string>
<string name="no_shownotes_label">Este episódio não tem notas.</string>
<string name="no_run_downloads_head_label">Não existem descargas em curso</string>
<string name="no_run_downloads_label">Pode descarregar os episódios no ecrã de detalhes do podcast.</string>
@@ -337,6 +319,8 @@
<string name="no_new_episodes_label">Assim que existir um novo episódio, ele será mostrado aqui.</string>
<string name="no_fav_episodes_head_label">Não existem episódios favoritos</string>
<string name="no_fav_episodes_label">Pode adicionar episódios aos favoritos com um toque longo.</string>
+ <string name="no_chapters_head_label">Não há capítulos</string>
+ <string name="no_chapters_label">Este episódio não tem capítulos.</string>
<!--Preferences-->
<string name="storage_pref">Armazenamento</string>
<string name="project_pref">Projeto</string>
@@ -344,8 +328,6 @@
<string name="about_pref">Sobre</string>
<string name="queue_label">Fila</string>
<string name="integrations_label">Integrações</string>
- <string name="flattr_label">Flattr</string>
- <string name="flattr_summary">Serviço de micro pagamentos</string>
<string name="automation">Automatização</string>
<string name="download_pref_details">Detalhes</string>
<string name="import_export_pref">Importar/Exportar</string>
@@ -353,7 +335,10 @@
<string name="appearance">Aparência</string>
<string name="external_elements">Elementos externos</string>
<string name="interruptions">Interrupções</string>
- <string name="buttons">Botões para controlo de reprodução</string>
+ <string name="playback_control">Controlo de reprodução</string>
+ <string name="preference_search_hint">Pesquisar...</string>
+ <string name="preference_search_no_results">Não existem resultados</string>
+ <string name="preference_search_clear_history">Limpar histórico</string>
<string name="media_player">Reprodutor multimédia</string>
<string name="pref_episode_cleanup_title">Limpeza de episódios</string>
<string name="pref_episode_cleanup_summary">Os episódios que não estejam na fila e não sejam favoritos podem ser elegíveis para serem removidos se a Descarga automática necessitar de espaço para novos episódios.</string>
@@ -389,21 +374,14 @@
<string name="pref_pauseOnHeadsetDisconnect_title">Auscultadores removidos</string>
<string name="pref_unpauseOnHeadsetReconnect_title">Auscultadores inseridos</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Ligação bluetooth</string>
- <string name="pref_mobileUpdate_title">Atualizações móveis</string>
- <string name="pref_mobileUpdate_sum">Permitir atualizações através da rede de dados móveis</string>
- <string name="pref_mobileUpdate_nothing">Nada</string>
- <string name="pref_mobileUpdate_images">Apenas imagens</string>
- <string name="pref_mobileUpdate_everything">Tudo</string>
+ <string name="pref_mobileUpdate_title">Dados móveis</string>
+ <string name="pref_mobileUpdate_sum">Selecione o que pode ser permitido através de dados móveis</string>
+ <string name="pref_mobileUpdate_refresh">Atualização de fontes</string>
+ <string name="pref_mobileUpdate_images">Descarga de imagens</string>
+ <string name="pref_mobileUpdate_auto_download">Descarga automática</string>
+ <string name="pref_mobileUpdate_episode_download">Descarga de episódios</string>
+ <string name="pref_mobileUpdate_streaming">Reprodução</string>
<string name="refreshing_label">A atualizar</string>
- <string name="flattr_settings_label">Definições flattr</string>
- <string name="pref_flattr_auth_title">Sessão flattr</string>
- <string name="pref_flattr_auth_sum">Inicie sessão na sua conta flattr para fazer o flattr no AntennaPod</string>
- <string name="pref_flattr_this_app_title">Flattr desta aplicação</string>
- <string name="pref_flattr_this_app_sum">Ajude no desenvolvimento do AntennaPod através do Flattr. Obrigado!</string>
- <string name="pref_revokeAccess_title">Revogar acesso</string>
- <string name="pref_revokeAccess_sum">Revogar permissões de acesso da aplicação à sua conta flattr</string>
- <string name="pref_auto_flattr_title">Flattr automático</string>
- <string name="pref_auto_flattr_sum">Configurar flattr automático</string>
<string name="user_interface_label">Interface</string>
<string name="pref_set_theme_title">Tema</string>
<string name="pref_nav_drawer_title">Menu de navegação</string>
@@ -425,6 +403,7 @@
<string name="pref_automatic_download_on_battery_sum">Permitir descarga automática se a bateria não estiver a ser carregada</string>
<string name="pref_parallel_downloads_title">Descargas simultâneas</string>
<string name="pref_episode_cache_title">Cache de episódios</string>
+ <string name="pref_episode_cache_summary">Número máximo de episódios descarregados para colocar em cache. A descarga automática será suspensa se este número for atingido.</string>
<string name="pref_theme_title_light">Claro</string>
<string name="pref_theme_title_dark">Escuro</string>
<string name="pref_theme_title_trueblack">Preto (AMOLED)</string>
@@ -450,6 +429,8 @@
<string name="pref_gpodnet_notifications_sum">Esta definição não é aplicável aos erros de autenticação.</string>
<string name="pref_playback_speed_title">Velocidades de reprodução</string>
<string name="pref_playback_speed_sum">Personalizar as velocidades de reprodução disponíveis</string>
+ <string name="pref_playback_time_respects_speed_title">Ajustar informações multimédia à velocidade de reprodução</string>
+ <string name="pref_playback_time_respects_speed_sum">A posição e a duração serão ajustadas automaticamente à velocidade de reprodução</string>
<string name="pref_fast_forward">Tempo a avançar</string>
<string name="pref_fast_forward_sum">Personalizar o número de segundos a avançar ao clicar no botão de avanço rápido</string>
<string name="pref_rewind">Tempo a recuar</string>
@@ -509,11 +490,6 @@
<string name="back_button_go_to_page_title">Selecionar página</string>
<string name="pref_delete_removes_from_queue_title">Remover da fila</string>
<string name="pref_delete_removes_from_queue_sum">Remover episódio da fila se este for eliminado.</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">Ativar flattr automático</string>
- <string name="auto_flattr_after_percent">Flattr de episódios ao atingir %d porcento de reprodução</string>
- <string name="auto_flattr_ater_beginning">Flattr de episodios ao iniciar a reprodução</string>
- <string name="auto_flattr_ater_end">Flattr de episódios ao terminar a reprodução</string>
<!--Search-->
<string name="search_hint">Pesquisar por episódios</string>
<string name="found_in_shownotes_label">Encontrado nas notas</string>
@@ -607,12 +583,14 @@
<string name="gpodnetsync_error_descr">Ocorreu um erro ao sincronizar:\u0020</string>
<string name="gpodnetsync_pref_report_successful">Sucesso</string>
<string name="gpodnetsync_pref_report_failed">Falha</string>
+ <string name="gpodnetsync_username_characters_error">Apenas pode utilizar letras, dígitos, hífenes e sublinhados para o nome de utilizador.</string>
<!--Directory chooser-->
<string name="selected_folder_label">Diretório escolhido:</string>
<string name="create_folder_label">Criar pasta</string>
<string name="choose_data_directory">Escolha a pasta de dados</string>
<string name="choose_data_directory_message">Escolha a base da pasta de dados. O AntennaPod irá criar as subpastas apropriadas.</string>
<string name="choose_data_directory_permission_rationale">Para alterar a pasta de dados, tem que ter acesso ao armazenamento externo</string>
+ <string name="choose_data_directory_available_space">%1$s de %2$s disponível</string>
<string name="create_folder_msg">Criar uma pasta com o nome \"%1$s\"?</string>
<string name="create_folder_success">Nova pasta criada</string>
<string name="create_folder_error_no_write_access">Não é possível guardar nesta pasta</string>
@@ -653,13 +631,18 @@
<string name="episode_filters_exclude">Excluir</string>
<string name="episode_filters_hint">Uma palavra\n\"Várias palavras\"</string>
<string name="keep_updated">Manter atualizada</string>
+ <string name="keep_updated_summary">Incluir esta fonte ao recarregar automaticamente todas as fontes</string>
+ <string name="auto_download_disabled_globally">A descarga automática está desativada nas definições do AntennaPod</string>
<!--Progress information-->
<string name="progress_upgrading_database">Atualizando base de dados</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Importar subscrições de aplicações single-purpose...</string>
+ <!--Add podcast fragment-->
+ <string name="search_podcast_hint">Pesquisar podcast...</string>
<string name="search_itunes_label">Pesquisar no iTunes</string>
- <string name="filter">Filtro</string>
<string name="search_fyyd_label">Pesquisar no fyyd</string>
+ <string name="advanced_search">Pesquisa avançada</string>
+ <string name="filter">Filtro</string>
<!--Episodes apply actions-->
<string name="all_label">Todos</string>
<string name="selected_all_label">Marcar todos os episódios</string>
@@ -749,4 +732,5 @@
<string name="notification_channel_playing_description">Permite o controlo da reprodução. Esta será a notificação que verá ao reproduzir um podcast.</string>
<string name="notification_channel_error">Erros</string>
<string name="notification_channel_error_description">Mostrar se ocorrerem erros como, por exemplo, não for possível a descarga.</string>
+ <string name="import_bad_file">Ficheiro inválido/danificado</string>
</resources>
diff --git a/core/src/main/res/values-ru/strings.xml b/core/src/main/res/values-ru/strings.xml
index a904d3ad9..36d69fd6f 100644
--- a/core/src/main/res/values-ru/strings.xml
+++ b/core/src/main/res/values-ru/strings.xml
@@ -95,12 +95,19 @@
<string name="episode_cleanup_never">Никогда</string>
<string name="episode_cleanup_queue_removal">Когда не в очереди</string>
<string name="episode_cleanup_after_listening">После прослушивания</string>
+ <plurals name="episode_cleanup_hours_after_listening">
+ <item quantity="one">1 час после прослушивания</item>
+ <item quantity="few">%d часов после прослушивания</item>
+ <item quantity="many">%d часов после прослушивания</item>
+ <item quantity="other">%d часов после прослушивания</item>
+ </plurals>
<plurals name="episode_cleanup_days_after_listening">
<item quantity="one">день после прослушивания</item>
<item quantity="few">%d дня после прослушивания</item>
<item quantity="many">%d дней после прослушивания</item>
<item quantity="other">%d дней после прослушивания</item>
</plurals>
+ <string name="num_selected_label">%d выбран</string>
<!--'Add Feed' Activity labels-->
<string name="feedurl_label">URL канала</string>
<string name="etxtFeedurlHint">www.example.com/feed</string>
@@ -108,14 +115,16 @@
<string name="podcastdirectories_label">Найти подкаст в каталоге</string>
<string name="podcastdirectories_descr">Вы можете искать новые подкасты в каталогах iTunes, fyyd или gpodder.net по имени, категории или популярности.</string>
<string name="browse_gpoddernet_label">Просмотр gpodder.net</string>
+ <string name="discover">Найти каналы</string>
+ <string name="discover_more">ещё »</string>
<!--Actions on feeds-->
<string name="mark_all_read_label">Отметить как прослушанное</string>
<string name="mark_all_read_msg">Отметить все выпуски как прослушанные</string>
<string name="mark_all_read_confirmation_msg">Подтвердите, что хотите пометить все эпизоды как прослушанные.</string>
<string name="mark_all_read_feed_confirmation_msg">Пожалуйста, подтвердите желание отметить все выпуски этого подкаста как прослушанные.</string>
- <string name="remove_all_new_flags_label">Отметить все как просмотренное</string>
- <string name="removed_all_new_flags_msg">Все выпуски отмечены как просмотренные</string>
- <string name="remove_all_new_flags_confirmation_msg">Пожалуйста, подтвердите намерение отметить все выпуски как просмотренные.</string>
+ <string name="remove_all_new_flags_label">Убрать все пометки \"новый\"</string>
+ <string name="removed_all_new_flags_msg">Все пометки \"новый\" убраны</string>
+ <string name="remove_all_new_flags_confirmation_msg">Подтвердите, что хотите убрать пометки \"новый\" со всех выпусков.</string>
<string name="show_info_label">Показать информацию</string>
<string name="show_feed_settings_label">Показать настройки подкаста</string>
<string name="feed_info_label">Сведения о подкасте</string>
@@ -150,6 +159,12 @@
<string name="open_podcast">Открыть подкаст</string>
<!--actions on feeditems-->
<string name="download_label">Загрузить</string>
+ <plurals name="downloading_batch_label">
+ <item quantity="one">Загрузка %d выпуска</item>
+ <item quantity="few">Загрузка %d выпусков</item>
+ <item quantity="many">Загрузка %d выпусков</item>
+ <item quantity="other">Загрузка %d выпусков.</item>
+ </plurals>
<string name="play_label">Воспроизвести</string>
<string name="pause_label">Пауза</string>
<string name="stop_label">Остановить</string>
@@ -157,20 +172,50 @@
<string name="remove_label">Удалить</string>
<string name="delete_label">Удалить</string>
<string name="delete_failed">Невозможно удалить файл. Попробуйте перезагрузить устройство.</string>
- <string name="remove_new_flag_label">Просмотрено</string>
- <string name="removed_new_flag_label">Отмечено как просмотренное</string>
+ <string name="delete_episode_label">Удалить выпуск</string>
+ <plurals name="deleted_episode_batch_label">
+ <item quantity="one">%d выпуск удален</item>
+ <item quantity="few">%d выпусков удаленно</item>
+ <item quantity="many">%d выпусков удаленно</item>
+ <item quantity="other">%d выпусков удаленно</item>
+ </plurals>
+ <string name="remove_new_flag_label">Убрать пометку \"новый\"</string>
+ <string name="removed_new_flag_label">Пометка \"новый\" убрана</string>
<string name="mark_read_label">Отметить как прослушанное</string>
<string name="marked_as_read_label">Помечено как прослушанное</string>
+ <plurals name="marked_read_batch_label">
+ <item quantity="one">%d выпуск отмечен как прослушанный.</item>
+ <item quantity="few">%d выпусков отмечено как прослушанные.</item>
+ <item quantity="many">%d выпусков отмечено как прослушанные.</item>
+ <item quantity="other">%d выпусков отмечено как прослушанные.</item>
+ </plurals>
<string name="mark_unread_label">Отметить как непрослушанное</string>
+ <plurals name="marked_unread_batch_label">
+ <item quantity="one">%d выпуск отмечен непрослушанный.</item>
+ <item quantity="few">%d выпусков отмечено непрослушанные.</item>
+ <item quantity="many">%d выпусков отмечено непрослушанные.</item>
+ <item quantity="other">%d выпусков отмечено непрослушанные.</item>
+ </plurals>
<string name="add_to_queue_label">Добавить в очередь</string>
<string name="added_to_queue_label">Добавлено в очередь</string>
+ <plurals name="added_to_queue_batch_label">
+ <item quantity="one">%d выпуск добавлен в очередь.</item>
+ <item quantity="few">%d выпусков добавлено в очередь.</item>
+ <item quantity="many">%d выпусков добавлено в очередь.</item>
+ <item quantity="other">%d выпусков добавлено в очередь.</item>
+ </plurals>
<string name="remove_from_queue_label">Удалить из очереди</string>
+ <plurals name="removed_from_queue_batch_label">
+ <item quantity="one">%d выпуск удален из очереди.</item>
+ <item quantity="few">%d выпусков удалено из очереди.</item>
+ <item quantity="many">%d выпусков удалено из очереди.</item>
+ <item quantity="other">%d выпусков удалено из очереди.</item>
+ </plurals>
<string name="add_to_favorite_label">Добавить в избранное</string>
<string name="added_to_favorites">Добавлено в избранное</string>
<string name="remove_from_favorite_label">Удалить из избранного</string>
<string name="removed_from_favorites">Удалено из избранного</string>
<string name="visit_website_label">Посетить сайт</string>
- <string name="support_label">Поддержать через Flattr</string>
<string name="skip_episode_label">Пропустить выпуск</string>
<string name="activate_auto_download">Включить автоматическую загрузку</string>
<string name="deactivate_auto_download">Отключить автоматическую загрузку</string>
@@ -221,11 +266,15 @@ URL файла:
<string name="download_type_media">Медиафайл</string>
<string name="download_type_image">Изображение</string>
<string name="download_request_error_dialog_message_prefix">Ошибка при загрузке файла:\u0020</string>
+ <string name="null_value_podcast_error">Не предоставлен подкаст, который можно было бы показать.</string>
<string name="authentication_notification_title">Необходима авторизация</string>
<string name="authentication_notification_msg">Для доступа к ресурсу необходимо ввести имя пользователя и пароль</string>
<string name="confirm_mobile_download_dialog_title">Подтвердите загрузку через мобильное соединение</string>
<string name="confirm_mobile_download_dialog_message_not_in_queue">Загрузка через мобильное соединение отключена в настройках.\n\nВы можете добавить выпуск в очередь или временно разрешить загрузку.\n\n<small>Настройка сохранится на 10 минут.</small></string>
<string name="confirm_mobile_download_dialog_message">Загрузка через мобильное соединение отключена в настройках.\n\nВы желаете временно разрешить загрузку?\n\n<small>Настройка сохранится на 10 минут.</small></string>
+ <string name="confirm_mobile_streaming_notification_title">Подтвердите трансляцию через мобильное соединение</string>
+ <string name="confirm_mobile_streaming_notification_message">Трансляция через мобильное подключение к интернету отключено в настройках. Нажмите, чтобы продолжить.</string>
+ <string name="confirm_mobile_streaming_button_always">Разрешить навсегда</string>
<string name="confirm_mobile_download_dialog_only_add_to_queue">Добавить в очередь</string>
<string name="confirm_mobile_download_dialog_enable_temporarily">Разрешить временно</string>
<!--Mediaplayer messages-->
@@ -235,6 +284,8 @@ URL файла:
<string name="player_ready_msg">Готово</string>
<string name="player_seeking_msg">Перемотка</string>
<string name="playback_error_server_died">Сервер недоступен</string>
+ <string name="playback_error_unsupported">Не поддерживаемый формат</string>
+ <string name="playback_error_timeout">Не выполнено вовремя</string>
<string name="playback_error_unknown">Неизвестная ошибка</string>
<string name="no_media_playing_label">Ничего не воспроизводится</string>
<string name="player_buffering_msg">Буферизация</string>
@@ -252,6 +303,7 @@ URL файла:
<string name="move_to_top_label">Переместить вверх</string>
<string name="move_to_bottom_label">Переместить вниз</string>
<string name="sort">Сортировать</string>
+ <string name="keep_sorted">Сохранять сортировку</string>
<string name="date">По дате</string>
<string name="duration">По продолжительности</string>
<string name="episode_title">Название выпуска</string>
@@ -261,32 +313,8 @@ URL файла:
<string name="ascending">По возрастанию</string>
<string name="descending">По убыванию</string>
<string name="clear_queue_confirmation_msg">Подтвердите, что хотите очистить очередь от ВСЕХ эпизодов.</string>
- <!--Flattr-->
- <string name="flattr_auth_label">Авторизоваться в Flattr</string>
- <string name="flattr_auth_explanation">Нажмите кнопку, чтобы начать процесс авторизации. Вы будете перенаправлены на сайт Flattr, где нужно будет разрешить AntennaPod использовать ваш аккаунт. После этого вы автоматически будете перенаправлены обратно.</string>
- <string name="authenticate_label">Авторизовать</string>
- <string name="return_home_label">Вернуться к началу</string>
- <string name="flattr_auth_success">Успешная авторизация. Теперь можно использовать Flattr прямо из приложения.</string>
- <string name="no_flattr_token_title">Токен Flattr не найден</string>
- <string name="no_flattr_token_notification_msg">Ваша учетная запись Flattr не подключена к AntennaPod. Нажмите здесь, чтобы войти.</string>
- <string name="no_flattr_token_msg">Кажется, ваш аккаунт Flattr не подключен к AntennaPod. Можно подключить аккаунт к AntennaPod или посетить сайт канала, чтобы пожертвовать через Flattr прямо на сайте.</string>
- <string name="authenticate_now_label">Авторизоваться</string>
- <string name="action_forbidden_title">Действие запрещено</string>
- <string name="action_forbidden_msg">AntennaPod не имеет прав для выполнения этого действия. Возможно, доступ к вашему аккаунту был отозван. Можно авторизоваться заново или посетить сайт, которому вы пожертвовали через Flattr.</string>
- <string name="access_revoked_title">Доступ отозван</string>
- <string name="access_revoked_info">Вы успешно отключили AntennaPod от аккаунта в Flattr. Чтобы завершить этот процесс нужно удалить AntennaPod из списка приложений подключенных к аккаунту на сайте Flattr.</string>
- <!--Flattr-->
- <string name="flattr_click_success">Один поддержан через Flattr!</string>
- <string name="flattr_click_success_count">Поддержано через Flattr: %d.</string>
- <string name="flattr_click_success_queue">Поддержано через Flattr: %s.</string>
- <string name="flattr_click_failure_count">Не удалось поддержать через Flattr: %d!</string>
- <string name="flattr_click_failure">Не поддержано через Flattr: %s.</string>
- <string name="flattr_click_enqueued">Будет поддержано через Flattr потом</string>
- <string name="flattring_thing">%s поддерживается через Flattr</string>
- <string name="flattring_label">AntennaPod поддерживается через Flattr</string>
- <string name="flattrd_label">Вы поддержали AntennaPod через Flattr</string>
- <string name="flattrd_failed_label">Ошибка</string>
- <string name="flattr_retrieving_status">Получение списка поддержаного через Flattr</string>
+ <string name="sort_old_to_new">От старых к новым</string>
+ <string name="sort_new_to_old">От новых к старым</string>
<!--Variable Speed-->
<string name="download_plugin_label">Загрузить плагин</string>
<string name="no_playback_plugin_title">Плагин не установлен</string>
@@ -294,9 +322,26 @@ URL файла:
<string name="set_playback_speed_label">Скорость воспроизведения</string>
<string name="enable_sonic">Включить Sonic</string>
<!--Empty list labels-->
+ <string name="no_items_header_label">Нет эпизодов в очереди</string>
+ <string name="no_items_label">Добавьте выпуск, загрузив его, или долго удерживайте выпуск и выберите «Добавить в очередь».</string>
<string name="no_feeds_label">Вы ещё не подписаны ни на один подкаст.</string>
- <string name="no_chapters_label">Этот выпуск не содержит оглавления.</string>
<string name="no_shownotes_label">Этот выпуск не содержит примечаний.</string>
+ <string name="no_run_downloads_head_label">Нет запущенных загрузок</string>
+ <string name="no_run_downloads_label">Вы можете загрузить выпуски на экране сведений о подкасте.</string>
+ <string name="no_comp_downloads_head_label">Нет загруженных выпусков</string>
+ <string name="no_comp_downloads_label">Вы можете загрузить выпуски на экране сведений подкаста.</string>
+ <string name="no_log_downloads_head_label">Нет журнала загрузки</string>
+ <string name="no_log_downloads_label">Журналы загрузок появятся здесь, когда они будут доступны.</string>
+ <string name="no_history_head_label">Нет истории</string>
+ <string name="no_history_label">После того, как вы прослушаете выпуск, он появится здесь.</string>
+ <string name="no_all_episodes_head_label">Нет выпусков</string>
+ <string name="no_all_episodes_label">Когда вы добавите подкаст, выпуски будут показаны здесь.</string>
+ <string name="no_new_episodes_head_label">Нет новых выпусков</string>
+ <string name="no_new_episodes_label">Когда появятся новые выпуски, они будут показаны здесь.</string>
+ <string name="no_fav_episodes_head_label">Нет избранных выпусков</string>
+ <string name="no_fav_episodes_label">Вы можете добавить выпуски в избранное долгим нажатием на них.</string>
+ <string name="no_chapters_head_label">Нет оглавления</string>
+ <string name="no_chapters_label">Этот выпуск не содержит оглавления.</string>
<!--Preferences-->
<string name="storage_pref">Хранилище</string>
<string name="project_pref">Проект</string>
@@ -304,15 +349,17 @@ URL файла:
<string name="about_pref">О программе</string>
<string name="queue_label">Очередь</string>
<string name="integrations_label">Интеграция</string>
- <string name="flattr_label">Flattr</string>
- <string name="flattr_summary">Сервис микроплатежей</string>
<string name="automation">Автоматизация</string>
<string name="download_pref_details">Подробнее</string>
<string name="import_export_pref">Импорт/экспорт</string>
+ <string name="import_export_search_keywords">резервирование, восстановление</string>
<string name="appearance">Внешний вид</string>
<string name="external_elements">Внешние органы управления</string>
<string name="interruptions">Прерывания</string>
- <string name="buttons">Кнопки управления воспроизведением</string>
+ <string name="playback_control">Управление воспроизведением</string>
+ <string name="preference_search_hint">Найти…</string>
+ <string name="preference_search_no_results">Безрезультатно</string>
+ <string name="preference_search_clear_history">Очистить историю</string>
<string name="media_player">Проигрыватель</string>
<string name="pref_episode_cleanup_title">Удаление выпусков</string>
<string name="pref_episode_cleanup_summary">Выпуски, которые не стоят в очереди и не отмечены как избранные могут быть удалены для освобождения места под Автозагрузку.</string>
@@ -349,17 +396,13 @@ URL файла:
<string name="pref_unpauseOnHeadsetReconnect_title">Наушники подключены обратно</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Bluetooth-соединение восстановлено</string>
<string name="pref_mobileUpdate_title">Мобильные обновления</string>
- <string name="pref_mobileUpdate_sum">Позволить обновления через мобильное интернет-подключение</string>
+ <string name="pref_mobileUpdate_sum">Выберите что допускается загружать при мобильном интернет-подключении</string>
+ <string name="pref_mobileUpdate_refresh">Обновления каналов</string>
+ <string name="pref_mobileUpdate_images">Обложки</string>
+ <string name="pref_mobileUpdate_auto_download">Автозагрузка</string>
+ <string name="pref_mobileUpdate_episode_download">Загрузка выпусков</string>
+ <string name="pref_mobileUpdate_streaming">Трансляции по сети</string>
<string name="refreshing_label">Обновление</string>
- <string name="flattr_settings_label">Настройки Flattr</string>
- <string name="pref_flattr_auth_title">Авторизация Flattr</string>
- <string name="pref_flattr_auth_sum">Авторизуйтесь во Flattr чтобы поддерживать каналы прямо из приложения</string>
- <string name="pref_flattr_this_app_title">Поддержать это приложение в Flattr</string>
- <string name="pref_flattr_this_app_sum">Поддержите разработку AntennaPod через Flattr. Спасибо!</string>
- <string name="pref_revokeAccess_title">Отозвать доступ</string>
- <string name="pref_revokeAccess_sum">Отменить доступ этого приложения к вашему аккаунту Flattr.</string>
- <string name="pref_auto_flattr_title">Автоматически поддерживать через Flattr</string>
- <string name="pref_auto_flattr_sum">Настройка автоматической поддержки через Flattr</string>
<string name="user_interface_label">Интерфейс</string>
<string name="pref_set_theme_title">Выбор темы</string>
<string name="pref_nav_drawer_title">Настроить боковую панель</string>
@@ -381,6 +424,7 @@ URL файла:
<string name="pref_automatic_download_on_battery_sum">Разрешать автоматическую загрузку когда батарея не заряжается</string>
<string name="pref_parallel_downloads_title">Одновременные загрузки</string>
<string name="pref_episode_cache_title">Кэш выпусков</string>
+ <string name="pref_episode_cache_summary">Общее количество загруженных в кэш выпусков. Автоматическая загрузка будет приостановлена, если это количество будет достигнуто.</string>
<string name="pref_theme_title_light">Светлая</string>
<string name="pref_theme_title_dark">Тёмная</string>
<string name="pref_theme_title_trueblack">Чёрная (для AMOLED)</string>
@@ -406,6 +450,8 @@ URL файла:
<string name="pref_gpodnet_notifications_sum">Не затрагивает ошибки авторизации.</string>
<string name="pref_playback_speed_title">Скорость воспроизведения</string>
<string name="pref_playback_speed_sum">Настроить скорости воспроизведения</string>
+ <string name="pref_playback_time_respects_speed_title">Корректировка информации о медиа файлов с учетом скорости воспроизведения</string>
+ <string name="pref_playback_time_respects_speed_sum">Отображаемые позиция и длительность адаптированы к скорости воспроизведения</string>
<string name="pref_fast_forward">Интервал быстрой перемотки вперед</string>
<string name="pref_fast_forward_sum">Настройте длину шага в секундах при нажатии кнопки перемотки вперёд</string>
<string name="pref_rewind">Интервал быстрой перемотки назад</string>
@@ -447,6 +493,7 @@ URL файла:
<string name="pref_enqueue_downloaded_title">Добавлять загруженные в очередь</string>
<string name="pref_enqueue_downloaded_summary">Добавлять загруженные выпуски в очередь</string>
<string name="media_player_builtin">Встроенный в Android проигрыватель</string>
+ <string name="pref_skip_silence_title">Пропускать тишину в выпуске</string>
<string name="pref_videoBehavior_title">При завершении видео</string>
<string name="pref_videoBehavior_sum">При сворачивании проигрывателя видео</string>
<string name="stop_playback">Остановить воспроизведение</string>
@@ -462,11 +509,8 @@ URL файла:
<string name="double_tap_toast">Коснитесь кнопки \"Назад\" ещё раз, чтобы выйти</string>
<string name="back_button_go_to_page">Загрузить страницу…</string>
<string name="back_button_go_to_page_title">Выбрать страницу</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">Включить автоматическую поддержку через Flattr</string>
- <string name="auto_flattr_after_percent">Поддерживать через Flattr эпизоды, прослушанные на %d процентов</string>
- <string name="auto_flattr_ater_beginning">Поддерживать эпизод через Flattr в начале воспроизведения</string>
- <string name="auto_flattr_ater_end">Поддерживать эпизод через Flattr в конце воспроизведения</string>
+ <string name="pref_delete_removes_from_queue_title">Убирать удаленные из очереди</string>
+ <string name="pref_delete_removes_from_queue_sum">Автоматически убирать выпуск из очереди при его удалении.</string>
<!--Search-->
<string name="search_hint">Найти выпуски</string>
<string name="found_in_shownotes_label">Найдено в примечаниях к выпуску</string>
@@ -568,12 +612,14 @@ URL файла:
<string name="gpodnetsync_error_descr">Произошла ошибка во время синхронизации:\u0020</string>
<string name="gpodnetsync_pref_report_successful">Успешно</string>
<string name="gpodnetsync_pref_report_failed">Неудачно</string>
+ <string name="gpodnetsync_username_characters_error">Имя пользователя может содержать только буквы, цифры, дефисы и символы подчеркивания.</string>
<!--Directory chooser-->
<string name="selected_folder_label">Выбранная папка:</string>
<string name="create_folder_label">Создать папку</string>
<string name="choose_data_directory">Выбрать папку для хранения данных</string>
<string name="choose_data_directory_message">Укажите корневую папку для хранения данных. AntennaPod создаст необходимые подкаталоги.</string>
<string name="choose_data_directory_permission_rationale">Для смены папки хранения данных необходим доступ к внешнему хранилищу</string>
+ <string name="choose_data_directory_available_space">%1$s из %2$s свободно</string>
<string name="create_folder_msg">Создать папку \"%1$s\"?</string>
<string name="create_folder_success">Новая папка создана</string>
<string name="create_folder_error_no_write_access">Запись в эту папку невозможна</string>
@@ -614,13 +660,18 @@ URL файла:
<string name="episode_filters_exclude">Исключить</string>
<string name="episode_filters_hint">По одному слову \n\"По фразе\"</string>
<string name="keep_updated">Постоянно обновлять</string>
+ <string name="keep_updated_summary">Обновлять этот канал при (авто-)обновлении всех каналов</string>
+ <string name="auto_download_disabled_globally">Автоматическая загрузка отключена в основных настройках AntennaPod</string>
<!--Progress information-->
<string name="progress_upgrading_database">Обновление базы данных</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Импорт подписок из одноцелевых приложений…</string>
+ <!--Add podcast fragment-->
+ <string name="search_podcast_hint">Искать подкаст...</string>
<string name="search_itunes_label">Поиск в iTunes</string>
- <string name="filter">Фильтровать</string>
<string name="search_fyyd_label">Поиск в fyyd</string>
+ <string name="advanced_search">Расширенный поиск</string>
+ <string name="filter">Фильтровать</string>
<!--Episodes apply actions-->
<string name="all_label">Все</string>
<string name="selected_all_label">Отмечены все выпуски</string>
@@ -662,6 +713,7 @@ URL файла:
<string name="audio_effects">Звуковые эффекты</string>
<string name="stereo_to_mono">Низвести стерео до моно</string>
<string name="sonic_only">Только для Sonic</string>
+ <string name="exoplayer_only">Только ExoPlayer</string>
<!--proxy settings-->
<string name="proxy_type_label">Тип</string>
<string name="host_label">Хост</string>
@@ -675,6 +727,7 @@ URL файла:
<string name="proxy_host_invalid_error">Неверный адрес или домен хоста</string>
<string name="proxy_port_invalid_error">Неверный порт</string>
<!--Subscriptions fragment-->
+ <string name="subscription_num_columns">Количество колонок</string>
<!--Database import/export-->
<string name="import_export">Импорт/экспорт базы данных</string>
<string name="import_export_warning">Данная опытная функция поможет перенести Ваши подписки и прослушанные выпуски на другое устройство.\n\nЭкспортированные базы данных можно импортировать только в ту же версию AntennaPod. В противном случае может произойти непредвиденное.\n\nПосле импорта выпуски могут быть помечены как загруженные, хотя это и не так. Простого нажатия на кнопку воспроизведения достаточно, чтобы AntennaPod распознала такой случай.</string>
@@ -708,4 +761,5 @@ URL файла:
<string name="notification_channel_playing_description">Позволяет управлять воспроизведением. Основное уведомление, показывается при воспроизведении подкаста.</string>
<string name="notification_channel_error">Ошибки</string>
<string name="notification_channel_error_description">Показывается если что-то пошло не так, к примеру, неудавшаяся загрузка или синхронизация с gpodder.</string>
+ <string name="import_bad_file">Недопустимый или поврежденный файл</string>
</resources>
diff --git a/core/src/main/res/values-sv-rSE/strings.xml b/core/src/main/res/values-sv-rSE/strings.xml
index a44834efb..6e7fd18ef 100644
--- a/core/src/main/res/values-sv-rSE/strings.xml
+++ b/core/src/main/res/values-sv-rSE/strings.xml
@@ -111,14 +111,16 @@
<string name="podcastdirectories_label">Hitta Podcast i biblioteket</string>
<string name="podcastdirectories_descr">För att hitta nya podcasts kan du söka i iTunes, fyyd, eller på gpodder.net baserat på namn, kategori eller popularitet.</string>
<string name="browse_gpoddernet_label">Bläddra på gpodder.net</string>
+ <string name="discover">Upptäck</string>
+ <string name="discover_more">mer »</string>
<!--Actions on feeds-->
<string name="mark_all_read_label">Markera alla som spelade</string>
<string name="mark_all_read_msg">Markera alla episoder som spelade</string>
<string name="mark_all_read_confirmation_msg">Bekräfta att du verkligen vill markera alla episoder som spelade.</string>
<string name="mark_all_read_feed_confirmation_msg">Bekräfta att du vill markera alla episider i denna podcast som spelade.</string>
- <string name="remove_all_new_flags_label">Markera alla som sedda</string>
- <string name="removed_all_new_flags_msg">Markerade alla episoder som sedda</string>
- <string name="remove_all_new_flags_confirmation_msg">Bekräfta att du vill markera alla episoder som sedda.</string>
+ <string name="remove_all_new_flags_label">Ta bort alla \"ny\"-flaggor</string>
+ <string name="removed_all_new_flags_msg">Tog bort alla \"ny\"-flaggor</string>
+ <string name="remove_all_new_flags_confirmation_msg">Bekräfta att du vill ta bort alla \"ny\"-flaggor från alla episoder.</string>
<string name="show_info_label">Visa information</string>
<string name="show_feed_settings_label">Visa podcastinställningar</string>
<string name="feed_info_label">Podcastinfo</string>
@@ -169,8 +171,8 @@
<item quantity="one">1%d episod raderad.</item>
<item quantity="other">1%d episder raderade.</item>
</plurals>
- <string name="remove_new_flag_label">Markera som sedd</string>
- <string name="removed_new_flag_label">Markera som sedd</string>
+ <string name="remove_new_flag_label">Ta bort \"ny\"-flagga</string>
+ <string name="removed_new_flag_label">Tog bort \"ny\"-flagga</string>
<string name="mark_read_label">Markera som spelad</string>
<string name="marked_as_read_label">Markera som spelad</string>
<plurals name="marked_read_batch_label">
@@ -198,7 +200,6 @@
<string name="remove_from_favorite_label">Ta bort från favoriter</string>
<string name="removed_from_favorites">Borrtagen ur favoriter</string>
<string name="visit_website_label">Besök websidan</string>
- <string name="support_label">Flattra det här</string>
<string name="skip_episode_label">Hoppa över episoden</string>
<string name="activate_auto_download">Aktivera automatisk nedladdning</string>
<string name="deactivate_auto_download">Avaktivera automatisk nedladdning</string>
@@ -285,32 +286,8 @@
<string name="ascending">Stigande</string>
<string name="descending">Fallande</string>
<string name="clear_queue_confirmation_msg">Bekräfta att du vill rensa kön från ALLA episoder.</string>
- <!--Flattr-->
- <string name="flattr_auth_label">Flattr inloggning</string>
- <string name="flattr_auth_explanation">Tryck på knappen nedan för att starta autentiseringen. Du kommer att vidarebefordras till Flattrs inloggningsskärm i din webbläsare och uppmanas att ge AntennaPod tillstånd att Flattra saker. Efter att du har gett tillstånd, kommer du automatiskt tillbaka till den här skärmen.</string>
- <string name="authenticate_label">Autentisera</string>
- <string name="return_home_label">Återgå till startsidan</string>
- <string name="flattr_auth_success">Autentiseringen lyckades! Du kan nu Flattra saker i appen.</string>
- <string name="no_flattr_token_title">Ingen Flattr token hittades</string>
- <string name="no_flattr_token_notification_msg">Ditt Flattr-konto verkar inte vara anslutet till AntennaPod. Tryck här för att autentisera.</string>
- <string name="no_flattr_token_msg">Ditt Flattr konto verkar inte vara ansluten till AntennaPod. Du kan antingen ansluta ditt konto till AntennaPod att Flattra saker i app eller så kan du besöka webbplatsen för att Flattra det där.</string>
- <string name="authenticate_now_label">Autentisera</string>
- <string name="action_forbidden_title">Åtgärd förbjuden</string>
- <string name="action_forbidden_msg">AntennaPod saknar behörighet för den här åtgärden. Anledningen till detta kan vara att AntennaPods tillgång till ditt konto har återkallats. Du kan antingen åter autentisera AntennaPod eller besöka hemsidan istället.</string>
- <string name="access_revoked_title">Tillgång återkallad</string>
- <string name="access_revoked_info">Du har nu återkallat AntennaPods tillgång till ditt konto. För att slutföra processen, måste du ta bort den här appen från listan godkända appar i dina kontoinställningar på Flattrs hemsida.</string>
- <!--Flattr-->
- <string name="flattr_click_success">Flattrade en sak!</string>
- <string name="flattr_click_success_count">Flattrade %d saker!</string>
- <string name="flattr_click_success_queue">Flattrade: %s.</string>
- <string name="flattr_click_failure_count">Misslyckades att flattra %d saker!</string>
- <string name="flattr_click_failure">Ej flattrade: %s.</string>
- <string name="flattr_click_enqueued">Saker som kommer att flattras senare</string>
- <string name="flattring_thing">Flattrar %s</string>
- <string name="flattring_label">AnntennaPod flattrar</string>
- <string name="flattrd_label">AntennaPod har flattrat</string>
- <string name="flattrd_failed_label">AntennaPod misslyckades att flattra</string>
- <string name="flattr_retrieving_status">Hämtar flattrade saker</string>
+ <string name="sort_old_to_new">Gammal till ny</string>
+ <string name="sort_new_to_old">Ny till gammal</string>
<!--Variable Speed-->
<string name="download_plugin_label">Ladda ner tillägg</string>
<string name="no_playback_plugin_title">Tillägg ej installerat</string>
@@ -321,7 +298,6 @@
<string name="no_items_header_label">Inga köade episoder</string>
<string name="no_items_label">Lägg till en episod genom att ladda ner den, eller tryck länge på en episod och väl \"Lägg till i kön\".</string>
<string name="no_feeds_label">Du har inte prenumererat på några podcasts än.</string>
- <string name="no_chapters_label">Denna episod har inga kapitel.</string>
<string name="no_shownotes_label">Denna episod har inga shownotes.</string>
<string name="no_run_downloads_head_label">Inga pågående nedladdningar</string>
<string name="no_run_downloads_label">Du kan ladda ner episoder på sidan podcastdetaljer.</string>
@@ -337,6 +313,8 @@
<string name="no_new_episodes_label">När nya episoder anländer visas de här.</string>
<string name="no_fav_episodes_head_label">Inga favoritepisoder</string>
<string name="no_fav_episodes_label">Du kan lägga till episoder i favoriter genom att lång-trycka på dem.</string>
+ <string name="no_chapters_head_label">Inga kapitel</string>
+ <string name="no_chapters_label">Denna episod har inga kapitel.</string>
<!--Preferences-->
<string name="storage_pref">Lagring</string>
<string name="project_pref">Projekt</string>
@@ -344,8 +322,6 @@
<string name="about_pref">Om</string>
<string name="queue_label">Kö</string>
<string name="integrations_label">Integrationer</string>
- <string name="flattr_label">Flattr</string>
- <string name="flattr_summary">Mikrobetalningstjänst</string>
<string name="automation">Automatisering</string>
<string name="download_pref_details">Detaljer</string>
<string name="import_export_pref">Importera/Exportera</string>
@@ -353,7 +329,7 @@
<string name="appearance">Utseende</string>
<string name="external_elements">Externa element</string>
<string name="interruptions">Avbrott</string>
- <string name="buttons">Uppspelningsknappar</string>
+ <string name="playback_control">Uppspelningskontroll</string>
<string name="media_player">Mediaspelare</string>
<string name="pref_episode_cleanup_title">Episodupprensning</string>
<string name="pref_episode_cleanup_summary">Episoder som inte är i kön och inte är favoriter kan tas bort om Automatisk Nedladdning behöver utrymme för nya episoder</string>
@@ -390,20 +366,7 @@
<string name="pref_unpauseOnHeadsetReconnect_title">Hörlurar återanslutna</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Blutetooth återansluts</string>
<string name="pref_mobileUpdate_title">Mobila uppdateringar</string>
- <string name="pref_mobileUpdate_sum">Tillåt uppdateringar via mobil dataanslutning</string>
- <string name="pref_mobileUpdate_nothing">Inget</string>
- <string name="pref_mobileUpdate_images">Bara bilder</string>
- <string name="pref_mobileUpdate_everything">Allt</string>
<string name="refreshing_label">Uppdaterar</string>
- <string name="flattr_settings_label">Flattr inställningar</string>
- <string name="pref_flattr_auth_title">Flattr inloggning</string>
- <string name="pref_flattr_auth_sum">För att Flattra saker direkt från appen, logga in på ditt Flattr-konto.</string>
- <string name="pref_flattr_this_app_title">Flattra denna app</string>
- <string name="pref_flattr_this_app_sum">Stöd utvecklingen av AntennaPod genom att flattra den. Tack!</string>
- <string name="pref_revokeAccess_title">Återkalla åtkomst</string>
- <string name="pref_revokeAccess_sum">Återkalla behörigheten till ditt Flattr-konto för denna app.</string>
- <string name="pref_auto_flattr_title">Automatisk Flattring</string>
- <string name="pref_auto_flattr_sum">Konfigurerar automatisk Flattring</string>
<string name="user_interface_label">Användargränssnitt</string>
<string name="pref_set_theme_title">Välj tema</string>
<string name="pref_nav_drawer_title">Anpassa navigeringsmenyn</string>
@@ -425,6 +388,7 @@
<string name="pref_automatic_download_on_battery_sum">Tillåt automatisk nedladdning när batteriet inte laddas</string>
<string name="pref_parallel_downloads_title">Parallella nedladdningar</string>
<string name="pref_episode_cache_title">Episodcache</string>
+ <string name="pref_episode_cache_summary">Totalt antal nedladdade epidoder som ligger i enhetens cache. Automatisk nedladdning kommer att vänta om detta antal nås.</string>
<string name="pref_theme_title_light">Ljust</string>
<string name="pref_theme_title_dark">Mörkt</string>
<string name="pref_theme_title_trueblack">Svart (AMOLED redo)</string>
@@ -450,6 +414,8 @@
<string name="pref_gpodnet_notifications_sum">Denna inställning påverkar inte autentiseringsfel.</string>
<string name="pref_playback_speed_title">Uppspelningshastigheter</string>
<string name="pref_playback_speed_sum">Anpassa de tillgängliga hastigheterna för variabel uppspelningshastighet.</string>
+ <string name="pref_playback_time_respects_speed_title">Justera mediainfo till uppspelningshastigheten</string>
+ <string name="pref_playback_time_respects_speed_sum">Visad position och totallängd anpassas till uppspelningshastigheten</string>
<string name="pref_fast_forward">Snabbspolningslängd</string>
<string name="pref_fast_forward_sum">Anpassa antalet sekunder att hoppa framåt när snabbspolningsknappen används</string>
<string name="pref_rewind">Snabbspolningslängd bakåt</string>
@@ -509,11 +475,6 @@
<string name="back_button_go_to_page_title">Välj sida</string>
<string name="pref_delete_removes_from_queue_title">Radering tar bort från kön</string>
<string name="pref_delete_removes_from_queue_sum">Ta automatiskt bort episoder från kön när de raderas.</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">Aktivera automatisk Flattring</string>
- <string name="auto_flattr_after_percent">Flattra episoden så snart %d procent har spelats</string>
- <string name="auto_flattr_ater_beginning">Flattra episoden när den startas</string>
- <string name="auto_flattr_ater_end">Flattra episoden när den spelats klart</string>
<!--Search-->
<string name="search_hint">Sök efter episoder</string>
<string name="found_in_shownotes_label">Hittad i shownotes</string>
@@ -607,12 +568,14 @@
<string name="gpodnetsync_error_descr">Ett fel uppstod under synkronisering:\u0020</string>
<string name="gpodnetsync_pref_report_successful">Lyckades</string>
<string name="gpodnetsync_pref_report_failed">Misslyckades</string>
+ <string name="gpodnetsync_username_characters_error">Användarnamn får bara innehålla bokstäver, siffror, bindesstreck och understreck.</string>
<!--Directory chooser-->
<string name="selected_folder_label">Vald mapp:</string>
<string name="create_folder_label">Skapa mapp</string>
<string name="choose_data_directory">Välj Datakatalog</string>
<string name="choose_data_directory_message">Välj rotkatalogen för din data. AntennaPod skapar de underkataloger som behövs.</string>
<string name="choose_data_directory_permission_rationale">Tillgång till extern lagring krävs för att byta datakatalogen</string>
+ <string name="choose_data_directory_available_space">%1$s av %2$s ledigt</string>
<string name="create_folder_msg">Skapa ny mapp med namnet \"%1$s\"?</string>
<string name="create_folder_success">Skapade ny mapp</string>
<string name="create_folder_error_no_write_access">Kan inte skriva till den här mappen</string>
@@ -653,13 +616,18 @@
<string name="episode_filters_exclude">Exkludera</string>
<string name="episode_filters_hint">Enstaka ord \n\"Flera ord\"</string>
<string name="keep_updated">Håll uppdaterad</string>
+ <string name="keep_updated_summary">Inkludera detta flöde vid (auto-)uppdatering av flöden</string>
+ <string name="auto_download_disabled_globally">Automatisk nedladdning är avstängt i AntennaPods huvudinställningar</string>
<!--Progress information-->
<string name="progress_upgrading_database">Uppgraderar databasen</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Importerar prenumerationer från appar gjorda för ett enda syfte…</string>
+ <!--Add podcast fragment-->
+ <string name="search_podcast_hint">Sök podcast...</string>
<string name="search_itunes_label">Leta i iTunes</string>
- <string name="filter">Filtrera</string>
<string name="search_fyyd_label">Sök i fyyd</string>
+ <string name="advanced_search">Avancerad sök</string>
+ <string name="filter">Filtrera</string>
<!--Episodes apply actions-->
<string name="all_label">Alla</string>
<string name="selected_all_label">Välj alla episoder</string>
@@ -749,4 +717,5 @@
<string name="notification_channel_playing_description">Medger kontroll över uppspelning. Detta är huvudnotifieringen som du ser när en podcast spelas.</string>
<string name="notification_channel_error">Fel</string>
<string name="notification_channel_error_description">Visas om något blev fel, exempelvis om nedladdning eller gpodder synkronisering misslyckas.</string>
+ <string name="import_bad_file">Ogiltig/korrupt fil</string>
</resources>
diff --git a/core/src/main/res/values-tr/strings.xml b/core/src/main/res/values-tr/strings.xml
index 79ef2fe2c..9ec4df009 100644
--- a/core/src/main/res/values-tr/strings.xml
+++ b/core/src/main/res/values-tr/strings.xml
@@ -107,9 +107,6 @@
<string name="mark_all_read_msg">Tüm bölümleri oynatıldı olarak işaretle</string>
<string name="mark_all_read_confirmation_msg">Lütfen tüm bölümleri oynatıldı olarak işaretlemek istediğinizi onaylayın.</string>
<string name="mark_all_read_feed_confirmation_msg">Lütfen bu yayındaki bütün bölümleri oynatıldı olarak işaretlemek istediğinizi onaylayın.</string>
- <string name="remove_all_new_flags_label">Hepsini görüldü olarak işaretle</string>
- <string name="removed_all_new_flags_msg">Bütün bölümler görüldü olarak işaretlendi</string>
- <string name="remove_all_new_flags_confirmation_msg">Lütfen tüm bölümleri görüldü olarak işaretlemek istediğinizi onaylayın.</string>
<string name="show_info_label">Bilgiyi göster</string>
<string name="show_feed_settings_label">Cepyayın ayarlarını göster</string>
<string name="feed_info_label">Cepyayın bilgisi</string>
@@ -151,8 +148,6 @@
<string name="remove_label">Kaldır</string>
<string name="delete_label">Sil</string>
<string name="delete_failed">Dosya silinemiyor. Cihazı yeniden başlatmak yardımcı olabilir.</string>
- <string name="remove_new_flag_label">Hepsini görüldü olarak işaretle</string>
- <string name="removed_new_flag_label">Görüldü olarak işaretlendi</string>
<string name="mark_read_label">Oynatıldı olarak işaretle</string>
<string name="marked_as_read_label">Oynatıldı olarak işaretlendi</string>
<string name="mark_unread_label">Oynatılmadı olarak işaretle</string>
@@ -164,7 +159,6 @@
<string name="remove_from_favorite_label">Favorilerden Kaldır</string>
<string name="removed_from_favorites">Favorilerden Kaldırıldı</string>
<string name="visit_website_label">Siteyi Ziyaret Et</string>
- <string name="support_label">Flattr ile destekle</string>
<string name="skip_episode_label">Bölümü atla</string>
<string name="activate_auto_download">Otomatik indirmeyi etkinleştir</string>
<string name="deactivate_auto_download">Otomatik indirmeyi devre dışı bırak</string>
@@ -249,32 +243,6 @@
<string name="ascending">Artan</string>
<string name="descending">Azalan</string>
<string name="clear_queue_confirmation_msg">Lütfen içerisindeki BÜTÜN ölümlerle birlikte kuyruğu temizleme isteğinizi onaylayın.</string>
- <!--Flattr-->
- <string name="flattr_auth_label">Flattr giriş</string>
- <string name="flattr_auth_explanation">Yetkilendirme işlemini başlatmak için aşağıdaki butona basın. Tarayıcınızda flattr giriş ekranına yönlendirileceksiniz ve AntennaPod\'un flattr ile etkileşime girebilmesi için izniniz istenecek. İzin verdikten sonra otomatik olarak bu ekrana döneceksiniz.</string>
- <string name="authenticate_label">Yetkilendir</string>
- <string name="return_home_label">Anasayfaya dön</string>
- <string name="flattr_auth_success">Yetkilendirme başarılı! Şimdi istediğiniz şeyleri uygulama içinden flattr ile destekleyebilirsiniz.</string>
- <string name="no_flattr_token_title">Flattr jetonu bulunamadı</string>
- <string name="no_flattr_token_notification_msg">Flattr hesabınız AntennaPod ile bağlı görünmüyor. Yetkilendirme için buraya tıklayın.</string>
- <string name="no_flattr_token_msg">Flattr hesabınız AntennaPod\'a bağlanmamış. Bazı şeyleri uyuglama içinden flattr\'lamak için hesabınızı AntennaPod\'a bağlayabilirsiniz veya o şeyin sitesine gidip oradan yapabilirsiniz.</string>
- <string name="authenticate_now_label">Yetkilendir</string>
- <string name="action_forbidden_title">Yasaklanmış eylem</string>
- <string name="action_forbidden_msg">AntennaPod bu eylem için izni yok. Bunun sebebi AntennaPod\'un hesabınıza erişimi iptal edilmiş olabilir. Yeniden erişim izni verebilirsiniz veya bu şeyin web sayfasını ziyaret edebilirsiniz.</string>
- <string name="access_revoked_title">Erişim iptal edildi</string>
- <string name="access_revoked_info">AntennaPod\'un hesabınıza erişebilmesini başarıyla iptal ettiniz. İşlemi tamamlamak için flattr web sayfasındaki hesap ayarları kısmından bu uygulamayı doğrulanan uygulamalar içinden çıkarmalısınız.</string>
- <!--Flattr-->
- <string name="flattr_click_success">Bir öğe Flattr\'landı!</string>
- <string name="flattr_click_success_count">%d öğe Flattr\'landı!</string>
- <string name="flattr_click_success_queue">Flattr\'landı: %s.</string>
- <string name="flattr_click_failure_count">%d öğe Flattr\'lanamadı!</string>
- <string name="flattr_click_failure">Flattr\'lanmadı: %s.</string>
- <string name="flattr_click_enqueued">Daha sonra Flattr\'lanacak</string>
- <string name="flattring_thing">%s Flattr\'lanıyor</string>
- <string name="flattring_label">AntennaPod flattr\'lıyor</string>
- <string name="flattrd_label">AntennaPod flattr\'ladı</string>
- <string name="flattrd_failed_label">AntennaPod flattr\'layamadı</string>
- <string name="flattr_retrieving_status">Flattr\'lanan öğeler alınıyor</string>
<!--Variable Speed-->
<string name="download_plugin_label">Eklentiyi İndir</string>
<string name="no_playback_plugin_title">Eklenti Yüklenmedi</string>
@@ -283,8 +251,8 @@
<string name="enable_sonic">Sonic\'i Etkinleştir</string>
<!--Empty list labels-->
<string name="no_feeds_label">Henüz hiç bir Cepyayınına abone olmadınız.</string>
- <string name="no_chapters_label">Bu dosya herhangi bir bölüm içermiyor.</string>
<string name="no_shownotes_label">Bu dosya herhangi bir bilgi notu içermiyor.</string>
+ <string name="no_chapters_label">Bu dosya herhangi bir bölüm içermiyor.</string>
<!--Preferences-->
<string name="storage_pref">Depolama</string>
<string name="project_pref">Proje</string>
@@ -292,15 +260,12 @@
<string name="about_pref">Hakkında</string>
<string name="queue_label">Kuyruk</string>
<string name="integrations_label">Entegrasyon</string>
- <string name="flattr_label">Flattr</string>
- <string name="flattr_summary">Mikro ödeme hizmeti</string>
<string name="automation">Otomasyon</string>
<string name="download_pref_details">Detaylar</string>
<string name="import_export_pref">Al/Aktar</string>
<string name="appearance">Görünüm</string>
<string name="external_elements">Dış elemanlar</string>
<string name="interruptions">Kesintiler</string>
- <string name="buttons">Oynatıcı kontrol düğmeleri</string>
<string name="media_player">Medya oynatıcı</string>
<string name="pref_episode_cleanup_title">Bölüm Temizliği</string>
<string name="pref_episode_cleanup_summary">Yeni bölümleri otomatik indirme için alan gerekirse, kuyrukta veya favorilerde olmayan bölümler otomatik olarak silinebilir</string>
@@ -337,17 +302,7 @@
<string name="pref_unpauseOnHeadsetReconnect_title">Kulaklıklar yeniden bağlı</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Bluetooth yeniden bağlandı</string>
<string name="pref_mobileUpdate_title">Mobil güncellemeler</string>
- <string name="pref_mobileUpdate_sum">Mobil veri üzerinden güncellemelere izin ver</string>
<string name="refreshing_label">Yenileniyor</string>
- <string name="flattr_settings_label">Flattr ayarları</string>
- <string name="pref_flattr_auth_title">Flattr giriş</string>
- <string name="pref_flattr_auth_sum">Diğer şeyleri uygulama içinden Flattr\'layabilmek için Flattr hesabınıza oturum açın.</string>
- <string name="pref_flattr_this_app_title">Bu uygulamayı Flattr\'la</string>
- <string name="pref_flattr_this_app_sum">AntennaPod\'u flattr\'layarak geliştirilmesine destek olun. Teşekkürler!</string>
- <string name="pref_revokeAccess_title">Erişimi İptal et</string>
- <string name="pref_revokeAccess_sum">Bu uygulamanın flattr hesabınıza erişim iznini iptal edin.</string>
- <string name="pref_auto_flattr_title">Otomatik Flattr</string>
- <string name="pref_auto_flattr_sum">Otomatik Flattr\'lamayı Yapılandır</string>
<string name="user_interface_label">Kullanıcı Arayüzü</string>
<string name="pref_set_theme_title">Temayı seç</string>
<string name="pref_nav_drawer_title">Uygulama Çekmecesini Özelleştir</string>
@@ -397,11 +352,6 @@
<string name="send_email">E-posta gönder</string>
<string name="experimental_pref">Deneysel</string>
<string name="pref_faq">SSS</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">Otomatik Flattr\'lamayı etkinleştir</string>
- <string name="auto_flattr_after_percent">Bölümün yüzde %d kısmı oynatıldığında Flattr\'la</string>
- <string name="auto_flattr_ater_beginning">Oynatma başladığında bölümü Flattr\'la</string>
- <string name="auto_flattr_ater_end">Oynatma bittiğinde bölümü Flattr\'la</string>
<!--Search-->
<string name="found_in_chapters_label">Kısımlarda bulundu</string>
<string name="search_status_no_results">Sonuç bulunamadı</string>
@@ -520,6 +470,7 @@
<string name="progress_upgrading_database">Veritabanı yükseltiliyor</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Üyelikler tek-amaçlı uygulamalardan içe aktarılıyor...</string>
+ <!--Add podcast fragment-->
<string name="search_itunes_label">iTunes\'da Arama</string>
<!--Episodes apply actions-->
<string name="all_label">Tümü</string>
diff --git a/core/src/main/res/values-uk-rUA/strings.xml b/core/src/main/res/values-uk-rUA/strings.xml
index 18ba0c6e3..dce11d4e6 100644
--- a/core/src/main/res/values-uk-rUA/strings.xml
+++ b/core/src/main/res/values-uk-rUA/strings.xml
@@ -120,9 +120,6 @@
<string name="mark_all_read_msg">Позначено всі епізоди як відтворені</string>
<string name="mark_all_read_confirmation_msg">Будь ласка, підтвердіть що ви бажаєте позначити всі епізоди як відтворені.</string>
<string name="mark_all_read_feed_confirmation_msg">Будь ласка, підтвердіть, що ви бажаєте позначити всі епізоди цього подкасту як відтворені. </string>
- <string name="remove_all_new_flags_label">Позначити всі як переглянуті</string>
- <string name="removed_all_new_flags_msg">Всі епізоди позначено як переглянуті</string>
- <string name="remove_all_new_flags_confirmation_msg">Будь ласка, підтвердіть що ви бажаєте позначити всі епізоди як переглянуті.</string>
<string name="show_info_label">Інформація</string>
<string name="show_feed_settings_label">Показати налаштування подкасту</string>
<string name="feed_info_label">Інформація про подкаст</string>
@@ -177,8 +174,6 @@
<item quantity="many">%dепізодів видалено. </item>
<item quantity="other">%d епізодів видалено.</item>
</plurals>
- <string name="remove_new_flag_label">Позначити як переглянутий</string>
- <string name="removed_new_flag_label">Позначено як переглянутий</string>
<string name="mark_read_label">Позначити як відтворений</string>
<string name="marked_as_read_label">Позначено як відтворений</string>
<plurals name="marked_read_batch_label">
@@ -214,7 +209,6 @@
<string name="remove_from_favorite_label">Видалити з улюблених</string>
<string name="removed_from_favorites">Видалено з улюблених</string>
<string name="visit_website_label">Відкрити сайт</string>
- <string name="support_label">Підтримати за допомогою Flattr</string>
<string name="skip_episode_label">Пропустити епізод</string>
<string name="activate_auto_download">Включити автозавантаження</string>
<string name="deactivate_auto_download">Виключити автозавантаження</string>
@@ -303,32 +297,6 @@
<string name="ascending">За зростанням</string>
<string name="descending">За спаданням</string>
<string name="clear_queue_confirmation_msg">Будь ласка, підтвердіть що ви бажаєте вилучити всі епізоди з черги.</string>
- <!--Flattr-->
- <string name="flattr_auth_label">Увійти до Flattr</string>
- <string name="flattr_auth_explanation">Нажміть цю кнопку для початку авторізації. Буде відкрито flattr в браузері, буде запит на дозвіл доступу AntennaPod до flattr. Після надання доступу ви повернетесь до цього екрану автоматично</string>
- <string name="authenticate_label">Ввісти ім\'я та пароль</string>
- <string name="return_home_label">Повернення до початку</string>
- <string name="flattr_auth_success">Вдала авторизація. Тепер ви можете flattr things за допомогою додатку</string>
- <string name="no_flattr_token_title">Немає flattr token</string>
- <string name="no_flattr_token_notification_msg">Ваш обліковий запис flattr, здається, не підключений до AntennaPod. Натисніть тут для підключення.</string>
- <string name="no_flattr_token_msg">Здається ваш обліковий запис flattr не під\'єднано до AntennaPod. Ви можете або під\'єднати її або відкривати web сторінку в браузері</string>
- <string name="authenticate_now_label">Пароль та логін</string>
- <string name="action_forbidden_title">Заборонено</string>
- <string name="action_forbidden_msg">AntennaPod не маэ дозвілу це зробити. Можливо відкликаний доступ до AntennaPod. Або ввідіть логін пароль в налаштуваннях або зробить це на сайті</string>
- <string name="access_revoked_title">Доступ відкликано</string>
- <string name="access_revoked_info">Ви відкликали доступ AntennaPod до облікового запису. Для закінчення процессу вам потрібно видалити додаток з затвержденного списку в вашому облікову запису на сайті flattr</string>
- <!--Flattr-->
- <string name="flattr_click_success">Підтримано через Flattr!</string>
- <string name="flattr_click_success_count">Flattr\'ed %d things!</string>
- <string name="flattr_click_success_queue">Підтримано через Flattr: %s.</string>
- <string name="flattr_click_failure_count">Failed to flattr %d things!</string>
- <string name="flattr_click_failure">Не підтримано через flattr: %s.</string>
- <string name="flattr_click_enqueued">Буде підтримано через flattr пізніше</string>
- <string name="flattring_thing">Flattring %s</string>
- <string name="flattring_label">AntennaPod is flattring</string>
- <string name="flattrd_label">AntennaPod has flattr\'ed</string>
- <string name="flattrd_failed_label">AntennaPod flattr failed</string>
- <string name="flattr_retrieving_status">Retrieving flattr\'ed things</string>
<!--Variable Speed-->
<string name="download_plugin_label">Завантажити додаток</string>
<string name="no_playback_plugin_title">Додаток не встановлено</string>
@@ -339,7 +307,6 @@
<string name="no_items_header_label">В черзі немає епізодів.</string>
<string name="no_items_label">Додайте епізод, завантаживши його, або довго натиснувши на нього і вибравши \"Додати до черги\".</string>
<string name="no_feeds_label">Ви ще не підписалися на жодні подкасти.</string>
- <string name="no_chapters_label">В цьому епізоді немає розділів.</string>
<string name="no_shownotes_label">До цього епізода немає нотаток.</string>
<string name="no_run_downloads_head_label">Зараз нічого не завантажується.</string>
<string name="no_run_downloads_label">Завантажувати епізоди можна з детального перегляда подкаста.</string>
@@ -355,6 +322,7 @@
<string name="no_new_episodes_label">Коли з’являться нові епізоди, іх буде показано тут.</string>
<string name="no_fav_episodes_head_label">Немає улюблених епізодів</string>
<string name="no_fav_episodes_label">Ви можете додавати епізоди до улюблених за допомогою довгого натискання.</string>
+ <string name="no_chapters_label">В цьому епізоді немає розділів.</string>
<!--Preferences-->
<string name="storage_pref">Зберігання</string>
<string name="project_pref">Проект</string>
@@ -362,8 +330,6 @@
<string name="about_pref">Про програму</string>
<string name="queue_label">Черга</string>
<string name="integrations_label">Інтеграції</string>
- <string name="flattr_label">Flattr</string>
- <string name="flattr_summary">Сервіс мікроплатежів</string>
<string name="automation">Автоматизація</string>
<string name="download_pref_details">Детально</string>
<string name="import_export_pref">Імпорт/Експорт</string>
@@ -371,7 +337,6 @@
<string name="appearance">Вигляд</string>
<string name="external_elements">Зовнішні елементи</string>
<string name="interruptions">Тимчасові паузи</string>
- <string name="buttons">Кнопки керування відтворенням</string>
<string name="media_player">Медіа програвач</string>
<string name="pref_episode_cleanup_title">Очищення епізодів</string>
<string name="pref_episode_cleanup_summary">Епізоди що не знаходяться в черзі та не помічені як улюблені можуть бути видалені якщо Автозавантажувач потребуватиме місце для нових епізодів.</string>
@@ -408,20 +373,7 @@
<string name="pref_unpauseOnHeadsetReconnect_title">Повторне під’єднання навушників</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Повторне під’єднання блютуз</string>
<string name="pref_mobileUpdate_title">Мобільне оновлення</string>
- <string name="pref_mobileUpdate_sum">Дозволити оновлення через оператора зв\'язку</string>
- <string name="pref_mobileUpdate_nothing">Нічого</string>
- <string name="pref_mobileUpdate_images">Тільки зображення</string>
- <string name="pref_mobileUpdate_everything">Все</string>
<string name="refreshing_label">Оновлення</string>
- <string name="flattr_settings_label">Налаштування Flattr</string>
- <string name="pref_flattr_auth_title">Увійти до Flattr</string>
- <string name="pref_flattr_auth_sum">Увійти в облікову flattr для підтримки авторів напряму з додатку</string>
- <string name="pref_flattr_this_app_title">Підтримати цей додаток за допомогою Flattr</string>
- <string name="pref_flattr_this_app_sum">Підтримайте розробку AntennaPod за допомогою flattr. Дякую!</string>
- <string name="pref_revokeAccess_title">Відкликати доступ</string>
- <string name="pref_revokeAccess_sum">Відкликати дозвіл на доступ до вашого flattr з цього додатку</string>
- <string name="pref_auto_flattr_title">Automatic Flattr</string>
- <string name="pref_auto_flattr_sum">Налаштування автоматичного заохочення авторів через сервіс flattr</string>
<string name="user_interface_label">Вигляд</string>
<string name="pref_set_theme_title">Обрати тему</string>
<string name="pref_nav_drawer_title">Налаштувати меню навігації</string>
@@ -527,11 +479,6 @@
<string name="back_button_go_to_page_title">Вибрати сторінку</string>
<string name="pref_delete_removes_from_queue_title">Видалення з черги видалених епізодів</string>
<string name="pref_delete_removes_from_queue_sum">Автоматично видаляти епізод із черги, коли він буде видалений.</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">Включити автоматичне заохочення авторів через сервіс flattr</string>
- <string name="auto_flattr_after_percent">Заохотити автора через Flattr щойно %d відсотків епізода було відтворено</string>
- <string name="auto_flattr_ater_beginning">Заохотити автора через Flattr коли починається відтворення</string>
- <string name="auto_flattr_ater_end">Заохотити автора через Flattr коли закінчується відтворення</string>
<!--Search-->
<string name="search_hint">Пошук епізодів</string>
<string name="found_in_shownotes_label">Знайдено в нотатках епізода</string>
@@ -681,9 +628,10 @@
<string name="progress_upgrading_database">Оновлення бази даних</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Імпорт подкастів з інших програм...</string>
+ <!--Add podcast fragment-->
<string name="search_itunes_label">Пошук в iTunes</string>
- <string name="filter">Фільтр</string>
<string name="search_fyyd_label">Шукати в fyyd</string>
+ <string name="filter">Фільтр</string>
<!--Episodes apply actions-->
<string name="all_label">Всі</string>
<string name="selected_all_label">Обрано всі епізоди</string>
diff --git a/core/src/main/res/values-v16/styles.xml b/core/src/main/res/values-v16/styles.xml
index a92790152..947e43f38 100644
--- a/core/src/main/res/values-v16/styles.xml
+++ b/core/src/main/res/values-v16/styles.xml
@@ -6,12 +6,4 @@
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:fontFamily">sans-serif-light</item>
</style>
-
- <style name="AntennaPod.Dialog.Title" parent="@android:style/TextAppearance.Medium">
- <item name="android:textSize">@dimen/text_size_medium</item>
- <item name="android:textColor">@color/holo_blue_light</item>
- <item name="android:maxLines">2</item>
- <item name="android:ellipsize">end</item>
- <item name="android:fontFamily">sans-serif-light</item>
- </style>
</resources> \ No newline at end of file
diff --git a/core/src/main/res/values-v19/colors.xml b/core/src/main/res/values-v19/colors.xml
index 16c065d75..4154280e8 100644
--- a/core/src/main/res/values-v19/colors.xml
+++ b/core/src/main/res/values-v19/colors.xml
@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="selection_background_color_dark">#484B4D</color>
- <color name="selection_background_color_light">#E3E3E3</color>
</resources> \ No newline at end of file
diff --git a/core/src/main/res/values-zh-rCN/strings.xml b/core/src/main/res/values-zh-rCN/strings.xml
index 0d9188b0e..5bc57c0c7 100644
--- a/core/src/main/res/values-zh-rCN/strings.xml
+++ b/core/src/main/res/values-zh-rCN/strings.xml
@@ -109,23 +109,36 @@
<string name="podcastdirectories_label">从目录中寻找播客</string>
<string name="podcastdirectories_descr">您可以在 gpodder.net 通过名称、类别或热门来搜索新播客</string>
<string name="browse_gpoddernet_label">浏览 gpodder.net</string>
+ <string name="discover">发现</string>
+ <string name="discover_more">更多</string>
<!--Actions on feeds-->
<string name="mark_all_read_label">全部标识已读</string>
<string name="mark_all_read_msg">将所有曲目标记为已播放</string>
<string name="mark_all_read_confirmation_msg">请确认您要将所有曲目标为已播放</string>
- <string name="remove_all_new_flags_label">所有可见</string>
- <string name="remove_all_new_flags_confirmation_msg">请确认您要将所有曲目标记为已读。</string>
+ <string name="mark_all_read_feed_confirmation_msg">请确认您想将该播客中的所有节目标记为播放</string>
+ <string name="remove_all_new_flags_label">移除所有“新”标签</string>
+ <string name="removed_all_new_flags_msg">移除了所有“新”标签</string>
+ <string name="remove_all_new_flags_confirmation_msg">请确认您想从所有节目中移除“新”标签</string>
<string name="show_info_label">查看信息</string>
+ <string name="show_feed_settings_label">显示播客设置</string>
<string name="feed_info_label">播客信息</string>
<string name="feed_settings_label">播客设置</string>
<string name="rename_feed_label">重命名播客</string>
<string name="remove_feed_label">移除播客</string>
<string name="share_label">分享</string>
+ <string name="share_link_label">分享剧集地址</string>
+ <string name="share_link_with_position_label">分享带播放位置的节目地址</string>
<string name="share_file_label">分享文件</string>
<string name="share_feed_url_label">分享订阅地址</string>
+ <string name="share_item_url_label">分享媒体文件地址</string>
+ <string name="share_item_url_with_position_label">分享带播放位置的媒体文件地址</string>
+ <string name="feed_delete_confirmation_msg">请确认您想删除播客“1%1$s” 及其所有节目(包括已经下载的)</string>
<string name="feed_remover_msg">正在移除播客</string>
+ <string name="load_complete_feed">刷新整档博客</string>
<string name="hide_episodes_title">隐藏曲目</string>
<string name="batch_edit">批量编辑</string>
+ <string name="select_all_above">选中上面所有</string>
+ <string name="select_all_below">选中下面所有</string>
<string name="hide_unplayed_episodes_label">未播放</string>
<string name="hide_paused_episodes_label">已暂停</string>
<string name="hide_played_episodes_label">已播放</string>
@@ -133,11 +146,16 @@
<string name="hide_not_queued_episodes_label">不在播放列表中</string>
<string name="hide_downloaded_episodes_label">已下载</string>
<string name="hide_not_downloaded_episodes_label">未下载</string>
+ <string name="hide_has_media_label">包含媒体文件</string>
+ <string name="hide_is_favorite_label">喜爱的</string>
<string name="filtered_label">已过滤的</string>
<string name="refresh_failed_msg">{fa-exclamation-circle} 上次刷新失败</string>
<string name="open_podcast">打开播客</string>
<!--actions on feeditems-->
<string name="download_label">下载</string>
+ <plurals name="downloading_batch_label">
+ <item quantity="other">正下载1%d个音频节目</item>
+ </plurals>
<string name="play_label">播放</string>
<string name="pause_label">暂停</string>
<string name="stop_label">停止</string>
@@ -145,20 +163,35 @@
<string name="remove_label">删除</string>
<string name="delete_label">删除</string>
<string name="delete_failed">无法删除文件。重启可能解决该问题。</string>
- <string name="remove_new_flag_label">标记为已读</string>
- <string name="removed_new_flag_label">标记为已读</string>
+ <string name="delete_episode_label">删除节目</string>
+ <plurals name="deleted_episode_batch_label">
+ <item quantity="other">已删除1%d个节目</item>
+ </plurals>
+ <string name="remove_new_flag_label">移除“新的”标签</string>
+ <string name="removed_new_flag_label">已移除“新的”标签</string>
<string name="mark_read_label">标记已播放</string>
<string name="marked_as_read_label">已标记为已播放</string>
+ <plurals name="marked_read_batch_label">
+ <item quantity="other">已将1%d个节目标记为已播放</item>
+ </plurals>
<string name="mark_unread_label">标记未播放</string>
+ <plurals name="marked_unread_batch_label">
+ <item quantity="other">已将1%d个节目标记为未播放</item>
+ </plurals>
<string name="add_to_queue_label">添加到播放列表</string>
<string name="added_to_queue_label">已添加到播放列表</string>
+ <plurals name="added_to_queue_batch_label">
+ <item quantity="other">已将1%d个节目添加到序列中</item>
+ </plurals>
<string name="remove_from_queue_label">从播放列表中删除</string>
+ <plurals name="removed_from_queue_batch_label">
+ <item quantity="other">已从序列中移除1%d个节目</item>
+ </plurals>
<string name="add_to_favorite_label">加入收藏</string>
<string name="added_to_favorites">添加到收藏</string>
<string name="remove_from_favorite_label">从收藏删除</string>
<string name="removed_from_favorites">从收藏中移除</string>
<string name="visit_website_label">访问网站</string>
- <string name="support_label">Flattr 他</string>
<string name="skip_episode_label">跳过曲目</string>
<string name="activate_auto_download">开启自动下载</string>
<string name="deactivate_auto_download">关闭自动下载</string>
@@ -242,59 +275,69 @@
<string name="ascending">升序</string>
<string name="descending">降序</string>
<string name="clear_queue_confirmation_msg">请确认您要清除队列中的全部曲目</string>
- <!--Flattr-->
- <string name="flattr_auth_label">Flattr 登录</string>
- <string name="flattr_auth_explanation">按下面的按钮开始身份验证过程. 将在浏览器中打开 Flattr 登录界面并要求给予 AntennaPod 访问 Flattr 的权限. 权限许可后, 将自动回到这个界面.</string>
- <string name="authenticate_label">验证</string>
- <string name="return_home_label">返回主页</string>
- <string name="flattr_auth_success">验证成功! 现在可以使用应用内 Flattr 相关功能了.</string>
- <string name="no_flattr_token_title">没有找到 Flattr 验证令牌信息</string>
- <string name="no_flattr_token_notification_msg">您的 flattr 账户似乎并没有连接到 AntennaPod,点这里验证。</string>
- <string name="no_flattr_token_msg">您的 flattr 账户似乎并没有连接到 AntennaPod. 您可以关联您的账户到AntennaPod以便在应用内flattr条目,或者您可以自己访问条目的网站完成flattr</string>
- <string name="authenticate_now_label">验证</string>
- <string name="action_forbidden_title">被禁止</string>
- <string name="action_forbidden_msg">AntennaPod 没有权限执行本动作. 原因可能是: AntennaPod 对您账户的访问令牌被撤销. 你可以重新\"验证\"或访问该网站来授权.</string>
- <string name="access_revoked_title">撤销访问</string>
- <string name="access_revoked_info">您已经成功撤销 AntennaPod 对账户令牌的访问. 为了完成这个过程, 您必须到 Flattr 网站 \"账户设置-&gt;已批准应用\" 列表内删除本应用.</string>
- <!--Flattr-->
- <string name="flattr_click_success">成功Flattr一个条目</string>
- <string name="flattr_click_success_count">成功Flattr%d个条目</string>
- <string name="flattr_click_success_queue">Flattr%s成功.</string>
- <string name="flattr_click_failure_count">Flattr失败%d个条目</string>
- <string name="flattr_click_failure">%sFlattr失败.</string>
- <string name="flattr_click_enqueued">稍后将Flattr该条目</string>
- <string name="flattring_thing">正在Flattr%s</string>
- <string name="flattring_label">AntennaPod正在Flattr</string>
- <string name="flattrd_label">AntennaPod已经Flattr</string>
- <string name="flattrd_failed_label">AntennaPod Flattr失败</string>
- <string name="flattr_retrieving_status">查询Flattr结果状态</string>
+ <string name="sort_old_to_new">从旧到新</string>
+ <string name="sort_new_to_old">从新到旧</string>
<!--Variable Speed-->
<string name="download_plugin_label">插件下载</string>
<string name="no_playback_plugin_title">插件没有安装</string>
+ <string name="no_playback_plugin_or_sonic_msg">为使可变速度回放正常工作,我们建议启用内置的Sonic媒体播放器[安卓系统4.1以上]您也可以从谷歌商城下载第三方插件1 Prestissimo1 ,但任何有关该插件的问题均非AntennaPod的责任,应当报告插件所有者</string>
<string name="set_playback_speed_label">播放速度</string>
<string name="enable_sonic">允许声音</string>
<!--Empty list labels-->
- <string name="no_chapters_label">此曲目没有章节信息</string>
+ <string name="no_items_header_label">没有处在播放列表的曲目</string>
+ <string name="no_items_label">通过下载或者长按一项剧集再选择“添加到播放列表”以添加剧集</string>
+ <string name="no_feeds_label">您尚未订阅任何播客</string>
<string name="no_shownotes_label">本集不包含展示信息</string>
+ <string name="no_run_downloads_head_label">没有正在运行的下载</string>
+ <string name="no_run_downloads_label">您可以在播客的详情界面下载曲目</string>
+ <string name="no_comp_downloads_head_label">没有已下载的剧集</string>
+ <string name="no_comp_downloads_label">您可以在播客的详情界面下载曲目</string>
+ <string name="no_log_downloads_head_label">没有下载日志</string>
+ <string name="no_log_downloads_label">可用的下载日志会显示在这里</string>
+ <string name="no_history_head_label">没有历史</string>
+ <string name="no_history_label">在您收听一项剧集之后,它会显示在这里。</string>
+ <string name="no_all_episodes_head_label">无节目</string>
+ <string name="no_all_episodes_label">当您添加一个播客时,节目会显示在此处</string>
+ <string name="no_new_episodes_head_label">没有新的曲目</string>
+ <string name="no_new_episodes_label">当新节目到来,它们会显示在此处</string>
+ <string name="no_fav_episodes_head_label">没有收藏的曲目</string>
+ <string name="no_fav_episodes_label">您可以通过长按曲目将其添加至收藏</string>
+ <string name="no_chapters_head_label">无章节</string>
+ <string name="no_chapters_label">此曲目没有章节信息</string>
<!--Preferences-->
<string name="storage_pref">存储</string>
<string name="project_pref">项目</string>
<string name="other_pref">其他</string>
<string name="about_pref">关于</string>
<string name="queue_label">播放列表</string>
- <string name="flattr_label">Flattr</string>
+ <string name="integrations_label">插件</string>
+ <string name="automation">自动化</string>
+ <string name="download_pref_details">细节</string>
<string name="import_export_pref">导入/导出</string>
<string name="import_export_search_keywords">数据, 备份, 还原, backup, restore</string>
<string name="appearance">样式</string>
+ <string name="external_elements">外部元素</string>
+ <string name="interruptions">中断</string>
+ <string name="playback_control">回放控制</string>
+ <string name="media_player">媒体播放器</string>
<string name="pref_episode_cleanup_title">清理曲目</string>
+ <string name="pref_episode_cleanup_summary">如果自动下载需要为新剧集腾出空间时不在列表和收藏里的剧集可以被移除</string>
<string name="pref_pauseOnDisconnect_sum">暂停播放曲目当耳机或蓝牙重新连接</string>
<string name="pref_unpauseOnHeadsetReconnect_sum">当耳机重新连接时恢复播放</string>
<string name="pref_unpauseOnBluetoothReconnect_sum">恢复播放曲目当蓝牙重新连接</string>
+ <string name="pref_hardwareForwardButtonSkips_title"> 快进按钮跳过曲目</string>
+ <string name="pref_hardwareForwardButtonSkips_sum">当按压一个蓝牙连接设备的快进按钮时跳到下一项曲目而不是快进</string>
+ <string name="pref_hardwarePreviousButtonRestarts_title">“上一个”按钮重启</string>
+ <string name="pref_hardwarePreviousButtonRestarts_sum">当按压硬件上一个按钮时重新开始播放当前曲目而不是倒回</string>
<string name="pref_followQueue_sum">播放完成跳转到播放列表下一项</string>
<string name="pref_auto_delete_sum">当播放完成后删除曲目</string>
<string name="pref_auto_delete_title">自动删除</string>
<string name="pref_smart_mark_as_played_sum">当曲目的剩余未播放时间小于一个确定值时将其表为已播放</string>
<string name="pref_smart_mark_as_played_title">智能标记为已播放</string>
+ <string name="pref_skip_keeps_episodes_sum">当剧集被跳过时保留它们</string>
+ <string name="pref_skip_keeps_episodes_title">保留跳过的剧集</string>
+ <string name="pref_favorite_keeps_episodes_sum">当剧集被收藏时保留它们</string>
+ <string name="pref_favorite_keeps_episodes_title">保留收藏的剧集</string>
<string name="playback_pref">播放</string>
<string name="network_pref">网络</string>
<string name="pref_autoUpdateIntervallOrTime_title">定时更新</string>
@@ -312,18 +355,7 @@
<string name="pref_unpauseOnHeadsetReconnect_title">耳机重新连接</string>
<string name="pref_unpauseOnBluetoothReconnect_title">蓝牙重新连接</string>
<string name="pref_mobileUpdate_title">数据网络时更新</string>
- <string name="pref_mobileUpdate_sum">允许移动数据网络情况下进行数据链接</string>
<string name="refreshing_label">刷新中</string>
- <string name="flattr_settings_label">Flattr 设置</string>
- <string name="pref_flattr_auth_title">Flattr 登录</string>
- <string name="pref_flattr_auth_sum">登录 Flattr 账户, 以便直接使用本应用中的相关功能.</string>
- <string name="pref_flattr_this_app_title">Flattr 本应用</string>
- <string name="pref_flattr_this_app_sum">支持 AntennaPod 发展, 请 Flattring 他. 谢谢!!
-</string>
- <string name="pref_revokeAccess_title">撤销访问</string>
- <string name="pref_revokeAccess_sum">撤销访问本应用对您 Flattr 账户的访问权限.</string>
- <string name="pref_auto_flattr_title">自动Flattr</string>
- <string name="pref_auto_flattr_sum">设置自动 flattring</string>
<string name="user_interface_label">界面</string>
<string name="pref_set_theme_title">主题选择</string>
<string name="pref_nav_drawer_title">侧边栏设置</string>
@@ -333,15 +365,20 @@
<string name="pref_nav_drawer_feed_order_title">设置订阅的排序方式</string>
<string name="pref_nav_drawer_feed_order_sum">改变你的订阅的排序方式</string>
<string name="pref_nav_drawer_feed_counter_title">设定订阅数</string>
+ <string name="pref_nav_drawer_feed_counter_sum">更改订阅计数器显示的信息。 如果“订阅的排序顺序”设置为“按数量排序”,这也会影响订阅的排序。</string>
<string name="pref_set_theme_sum">改变 AntennaPod 外观</string>
<string name="pref_automatic_download_title">自动下载</string>
<string name="pref_automatic_download_sum">配置自动下载的曲目</string>
<string name="pref_autodl_wifi_filter_title">打开 Wi-Fi 过滤器</string>
<string name="pref_autodl_wifi_filter_sum">只允许在 Wi-Fi 网络下自动下载</string>
+ <string name="pref_autodl_allow_on_mobile_title">移动数据连接时下载</string>
+ <string name="pref_autodl_allow_on_mobile_sum">允许在数据连接下自动下载</string>
<string name="pref_automatic_download_on_battery_title">未充电时下载</string>
<string name="pref_automatic_download_on_battery_sum">未充电时允许自动下载</string>
<string name="pref_parallel_downloads_title">并行下载</string>
<string name="pref_episode_cache_title">曲目缓存</string>
+ <string name="pref_episode_cache_summary">缓存在设备上的已下载节目总数
+若达到此数目,自动下载将被暂停</string>
<string name="pref_theme_title_light">浅色</string>
<string name="pref_theme_title_dark">暗色</string>
<string name="pref_theme_title_trueblack">纯黑(适用于 AMOLED 设备)</string>
@@ -356,7 +393,9 @@
<string name="pref_gpodnet_setlogin_information_title">改变登录信息</string>
<string name="pref_gpodnet_setlogin_information_sum">改变 gpodder.net 账户登录信息.</string>
<string name="pref_gpodnet_sync_changes_title">立即同步改动</string>
+ <string name="pref_gpodnet_sync_changes_sum">和gpodder.net同步订阅和节目状态</string>
<string name="pref_gpodnet_full_sync_title">立即完整同步</string>
+ <string name="pref_gpodnet_full_sync_sum">与gpodder.net同步所有订阅和节目状态</string>
<string name="pref_gpodnet_sync_sum_last_sync_line">最后同步尝试于:%1$s(%2$s)</string>
<string name="pref_gpodnet_sync_started">已开始同步</string>
<string name="pref_gpodnet_full_sync_started">完整同步以开始</string>
@@ -365,10 +404,16 @@
<string name="pref_gpodnet_notifications_sum">该设置无法适用于验证错误。</string>
<string name="pref_playback_speed_title">播放速度</string>
<string name="pref_playback_speed_sum">自定义音频播放速度</string>
+ <string name="pref_playback_time_respects_speed_title">根据回放速度调整媒体信息</string>
+ <string name="pref_playback_time_respects_speed_sum">显示的播放位置和持续时间已根据回放速度进行调整</string>
+ <string name="pref_fast_forward">快进跳过时间</string>
<string name="pref_fast_forward_sum">自定义每次快进节目的秒数</string>
+ <string name="pref_rewind">倒回跳过时间</string>
<string name="pref_rewind_sum">自定义每次倒回节目的秒数</string>
<string name="pref_gpodnet_sethostname_title">设置主机名</string>
<string name="pref_gpodnet_sethostname_use_default_host">使用默认主机</string>
+ <string name="pref_expandNotify_title">高通知优先级</string>
+ <string name="pref_expandNotify_sum">这通常会拓展通知以显示播放按钮。</string>
<string name="pref_persistNotify_title">保持播放控制</string>
<string name="pref_persistNotify_sum">在暂停时保持通知和锁屏界面的控制。</string>
<string name="pref_compact_notification_buttons_title">设置锁屏按钮</string>
@@ -389,6 +434,7 @@
<string name="crash_report_sum">通过 E-mail 发送最后崩溃报告</string>
<string name="send_email">发送 E-mail</string>
<string name="experimental_pref">实验性</string>
+ <string name="pref_media_player_message">选择使用哪个媒体播放器来播放文件</string>
<string name="pref_current_value">当前值:%1$s</string>
<string name="pref_proxy_title">代理</string>
<string name="pref_proxy_sum">选择一个网络代理</string>
@@ -398,17 +444,33 @@
<string name="pref_cast_title">Chromecast 支持</string>
<string name="pref_cast_message_play_flavor">启用在 Cast 设备(例如 Chromecast 、 Audio Speakers 和 Android TV )上对于远端媒体回放的支持</string>
<string name="pref_cast_message_free_flavor">Chromecast 所需要的第三方库文件在这个版本的 AntennaPod 中被禁用</string>
+ <string name="pref_enqueue_downloaded_title">已下载队列</string>
<string name="pref_enqueue_downloaded_summary">向队列添加已下载的节目</string>
+ <string name="media_player_builtin">内置安卓播放器</string>
+ <string name="pref_skip_silence_title">跳过没有声音的音频</string>
+ <string name="pref_videoBehavior_title">退出视频后</string>
+ <string name="pref_videoBehavior_sum">离开视频播放后的行为</string>
+ <string name="stop_playback">停止播放</string>
+ <string name="continue_playback">继续播放音频</string>
+ <string name="behavior">行为</string>
+ <string name="pref_back_button_behavior_title">返回键行为</string>
+ <string name="pref_back_button_behavior_sum">改变返回键的行为</string>
<string name="back_button_default">默认</string>
<string name="back_button_open_drawer">打开导航抽屉</string>
- <!--Auto-Flattr dialog-->
- <string name="auto_flattr_enable">启用自动 flattring</string>
- <string name="auto_flattr_after_percent">当播放到百分之%d时Flattr改曲目</string>
- <string name="auto_flattr_ater_beginning">当播放开始时Flattr改曲目</string>
- <string name="auto_flattr_ater_end">当播放结束时Flattr改曲目</string>
+ <string name="back_button_double_tap">双击退出</string>
+ <string name="back_button_show_prompt">确认退出</string>
+ <string name="close_prompt">您确定想要关闭AntennaPod吗?</string>
+ <string name="double_tap_toast">再次点按返回键以退出</string>
+ <string name="back_button_go_to_page">前往页面</string>
+ <string name="back_button_go_to_page_title">选择页面</string>
+ <string name="pref_delete_removes_from_queue_title">删除队列间距</string>
+ <string name="pref_delete_removes_from_queue_sum">剧集被删除时自动将其移除列表</string>
<!--Search-->
<string name="search_hint">查找节目</string>
+ <string name="found_in_shownotes_label">在节目笔记中找到</string>
<string name="found_in_chapters_label">章节中查找</string>
+ <string name="found_in_authors_label">在作者中找到</string>
+ <string name="found_in_feeds_label">在播客中找到</string>
<string name="search_status_no_results">没有找到任何结果</string>
<string name="search_label">搜索</string>
<string name="found_in_title_label">标题中查找</string>
@@ -434,6 +496,8 @@
<string name="html_export_label">导出为 HTML 文件</string>
<string name="exporting_label">正在导出</string>
<string name="export_error_label">导出出错</string>
+ <string name="export_success_title">成功导出</string>
+ <string name="export_success_sum">导出文件被写入:\n\n 1%1$s</string>
<string name="opml_import_ask_read_permission">读取 OPML 文件需要访问外部存储的权限</string>
<!--Sleep timer-->
<string name="set_sleeptimer_label">设置休眠计时器</string>
@@ -491,6 +555,7 @@
<string name="gpodnetsync_error_descr">同步过程中发生错误: \u0020</string>
<string name="gpodnetsync_pref_report_successful">成功了</string>
<string name="gpodnetsync_pref_report_failed">失败了</string>
+ <string name="gpodnetsync_username_characters_error">用户名只能包含字母、数字、连字符和下划线</string>
<!--Directory chooser-->
<string name="selected_folder_label">已选文件夹:</string>
<string name="create_folder_label">穿件文件夹</string>
@@ -532,16 +597,22 @@
<string name="authentication_descr">给本播客及曲目变更用户名及密码</string>
<string name="auto_download_settings_label">自动下载设置</string>
<string name="episode_filters_label">曲目过滤器</string>
+ <string name="episode_filters_description">条款列表曾用于确定是否应在自动下载时包含或排除剧集</string>
<string name="episode_filters_include">包含</string>
<string name="episode_filters_exclude">排除</string>
<string name="keep_updated">保持最新</string>
+ <string name="keep_updated_summary">(自动)刷新所有源时包含该源</string>
+ <string name="auto_download_disabled_globally">AntennaPod主设置中已禁用自动下载</string>
<!--Progress information-->
<string name="progress_upgrading_database">升级数据库</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">正在从选定的应用中导入订阅...</string>
+ <!--Add podcast fragment-->
+ <string name="search_podcast_hint">搜索播客……</string>
<string name="search_itunes_label">搜索 iTunes</string>
+ <string name="search_fyyd_label">搜索 fydd</string>
+ <string name="advanced_search">高级搜索</string>
<string name="filter">过滤器</string>
- <string name="search_fyyd_label">在 fyyd 上搜索</string>
<!--Episodes apply actions-->
<string name="all_label">全部</string>
<string name="selected_all_label">全选</string>
@@ -559,6 +630,8 @@
<string name="selected_queued_label">已选曲目</string>
<string name="not_queued_label">不在播放列表中</string>
<string name="selected_not_queued_label">选择不在播放列表的曲目</string>
+ <string name="has_media">包含媒体</string>
+ <string name="selected_has_media_label">已选中含媒体的节目</string>
<!--Sort-->
<string name="sort_title_a_z">标题 (A \u2192 Z)</string>
<string name="sort_title_z_a">标题 (Z \u2192 A)</string>
@@ -579,7 +652,9 @@
<string name="left_short">L</string>
<string name="right_short">R</string>
<string name="audio_effects">音频效果</string>
+ <string name="stereo_to_mono">下降混合:由立体声到单声道</string>
<string name="sonic_only">仅声音</string>
+ <string name="exoplayer_only">仅ExoPlayer</string>
<!--proxy settings-->
<string name="proxy_type_label">类型</string>
<string name="host_label">主机地址</string>
@@ -593,18 +668,39 @@
<string name="proxy_host_invalid_error">主机地址为无效的IP地址或域名</string>
<string name="proxy_port_invalid_error">端口不可用</string>
<!--Subscriptions fragment-->
+ <string name="subscription_num_columns">列数</string>
<!--Database import/export-->
+ <string name="import_export">数据库导入/导出</string>
+ <string name="import_export_warning">此实验功能可将您订阅和播放的剧集转移到另一台设备。\ n \ n导出的数据库只有在使用相同版本的 AntennaPod 时才能导入。 否则,此功能将导致意外行为。\ n \ n剧集被导入后,可能会显示为已下载,如果它们没有。 只需点击剧集的播放按钮即可使 AntennaPod 检测到状态。</string>
<string name="label_import">导入</string>
<string name="label_export">导出</string>
+ <string name="import_select_file">选择导入文件</string>
<string name="export_ok">导出成功。</string>
+ <string name="import_ok">成功导入,请按OK重启AntennaPod</string>
<!--Casting-->
+ <string name="cast_media_route_menu_title">投影路径</string>
+ <string name="cast_disconnect_label">断开投影会话</string>
+ <string name="cast_not_castable">选中的媒体文件不兼容投影设备</string>
<string name="cast_failed_to_play">媒体回放开始失败</string>
<string name="cast_failed_to_stop">媒体回放停止失败</string>
<string name="cast_failed_to_pause">媒体回放暂停失败</string>
<!--<string name="cast_failed_to_connect">Could not connect to the device</string>-->
<string name="cast_failed_setting_volume">音量设置失败</string>
+ <string name="cast_failed_no_connection">与投影设备间无连接</string>
+ <string name="cast_failed_no_connection_trans">与投影设备间的连接已丢失。程序正尝试重新建立连接。请等待数秒并再次尝试。</string>
+ <string name="cast_failed_perform_action">未能执行动作</string>
+ <string name="cast_failed_status_request">未能与投影设备同步</string>
+ <string name="cast_failed_seek">未能在投影设备上找到新播放位置</string>
+ <string name="cast_failed_receiver_player_error">接收播放器遇到一个严重错误</string>
<string name="cast_failed_media_error_skipping">媒体播放出错.跳转中...</string>
<!--Notification channels-->
+ <string name="notification_channel_user_action">需要操作</string>
+ <string name="notification_channel_user_action_description">显示是否需要您的操作,比如是否需要您输入一个密码</string>
<string name="notification_channel_downloading">正在下载</string>
+ <string name="notification_channel_downloading_description">下载时显示</string>
+ <string name="notification_channel_playing">当前播放</string>
+ <string name="notification_channel_playing_description">允许控制回放。这是播放播客时您所见的主通知。</string>
<string name="notification_channel_error">错误</string>
+ <string name="notification_channel_error_description">发生错误时显示,比如下载或与gpodder的同步失败</string>
+ <string name="import_bad_file">无效/损坏文件</string>
</resources>
diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml
index 8190a39e2..795d06d8d 100644
--- a/core/src/main/res/values/arrays.xml
+++ b/core/src/main/res/values/arrays.xml
@@ -168,19 +168,15 @@
<item>4.00</item>
</string-array>
- <string-array name="autodl_select_networks_default_entries">
- <item>N/A</item>
- </string-array>
- <string-array name="autodl_select_networks_default_values">
- <item>0</item>
- </string-array>
-
<string-array name="theme_options">
+ <item>@string/pref_theme_title_use_system</item>
<item>@string/pref_theme_title_light</item>
<item>@string/pref_theme_title_dark</item>
<item>@string/pref_theme_title_trueblack</item>
</string-array>
+
<string-array name="theme_values">
+ <item>system</item>
<item>0</item>
<item>1</item>
<item>2</item>
diff --git a/core/src/main/res/values/attrs.xml b/core/src/main/res/values/attrs.xml
index eb7f065ce..530b40d46 100644
--- a/core/src/main/res/values/attrs.xml
+++ b/core/src/main/res/values/attrs.xml
@@ -9,6 +9,7 @@
<attr name="av_fast_forward" format="reference"/>
<attr name="av_pause" format="reference"/>
<attr name="av_play" format="reference"/>
+ <attr name="av_speed" format="reference"/>
<attr name="av_rewind" format="reference"/>
<attr name="content_discard" format="reference"/>
<attr name="content_new" format="reference"/>
@@ -56,9 +57,9 @@
<attr name="ic_cast_disconnect" format="reference"/>
<attr name="ic_swap" format="reference"/>
<attr name="ic_cellphone_text" format="reference"/>
- <attr name="ic_question_answer" format="reference" />
+ <attr name="ic_questionmark" format="reference" />
+ <attr name="ic_chat" format="reference"/>
<attr name="ic_bug" format="reference" />
- <attr name="ic_known_issues" format="reference" />
<attr name="master_switch_background" format="color"/>
<attr name="currently_playing_background" format="color"/>
<attr name="ic_bookmark" format="reference"/>
@@ -74,4 +75,5 @@
<attr name="about_screen_card_background" format="color"/>
<attr name="about_screen_card_border" format="color"/>
<attr name="about_screen_font_color" format="color"/>
+ <attr name="batch_edit_fab_icon" format="reference"/>
</resources>
diff --git a/core/src/main/res/values/colors.xml b/core/src/main/res/values/colors.xml
index 5d820f3cf..fea7da4a4 100644
--- a/core/src/main/res/values/colors.xml
+++ b/core/src/main/res/values/colors.xml
@@ -2,30 +2,20 @@
<resources>
<color name="white">#FFFFFF</color>
- <color name="gray">#808080</color>
<color name="grey600">#757575</color>
<color name="light_gray">#bfbfbf</color>
<color name="black">#000000</color>
<color name="holo_blue_light">#33B5E5</color>
<color name="holo_blue_dark">#0099CC</color>
- <color name="ics_gray">#858585</color>
- <color name="actionbar_gray">#DDDDDD</color>
<color name="download_success_green">#669900</color>
<color name="download_failed_red">#CC0000</color>
<color name="status_progress">#E033B5E5</color>
- <color name="status_playing">#E0EE5F52</color>
<color name="overlay_dark">#2C2C2C</color>
<color name="overlay_light">#FFFFFF</color>
- <color name="swipe_refresh_secondary_color_light">#EDEDED</color>
- <color name="swipe_refresh_secondary_color_dark">#060708</color>
<color name="new_indicator_green">#669900</color>
<color name="image_readability_tint">#80000000</color>
<color name="feed_image_bg">#50000000</color>
- <color name="selection_background_color_trueblack">#286E8A</color>
- <color name="selection_background_color_dark">#286E8A</color>
- <color name="selection_background_color_light">#81CFEA</color>
-
<!-- Theme colors -->
<color name="primary_light">#FFFFFF</color>
<color name="primary_darktheme">#212121</color>
diff --git a/core/src/main/res/values/dimens.xml b/core/src/main/res/values/dimens.xml
index cdde0027d..02c398b62 100644
--- a/core/src/main/res/values/dimens.xml
+++ b/core/src/main/res/values/dimens.xml
@@ -10,7 +10,6 @@
<dimen name="text_size_navdrawer">16sp</dimen>
<dimen name="text_size_medium">18sp</dimen>
<dimen name="text_size_large">22sp</dimen>
- <dimen name="status_indicator_width">32dp</dimen>
<dimen name="thumbnail_length_itemlist">64dp</dimen>
<dimen name="thumbnail_length_queue_item">64dp</dimen>
<dimen name="thumbnail_length_downloaded_item">64dp</dimen>
@@ -21,7 +20,6 @@
<dimen name="drawer_width">280dp</dimen>
<dimen name="listitem_iconwithtext_height">48dp</dimen>
<dimen name="listitem_iconwithtext_textleftpadding">16dp</dimen>
- <dimen name="listitem_iconwithtext_textverticalpadding">16dp</dimen>
<dimen name="listitem_threeline_textleftpadding">16dp</dimen>
<dimen name="listitem_threeline_textrightpadding">8dp</dimen>
@@ -29,7 +27,6 @@
<dimen name="listitem_threeline_horizontalpadding">16dp</dimen>
<dimen name="list_vertical_padding">8dp</dimen>
- <dimen name="minimum_text_margin">8dp</dimen>
<dimen name="listitem_icon_leftpadding">16dp</dimen>
<dimen name="listitem_icon_rightpadding">16dp</dimen>
diff --git a/core/src/main/res/values/integers.xml b/core/src/main/res/values/integers.xml
index 33501d9fb..73d90cf98 100644
--- a/core/src/main/res/values/integers.xml
+++ b/core/src/main/res/values/integers.xml
@@ -1,4 +1,3 @@
<resources>
- <integer name="undobar_hide_delay">5000</integer>
<integer name="episode_cache_size_unlimited">-1</integer>
</resources>
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index 717d2302d..5b6e9eed6 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -27,10 +27,8 @@
<string name="gpodnet_main_label">gpodder.net</string>
<string name="gpodnet_summary">Synchronize with other devices</string>
<string name="gpodnet_auth_label">gpodder.net Login</string>
- <string name="free_space_label">%1$s free</string>
<string name="episode_cache_full_title">Episode cache full</string>
<string name="episode_cache_full_message">The episode cache limit has been reached. You can increase the cache size in the Settings.</string>
- <string name="synchronizing">Synchronizing…</string>
<!-- Statistics fragment -->
<string name="total_time_listened_to_podcasts">Total time of podcasts played:</string>
@@ -73,7 +71,6 @@
<string name="author_label">Author(s)</string>
<string name="language_label">Language</string>
<string name="url_label">URL</string>
- <string name="podcast_settings_label">Settings</string>
<string name="cover_label">Picture</string>
<string name="error_label">Error</string>
<string name="error_msg_prefix">An error occurred:</string>
@@ -82,14 +79,9 @@
<string name="external_storage_error_msg">No external storage is available. Please make sure that external storage is mounted so that the app can work properly.</string>
<string name="chapters_label">Chapters</string>
<string name="chapter_duration">Duration: %1$s</string>
- <string name="shownotes_label">Shownotes</string>
<string name="description_label">Description</string>
- <string name="most_recent_prefix">Most recent episode:\u0020</string>
<string name="episodes_suffix">\u0020episodes</string>
- <string name="length_prefix">Length:\u0020</string>
- <string name="size_prefix">Size:\u0020</string>
<string name="processing_label">Processing</string>
- <string name="loading_label">Loading&#8230;</string>
<string name="save_username_password_label">Save username and password</string>
<string name="close_label">Close</string>
<string name="retry_label">Retry</string>
@@ -123,8 +115,6 @@
<string name="feedurl_label">Feed URL</string>
<string name="etxtFeedurlHint">www.example.com/feed</string>
<string name="txtvfeedurl_label">Add Podcast by URL</string>
- <string name="podcastdirectories_label">Find Podcast in Directory</string>
- <string name="podcastdirectories_descr">For new podcasts, you can search iTunes or fyyd, or browse gpodder.net by name, category or popularity.</string>
<string name="browse_gpoddernet_label">Browse gpodder.net</string>
<string name="discover">Discover</string>
<string name="discover_more">more »</string>
@@ -147,13 +137,13 @@
<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 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>
<string name="feed_remover_msg">Removing podcast</string>
<string name="load_complete_feed">Refresh complete podcast</string>
- <string name="hide_episodes_title">Hide Episodes</string>
<string name="batch_edit">Batch edit</string>
<string name="select_all_above">Select all above</string>
<string name="select_all_below">Select all below</string>
@@ -178,9 +168,7 @@
</plurals>
<string name="play_label">Play</string>
<string name="pause_label">Pause</string>
- <string name="stop_label">Stop</string>
<string name="stream_label">Stream</string>
- <string name="remove_label">Remove</string>
<string name="delete_label">Delete</string>
<string name="delete_failed">Unable to delete file. Rebooting the device could help.</string>
<string name="delete_episode_label">Delete Episode</string>
@@ -225,14 +213,12 @@
<!-- Download messages and labels -->
<string name="download_successful">successful</string>
- <string name="download_failed">failed</string>
<string name="download_pending">Download pending</string>
<string name="download_running">Download running</string>
<string name="download_error_details">Details</string>
<string name="download_error_details_message">%1$s \n\nFile URL:\n%2$s</string>
<string name="download_error_device_not_found">Storage Device not found</string>
<string name="download_error_insufficient_space">Insufficient Space</string>
- <string name="download_error_file_error">File Error</string>
<string name="download_error_http_data_error">HTTP Data Error</string>
<string name="download_error_error_unknown">Unknown Error</string>
<string name="download_error_parser_exception">Parser Exception</string>
@@ -242,7 +228,6 @@
<string name="download_error_unauthorized">Authentication Error</string>
<string name="download_error_file_type_type">File Type Error</string>
<string name="download_error_forbidden">Forbidden</string>
- <string name="cancel_all_downloads_label">Cancel all downloads</string>
<string name="download_canceled_msg">Download canceled</string>
<string name="download_canceled_autodownload_enabled_msg">Download canceled\nDisabled <i>Auto Download</i> for this item</string>
<string name="download_report_title">Downloads completed with error(s)</string>
@@ -261,7 +246,6 @@
<string name="download_log_title_unknown">Unknown Title</string>
<string name="download_type_feed">Feed</string>
<string name="download_type_media">Media file</string>
- <string name="download_type_image">Image</string>
<string name="download_request_error_dialog_message_prefix">An error occurred when trying to download the file:\u0020</string>
<string name="null_value_podcast_error">No podcast was provided that could be shown.</string>
<string name="authentication_notification_title">Authentication required</string>
@@ -271,6 +255,7 @@
<string name="confirm_mobile_download_dialog_message">Downloading over mobile data connection is disabled in the settings.\n\nDo you want to allow downloading temporarily?\n\n<small>Your choice will be remembered for 10 minutes.</small></string>
<string name="confirm_mobile_streaming_notification_title">Confirm Mobile streaming</string>
<string name="confirm_mobile_streaming_notification_message">Streaming over mobile data connection is disabled in the settings. Tap to stream anyway.</string>
+ <string name="confirm_mobile_streaming_button_always">Always allow</string>
<string name="confirm_mobile_download_dialog_only_add_to_queue">Enqueue</string>
<string name="confirm_mobile_download_dialog_enable_temporarily">Allow temporarily</string>
@@ -281,12 +266,13 @@
<string name="player_ready_msg">Ready</string>
<string name="player_seeking_msg">Seeking</string>
<string name="playback_error_server_died">Server died</string>
+ <string name="playback_error_unsupported">Unsupported media type</string>
+ <string name="playback_error_timeout">Operation timed out</string>
<string name="playback_error_unknown">Unknown Error</string>
<string name="no_media_playing_label">No media playing</string>
<string name="position_default_label" translate="false">00:00:00</string>
<string name="player_buffering_msg">Buffering</string>
<string name="player_go_to_picture_in_picture">Picture-in-picture mode</string>
- <string name="playbackservice_notification_title">Playing podcast</string>
<string name="unknown_media_key">AntennaPod - Unknown media key: %1$d</string>
<!-- Queue operations -->
@@ -294,9 +280,10 @@
<string name="unlock_queue">Unlock Queue</string>
<string name="queue_locked">Queue locked</string>
<string name="queue_unlocked">Queue unlocked</string>
+ <string name="queue_lock_warning">If you lock the queue, you can no longer swipe or reorder episodes.</string>
+ <string name="checkbox_do_not_show_again">Do not show again</string>
<string name="clear_queue_label">Clear Queue</string>
<string name="undo">Undo</string>
- <string name="removed_from_queue">Item removed</string>
<string name="move_to_top_label">Move to top</string>
<string name="move_to_bottom_label">Move to bottom</string>
<string name="sort">Sort</string>
@@ -323,7 +310,6 @@
<!-- Empty list labels -->
<string name="no_items_header_label">No queued episodes</string>
<string name="no_items_label">Add an episode by downloading it, or long press an episode and select \"Add to queue\".</string>
- <string name="no_feeds_label">You haven\'t subscribed to any podcasts yet.</string>
<string name="no_shownotes_label">This episode has no shownotes.</string>
<string name="no_run_downloads_head_label">No downloads running</string>
<string name="no_run_downloads_label">You can download episodes on the podcast details screen.</string>
@@ -345,7 +331,6 @@
<!-- Preferences -->
<string name="storage_pref">Storage</string>
<string name="project_pref">Project</string>
- <string name="other_pref">Other</string>
<string name="about_pref">About</string>
<string name="queue_label">Queue</string>
<string name="integrations_label">Integrations</string>
@@ -357,6 +342,9 @@
<string name="external_elements">External elements</string>
<string name="interruptions">Interruptions</string>
<string name="playback_control">Playback control</string>
+ <string name="preference_search_hint">Search…</string>
+ <string name="preference_search_no_results">No results</string>
+ <string name="preference_search_clear_history">Clear history</string>
<string name="media_player">Media player</string>
<string name="pref_episode_cleanup_title">Episode Cleanup</string>
<string name="pref_episode_cleanup_summary">Episodes that aren\'t in the queue and aren\'t favorites should be eligible for removal if Auto Download needs space for new episodes</string>
@@ -386,9 +374,7 @@
<string name="pref_autoUpdateIntervallOrTime_TimeOfDay">Set Time of Day</string>
<string name="pref_autoUpdateIntervallOrTime_every">every %1$s</string>
<string name="pref_autoUpdateIntervallOrTime_at">at %1$s</string>
- <string name="pref_downloadMediaOnWifiOnly_sum">Download media files only over WiFi</string>
<string name="pref_followQueue_title">Continuous Playback</string>
- <string name="pref_downloadMediaOnWifiOnly_title">WiFi media download</string>
<string name="pref_pauseOnHeadsetDisconnect_title">Headphones Disconnect</string>
<string name="pref_unpauseOnHeadsetReconnect_title">Headphones Reconnect</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Bluetooth Reconnect</string>
@@ -399,11 +385,8 @@
<string name="pref_mobileUpdate_auto_download">Auto download</string>
<string name="pref_mobileUpdate_episode_download">Episode download</string>
<string name="pref_mobileUpdate_streaming">Streaming</string>
- <string name="refreshing_label">Refreshing</string>
<string name="user_interface_label">User Interface</string>
<string name="pref_set_theme_title">Select Theme</string>
- <string name="pref_nav_drawer_title">Customize Navigation Drawer</string>
- <string name="pref_nav_drawer_sum">Customize the appearance of the navigation drawer.</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>
<string name="pref_nav_drawer_feed_order_title">Set Subscription Order</string>
@@ -415,13 +398,14 @@
<string name="pref_automatic_download_sum">Configure the automatic download of episodes.</string>
<string name="pref_autodl_wifi_filter_title">Enable Wi-Fi filter</string>
<string name="pref_autodl_wifi_filter_sum">Allow automatic download only for selected Wi-Fi networks.</string>
- <string name="pref_autodl_allow_on_mobile_title">Download on mobile connection</string>
- <string name="pref_autodl_allow_on_mobile_sum">Allow automatic download over the mobile data connection.</string>
+ <string name="autodl_wifi_filter_permission_title">Permission required</string>
+ <string name="autodl_wifi_filter_permission_message">Location permission is required for Wi-Fi filter. Tap to grant the permission.</string>
<string name="pref_automatic_download_on_battery_title">Download when not charging</string>
<string name="pref_automatic_download_on_battery_sum">Allow automatic download when the battery is not charging</string>
<string name="pref_parallel_downloads_title">Parallel Downloads</string>
<string name="pref_episode_cache_title">Episode Cache</string>
<string name="pref_episode_cache_summary">Total number of downloaded episodes cached on the device. Automatic download will be suspended if this number is reached.</string>
+ <string name="pref_theme_title_use_system">Use system theme</string>
<string name="pref_theme_title_light">Light</string>
<string name="pref_theme_title_dark">Dark</string>
<string name="pref_theme_title_trueblack">Black (AMOLED ready)</string>
@@ -441,7 +425,6 @@
<string name="pref_gpodnet_full_sync_sum">Sync all subscriptions and episode states with gpodder.net.</string>
<string name="pref_gpodnet_sync_sum_last_sync_line">Last sync attempt: %1$s (%2$s)</string>
<string name="pref_gpodnet_sync_started">Sync started</string>
- <string name="pref_gpodnet_full_sync_started">Full sync started</string>
<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>
@@ -473,16 +456,17 @@
<string name="pref_smart_mark_as_played_disabled">Disabled</string>
<string name="pref_image_cache_size_title">Image Cache Size</string>
<string name="pref_image_cache_size_sum">Size of the disk cache for images.</string>
- <string name="crash_report_title">Crash Report</string>
- <string name="crash_report_sum">Send the latest crash report via e-mail</string>
- <string name="send_email">Send e-mail</string>
+ <string name="view_mailing_list">View mailing list</string>
+ <string name="bug_report_title">Report bug</string>
+ <string name="open_bug_tracker">Open bug tracker</string>
+ <string name="copy_to_clipboard">Copy to clipboard</string>
+ <string name="copied_to_clipboard">Copied to clipboard</string>
<string name="experimental_pref">Experimental</string>
<string name="pref_media_player_message">Select which media player to use to play files</string>
<string name="pref_current_value">Current value: %1$s</string>
<string name="pref_proxy_title">Proxy</string>
<string name="pref_proxy_sum">Set a network proxy</string>
- <string name="pref_faq">FAQ</string>
- <string name="pref_known_issues">Known issues</string>
+ <string name="pref_faq">Frequently Asked Questions</string>
<string name="pref_no_browser_found">No web browser found.</string>
<string name="pref_cast_title">Chromecast support</string>
<string name="pref_cast_message_play_flavor">Enable support for remote media playback on Cast devices (such as Chromecast, Audio Speakers or Android TV)</string>
@@ -523,21 +507,16 @@
<string name="no_results_for_query">No results were found for \"%1$s\"</string>
<!-- OPML import and export -->
- <string name="opml_import_txtv_button_lable">OPML files allow you to move your podcasts from one podcatcher to another.</string>
<string name="opml_import_option">Option %1$d</string>
<string name="opml_import_explanation_1">Choose a specific file path from the local filesystem.</string>
- <string name="opml_import_explanation_2">Use an external applications like Dropbox, Google Drive or your favourite file manager to open an OPML file.</string>
- <string name="opml_import_explanation_3">Many applications like Google Mail, Dropbox, Google Drive and most file managers can <i>open</i> OPML files <i>with</i> AntennaPod.</string> <string name="start_import_label">Start import</string>
+ <string name="opml_import_explanation_3">Many applications like Google Mail, Dropbox, Google Drive and most file managers can <i>open</i> OPML files <i>with</i> AntennaPod.</string>
<string name="opml_import_label">OPML Import</string>
- <string name="opml_directory_error">ERROR!</string>
<string name="reading_opml_label">Reading OPML file</string>
<string name="opml_reader_error">An error has occurred while reading the OPML document:</string>
<string name="opml_import_error_no_file">No file selected!</string>
<string name="select_all_label">Select all</string>
<string name="deselect_all_label">Deselect all</string>
- <string name="select_options_label">Select&#8230;</string>
<string name="choose_file_from_filesystem">From local filesystem</string>
- <string name="choose_file_from_external_application">Use external application</string>
<string name="opml_export_label">OPML export</string>
<string name="html_export_label">HTML export</string>
<string name="exporting_label">Exporting&#8230;</string>
@@ -636,7 +615,6 @@
<!-- Online feed view -->
<string name="subscribe_label">Subscribe</string>
- <string name="subscribed_label">Subscribed</string>
<string name="downloading_label">Downloading&#8230;</string>
<!-- Content descriptions for image buttons -->
@@ -759,7 +737,6 @@
<string name="cast_failed_setting_volume">Failed to set the volume</string>
<string name="cast_failed_no_connection">No connection to the cast device is present</string>
<string name="cast_failed_no_connection_trans">Connection to the cast device has been lost. Application is trying to re-establish the connection, if possible. Please wait for a few seconds and try again.</string>
- <string name="cast_failed_perform_action">Failed to perform the action</string>
<string name="cast_failed_status_request">Failed to sync up with the cast device</string>
<string name="cast_failed_seek">Failed to seek to the new position on the cast device</string>
<string name="cast_failed_receiver_player_error">Receiver player has encountered a severe error</string>
diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml
index 4c69306a9..d2ba4bb50 100644
--- a/core/src/main/res/values/styles.xml
+++ b/core/src/main/res/values/styles.xml
@@ -23,6 +23,7 @@
<item name="av_fast_forward">@drawable/ic_fast_forward_grey600_24dp</item>
<item name="av_pause">@drawable/ic_pause_grey600_24dp</item>
<item name="av_play">@drawable/ic_play_arrow_grey600_24dp</item>
+ <item name="av_speed">@drawable/ic_playback_speed_dark</item>
<item name="av_rewind">@drawable/ic_fast_rewind_grey600_24dp</item>
<item name="content_discard">@drawable/ic_delete_grey600_24dp</item>
<item name="content_new">@drawable/ic_add_grey600_24dp</item>
@@ -68,10 +69,11 @@
<item name="ic_create_new_folder">@drawable/ic_create_new_folder_grey600_24dp</item>
<item name="ic_cast_disconnect">@drawable/ic_cast_disconnect_grey600_36dp</item>
<item name="ic_cellphone_text">@drawable/ic_cellphone_text_grey600_24dp</item>
- <item name="ic_question_answer">@drawable/ic_forum_grey600_24dp</item>
+ <item name="ic_questionmark">@drawable/ic_questionmark_grey600</item>
+ <item name="ic_chat">@drawable/ic_chat_grey600</item>
<item name="ic_bug">@drawable/ic_bug_grey600_24dp</item>
- <item name="ic_known_issues">@drawable/ic_format_list_bulleted_grey600_24dp</item>
<item name="ic_bookmark">@drawable/ic_bookmark_grey600_24dp</item>
+ <item name="batch_edit_fab_icon">@drawable/ic_fab_edit_white</item>
<item name="master_switch_background">@color/master_switch_background_light</item>
<item name="currently_playing_background">@color/highlight_light</item>
@@ -107,6 +109,7 @@
<item name="av_fast_forward">@drawable/ic_fast_forward_white_24dp</item>
<item name="av_pause">@drawable/ic_pause_white_24dp</item>
<item name="av_play">@drawable/ic_play_arrow_white_24dp</item>
+ <item name="av_speed">@drawable/ic_playback_speed_white</item>
<item name="av_rewind">@drawable/ic_fast_rewind_white_24dp</item>
<item name="content_discard">@drawable/ic_delete_white_24dp</item>
<item name="content_new">@drawable/ic_add_white_24dp</item>
@@ -152,10 +155,11 @@
<item name="ic_create_new_folder">@drawable/ic_create_new_folder_white_24dp</item>
<item name="ic_cast_disconnect">@drawable/ic_cast_disconnect_white_36dp</item>
<item name="ic_cellphone_text">@drawable/ic_cellphone_text_white_24dp</item>
- <item name="ic_question_answer">@drawable/ic_baseline_question_answer_white_24dp</item>
+ <item name="ic_questionmark">@drawable/ic_questionmark_white</item>
+ <item name="ic_chat">@drawable/ic_chat_white</item>
<item name="ic_bug">@drawable/ic_bug_white_24dp</item>
- <item name="ic_known_issues">@drawable/ic_format_list_bulleted_white_24dp</item>
<item name="ic_bookmark">@drawable/ic_bookmark_white_24dp</item>
+ <item name="batch_edit_fab_icon">@drawable/ic_fab_edit_white</item>
<item name="master_switch_background">@color/master_switch_background_dark</item>
<item name="currently_playing_background">@color/highlight_dark</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
@@ -176,6 +180,7 @@
<item name="overlay_background">@color/black</item>
<item name="overlay_drawable">@drawable/overlay_drawable_dark_trueblack</item>
<item name="dragview_background">@drawable/ic_drag_vertical_white_48dp</item>
+ <item name="batch_edit_fab_icon">@drawable/ic_fab_edit_black</item>
<item name="dragview_float_background">@color/black</item>
<item name="nav_drawer_background">@color/black</item>
<item name="drawer_activated_color">@color/highlight_trueblack</item>
@@ -213,23 +218,10 @@
<!-- Room for API dependent attributes -->
</style>
- <style name="Theme.Base.AntennaPod.TrueBlack.NoTitle" parent="Theme.Base.AntennaPod.Dark.NoTitle">
- <item name="progressBarTheme">@style/ProgressBarTrueBlack</item>
- <item name="non_transparent_background">@color/black</item>
- <item name="overlay_background">@color/black</item>
- <item name="overlay_drawable">@drawable/overlay_drawable_dark_trueblack</item>
- <item name="dragview_background">@drawable/ic_drag_vertical_white_48dp</item>
- <item name="dragview_float_background">@color/black</item>
- <item name="nav_drawer_background">@color/black</item>
- <item name="drawer_activated_color">@color/highlight_trueblack</item>
- <item name="currently_playing_background">@color/highlight_trueblack</item>
- <item name="android:textColorPrimary">@color/white</item>
- <item name="android:color">@color/white</item>
- <item name="android:colorBackground">@color/black</item>
- <item name="android:windowBackground">@color/black</item>
- <item name="android:actionBarStyle">@color/black</item>
- <item name="colorPrimary">@color/black</item>
- <item name="colorPrimaryDark">@color/black</item>
+ <style name="Theme.Base.AntennaPod.TrueBlack.NoTitle" parent="Theme.Base.AntennaPod.TrueBlack">
+ <item name="windowActionBar">false</item>
+ <item name="windowNoTitle">true</item>
+ <item name="windowActionModeOverlay">true</item>
</style>
@@ -268,13 +260,6 @@
<item name="android:ellipsize">end</item>
</style>
- <style name="AntennaPod.Dialog.Title" parent="@android:style/TextAppearance.Medium">
- <item name="android:textSize">@dimen/text_size_medium</item>
- <item name="android:textColor">?android:attr/textColorPrimary</item>
- <item name="android:maxLines">2</item>
- <item name="android:ellipsize">end</item>
- </style>
-
<style name="AntennaPod.TextView.UnreadIndicator" parent="@android:style/TextAppearance.Small">
<item name="android:textSize">@dimen/text_size_micro</item>
<item name="android:textColor">@color/new_indicator_green</item>
@@ -286,16 +271,6 @@
<item name="textAllCaps">false</item>
</style>
- <style name="Divider">
- <item name="android:layout_width">match_parent</item>
- <item name="android:layout_height">1dp</item>
- <item name="android:layout_marginTop">8dp</item>
- <item name="android:layout_marginLeft">16dp</item>
- <item name="android:layout_marginRight">16dp</item>
- <item name="android:layout_marginBottom">8dp</item>
- <item name="android:background">?android:attr/listDivider</item>
- </style>
-
<style name="AntennaPod.Dialog.Light" parent="Theme.AppCompat.Light.Dialog">
<item name="colorAccent">@color/holo_blue_light</item>
</style>
diff --git a/core/src/play/java/de/danoeh/antennapod/core/ClientConfig.java b/core/src/play/java/de/danoeh/antennapod/core/ClientConfig.java
index 862fe23f5..800222ada 100644
--- a/core/src/play/java/de/danoeh/antennapod/core/ClientConfig.java
+++ b/core/src/play/java/de/danoeh/antennapod/core/ClientConfig.java
@@ -1,6 +1,7 @@
package de.danoeh.antennapod.core;
import android.content.Context;
+import android.util.Log;
import de.danoeh.antennapod.core.cast.CastManager;
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
@@ -8,12 +9,15 @@ import de.danoeh.antennapod.core.preferences.SleepTimerPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.danoeh.antennapod.core.util.NetworkUtils;
+import de.danoeh.antennapod.core.util.exception.RxJavaErrorHandlerSetup;
/**
* Stores callbacks for core classes like Services, DB classes etc. and other configuration variables.
* Apps using the core module of AntennaPod should register implementations of all interfaces here.
*/
public class ClientConfig {
+ private static final String TAG = "ClientConfig";
+
private ClientConfig(){}
/**
@@ -36,15 +40,24 @@ public class ClientConfig {
private static boolean initialized = false;
public static synchronized void initialize(Context context) {
- if(initialized) {
+ if (initialized) {
return;
}
PodDBAdapter.init(context);
UserPreferences.init(context);
PlaybackPreferences.init(context);
NetworkUtils.init(context);
- CastManager.init(context);
+ // Don't initialize Cast-related logic unless it is enabled, to avoid the unnecessary
+ // Google Play Service usage.
+ // Down side: when the user decides to enable casting, AntennaPod needs to be restarted
+ // for it to take effect.
+ if (UserPreferences.isCastEnabled()) {
+ CastManager.init(context);
+ } else {
+ Log.v(TAG, "Cast is disabled. All Cast-related initialization will be skipped.");
+ }
SleepTimerPreferences.init(context);
+ RxJavaErrorHandlerSetup.setupRxJavaErrorHandler();
initialized = true;
}
diff --git a/core/src/play/java/de/danoeh/antennapod/core/cast/CastManager.java b/core/src/play/java/de/danoeh/antennapod/core/cast/CastManager.java
index 5198a76bd..414a7840c 100644
--- a/core/src/play/java/de/danoeh/antennapod/core/cast/CastManager.java
+++ b/core/src/play/java/de/danoeh/antennapod/core/cast/CastManager.java
@@ -163,6 +163,10 @@ public class CastManager extends BaseCastManager implements OnFailedListener {
return INSTANCE;
}
+ public static boolean isInitialized() {
+ return INSTANCE != null;
+ }
+
/**
* Returns the active {@link RemoteMediaPlayer} instance. Since there are a number of media
* control APIs that this library do not provide a wrapper for, client applications can call
diff --git a/core/src/play/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceFlavorHelper.java b/core/src/play/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceFlavorHelper.java
index 7ab1be380..79c71f164 100644
--- a/core/src/play/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceFlavorHelper.java
+++ b/core/src/play/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceFlavorHelper.java
@@ -56,11 +56,18 @@ public class PlaybackServiceFlavorHelper {
PlaybackServiceFlavorHelper(Context context, PlaybackService.FlavorHelperCallback callback) {
this.callback = callback;
+ if (!CastManager.isInitialized()) {
+ return;
+ }
mediaRouter = MediaRouter.getInstance(context.getApplicationContext());
setCastConsumer(context);
}
void initializeMediaPlayer(Context context) {
+ if (!CastManager.isInitialized()) {
+ callback.setMediaPlayer(new LocalPSMP(context, callback.getMediaPlayerCallback()));
+ return;
+ }
castManager = CastManager.getInstance();
castManager.addCastConsumer(castConsumer);
boolean isCasting = castManager.isConnected();
@@ -77,10 +84,16 @@ public class PlaybackServiceFlavorHelper {
}
void removeCastConsumer() {
+ if (!CastManager.isInitialized()) {
+ return;
+ }
castManager.removeCastConsumer(castConsumer);
}
boolean castDisconnect(boolean castDisconnect) {
+ if (!CastManager.isInitialized()) {
+ return false;
+ }
if (castDisconnect) {
castManager.disconnect();
}
@@ -88,6 +101,9 @@ public class PlaybackServiceFlavorHelper {
}
boolean onMediaPlayerInfo(Context context, int code, @StringRes int resourceId) {
+ if (!CastManager.isInitialized()) {
+ return false;
+ }
switch (code) {
case RemotePSMP.CAST_ERROR:
callback.sendNotificationBroadcast(PlaybackService.NOTIFICATION_TYPE_SHOW_TOAST, resourceId);
@@ -218,6 +234,9 @@ public class PlaybackServiceFlavorHelper {
}
void registerWifiBroadcastReceiver() {
+ if (!CastManager.isInitialized()) {
+ return;
+ }
if (wifiBroadcastReceiver != null) {
return;
}
@@ -243,6 +262,9 @@ public class PlaybackServiceFlavorHelper {
}
void unregisterWifiBroadcastReceiver() {
+ if (!CastManager.isInitialized()) {
+ return;
+ }
if (wifiBroadcastReceiver != null) {
callback.unregisterReceiver(wifiBroadcastReceiver);
wifiBroadcastReceiver = null;
@@ -250,6 +272,9 @@ public class PlaybackServiceFlavorHelper {
}
boolean onSharedPreference(String key) {
+ if (!CastManager.isInitialized()) {
+ return false;
+ }
if (UserPreferences.PREF_CAST_ENABLED.equals(key)) {
if (!UserPreferences.isCastEnabled()) {
if (castManager.isConnecting() || castManager.isConnected()) {
@@ -263,6 +288,9 @@ public class PlaybackServiceFlavorHelper {
}
void sessionStateAddActionForWear(PlaybackStateCompat.Builder sessionState, String actionName, CharSequence name, int icon) {
+ if (!CastManager.isInitialized()) {
+ return;
+ }
PlaybackStateCompat.CustomAction.Builder actionBuilder =
new PlaybackStateCompat.CustomAction.Builder(actionName, name, icon);
Bundle actionExtras = new Bundle();
@@ -273,6 +301,9 @@ public class PlaybackServiceFlavorHelper {
}
void mediaSessionSetExtraForWear(MediaSessionCompat mediaSession) {
+ if (!CastManager.isInitialized()) {
+ return;
+ }
Bundle sessionExtras = new Bundle();
sessionExtras.putBoolean(MediaControlConstants.EXTRA_RESERVE_SLOT_SKIP_TO_PREVIOUS, true);
sessionExtras.putBoolean(MediaControlConstants.EXTRA_RESERVE_SLOT_SKIP_TO_NEXT, true);
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 5f1b1201a..f4d7b2bf6 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.4-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists