diff options
Diffstat (limited to 'app')
140 files changed, 1806 insertions, 896 deletions
diff --git a/app/build.gradle b/app/build.gradle index 1b5d8b713..4b44cf80c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -98,7 +98,14 @@ android { } lintOptions { - abortOnError false + disable 'ObsoleteLintCustomCheck', 'CheckResult', 'UnusedAttribute', 'BatteryLife', 'InflateParams', + 'GradleDependency', 'RestrictedApi', 'TrustAllX509TrustManager', 'ExportedReceiver', 'AllowBackup', + 'StaticFieldLeak', 'UseCompoundDrawables', 'NestedWeights', 'Overdraw', 'UselessParent', 'TextFields', + 'AlwaysShowAction', 'Autofill', 'ClickableViewAccessibility', 'ContentDescription', + 'KeyboardInaccessibleWidget', 'LabelFor', 'SetTextI18n', 'HardcodedText', 'RelativeOverlap', + 'RtlCompat', 'RtlHardcoded', 'MissingMediaBrowserServiceIntentFilter' + warningsAsErrors true + abortOnError true } compileOptions { @@ -182,6 +189,7 @@ dependencies { androidTestImplementation "androidx.test.espresso:espresso-intents:$espressoVersion" androidTestImplementation "androidx.test:runner:$runnerVersion" androidTestImplementation "androidx.test:rules:$rulesVersion" + androidTestImplementation 'androidx.test.ext:junit:1.1.1' } if (project.hasProperty("antennaPodPlayPublisherCredentials")) { @@ -198,7 +206,6 @@ task copyLicense(type: Copy) { rename { String fileName -> fileName + ".txt" } - outputs.upToDateWhen { false } } preBuild.dependsOn copyLicense diff --git a/app/src/androidTest/java/de/test/antennapod/EspressoTestUtils.java b/app/src/androidTest/java/de/test/antennapod/EspressoTestUtils.java index 41c8365fb..3c8c5d7f0 100644 --- a/app/src/androidTest/java/de/test/antennapod/EspressoTestUtils.java +++ b/app/src/androidTest/java/de/test/antennapod/EspressoTestUtils.java @@ -5,7 +5,7 @@ import android.content.Intent; import androidx.annotation.IdRes; import androidx.annotation.StringRes; import androidx.preference.PreferenceManager; -import androidx.test.InstrumentationRegistry; +import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.espresso.PerformException; import androidx.test.espresso.UiController; import androidx.test.espresso.ViewAction; @@ -116,38 +116,39 @@ public class EspressoTestUtils { * Clear all app databases */ public static void clearPreferences() { - File root = InstrumentationRegistry.getTargetContext().getFilesDir().getParentFile(); + File root = InstrumentationRegistry.getInstrumentation().getTargetContext().getFilesDir().getParentFile(); String[] sharedPreferencesFileNames = new File(root, "shared_prefs").list(); for (String fileName : sharedPreferencesFileNames) { System.out.println("Cleared database: " + fileName); - InstrumentationRegistry.getTargetContext().getSharedPreferences( + InstrumentationRegistry.getInstrumentation().getTargetContext().getSharedPreferences( fileName.replace(".xml", ""), Context.MODE_PRIVATE).edit().clear().commit(); } - InstrumentationRegistry.getTargetContext().getSharedPreferences(MainActivity.PREF_NAME, Context.MODE_PRIVATE) + InstrumentationRegistry.getInstrumentation().getTargetContext() + .getSharedPreferences(MainActivity.PREF_NAME, Context.MODE_PRIVATE) .edit() .putBoolean(MainActivity.PREF_IS_FIRST_LAUNCH, false) .commit(); - PreferenceManager.getDefaultSharedPreferences(InstrumentationRegistry.getTargetContext()) + PreferenceManager.getDefaultSharedPreferences(InstrumentationRegistry.getInstrumentation().getTargetContext()) .edit() .putString(UserPreferences.PREF_UPDATE_INTERVAL, "0") .commit(); - RatingDialog.init(InstrumentationRegistry.getTargetContext()); + RatingDialog.init(InstrumentationRegistry.getInstrumentation().getTargetContext()); RatingDialog.saveRated(); } public static void setLastNavFragment(String tag) { - InstrumentationRegistry.getTargetContext().getSharedPreferences( - NavDrawerFragment.PREF_NAME, Context.MODE_PRIVATE) + InstrumentationRegistry.getInstrumentation().getTargetContext() + .getSharedPreferences(NavDrawerFragment.PREF_NAME, Context.MODE_PRIVATE) .edit() .putString(NavDrawerFragment.PREF_LAST_FRAGMENT_TAG, tag) .commit(); } public static void clearDatabase() { - PodDBAdapter.init(InstrumentationRegistry.getTargetContext()); + PodDBAdapter.init(InstrumentationRegistry.getInstrumentation().getTargetContext()); PodDBAdapter.deleteDatabase(); PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); @@ -172,7 +173,7 @@ public class EspressoTestUtils { } public static void tryKillPlaybackService() { - Context context = InstrumentationRegistry.getTargetContext(); + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); context.stopService(new Intent(context, PlaybackService.class)); try { // Android has no reliable way to stop a service instantly. @@ -183,11 +184,11 @@ public class EspressoTestUtils { } catch (ConditionTimeoutException e) { e.printStackTrace(); } - androidx.test.platform.app.InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + InstrumentationRegistry.getInstrumentation().waitForIdleSync(); } public static void tryKillDownloadService() { - Context context = InstrumentationRegistry.getTargetContext(); + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); context.stopService(new Intent(context, DownloadService.class)); try { // Android has no reliable way to stop a service instantly. @@ -198,7 +199,7 @@ public class EspressoTestUtils { } catch (ConditionTimeoutException e) { e.printStackTrace(); } - androidx.test.platform.app.InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + InstrumentationRegistry.getInstrumentation().waitForIdleSync(); } public static Matcher<View> actionBarOverflow() { diff --git a/app/src/androidTest/java/de/test/antennapod/dialogs/ShareDialogTest.java b/app/src/androidTest/java/de/test/antennapod/dialogs/ShareDialogTest.java new file mode 100644 index 000000000..8c628efd5 --- /dev/null +++ b/app/src/androidTest/java/de/test/antennapod/dialogs/ShareDialogTest.java @@ -0,0 +1,92 @@ +package de.test.antennapod.dialogs; + +import android.content.Context; +import android.content.Intent; +import android.view.View; + +import org.hamcrest.Matcher; +import org.hamcrest.Matchers; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.List; + +import androidx.test.espresso.intent.rule.IntentsTestRule; +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.activity.MainActivity; +import de.danoeh.antennapod.core.feed.FeedItem; +import de.danoeh.antennapod.core.storage.DBReader; +import de.danoeh.antennapod.fragment.EpisodesFragment; +import de.test.antennapod.EspressoTestUtils; +import de.test.antennapod.ui.UITestUtils; + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.action.ViewActions.scrollTo; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition; +import static androidx.test.espresso.matcher.ViewMatchers.hasMinimumChildCount; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.isRoot; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static de.test.antennapod.EspressoTestUtils.onDrawerItem; +import static de.test.antennapod.EspressoTestUtils.openNavDrawer; +import static de.test.antennapod.EspressoTestUtils.waitForView; +import static de.test.antennapod.NthMatcher.first; +import static org.hamcrest.CoreMatchers.allOf; + +/** + * User interface tests for share dialog. + */ +@RunWith(AndroidJUnit4.class) +public class ShareDialogTest { + + @Rule + public IntentsTestRule<MainActivity> activityRule = new IntentsTestRule<>(MainActivity.class, false, false); + + private UITestUtils uiTestUtils; + protected Context context; + + @Before + public void setUp() throws Exception { + context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + EspressoTestUtils.clearPreferences(); + EspressoTestUtils.clearDatabase(); + EspressoTestUtils.setLastNavFragment(EpisodesFragment.TAG); + uiTestUtils = new UITestUtils(context); + uiTestUtils.setup(); + uiTestUtils.addLocalFeedData(true); + + activityRule.launchActivity(new Intent()); + + openNavDrawer(); + onDrawerItem(withText(R.string.episodes_label)).perform(click()); + onView(isRoot()).perform(waitForView(withText(R.string.all_episodes_short_label), 1000)); + onView(withText(R.string.all_episodes_short_label)).perform(click()); + + Matcher<View> allEpisodesMatcher; + final List<FeedItem> episodes = DBReader.getRecentlyPublishedEpisodes(0, 10); + allEpisodesMatcher = Matchers.allOf(withId(android.R.id.list), isDisplayed(), hasMinimumChildCount(2)); + onView(isRoot()).perform(waitForView(allEpisodesMatcher, 1000)); + onView(allEpisodesMatcher).perform(actionOnItemAtPosition(0, click())); + onView(first(EspressoTestUtils.actionBarOverflow())).perform(click()); + } + + @Test + public void testShareDialogDisplayed() throws InterruptedException { + onView(withText(R.string.share_label_with_ellipses)).perform(click()); + onView(allOf(isDisplayed(), withText(R.string.share_label))); + } + + @Test + public void testShareDialogCancelButton() { + onView(withText(R.string.share_label_with_ellipses)).perform(scrollTo()).perform(click()); + onView(withText(R.string.cancel_label)).check(matches(isDisplayed())).perform(scrollTo()).perform(click()); + } + +} diff --git a/app/src/androidTest/java/de/test/antennapod/entities/ExternalMediaTest.java b/app/src/androidTest/java/de/test/antennapod/entities/ExternalMediaTest.java index b3c79367f..83d7a4d22 100644 --- a/app/src/androidTest/java/de/test/antennapod/entities/ExternalMediaTest.java +++ b/app/src/androidTest/java/de/test/antennapod/entities/ExternalMediaTest.java @@ -2,9 +2,9 @@ package de.test.antennapod.entities; import android.annotation.SuppressLint; import android.content.SharedPreferences; -import android.preference.PreferenceManager; +import androidx.preference.PreferenceManager; -import androidx.test.InstrumentationRegistry; +import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.filters.LargeTest; import androidx.test.filters.SmallTest; import de.danoeh.antennapod.core.feed.MediaType; @@ -36,7 +36,7 @@ public class ExternalMediaTest { } private SharedPreferences getDefaultSharedPrefs() { - return PreferenceManager.getDefaultSharedPreferences(InstrumentationRegistry.getTargetContext()); + return PreferenceManager.getDefaultSharedPreferences(InstrumentationRegistry.getInstrumentation().getTargetContext()); } @Test diff --git a/app/src/androidTest/java/de/test/antennapod/feed/FeedFilterTest.java b/app/src/androidTest/java/de/test/antennapod/feed/FeedFilterTest.java index 4b81a4f2b..fc2943205 100644 --- a/app/src/androidTest/java/de/test/antennapod/feed/FeedFilterTest.java +++ b/app/src/androidTest/java/de/test/antennapod/feed/FeedFilterTest.java @@ -6,6 +6,7 @@ import de.danoeh.antennapod.core.feed.FeedItem; import org.junit.Test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @SmallTest @@ -17,8 +18,8 @@ public class FeedFilterTest { FeedItem item = new FeedItem(); item.setTitle("Hello world"); - assertTrue(!filter.excludeOnly()); - assertTrue(!filter.includeOnly()); + assertFalse(filter.excludeOnly()); + assertFalse(filter.includeOnly()); assertEquals("", filter.getExcludeFilter()); assertEquals("", filter.getIncludeFilter()); assertTrue(filter.shouldAutoDownload(item)); @@ -34,12 +35,12 @@ public class FeedFilterTest { FeedItem item2 = new FeedItem(); item2.setTitle("Don't include me"); - assertTrue(!filter.excludeOnly()); + assertFalse(filter.excludeOnly()); assertTrue(filter.includeOnly()); assertEquals("", filter.getExcludeFilter()); assertEquals(includeFilter, filter.getIncludeFilter()); assertTrue(filter.shouldAutoDownload(item)); - assertTrue(!filter.shouldAutoDownload(item2)); + assertFalse(filter.shouldAutoDownload(item2)); } @Test @@ -53,10 +54,10 @@ public class FeedFilterTest { item2.setTitle("Item2"); assertTrue(filter.excludeOnly()); - assertTrue(!filter.includeOnly()); + assertFalse(filter.includeOnly()); assertEquals(excludeFilter, filter.getExcludeFilter()); assertEquals("", filter.getIncludeFilter()); - assertTrue(!filter.shouldAutoDownload(item)); + assertFalse(filter.shouldAutoDownload(item)); assertTrue(filter.shouldAutoDownload(item2)); } @@ -73,12 +74,12 @@ public class FeedFilterTest { FeedItem item3 = new FeedItem(); item3.setTitle("One two words"); - assertTrue(!filter.excludeOnly()); + assertFalse(filter.excludeOnly()); assertTrue(filter.includeOnly()); assertEquals("", filter.getExcludeFilter()); assertEquals(includeFilter, filter.getIncludeFilter()); assertTrue(filter.shouldAutoDownload(item)); - assertTrue(!filter.shouldAutoDownload(item2)); + assertFalse(filter.shouldAutoDownload(item2)); assertTrue(filter.shouldAutoDownload(item3)); } @@ -96,12 +97,12 @@ public class FeedFilterTest { item3.setTitle("One two words"); assertTrue(filter.excludeOnly()); - assertTrue(!filter.includeOnly()); + assertFalse(filter.includeOnly()); assertEquals(excludeFilter, filter.getExcludeFilter()); assertEquals("", filter.getIncludeFilter()); - assertTrue(!filter.shouldAutoDownload(item)); + assertFalse(filter.shouldAutoDownload(item)); assertTrue(filter.shouldAutoDownload(item2)); - assertTrue(!filter.shouldAutoDownload(item3)); + assertFalse(filter.shouldAutoDownload(item3)); } @Test @@ -122,8 +123,8 @@ public class FeedFilterTest { assertTrue(filter.hasExcludeFilter()); assertTrue(filter.hasIncludeFilter()); assertTrue(filter.shouldAutoDownload(download)); - assertTrue(!filter.shouldAutoDownload(doNotDownload)); - assertTrue(!filter.shouldAutoDownload(doNotDownload2)); + assertFalse(filter.shouldAutoDownload(doNotDownload)); + assertFalse(filter.shouldAutoDownload(doNotDownload2)); } } diff --git a/app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java b/app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java index e7e8c5b09..9b3422a5d 100644 --- a/app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java +++ b/app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java @@ -4,7 +4,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetService; import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetServiceException; diff --git a/app/src/androidTest/java/de/test/antennapod/playback/PlaybackTest.java b/app/src/androidTest/java/de/test/antennapod/playback/PlaybackTest.java index 0a3a9f13a..419cf2096 100644 --- a/app/src/androidTest/java/de/test/antennapod/playback/PlaybackTest.java +++ b/app/src/androidTest/java/de/test/antennapod/playback/PlaybackTest.java @@ -3,7 +3,7 @@ package de.test.antennapod.playback; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; -import android.preference.PreferenceManager; +import androidx.preference.PreferenceManager; import android.view.View; import androidx.test.filters.LargeTest; diff --git a/app/src/androidTest/java/de/test/antennapod/service/download/DownloadServiceTest.java b/app/src/androidTest/java/de/test/antennapod/service/download/DownloadServiceTest.java index b75044d73..fd395f7c1 100644 --- a/app/src/androidTest/java/de/test/antennapod/service/download/DownloadServiceTest.java +++ b/app/src/androidTest/java/de/test/antennapod/service/download/DownloadServiceTest.java @@ -5,8 +5,8 @@ import android.content.Intent; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.util.Consumer; -import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; import de.test.antennapod.EspressoTestUtils; import org.awaitility.Awaitility; @@ -81,7 +81,7 @@ public class DownloadServiceTest { @After public void tearDown() throws Exception { DownloadService.setDownloaderFactory(origFactory); - Context context = InstrumentationRegistry.getTargetContext(); + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); DownloadRequester.getInstance().cancelAllDownloads(context); context.stopService(new Intent(context, DownloadService.class)); EspressoTestUtils.tryKillDownloadService(); @@ -106,9 +106,7 @@ public class DownloadServiceTest { // OPEN: Ideally, I'd like the download time long enough so that multiple in-progress DownloadEvents // are generated (to simulate typical download), but it'll make download time quite long (1-2 seconds) // to do so - DownloadService.setDownloaderFactory(new StubDownloaderFactory(50, downloadStatus -> { - downloadStatus.setSuccessful(); - })); + DownloadService.setDownloaderFactory(new StubDownloaderFactory(50, DownloadStatus::setSuccessful)); UserPreferences.setEnqueueDownloadedEpisodes(enqueueDownloaded); withFeedItemEventListener(feedItemEventListener -> { @@ -117,7 +115,8 @@ public class DownloadServiceTest { assertFalse("The media in test should not yet been downloaded", DBReader.getFeedMedia(testMedia11.getId()).isDownloaded()); - DownloadRequester.getInstance().downloadMedia(false, InstrumentationRegistry.getTargetContext(), true, testMedia11.getItem()); + DownloadRequester.getInstance().downloadMedia(false, InstrumentationRegistry + .getInstrumentation().getTargetContext(), true, testMedia11.getItem()); Awaitility.await() .atMost(5000, TimeUnit.MILLISECONDS) .until(() -> feedItemEventListener.getEvents().size() >= numEventsExpected); @@ -144,11 +143,10 @@ public class DownloadServiceTest { } private void doTestCancelDownload_UndoEnqueue(boolean itemAlreadyInQueue) throws Exception { - Context context = InstrumentationRegistry.getTargetContext(); + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); // let download take longer to ensure the test can cancel the download in time - DownloadService.setDownloaderFactory(new StubDownloaderFactory(30000, downloadStatus -> { - downloadStatus.setSuccessful(); - })); + DownloadService.setDownloaderFactory( + new StubDownloaderFactory(30000, DownloadStatus::setSuccessful)); UserPreferences.setEnqueueDownloadedEpisodes(true); UserPreferences.setEnableAutodownload(false); diff --git a/app/src/androidTest/java/de/test/antennapod/service/download/HttpDownloaderTest.java b/app/src/androidTest/java/de/test/antennapod/service/download/HttpDownloaderTest.java index 301ceea6c..4ef6594e3 100644 --- a/app/src/androidTest/java/de/test/antennapod/service/download/HttpDownloaderTest.java +++ b/app/src/androidTest/java/de/test/antennapod/service/download/HttpDownloaderTest.java @@ -1,6 +1,6 @@ package de.test.antennapod.service.download; -import androidx.test.InstrumentationRegistry; +import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.filters.LargeTest; import android.util.Log; @@ -51,7 +51,7 @@ public class HttpDownloaderTest { @Before public void setUp() throws Exception { UserPreferences.init(InstrumentationRegistry.getInstrumentation().getTargetContext()); - destDir = InstrumentationRegistry.getTargetContext().getExternalFilesDir(DOWNLOAD_DIR); + destDir = InstrumentationRegistry.getInstrumentation().getTargetContext().getExternalFilesDir(DOWNLOAD_DIR); assertNotNull(destDir); assertTrue(destDir.exists()); httpServer = new HTTPBin(); @@ -82,7 +82,7 @@ public class HttpDownloaderTest { downloader.call(); DownloadStatus status = downloader.getResult(); assertNotNull(status); - assertTrue(status.isSuccessful() == expectedResult); + assertEquals(expectedResult, status.isSuccessful()); assertTrue(status.isDone()); // the file should not exist if the download has failed and deleteExisting was true assertTrue(!deleteExisting || new File(feedFile.getFile_url()).exists() == expectedResult); diff --git a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java index cfce069ec..c9cbf1bb2 100644 --- a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java +++ b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java @@ -38,6 +38,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -173,7 +174,7 @@ public class PlaybackServiceMediaPlayerTest { throw assertionError; assertTrue(res); - assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.INITIALIZED); + assertSame(PlayerStatus.INITIALIZED, psmp.getPSMPInfo().playerStatus); assertFalse(psmp.isStartWhenPrepared()); callback.cancel(); psmp.shutdown(); @@ -214,7 +215,7 @@ public class PlaybackServiceMediaPlayerTest { throw assertionError; assertTrue(res); - assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.INITIALIZED); + assertSame(PlayerStatus.INITIALIZED, psmp.getPSMPInfo().playerStatus); assertTrue(psmp.isStartWhenPrepared()); callback.cancel(); psmp.shutdown(); @@ -256,7 +257,7 @@ public class PlaybackServiceMediaPlayerTest { if (assertionError != null) throw assertionError; assertTrue(res); - assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.PREPARED); + assertSame(PlayerStatus.PREPARED, psmp.getPSMPInfo().playerStatus); callback.cancel(); psmp.shutdown(); @@ -301,7 +302,7 @@ public class PlaybackServiceMediaPlayerTest { if (assertionError != null) throw assertionError; assertTrue(res); - assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.PLAYING); + assertSame(PlayerStatus.PLAYING, psmp.getPSMPInfo().playerStatus); callback.cancel(); psmp.shutdown(); } @@ -339,7 +340,7 @@ public class PlaybackServiceMediaPlayerTest { if (assertionError != null) throw assertionError; assertTrue(res); - assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.INITIALIZED); + assertSame(PlayerStatus.INITIALIZED, psmp.getPSMPInfo().playerStatus); assertFalse(psmp.isStartWhenPrepared()); callback.cancel(); psmp.shutdown(); @@ -378,7 +379,7 @@ public class PlaybackServiceMediaPlayerTest { if (assertionError != null) throw assertionError; assertTrue(res); - assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.INITIALIZED); + assertSame(PlayerStatus.INITIALIZED, psmp.getPSMPInfo().playerStatus); assertTrue(psmp.isStartWhenPrepared()); callback.cancel(); psmp.shutdown(); @@ -420,7 +421,7 @@ public class PlaybackServiceMediaPlayerTest { if (assertionError != null) throw assertionError; assertTrue(res); - assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.PREPARED); + assertSame(PlayerStatus.PREPARED, psmp.getPSMPInfo().playerStatus); callback.cancel(); psmp.shutdown(); } @@ -465,7 +466,7 @@ public class PlaybackServiceMediaPlayerTest { if (assertionError != null) throw assertionError; assertTrue(res); - assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.PLAYING); + assertSame(PlayerStatus.PLAYING, psmp.getPSMPInfo().playerStatus); callback.cancel(); psmp.shutdown(); } diff --git a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java index fce78ea4f..f039c8bdf 100644 --- a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java +++ b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java @@ -1,7 +1,7 @@ package de.test.antennapod.service.playback; import android.content.Context; -import androidx.test.InstrumentationRegistry; +import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.annotation.UiThreadTest; import androidx.test.filters.LargeTest; @@ -29,6 +29,7 @@ import de.danoeh.antennapod.core.storage.PodDBAdapter; import de.danoeh.antennapod.core.util.playback.Playable; import static de.test.antennapod.util.event.FeedItemEventListener.withFeedItemEventListener; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -92,9 +93,9 @@ public class PlaybackServiceTaskManagerTest { PlaybackServiceTaskManager pstm = new PlaybackServiceTaskManager(c, defaultPSTM); List<FeedItem> testQueue = pstm.getQueue(); assertNotNull(testQueue); - assertTrue(queue.size() == testQueue.size()); + assertEquals(testQueue.size(), queue.size()); for (int i = 0; i < queue.size(); i++) { - assertTrue(queue.get(i).getId() == testQueue.get(i).getId()); + assertEquals(testQueue.get(i).getId(), queue.get(i).getId()); } pstm.shutdown(); } @@ -114,9 +115,9 @@ public class PlaybackServiceTaskManagerTest { assertNotNull(queue); testQueue = pstm.getQueue(); assertNotNull(testQueue); - assertTrue(queue.size() == testQueue.size()); + assertEquals(testQueue.size(), queue.size()); for (int i = 0; i < queue.size(); i++) { - assertTrue(queue.get(i).getId() == testQueue.get(i).getId()); + assertEquals(testQueue.get(i).getId(), queue.get(i).getId()); } pstm.shutdown(); } @@ -171,7 +172,7 @@ public class PlaybackServiceTaskManagerTest { } @Override - public void onSleepTimerAlmostExpired() { + public void onSleepTimerAlmostExpired(long timeLeft) { } @@ -232,7 +233,7 @@ public class PlaybackServiceTaskManagerTest { } @Override - public void onSleepTimerAlmostExpired() { + public void onSleepTimerAlmostExpired(long timeLeft) { } @@ -329,7 +330,7 @@ public class PlaybackServiceTaskManagerTest { } @Override - public void onSleepTimerAlmostExpired() { + public void onSleepTimerAlmostExpired(long timeLeft) { } @@ -375,7 +376,7 @@ public class PlaybackServiceTaskManagerTest { } @Override - public void onSleepTimerAlmostExpired() { + public void onSleepTimerAlmostExpired(long timeLeft) { } @@ -433,7 +434,7 @@ public class PlaybackServiceTaskManagerTest { } @Override - public void onSleepTimerAlmostExpired() { + public void onSleepTimerAlmostExpired(long timeLeft) { } diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBCleanupTests.java b/app/src/androidTest/java/de/test/antennapod/storage/DBCleanupTests.java index 88d78fd14..6c36da13e 100644 --- a/app/src/androidTest/java/de/test/antennapod/storage/DBCleanupTests.java +++ b/app/src/androidTest/java/de/test/antennapod/storage/DBCleanupTests.java @@ -2,7 +2,7 @@ package de.test.antennapod.storage; import android.content.Context; import android.content.SharedPreferences; -import android.preference.PreferenceManager; +import androidx.preference.PreferenceManager; import java.io.File; import java.io.IOException; @@ -10,7 +10,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; -import androidx.test.InstrumentationRegistry; +import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.filters.LargeTest; import androidx.test.filters.SmallTest; import de.danoeh.antennapod.core.feed.Feed; @@ -64,7 +64,7 @@ public class DBCleanupTests { @Before public void setUp() throws Exception { - context = InstrumentationRegistry.getTargetContext(); + context = InstrumentationRegistry.getInstrumentation().getTargetContext(); destFolder = new File(context.getCacheDir(), "DDCleanupTests"); destFolder.mkdir(); cleanupDestFolder(destFolder); diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBNullCleanupAlgorithmTest.java b/app/src/androidTest/java/de/test/antennapod/storage/DBNullCleanupAlgorithmTest.java index 24cc80061..d7ebf2351 100644 --- a/app/src/androidTest/java/de/test/antennapod/storage/DBNullCleanupAlgorithmTest.java +++ b/app/src/androidTest/java/de/test/antennapod/storage/DBNullCleanupAlgorithmTest.java @@ -2,7 +2,7 @@ package de.test.antennapod.storage; import android.content.Context; import android.content.SharedPreferences; -import android.preference.PreferenceManager; +import androidx.preference.PreferenceManager; import java.io.File; import java.io.IOException; @@ -10,7 +10,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; -import androidx.test.InstrumentationRegistry; +import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.filters.LargeTest; import androidx.test.filters.SmallTest; import de.danoeh.antennapod.core.feed.Feed; @@ -55,7 +55,7 @@ public class DBNullCleanupAlgorithmTest { @Before public void setUp() throws Exception { - context = InstrumentationRegistry.getTargetContext(); + context = InstrumentationRegistry.getInstrumentation().getTargetContext(); destFolder = context.getExternalCacheDir(); cleanupDestFolder(destFolder); assertNotNull(destFolder); diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java b/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java index b2458bac6..409100e26 100644 --- a/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java +++ b/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java @@ -5,7 +5,7 @@ import java.util.Date; import java.util.List; import java.util.Random; -import androidx.test.InstrumentationRegistry; +import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.filters.SmallTest; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedItem; @@ -38,7 +38,7 @@ public class DBReaderTest { @Before public void setUp() throws Exception { // create new database - PodDBAdapter.init(InstrumentationRegistry.getTargetContext()); + PodDBAdapter.init(InstrumentationRegistry.getInstrumentation().getTargetContext()); PodDBAdapter.deleteDatabase(); PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); @@ -52,7 +52,7 @@ public class DBReaderTest { assertNotNull(savedFeeds); assertEquals(feeds.size(), savedFeeds.size()); for (int i = 0; i < feeds.size(); i++) { - assertTrue(savedFeeds.get(i).getId() == feeds.get(i).getId()); + assertEquals(feeds.get(i).getId(), savedFeeds.get(i).getId()); } } @@ -91,7 +91,7 @@ public class DBReaderTest { List<Feed> feeds = saveFeedlist(10, 0, false); List<String> urls = DBReader.getFeedListDownloadUrls(); assertNotNull(urls); - assertTrue(urls.size() == feeds.size()); + assertEquals(feeds.size(), urls.size()); for (int i = 0; i < urls.size(); i++) { assertEquals(urls.get(i), feeds.get(i).getDownload_url()); } @@ -115,8 +115,8 @@ public class DBReaderTest { for (int j = 0; j < numItems; j++) { FeedItem item = feeds.get(i).getItems().get(j); assertNotNull(item.getFeed()); - assertTrue(item.getFeed().getId() == feeds.get(i).getId()); - assertTrue(item.getFeedId() == item.getFeed().getId()); + assertEquals(feeds.get(i).getId(), item.getFeed().getId()); + assertEquals(item.getFeed().getId(), item.getFeedId()); } } } @@ -130,9 +130,9 @@ public class DBReaderTest { feed.setItems(null); List<FeedItem> savedItems = DBReader.getFeedItemList(feed); assertNotNull(savedItems); - assertTrue(savedItems.size() == items.size()); + assertEquals(items.size(), savedItems.size()); for (int i = 0; i < savedItems.size(); i++) { - assertTrue(items.get(i).getId() == savedItems.get(i).getId()); + assertEquals(savedItems.get(i).getId(), items.get(i).getId()); } } @@ -167,10 +167,10 @@ public class DBReaderTest { List<FeedItem> queue = saveQueue(numItems); LongList ids = DBReader.getQueueIDList(); assertNotNull(ids); - assertTrue(queue.size() == ids.size()); + assertEquals(ids.size(), queue.size()); for (int i = 0; i < queue.size(); i++) { assertTrue(ids.get(i) != 0); - assertTrue(queue.get(i).getId() == ids.get(i)); + assertEquals(ids.get(i), queue.get(i).getId()); } } @@ -180,10 +180,10 @@ public class DBReaderTest { List<FeedItem> queue = saveQueue(numItems); List<FeedItem> savedQueue = DBReader.getQueue(); assertNotNull(savedQueue); - assertTrue(queue.size() == savedQueue.size()); + assertEquals(savedQueue.size(), queue.size()); for (int i = 0; i < queue.size(); i++) { assertTrue(savedQueue.get(i).getId() != 0); - assertTrue(queue.get(i).getId() == savedQueue.get(i).getId()); + assertEquals(savedQueue.get(i).getId(), queue.get(i).getId()); } } @@ -221,7 +221,7 @@ public class DBReaderTest { List<FeedItem> downloaded = saveDownloadedItems(numItems); List<FeedItem> downloaded_saved = DBReader.getDownloadedItems(); assertNotNull(downloaded_saved); - assertTrue(downloaded_saved.size() == downloaded.size()); + assertEquals(downloaded.size(), downloaded_saved.size()); for (FeedItem item : downloaded_saved) { assertNotNull(item.getMedia()); assertTrue(item.getMedia().isDownloaded()); @@ -264,7 +264,7 @@ public class DBReaderTest { } List<FeedItem> newItemsSaved = DBReader.getNewItemsList(0, Integer.MAX_VALUE); assertNotNull(newItemsSaved); - assertTrue(newItems.size() == newItemsSaved.size()); + assertEquals(newItemsSaved.size(), newItems.size()); for (FeedItem feedItem : newItemsSaved) { long savedId = feedItem.getId(); boolean found = false; diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java b/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java index 090cd2213..595a9794f 100644 --- a/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java +++ b/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java @@ -2,7 +2,7 @@ package de.test.antennapod.storage; import android.content.Context; -import androidx.test.InstrumentationRegistry; +import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.filters.SmallTest; import org.junit.After; @@ -29,6 +29,8 @@ import static java.util.Collections.singletonList; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; /** @@ -45,7 +47,7 @@ public class DBTasksTest { @Before public void setUp() throws Exception { - context = InstrumentationRegistry.getTargetContext(); + context = InstrumentationRegistry.getInstrumentation().getTargetContext(); // create new database PodDBAdapter.init(context); @@ -68,7 +70,7 @@ public class DBTasksTest { } Feed newFeed = DBTasks.updateFeed(context, feed)[0]; - assertTrue(newFeed == feed); + assertSame(feed, newFeed); assertTrue(feed.getId() != 0); for (FeedItem item : feed.getItems()) { assertFalse(item.isPlayed()); @@ -123,13 +125,13 @@ public class DBTasksTest { } final Feed newFeed = DBTasks.updateFeed(context, feed)[0]; - assertTrue(feed != newFeed); + assertNotSame(newFeed, feed); updatedFeedTest(newFeed, feedID, itemIDs, NUM_ITEMS_OLD, NUM_ITEMS_NEW); final Feed feedFromDB = DBReader.getFeed(newFeed.getId()); assertNotNull(feedFromDB); - assertTrue(feedFromDB.getId() == newFeed.getId()); + assertEquals(newFeed.getId(), feedFromDB.getId()); updatedFeedTest(feedFromDB, feedID, itemIDs, NUM_ITEMS_OLD, NUM_ITEMS_NEW); } @@ -155,7 +157,7 @@ public class DBTasksTest { feed.setItems(list); final Feed newFeed = DBTasks.updateFeed(context, feed)[0]; - assertTrue(feed != newFeed); + assertNotSame(newFeed, feed); final Feed feedFromDB = DBReader.getFeed(newFeed.getId()); final FeedItem feedItemFromDB = feedFromDB.getItems().get(0); @@ -163,21 +165,21 @@ public class DBTasksTest { } private void updatedFeedTest(final Feed newFeed, long feedID, List<Long> itemIDs, final int NUM_ITEMS_OLD, final int NUM_ITEMS_NEW) { - assertTrue(newFeed.getId() == feedID); - assertTrue(newFeed.getItems().size() == NUM_ITEMS_NEW + NUM_ITEMS_OLD); + assertEquals(feedID, newFeed.getId()); + assertEquals(NUM_ITEMS_NEW + NUM_ITEMS_OLD, newFeed.getItems().size()); Collections.reverse(newFeed.getItems()); Date lastDate = new Date(0); for (int i = 0; i < NUM_ITEMS_OLD; i++) { FeedItem item = newFeed.getItems().get(i); - assertTrue(item.getFeed() == newFeed); - assertTrue(item.getId() == itemIDs.get(i)); + assertSame(newFeed, item.getFeed()); + assertEquals((long) itemIDs.get(i), item.getId()); assertTrue(item.isPlayed()); assertTrue(item.getPubDate().getTime() >= lastDate.getTime()); lastDate = item.getPubDate(); } for (int i = NUM_ITEMS_OLD; i < NUM_ITEMS_NEW + NUM_ITEMS_OLD; i++) { FeedItem item = newFeed.getItems().get(i); - assertTrue(item.getFeed() == newFeed); + assertSame(newFeed, item.getFeed()); assertTrue(item.getId() != 0); assertFalse(item.isPlayed()); assertTrue(item.getPubDate().getTime() >= lastDate.getTime()); diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java b/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java index d82e366da..d300e23e7 100644 --- a/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java +++ b/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java @@ -3,11 +3,11 @@ package de.test.antennapod.storage; import android.content.Context; import android.content.SharedPreferences; import android.database.Cursor; -import android.preference.PreferenceManager; +import androidx.preference.PreferenceManager; import android.util.Log; import androidx.core.util.Consumer; -import androidx.test.InstrumentationRegistry; +import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.filters.MediumTest; import org.awaitility.Awaitility; @@ -35,9 +35,9 @@ import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.storage.PodDBAdapter; import de.danoeh.antennapod.core.util.FeedItemUtil; -import static androidx.test.InstrumentationRegistry.getInstrumentation; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -56,7 +56,7 @@ public class DBWriterTest { public void tearDown() throws Exception { assertTrue(PodDBAdapter.deleteDatabase()); - final Context context = InstrumentationRegistry.getTargetContext(); + final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); File testDir = context.getExternalFilesDir(TEST_FOLDER); assertNotNull(testDir); for (File f : testDir.listFiles()) { @@ -67,13 +67,13 @@ public class DBWriterTest { @Before public void setUp() throws Exception { // create new database - PodDBAdapter.init(InstrumentationRegistry.getTargetContext()); + PodDBAdapter.init(InstrumentationRegistry.getInstrumentation().getTargetContext()); PodDBAdapter.deleteDatabase(); PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); adapter.close(); - Context context = InstrumentationRegistry.getTargetContext(); + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); SharedPreferences.Editor prefEdit = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()).edit(); prefEdit.putBoolean(UserPreferences.PREF_DELETE_REMOVES_FROM_QUEUE, true).commit(); @@ -116,7 +116,8 @@ public class DBWriterTest { @Test public void testDeleteFeedMediaOfItemFileExists() throws IOException, ExecutionException, InterruptedException, TimeoutException { - File dest = new File(getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER), "testFile"); + File dest = new File(InstrumentationRegistry + .getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER), "testFile"); assertTrue(dest.createNewFile()); @@ -137,7 +138,7 @@ public class DBWriterTest { assertTrue(media.getId() != 0); assertTrue(item.getId() != 0); - DBWriter.deleteFeedMediaOfItem(getInstrumentation().getTargetContext(), media.getId()) + DBWriter.deleteFeedMediaOfItem(InstrumentationRegistry.getInstrumentation().getTargetContext(), media.getId()) .get(TIMEOUT, TimeUnit.SECONDS); media = DBReader.getFeedMedia(media.getId()); assertNotNull(media); @@ -151,7 +152,8 @@ public class DBWriterTest { throws IOException, ExecutionException, InterruptedException, TimeoutException { assertTrue(UserPreferences.shouldDeleteRemoveFromQueue()); - File dest = new File(getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER), "testFile"); + File dest = new File(InstrumentationRegistry + .getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER), "testFile"); assertTrue(dest.createNewFile()); @@ -177,7 +179,7 @@ public class DBWriterTest { queue = DBReader.getQueue(); assertTrue(queue.size() != 0); - DBWriter.deleteFeedMediaOfItem(getInstrumentation().getTargetContext(), media.getId()); + DBWriter.deleteFeedMediaOfItem(InstrumentationRegistry.getInstrumentation().getTargetContext(), media.getId()); Awaitility.await().until(() -> !dest.exists()); media = DBReader.getFeedMedia(media.getId()); assertNotNull(media); @@ -185,12 +187,12 @@ public class DBWriterTest { assertFalse(media.isDownloaded()); assertNull(media.getFile_url()); queue = DBReader.getQueue(); - assertTrue(queue.size() == 0); + assertEquals(0, queue.size()); } @Test public void testDeleteFeed() throws ExecutionException, InterruptedException, IOException, TimeoutException { - File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER); + File destFolder = InstrumentationRegistry.getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER); assertNotNull(destFolder); Feed feed = new Feed("url", null, "title"); @@ -221,7 +223,8 @@ public class DBWriterTest { assertTrue(item.getMedia().getId() != 0); } - DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS); + DBWriter.deleteFeed(InstrumentationRegistry + .getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS); // check if files still exist for (File f : itemFiles) { @@ -231,14 +234,14 @@ public class DBWriterTest { adapter = PodDBAdapter.getInstance(); adapter.open(); Cursor c = adapter.getFeedCursor(feed.getId()); - assertTrue(c.getCount() == 0); + assertEquals(0, c.getCount()); c.close(); for (FeedItem item : feed.getItems()) { c = adapter.getFeedItemCursor(String.valueOf(item.getId())); - assertTrue(c.getCount() == 0); + assertEquals(0, c.getCount()); c.close(); c = adapter.getSingleFeedMediaCursor(item.getMedia().getId()); - assertTrue(c.getCount() == 0); + assertEquals(0, c.getCount()); c.close(); } adapter.close(); @@ -246,7 +249,7 @@ public class DBWriterTest { @Test public void testDeleteFeedNoItems() throws IOException, ExecutionException, InterruptedException, TimeoutException { - File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER); + File destFolder = InstrumentationRegistry.getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER); assertNotNull(destFolder); Feed feed = new Feed("url", null, "title"); @@ -260,19 +263,20 @@ public class DBWriterTest { assertTrue(feed.getId() != 0); - DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS); + DBWriter.deleteFeed(InstrumentationRegistry + .getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS); adapter = PodDBAdapter.getInstance(); adapter.open(); Cursor c = adapter.getFeedCursor(feed.getId()); - assertTrue(c.getCount() == 0); + assertEquals(0, c.getCount()); c.close(); adapter.close(); } @Test public void testDeleteFeedNoFeedMedia() throws IOException, ExecutionException, InterruptedException, TimeoutException { - File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER); + File destFolder = InstrumentationRegistry.getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER); assertNotNull(destFolder); Feed feed = new Feed("url", null, "title"); @@ -297,17 +301,18 @@ public class DBWriterTest { assertTrue(item.getId() != 0); } - DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS); + DBWriter.deleteFeed(InstrumentationRegistry + .getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS); adapter = PodDBAdapter.getInstance(); adapter.open(); Cursor c = adapter.getFeedCursor(feed.getId()); - assertTrue(c.getCount() == 0); + assertEquals(0, c.getCount()); c.close(); for (FeedItem item : feed.getItems()) { c = adapter.getFeedItemCursor(String.valueOf(item.getId())); - assertTrue(c.getCount() == 0); + assertEquals(0, c.getCount()); c.close(); } adapter.close(); @@ -315,7 +320,7 @@ public class DBWriterTest { @Test public void testDeleteFeedWithQueueItems() throws ExecutionException, InterruptedException, TimeoutException { - File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER); + File destFolder = InstrumentationRegistry.getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER); assertNotNull(destFolder); Feed feed = new Feed("url", null, "title"); @@ -344,39 +349,39 @@ public class DBWriterTest { } - List<FeedItem> queue = new ArrayList<>(); - queue.addAll(feed.getItems()); + List<FeedItem> queue = new ArrayList<>(feed.getItems()); adapter.open(); adapter.setQueue(queue); Cursor queueCursor = adapter.getQueueIDCursor(); - assertTrue(queueCursor.getCount() == queue.size()); + assertEquals(queue.size(), queueCursor.getCount()); queueCursor.close(); adapter.close(); - DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS); + DBWriter.deleteFeed(InstrumentationRegistry + .getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS); adapter.open(); Cursor c = adapter.getFeedCursor(feed.getId()); - assertTrue(c.getCount() == 0); + assertEquals(0, c.getCount()); c.close(); for (FeedItem item : feed.getItems()) { c = adapter.getFeedItemCursor(String.valueOf(item.getId())); - assertTrue(c.getCount() == 0); + assertEquals(0, c.getCount()); c.close(); c = adapter.getSingleFeedMediaCursor(item.getMedia().getId()); - assertTrue(c.getCount() == 0); + assertEquals(0, c.getCount()); c.close(); } c = adapter.getQueueCursor(); - assertTrue(c.getCount() == 0); + assertEquals(0, c.getCount()); c.close(); adapter.close(); } @Test public void testDeleteFeedNoDownloadedFiles() throws ExecutionException, InterruptedException, TimeoutException { - File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER); + File destFolder = InstrumentationRegistry.getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER); assertNotNull(destFolder); Feed feed = new Feed("url", null, "title"); @@ -404,19 +409,20 @@ public class DBWriterTest { assertTrue(item.getMedia().getId() != 0); } - DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS); + DBWriter.deleteFeed(InstrumentationRegistry + .getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS); adapter = PodDBAdapter.getInstance(); adapter.open(); Cursor c = adapter.getFeedCursor(feed.getId()); - assertTrue(c.getCount() == 0); + assertEquals(0, c.getCount()); c.close(); for (FeedItem item : feed.getItems()) { c = adapter.getFeedItemCursor(String.valueOf(item.getId())); - assertTrue(c.getCount() == 0); + assertEquals(0, c.getCount()); c.close(); c = adapter.getSingleFeedMediaCursor(item.getMedia().getId()); - assertTrue(c.getCount() == 0); + assertEquals(0, c.getCount()); c.close(); } adapter.close(); @@ -465,11 +471,11 @@ public class DBWriterTest { assertNotNull(media); assertNotNull(media.getPlaybackCompletionDate()); - assertFalse(OLD_DATE == media.getPlaybackCompletionDate().getTime()); + assertNotEquals(media.getPlaybackCompletionDate().getTime(), OLD_DATE); } private Feed queueTestSetupMultipleItems(final int numItems) throws InterruptedException, ExecutionException, TimeoutException { - final Context context = getInstrumentation().getTargetContext(); + final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); UserPreferences.setEnqueueLocation(UserPreferences.EnqueueLocation.BACK); Feed feed = new Feed("url", null, "title"); feed.setItems(new ArrayList<>()); @@ -498,7 +504,7 @@ public class DBWriterTest { @Test public void testAddQueueItemSingleItem() throws InterruptedException, ExecutionException, TimeoutException { - final Context context = getInstrumentation().getTargetContext(); + final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); Feed feed = new Feed("url", null, "title"); feed.setItems(new ArrayList<>()); FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), FeedItem.PLAYED, feed); @@ -516,14 +522,14 @@ public class DBWriterTest { adapter.open(); Cursor cursor = adapter.getQueueIDCursor(); assertTrue(cursor.moveToFirst()); - assertTrue(cursor.getLong(0) == item.getId()); + assertEquals(item.getId(), cursor.getLong(0)); cursor.close(); adapter.close(); } @Test public void testAddQueueItemSingleItemAlreadyInQueue() throws InterruptedException, ExecutionException, TimeoutException { - final Context context = getInstrumentation().getTargetContext(); + final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); Feed feed = new Feed("url", null, "title"); feed.setItems(new ArrayList<>()); FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), FeedItem.PLAYED, feed); @@ -541,7 +547,7 @@ public class DBWriterTest { adapter.open(); Cursor cursor = adapter.getQueueIDCursor(); assertTrue(cursor.moveToFirst()); - assertTrue(cursor.getLong(0) == item.getId()); + assertEquals(item.getId(), cursor.getLong(0)); cursor.close(); adapter.close(); @@ -550,8 +556,8 @@ public class DBWriterTest { adapter.open(); cursor = adapter.getQueueIDCursor(); assertTrue(cursor.moveToFirst()); - assertTrue(cursor.getLong(0) == item.getId()); - assertTrue(cursor.getCount() == 1); + assertEquals(item.getId(), cursor.getLong(0)); + assertEquals(1, cursor.getCount()); cursor.close(); adapter.close(); } @@ -565,7 +571,7 @@ public class DBWriterTest { adapter.open(); Cursor cursor = adapter.getQueueIDCursor(); assertTrue(cursor.moveToFirst()); - assertTrue(cursor.getCount() == NUM_ITEMS); + assertEquals(NUM_ITEMS, cursor.getCount()); List<Long> expectedIds = FeedItemUtil.getIdList(feed.getItems()); List<Long> actualIds = new ArrayList<>(); for (int i = 0; i < NUM_ITEMS; i++) { @@ -595,7 +601,7 @@ public class DBWriterTest { @Test public void testRemoveQueueItem() throws InterruptedException, ExecutionException, TimeoutException { final int NUM_ITEMS = 10; - final Context context = getInstrumentation().getTargetContext(); + final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); Feed feed = createTestFeed(NUM_ITEMS); for (int removeIndex = 0; removeIndex < NUM_ITEMS; removeIndex++) { @@ -609,7 +615,7 @@ public class DBWriterTest { adapter = PodDBAdapter.getInstance(); adapter.open(); Cursor queue = adapter.getQueueIDCursor(); - assertTrue(queue.getCount() == NUM_ITEMS - 1); + assertEquals(NUM_ITEMS - 1, queue.getCount()); for (int i = 0; i < queue.getCount(); i++) { assertTrue(queue.moveToPosition(i)); final long queueID = queue.getLong(0); @@ -631,7 +637,7 @@ public class DBWriterTest { // final int NUM_ITEMS = 5; final int NUM_IN_QUEUE = NUM_ITEMS - 1; // the last one not in queue for boundary condition - final Context context = getInstrumentation().getTargetContext(); + final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); Feed feed = createTestFeed(NUM_ITEMS); List<FeedItem> itemsToAdd = feed.getItems().subList(0, NUM_IN_QUEUE); @@ -698,11 +704,11 @@ public class DBWriterTest { adapter = PodDBAdapter.getInstance(); adapter.open(); Cursor queue = adapter.getQueueIDCursor(); - assertTrue(queue.getCount() == NUM_ITEMS); + assertEquals(NUM_ITEMS, queue.getCount()); assertTrue(queue.moveToPosition(from)); - assertFalse(queue.getLong(0) == fromID); + assertNotEquals(fromID, queue.getLong(0)); assertTrue(queue.moveToPosition(to)); - assertTrue(queue.getLong(0) == fromID); + assertEquals(fromID, queue.getLong(0)); queue.close(); adapter.close(); diff --git a/app/src/androidTest/java/de/test/antennapod/ui/FeedSettingsTest.java b/app/src/androidTest/java/de/test/antennapod/ui/FeedSettingsTest.java index b49be9a04..8bd4f1be6 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/FeedSettingsTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/FeedSettingsTest.java @@ -3,7 +3,7 @@ package de.test.antennapod.ui; import android.content.Intent; import androidx.test.espresso.intent.rule.IntentsTestRule; import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.core.feed.Feed; diff --git a/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java b/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java index 47988d23f..c7520a2e6 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java @@ -2,10 +2,10 @@ package de.test.antennapod.ui; import android.app.Activity; import android.content.Intent; -import androidx.test.InstrumentationRegistry; +import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.espresso.Espresso; import androidx.test.espresso.intent.rule.IntentsTestRule; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import com.robotium.solo.Solo; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; @@ -20,7 +20,6 @@ import org.junit.runner.RunWith; import java.io.IOException; -import static androidx.test.InstrumentationRegistry.getInstrumentation; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; import static androidx.test.espresso.action.ViewActions.replaceText; @@ -55,10 +54,10 @@ public class MainActivityTest { mActivityRule.launchActivity(new Intent()); - uiTestUtils = new UITestUtils(InstrumentationRegistry.getTargetContext()); + uiTestUtils = new UITestUtils(InstrumentationRegistry.getInstrumentation().getTargetContext()); uiTestUtils.setup(); - solo = new Solo(getInstrumentation(), mActivityRule.getActivity()); + solo = new Solo(InstrumentationRegistry.getInstrumentation(), mActivityRule.getActivity()); } @After diff --git a/app/src/androidTest/java/de/test/antennapod/ui/NavigationDrawerTest.java b/app/src/androidTest/java/de/test/antennapod/ui/NavigationDrawerTest.java index bf4dae882..ade5ea298 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/NavigationDrawerTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/NavigationDrawerTest.java @@ -1,10 +1,10 @@ package de.test.antennapod.ui; import android.content.Intent; -import androidx.test.InstrumentationRegistry; +import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.espresso.contrib.DrawerActions; import androidx.test.espresso.intent.rule.IntentsTestRule; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.activity.PreferenceActivity; @@ -59,7 +59,7 @@ public class NavigationDrawerTest { @Before public void setUp() throws IOException { - uiTestUtils = new UITestUtils(InstrumentationRegistry.getTargetContext()); + uiTestUtils = new UITestUtils(InstrumentationRegistry.getInstrumentation().getTargetContext()); uiTestUtils.setup(); EspressoTestUtils.clearPreferences(); diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java index 6741cbc86..9bf89980c 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java @@ -3,11 +3,10 @@ package de.test.antennapod.ui; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Resources; -import android.preference.PreferenceManager; +import androidx.preference.PreferenceManager; import androidx.annotation.StringRes; import androidx.test.filters.LargeTest; import androidx.test.rule.ActivityTestRule; -import com.google.android.material.snackbar.Snackbar; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.PreferenceActivity; import de.danoeh.antennapod.core.preferences.UserPreferences; @@ -31,7 +30,6 @@ import java.util.concurrent.TimeUnit; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; import static androidx.test.espresso.action.ViewActions.replaceText; -import static androidx.test.espresso.action.ViewActions.scrollTo; import static androidx.test.espresso.action.ViewActions.swipeDown; import static androidx.test.espresso.action.ViewActions.swipeUp; import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; @@ -46,7 +44,6 @@ import static de.test.antennapod.EspressoTestUtils.clickPreference; import static de.test.antennapod.EspressoTestUtils.waitForView; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static junit.framework.TestCase.assertTrue; -import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.not; @@ -235,12 +232,10 @@ public class PreferencesTest { @Test public void testPlaybackSpeeds() { clickPreference(R.string.playback_pref); - clickPreference(R.string.media_player); - onView(withText(R.string.media_player_exoplayer)).perform(click()); - clickPreference(R.string.pref_playback_speed_title); - onView(isRoot()).perform(waitForView(withText("0.50"), 1000)); - onView(withText("0.50")).check(matches(isDisplayed())); - onView(withText(R.string.cancel_label)).perform(click()); + clickPreference(R.string.playback_speed); + onView(isRoot()).perform(waitForView(withText("0.75"), 1000)); + onView(withText("0.75")).check(matches(isDisplayed())); + onView(withText(R.string.close_label)).perform(click()); } @Test diff --git a/app/src/androidTest/java/de/test/antennapod/ui/QueueFragmentTest.java b/app/src/androidTest/java/de/test/antennapod/ui/QueueFragmentTest.java index b5c7dd0d1..634904f71 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/QueueFragmentTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/QueueFragmentTest.java @@ -4,7 +4,7 @@ import android.content.Intent; import android.view.View; import androidx.test.espresso.Espresso; import androidx.test.espresso.intent.rule.IntentsTestRule; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.fragment.QueueFragment; diff --git a/app/src/androidTest/java/de/test/antennapod/ui/SpeedChangeTest.java b/app/src/androidTest/java/de/test/antennapod/ui/SpeedChangeTest.java index 6c26078c1..5f79e935c 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/SpeedChangeTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/SpeedChangeTest.java @@ -3,9 +3,9 @@ package de.test.antennapod.ui; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; -import android.preference.PreferenceManager; +import androidx.preference.PreferenceManager; import androidx.test.rule.ActivityTestRule; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.core.feed.FeedItem; @@ -25,6 +25,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; @@ -70,7 +71,7 @@ public class SpeedChangeTest { List<FeedItem> queue = DBReader.getQueue(); PlaybackPreferences.writeMediaPlaying(queue.get(0).getMedia(), PlayerStatus.PAUSED, false); availableSpeeds = new String[] {"1.00", "2.00", "3.00"}; - UserPreferences.setPlaybackSpeedArray(availableSpeeds); + UserPreferences.setPlaybackSpeedArray(Arrays.asList(1.0f, 2.0f, 3.0f)); EspressoTestUtils.tryKillPlaybackService(); activityRule.launchActivity(new Intent().putExtra(MainActivity.EXTRA_OPEN_PLAYER, true)); diff --git a/app/src/androidTest/java/de/test/antennapod/ui/TextOnlyFeedsTest.java b/app/src/androidTest/java/de/test/antennapod/ui/TextOnlyFeedsTest.java index 782bb09d8..488c87052 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/TextOnlyFeedsTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/TextOnlyFeedsTest.java @@ -3,7 +3,7 @@ package de.test.antennapod.ui; import android.content.Intent; import androidx.test.espresso.intent.rule.IntentsTestRule; import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.core.feed.Feed; diff --git a/app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java b/app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java index a183b648e..60516454f 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java @@ -5,7 +5,7 @@ import java.net.HttpURLConnection; import java.net.URL; import java.util.List; -import androidx.test.InstrumentationRegistry; +import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.filters.LargeTest; import androidx.test.filters.MediumTest; import de.danoeh.antennapod.core.feed.Feed; @@ -29,7 +29,7 @@ public class UITestUtilsTest { @Before public void setUp() throws Exception { - uiTestUtils = new UITestUtils(InstrumentationRegistry.getTargetContext()); + uiTestUtils = new UITestUtils(InstrumentationRegistry.getInstrumentation().getTargetContext()); uiTestUtils.setup(); } diff --git a/app/src/androidTest/java/de/test/antennapod/util/FilenameGeneratorTest.java b/app/src/androidTest/java/de/test/antennapod/util/FilenameGeneratorTest.java index 6f8042d61..93e5bcb74 100644 --- a/app/src/androidTest/java/de/test/antennapod/util/FilenameGeneratorTest.java +++ b/app/src/androidTest/java/de/test/antennapod/util/FilenameGeneratorTest.java @@ -21,32 +21,28 @@ import static org.junit.Assert.assertTrue; @SmallTest public class FilenameGeneratorTest { - private static final String VALID1 = "abc abc"; - private static final String INVALID1 = "ab/c: <abc"; - private static final String INVALID2 = "abc abc "; - public FilenameGeneratorTest() { super(); } @Test public void testGenerateFileName() throws IOException { - String result = FileNameGenerator.generateFileName(VALID1); - assertEquals(result, VALID1); + String result = FileNameGenerator.generateFileName("abc abc"); + assertEquals(result, "abc abc"); createFiles(result); } @Test public void testGenerateFileName1() throws IOException { - String result = FileNameGenerator.generateFileName(INVALID1); - assertEquals(result, VALID1); + String result = FileNameGenerator.generateFileName("ab/c: <abc"); + assertEquals(result, "abc abc"); createFiles(result); } @Test public void testGenerateFileName2() throws IOException { - String result = FileNameGenerator.generateFileName(INVALID2); - assertEquals(result, VALID1); + String result = FileNameGenerator.generateFileName("abc abc "); + assertEquals(result, "abc abc"); createFiles(result); } @@ -63,6 +59,12 @@ public class FilenameGeneratorTest { } @Test + public void testFeedTitleContainsAccents() { + String result = FileNameGenerator.generateFileName("Äà áâãå"); + assertEquals("Aaaaaa", result); + } + + @Test public void testInvalidInput() { String result = FileNameGenerator.generateFileName("???"); assertFalse(TextUtils.isEmpty(result)); @@ -97,14 +99,6 @@ public class FilenameGeneratorTest { assertTrue(testFile.exists()); testFile.delete(); assertTrue(testFile.createNewFile()); - - } - - @After - public void tearDown() { - Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); - File f = new File(context.getExternalCacheDir(), VALID1); - f.delete(); } } diff --git a/app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java b/app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java index 59b9ceaca..ed37b7daa 100644 --- a/app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java +++ b/app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java @@ -2,7 +2,7 @@ package de.test.antennapod.util.playback; import android.content.Context; -import androidx.test.InstrumentationRegistry; +import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.filters.SmallTest; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; @@ -35,7 +35,7 @@ public class TimelineTest { @Before public void setUp() { - context = InstrumentationRegistry.getTargetContext(); + context = InstrumentationRegistry.getInstrumentation().getTargetContext(); } private Playable newTestPlayable(List<Chapter> chapters, String shownotes, int duration) { diff --git a/app/src/androidTest/java/de/test/antennapod/util/syndication/FeedDiscovererTest.java b/app/src/androidTest/java/de/test/antennapod/util/syndication/FeedDiscovererTest.java index 2dda77524..b213a5efa 100644 --- a/app/src/androidTest/java/de/test/antennapod/util/syndication/FeedDiscovererTest.java +++ b/app/src/androidTest/java/de/test/antennapod/util/syndication/FeedDiscovererTest.java @@ -1,11 +1,12 @@ package de.test.antennapod.util.syndication; -import androidx.test.InstrumentationRegistry; +import androidx.test.platform.app.InstrumentationRegistry; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import java.io.File; import java.io.FileOutputStream; +import java.nio.charset.Charset; import java.util.Map; import de.danoeh.antennapod.core.util.syndication.FeedDiscoverer; @@ -29,7 +30,8 @@ public class FeedDiscovererTest { @Before public void setUp() throws Exception { fd = new FeedDiscoverer(); - testDir = new File(InstrumentationRegistry.getTargetContext().getFilesDir(), "FeedDiscovererTest"); + testDir = new File(InstrumentationRegistry + .getInstrumentation().getTargetContext().getFilesDir(), "FeedDiscovererTest"); testDir.mkdir(); assertTrue(testDir.exists()); } @@ -67,7 +69,7 @@ public class FeedDiscovererTest { } else { File testFile = new File(testDir, "feed"); FileOutputStream out = new FileOutputStream(testFile); - IOUtils.write(html, out); + IOUtils.write(html, out, Charset.forName("UTF-8")); out.close(); res = fd.findLinks(testFile, base); } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 926329247..afb53f0bd 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -36,7 +36,8 @@ android:theme="@style/Theme.AntennaPod.Splash" android:usesCleartextTraffic="true" android:supportsRtl="true" - android:logo="@mipmap/ic_launcher"> + android:logo="@mipmap/ic_launcher" + android:resizeableActivity="true"> <meta-data android:name="android.webkit.WebView.MetricsOptOut" @@ -50,6 +51,11 @@ android:name="com.google.android.backup.api_key" android:value="AEdPqrEAAAAI3a05VToCTlqBymJrbFGaKQMvF-bBAuLsOdavBA"/> + <!-- Version < 3.0. DeX Mode and Screen Mirroring support --> + <meta-data android:name="com.samsung.android.keepalive.density" android:value="true"/> + <!-- Version >= 3.0. DeX Dual Mode support --> + <meta-data android:name="com.samsung.android.multidisplay.keep_process_alive" android:value="true"/> + <activity android:name=".activity.SplashActivity" android:label="@string/app_name" @@ -73,7 +79,7 @@ <activity android:name=".activity.MainActivity" - android:configChanges="keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout" + android:configChanges="keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|density|uiMode|keyboard|navigation" android:windowSoftInputMode="stateAlwaysHidden" android:launchMode="singleTask" android:label="@string/app_name"> diff --git a/app/src/main/java/de/danoeh/antennapod/activity/BugReportActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/BugReportActivity.java index 48264bb26..b1a0ba2a2 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/BugReportActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/BugReportActivity.java @@ -42,9 +42,8 @@ public class BugReportActivity extends AppCompatActivity { } crashDetailsTextView.setText(crashDetailsText); - findViewById(R.id.btn_open_bug_tracker).setOnClickListener(v -> { - IntentUtils.openInBrowser(BugReportActivity.this, "https://github.com/AntennaPod/AntennaPod/issues"); - }); + findViewById(R.id.btn_open_bug_tracker).setOnClickListener(v -> IntentUtils.openInBrowser( + BugReportActivity.this, "https://github.com/AntennaPod/AntennaPod/issues")); findViewById(R.id.btn_copy_log).setOnClickListener(v -> { ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); diff --git a/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java index 810005d2d..1d3d9bf11 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java @@ -3,6 +3,8 @@ package de.danoeh.antennapod.activity; import android.app.Activity; import android.content.Intent; import android.os.Bundle; + +import androidx.annotation.NonNull; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import android.widget.Button; @@ -86,7 +88,7 @@ public class DownloadAuthenticationActivity extends AppCompatActivity { } @Override - protected void onSaveInstanceState(Bundle outState) { + protected void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); outState.putString("username", etxtUsername.getText().toString()); outState.putString("password", etxtPassword.getText().toString()); diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java index eaa423708..f772cb084 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java @@ -5,10 +5,13 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Configuration; +import android.content.res.Resources; import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.util.DisplayMetrics; import android.util.Log; +import android.util.TypedValue; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; @@ -31,6 +34,7 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.event.MessageEvent; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.util.StorageUtils; +import de.danoeh.antennapod.core.util.ThemeUtils; import de.danoeh.antennapod.core.util.download.AutoUpdateManager; import de.danoeh.antennapod.dialog.RatingDialog; import de.danoeh.antennapod.fragment.AddFeedFragment; @@ -68,9 +72,9 @@ public class MainActivity extends CastEnabledActivity { public static final String EXTRA_OPEN_PLAYER = "open_player"; public static final String EXTRA_REFRESH_ON_START = "refresh_on_start"; - private DrawerLayout drawerLayout; + private @Nullable DrawerLayout drawerLayout; + private @Nullable ActionBarDrawerToggle drawerToggle; private View navDrawer; - private ActionBarDrawerToggle drawerToggle; private LockableBottomSheetBehavior sheetBehavior; private long lastBackButtonPressTime = 0; private RecyclerView.RecycledViewPool recycledViewPool = new RecyclerView.RecycledViewPool(); @@ -95,10 +99,17 @@ public class MainActivity extends CastEnabledActivity { drawerLayout = findViewById(R.id.drawer_layout); navDrawer = findViewById(R.id.navDrawerFragment); + setNavDrawerSize(); final FragmentManager fm = getSupportFragmentManager(); - fm.addOnBackStackChangedListener(() -> - drawerToggle.setDrawerIndicatorEnabled(fm.getBackStackEntryCount() == 0)); + fm.addOnBackStackChangedListener(() -> { + boolean showArrow = fm.getBackStackEntryCount() != 0; + if (drawerToggle != null) { // Tablet layout does not have a drawer + drawerToggle.setDrawerIndicatorEnabled(!showArrow); + } else if (getActionBar() != null) { + getActionBar().setDisplayHomeAsUpEnabled(showArrow); + } + }); if (fm.findFragmentByTag(MAIN_FRAGMENT_TAG) == null) { String lastFragment = NavDrawerFragment.getLastNavFragment(this); @@ -151,12 +162,18 @@ public class MainActivity extends CastEnabledActivity { @Override public void setSupportActionBar(@Nullable Toolbar toolbar) { - drawerLayout.removeDrawerListener(drawerToggle); - drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, - R.string.drawer_open, R.string.drawer_close); - drawerLayout.addDrawerListener(drawerToggle); - drawerToggle.syncState(); - drawerToggle.setDrawerIndicatorEnabled(getSupportFragmentManager().getBackStackEntryCount() == 0); + if (drawerLayout != null) { // Tablet layout does not have a drawer + drawerLayout.removeDrawerListener(drawerToggle); + drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, + R.string.drawer_open, R.string.drawer_close); + drawerLayout.addDrawerListener(drawerToggle); + drawerToggle.syncState(); + drawerToggle.setDrawerIndicatorEnabled(getSupportFragmentManager().getBackStackEntryCount() == 0); + } else if (getSupportFragmentManager().getBackStackEntryCount() == 0) { + toolbar.setNavigationIcon(null); + } else { + toolbar.setNavigationIcon(ThemeUtils.getDrawableFromAttr(this, R.attr.homeAsUpIndicator)); + } super.setSupportActionBar(toolbar); } @@ -164,7 +181,11 @@ public class MainActivity extends CastEnabledActivity { SharedPreferences prefs = getSharedPreferences(PREF_NAME, MODE_PRIVATE); if (prefs.getBoolean(PREF_IS_FIRST_LAUNCH, true)) { loadFragment(AddFeedFragment.TAG, null); - new Handler().postDelayed(() -> drawerLayout.openDrawer(navDrawer), 1500); + new Handler().postDelayed(() -> { + if (drawerLayout != null) { // Tablet layout does not have a drawer + drawerLayout.openDrawer(navDrawer); + } + }, 1500); // for backward compatibility, we only change defaults for fresh installs UserPreferences.setUpdateInterval(12); @@ -258,7 +279,10 @@ public class MainActivity extends CastEnabledActivity { // not commit anything in an AsyncTask, but that's a bigger // change than we want now. t.commitAllowingStateLoss(); - drawerLayout.closeDrawer(navDrawer); + + if (drawerLayout != null) { // Tablet layout does not have a drawer + drawerLayout.closeDrawer(navDrawer); + } } public void loadChildFragment(Fragment fragment, TransitionEffect transition) { @@ -292,13 +316,35 @@ public class MainActivity extends CastEnabledActivity { @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); - drawerToggle.syncState(); + if (drawerToggle != null) { // Tablet layout does not have a drawer + drawerToggle.syncState(); + } } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - drawerToggle.onConfigurationChanged(newConfig); + if (drawerToggle != null) { // Tablet layout does not have a drawer + drawerToggle.onConfigurationChanged(newConfig); + } + setNavDrawerSize(); + } + + private void setNavDrawerSize() { + if (drawerToggle == null) { // Tablet layout does not have a drawer + return; + } + float screenPercent = getResources().getInteger(R.integer.nav_drawer_screen_size_percent) * 0.01f; + int width = (int) (getScreenWidth() * screenPercent); + int maxWidth = (int) getResources().getDimension(R.dimen.nav_drawer_max_screen_size); + + navDrawer.getLayoutParams().width = Math.min(width, maxWidth); + } + + private int getScreenWidth() { + DisplayMetrics displayMetrics = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); + return displayMetrics.widthPixels; } @Override @@ -351,7 +397,7 @@ public class MainActivity extends CastEnabledActivity { @Override public boolean onOptionsItemSelected(MenuItem item) { - if (drawerToggle.onOptionsItemSelected(item)) { + if (drawerToggle != null && drawerToggle.onOptionsItemSelected(item)) { // Tablet layout does not have a drawer return true; } else if (item.getItemId() == android.R.id.home) { if (getSupportFragmentManager().getBackStackEntryCount() > 0) { @@ -374,7 +420,9 @@ public class MainActivity extends CastEnabledActivity { } else { switch (UserPreferences.getBackButtonBehavior()) { case OPEN_DRAWER: - drawerLayout.openDrawer(navDrawer); + if (drawerLayout != null) { // Tablet layout does not have drawer + drawerLayout.openDrawer(navDrawer); + } break; case SHOW_PROMPT: new AlertDialog.Builder(this) diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java index 34c7e3aba..b03d1e5cd 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java @@ -18,16 +18,23 @@ import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; import android.widget.Toast; + +import com.bumptech.glide.Glide; + +import org.apache.commons.lang3.StringUtils; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.text.NumberFormat; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; -import androidx.arch.core.util.Function; +import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityOptionsCompat; import androidx.core.content.ContextCompat; -import androidx.core.util.Consumer; -import androidx.core.util.Supplier; -import com.bumptech.glide.Glide; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.event.PlaybackPositionEvent; import de.danoeh.antennapod.core.feed.FeedItem; @@ -39,7 +46,6 @@ import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.FeedItemUtil; -import de.danoeh.antennapod.core.util.Flavors; import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.core.util.ShareUtils; import de.danoeh.antennapod.core.util.StorageUtils; @@ -51,18 +57,13 @@ import de.danoeh.antennapod.core.util.playback.Playable; import de.danoeh.antennapod.core.util.playback.PlaybackController; import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter; import de.danoeh.antennapod.dialog.PlaybackControlsDialog; +import de.danoeh.antennapod.dialog.ShareDialog; import de.danoeh.antennapod.dialog.SkipPreferenceDialog; import de.danoeh.antennapod.dialog.SleepTimerDialog; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; -import org.apache.commons.lang3.StringUtils; -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; -import org.greenrobot.eventbus.ThreadMode; - -import java.text.NumberFormat; /** @@ -304,7 +305,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements return false; } Playable media = controller.getMedia(); - boolean isFeedMedia = media != null && (media instanceof FeedMedia); + boolean isFeedMedia = (media instanceof FeedMedia); menu.findItem(R.id.open_feed_item).setVisible(isFeedMedia); // FeedMedia implies it belongs to a Feed @@ -313,13 +314,8 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements boolean isItemAndHasLink = isFeedMedia && ShareUtils.hasLinkToShare(((FeedMedia) media).getItem()); - menu.findItem(R.id.share_link_item).setVisible(isItemAndHasLink); - menu.findItem(R.id.share_link_with_position_item).setVisible(isItemAndHasLink); boolean isItemHasDownloadLink = isFeedMedia && ((FeedMedia) media).getDownload_url() != null; - menu.findItem(R.id.share_download_url_item).setVisible(isItemHasDownloadLink); - menu.findItem(R.id.share_download_url_with_position_item).setVisible(isItemHasDownloadLink); - menu.findItem(R.id.share_file).setVisible(isFeedMedia && ((FeedMedia) media).fileExists()); menu.findItem(R.id.share_item).setVisible(hasWebsiteLink || isItemAndHasLink || isItemHasDownloadLink); @@ -380,8 +376,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements new SleepTimerDialog().show(getSupportFragmentManager(), "SleepTimerDialog"); break; case R.id.audio_controls: - boolean isPlayingVideo = controller.getMedia().getMediaType() == MediaType.VIDEO; - PlaybackControlsDialog dialog = PlaybackControlsDialog.newInstance(isPlayingVideo); + PlaybackControlsDialog dialog = PlaybackControlsDialog.newInstance(); dialog.show(getSupportFragmentManager(), "playback_controls"); break; case R.id.open_feed_item: @@ -393,29 +388,10 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements case R.id.visit_website_item: IntentUtils.openInBrowser(MediaplayerActivity.this, getWebsiteLinkWithFallback(media)); break; - case R.id.share_link_item: - if (feedItem != null) { - ShareUtils.shareFeedItemLink(this, feedItem); - } - break; - case R.id.share_download_url_item: - if (feedItem != null) { - ShareUtils.shareFeedItemDownloadLink(this, feedItem); - } - break; - case R.id.share_link_with_position_item: + case R.id.share_item: if (feedItem != null) { - ShareUtils.shareFeedItemLink(this, feedItem, true); - } - break; - case R.id.share_download_url_with_position_item: - if (feedItem != null) { - ShareUtils.shareFeedItemDownloadLink(this, feedItem, true); - } - break; - case R.id.share_file: - if (media instanceof FeedMedia) { - ShareUtils.shareFeedItemFile(this, ((FeedMedia) media)); + ShareDialog shareDialog = ShareDialog.newInstance(feedItem); + shareDialog.show(getSupportFragmentManager(), "ShareEpisodeDialog"); } break; default: diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java index beb6e0a9f..f6623d5dc 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java @@ -227,15 +227,14 @@ public class OnlineFeedViewActivity extends AppCompatActivity { @Override public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - Intent destIntent = new Intent(this, MainActivity.class); - if (NavUtils.shouldUpRecreateTask(this, destIntent)) { - startActivity(destIntent); - } else { - NavUtils.navigateUpFromSameTask(this); - } - return true; + if (item.getItemId() == android.R.id.home) { + Intent destIntent = new Intent(this, MainActivity.class); + if (NavUtils.shouldUpRecreateTask(this, destIntent)) { + startActivity(destIntent); + } else { + NavUtils.navigateUpFromSameTask(this); + } + return true; } return super.onOptionsItemSelected(item); } @@ -606,9 +605,8 @@ public class OnlineFeedViewActivity extends AppCompatActivity { } final List<String> titles = new ArrayList<>(); - final List<String> urls = new ArrayList<>(); - urls.addAll(urlsMap.keySet()); + final List<String> urls = new ArrayList<>(urlsMap.keySet()); for (String url : urls) { titles.add(urlsMap.get(url)); } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java index 337880317..cfd6ec702 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java @@ -88,10 +88,9 @@ public class GpodnetAuthenticationActivity extends AppCompatActivity { @Override public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - finish(); - return true; + if (item.getItemId() == android.R.id.home) { + finish(); + return true; } return super.onOptionsItemSelected(item); } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java index 690bb9e3d..6bfd34d5c 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java @@ -7,6 +7,10 @@ import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.feed.MediaType; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; @@ -32,8 +36,9 @@ public class FeedItemlistDescriptionAdapter extends ArrayAdapter<FeedItem> { super(context, resource, objects); } + @NonNull @Override - public View getView(int position, View convertView, ViewGroup parent) { + public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { Holder holder; FeedItem item = getItem(position); diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java index e66032e11..a53adc719 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java @@ -5,7 +5,7 @@ import android.content.Context; import android.content.SharedPreferences; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; -import android.preference.PreferenceManager; +import androidx.preference.PreferenceManager; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; @@ -61,7 +61,7 @@ public class NavListAdapter extends BaseAdapter private final ItemAccess itemAccess; private final WeakReference<Activity> activity; - private boolean showSubscriptionList = true; + public boolean showSubscriptionList = true; public NavListAdapter(ItemAccess itemAccess, Activity context) { this.itemAccess = itemAccess; @@ -194,7 +194,7 @@ public class NavListAdapter extends BaseAdapter @Override public View getView(int position, View convertView, ViewGroup parent) { int viewType = getItemViewType(position); - View v = null; + View v; if (viewType == VIEW_TYPE_NAV) { v = getNavView((String) getItem(position), position, convertView, parent); } else if (viewType == VIEW_TYPE_SECTION_DIVIDER) { @@ -296,9 +296,17 @@ public class NavListAdapter extends BaseAdapter .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.nav_section_item, parent, false); + TextView feedsFilteredMsg = convertView.findViewById(R.id.nav_feeds_filtered_message); - convertView.setEnabled(false); - convertView.setOnClickListener(null); + if (UserPreferences.getFeedFilter() != UserPreferences.FEED_FILTER_NONE && showSubscriptionList) { + convertView.setEnabled(true); + feedsFilteredMsg.setText("{md-info-outline} " + context.getString(R.string.subscriptions_are_filtered)); + Iconify.addIcons(feedsFilteredMsg); + feedsFilteredMsg.setVisibility(View.VISIBLE); + } else { + convertView.setEnabled(false); + feedsFilteredMsg.setVisibility(View.GONE); + } return convertView; } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java index 428a968c6..7ce086694 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java @@ -20,16 +20,17 @@ public class QueueRecyclerAdapter extends EpisodeItemListAdapter { private static final String TAG = "QueueRecyclerAdapter"; private final ItemTouchHelper itemTouchHelper; - private boolean locked; + private boolean dragDropEnabled; + public QueueRecyclerAdapter(MainActivity mainActivity, ItemTouchHelper itemTouchHelper) { super(mainActivity); this.itemTouchHelper = itemTouchHelper; - locked = UserPreferences.isQueueLocked(); + dragDropEnabled = ! (UserPreferences.isQueueKeepSorted() || UserPreferences.isQueueLocked()); } - public void setLocked(boolean locked) { - this.locked = locked; + public void updateDragDropEnabled() { + dragDropEnabled = ! (UserPreferences.isQueueKeepSorted() || UserPreferences.isQueueLocked()); notifyDataSetChanged(); } @@ -37,14 +38,14 @@ public class QueueRecyclerAdapter extends EpisodeItemListAdapter { @SuppressLint("ClickableViewAccessibility") protected void afterBindViewHolder(EpisodeItemViewHolder holder, int pos) { View.OnTouchListener startDragTouchListener = (v1, event) -> { - if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) { + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { Log.d(TAG, "startDrag()"); itemTouchHelper.startDrag(holder); } return false; }; - if (locked) { + if (!dragDropEnabled) { holder.dragHandle.setVisibility(View.GONE); holder.dragHandle.setOnTouchListener(null); holder.coverHolder.setOnTouchListener(null); diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java index ac1e94437..c3177668a 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java @@ -220,7 +220,7 @@ public class EpisodesApplyActionFragment extends Fragment { } @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.episodes_apply_action_options, menu); @@ -236,7 +236,7 @@ public class EpisodesApplyActionFragment extends Fragment { } @Override - public void onPrepareOptionsMenu(Menu menu) { + public void onPrepareOptionsMenu(@NonNull Menu menu) { // Prepare icon for select toggle button int[] icon = new int[1]; @@ -413,7 +413,7 @@ public class EpisodesApplyActionFragment extends Fragment { boolean checked = checkedIds.contains(episode.getId()); mListView.setItemChecked(i, checked); } - ActivityCompat.invalidateOptionsMenu(EpisodesApplyActionFragment.this.getActivity()); + getActivity().invalidateOptionsMenu(); toolbar.setTitle(getResources().getQuantityString(R.plurals.num_selected_label, checkedIds.size(), checkedIds.size())); } diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/FeedFilterDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/FeedFilterDialog.java new file mode 100644 index 000000000..3b0e2d04b --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/dialog/FeedFilterDialog.java @@ -0,0 +1,38 @@ +package de.danoeh.antennapod.dialog; + +import android.content.Context; + +import androidx.appcompat.app.AlertDialog; + +import org.greenrobot.eventbus.EventBus; + +import java.util.Arrays; +import java.util.List; + +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent; +import de.danoeh.antennapod.core.preferences.UserPreferences; + +public class FeedFilterDialog { + public static void showDialog(Context context) { + AlertDialog.Builder dialog = new AlertDialog.Builder(context); + dialog.setTitle(context.getString(R.string.pref_filter_feed_title)); + dialog.setNegativeButton(android.R.string.cancel, (d, listener) -> d.dismiss()); + + int selected = UserPreferences.getFeedFilter(); + List<String> entryValues = + Arrays.asList(context.getResources().getStringArray(R.array.nav_drawer_feed_filter_values)); + final int selectedIndex = entryValues.indexOf("" + selected); + + String[] items = context.getResources().getStringArray(R.array.nav_drawer_feed_filter_options); + dialog.setSingleChoiceItems(items, selectedIndex, (d, which) -> { + if (selectedIndex != which) { + UserPreferences.setFeedFilter(entryValues.get(which)); + //Update subscriptions + EventBus.getDefault().post(new UnreadItemsUpdateEvent()); + } + d.dismiss(); + }); + dialog.show(); + } +} diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/FeedSortDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/FeedSortDialog.java new file mode 100644 index 000000000..96d1b9b67 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/dialog/FeedSortDialog.java @@ -0,0 +1,38 @@ +package de.danoeh.antennapod.dialog; + +import android.content.Context; + +import androidx.appcompat.app.AlertDialog; + +import org.greenrobot.eventbus.EventBus; + +import java.util.Arrays; +import java.util.List; + +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent; +import de.danoeh.antennapod.core.preferences.UserPreferences; + +public class FeedSortDialog { + public static void showDialog(Context context) { + AlertDialog.Builder dialog = new AlertDialog.Builder(context); + dialog.setTitle(context.getString(R.string.pref_nav_drawer_feed_order_title)); + dialog.setNegativeButton(android.R.string.cancel, (d, listener) -> d.dismiss()); + + int selected = UserPreferences.getFeedOrder(); + List<String> entryValues = + Arrays.asList(context.getResources().getStringArray(R.array.nav_drawer_feed_order_values)); + final int selectedIndex = entryValues.indexOf("" + selected); + + String[] items = context.getResources().getStringArray(R.array.nav_drawer_feed_order_options); + dialog.setSingleChoiceItems(items, selectedIndex, (d, which) -> { + if (selectedIndex != which) { + UserPreferences.setFeedOrder(entryValues.get(which)); + //Update subscriptions + EventBus.getDefault().post(new UnreadItemsUpdateEvent()); + } + d.dismiss(); + }); + dialog.show(); + } +} diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/FilterDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/FilterDialog.java index d2912f90f..82010637f 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/FilterDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/FilterDialog.java @@ -1,8 +1,12 @@ package de.danoeh.antennapod.dialog; import android.content.Context; -import androidx.appcompat.app.AlertDialog; import android.text.TextUtils; +import android.view.LayoutInflater; +import android.widget.LinearLayout; +import android.widget.RadioButton; + +import androidx.appcompat.app.AlertDialog; import java.util.Arrays; import java.util.HashSet; @@ -10,6 +14,8 @@ import java.util.Set; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.feed.FeedItemFilter; +import de.danoeh.antennapod.core.feed.FeedItemFilterGroup; +import de.danoeh.antennapod.view.RecursiveRadioGroup; public abstract class FilterDialog { @@ -22,36 +28,46 @@ public abstract class FilterDialog { } public void openDialog() { - final String[] items = context.getResources().getStringArray(R.array.episode_filter_options); - final String[] values = context.getResources().getStringArray(R.array.episode_filter_values); - final boolean[] checkedItems = new boolean[items.length]; final Set<String> filterValues = new HashSet<>(Arrays.asList(filter.getValues())); + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(R.string.filter); - // make sure we have no empty strings in the filter list - for (String filterValue : filterValues) { - if (TextUtils.isEmpty(filterValue)) { - filterValues.remove(filterValue); - } + LayoutInflater inflater = LayoutInflater.from(this.context); + LinearLayout layout = (LinearLayout) inflater.inflate(R.layout.filter_dialog, null, false); + builder.setView(layout); + + for (FeedItemFilterGroup item : FeedItemFilterGroup.values()) { + RecursiveRadioGroup row = (RecursiveRadioGroup) inflater.inflate(R.layout.filter_dialog_row, null); + RadioButton filter1 = row.findViewById(R.id.filter_dialog_radioButton1); + RadioButton filter2 = row.findViewById(R.id.filter_dialog_radioButton2); + filter1.setText(item.values[0].displayName); + filter1.setTag(item.values[0].filterId); + filter2.setText(item.values[1].displayName); + filter2.setTag(item.values[1].filterId); + layout.addView(row); } - for (int i = 0; i < values.length; i++) { - String value = values[i]; - if (filterValues.contains(value)) { - checkedItems[i] = true; + for (String filterId : filterValues) { + if (!TextUtils.isEmpty(filterId)) { + ((RadioButton) layout.findViewWithTag(filterId)).setChecked(true); } } - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(R.string.filter); - builder.setMultiChoiceItems(items, checkedItems, (dialog, which, isChecked) -> { - if (isChecked) { - filterValues.add(values[which]); - } else { - filterValues.remove(values[which]); - } - }); builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> { + filterValues.clear(); + for (int i = 0; i < layout.getChildCount(); i++) { + if (!(layout.getChildAt(i) instanceof RecursiveRadioGroup)) { + continue; + } + RecursiveRadioGroup group = (RecursiveRadioGroup) layout.getChildAt(i); + if (group.getCheckedButton() != null) { + String tag = (String) group.getCheckedButton().getTag(); + if (tag != null) { // Clear buttons use no tag + filterValues.add((String) group.getCheckedButton().getTag()); + } + } + } updateFilter(filterValues); }); builder.setNegativeButton(R.string.cancel_label, null); diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java index d1ffdc148..e45533826 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java @@ -11,27 +11,21 @@ import android.widget.Button; import android.widget.CheckBox; import android.widget.SeekBar; import android.widget.TextView; -import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.feed.util.PlaybackSpeedUtils; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.util.Converter; -import de.danoeh.antennapod.core.util.playback.Playable; import de.danoeh.antennapod.core.util.playback.PlaybackController; +import de.danoeh.antennapod.view.PlaybackSpeedSeekBar; import java.util.List; import java.util.Locale; public class PlaybackControlsDialog extends DialogFragment { - private static final String ARGUMENT_IS_PLAYING_VIDEO = "isPlayingVideo"; - private PlaybackController controller; private AlertDialog dialog; - private boolean isPlayingVideo; - public static PlaybackControlsDialog newInstance(boolean isPlayingVideo) { + public static PlaybackControlsDialog newInstance() { Bundle arguments = new Bundle(); - arguments.putBoolean(ARGUMENT_IS_PLAYING_VIDEO, isPlayingVideo); PlaybackControlsDialog dialog = new PlaybackControlsDialog(); dialog.setArguments(arguments); return dialog; @@ -65,8 +59,6 @@ public class PlaybackControlsDialog extends DialogFragment { @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - isPlayingVideo = getArguments() != null && getArguments().getBoolean(ARGUMENT_IS_PLAYING_VIDEO); - dialog = new AlertDialog.Builder(getContext()) .setTitle(R.string.audio_controls) .setView(R.layout.audio_controls) @@ -79,68 +71,18 @@ public class PlaybackControlsDialog extends DialogFragment { } private void setupUi() { - final SeekBar barPlaybackSpeed = dialog.findViewById(R.id.playback_speed); - final TextView butDecSpeed = dialog.findViewById(R.id.butDecSpeed); - butDecSpeed.setOnClickListener(v -> { - if (controller != null && controller.canSetPlaybackSpeed()) { - barPlaybackSpeed.setProgress(barPlaybackSpeed.getProgress() - 2); - } else { - VariableSpeedDialog.showGetPluginDialog(getContext()); - } - }); - final TextView butIncSpeed = dialog.findViewById(R.id.butIncSpeed); - butIncSpeed.setOnClickListener(v -> { - if (controller != null && controller.canSetPlaybackSpeed()) { - barPlaybackSpeed.setProgress(barPlaybackSpeed.getProgress() + 2); - } else { - VariableSpeedDialog.showGetPluginDialog(getContext()); - } - }); - final TextView txtvPlaybackSpeed = dialog.findViewById(R.id.txtvPlaybackSpeed); - float currentSpeed = getCurrentSpeed(); - txtvPlaybackSpeed.setText(String.format(Locale.getDefault(), "%.2fx", currentSpeed)); - barPlaybackSpeed.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - if (controller != null && controller.canSetPlaybackSpeed()) { - float playbackSpeed = (progress + 10) / 20.0f; - controller.setPlaybackSpeed(playbackSpeed); - - PlaybackPreferences.setCurrentlyPlayingTemporaryPlaybackSpeed(playbackSpeed); - if (isPlayingVideo) { - UserPreferences.setVideoPlaybackSpeed(playbackSpeed); - } else { - UserPreferences.setPlaybackSpeed(playbackSpeed); - } - - String speedStr = String.format(Locale.getDefault(), "%.2fx", playbackSpeed); - txtvPlaybackSpeed.setText(speedStr); - } else if (fromUser) { - float speed = getCurrentSpeed(); - barPlaybackSpeed.post(() -> barPlaybackSpeed.setProgress(Math.round((20 * speed) - 10))); - } - } + PlaybackSpeedSeekBar speedSeekBar = dialog.findViewById(R.id.speed_seek_bar); + speedSeekBar.setController(controller); + speedSeekBar.setProgressChangedListener(speed + -> txtvPlaybackSpeed.setText(String.format(Locale.getDefault(), "%.2fx", speed))); - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - if (controller != null && !controller.canSetPlaybackSpeed()) { - VariableSpeedDialog.showGetPluginDialog(getContext()); - } - } - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - } - }); - barPlaybackSpeed.setProgress(Math.round((20 * currentSpeed) - 10)); - - final SeekBar barLeftVolume = (SeekBar) dialog.findViewById(R.id.volume_left); + final SeekBar barLeftVolume = dialog.findViewById(R.id.volume_left); barLeftVolume.setProgress(UserPreferences.getLeftVolumePercentage()); - final SeekBar barRightVolume = (SeekBar) dialog.findViewById(R.id.volume_right); + final SeekBar barRightVolume = dialog.findViewById(R.id.volume_right); barRightVolume.setProgress(UserPreferences.getRightVolumePercentage()); - final CheckBox stereoToMono = (CheckBox) dialog.findViewById(R.id.stereo_to_mono); + final CheckBox stereoToMono = dialog.findViewById(R.id.stereo_to_mono); stereoToMono.setChecked(UserPreferences.stereoToMono()); if (controller != null && !controller.canDownmix()) { stereoToMono.setEnabled(false); @@ -220,13 +162,4 @@ public class PlaybackControlsDialog extends DialogFragment { new Handler().postDelayed(this::setupAudioTracks, 500); }); } - - private float getCurrentSpeed() { - Playable media = null; - if (controller != null) { - media = controller.getMedia(); - } - - return PlaybackSpeedUtils.getCurrentPlaybackSpeed(media); - } } diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java index 0c25e3e9f..d0fb91692 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java @@ -23,6 +23,7 @@ import java.net.Proxy; import java.net.SocketAddress; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.concurrent.TimeUnit; import de.danoeh.antennapod.R; @@ -63,6 +64,8 @@ public class ProxyDialog { public Dialog show() { View content = View.inflate(context, R.layout.proxy_settings, null); + spType = content.findViewById(R.id.spType); + dialog = new AlertDialog.Builder(context) .setTitle(R.string.pref_proxy_title) .setView(content) @@ -76,7 +79,7 @@ public class ProxyDialog { test(); return; } - String type = (String) ((Spinner) content.findViewById(R.id.spType)).getSelectedItem(); + String type = (String) spType.getSelectedItem(); ProxyConfig proxy; if (Proxy.Type.valueOf(type) == Proxy.Type.DIRECT) { proxy = ProxyConfig.direct(); @@ -106,7 +109,6 @@ public class ProxyDialog { dialog.dismiss(); }); - spType = content.findViewById(R.id.spType); List<String> types = new ArrayList<>(); types.add(Proxy.Type.DIRECT.name()); types.add(Proxy.Type.HTTP.name()); @@ -227,12 +229,11 @@ public class ProxyDialog { if(required) { testSuccessful = false; dialog.getButton(AlertDialog.BUTTON_POSITIVE).setText(R.string.proxy_test_label); - dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true); } else { testSuccessful = true; dialog.getButton(AlertDialog.BUTTON_POSITIVE).setText(android.R.string.ok); - dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true); } + dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true); } private void test() { @@ -261,7 +262,7 @@ public class ProxyDialog { portValue = Integer.parseInt(port); } SocketAddress address = InetSocketAddress.createUnresolved(host, portValue); - Proxy.Type proxyType = Proxy.Type.valueOf(type.toUpperCase()); + Proxy.Type proxyType = Proxy.Type.valueOf(type.toUpperCase(Locale.US)); Proxy proxy = new Proxy(proxyType, address); OkHttpClient.Builder builder = AntennapodHttpClient.newBuilder() .connectTimeout(10, TimeUnit.SECONDS) diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/ShareDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/ShareDialog.java new file mode 100644 index 000000000..8104d3539 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/dialog/ShareDialog.java @@ -0,0 +1,112 @@ +package de.danoeh.antennapod.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.view.View; +import android.widget.CheckBox; +import android.widget.RadioButton; +import android.widget.RadioGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.DialogFragment; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.core.feed.FeedItem; +import de.danoeh.antennapod.core.util.ShareUtils; + +public class ShareDialog extends DialogFragment { + + private static final String ARGUMENT_FEED_ITEM = "feedItem"; + + private static final String TAG = "ShareDialog"; + private Context ctx; + private FeedItem item; + + private static final String PREF_SHARE_DIALOG_OPTION = "prefShareDialogOption"; + private static final String PREF_SHARE_EPISODE_START_AT = "prefShareEpisodeStartAt"; + + private RadioGroup radioGroup; + private RadioButton radioEpisodeWebsite; + private RadioButton radioMediaFile; + private CheckBox checkBoxStartAt; + private SharedPreferences prefs; + + public ShareDialog() { + // Empty constructor required for DialogFragment + } + + public static ShareDialog newInstance(FeedItem item) { + Bundle arguments = new Bundle(); + arguments.putSerializable(ARGUMENT_FEED_ITEM, item); + ShareDialog dialog = new ShareDialog(); + dialog.setArguments(arguments); + return dialog; + } + + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + if (getArguments() != null) { + ctx = getActivity(); + item = (FeedItem) getArguments().getSerializable(ARGUMENT_FEED_ITEM); + prefs = getActivity().getSharedPreferences("ShareDialog", Context.MODE_PRIVATE); + } + + View content = View.inflate(ctx, R.layout.share_episode_dialog, null); + AlertDialog.Builder builder = new AlertDialog.Builder(ctx); + builder.setTitle(R.string.share_label); + builder.setView(content); + + radioGroup = content.findViewById(R.id.share_dialog_radio_group); + radioEpisodeWebsite = content.findViewById(R.id.share_episode_website_radio); + radioMediaFile = content.findViewById(R.id.share_media_file_radio); + checkBoxStartAt = content.findViewById(R.id.share_start_at_timer_dialog); + + setupOptions(); + + builder.setPositiveButton(R.string.share_label, (dialog, id) -> { + boolean includePlaybackPosition = checkBoxStartAt.isChecked(); + if (radioEpisodeWebsite.isChecked()) { + ShareUtils.shareFeedItemLink(ctx, item, includePlaybackPosition); + prefs.edit().putString(PREF_SHARE_DIALOG_OPTION, "website").apply(); + } else { + ShareUtils.shareFeedItemDownloadLink(ctx, item, includePlaybackPosition); + prefs.edit().putString(PREF_SHARE_DIALOG_OPTION, "media").apply(); + } + prefs.edit().putBoolean(PREF_SHARE_EPISODE_START_AT, includePlaybackPosition).apply(); + }).setNegativeButton(R.string.cancel_label, (dialog, id) -> dialog.dismiss()); + + return builder.create(); + } + + private void setupOptions() { + final boolean hasMedia = item.getMedia() != null; + + if (!ShareUtils.hasLinkToShare(item)) { + radioEpisodeWebsite.setVisibility(View.GONE); + radioMediaFile.setChecked(true); + } + + if (!hasMedia || item.getMedia().getDownload_url() == null) { + radioMediaFile.setVisibility(View.GONE); + radioEpisodeWebsite.setChecked(true); + } + + if (radioEpisodeWebsite.getVisibility() == View.VISIBLE && radioMediaFile.getVisibility() == View.VISIBLE) { + String option = prefs.getString(PREF_SHARE_DIALOG_OPTION, "website"); + if (option.equals("website")) { + radioEpisodeWebsite.setChecked(true); + radioMediaFile.setChecked(false); + } else { + radioEpisodeWebsite.setChecked(false); + radioMediaFile.setChecked(true); + } + } + + boolean switchIsChecked = prefs.getBoolean(PREF_SHARE_EPISODE_START_AT, false); + checkBoxStartAt.setChecked(switchIsChecked); + } +} diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java index 3a6ba183f..ef8ed335d 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java @@ -1,97 +1,171 @@ package de.danoeh.antennapod.dialog; +import android.app.Dialog; import android.content.Context; -import android.os.Build; +import android.os.Bundle; +import android.view.View; +import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.DialogFragment; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import com.google.android.material.chip.Chip; +import com.google.android.material.snackbar.Snackbar; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.util.playback.PlaybackController; +import de.danoeh.antennapod.view.ItemOffsetDecoration; +import de.danoeh.antennapod.view.PlaybackSpeedSeekBar; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Locale; -public class VariableSpeedDialog { +public class VariableSpeedDialog extends DialogFragment { + private SpeedSelectionAdapter adapter; + private final DecimalFormat speedFormat; + private PlaybackController controller; + private final List<Float> selectedSpeeds; + private PlaybackSpeedSeekBar speedSeekBar; + private Chip addCurrentSpeedChip; - private VariableSpeedDialog() { - } - - public static void showDialog(final Context context) { - if (UserPreferences.useSonic() - || UserPreferences.useExoplayer() - || Build.VERSION.SDK_INT >= 23) { - showSpeedSelectorDialog(context); - } else { - showGetPluginDialog(context, true); - } + public VariableSpeedDialog() { + DecimalFormatSymbols format = new DecimalFormatSymbols(Locale.US); + format.setDecimalSeparator('.'); + speedFormat = new DecimalFormat("0.00", format); + selectedSpeeds = new ArrayList<>(UserPreferences.getPlaybackSpeedArray()); } public static void showGetPluginDialog(final Context context) { - showGetPluginDialog(context, false); - } - - private static void showGetPluginDialog(final Context context, boolean showSpeedSelector) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.no_playback_plugin_title); builder.setMessage(R.string.no_playback_plugin_or_sonic_msg); builder.setPositiveButton(R.string.enable_sonic, (dialog, which) -> { UserPreferences.enableSonic(); - if (showSpeedSelector) { - showSpeedSelectorDialog(context); - } }); builder.setNeutralButton(R.string.close_label, null); builder.show(); } - private static void showSpeedSelectorDialog(final Context context) { - DecimalFormatSymbols format = new DecimalFormatSymbols(Locale.US); - format.setDecimalSeparator('.'); - DecimalFormat speedFormat = new DecimalFormat("0.00", format); - - final String[] speedValues = context.getResources().getStringArray( - R.array.playback_speed_values); - // According to Java spec these get initialized to false on creation - final boolean[] speedChecked = new boolean[speedValues.length]; - - // Build the "isChecked" array so that multiChoice dialog is populated correctly - List<String> selectedSpeedList = new ArrayList<>(); - float[] selectedSpeeds = UserPreferences.getPlaybackSpeedArray(); - for (float speed : selectedSpeeds) { - selectedSpeedList.add(speedFormat.format(speed)); + @Override + public void onStart() { + super.onStart(); + controller = new PlaybackController(getActivity()) { + @Override + public void setupGUI() { + updateSpeed(); + } + + @Override + public void onPlaybackSpeedChange() { + updateSpeed(); + } + }; + controller.init(); + speedSeekBar.setController(controller); + } + + private void updateSpeed() { + speedSeekBar.updateSpeed(); + addCurrentSpeedChip.setText(speedFormat.format(controller.getCurrentPlaybackSpeedMultiplier())); + } + + @Override + public void onStop() { + super.onStop(); + controller.release(); + controller = null; + } + + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder.setPositiveButton(R.string.close_label, null); + + View root = View.inflate(getContext(), R.layout.speed_select_dialog, null); + speedSeekBar = root.findViewById(R.id.speed_seek_bar); + RecyclerView selectedSpeedsGrid = root.findViewById(R.id.selected_speeds_grid); + selectedSpeedsGrid.setLayoutManager(new GridLayoutManager(getContext(), 3)); + selectedSpeedsGrid.addItemDecoration(new ItemOffsetDecoration(getContext(), 4)); + adapter = new SpeedSelectionAdapter(); + adapter.setHasStableIds(true); + selectedSpeedsGrid.setAdapter(adapter); + + addCurrentSpeedChip = root.findViewById(R.id.add_current_speed_chip); + addCurrentSpeedChip.setCloseIconVisible(true); + addCurrentSpeedChip.setCloseIconResource(R.drawable.ic_add_black); + addCurrentSpeedChip.setOnCloseIconClickListener(v -> addCurrentSpeed()); + addCurrentSpeedChip.setOnClickListener(v -> addCurrentSpeed()); + + builder.setView(root); + return builder.create(); + } + + private void addCurrentSpeed() { + float newSpeed = controller.getCurrentPlaybackSpeedMultiplier(); + if (selectedSpeeds.contains(newSpeed)) { + Snackbar.make(addCurrentSpeedChip, + getString(R.string.preset_already_exists, newSpeed), Snackbar.LENGTH_LONG).show(); + } else { + selectedSpeeds.add(newSpeed); + Collections.sort(selectedSpeeds); + UserPreferences.setPlaybackSpeedArray(selectedSpeeds); + adapter.notifyDataSetChanged(); } + } - for (int i = 0; i < speedValues.length; i++) { - speedChecked[i] = selectedSpeedList.contains(speedValues[i]); + public class SpeedSelectionAdapter extends RecyclerView.Adapter<SpeedSelectionAdapter.ViewHolder> { + + @Override + @NonNull + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + Chip chip = new Chip(getContext()); + chip.setCloseIconVisible(true); + chip.setCloseIconResource(R.drawable.ic_delete_black); + return new ViewHolder(chip); } - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(R.string.set_playback_speed_label); - builder.setMultiChoiceItems(R.array.playback_speed_values, - speedChecked, (dialog, which, isChecked) -> speedChecked[which] = isChecked); - builder.setNegativeButton(android.R.string.cancel, null); - builder.setPositiveButton(android.R.string.ok, - (dialog, which) -> { - int choiceCount = 0; - for (boolean checked : speedChecked) { - if (checked) { - choiceCount++; - } - } - String[] newSpeedValues = new String[choiceCount]; - int newSpeedIndex = 0; - for (int i = 0; i < speedChecked.length; i++) { - if (speedChecked[i]) { - newSpeedValues[newSpeedIndex++] = speedValues[i]; - } + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + float speed = selectedSpeeds.get(position); + + holder.chip.setText(speedFormat.format(speed)); + holder.chip.setOnCloseIconClickListener(v -> { + selectedSpeeds.remove(speed); + UserPreferences.setPlaybackSpeedArray(selectedSpeeds); + notifyDataSetChanged(); + }); + holder.chip.setOnClickListener(v -> { + if (controller != null) { + controller.setPlaybackSpeed(speed); + notifyDataSetChanged(); } + }); + } - UserPreferences.setPlaybackSpeedArray(newSpeedValues); + @Override + public int getItemCount() { + return selectedSpeeds.size(); + } - }); - builder.create().show(); - } + @Override + public long getItemId(int position) { + return selectedSpeeds.get(position).hashCode(); + } + + public class ViewHolder extends RecyclerView.ViewHolder { + Chip chip; + ViewHolder(Chip itemView) { + super(itemView); + chip = itemView; + } + } + } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java index 546684f14..167daa08b 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java @@ -12,9 +12,13 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.EditText; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; + import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.activity.OnlineFeedViewActivity; @@ -36,7 +40,10 @@ public class AddFeedFragment extends Fragment { private MainActivity activity; @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + @Nullable + public View onCreateView(@NonNull LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); View root = inflater.inflate(R.layout.addfeed, container, false); activity = (MainActivity) getActivity(); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java index 05f38000c..4a1c12e0a 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java @@ -45,20 +45,18 @@ public class AllEpisodesFragment extends EpisodesListFragment { @Override public boolean onOptionsItemSelected(MenuItem item) { if (!super.onOptionsItemSelected(item)) { - switch (item.getItemId()) { - case R.id.filter_items: - showFilterDialog(); - return true; - default: - return false; + if (item.getItemId() == R.id.filter_items) { + showFilterDialog(); + return true; } + return false; } else { return true; } } @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); menu.findItem(R.id.filter_items).setVisible(true); menu.findItem(R.id.mark_all_read_item).setVisible(true); @@ -69,7 +67,7 @@ public class AllEpisodesFragment extends EpisodesListFragment { super.onFragmentLoaded(episodes); if (feedItemFilter.getValues().length > 0) { - txtvInformation.setText("{fa-info-circle} " + this.getString(R.string.filtered_label)); + txtvInformation.setText("{md-info-outline} " + this.getString(R.string.filtered_label)); Iconify.addIcons(txtvInformation); txtvInformation.setVisibility(View.VISIBLE); } else { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java index 5ca8b666a..7eb749681 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java @@ -13,7 +13,6 @@ import android.widget.ImageButton; import android.widget.ProgressBar; import android.widget.SeekBar; import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; @@ -21,17 +20,8 @@ import androidx.appcompat.widget.Toolbar; import androidx.fragment.app.Fragment; import androidx.viewpager2.adapter.FragmentStateAdapter; import androidx.viewpager2.widget.ViewPager2; - import com.google.android.material.bottomsheet.BottomSheetBehavior; - import com.google.android.material.snackbar.Snackbar; -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; -import org.greenrobot.eventbus.ThreadMode; - -import java.text.DecimalFormat; -import java.text.NumberFormat; - import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.CastEnabledActivity; import de.danoeh.antennapod.activity.MainActivity; @@ -40,7 +30,6 @@ import de.danoeh.antennapod.core.event.PlaybackPositionEvent; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.util.PlaybackSpeedUtils; -import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.util.Converter; @@ -60,6 +49,13 @@ import io.reactivex.Maybe; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.List; /** * Shows the audio player. @@ -96,7 +92,9 @@ public class AudioPlayerFragment extends Fragment implements private boolean showTimeLeft; @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); View root = inflater.inflate(R.layout.audioplayer_fragment, container, false); toolbar = root.findViewById(R.id.toolbar); @@ -206,30 +204,29 @@ public class AudioPlayerFragment extends Fragment implements VariableSpeedDialog.showGetPluginDialog(getContext()); return; } - float[] availableSpeeds = UserPreferences.getPlaybackSpeedArray(); + List<Float> availableSpeeds = UserPreferences.getPlaybackSpeedArray(); float currentSpeed = controller.getCurrentPlaybackSpeedMultiplier(); int newSpeedIndex = 0; - while (newSpeedIndex < availableSpeeds.length && availableSpeeds[newSpeedIndex] < currentSpeed + EPSILON) { + while (newSpeedIndex < availableSpeeds.size() + && availableSpeeds.get(newSpeedIndex) < currentSpeed + EPSILON) { newSpeedIndex++; } float newSpeed; - if (availableSpeeds.length == 0) { + if (availableSpeeds.size() == 0) { newSpeed = 1.0f; - } else if (newSpeedIndex == availableSpeeds.length) { - newSpeed = availableSpeeds[0]; + } else if (newSpeedIndex == availableSpeeds.size()) { + newSpeed = availableSpeeds.get(0); } else { - newSpeed = availableSpeeds[newSpeedIndex]; + newSpeed = availableSpeeds.get(newSpeedIndex); } - PlaybackPreferences.setCurrentlyPlayingTemporaryPlaybackSpeed(newSpeed); - UserPreferences.setPlaybackSpeed(newSpeed); controller.setPlaybackSpeed(newSpeed); loadMediaInfo(); }); butPlaybackSpeed.setOnLongClickListener(v -> { - VariableSpeedDialog.showDialog(getContext()); + new VariableSpeedDialog().show(getChildFragmentManager(), null); return true; }); butPlaybackSpeed.setVisibility(View.VISIBLE); @@ -491,11 +488,11 @@ public class AudioPlayerFragment extends Fragment implements switch (item.getItemId()) { case R.id.disable_sleeptimer_item: // Fall-through case R.id.set_sleeptimer_item: - new SleepTimerDialog().show(getFragmentManager(), "SleepTimerDialog"); + new SleepTimerDialog().show(getChildFragmentManager(), "SleepTimerDialog"); return true; case R.id.audio_controls: - PlaybackControlsDialog dialog = PlaybackControlsDialog.newInstance(false); - dialog.show(getFragmentManager(), "playback_controls"); + PlaybackControlsDialog dialog = PlaybackControlsDialog.newInstance(); + dialog.show(getChildFragmentManager(), "playback_controls"); return true; case R.id.open_feed_item: if (feedItem != null) { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java index 48c25552f..6911687dd 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java @@ -45,7 +45,6 @@ public class ChaptersFragment extends Fragment { RecyclerView recyclerView = root.findViewById(R.id.recyclerView); layoutManager = new LinearLayoutManager(getActivity()); recyclerView.setLayoutManager(layoutManager); - recyclerView.setHasFixedSize(true); recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getActivity()).build()); adapter = new ChaptersListAdapter(getActivity(), pos -> { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java index 13941dd2c..55a5d744e 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java @@ -17,16 +17,21 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.adapter.EpisodeItemListAdapter; import de.danoeh.antennapod.adapter.actionbutton.DeleteActionButton; +import de.danoeh.antennapod.core.event.DownloadEvent; import de.danoeh.antennapod.core.event.DownloadLogEvent; import de.danoeh.antennapod.core.event.FeedItemEvent; import de.danoeh.antennapod.core.event.PlaybackPositionEvent; import de.danoeh.antennapod.core.event.PlayerStatusEvent; import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent; import de.danoeh.antennapod.core.feed.FeedItem; +import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.storage.DBReader; +import de.danoeh.antennapod.core.storage.DownloadRequester; import de.danoeh.antennapod.core.util.FeedItemUtil; +import de.danoeh.antennapod.core.util.download.AutoUpdateManager; import de.danoeh.antennapod.dialog.EpisodesApplyActionFragment; import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; +import de.danoeh.antennapod.menuhandler.MenuItemUtils; import de.danoeh.antennapod.view.EmptyViewHandler; import de.danoeh.antennapod.view.EpisodeItemListRecyclerView; import de.danoeh.antennapod.view.viewholder.EpisodeItemViewHolder; @@ -58,6 +63,8 @@ public class CompletedDownloadsFragment extends Fragment { private Disposable disposable; private EmptyViewHandler emptyView; + private boolean isUpdatingFeeds = false; + @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { @@ -104,10 +111,11 @@ public class CompletedDownloadsFragment extends Fragment { } @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.downloads_completed, menu); menu.findItem(R.id.episode_actions).setVisible(items.size() > 0); + isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker); } @Override @@ -116,10 +124,24 @@ public class CompletedDownloadsFragment extends Fragment { ((MainActivity) requireActivity()) .loadChildFragment(EpisodesApplyActionFragment.newInstance(items, ACTION_DELETE | ACTION_ADD_TO_QUEUE)); return true; + } else if (item.getItemId() == R.id.refresh_item) { + AutoUpdateManager.runImmediate(requireContext()); + return true; } return false; } + @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) + public void onEventMainThread(DownloadEvent event) { + Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); + if (event.hasChangedFeedUpdateStatus(isUpdatingFeeds)) { + getActivity().invalidateOptionsMenu(); + } + } + + private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker = + () -> DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds(); + @Override public boolean onContextItemSelected(@NonNull MenuItem item) { FeedItem selectedItem = adapter.getSelectedItem(); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java index 312e3cb62..055d88285 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java @@ -1,11 +1,16 @@ package de.danoeh.antennapod.fragment; import android.app.Dialog; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; import android.content.res.TypedArray; import android.os.Bundle; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.ListFragment; -import androidx.core.view.MenuItemCompat; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; @@ -17,14 +22,21 @@ import android.widget.TextView; import java.util.ArrayList; import java.util.List; +import com.google.android.material.snackbar.Snackbar; import de.danoeh.antennapod.R; +import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.adapter.DownloadLogAdapter; +import de.danoeh.antennapod.core.event.DownloadEvent; import de.danoeh.antennapod.core.event.DownloadLogEvent; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedMedia; +import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; +import de.danoeh.antennapod.core.storage.DownloadRequester; +import de.danoeh.antennapod.core.util.download.AutoUpdateManager; +import de.danoeh.antennapod.menuhandler.MenuItemUtils; import de.danoeh.antennapod.view.EmptyViewHandler; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; @@ -32,6 +44,7 @@ import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; /** * Shows the download log @@ -44,6 +57,8 @@ public class DownloadLogFragment extends ListFragment { private DownloadLogAdapter adapter; private Disposable disposable; + private boolean isUpdatingFeeds = false; + @Override public void onStart() { super.onStart(); @@ -65,7 +80,7 @@ public class DownloadLogFragment extends ListFragment { } @Override - public void onViewCreated(View view, Bundle savedInstanceState) { + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // add padding final ListView lv = getListView(); @@ -93,11 +108,11 @@ public class DownloadLogFragment extends ListFragment { private void onFragmentLoaded() { setListShown(true); adapter.notifyDataSetChanged(); - getActivity().supportInvalidateOptionsMenu(); + getActivity().invalidateOptionsMenu(); } @Override - public void onListItemClick(ListView l, View v, int position, long id) { + public void onListItemClick(@NonNull ListView l, @NonNull View v, int position, long id) { super.onListItemClick(l, v, position, id); DownloadStatus status = adapter.getItem(position); @@ -119,10 +134,17 @@ public class DownloadLogFragment extends ListFragment { message = status.getReasonDetailed(); } + String messageFull = getString(R.string.download_error_details_message, message, url); AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setTitle(R.string.download_error_details); - builder.setMessage(getString(R.string.download_error_details_message, message, url)); + builder.setMessage(messageFull); builder.setPositiveButton(android.R.string.ok, null); + builder.setNeutralButton(R.string.copy_to_clipboard, (dialog, which) -> { + ClipboardManager clipboard = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clip = ClipData.newPlainText(getString(R.string.download_error_details), messageFull); + clipboard.setPrimaryClip(clip); + ((MainActivity) getActivity()).showSnackbarAbovePlayer(R.string.copied_to_clipboard, Snackbar.LENGTH_SHORT); + }); Dialog dialog = builder.show(); ((TextView) dialog.findViewById(android.R.id.message)).setTextIsSelectable(true); } @@ -150,20 +172,14 @@ public class DownloadLogFragment extends ListFragment { } @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - if (!isAdded()) { - return; - } + public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); - MenuItem clearHistory = menu.add(Menu.NONE, R.id.clear_history_item, Menu.CATEGORY_CONTAINER, R.string.clear_history_label); - MenuItemCompat.setShowAsAction(clearHistory, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM); - TypedArray drawables = getActivity().obtainStyledAttributes(new int[]{R.attr.ic_delete}); - clearHistory.setIcon(drawables.getDrawable(0)); - drawables.recycle(); + inflater.inflate(R.menu.downloads_log, menu); + isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker); } @Override - public void onPrepareOptionsMenu(Menu menu) { + public void onPrepareOptionsMenu(@NonNull Menu menu) { super.onPrepareOptionsMenu(menu); MenuItem menuItem = menu.findItem(R.id.clear_history_item); if (menuItem != null) { @@ -172,12 +188,15 @@ public class DownloadLogFragment extends ListFragment { } @Override - public boolean onOptionsItemSelected(MenuItem item) { + public boolean onOptionsItemSelected(@NonNull MenuItem item) { if (!super.onOptionsItemSelected(item)) { switch (item.getItemId()) { case R.id.clear_history_item: DBWriter.clearDownloadLog(); return true; + case R.id.refresh_item: + AutoUpdateManager.runImmediate(requireContext()); + return true; default: return false; } @@ -186,6 +205,17 @@ public class DownloadLogFragment extends ListFragment { } } + @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) + public void onEventMainThread(DownloadEvent event) { + Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); + if (event.hasChangedFeedUpdateStatus(isUpdatingFeeds)) { + getActivity().invalidateOptionsMenu(); + } + } + + private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker = + () -> DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds(); + private void loadItems() { if (disposable != null) { disposable.dispose(); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java index cf0c6db90..c173bf8ee 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java @@ -8,6 +8,7 @@ import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.fragment.app.Fragment; @@ -39,7 +40,9 @@ public class DownloadsFragment extends Fragment { private TabLayout tabLayout; @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); View root = inflater.inflate(R.layout.pager_fragment, container, false); Toolbar toolbar = root.findViewById(R.id.toolbar); @@ -76,7 +79,7 @@ public class DownloadsFragment extends Fragment { } @Override - public void onViewCreated(View view, Bundle savedInstanceState) { + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); if (getArguments() != null) { int tab = getArguments().getInt(ARG_SELECTED_TAB); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java index 29b6a1b16..44f6c8827 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java @@ -120,7 +120,7 @@ public abstract class EpisodesListFragment extends Fragment { } @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { if (!isAdded()) { return; } @@ -131,7 +131,7 @@ public abstract class EpisodesListFragment extends Fragment { } @Override - public boolean onOptionsItemSelected(MenuItem item) { + public boolean onOptionsItemSelected(@NonNull MenuItem item) { if (!super.onOptionsItemSelected(item)) { switch (item.getItemId()) { case R.id.refresh_item: @@ -176,7 +176,7 @@ public abstract class EpisodesListFragment extends Fragment { } @Override - public boolean onContextItemSelected(MenuItem item) { + public boolean onContextItemSelected(@NonNull MenuItem item) { Log.d(TAG, "onContextItemSelected() called with: " + "item = [" + item + "]"); if (!getUserVisibleHint()) { return false; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java index 4f8b4f00c..d50be88c5 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java @@ -53,12 +53,14 @@ public class FavoriteEpisodesFragment extends EpisodesListFragment { ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) { @Override - public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { + public boolean onMove(@NonNull RecyclerView recyclerView, + @NonNull RecyclerView.ViewHolder viewHolder, + @NonNull RecyclerView.ViewHolder target) { return false; } @Override - public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) { + public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int swipeDir) { EpisodeItemViewHolder holder = (EpisodeItemViewHolder) viewHolder; Log.d(TAG, String.format("remove(%s)", holder.getFeedItem().getId())); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FeedInfoFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FeedInfoFragment.java index c58e6c15f..ae03b5032 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/FeedInfoFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/FeedInfoFragment.java @@ -3,6 +3,7 @@ package de.danoeh.antennapod.fragment; import android.content.ClipData; import android.content.Context; import android.content.Intent; +import android.content.res.Configuration; import android.graphics.LightingColorFilter; import android.net.Uri; import android.os.Bundle; @@ -47,9 +48,6 @@ import io.reactivex.MaybeOnSubscribe; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; -import org.apache.commons.lang3.StringUtils; -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; /** * Displays information about a feed. @@ -71,6 +69,8 @@ public class FeedInfoFragment extends Fragment { private TextView txtvUrl; private TextView txtvAuthorHeader; private ImageView imgvBackground; + private View infoContainer; + private View header; private Menu optionsMenu; private ToolbarIconTintManager iconTintManager; @@ -124,6 +124,8 @@ public class FeedInfoFragment extends Fragment { txtvTitle = root.findViewById(R.id.txtvTitle); txtvAuthorHeader = root.findViewById(R.id.txtvAuthor); imgvBackground = root.findViewById(R.id.imgvBackground); + header = root.findViewById(R.id.headerContainer); + infoContainer = root.findViewById(R.id.infoContainer); root.findViewById(R.id.butShowInfo).setVisibility(View.INVISIBLE); root.findViewById(R.id.butShowSettings).setVisibility(View.INVISIBLE); // https://github.com/bumptech/glide/issues/529 @@ -159,6 +161,15 @@ public class FeedInfoFragment extends Fragment { }, error -> Log.d(TAG, Log.getStackTraceString(error)), () -> { }); } + @Override + public void onConfigurationChanged(@NonNull Configuration newConfig) { + super.onConfigurationChanged(newConfig); + int horizontalSpacing = (int) getResources().getDimension(R.dimen.additional_horizontal_spacing); + header.setPadding(horizontalSpacing, header.getPaddingTop(), horizontalSpacing, header.getPaddingBottom()); + infoContainer.setPadding(horizontalSpacing, infoContainer.getPaddingTop(), + horizontalSpacing, infoContainer.getPaddingBottom()); + } + private void showFeed() { Log.d(TAG, "Language is " + feed.getLanguage()); Log.d(TAG, "Author is " + feed.getAuthor()); @@ -216,7 +227,7 @@ public class FeedInfoFragment extends Fragment { } @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.feedinfo, menu); optionsMenu = menu; @@ -224,7 +235,7 @@ public class FeedInfoFragment extends Fragment { } @Override - public void onPrepareOptionsMenu(Menu menu) { + public void onPrepareOptionsMenu(@NonNull Menu menu) { super.onPrepareOptionsMenu(menu); menu.findItem(R.id.share_link_item).setVisible(feed != null && feed.getLink() != null); menu.findItem(R.id.visit_website_item).setVisible(feed != null && feed.getLink() != null @@ -232,7 +243,7 @@ public class FeedInfoFragment extends Fragment { } @Override - public boolean onOptionsItemSelected(MenuItem item) { + public boolean onOptionsItemSelected(@NonNull MenuItem item) { if (feed == null) { ((MainActivity) getActivity()).showSnackbarAbovePlayer( R.string.please_wait_for_data, Toast.LENGTH_LONG); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java index 67433166c..965cfdc86 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java @@ -2,6 +2,8 @@ package de.danoeh.antennapod.fragment; import android.content.Context; import android.content.DialogInterface; +import android.content.res.Configuration; +import android.content.Intent; import android.graphics.LightingColorFilter; import android.os.Bundle; import android.util.Log; @@ -52,6 +54,7 @@ import de.danoeh.antennapod.core.glide.FastBlurTransformation; import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBTasks; +import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.storage.DownloadRequestException; import de.danoeh.antennapod.core.storage.DownloadRequester; import de.danoeh.antennapod.core.util.FeedItemPermutors; @@ -60,6 +63,7 @@ import de.danoeh.antennapod.core.util.Optional; import de.danoeh.antennapod.core.util.ThemeUtils; import de.danoeh.antennapod.core.util.gui.MoreContentListFooterUtil; import de.danoeh.antennapod.dialog.EpisodesApplyActionFragment; +import de.danoeh.antennapod.dialog.FilterDialog; import de.danoeh.antennapod.dialog.RenameFeedDialog; import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; import de.danoeh.antennapod.menuhandler.FeedMenuHandler; @@ -77,6 +81,7 @@ import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import java.util.List; +import java.util.Set; /** * Displays a list of FeedItems. @@ -98,6 +103,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem private TextView txtvAuthor; private ImageButton butShowInfo; private ImageButton butShowSettings; + private View header; private Menu optionsMenu; private ToolbarIconTintManager iconTintManager; @@ -155,6 +161,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem butShowSettings = root.findViewById(R.id.butShowSettings); txtvInformation = root.findViewById(R.id.txtvInformation); txtvFailure = root.findViewById(R.id.txtvFailure); + header = root.findViewById(R.id.headerContainer); AppBarLayout appBar = root.findViewById(R.id.appBar); CollapsingToolbarLayout collapsingToolbar = root.findViewById(R.id.collapsing_toolbar); @@ -221,7 +228,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem }; @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { if (!isAdded()) { return; } @@ -239,14 +246,21 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem } @Override - public void onPrepareOptionsMenu(Menu menu) { + public void onPrepareOptionsMenu(@NonNull Menu menu) { if (feed != null) { FeedMenuHandler.onPrepareOptionsMenu(menu, feed); } } @Override - public boolean onOptionsItemSelected(MenuItem item) { + public void onConfigurationChanged(@NonNull Configuration newConfig) { + super.onConfigurationChanged(newConfig); + int horizontalSpacing = (int) getResources().getDimension(R.dimen.additional_horizontal_spacing); + header.setPadding(horizontalSpacing, header.getPaddingTop(), horizontalSpacing, header.getPaddingBottom()); + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { if (!super.onOptionsItemSelected(item)) { if (feed == null) { ((MainActivity) getActivity()).showSnackbarAbovePlayer( @@ -405,7 +419,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem private void updateSyncProgressBarVisibility() { if (isUpdatingFeed != updateRefreshMenuItemChecker.isRefreshing()) { - getActivity().supportInvalidateOptionsMenu(); + getActivity().invalidateOptionsMenu(); } if (!DownloadRequester.getInstance().isDownloadingFeeds()) { nextPageLoader.getRoot().setVisibility(View.GONE); @@ -429,7 +443,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem adapter.updateItems(feed.getItems()); } - getActivity().supportInvalidateOptionsMenu(); + getActivity().invalidateOptionsMenu(); updateSyncProgressBarVisibility(); } @@ -454,8 +468,19 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) txtvInformation.getLayoutParams(); p.addRule(RelativeLayout.BELOW, R.id.txtvFailure); } - txtvInformation.setText("{fa-info-circle} " + this.getString(R.string.filtered_label)); + txtvInformation.setText("{md-info-outline} " + this.getString(R.string.filtered_label)); Iconify.addIcons(txtvInformation); + txtvInformation.setOnClickListener((l) -> { + FilterDialog filterDialog = new FilterDialog(requireContext(), feed.getItemFilter()) { + @Override + protected void updateFilter(Set<String> filterValues) { + feed.setItemFilter(filterValues.toArray(new String[0])); + DBWriter.setFeedItemsFilter(feed.getId(), filterValues); + } + }; + + filterDialog.openDialog(); + }); txtvInformation.setVisibility(View.VISIBLE); } else { txtvInformation.setVisibility(View.GONE); @@ -482,6 +507,14 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem ((MainActivity) getActivity()).loadChildFragment(fragment, TransitionEffect.SLIDE); } }); + txtvFailure.setOnClickListener(v -> { + Intent intent = new Intent(getContext(), MainActivity.class); + intent.putExtra(MainActivity.EXTRA_FRAGMENT_TAG, DownloadsFragment.TAG); + Bundle args = new Bundle(); + args.putInt(DownloadsFragment.ARG_SELECTED_TAB, DownloadsFragment.POS_LOG); + intent.putExtra(MainActivity.EXTRA_FRAGMENT_ARGS, args); + startActivity(intent); + }); headerCreated = true; } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java index 8251e8716..a82c60d6c 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java @@ -14,7 +14,7 @@ import androidx.appcompat.widget.Toolbar; import androidx.fragment.app.Fragment; import androidx.preference.ListPreference; import androidx.preference.PreferenceFragmentCompat; -import androidx.preference.SwitchPreference; +import androidx.preference.SwitchPreferenceCompat; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.dialog.ConfirmationDialog; import de.danoeh.antennapod.core.event.settings.SkipIntroEndingChangedEvent; @@ -66,7 +66,7 @@ public class FeedSettingsFragment extends Fragment { Toolbar toolbar = root.findViewById(R.id.toolbar); ((AppCompatActivity) getActivity()).setSupportActionBar(toolbar); - getFragmentManager().beginTransaction() + getParentFragmentManager().beginTransaction() .replace(R.id.settings_fragment_container, FeedSettingsPreferenceFragment.newInstance(feedId), "settings_fragment") .commitAllowingStateLoss(); @@ -322,7 +322,7 @@ public class FeedSettingsFragment extends Fragment { } private void setupKeepUpdatedPreference() { - SwitchPreference pref = findPreference("keepUpdated"); + SwitchPreferenceCompat pref = findPreference("keepUpdated"); pref.setChecked(feedPreferences.getKeepUpdated()); pref.setOnPreferenceChangeListener((preference, newValue) -> { @@ -336,7 +336,7 @@ public class FeedSettingsFragment extends Fragment { private void setupAutoDownloadGlobalPreference() { if (!UserPreferences.isEnableAutodownload()) { - SwitchPreference autodl = findPreference("autoDownload"); + SwitchPreferenceCompat autodl = findPreference("autoDownload"); autodl.setChecked(false); autodl.setEnabled(false); autodl.setSummary(R.string.auto_download_disabled_globally); @@ -345,7 +345,7 @@ public class FeedSettingsFragment extends Fragment { } private void setupAutoDownloadPreference() { - SwitchPreference pref = findPreference("autoDownload"); + SwitchPreferenceCompat pref = findPreference("autoDownload"); pref.setEnabled(UserPreferences.isEnableAutodownload()); if (UserPreferences.isEnableAutodownload()) { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java index aaf0fc7d4..337c789fe 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java @@ -145,9 +145,7 @@ public class ItemFragment extends Fragment { } txtvDuration = layout.findViewById(R.id.txtvDuration); txtvPublished = layout.findViewById(R.id.txtvPublished); - if (Build.VERSION.SDK_INT >= 14) { // ellipsize is causing problems on old versions, see #448 - txtvTitle.setEllipsize(TextUtils.TruncateAt.END); - } + txtvTitle.setEllipsize(TextUtils.TruncateAt.END); webvDescription = layout.findViewById(R.id.webvDescription); webvDescription.setTimecodeSelectedListener(time -> { if (controller != null && item.getMedia() != null && controller.getMedia() != null diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java index c198ce258..3b1171df4 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java @@ -140,13 +140,11 @@ public class ItemPagerFragment extends Fragment { @Override public boolean onOptionsItemSelected(MenuItem menuItem) { - switch (menuItem.getItemId()) { - case R.id.open_podcast: - openPodcast(); - return true; - default: - return FeedItemMenuHandler.onMenuItemClicked(this, menuItem.getItemId(), item); + if (menuItem.getItemId() == R.id.open_podcast) { + openPodcast(); + return true; } + return FeedItemMenuHandler.onMenuItemClicked(this, menuItem.getItemId(), item); } @Subscribe(threadMode = ThreadMode.MAIN) diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java index da5710936..8b7d2b886 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java @@ -37,6 +37,7 @@ import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.FeedItemUtil; import de.danoeh.antennapod.core.util.IntentUtils; +import de.danoeh.antennapod.dialog.FeedFilterDialog; import de.danoeh.antennapod.dialog.RenameFeedDialog; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; @@ -86,9 +87,8 @@ public class NavDrawerFragment extends Fragment implements AdapterView.OnItemCli registerForContextMenu(navList); updateSelection(); - root.findViewById(R.id.nav_settings).setOnClickListener(v -> { - startActivity(new Intent(getActivity(), PreferenceActivity.class)); - }); + root.findViewById(R.id.nav_settings).setOnClickListener(v -> + startActivity(new Intent(getActivity(), PreferenceActivity.class))); getContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) .registerOnSharedPreferenceChangeListener(this); return root; @@ -388,6 +388,9 @@ public class NavDrawerFragment extends Fragment implements AdapterView.OnItemCli startActivity(intent); } } + } else if (UserPreferences.getFeedFilter() != UserPreferences.FEED_FILTER_NONE + && navAdapter.showSubscriptionList) { + FeedFilterDialog.showDialog(requireContext()); } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/OnlineSearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/OnlineSearchFragment.java index d9c31f993..e8bd5a1e1 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/OnlineSearchFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/OnlineSearchFragment.java @@ -107,8 +107,8 @@ public class OnlineSearchFragment extends Fragment { txtvError = root.findViewById(R.id.txtvError); butRetry = root.findViewById(R.id.butRetry); txtvEmpty = root.findViewById(android.R.id.empty); - - txtvEmpty.setText(getString(R.string.search_powered_by, searchProvider.getName())); + TextView txtvPoweredBy = root.findViewById(R.id.search_powered_by); + txtvPoweredBy.setText(getString(R.string.search_powered_by, searchProvider.getName())); return root; } @@ -126,7 +126,7 @@ public class OnlineSearchFragment extends Fragment { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.online_search, menu); MenuItem searchItem = menu.findItem(R.id.action_search); - final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem); + final SearchView sv = (SearchView) searchItem.getActionView(); sv.setQueryHint(getString(R.string.search_podcast_hint)); sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java index dabff7269..db4bda1f5 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java @@ -153,7 +153,7 @@ public class PlaybackHistoryFragment extends Fragment { } super.onCreateOptionsMenu(menu, inflater); MenuItem clearHistory = menu.add(Menu.NONE, R.id.clear_history_item, Menu.CATEGORY_CONTAINER, R.string.clear_history_label); - MenuItemCompat.setShowAsAction(clearHistory, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM); + clearHistory.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); TypedArray drawables = getActivity().obtainStyledAttributes(new int[]{R.attr.ic_delete}); clearHistory.setIcon(drawables.getDrawable(0)); drawables.recycle(); @@ -171,13 +171,11 @@ public class PlaybackHistoryFragment extends Fragment { @Override public boolean onOptionsItemSelected(MenuItem item) { if (!super.onOptionsItemSelected(item)) { - switch (item.getItemId()) { - case R.id.clear_history_item: - DBWriter.clearPlaybackHistory(); - return true; - default: - return false; + if (item.getItemId() == R.id.clear_history_item) { + DBWriter.clearPlaybackHistory(); + return true; } + return false; } else { return true; } @@ -196,18 +194,18 @@ public class PlaybackHistoryFragment extends Fragment { @Subscribe(threadMode = ThreadMode.MAIN) public void onHistoryUpdated(PlaybackHistoryEvent event) { loadItems(); - getActivity().supportInvalidateOptionsMenu(); + getActivity().invalidateOptionsMenu(); } @Subscribe(threadMode = ThreadMode.MAIN) public void onPlayerStatusChanged(PlayerStatusEvent event) { loadItems(); - getActivity().supportInvalidateOptionsMenu(); + getActivity().invalidateOptionsMenu(); } private void onFragmentLoaded() { adapter.notifyDataSetChanged(); - getActivity().supportInvalidateOptionsMenu(); + getActivity().invalidateOptionsMenu(); } private void loadItems() { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java index 49c53627f..26216b375 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java @@ -16,7 +16,6 @@ import android.widget.ProgressBar; import android.widget.TextView; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; -import androidx.core.view.ViewCompat; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; @@ -136,6 +135,7 @@ public class QueueFragment extends Fragment { recyclerAdapter.notifyItemInserted(event.position); break; case SET_QUEUE: + case SORTED: //Deliberate fall-through queue = event.items; recyclerAdapter.notifyDataSetChanged(); break; @@ -149,10 +149,6 @@ public class QueueFragment extends Fragment { queue.clear(); recyclerAdapter.notifyDataSetChanged(); break; - case SORTED: - queue = event.items; - recyclerAdapter.notifyDataSetChanged(); - break; case MOVED: return; } @@ -216,7 +212,7 @@ public class QueueFragment extends Fragment { public void onPlayerStatusChanged(PlayerStatusEvent event) { loadItems(false); if (isUpdatingFeeds != updateRefreshMenuItemChecker.isRefreshing()) { - getActivity().supportInvalidateOptionsMenu(); + getActivity().invalidateOptionsMenu(); } } @@ -225,7 +221,7 @@ public class QueueFragment extends Fragment { // Sent when playback position is reset loadItems(false); if (isUpdatingFeeds != updateRefreshMenuItemChecker.isRefreshing()) { - getActivity().supportInvalidateOptionsMenu(); + getActivity().invalidateOptionsMenu(); } } @@ -340,10 +336,10 @@ public class QueueFragment extends Fragment { SortOrder sortOrder = UserPreferences.getQueueKeepSortedOrder(); DBWriter.reorderQueue(sortOrder, true); if (recyclerAdapter != null) { - recyclerAdapter.setLocked(true); + recyclerAdapter.updateDragDropEnabled(); } } else if (recyclerAdapter != null) { - recyclerAdapter.setLocked(UserPreferences.isQueueLocked()); + recyclerAdapter.updateDragDropEnabled(); } getActivity().invalidateOptionsMenu(); return true; @@ -384,14 +380,16 @@ public class QueueFragment extends Fragment { private void setQueueLocked(boolean locked) { UserPreferences.setQueueLocked(locked); - getActivity().supportInvalidateOptionsMenu(); + getActivity().invalidateOptionsMenu(); if (recyclerAdapter != null) { - recyclerAdapter.setLocked(locked); + recyclerAdapter.updateDragDropEnabled(); } - if (locked) { - ((MainActivity) getActivity()).showSnackbarAbovePlayer(R.string.queue_locked, Snackbar.LENGTH_SHORT); - } else { - ((MainActivity) getActivity()).showSnackbarAbovePlayer(R.string.queue_unlocked, Snackbar.LENGTH_SHORT); + if (queue.size() == 0) { + if (locked) { + ((MainActivity) getActivity()).showSnackbarAbovePlayer(R.string.queue_locked, Snackbar.LENGTH_SHORT); + } else { + ((MainActivity) getActivity()).showSnackbarAbovePlayer(R.string.queue_unlocked, Snackbar.LENGTH_SHORT); + } } } @@ -572,7 +570,7 @@ public class QueueFragment extends Fragment { // we need to refresh the options menu because it sometimes // needs data that may have just been loaded. - getActivity().supportInvalidateOptionsMenu(); + getActivity().invalidateOptionsMenu(); refreshInfoBar(); } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java index ddcf09992..ca9fba694 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java @@ -1,8 +1,13 @@ package de.danoeh.antennapod.fragment; import android.os.Bundle; + +import androidx.annotation.NonNull; import androidx.fragment.app.ListFragment; import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; import android.widget.ListView; import android.widget.Toast; @@ -21,10 +26,13 @@ import de.danoeh.antennapod.core.event.DownloaderUpdate; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.DownloadRequest; +import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.service.download.Downloader; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.storage.DownloadRequester; +import de.danoeh.antennapod.core.util.download.AutoUpdateManager; +import de.danoeh.antennapod.menuhandler.MenuItemUtils; import de.danoeh.antennapod.view.EmptyViewHandler; import org.greenrobot.eventbus.ThreadMode; @@ -38,6 +46,8 @@ public class RunningDownloadsFragment extends ListFragment { private DownloadlistAdapter adapter; private List<Downloader> downloaderList = new ArrayList<>(); + private boolean isUpdatingFeeds = false; + @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); @@ -66,6 +76,12 @@ public class RunningDownloadsFragment extends ListFragment { } @Override + public void onResume() { + super.onResume(); + setHasOptionsMenu(true); + } + + @Override public void onStop() { super.onStop(); EventBus.getDefault().unregister(this); @@ -77,6 +93,33 @@ public class RunningDownloadsFragment extends ListFragment { setListAdapter(null); } + @Override + public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + inflater.inflate(R.menu.downloads_running, menu); + isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == R.id.refresh_item) { + AutoUpdateManager.runImmediate(requireContext()); + return true; + } + return false; + } + + @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) + public void onEventMainThread(DownloadEvent event) { + Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); + if (event.hasChangedFeedUpdateStatus(isUpdatingFeeds)) { + getActivity().invalidateOptionsMenu(); + } + } + + private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker = + () -> DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds(); + @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) public void onEvent(DownloadEvent event) { Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]"); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java index 0d33c1282..0c03d407e 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java @@ -124,7 +124,6 @@ public class SearchFragment extends Fragment { LinearLayoutManager layoutManagerFeeds = new LinearLayoutManager(getActivity()); layoutManagerFeeds.setOrientation(RecyclerView.HORIZONTAL); recyclerViewFeeds.setLayoutManager(layoutManagerFeeds); - recyclerViewFeeds.setHasFixedSize(true); adapterFeeds = new FeedSearchResultAdapter((MainActivity) getActivity()); recyclerViewFeeds.setAdapter(adapterFeeds); @@ -174,7 +173,7 @@ public class SearchFragment extends Fragment { @Override public boolean onMenuItemActionCollapse(MenuItem item) { - getFragmentManager().popBackStack(); + getParentFragmentManager().popBackStack(); return true; } }); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java index ba5d44b4d..3837c5025 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java @@ -19,8 +19,10 @@ import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.GridView; +import android.widget.TextView; import com.google.android.material.floatingactionbutton.FloatingActionButton; +import com.joanzapata.iconify.Iconify; import java.util.concurrent.Callable; @@ -34,6 +36,7 @@ import de.danoeh.antennapod.core.event.FeedListUpdateEvent; import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; +import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.storage.DBReader; @@ -42,6 +45,8 @@ import de.danoeh.antennapod.core.storage.DownloadRequester; import de.danoeh.antennapod.core.util.FeedItemUtil; import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.core.util.download.AutoUpdateManager; +import de.danoeh.antennapod.dialog.FeedFilterDialog; +import de.danoeh.antennapod.dialog.FeedSortDialog; import de.danoeh.antennapod.dialog.RenameFeedDialog; import de.danoeh.antennapod.menuhandler.MenuItemUtils; import de.danoeh.antennapod.view.EmptyViewHandler; @@ -68,6 +73,7 @@ public class SubscriptionFragment extends Fragment { private FloatingActionButton subscriptionAddButton; private ProgressBar progressBar; private EmptyViewHandler emptyView; + private TextView feedsFilteredMsg; private int mPosition = -1; private boolean isUpdatingFeeds = false; @@ -90,10 +96,13 @@ public class SubscriptionFragment extends Fragment { View root = inflater.inflate(R.layout.fragment_subscriptions, container, false); ((AppCompatActivity) getActivity()).setSupportActionBar(root.findViewById(R.id.toolbar)); subscriptionGridLayout = root.findViewById(R.id.subscriptions_grid); - subscriptionGridLayout.setNumColumns(prefs.getInt(PREF_NUM_COLUMNS, 3)); + subscriptionGridLayout.setNumColumns(prefs.getInt(PREF_NUM_COLUMNS, getDefaultNumOfColumns())); registerForContextMenu(subscriptionGridLayout); subscriptionAddButton = root.findViewById(R.id.subscriptions_add); progressBar = root.findViewById(R.id.progLoading); + + feedsFilteredMsg = root.findViewById(R.id.feeds_filtered_message); + feedsFilteredMsg.setOnClickListener((l) -> FeedFilterDialog.showDialog(requireContext())); return root; } @@ -102,7 +111,7 @@ public class SubscriptionFragment extends Fragment { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.subscriptions, menu); - int columns = prefs.getInt(PREF_NUM_COLUMNS, 3); + int columns = prefs.getInt(PREF_NUM_COLUMNS, getDefaultNumOfColumns()); menu.findItem(R.id.subscription_num_columns_2).setChecked(columns == 2); menu.findItem(R.id.subscription_num_columns_3).setChecked(columns == 3); menu.findItem(R.id.subscription_num_columns_4).setChecked(columns == 4); @@ -120,6 +129,12 @@ public class SubscriptionFragment extends Fragment { case R.id.refresh_item: AutoUpdateManager.runImmediate(requireContext()); return true; + case R.id.subscriptions_filter: + FeedFilterDialog.showDialog(requireContext()); + return true; + case R.id.subscriptions_sort: + FeedSortDialog.showDialog(requireContext()); + return true; case R.id.subscription_num_columns_2: setColumnNumber(2); return true; @@ -198,6 +213,18 @@ public class SubscriptionFragment extends Fragment { emptyView.updateVisibility(); progressBar.setVisibility(View.GONE); }, error -> Log.e(TAG, Log.getStackTraceString(error))); + + if (UserPreferences.getFeedFilter() != UserPreferences.FEED_FILTER_NONE) { + feedsFilteredMsg.setText("{md-info-outline} " + getString(R.string.subscriptions_are_filtered)); + Iconify.addIcons(feedsFilteredMsg); + feedsFilteredMsg.setVisibility(View.VISIBLE); + } else { + feedsFilteredMsg.setVisibility(View.GONE); + } + } + + private int getDefaultNumOfColumns() { + return getResources().getInteger(R.integer.subscriptions_default_num_of_columns); } @Override diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java index e1c85a2d3..d5cac07f1 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java @@ -56,9 +56,9 @@ public abstract class PodcastListFragment extends Fragment { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.gpodder_podcasts, menu); MenuItem searchItem = menu.findItem(R.id.action_search); - final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem); + final SearchView sv = (SearchView) searchItem.getActionView(); sv.setQueryHint(getString(R.string.gpodnet_search_hint)); - sv.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() { + sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String s) { sv.clearFocus(); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java index 80f1a6ae0..72a752bf1 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java @@ -48,7 +48,7 @@ public class SearchListFragment extends PodcastListFragment { super.onCreateOptionsMenu(menu, inflater); // parent already inflated menu MenuItem searchItem = menu.findItem(R.id.action_search); - final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem); + final SearchView sv = (SearchView) searchItem.getActionView(); sv.setQueryHint(getString(R.string.gpodnet_search_hint)); sv.setQuery(query, false); sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java index a7a0781ce..53a31b68d 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java @@ -38,7 +38,7 @@ public class TagListFragment extends ListFragment { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.gpodder_podcasts, menu); MenuItem searchItem = menu.findItem(R.id.action_search); - final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem); + final SearchView sv = (SearchView) searchItem.getActionView(); sv.setQueryHint(getString(R.string.gpodnet_search_hint)); sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AboutFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AboutFragment.java index 0fa7bd4bb..eb57972a1 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AboutFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AboutFragment.java @@ -28,12 +28,12 @@ public class AboutFragment extends PreferenceFragmentCompat { return true; }); findPreference("about_developers").setOnPreferenceClickListener((preference) -> { - getFragmentManager().beginTransaction().replace(R.id.content, new AboutDevelopersFragment()) + getParentFragmentManager().beginTransaction().replace(R.id.content, new AboutDevelopersFragment()) .addToBackStack(getString(R.string.developers)).commit(); return true; }); findPreference("about_translators").setOnPreferenceClickListener((preference) -> { - getFragmentManager().beginTransaction().replace(R.id.content, new AboutTranslatorsFragment()) + getParentFragmentManager().beginTransaction().replace(R.id.content, new AboutTranslatorsFragment()) .addToBackStack(getString(R.string.translators)).commit(); return true; }); @@ -42,7 +42,7 @@ public class AboutFragment extends PreferenceFragmentCompat { return true; }); findPreference("about_licenses").setOnPreferenceClickListener((preference) -> { - getFragmentManager().beginTransaction().replace(R.id.content, new AboutLicensesFragment()) + getParentFragmentManager().beginTransaction().replace(R.id.content, new AboutLicensesFragment()) .addToBackStack(getString(R.string.translators)).commit(); return true; }); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AutoDownloadPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AutoDownloadPreferencesFragment.java index 6b15e4301..064c4b3bc 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AutoDownloadPreferencesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AutoDownloadPreferencesFragment.java @@ -1,5 +1,6 @@ package de.danoeh.antennapod.fragment.preferences; +import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.content.res.Resources; @@ -85,6 +86,7 @@ public class AutoDownloadPreferencesFragment extends PreferenceFragmentCompat { return val == null ? "" : val; } + @SuppressLint("MissingPermission") // getConfiguredNetworks needs location permission starting with API 29 private void buildAutodownloadSelectedNetworksPreference() { if (Build.VERSION.SDK_INT >= 29) { return; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderPreferencesFragment.java index 8f8b4675d..546e12e65 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderPreferencesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderPreferencesFragment.java @@ -3,9 +3,11 @@ package de.danoeh.antennapod.fragment.preferences; import android.app.Activity; import android.content.SharedPreferences; import android.os.Bundle; +import androidx.core.text.HtmlCompat; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; -import android.text.Html; + +import android.text.Spanned; import android.text.format.DateUtils; import android.widget.Toast; import com.google.android.material.snackbar.Snackbar; @@ -115,7 +117,8 @@ public class GpodderPreferencesFragment extends PreferenceFragmentCompat { String format = getActivity().getString(R.string.pref_gpodnet_login_status); String summary = String.format(format, GpodnetPreferences.getUsername(), GpodnetPreferences.getDeviceID()); - findPreference(PREF_GPODNET_LOGOUT).setSummary(Html.fromHtml(summary)); + Spanned formattedSummary = HtmlCompat.fromHtml(summary, HtmlCompat.FROM_HTML_MODE_LEGACY); + findPreference(PREF_GPODNET_LOGOUT).setSummary(formattedSummary); updateLastGpodnetSyncReport(SyncService.isLastSyncSuccessful(getContext()), SyncService.getLastSyncAttempt(getContext())); } else { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/ImportExportPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/ImportExportPreferencesFragment.java index f3b4d3003..5eb4a3aea 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/ImportExportPreferencesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/ImportExportPreferencesFragment.java @@ -38,6 +38,7 @@ import java.io.FileOutputStream; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; +import java.util.Locale; public class ImportExportPreferencesFragment extends PreferenceFragmentCompat { private static final String TAG = "ImportExPrefFragment"; @@ -86,9 +87,7 @@ public class ImportExportPreferencesFragment extends PreferenceFragmentCompat { } private String dateStampFilename(String fname) { - return String.format(fname, - new SimpleDateFormat("yyyy-MM-dd") - .format(new Date())); + return String.format(fname, new SimpleDateFormat("yyyy-MM-dd", Locale.US).format(new Date())); } private void setupStorageScreen() { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/MainPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/MainPreferencesFragment.java index 406585808..3f1cec729 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/MainPreferencesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/MainPreferencesFragment.java @@ -22,6 +22,7 @@ public class MainPreferencesFragment extends PreferenceFragmentCompat { private static final String PREF_FAQ = "prefFaq"; private static final String PREF_VIEW_FORUM = "prefViewForum"; private static final String PREF_SEND_BUG_REPORT = "prefSendBugReport"; + private static final String PREF_CATEGORY_PROJECT = "project"; private static final String STATISTICS = "statistics"; private static final String PREF_ABOUT = "prefAbout"; @@ -30,6 +31,13 @@ public class MainPreferencesFragment extends PreferenceFragmentCompat { addPreferencesFromResource(R.xml.preferences); setupMainScreen(); setupSearch(); + + // If you are writing a spin-off, please update the details on screens like "About" and "Report bug" + // and afterwards remove the following lines. + String packageName = getContext().getPackageName(); + if (!"de.danoeh.antennapod".equals(packageName) && !"de.danoeh.antennapod.debug".equals(packageName)) { + findPreference(PREF_CATEGORY_PROJECT).setVisible(false); + } } @Override @@ -62,14 +70,14 @@ public class MainPreferencesFragment extends PreferenceFragmentCompat { findPreference(PREF_ABOUT).setOnPreferenceClickListener( preference -> { - getFragmentManager().beginTransaction().replace(R.id.content, new AboutFragment()) + getParentFragmentManager().beginTransaction().replace(R.id.content, new AboutFragment()) .addToBackStack(getString(R.string.about_pref)).commit(); return true; } ); findPreference(STATISTICS).setOnPreferenceClickListener( preference -> { - getFragmentManager().beginTransaction().replace(R.id.content, new StatisticsFragment()) + getParentFragmentManager().beginTransaction().replace(R.id.content, new StatisticsFragment()) .addToBackStack(getString(R.string.statistics_label)).commit(); return true; } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/PlaybackPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/PlaybackPreferencesFragment.java index 741080cf1..f07e59afe 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/PlaybackPreferencesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/PlaybackPreferencesFragment.java @@ -45,7 +45,7 @@ public class PlaybackPreferencesFragment extends PreferenceFragmentCompat { final Activity activity = getActivity(); findPreference(PREF_PLAYBACK_SPEED_LAUNCHER).setOnPreferenceClickListener(preference -> { - VariableSpeedDialog.showDialog(activity); + new VariableSpeedDialog().show(getChildFragmentManager(), null); return true; }); findPreference(PREF_PLAYBACK_REWIND_DELTA_LAUNCHER).setOnPreferenceClickListener(preference -> { @@ -116,7 +116,7 @@ public class PlaybackPreferencesFragment extends PreferenceFragmentCompat { if(x == 0) { entries[x] = res.getString(R.string.pref_smart_mark_as_played_disabled); } else { - Integer v = Integer.parseInt(values[x]); + int v = Integer.parseInt(values[x]); if(v < 60) { entries[x] = res.getQuantityString(R.plurals.time_seconds_quantified, v, v); } else { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java index a44623f48..12be76ba7 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java @@ -12,6 +12,8 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.activity.PreferenceActivity; import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.dialog.FeedFilterDialog; +import de.danoeh.antennapod.dialog.FeedSortDialog; import de.danoeh.antennapod.fragment.NavDrawerFragment; import org.apache.commons.lang3.ArrayUtils; @@ -75,6 +77,18 @@ public class UserInterfacePreferencesFragment extends PreferenceFragmentCompat { return true; }); + findPreference(UserPreferences.PREF_FILTER_FEED) + .setOnPreferenceClickListener((preference -> { + FeedFilterDialog.showDialog(requireContext()); + return true; + })); + + findPreference(UserPreferences.PREF_DRAWER_FEED_ORDER) + .setOnPreferenceClickListener((preference -> { + FeedSortDialog.showDialog(requireContext()); + return true; + })); + if (Build.VERSION.SDK_INT >= 26) { findPreference(UserPreferences.PREF_EXPANDED_NOTIFICATION).setVisible(false); } diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java index 1f15f66ec..bddafb75e 100644 --- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java +++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java @@ -2,13 +2,14 @@ package de.danoeh.antennapod.menuhandler; import android.content.Context; import android.os.Handler; -import androidx.annotation.NonNull; -import com.google.android.material.snackbar.Snackbar; -import androidx.fragment.app.Fragment; import android.util.Log; import android.view.Menu; import android.view.MenuItem; +import com.google.android.material.snackbar.Snackbar; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.core.feed.FeedItem; @@ -23,6 +24,7 @@ import de.danoeh.antennapod.core.sync.model.EpisodeAction; import de.danoeh.antennapod.core.util.FeedItemUtil; import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.core.util.ShareUtils; +import de.danoeh.antennapod.dialog.ShareDialog; /** * Handles interactions with the FeedItemMenu. @@ -61,20 +63,9 @@ public class FeedItemMenuHandler { } if (!ShareUtils.hasLinkToShare(selectedItem)) { setItemVisibility(menu, R.id.visit_website_item, false); - setItemVisibility(menu, R.id.share_link_item, false); - setItemVisibility(menu, R.id.share_link_with_position_item, false); - } - if (!hasMedia || selectedItem.getMedia().getDownload_url() == null) { - setItemVisibility(menu, R.id.share_download_url_item, false); - setItemVisibility(menu, R.id.share_download_url_with_position_item, false); - } - if(!hasMedia || selectedItem.getMedia().getPosition() <= 0) { - setItemVisibility(menu, R.id.share_download_url_with_position_item, false); - setItemVisibility(menu, R.id.share_link_with_position_item, false); } boolean fileDownloaded = hasMedia && selectedItem.getMedia().fileExists(); - setItemVisibility(menu, R.id.share_file, fileDownloaded); setItemVisibility(menu, R.id.remove_new_flag_item, selectedItem.isNew()); if (selectedItem.isPlayed()) { @@ -243,20 +234,9 @@ public class FeedItemMenuHandler { case R.id.visit_website_item: IntentUtils.openInBrowser(context, FeedItemUtil.getLinkWithFallback(selectedItem)); break; - case R.id.share_link_item: - ShareUtils.shareFeedItemLink(context, selectedItem); - break; - case R.id.share_download_url_item: - ShareUtils.shareFeedItemDownloadLink(context, selectedItem); - break; - case R.id.share_link_with_position_item: - ShareUtils.shareFeedItemLink(context, selectedItem, true); - break; - case R.id.share_download_url_with_position_item: - ShareUtils.shareFeedItemDownloadLink(context, selectedItem, true); - break; - case R.id.share_file: - ShareUtils.shareFeedItemFile(context, selectedItem.getMedia()); + case R.id.share_item: + ShareDialog shareDialog = ShareDialog.newInstance(selectedItem); + shareDialog.show((fragment.getActivity().getSupportFragmentManager()), "ShareEpisodeDialog"); break; default: Log.d(TAG, "Unknown menuItemId: " + menuItemId); diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/MasterSwitchPreference.java b/app/src/main/java/de/danoeh/antennapod/preferences/MasterSwitchPreference.java index 007457c24..94e60ef61 100644 --- a/app/src/main/java/de/danoeh/antennapod/preferences/MasterSwitchPreference.java +++ b/app/src/main/java/de/danoeh/antennapod/preferences/MasterSwitchPreference.java @@ -4,7 +4,7 @@ import android.annotation.TargetApi; import android.content.Context; import android.graphics.Typeface; import android.os.Build; -import androidx.preference.SwitchPreference; +import androidx.preference.SwitchPreferenceCompat; import androidx.preference.PreferenceViewHolder; import android.util.AttributeSet; import android.util.TypedValue; @@ -12,7 +12,7 @@ import android.widget.TextView; import de.danoeh.antennapod.R; -public class MasterSwitchPreference extends SwitchPreference { +public class MasterSwitchPreference extends SwitchPreferenceCompat { public MasterSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java index 367593131..2a157c23b 100644 --- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java +++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java @@ -2,7 +2,7 @@ package de.danoeh.antennapod.preferences; import android.content.Context; import android.content.SharedPreferences; -import android.preference.PreferenceManager; +import androidx.preference.PreferenceManager; import de.danoeh.antennapod.BuildConfig; import de.danoeh.antennapod.CrashReportWriter; diff --git a/app/src/main/java/de/danoeh/antennapod/spa/SPAUtil.java b/app/src/main/java/de/danoeh/antennapod/spa/SPAUtil.java index 1f28b5c49..f9c10041e 100644 --- a/app/src/main/java/de/danoeh/antennapod/spa/SPAUtil.java +++ b/app/src/main/java/de/danoeh/antennapod/spa/SPAUtil.java @@ -3,7 +3,7 @@ package de.danoeh.antennapod.spa; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; -import android.preference.PreferenceManager; +import androidx.preference.PreferenceManager; import android.util.Log; import de.danoeh.antennapod.BuildConfig; diff --git a/app/src/main/java/de/danoeh/antennapod/view/EpisodeItemListRecyclerView.java b/app/src/main/java/de/danoeh/antennapod/view/EpisodeItemListRecyclerView.java index 58d562616..83d90f98b 100644 --- a/app/src/main/java/de/danoeh/antennapod/view/EpisodeItemListRecyclerView.java +++ b/app/src/main/java/de/danoeh/antennapod/view/EpisodeItemListRecyclerView.java @@ -2,6 +2,7 @@ package de.danoeh.antennapod.view; import android.content.Context; import android.content.SharedPreferences; +import android.content.res.Configuration; import android.util.AttributeSet; import android.view.View; import androidx.appcompat.view.ContextThemeWrapper; @@ -39,6 +40,14 @@ public class EpisodeItemListRecyclerView extends RecyclerView { setLayoutManager(layoutManager); setHasFixedSize(true); addItemDecoration(new HorizontalDividerItemDecoration.Builder(getContext()).build()); + setClipToPadding(false); + } + + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + int horizontalSpacing = (int) getResources().getDimension(R.dimen.additional_horizontal_spacing); + setPadding(horizontalSpacing, getPaddingTop(), horizontalSpacing, getPaddingBottom()); } public void saveScrollPosition(String tag) { diff --git a/app/src/main/java/de/danoeh/antennapod/view/ItemOffsetDecoration.java b/app/src/main/java/de/danoeh/antennapod/view/ItemOffsetDecoration.java new file mode 100644 index 000000000..4a1267d81 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/view/ItemOffsetDecoration.java @@ -0,0 +1,24 @@ +package de.danoeh.antennapod.view; + +import android.content.Context; +import android.graphics.Rect; +import android.view.View; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +/** + * Source: https://stackoverflow.com/a/30794046 + */ +public class ItemOffsetDecoration extends RecyclerView.ItemDecoration { + private final int itemOffset; + + public ItemOffsetDecoration(@NonNull Context context, int itemOffsetDp) { + itemOffset = (int) (itemOffsetDp * context.getResources().getDisplayMetrics().density); + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + outRect.set(itemOffset, itemOffset, itemOffset, itemOffset); + } +} diff --git a/app/src/main/java/de/danoeh/antennapod/view/NestedScrollableHost.java b/app/src/main/java/de/danoeh/antennapod/view/NestedScrollableHost.java index a4daa9109..0e1846f1c 100644 --- a/app/src/main/java/de/danoeh/antennapod/view/NestedScrollableHost.java +++ b/app/src/main/java/de/danoeh/antennapod/view/NestedScrollableHost.java @@ -54,7 +54,7 @@ class NestedScrollableHost extends FrameLayout { touchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); } - private int touchSlop = 0; + private int touchSlop; private float initialX = 0f; private float initialY = 0f; diff --git a/app/src/main/java/de/danoeh/antennapod/view/PlaybackSpeedSeekBar.java b/app/src/main/java/de/danoeh/antennapod/view/PlaybackSpeedSeekBar.java new file mode 100644 index 000000000..47797e4a4 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/view/PlaybackSpeedSeekBar.java @@ -0,0 +1,86 @@ +package de.danoeh.antennapod.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.SeekBar; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.util.Consumer; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.core.util.playback.PlaybackController; +import de.danoeh.antennapod.dialog.VariableSpeedDialog; + +public class PlaybackSpeedSeekBar extends FrameLayout { + private SeekBar seekBar; + private PlaybackController controller; + private Consumer<Float> progressChangedListener; + + public PlaybackSpeedSeekBar(@NonNull Context context) { + super(context); + setup(); + } + + public PlaybackSpeedSeekBar(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + setup(); + } + + public PlaybackSpeedSeekBar(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + setup(); + } + + private void setup() { + View.inflate(getContext(), R.layout.playback_speed_seek_bar, this); + seekBar = findViewById(R.id.playback_speed); + findViewById(R.id.butDecSpeed).setOnClickListener(v -> seekBar.setProgress(seekBar.getProgress() - 2)); + findViewById(R.id.butIncSpeed).setOnClickListener(v -> seekBar.setProgress(seekBar.getProgress() + 2)); + + seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (controller != null && controller.canSetPlaybackSpeed()) { + float playbackSpeed = (progress + 10) / 20.0f; + controller.setPlaybackSpeed(playbackSpeed); + + if (progressChangedListener != null) { + progressChangedListener.accept(playbackSpeed); + } + } else if (fromUser) { + seekBar.post(() -> updateSpeed()); + } + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + if (controller != null && !controller.canSetPlaybackSpeed()) { + VariableSpeedDialog.showGetPluginDialog(getContext()); + } + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + } + }); + } + + public void updateSpeed() { + if (controller != null) { + seekBar.setProgress(Math.round((20 * controller.getCurrentPlaybackSpeedMultiplier()) - 10)); + } + } + + public void setController(PlaybackController controller) { + this.controller = controller; + updateSpeed(); + if (progressChangedListener != null && controller != null) { + progressChangedListener.accept(controller.getCurrentPlaybackSpeedMultiplier()); + } + } + + public void setProgressChangedListener(Consumer<Float> progressChangedListener) { + this.progressChangedListener = progressChangedListener; + } +} diff --git a/app/src/main/java/de/danoeh/antennapod/view/RecursiveRadioGroup.java b/app/src/main/java/de/danoeh/antennapod/view/RecursiveRadioGroup.java new file mode 100644 index 000000000..ee5e7c51d --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/view/RecursiveRadioGroup.java @@ -0,0 +1,67 @@ +package de.danoeh.antennapod.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.RadioButton; +import java.util.ArrayList; + +/** + * An alternative to {@link android.widget.RadioGroup} that allows to nest children. + * Basend on https://stackoverflow.com/a/14309274. + */ +public class RecursiveRadioGroup extends LinearLayout { + private final ArrayList<RadioButton> radioButtons = new ArrayList<>(); + private RadioButton checkedButton = null; + + public RecursiveRadioGroup(Context context) { + super(context); + } + + public RecursiveRadioGroup(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public RecursiveRadioGroup(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + public void addView(View child, int index, ViewGroup.LayoutParams params) { + super.addView(child, index, params); + parseChild(child); + } + + public void parseChild(final View child) { + if (child instanceof RadioButton) { + RadioButton button = (RadioButton) child; + radioButtons.add(button); + button.setOnCheckedChangeListener((buttonView, isChecked) -> { + if (!isChecked) { + return; + } + checkedButton = (RadioButton) buttonView; + + for (RadioButton view : radioButtons) { + if (view != buttonView) { + view.setChecked(false); + } + } + }); + } else if (child instanceof ViewGroup) { + parseChildren((ViewGroup) child); + } + } + + public void parseChildren(final ViewGroup child) { + for (int i = 0; i < child.getChildCount(); i++) { + parseChild(child.getChildAt(i)); + } + } + + public RadioButton getCheckedButton() { + return checkedButton; + } +} diff --git a/app/src/main/java/de/danoeh/antennapod/view/ToolbarIconTintManager.java b/app/src/main/java/de/danoeh/antennapod/view/ToolbarIconTintManager.java index dcf8ff20d..163100fff 100644 --- a/app/src/main/java/de/danoeh/antennapod/view/ToolbarIconTintManager.java +++ b/app/src/main/java/de/danoeh/antennapod/view/ToolbarIconTintManager.java @@ -33,11 +33,15 @@ public abstract class ToolbarIconTintManager implements AppBarLayout.OnOffsetCha public void updateTint() { if (isTinted) { doTint(new ContextThemeWrapper(context, R.style.Theme_AntennaPod_Dark)); - toolbar.getNavigationIcon().setColorFilter(0xffffffff, PorterDuff.Mode.SRC_ATOP); + if (toolbar.getNavigationIcon() != null) { // Tablets do not show a navigation icon + toolbar.getNavigationIcon().setColorFilter(0xffffffff, PorterDuff.Mode.SRC_ATOP); + } toolbar.getOverflowIcon().setColorFilter(0xffffffff, PorterDuff.Mode.SRC_ATOP); } else { doTint(context); - toolbar.getNavigationIcon().clearColorFilter(); + if (toolbar.getNavigationIcon() != null) { // Tablets do not show a navigation icon + toolbar.getNavigationIcon().clearColorFilter(); + } toolbar.getOverflowIcon().clearColorFilter(); } } diff --git a/app/src/main/res/layout-sw720dp/main.xml b/app/src/main/res/layout-sw720dp/main.xml new file mode 100644 index 000000000..79b7213e0 --- /dev/null +++ b/app/src/main/res/layout-sw720dp/main.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:orientation="horizontal" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <FrameLayout + android:id="@+id/navDrawerFragment" + android:layout_width="300dp" + android:layout_height="match_parent" + android:layout_gravity="start" + android:orientation="vertical" /> + + <View + android:layout_width="1dp" + android:layout_height="match_parent" + android:background="?android:attr/listDivider" /> + + <androidx.coordinatorlayout.widget.CoordinatorLayout + android:id="@+id/overview_coordinator_layout" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <FrameLayout + android:id="@+id/main_view" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_alignParentTop="true" + android:foreground="?android:windowContentOverlay" + tools:background="@android:color/holo_red_dark" /> + + <FrameLayout + android:elevation="8dp" + android:id="@+id/audioplayerFragment" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="?android:attr/windowBackground" + android:visibility="gone" + app:layout_behavior="de.danoeh.antennapod.view.LockableBottomSheetBehavior" /> + + </androidx.coordinatorlayout.widget.CoordinatorLayout> + +</LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/addfeed.xml b/app/src/main/res/layout/addfeed.xml index 9d14d209a..ff0a54bc1 100644 --- a/app/src/main/res/layout/addfeed.xml +++ b/app/src/main/res/layout/addfeed.xml @@ -71,7 +71,7 @@ android:focusableInTouchMode="true" android:padding="16dp"> - <fragment + <androidx.fragment.app.FragmentContainerView android:id="@+id/quickFeedDiscovery" android:name="de.danoeh.antennapod.fragment.QuickFeedDiscoveryFragment" android:layout_width="match_parent" @@ -91,8 +91,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:drawablePadding="8dp" - app:drawableStartCompat="?attr/content_new" - app:drawableLeftCompat="?attr/content_new" + app:drawableStartCompat="?attr/feed" + app:drawableLeftCompat="?attr/feed" android:paddingTop="8dp" android:paddingBottom="8dp" android:background="?android:attr/selectableItemBackground" diff --git a/app/src/main/res/layout/all_episodes_fragment.xml b/app/src/main/res/layout/all_episodes_fragment.xml index 73f061a0f..353e4f1d0 100644 --- a/app/src/main/res/layout/all_episodes_fragment.xml +++ b/app/src/main/res/layout/all_episodes_fragment.xml @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" @@ -24,9 +23,9 @@ android:layout_below="@+id/txtvInformation" android:layout_marginTop="0dp" android:layout_marginBottom="0dp" - android:clipToPadding="false" android:paddingTop="@dimen/list_vertical_padding" android:paddingBottom="@dimen/list_vertical_padding" + android:paddingHorizontal="@dimen/additional_horizontal_spacing" android:layout_above="@id/loadingMore" tools:itemCount="13" tools:listitem="@layout/feeditemlist_item" /> diff --git a/app/src/main/res/layout/audio_controls.xml b/app/src/main/res/layout/audio_controls.xml index aa1bdf236..2c9665aad 100644 --- a/app/src/main/res/layout/audio_controls.xml +++ b/app/src/main/res/layout/audio_controls.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> -<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" +<ScrollView + xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" @@ -38,47 +39,10 @@ </LinearLayout> - <LinearLayout + <de.danoeh.antennapod.view.PlaybackSpeedSeekBar + android:id="@+id/speed_seek_bar" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" - android:gravity="center_vertical"> - - <TextView - android:id="@+id/butDecSpeed" - android:layout_width="32dp" - android:layout_height="32dp" - android:gravity="center" - android:text="-" - android:clickable="true" - android:focusable="true" - android:textStyle="bold" - android:textSize="24sp" - android:textColor="?attr/colorSecondary" - android:contentDescription="@string/decrease_speed" - android:background="?attr/selectableItemBackgroundBorderless"/> - - <SeekBar - android:id="@+id/playback_speed" - android:layout_width="0dp" - android:layout_height="32dp" - android:max="70" - android:layout_weight="1" /> - - <TextView - android:id="@+id/butIncSpeed" - android:layout_width="32dp" - android:layout_height="32dp" - android:gravity="center" - android:text="+" - android:clickable="true" - android:focusable="true" - android:textStyle="bold" - android:textSize="24sp" - android:textColor="?attr/colorSecondary" - android:contentDescription="@string/increase_speed" - android:background="?attr/selectableItemBackgroundBorderless" /> - </LinearLayout> + android:layout_height="wrap_content"/> <TextView android:layout_width="wrap_content" diff --git a/app/src/main/res/layout/audioplayer_fragment.xml b/app/src/main/res/layout/audioplayer_fragment.xml index 5b4e26b69..1c2866a1b 100644 --- a/app/src/main/res/layout/audioplayer_fragment.xml +++ b/app/src/main/res/layout/audioplayer_fragment.xml @@ -184,7 +184,7 @@ android:layout_toStartOf="@id/butRev" android:layout_centerVertical="true" android:background="?attr/selectableItemBackgroundBorderless" - android:contentDescription="@string/set_playback_speed_label" + android:contentDescription="@string/playback_speed" tools:srcCompat="@drawable/ic_playback_speed_white"/> <TextView diff --git a/app/src/main/res/layout/choose_data_folder_dialog_entry.xml b/app/src/main/res/layout/choose_data_folder_dialog_entry.xml index ae59c0614..addc63f4d 100644 --- a/app/src/main/res/layout/choose_data_folder_dialog_entry.xml +++ b/app/src/main/res/layout/choose_data_folder_dialog_entry.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/root" android:layout_width="match_parent" diff --git a/app/src/main/res/layout/cover_fragment.xml b/app/src/main/res/layout/cover_fragment.xml index 443f19835..a66a5f5d7 100644 --- a/app/src/main/res/layout/cover_fragment.xml +++ b/app/src/main/res/layout/cover_fragment.xml @@ -12,7 +12,7 @@ <de.danoeh.antennapod.view.SquareImageView android:id="@+id/imgvCover" - android:layout_width="200dp" + android:layout_width="0dp" android:layout_height="200dp" android:layout_gravity="center" android:layout_marginLeft="64dp" diff --git a/app/src/main/res/layout/downloadlog_item.xml b/app/src/main/res/layout/downloadlog_item.xml index dd8328c8c..5cde763a0 100644 --- a/app/src/main/res/layout/downloadlog_item.xml +++ b/app/src/main/res/layout/downloadlog_item.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout - xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" diff --git a/app/src/main/res/layout/empty_view_layout.xml b/app/src/main/res/layout/empty_view_layout.xml index 768f74c41..da2040d93 100644 --- a/app/src/main/res/layout/empty_view_layout.xml +++ b/app/src/main/res/layout/empty_view_layout.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
diff --git a/app/src/main/res/layout/feed_item_list_fragment.xml b/app/src/main/res/layout/feed_item_list_fragment.xml index d6c7409a8..b995ff28f 100644 --- a/app/src/main/res/layout/feed_item_list_fragment.xml +++ b/app/src/main/res/layout/feed_item_list_fragment.xml @@ -52,6 +52,7 @@ android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" + android:paddingHorizontal="@dimen/additional_horizontal_spacing" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> <ProgressBar diff --git a/app/src/main/res/layout/feedinfo.xml b/app/src/main/res/layout/feedinfo.xml index fa6aac251..dd349c15c 100644 --- a/app/src/main/res/layout/feedinfo.xml +++ b/app/src/main/res/layout/feedinfo.xml @@ -62,6 +62,8 @@ <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" + android:id="@+id/infoContainer" + android:paddingHorizontal="@dimen/additional_horizontal_spacing" android:orientation="vertical"> <TextView diff --git a/app/src/main/res/layout/feeditemlist_header.xml b/app/src/main/res/layout/feeditemlist_header.xml index e74aeac0a..a8845ec27 100644 --- a/app/src/main/res/layout/feeditemlist_header.xml +++ b/app/src/main/res/layout/feeditemlist_header.xml @@ -5,6 +5,8 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" + android:id="@+id/headerContainer" + android:paddingHorizontal="@dimen/additional_horizontal_spacing" android:orientation="vertical"> <LinearLayout diff --git a/app/src/main/res/layout/filter_dialog.xml b/app/src/main/res/layout/filter_dialog.xml new file mode 100644 index 000000000..39e9258d9 --- /dev/null +++ b/app/src/main/res/layout/filter_dialog.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:paddingLeft="24dp" + android:paddingTop="24dp" + android:paddingRight="24dp" + android:paddingBottom="8dp"> + +</LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/filter_dialog_row.xml b/app/src/main/res/layout/filter_dialog_row.xml new file mode 100644 index 000000000..0863997b3 --- /dev/null +++ b/app/src/main/res/layout/filter_dialog_row.xml @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="utf-8"?> +<de.danoeh.antennapod.view.RecursiveRadioGroup + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:paddingBottom="8dp" + android:orientation="horizontal"> + + <androidx.cardview.widget.CardView + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:clipChildren="true" + app:cardCornerRadius="32dp" + app:cardElevation="0dp"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="horizontal"> + + <RadioButton + android:id="@+id/filter_dialog_radioButton1" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_marginEnd="2dp" + android:layout_marginRight="2dp" + android:layout_weight="1" + android:background="?attr/filter_dialog_button_background" + android:button="@android:color/transparent" + android:foreground="?android:attr/selectableItemBackground" + android:checked="false" + android:gravity="center" + android:textColor="@color/filter_dialog_button_text" /> + + <RadioButton + android:id="@+id/filter_dialog_radioButton2" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" + android:background="?attr/filter_dialog_button_background" + android:button="@android:color/transparent" + android:foreground="?android:attr/selectableItemBackground" + android:checked="false" + android:gravity="center" + android:textColor="@color/filter_dialog_button_text" /> + </LinearLayout> + </androidx.cardview.widget.CardView> + + <RadioButton + android:id="@+id/filter_dialog_clear" + android:layout_width="48dp" + android:layout_height="48dp" + android:background="@drawable/ic_filter_close" + android:button="@android:color/transparent" + android:foreground="?android:attr/selectableItemBackground" + android:layout_gravity="center_vertical" + android:checked="true" /> + +</de.danoeh.antennapod.view.RecursiveRadioGroup> diff --git a/app/src/main/res/layout/fragment_itunes_search.xml b/app/src/main/res/layout/fragment_itunes_search.xml index 228bfb803..d82051867 100644 --- a/app/src/main/res/layout/fragment_itunes_search.xml +++ b/app/src/main/res/layout/fragment_itunes_search.xml @@ -36,6 +36,7 @@ android:layout_height="match_parent" android:layout_centerInParent="true" android:gravity="center" + android:visibility="gone" android:text="@string/search_status_no_results" /> <ProgressBar @@ -71,4 +72,17 @@ tools:visibility="visible" tools:background="@android:color/holo_red_light" /> + <TextView + android:id="@+id/search_powered_by" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textColor="?android:attr/textColorTertiary" + android:text="@string/discover_powered_by_itunes" + android:textSize="12sp" + android:padding="4dp" + android:background="?android:attr/windowBackground" + android:layout_alignParentBottom="true" + android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" + android:textAlignment="textEnd"/> </RelativeLayout> diff --git a/app/src/main/res/layout/fragment_subscriptions.xml b/app/src/main/res/layout/fragment_subscriptions.xml index f37a6febd..a1a5a26f2 100644 --- a/app/src/main/res/layout/fragment_subscriptions.xml +++ b/app/src/main/res/layout/fragment_subscriptions.xml @@ -14,8 +14,22 @@ app:title="@string/subscriptions_label" android:id="@+id/toolbar"/> - <GridView + <TextView + android:id="@+id/feeds_filtered_message" + android:layout_width="match_parent" + android:layout_height="wrap_content" android:layout_below="@id/toolbar" + android:background="?android:attr/selectableItemBackground" + android:gravity="start" + android:paddingStart="8dp" + android:paddingTop="4dp" + android:paddingEnd="8dp" + android:paddingBottom="8dp" + android:textColor="?android:attr/textColorSecondary" + android:textSize="@dimen/text_size_small" /> + + <GridView + android:layout_below="@id/feeds_filtered_message" android:id="@+id/subscriptions_grid" android:layout_width="match_parent" android:numColumns="3" diff --git a/app/src/main/res/layout/listview_activity.xml b/app/src/main/res/layout/listview_activity.xml deleted file mode 100644 index b276f506c..000000000 --- a/app/src/main/res/layout/listview_activity.xml +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="match_parent"> - <ListView - android:id="@+id/listview" - android:layout_width="match_parent" - android:layout_height="match_parent"/> - -</LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/main.xml b/app/src/main/res/layout/main.xml index 6da514b4a..48195a176 100644 --- a/app/src/main/res/layout/main.xml +++ b/app/src/main/res/layout/main.xml @@ -5,7 +5,9 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/drawer_layout" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" + tools:ignore="InconsistentLayout"> + <!-- InconsistentLayout: Tablet layout does not have a drawer --> <androidx.coordinatorlayout.widget.CoordinatorLayout android:id="@+id/overview_coordinator_layout" @@ -35,8 +37,6 @@ android:id="@+id/navDrawerFragment" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_marginEnd="24dp" - android:layout_marginRight="24dp" android:layout_gravity="start" android:orientation="vertical" /> diff --git a/app/src/main/res/layout/nav_section_item.xml b/app/src/main/res/layout/nav_section_item.xml index 45d0dff59..fb3021556 100644 --- a/app/src/main/res/layout/nav_section_item.xml +++ b/app/src/main/res/layout/nav_section_item.xml @@ -1,16 +1,28 @@ <?xml version="1.0" encoding="utf-8"?> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" - android:layout_height="16dp" + android:layout_height="wrap_content" android:background="@android:color/transparent" android:orientation="vertical" - android:importantForAccessibility="no"> + android:importantForAccessibility="no" + android:paddingTop="8dp" + android:paddingBottom="8dp"> <View android:layout_width="match_parent" android:layout_height="1dp" - android:layout_centerVertical="true" android:background="?android:attr/listDivider" tools:background="@android:color/holo_red_dark"/> -</RelativeLayout> + + <TextView + android:id="@+id/nav_feeds_filtered_message" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="start" + android:paddingStart="@dimen/listitem_icon_leftpadding" + android:paddingTop="4dp" + android:paddingEnd="@dimen/listitem_icon_leftpadding" + android:textColor="?android:attr/textColorSecondary" + android:textSize="@dimen/text_size_small" /> +</LinearLayout> diff --git a/app/src/main/res/layout/playback_speed_seek_bar.xml b/app/src/main/res/layout/playback_speed_seek_bar.xml new file mode 100644 index 000000000..0d3985f5a --- /dev/null +++ b/app/src/main/res/layout/playback_speed_seek_bar.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:gravity="center_vertical"> + + <TextView + android:id="@+id/butDecSpeed" + android:layout_width="32dp" + android:layout_height="32dp" + android:gravity="center" + android:text="-" + android:clickable="true" + android:focusable="true" + android:textStyle="bold" + android:textSize="24sp" + android:textColor="?attr/colorSecondary" + android:contentDescription="@string/decrease_speed" + android:background="?attr/selectableItemBackgroundBorderless"/> + + <SeekBar + android:id="@+id/playback_speed" + android:layout_width="0dp" + android:layout_height="32dp" + android:max="70" + android:layout_weight="1" /> + + <TextView + android:id="@+id/butIncSpeed" + android:layout_width="32dp" + android:layout_height="32dp" + android:gravity="center" + android:text="+" + android:clickable="true" + android:focusable="true" + android:textStyle="bold" + android:textSize="24sp" + android:textColor="?attr/colorSecondary" + android:contentDescription="@string/increase_speed" + android:background="?attr/selectableItemBackgroundBorderless" /> +</LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/queue_fragment.xml b/app/src/main/res/layout/queue_fragment.xml index 94f929d30..6a1851648 100644 --- a/app/src/main/res/layout/queue_fragment.xml +++ b/app/src/main/res/layout/queue_fragment.xml @@ -36,6 +36,7 @@ android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" + android:paddingHorizontal="@dimen/additional_horizontal_spacing" android:layout_below="@id/divider" /> <ProgressBar diff --git a/app/src/main/res/layout/quick_feed_discovery.xml b/app/src/main/res/layout/quick_feed_discovery.xml index a274fcdc7..b125206c1 100644 --- a/app/src/main/res/layout/quick_feed_discovery.xml +++ b/app/src/main/res/layout/quick_feed_discovery.xml @@ -62,4 +62,15 @@ android:layout_height="wrap_content"/> </RelativeLayout> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textColor="?android:attr/textColorTertiary" + android:text="@string/discover_powered_by_itunes" + android:textSize="12sp" + android:layout_gravity="right|end" + android:paddingHorizontal="4dp" + android:textAlignment="textEnd"/> + </LinearLayout> diff --git a/app/src/main/res/layout/search_fragment.xml b/app/src/main/res/layout/search_fragment.xml index 19cd87409..0bc663db1 100644 --- a/app/src/main/res/layout/search_fragment.xml +++ b/app/src/main/res/layout/search_fragment.xml @@ -36,7 +36,7 @@ android:layout_below="@id/recyclerViewFeeds" android:layout_marginTop="-4dp" android:paddingTop="12dp" - android:clipToPadding="false" + android:paddingHorizontal="@dimen/additional_horizontal_spacing" android:layout_width="match_parent" android:layout_height="match_parent"/> </RelativeLayout> diff --git a/app/src/main/res/layout/searchlist_item.xml b/app/src/main/res/layout/searchlist_item.xml deleted file mode 100644 index 608bfc3bc..000000000 --- a/app/src/main/res/layout/searchlist_item.xml +++ /dev/null @@ -1,55 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="wrap_content" - tools:background="@android:color/darker_gray" - android:paddingTop="@dimen/listitem_threeline_verticalpadding" - android:paddingBottom="@dimen/listitem_threeline_verticalpadding"> - - <ImageView - android:id="@+id/imgvFeedimage" - android:layout_width="@dimen/thumbnail_length_itemlist" - android:layout_height="@dimen/thumbnail_length_itemlist" - android:layout_alignParentLeft="true" - android:layout_alignParentStart="true" - android:layout_centerVertical="true" - android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding" - android:layout_marginStart="@dimen/listitem_threeline_horizontalpadding" - android:importantForAccessibility="no" - android:scaleType="centerCrop" - tools:src="@drawable/ic_antenna" - tools:background="@android:color/holo_green_dark"/> - - <LinearLayout - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginLeft="@dimen/listitem_iconwithtext_textleftpadding" - android:layout_marginStart="@dimen/listitem_iconwithtext_textleftpadding" - android:layout_marginRight="@dimen/listitem_threeline_verticalpadding" - android:layout_marginEnd="@dimen/listitem_threeline_verticalpadding" - android:layout_toRightOf="@id/imgvFeedimage" - android:layout_toEndOf="@id/imgvFeedimage" - android:orientation="vertical" - tools:background="@android:color/holo_red_dark"> - - <TextView - android:id="@+id/txtvTitle" - style="@style/AntennaPod.TextView.ListItemPrimaryTitle" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginBottom="8dp" - tools:text="Search item title" - tools:background="@android:color/holo_green_dark" /> - - <TextView - android:id="@+id/txtvSubtitle" - style="@style/AntennaPod.TextView.ListItemSecondaryTitle" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:lines="1" - tools:text="Search item subtitle" - tools:background="@android:color/holo_blue_light"/> - </LinearLayout> - -</RelativeLayout> diff --git a/app/src/main/res/layout/share_episode_dialog.xml b/app/src/main/res/layout/share_episode_dialog.xml new file mode 100644 index 000000000..8cf955d4c --- /dev/null +++ b/app/src/main/res/layout/share_episode_dialog.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center" + android:padding="16dp"> + + <RadioGroup + android:id="@+id/share_dialog_radio_group" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="16dp" + android:orientation="vertical"> + + <RadioButton android:id="@+id/share_episode_website_radio" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/share_dialog_episode_website_label" + android:checked="true" + /> + <RadioButton android:id="@+id/share_media_file_radio" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/share_dialog_media_file_label" + /> + </RadioGroup> + + <TextView + android:layout_width="match_parent" + android:layout_height="match_parent" + android:text="@string/share_dialog_include_label"/> + + <CheckBox + android:id="@+id/share_start_at_timer_dialog" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/share_playback_position_dialog_label" /> + +</LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/simple_list_fragment.xml b/app/src/main/res/layout/simple_list_fragment.xml index 368029932..989566499 100644 --- a/app/src/main/res/layout/simple_list_fragment.xml +++ b/app/src/main/res/layout/simple_list_fragment.xml @@ -14,9 +14,9 @@ <de.danoeh.antennapod.view.EpisodeItemListRecyclerView android:layout_width="match_parent" android:layout_height="match_parent" + android:paddingHorizontal="@dimen/additional_horizontal_spacing" android:layout_below="@id/toolbar" - android:id="@+id/recyclerView" - android:clipToPadding="false"/> + android:id="@+id/recyclerView"/> <ProgressBar android:id="@+id/progLoading" diff --git a/app/src/main/res/layout/speed_select_dialog.xml b/app/src/main/res/layout/speed_select_dialog.xml new file mode 100644 index 000000000..e4d78c3fa --- /dev/null +++ b/app/src/main/res/layout/speed_select_dialog.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:padding="16dp" + android:orientation="vertical"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <TextView + android:text="@string/playback_speed" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + style="@style/AntennaPod.TextView.ListItemPrimaryTitle"/> + + <com.google.android.material.chip.Chip + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/add_current_speed_chip"/> + </LinearLayout> + + <de.danoeh.antennapod.view.PlaybackSpeedSeekBar + android:id="@+id/speed_seek_bar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="8dp"> + </de.danoeh.antennapod.view.PlaybackSpeedSeekBar> + + <TextView + android:text="@string/speed_presets" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + style="@style/AntennaPod.TextView.ListItemPrimaryTitle" + android:layout_marginBottom="8dp"/> + + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/selected_speeds_grid" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + +</LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/statistics_fragment.xml b/app/src/main/res/layout/statistics_fragment.xml deleted file mode 100644 index e44c7ca81..000000000 --- a/app/src/main/res/layout/statistics_fragment.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="vertical"> - - - <com.google.android.material.tabs.TabLayout - android:id="@+id/sliding_tabs" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="?android:attr/windowBackground" - app:tabBackground="?attr/selectableItemBackground" - app:tabGravity="fill" - app:tabMode="fixed" /> - - <androidx.viewpager2.widget.ViewPager2 - android:id="@+id/viewpager" - android:layout_width="match_parent" - android:layout_height="0px" - android:layout_weight="1" /> -</LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/menu/downloads_completed.xml b/app/src/main/res/menu/downloads_completed.xml index 8badc4927..e07af520f 100644 --- a/app/src/main/res/menu/downloads_completed.xml +++ b/app/src/main/res/menu/downloads_completed.xml @@ -7,4 +7,10 @@ android:title="@string/multi_select" android:icon="?attr/checkbox_multiple" app:showAsAction="ifRoom" /> + <item + android:id="@+id/refresh_item" + android:title="@string/refresh_label" + android:menuCategory="container" + app:showAsAction="ifRoom" + android:icon="?attr/navigation_refresh"/> </menu> diff --git a/app/src/main/res/menu/downloads_log.xml b/app/src/main/res/menu/downloads_log.xml new file mode 100644 index 000000000..d37d9bf3f --- /dev/null +++ b/app/src/main/res/menu/downloads_log.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + <item + android:id="@+id/clear_history_item" + android:menuCategory="container" + android:title="@string/clear_history_label" + android:icon="?attr/ic_delete" + app:showAsAction="ifRoom" /> + <item + android:id="@+id/refresh_item" + android:title="@string/refresh_label" + android:menuCategory="container" + app:showAsAction="ifRoom" + android:icon="?attr/navigation_refresh"/> +</menu>
\ No newline at end of file diff --git a/app/src/main/res/menu/downloads_running.xml b/app/src/main/res/menu/downloads_running.xml new file mode 100644 index 000000000..a2240d4aa --- /dev/null +++ b/app/src/main/res/menu/downloads_running.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + <item + android:id="@+id/refresh_item" + android:title="@string/refresh_label" + android:menuCategory="container" + app:showAsAction="ifRoom" + android:icon="?attr/navigation_refresh"/> +</menu>
\ No newline at end of file diff --git a/app/src/main/res/menu/episodes_apply_action_options.xml b/app/src/main/res/menu/episodes_apply_action_options.xml index c3f117386..181300fc5 100644 --- a/app/src/main/res/menu/episodes_apply_action_options.xml +++ b/app/src/main/res/menu/episodes_apply_action_options.xml @@ -33,7 +33,7 @@ <item android:id="@+id/check_all" android:title="@string/all_label"/> <item android:id="@+id/check_none" - android:title="@string/none_label"/> + android:title="@string/select_none_label"/> <item android:id="@+id/check_played" android:title="@string/played_label"/> <item android:id="@+id/check_unplayed" diff --git a/app/src/main/res/menu/feeditem_options.xml b/app/src/main/res/menu/feeditem_options.xml index e415ff85a..c29229e37 100644 --- a/app/src/main/res/menu/feeditem_options.xml +++ b/app/src/main/res/menu/feeditem_options.xml @@ -71,29 +71,7 @@ <item android:id="@+id/share_item" android:menuCategory="container" - android:title="@string/share_label"> - <menu> - <item - android:id="@+id/share_link_item" - android:menuCategory="container" - android:title="@string/share_link_label" /> - <item - android:id="@+id/share_link_with_position_item" - android:menuCategory="container" - android:title="@string/share_link_with_position_label" /> - <item - android:id="@+id/share_download_url_item" - android:menuCategory="container" - android:title="@string/share_item_url_label" /> - <item - android:id="@+id/share_download_url_with_position_item" - android:menuCategory="container" - android:title="@string/share_item_url_with_position_label" /> - <item - android:id="@+id/share_file" - android:menuCategory="container" - android:title="@string/share_file_label" /> - </menu> + android:title="@string/share_label_with_ellipses"> </item> <item diff --git a/app/src/main/res/menu/feedlist.xml b/app/src/main/res/menu/feedlist.xml index 939a51ab2..3614cfffa 100644 --- a/app/src/main/res/menu/feedlist.xml +++ b/app/src/main/res/menu/feedlist.xml @@ -52,19 +52,25 @@ android:title="@string/visit_website_label" android:visible="true"> </item> + <item - android:id="@+id/share_link_item" - android:menuCategory="container" - custom:showAsAction="collapseActionView" - android:title="@string/share_website_url_label"> - </item> - <item - android:id="@+id/share_download_url_item" + android:id="@+id/share_item" android:menuCategory="container" - custom:showAsAction="collapseActionView" - android:title="@string/share_feed_url_label"> + custom:showAsAction="never" + android:title="@string/share_label_with_ellipses"> + <menu> + <item + android:id="@+id/share_link_item" + android:title="@string/share_website_url_label"> + </item> + <item + android:id="@+id/share_download_url_item" + android:title="@string/share_feed_url_label"> + </item> + </menu> </item> + <item android:id="@+id/rename_item" android:menuCategory="container" diff --git a/app/src/main/res/menu/mediaplayer.xml b/app/src/main/res/menu/mediaplayer.xml index a61616ce9..8afdba369 100644 --- a/app/src/main/res/menu/mediaplayer.xml +++ b/app/src/main/res/menu/mediaplayer.xml @@ -62,28 +62,6 @@ android:id="@+id/share_item" android:menuCategory="container" custom:showAsAction="never" - android:title="@string/share_label"> - <menu> - <item - android:id="@+id/share_link_item" - android:menuCategory="container" - android:title="@string/share_link_label" /> - <item - android:id="@+id/share_link_with_position_item" - android:menuCategory="container" - android:title="@string/share_link_with_position_label" /> - <item - android:id="@+id/share_download_url_item" - android:menuCategory="container" - android:title="@string/share_item_url_label" /> - <item - android:id="@+id/share_download_url_with_position_item" - android:menuCategory="container" - android:title="@string/share_item_url_with_position_label" /> - <item - android:id="@+id/share_file" - android:menuCategory="container" - android:title="@string/share_file_label" /> - </menu> + android:title="@string/share_label_with_ellipses"> </item> </menu>
\ No newline at end of file diff --git a/app/src/main/res/menu/subscriptions.xml b/app/src/main/res/menu/subscriptions.xml index 1780592d5..b7dc95299 100644 --- a/app/src/main/res/menu/subscriptions.xml +++ b/app/src/main/res/menu/subscriptions.xml @@ -9,6 +9,15 @@ custom:showAsAction="always" android:icon="?attr/navigation_refresh"/> + + <item + android:id="@+id/subscriptions_filter" + android:title="@string/filter" + custom:showAsAction="never" /> + <item + android:id="@+id/subscriptions_sort" + android:title="@string/sort" + custom:showAsAction="never" /> <item android:id="@+id/subscription_num_columns" android:title="@string/subscription_num_columns" diff --git a/app/src/main/res/values-sw600dp/integers.xml b/app/src/main/res/values-sw600dp/integers.xml new file mode 100644 index 000000000..fb43e5de6 --- /dev/null +++ b/app/src/main/res/values-sw600dp/integers.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <integer name="subscriptions_default_num_of_columns">5</integer> +</resources>
\ No newline at end of file diff --git a/app/src/main/res/values-w1000dp/dimens.xml b/app/src/main/res/values-w1000dp/dimens.xml new file mode 100644 index 000000000..59ddcb5c0 --- /dev/null +++ b/app/src/main/res/values-w1000dp/dimens.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <dimen name="additional_horizontal_spacing">56dp</dimen> +</resources>
\ No newline at end of file diff --git a/app/src/main/res/values-w300dp/dimens-fabspeeddial.xml b/app/src/main/res/values-w300dp/dimens-fabspeeddial.xml deleted file mode 100644 index 1b90da786..000000000 --- a/app/src/main/res/values-w300dp/dimens-fabspeeddial.xml +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<resources xmlns:tools="http://schemas.android.com/tools"> - <!-- increase FAB speed dial label's max width if the screen is wide enough - (300dp ~ 1.875 inch, devices with 3.5-inch screens have a width of ~ 1.9in - so the setup is applicable for most phones) - --> - <dimen name="sd_label_max_width" tools:ignore="MissingDefaultResource">240dp</dimen> -</resources> diff --git a/app/src/main/res/values-w300dp/dimens.xml b/app/src/main/res/values-w300dp/dimens.xml new file mode 100644 index 000000000..8adaf4c2d --- /dev/null +++ b/app/src/main/res/values-w300dp/dimens.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources xmlns:tools="http://schemas.android.com/tools"> + <dimen name="additional_horizontal_spacing">0dp</dimen> + <!-- + Overwrites FAB library. + Increase FAB speed dial label's max width if the screen is wide enough + (300dp ~ 1.875 inch, devices with 3.5-inch screens have a width of ~ 1.9in + so the setup is applicable for most phones) + --> + <dimen name="sd_label_max_width" tools:ignore="MissingDefaultResource, UnusedResources">240dp</dimen> +</resources> diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 000000000..f5f6aa0a8 --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <dimen name="additional_horizontal_spacing">0dp</dimen> +</resources>
\ No newline at end of file diff --git a/app/src/main/res/values/integers.xml b/app/src/main/res/values/integers.xml new file mode 100644 index 000000000..a7a7ead7b --- /dev/null +++ b/app/src/main/res/values/integers.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <integer name="subscriptions_default_num_of_columns">3</integer> + <integer name="nav_drawer_screen_size_percent">80</integer> +</resources>
\ No newline at end of file diff --git a/app/src/main/res/xml/automotive_app_desc.xml b/app/src/main/res/xml/automotive_app_desc.xml index 8f0a7c59c..0a6a3c9fb 100644 --- a/app/src/main/res/xml/automotive_app_desc.xml +++ b/app/src/main/res/xml/automotive_app_desc.xml @@ -1,4 +1,4 @@ <?xml version="1.0" encoding="utf-8"?> -<automotiveApp xmlns:android="http://schemas.android.com/apk/res/android"> +<automotiveApp> <uses name="media"/> </automotiveApp>
\ No newline at end of file diff --git a/app/src/main/res/xml/feed_settings.xml b/app/src/main/res/xml/feed_settings.xml index 9f8392f44..a6820a4ad 100644 --- a/app/src/main/res/xml/feed_settings.xml +++ b/app/src/main/res/xml/feed_settings.xml @@ -3,7 +3,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:key="feedSettingsScreen"> - <SwitchPreference + <SwitchPreferenceCompat android:key="keepUpdated" android:icon="?attr/navigation_refresh" android:title="@string/keep_updated" @@ -45,7 +45,7 @@ android:key="volumeReduction"/> <PreferenceCategory android:title="@string/auto_download_settings_label"> - <SwitchPreference + <SwitchPreferenceCompat android:key="autoDownload" android:title="@string/auto_download_label"/> <Preference diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index b69f27473..0a19a36b1 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -44,7 +44,9 @@ android:title="@string/statistics_label" android:icon="?attr/statistics" /> - <PreferenceCategory android:title="@string/project_pref"> + <PreferenceCategory + android:key="project" + android:title="@string/project_pref"> <Preference android:key="prefFaq" android:title="@string/pref_faq" diff --git a/app/src/main/res/xml/preferences_autodownload.xml b/app/src/main/res/xml/preferences_autodownload.xml index 333224aa0..2b541afa3 100644 --- a/app/src/main/res/xml/preferences_autodownload.xml +++ b/app/src/main/res/xml/preferences_autodownload.xml @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:search="http://schemas.android.com/apk/com.bytehamster.lib.preferencesearch"> <de.danoeh.antennapod.preferences.MasterSwitchPreference @@ -23,12 +22,12 @@ android:title="@string/pref_episode_cleanup_title" android:summary="@string/pref_episode_cleanup_summary" android:entryValues="@array/episode_cleanup_values"/> - <SwitchPreference + <SwitchPreferenceCompat android:key="prefEnableAutoDownloadOnBattery" android:title="@string/pref_automatic_download_on_battery_title" android:summary="@string/pref_automatic_download_on_battery_sum" android:defaultValue="true"/> - <SwitchPreference + <SwitchPreferenceCompat android:key="prefEnableAutoDownloadWifiFilter" android:title="@string/pref_autodl_wifi_filter_title" android:summary="@string/pref_autodl_wifi_filter_sum"/> diff --git a/app/src/main/res/xml/preferences_gpodder.xml b/app/src/main/res/xml/preferences_gpodder.xml index 5789f5f84..d8478faf2 100644 --- a/app/src/main/res/xml/preferences_gpodder.xml +++ b/app/src/main/res/xml/preferences_gpodder.xml @@ -26,7 +26,7 @@ <Preference android:key="pref_gpodnet_hostname" android:title="@string/pref_gpodnet_sethostname_title"/> - <SwitchPreference + <SwitchPreferenceCompat android:key="pref_gpodnet_notifications" android:title="@string/pref_gpodnet_notifications_title" android:summary="@string/pref_gpodnet_notifications_sum" diff --git a/app/src/main/res/xml/preferences_network.xml b/app/src/main/res/xml/preferences_network.xml index 5d1831ef0..f51b9561e 100644 --- a/app/src/main/res/xml/preferences_network.xml +++ b/app/src/main/res/xml/preferences_network.xml @@ -29,13 +29,13 @@ numberpicker:maxValue="50" android:key="prefParallelDownloads" android:title="@string/pref_parallel_downloads_title"/> - <SwitchPreference + <SwitchPreferenceCompat android:defaultValue="true" android:enabled="true" android:key="prefShowDownloadReport" android:summary="@string/pref_showDownloadReport_sum" android:title="@string/pref_showDownloadReport_title"/> - <SwitchPreference + <SwitchPreferenceCompat android:defaultValue="false" android:enabled="true" android:key="prefShowAutoDownloadReport" diff --git a/app/src/main/res/xml/preferences_playback.xml b/app/src/main/res/xml/preferences_playback.xml index 32bf383d7..161332d2f 100644 --- a/app/src/main/res/xml/preferences_playback.xml +++ b/app/src/main/res/xml/preferences_playback.xml @@ -2,33 +2,33 @@ <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceCategory android:title="@string/interruptions"> - <SwitchPreference + <SwitchPreferenceCompat android:defaultValue="true" android:enabled="true" android:key="prefPauseOnHeadsetDisconnect" android:summary="@string/pref_pauseOnDisconnect_sum" android:title="@string/pref_pauseOnHeadsetDisconnect_title"/> - <SwitchPreference + <SwitchPreferenceCompat android:defaultValue="true" android:enabled="true" android:dependency="prefPauseOnHeadsetDisconnect" android:key="prefUnpauseOnHeadsetReconnect" android:summary="@string/pref_unpauseOnHeadsetReconnect_sum" android:title="@string/pref_unpauseOnHeadsetReconnect_title"/> - <SwitchPreference + <SwitchPreferenceCompat android:defaultValue="false" android:enabled="true" android:dependency="prefPauseOnHeadsetDisconnect" android:key="prefUnpauseOnBluetoothReconnect" android:summary="@string/pref_unpauseOnBluetoothReconnect_sum" android:title="@string/pref_unpauseOnBluetoothReconnect_title"/> - <SwitchPreference + <SwitchPreferenceCompat android:defaultValue="false" android:enabled="true" android:key="prefPauseForFocusLoss" android:summary="@string/pref_pausePlaybackForFocusLoss_sum" android:title="@string/pref_pausePlaybackForFocusLoss_title"/> - <SwitchPreference + <SwitchPreferenceCompat android:defaultValue="true" android:enabled="true" android:key="prefResumeAfterCall" @@ -44,13 +44,13 @@ </PreferenceCategory> <PreferenceCategory android:title="@string/playback_control"> - <SwitchPreference + <SwitchPreferenceCompat android:defaultValue="false" android:enabled="true" android:key="prefHardwareForwardButtonSkips" android:summary="@string/pref_hardwareForwardButtonSkips_sum" android:title="@string/pref_hardwareForwardButtonSkips_title"/> - <SwitchPreference + <SwitchPreferenceCompat android:defaultValue="false" android:enabled="true" android:key="prefHardwarePreviousButtonRestarts" @@ -67,13 +67,13 @@ <Preference android:key="prefPlaybackSpeedLauncher" android:summary="@string/pref_playback_speed_sum" - android:title="@string/pref_playback_speed_title"/> - <SwitchPreference + android:title="@string/playback_speed"/> + <SwitchPreferenceCompat android:defaultValue="false" android:key="prefPlaybackTimeRespectsSpeed" android:summary="@string/pref_playback_time_respects_speed_sum" android:title="@string/pref_playback_time_respects_speed_title"/> - <SwitchPreference + <SwitchPreferenceCompat android:defaultValue="false" android:key="prefStreamOverDownload" android:summary="@string/pref_stream_over_download_sum" @@ -81,7 +81,7 @@ </PreferenceCategory> <PreferenceCategory android:title="@string/queue_label"> - <SwitchPreference + <SwitchPreferenceCompat android:defaultValue="true" android:enabled="true" android:key="prefEnqueueDownloaded" @@ -93,7 +93,7 @@ android:entryValues="@array/enqueue_location_values" android:key="prefEnqueueLocation" android:title="@string/pref_enqueue_location_title"/> - <SwitchPreference + <SwitchPreferenceCompat android:defaultValue="true" android:enabled="true" android:key="prefFollowQueue" @@ -106,7 +106,7 @@ android:key="prefSmartMarkAsPlayedSecs" android:summary="@string/pref_smart_mark_as_played_sum" android:title="@string/pref_smart_mark_as_played_title"/> - <SwitchPreference + <SwitchPreferenceCompat android:defaultValue="true" android:enabled="true" android:key="prefSkipKeepsEpisode" @@ -125,7 +125,7 @@ </PreferenceCategory> <PreferenceCategory android:title="@string/experimental_pref"> - <SwitchPreference + <SwitchPreferenceCompat android:defaultValue="false" android:enabled="true" android:key="prefCast" diff --git a/app/src/main/res/xml/preferences_storage.xml b/app/src/main/res/xml/preferences_storage.xml index 18e2abb31..d3d570e6c 100644 --- a/app/src/main/res/xml/preferences_storage.xml +++ b/app/src/main/res/xml/preferences_storage.xml @@ -13,19 +13,19 @@ android:key="prefImageCacheSize" android:summary="@string/pref_image_cache_size_sum" android:defaultValue="100"/> - <SwitchPreference + <SwitchPreferenceCompat android:defaultValue="false" android:enabled="true" android:key="prefAutoDelete" android:summary="@string/pref_auto_delete_sum" android:title="@string/pref_auto_delete_title"/> - <SwitchPreference + <SwitchPreferenceCompat android:defaultValue="true" android:enabled="true" android:key="prefFavoriteKeepsEpisode" android:summary="@string/pref_favorite_keeps_episodes_sum" android:title="@string/pref_favorite_keeps_episodes_title"/> - <SwitchPreference + <SwitchPreferenceCompat android:defaultValue="false" android:enabled="true" android:key="prefDeleteRemovesFromQueue" diff --git a/app/src/main/res/xml/preferences_user_interface.xml b/app/src/main/res/xml/preferences_user_interface.xml index a2fc970e0..c1db2dc1e 100644 --- a/app/src/main/res/xml/preferences_user_interface.xml +++ b/app/src/main/res/xml/preferences_user_interface.xml @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto"> + xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceCategory android:title="@string/appearance"> <ListPreference @@ -15,35 +14,38 @@ android:key="prefHiddenDrawerItems" android:summary="@string/pref_nav_drawer_items_sum" android:title="@string/pref_nav_drawer_items_title"/> - <ListPreference - android:entryValues="@array/nav_drawer_feed_order_values" - android:entries="@array/nav_drawer_feed_order_options" - android:title="@string/pref_nav_drawer_feed_order_title" - android:key="prefDrawerFeedOrder" - android:summary="@string/pref_nav_drawer_feed_order_sum" - android:defaultValue="0"/> - <ListPreference - android:entryValues="@array/nav_drawer_feed_counter_values" - android:entries="@array/nav_drawer_feed_counter_options" - android:title="@string/pref_nav_drawer_feed_counter_title" - android:key="prefDrawerFeedIndicator" - android:summary="@string/pref_nav_drawer_feed_counter_sum" - android:defaultValue="1"/> - <SwitchPreference + <SwitchPreferenceCompat android:title="@string/pref_episode_cover_title" android:key="prefEpisodeCover" android:summary="@string/pref_episode_cover_summary" android:defaultValue="true" android:enabled="true"/> </PreferenceCategory> + <PreferenceCategory android:title="@string/subscriptions_label"> + <Preference + android:title="@string/pref_nav_drawer_feed_order_title" + android:key="prefDrawerFeedOrder" + android:summary="@string/pref_nav_drawer_feed_order_sum"/> + <ListPreference + android:entryValues="@array/nav_drawer_feed_counter_values" + android:entries="@array/nav_drawer_feed_counter_options" + android:title="@string/pref_nav_drawer_feed_counter_title" + android:key="prefDrawerFeedIndicator" + android:summary="@string/pref_nav_drawer_feed_counter_sum" + android:defaultValue="1"/> + <Preference + android:title="@string/pref_filter_feed_title" + android:key="prefFeedFilter" + android:summary="@string/pref_filter_feed_sum" /> + </PreferenceCategory> <PreferenceCategory android:title="@string/external_elements"> - <SwitchPreference + <SwitchPreferenceCompat android:defaultValue="false" android:enabled="true" android:key="prefExpandNotify" android:summary="@string/pref_expandNotify_sum" android:title="@string/pref_expandNotify_title"/> - <SwitchPreference + <SwitchPreferenceCompat android:defaultValue="true" android:enabled="true" android:key="prefPersistNotify" @@ -53,7 +55,7 @@ android:key="prefCompactNotificationButtons" android:summary="@string/pref_compact_notification_buttons_sum" android:title="@string/pref_compact_notification_buttons_title"/> - <SwitchPreference + <SwitchPreferenceCompat android:defaultValue="true" android:enabled="true" android:key="prefLockscreenBackground" diff --git a/app/src/main/res/xml/provider_paths.xml b/app/src/main/res/xml/provider_paths.xml index c4ed430be..a16b679e3 100644 --- a/app/src/main/res/xml/provider_paths.xml +++ b/app/src/main/res/xml/provider_paths.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<paths xmlns:android="http://schemas.android.com/apk/res/android"> +<paths> <external-path name="external_storage" path="."/> <root-path name="external_files" path="/storage/" /> </paths> diff --git a/app/src/main/res/xml/searchable.xml b/app/src/main/res/xml/searchable.xml deleted file mode 100644 index 0861ecdae..000000000 --- a/app/src/main/res/xml/searchable.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<searchable xmlns:android="http://schemas.android.com/apk/res/android" - android:hint="@string/search_label" - android:label="@string/app_name"/>
\ No newline at end of file diff --git a/app/src/play/java/de/danoeh/antennapod/activity/CastEnabledActivity.java b/app/src/play/java/de/danoeh/antennapod/activity/CastEnabledActivity.java index 10678f556..753feb3e7 100644 --- a/app/src/play/java/de/danoeh/antennapod/activity/CastEnabledActivity.java +++ b/app/src/play/java/de/danoeh/antennapod/activity/CastEnabledActivity.java @@ -3,7 +3,7 @@ package de.danoeh.antennapod.activity; import android.content.SharedPreferences; import android.media.AudioManager; import android.os.Bundle; -import android.preference.PreferenceManager; +import androidx.preference.PreferenceManager; import androidx.appcompat.app.AppCompatActivity; import android.util.Log; import android.view.Menu; |