From 04ff51bd6768884cd638bd2b8969a13aa17b05d2 Mon Sep 17 00:00:00 2001 From: peakvalleytech Date: Fri, 23 Apr 2021 20:04:10 +0200 Subject: New feed update interval or time dialog Co-authored-by: Fivel Rangel Co-authored-by: ByteHamster --- .../de/test/antennapod/ui/PreferencesTest.java | 54 +++++++---- .../dialog/FeedRefreshIntervalDialog.java | 106 ++++++++++++++++++++ .../preferences/NetworkPreferencesFragment.java | 108 ++++++--------------- app/src/main/res/layout/feed_refresh_dialog.xml | 39 ++++++++ app/src/main/res/xml/preferences_network.xml | 4 +- 5 files changed, 209 insertions(+), 102 deletions(-) create mode 100644 app/src/main/java/de/danoeh/antennapod/dialog/FeedRefreshIntervalDialog.java create mode 100644 app/src/main/res/layout/feed_refresh_dialog.xml (limited to 'app') 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 bba546a88..d51ae63ba 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java @@ -3,10 +3,21 @@ package de.test.antennapod.ui; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Resources; -import androidx.preference.PreferenceManager; + import androidx.annotation.StringRes; +import androidx.preference.PreferenceManager; +import androidx.test.espresso.matcher.RootMatchers; import androidx.test.filters.LargeTest; import androidx.test.rule.ActivityTestRule; + +import org.awaitility.Awaitility; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.PreferenceActivity; import de.danoeh.antennapod.core.preferences.UserPreferences; @@ -20,14 +31,8 @@ import de.danoeh.antennapod.fragment.EpisodesFragment; import de.danoeh.antennapod.fragment.QueueFragment; import de.danoeh.antennapod.fragment.SubscriptionFragment; import de.test.antennapod.EspressoTestUtils; -import org.awaitility.Awaitility; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.util.Arrays; -import java.util.concurrent.TimeUnit; +import static androidx.test.espresso.Espresso.onData; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; import static androidx.test.espresso.action.ViewActions.replaceText; @@ -44,6 +49,7 @@ import static androidx.test.espresso.matcher.ViewMatchers.withText; import static de.test.antennapod.EspressoTestUtils.clickPreference; import static de.test.antennapod.EspressoTestUtils.waitForView; import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static org.hamcrest.Matchers.anything; import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertTrue; @@ -53,18 +59,22 @@ public class PreferencesTest { private Resources res; @Rule - public ActivityTestRule mActivityRule = new ActivityTestRule<>(PreferenceActivity.class, false, false); + public ActivityTestRule activityTestRule = + new ActivityTestRule<>(PreferenceActivity.class, + false, + false); + @Before public void setUp() { EspressoTestUtils.clearDatabase(); EspressoTestUtils.clearPreferences(); - mActivityRule.launchActivity(new Intent()); - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mActivityRule.getActivity()); + activityTestRule.launchActivity(new Intent()); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activityTestRule.getActivity()); prefs.edit().putBoolean(UserPreferences.PREF_ENABLE_AUTODL, true).commit(); - res = mActivityRule.getActivity().getResources(); - UserPreferences.init(mActivityRule.getActivity()); + res = activityTestRule.getActivity().getResources(); + UserPreferences.init(activityTestRule.getActivity()); } @Test @@ -254,8 +264,10 @@ public class PreferencesTest { @Test public void testDisableUpdateInterval() { clickPreference(R.string.network_pref); - onView(withText(R.string.pref_autoUpdateIntervallOrTime_title)).perform(click()); - onView(withText(R.string.pref_autoUpdateIntervallOrTime_Disable)).perform(click()); + clickPreference(R.string.feed_refresh_title); + onView(withText(R.string.feed_refresh_never)).perform(click()); + onView(withId(R.id.disableRadioButton)).perform(click()); + onView(withText(R.string.confirm_label)).perform(click()); Awaitility.await().atMost(1000, MILLISECONDS) .until(() -> UserPreferences.getUpdateInterval() == 0); } @@ -263,12 +275,14 @@ public class PreferencesTest { @Test public void testSetUpdateInterval() { clickPreference(R.string.network_pref); - clickPreference(R.string.pref_autoUpdateIntervallOrTime_title); - onView(withText(R.string.pref_autoUpdateIntervallOrTime_Interval)).perform(click()); - String search = "12 " + res.getString(R.string.pref_update_interval_hours_plural); - onView(withText(search)).perform(click()); + clickPreference(R.string.feed_refresh_title); + onView(withId(R.id.intervalRadioButton)).perform(click()); + onView(withId(R.id.spinner)).perform(click()); + int position = 1; // an arbitrary position + onData(anything()).inRoot(RootMatchers.isPlatformPopup()).atPosition(position).perform(click()); + onView(withText(R.string.confirm_label)).perform(click()); Awaitility.await().atMost(1000, MILLISECONDS) - .until(() -> UserPreferences.getUpdateInterval() == TimeUnit.HOURS.toMillis(12)); + .until(() -> UserPreferences.getUpdateInterval() == TimeUnit.HOURS.toMillis(2)); } @Test diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/FeedRefreshIntervalDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/FeedRefreshIntervalDialog.java new file mode 100644 index 000000000..7e42302d1 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/dialog/FeedRefreshIntervalDialog.java @@ -0,0 +1,106 @@ +package de.danoeh.antennapod.dialog; + +import android.content.Context; +import android.content.res.Resources; +import android.os.Build; +import android.text.format.DateFormat; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ArrayAdapter; +import androidx.appcompat.app.AlertDialog; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.databinding.FeedRefreshDialogBinding; +import org.apache.commons.lang3.ArrayUtils; + +import java.util.concurrent.TimeUnit; + +public class FeedRefreshIntervalDialog { + private static final int[] INTERVAL_VALUES_HOURS = {1, 2, 4, 8, 12, 24, 72}; + private final Context context; + private FeedRefreshDialogBinding viewBinding; + + public FeedRefreshIntervalDialog(Context context) { + this.context = context; + } + + public void show() { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(R.string.feed_refresh_title); + builder.setMessage(R.string.feed_refresh_sum); + viewBinding = FeedRefreshDialogBinding.inflate(LayoutInflater.from(context)); + builder.setView(viewBinding.getRoot()); + + ArrayAdapter spinnerArrayAdapter = new ArrayAdapter<>(context, + android.R.layout.simple_spinner_item, buildSpinnerEntries()); + spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + viewBinding.spinner.setAdapter(spinnerArrayAdapter); + viewBinding.timePicker.setIs24HourView(DateFormat.is24HourFormat(context)); + viewBinding.spinner.setSelection(ArrayUtils.indexOf(INTERVAL_VALUES_HOURS, 24)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + viewBinding.timePicker.setHour(8); + viewBinding.timePicker.setMinute(0); + } else { + viewBinding.timePicker.setCurrentHour(8); + viewBinding.timePicker.setCurrentMinute(0); + } + + long currInterval = UserPreferences.getUpdateInterval(); + int[] updateTime = UserPreferences.getUpdateTimeOfDay(); + if (currInterval > 0) { + viewBinding.spinner.setSelection(ArrayUtils.indexOf(INTERVAL_VALUES_HOURS, + (int) TimeUnit.MILLISECONDS.toHours(currInterval))); + viewBinding.intervalRadioButton.setChecked(true); + } else if (updateTime.length == 2 && updateTime[0] >= 0) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + viewBinding.timePicker.setHour(updateTime[0]); + viewBinding.timePicker.setMinute(updateTime[1]); + } else { + viewBinding.timePicker.setCurrentHour(updateTime[0]); + viewBinding.timePicker.setCurrentMinute(updateTime[1]); + } + viewBinding.timeRadioButton.setChecked(true); + } else { + viewBinding.disableRadioButton.setChecked(true); + } + updateVisibility(); + + viewBinding.radioGroup.setOnCheckedChangeListener((radioGroup, i) -> updateVisibility()); + + builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> { + if (viewBinding.intervalRadioButton.isChecked()) { + UserPreferences.setUpdateInterval(INTERVAL_VALUES_HOURS[viewBinding.spinner.getSelectedItemPosition()]); + } else if (viewBinding.timeRadioButton.isChecked()) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + UserPreferences.setUpdateTimeOfDay(viewBinding.timePicker.getHour(), + viewBinding.timePicker.getMinute()); + } else { + UserPreferences.setUpdateTimeOfDay(viewBinding.timePicker.getCurrentHour(), + viewBinding.timePicker.getCurrentMinute()); + } + } else if (viewBinding.disableRadioButton.isChecked()) { + UserPreferences.disableAutoUpdate(context); + } else { + throw new IllegalStateException("Unexpected error."); + } + }); + + builder.setNegativeButton(R.string.cancel_label, null); + builder.show(); + } + + private String[] buildSpinnerEntries() { + final Resources res = context.getResources(); + String[] entries = new String[INTERVAL_VALUES_HOURS.length]; + for (int i = 0; i < INTERVAL_VALUES_HOURS.length; i++) { + int hours = INTERVAL_VALUES_HOURS[i]; + entries[i] = res.getQuantityString(R.plurals.feed_refresh_every_x_hours, hours, hours); + } + return entries; + } + + private void updateVisibility() { + viewBinding.spinner.setVisibility(viewBinding.intervalRadioButton.isChecked() ? View.VISIBLE : View.GONE); + viewBinding.timePicker.setVisibility(viewBinding.timeRadioButton.isChecked() ? View.VISIBLE : View.GONE); + } +} diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/NetworkPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/NetworkPreferencesFragment.java index 3889034fa..305e495e8 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/NetworkPreferencesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/NetworkPreferencesFragment.java @@ -1,23 +1,25 @@ package de.danoeh.antennapod.fragment.preferences; -import android.app.TimePickerDialog; import android.content.Context; +import android.content.SharedPreferences; import android.content.res.Resources; import android.os.Bundle; -import androidx.appcompat.app.AlertDialog; -import androidx.preference.PreferenceFragmentCompat; import android.text.format.DateFormat; +import androidx.preference.PreferenceFragmentCompat; +import androidx.preference.PreferenceManager; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.PreferenceActivity; import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.dialog.FeedRefreshIntervalDialog; import de.danoeh.antennapod.dialog.ProxyDialog; -import org.apache.commons.lang3.ArrayUtils; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.concurrent.TimeUnit; -public class NetworkPreferencesFragment extends PreferenceFragmentCompat { + +public class NetworkPreferencesFragment extends PreferenceFragmentCompat + implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String PREF_SCREEN_AUTODL = "prefAutoDownloadSettings"; private static final String PREF_PROXY = "prefProxy"; @@ -31,6 +33,13 @@ public class NetworkPreferencesFragment extends PreferenceFragmentCompat { public void onStart() { super.onStart(); ((PreferenceActivity) getActivity()).getSupportActionBar().setTitle(R.string.network_pref); + PreferenceManager.getDefaultSharedPreferences(getContext()).registerOnSharedPreferenceChangeListener(this); + } + + @Override + public void onStop() { + super.onStop(); + PreferenceManager.getDefaultSharedPreferences(getContext()).unregisterOnSharedPreferenceChangeListener(this); } @Override @@ -47,9 +56,10 @@ public class NetworkPreferencesFragment extends PreferenceFragmentCompat { }); findPreference(UserPreferences.PREF_UPDATE_INTERVAL) .setOnPreferenceClickListener(preference -> { - showUpdateIntervalTimePreferencesDialog(); + new FeedRefreshIntervalDialog(getContext()).show(); return true; }); + findPreference(UserPreferences.PREF_PARALLEL_DOWNLOADS) .setOnPreferenceChangeListener( (preference, o) -> { @@ -67,6 +77,9 @@ public class NetworkPreferencesFragment extends PreferenceFragmentCompat { }); } + /** + * Used to init and handle changes to view + */ private void setUpdateIntervalText() { Context context = getActivity().getApplicationContext(); String val; @@ -74,7 +87,7 @@ public class NetworkPreferencesFragment extends PreferenceFragmentCompat { if (interval > 0) { int hours = (int) TimeUnit.MILLISECONDS.toHours(interval); val = context.getResources().getQuantityString( - R.plurals.pref_autoUpdateIntervallOrTime_every_hours, hours, hours); + R.plurals.feed_refresh_every_x_hours, hours, hours); } else { int[] timeOfDay = UserPreferences.getUpdateTimeOfDay(); if (timeOfDay.length == 2) { @@ -82,94 +95,29 @@ public class NetworkPreferencesFragment extends PreferenceFragmentCompat { cal.set(Calendar.HOUR_OF_DAY, timeOfDay[0]); cal.set(Calendar.MINUTE, timeOfDay[1]); String timeOfDayStr = DateFormat.getTimeFormat(context).format(cal.getTime()); - val = String.format(context.getString(R.string.pref_autoUpdateIntervallOrTime_at), + val = String.format(context.getString(R.string.feed_refresh_interval_at), timeOfDayStr); } else { - val = context.getString(R.string.pref_smart_mark_as_played_disabled); // TODO: Is this a bug? Otherwise document why is this related to smart mark??? + val = context.getString(R.string.feed_refresh_never); } } - String summary = context.getString(R.string.pref_autoUpdateIntervallOrTime_sum) + "\n" + String summary = context.getString(R.string.feed_refresh_sum) + "\n" + String.format(context.getString(R.string.pref_current_value), val); findPreference(UserPreferences.PREF_UPDATE_INTERVAL).setSummary(summary); } private void setParallelDownloadsText(int downloads) { final Resources res = getActivity().getResources(); - String s = res.getString(R.string.parallel_downloads, downloads); findPreference(UserPreferences.PREF_PARALLEL_DOWNLOADS).setSummary(s); } - private void showUpdateIntervalTimePreferencesDialog() { - final Context context = getActivity(); - - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(R.string.pref_autoUpdateIntervallOrTime_title); - builder.setMessage(R.string.pref_autoUpdateIntervallOrTime_message); - builder.setPositiveButton(R.string.pref_autoUpdateIntervallOrTime_Interval, (dialog, which) -> { - AlertDialog.Builder builder1 = new AlertDialog.Builder(context); - builder1.setTitle(context.getString(R.string.pref_autoUpdateIntervallOrTime_Interval)); - final String[] values = context.getResources().getStringArray(R.array.update_intervall_values); - final String[] entries = getUpdateIntervalEntries(values); - long currInterval = UserPreferences.getUpdateInterval(); - int checkedItem = -1; - if(currInterval > 0) { - String currIntervalStr = String.valueOf(TimeUnit.MILLISECONDS.toHours(currInterval)); - checkedItem = ArrayUtils.indexOf(values, currIntervalStr); - } - builder1.setSingleChoiceItems(entries, checkedItem, (dialog1, which1) -> { - int hours = Integer.parseInt(values[which1]); - UserPreferences.setUpdateInterval(hours); - dialog1.dismiss(); - setUpdateIntervalText(); - }); - builder1.setNegativeButton(context.getString(R.string.cancel_label), null); - builder1.show(); - }); - builder.setNegativeButton(R.string.pref_autoUpdateIntervallOrTime_TimeOfDay, (dialog, which) -> { - int hourOfDay = 7; - int minute = 0; - int[] updateTime = UserPreferences.getUpdateTimeOfDay(); - if (updateTime.length == 2) { - hourOfDay = updateTime[0]; - minute = updateTime[1]; - } - TimePickerDialog timePickerDialog = new TimePickerDialog(context, - (view, selectedHourOfDay, selectedMinute) -> { - if (view.getTag() == null) { // onTimeSet() may get called twice! - view.setTag("TAGGED"); - UserPreferences.setUpdateTimeOfDay(selectedHourOfDay, selectedMinute); - setUpdateIntervalText(); - } - }, hourOfDay, minute, DateFormat.is24HourFormat(context)); - timePickerDialog.setTitle(context.getString(R.string.pref_autoUpdateIntervallOrTime_TimeOfDay)); - timePickerDialog.show(); - }); - builder.setNeutralButton(R.string.pref_autoUpdateIntervallOrTime_Disable, (dialog, which) -> { - UserPreferences.disableAutoUpdate(context); + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + if (UserPreferences.PREF_UPDATE_INTERVAL.equals(key)) { setUpdateIntervalText(); - }); - builder.show(); - } - - private String[] getUpdateIntervalEntries(final String[] values) { - final Resources res = getActivity().getResources(); - String[] entries = new String[values.length]; - for (int x = 0; x < values.length; x++) { - Integer v = Integer.parseInt(values[x]); - switch (v) { - case 0: - entries[x] = res.getString(R.string.pref_update_interval_hours_manual); - break; - case 1: - entries[x] = v + " " + res.getString(R.string.pref_update_interval_hours_singular); - break; - default: - entries[x] = v + " " + res.getString(R.string.pref_update_interval_hours_plural); - break; - - } } - return entries; } } + + diff --git a/app/src/main/res/layout/feed_refresh_dialog.xml b/app/src/main/res/layout/feed_refresh_dialog.xml new file mode 100644 index 000000000..02b49a6c6 --- /dev/null +++ b/app/src/main/res/layout/feed_refresh_dialog.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/xml/preferences_network.xml b/app/src/main/res/xml/preferences_network.xml index 0dbd1acee..428c891ad 100644 --- a/app/src/main/res/xml/preferences_network.xml +++ b/app/src/main/res/xml/preferences_network.xml @@ -6,8 +6,8 @@ + android:summary="@string/feed_refresh_sum" + android:title="@string/feed_refresh_title"/>