diff options
8 files changed, 240 insertions, 2 deletions
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 d6e7bce13..9a60b04b8 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java @@ -243,4 +243,70 @@ public class MainActivityTest { assertEquals(1, hidden.size()); assertTrue(hidden.contains(DownloadsFragment.TAG)); } + + @Test + public void testBackButtonBehaviorGoToPage() { + openNavDrawer(); + solo.clickOnText(solo.getString(R.string.settings_label)); + solo.clickOnText(solo.getString(R.string.user_interface_label)); + solo.clickOnText(solo.getString(R.string.pref_back_button_behavior_title)); + solo.clickOnText(solo.getString(R.string.back_button_go_to_page)); + solo.waitForDialogToOpen(); + solo.clickOnText(solo.getString(R.string.subscriptions_label)); + solo.clickOnText(solo.getString(R.string.confirm_label)); + solo.goBackToActivity(MainActivity.class.getSimpleName()); + solo.goBack(); + assertEquals(solo.getString(R.string.subscriptions_label), getActionbarTitle()); + } + + @Test + public void testBackButtonBehaviorOpenDrawer() { + openNavDrawer(); + solo.clickOnText(solo.getString(R.string.settings_label)); + solo.clickOnText(solo.getString(R.string.user_interface_label)); + solo.clickOnText(solo.getString(R.string.pref_back_button_behavior_title)); + solo.clickOnText(solo.getString(R.string.back_button_open_drawer)); + solo.goBackToActivity(MainActivity.class.getSimpleName()); + solo.goBack(); + assertTrue(((MainActivity)solo.getCurrentActivity()).isDrawerOpen()); + } + + @Test + public void testBackButtonBehaviorDoubleTap() { + openNavDrawer(); + solo.clickOnText(solo.getString(R.string.settings_label)); + solo.clickOnText(solo.getString(R.string.user_interface_label)); + solo.clickOnText(solo.getString(R.string.pref_back_button_behavior_title)); + solo.clickOnText(solo.getString(R.string.back_button_double_tap)); + solo.goBackToActivity(MainActivity.class.getSimpleName()); + solo.goBack(); + solo.goBack(); + assertTrue(solo.getCurrentActivity().isFinishing()); + } + + @Test + public void testBackButtonBehaviorPrompt() { + openNavDrawer(); + solo.clickOnText(solo.getString(R.string.settings_label)); + solo.clickOnText(solo.getString(R.string.user_interface_label)); + solo.clickOnText(solo.getString(R.string.pref_back_button_behavior_title)); + solo.clickOnText(solo.getString(R.string.back_button_show_prompt)); + solo.goBackToActivity(MainActivity.class.getSimpleName()); + solo.goBack(); + solo.clickOnText(solo.getString(R.string.yes)); + solo.waitForDialogToClose(); + assertTrue(solo.getCurrentActivity().isFinishing()); + } + + @Test + public void testBackButtonBehaviorDefault() { + openNavDrawer(); + solo.clickOnText(solo.getString(R.string.settings_label)); + solo.clickOnText(solo.getString(R.string.user_interface_label)); + solo.clickOnText(solo.getString(R.string.pref_back_button_behavior_title)); + solo.clickOnText(solo.getString(R.string.back_button_default)); + solo.goBackToActivity(MainActivity.class.getSimpleName()); + solo.goBack(); + assertTrue(solo.getCurrentActivity().isFinishing()); + } } 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 bf54ca910..f217ecffa 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java @@ -16,6 +16,10 @@ import de.danoeh.antennapod.core.storage.APCleanupAlgorithm; import de.danoeh.antennapod.core.storage.APNullCleanupAlgorithm; import de.danoeh.antennapod.core.storage.APQueueCleanupAlgorithm; import de.danoeh.antennapod.core.storage.EpisodeCleanupAlgorithm; +import de.danoeh.antennapod.fragment.EpisodesFragment; +import de.danoeh.antennapod.fragment.QueueFragment; +import de.danoeh.antennapod.fragment.SubscriptionFragment; + import org.hamcrest.Matcher; import org.junit.After; import org.junit.Before; @@ -466,6 +470,41 @@ public class PreferencesTest { } } + @Test + public void testBackButtonBehaviorGoToPageSelector() { + clickPreference(withText(R.string.user_interface_label)); + clickPreference(withText(R.string.pref_back_button_behavior_title)); + solo.waitForDialogToOpen(); + solo.clickOnText(solo.getString(R.string.back_button_go_to_page)); + solo.waitForDialogToOpen(); + solo.clickOnText(solo.getString(R.string.queue_label)); + solo.clickOnText(solo.getString(R.string.confirm_label)); + assertTrue(solo.waitForCondition(() -> UserPreferences.getBackButtonBehavior() == UserPreferences.BackButtonBehavior.GO_TO_PAGE, + Timeout.getLargeTimeout())); + assertTrue(solo.waitForCondition(() -> UserPreferences.getBackButtonGoToPage().equals(QueueFragment.TAG), + Timeout.getLargeTimeout())); + clickPreference(withText(R.string.pref_back_button_behavior_title)); + solo.waitForDialogToOpen(); + solo.clickOnText(solo.getString(R.string.back_button_go_to_page)); + solo.waitForDialogToOpen(); + solo.clickOnText(solo.getString(R.string.episodes_label)); + solo.clickOnText(solo.getString(R.string.confirm_label)); + assertTrue(solo.waitForCondition(() -> UserPreferences.getBackButtonBehavior() == UserPreferences.BackButtonBehavior.GO_TO_PAGE, + Timeout.getLargeTimeout())); + assertTrue(solo.waitForCondition(() -> UserPreferences.getBackButtonGoToPage().equals(EpisodesFragment.TAG), + Timeout.getLargeTimeout())); + clickPreference(withText(R.string.pref_back_button_behavior_title)); + solo.waitForDialogToOpen(); + solo.clickOnText(solo.getString(R.string.back_button_go_to_page)); + solo.waitForDialogToOpen(); + solo.clickOnText(solo.getString(R.string.subscriptions_label)); + solo.clickOnText(solo.getString(R.string.confirm_label)); + assertTrue(solo.waitForCondition(() -> UserPreferences.getBackButtonBehavior() == UserPreferences.BackButtonBehavior.GO_TO_PAGE, + Timeout.getLargeTimeout())); + assertTrue(solo.waitForCondition(() -> UserPreferences.getBackButtonGoToPage().equals(SubscriptionFragment.TAG), + Timeout.getLargeTimeout())); + } + private void clickPreference(Matcher<View> matcher) { onView(withId(R.id.list)) .perform(RecyclerViewActions.actionOnItem(hasDescendant(matcher), click())); 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 f506921d2..5595aeac4 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java @@ -27,6 +27,7 @@ import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.ListView; +import android.widget.Toast; import com.bumptech.glide.Glide; @@ -123,6 +124,8 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi private Subscription subscription; + private long lastBackButtonPressTime = 0; + @Override public void onCreate(Bundle savedInstanceState) { setTheme(UserPreferences.getNoTitleTheme()); @@ -643,10 +646,40 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi @Override public void onBackPressed() { - if(isDrawerOpen()) { + if (isDrawerOpen()) { drawerLayout.closeDrawer(navDrawer); - } else { + } else if (getSupportFragmentManager().getBackStackEntryCount() != 0) { super.onBackPressed(); + } else { + switch (UserPreferences.getBackButtonBehavior()) { + case OPEN_DRAWER: + drawerLayout.openDrawer(navDrawer); + break; + case SHOW_PROMPT: + new AlertDialog.Builder(this) + .setMessage(R.string.close_prompt) + .setPositiveButton(R.string.yes, (dialogInterface, i) -> MainActivity.super.onBackPressed()) + .setNegativeButton(R.string.no, null) + .setCancelable(false) + .show(); + break; + case DOUBLE_TAP: + if (lastBackButtonPressTime < System.currentTimeMillis() - 2000) { + Toast.makeText(this, R.string.double_tap_toast, Toast.LENGTH_SHORT).show(); + lastBackButtonPressTime = System.currentTimeMillis(); + } else { + super.onBackPressed(); + } + break; + case GO_TO_PAGE: + if (getLastNavFragment().equals(UserPreferences.getBackButtonGoToPage())) { + super.onBackPressed(); + } else { + loadFragment(UserPreferences.getBackButtonGoToPage(), null); + } + break; + default: super.onBackPressed(); + } } } diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java index 1d93afad9..a9a82d749 100644 --- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java +++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java @@ -227,6 +227,30 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc return true; }); + ui.findPreference(UserPreferences.PREF_BACK_BUTTON_BEHAVIOR) + .setOnPreferenceChangeListener((preference, newValue) -> { + if (newValue.equals("page")) { + final Context context = ui.getActivity(); + final String[] navTitles = context.getResources().getStringArray(R.array.back_button_go_to_pages); + final String[] navTags = context.getResources().getStringArray(R.array.back_button_go_to_pages_tags); + final String choice[] = { UserPreferences.getBackButtonGoToPage() }; + + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(R.string.back_button_go_to_page_title); + builder.setSingleChoiceItems(navTitles, ArrayUtils.indexOf(navTags, UserPreferences.getBackButtonGoToPage()), (dialogInterface, i) -> { + if (i >= 0) { + choice[0] = navTags[i]; + } + }); + builder.setPositiveButton(R.string.confirm_label, (dialogInterface, i) -> UserPreferences.setBackButtonGoToPage(choice[0])); + builder.setNegativeButton(R.string.cancel_label, null); + builder.create().show(); + return true; + } else { + return true; + } + }); + if (Build.VERSION.SDK_INT >= 26) { ui.findPreference(UserPreferences.PREF_EXPANDED_NOTIFICATION).setVisible(false); } diff --git a/app/src/main/res/xml/preferences_user_interface.xml b/app/src/main/res/xml/preferences_user_interface.xml index da694b844..1d970a5f7 100644 --- a/app/src/main/res/xml/preferences_user_interface.xml +++ b/app/src/main/res/xml/preferences_user_interface.xml @@ -57,4 +57,14 @@ android:summary="@string/pref_lockscreen_background_sum" android:title="@string/pref_lockscreen_background_title"/> </PreferenceCategory> + <PreferenceCategory android:title="@string/behavior"> + <ListPreference + android:entryValues="@array/back_button_behavior_values" + android:entries="@array/back_button_behavior_options" + android:key="prefBackButtonBehavior" + android:title="@string/pref_back_button_behavior_title" + android:summary="@string/pref_back_button_behavior_sum" + android:defaultValue="default" + app:useStockLayout="true"/> + </PreferenceCategory> </PreferenceScreen> diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index e6b5f9e1b..c44999c88 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -52,6 +52,8 @@ public class UserPreferences { public static final String PREF_COMPACT_NOTIFICATION_BUTTONS = "prefCompactNotificationButtons"; public static final String PREF_LOCKSCREEN_BACKGROUND = "prefLockscreenBackground"; private static final String PREF_SHOW_DOWNLOAD_REPORT = "prefShowDownloadReport"; + public static final String PREF_BACK_BUTTON_BEHAVIOR = "prefBackButtonBehavior"; + private static final String PREF_BACK_BUTTON_GO_TO_PAGE = "prefBackButtonGoToPage"; // Queue private static final String PREF_QUEUE_ADD_TO_FRONT = "prefQueueAddToFront"; @@ -809,4 +811,29 @@ public class UserPreferences { public enum VideoBackgroundBehavior { STOP, PICTURE_IN_PICTURE, CONTINUE_PLAYING } + + public enum BackButtonBehavior { + DEFAULT, OPEN_DRAWER, DOUBLE_TAP, SHOW_PROMPT, GO_TO_PAGE + } + + public static BackButtonBehavior getBackButtonBehavior() { + switch (prefs.getString(PREF_BACK_BUTTON_BEHAVIOR, "default")) { + case "default": return BackButtonBehavior.DEFAULT; + case "drawer": return BackButtonBehavior.OPEN_DRAWER; + case "doubletap": return BackButtonBehavior.DOUBLE_TAP; + case "prompt": return BackButtonBehavior.SHOW_PROMPT; + case "page": return BackButtonBehavior.GO_TO_PAGE; + default: return BackButtonBehavior.DEFAULT; + } + } + + public static String getBackButtonGoToPage() { + return prefs.getString(PREF_BACK_BUTTON_GO_TO_PAGE, "QueueFragment"); + } + + public static void setBackButtonGoToPage(String tag) { + prefs.edit() + .putString(PREF_BACK_BUTTON_GO_TO_PAGE, tag) + .apply(); + } } diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 7e2fed054..12961504c 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -277,4 +277,32 @@ <item>@string/select_all_above</item> <item>@string/select_all_below</item> </string-array> + + <string-array name="back_button_behavior_options"> + <item>@string/back_button_default</item> + <item>@string/back_button_go_to_page</item> + <item>@string/back_button_open_drawer</item> + <item>@string/back_button_double_tap</item> + <item>@string/back_button_show_prompt</item> + </string-array> + + <string-array name="back_button_behavior_values"> + <item>default</item> + <item>page</item> + <item>drawer</item> + <item>doubletap</item> + <item>prompt</item> + </string-array> + + <string-array name="back_button_go_to_pages"> + <item>@string/queue_label</item> + <item>@string/episodes_label</item> + <item>@string/subscriptions_label</item> + </string-array> + + <string-array name="back_button_go_to_pages_tags"> + <item>QueueFragment</item> + <item>EpisodesFragment</item> + <item>SubscriptionFragment</item> + </string-array> </resources> diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index ad91ecc76..9dd928311 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -470,6 +470,17 @@ <string name="pref_videoBehavior_sum">Behavior when leaving video playback</string> <string name="stop_playback">Stop playback</string> <string name="continue_playback">Continue audio playback</string> + <string name="behavior">Behavior</string> + <string name="pref_back_button_behavior_title">Back Button Behavior</string> + <string name="pref_back_button_behavior_sum">Change behavior of the back button.</string> + <string name="back_button_default">Default</string> + <string name="back_button_open_drawer">Open navigation drawer</string> + <string name="back_button_double_tap">Double tap to exit</string> + <string name="back_button_show_prompt">Confirm to exit</string> + <string name="close_prompt">Are you sure you want to close AntennaPod?</string> + <string name="double_tap_toast">Tap back button again to exit</string> + <string name="back_button_go_to_page">Go to pageā¦</string> + <string name="back_button_go_to_page_title">Select page</string> <!-- Auto-Flattr dialog --> <string name="auto_flattr_enable">Enable automatic flattring</string> |