From 99acff3b8feee5f69acb138a328aa323da8109dc Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Thu, 13 Jun 2019 23:09:59 +0200 Subject: [PATCH] Restructured preferences code --- .../PreferenceControllerFlavorHelper.java | 2 +- .../activity/PreferenceActivity.java | 193 +-- .../AutoDownloadPreferencesFragment.java | 185 +++ .../FlattrPreferencesFragment.java | 61 + .../GpodderPreferencesFragment.java | 144 ++ .../IntegrationsPreferencesFragment.java | 35 + .../preferences/MainPreferencesFragment.java | 150 +++ .../NetworkPreferencesFragment.java | 175 +++ .../PlaybackPreferencesFragment.java | 92 ++ .../StoragePreferencesFragment.java | 244 ++++ .../UserInterfacePreferencesFragment.java | 165 +++ .../preferences/PreferenceController.java | 1190 ----------------- .../PreferenceControllerFlavorHelper.java | 3 +- 13 files changed, 1322 insertions(+), 1317 deletions(-) create mode 100644 app/src/main/java/de/danoeh/antennapod/fragment/preferences/AutoDownloadPreferencesFragment.java create mode 100644 app/src/main/java/de/danoeh/antennapod/fragment/preferences/FlattrPreferencesFragment.java create mode 100644 app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderPreferencesFragment.java create mode 100644 app/src/main/java/de/danoeh/antennapod/fragment/preferences/IntegrationsPreferencesFragment.java create mode 100644 app/src/main/java/de/danoeh/antennapod/fragment/preferences/MainPreferencesFragment.java create mode 100644 app/src/main/java/de/danoeh/antennapod/fragment/preferences/NetworkPreferencesFragment.java create mode 100644 app/src/main/java/de/danoeh/antennapod/fragment/preferences/PlaybackPreferencesFragment.java create mode 100644 app/src/main/java/de/danoeh/antennapod/fragment/preferences/StoragePreferencesFragment.java create mode 100644 app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java delete mode 100644 app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java diff --git a/app/src/free/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java b/app/src/free/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java index 4e2c40885..ff39ed389 100644 --- a/app/src/free/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java +++ b/app/src/free/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java @@ -7,7 +7,7 @@ import de.danoeh.antennapod.core.preferences.UserPreferences; */ class PreferenceControllerFlavorHelper { - static void setupFlavoredUI(PreferenceController.PreferenceUI ui) { + public static void setupFlavoredUI(PlaybackPreferencesFragment ui) { ui.findPreference(UserPreferences.PREF_CAST_ENABLED).setEnabled(false); } } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java index 452e91bd3..c13f713e0 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java @@ -1,12 +1,9 @@ package de.danoeh.antennapod.activity; -import android.content.Intent; import android.os.Bundle; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; -import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceFragmentCompat; -import android.support.v7.preference.PreferenceScreen; import android.view.Menu; import android.view.MenuItem; import android.view.ViewGroup; @@ -15,56 +12,25 @@ import android.widget.FrameLayout; import com.bytehamster.lib.preferencesearch.SearchPreferenceResult; import com.bytehamster.lib.preferencesearch.SearchPreferenceResultListener; -import java.lang.ref.WeakReference; - import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.preferences.PreferenceController; +import de.danoeh.antennapod.fragment.preferences.AutoDownloadPreferencesFragment; +import de.danoeh.antennapod.fragment.preferences.FlattrPreferencesFragment; +import de.danoeh.antennapod.fragment.preferences.GpodderPreferencesFragment; +import de.danoeh.antennapod.fragment.preferences.IntegrationsPreferencesFragment; +import de.danoeh.antennapod.fragment.preferences.MainPreferencesFragment; +import de.danoeh.antennapod.fragment.preferences.NetworkPreferencesFragment; +import de.danoeh.antennapod.fragment.preferences.PlaybackPreferencesFragment; +import de.danoeh.antennapod.fragment.preferences.StoragePreferencesFragment; +import de.danoeh.antennapod.fragment.preferences.UserInterfacePreferencesFragment; /** * PreferenceActivity for API 11+. In order to change the behavior of the preference UI, see * PreferenceController. */ public class PreferenceActivity extends AppCompatActivity implements SearchPreferenceResultListener { - - public static final String PARAM_RESOURCE = "resource"; - private static WeakReference instance; - private PreferenceController preferenceController; - private final PreferenceController.PreferenceUI preferenceUI = new PreferenceController.PreferenceUI() { - private PreferenceFragmentCompat fragment; - - @Override - public void setFragment(PreferenceFragmentCompat fragment) { - this.fragment = fragment; - } - - @Override - public PreferenceFragmentCompat getFragment() { - return fragment; - } - - @Override - public Preference findPreference(CharSequence key) { - return fragment.findPreference(key); - } - - @Override - public PreferenceScreen getPreferenceScreen() { - return fragment.getPreferenceScreen(); - } - - @Override - public AppCompatActivity getActivity() { - return PreferenceActivity.this; - } - }; - @Override protected void onCreate(Bundle savedInstanceState) { - // This must be the FIRST thing we do, otherwise other code may not have the - // reference it needs - instance = new WeakReference<>(this); - setTheme(UserPreferences.getTheme()); super.onCreate(savedInstanceState); @@ -73,38 +39,67 @@ public class PreferenceActivity extends AppCompatActivity implements SearchPrefe ab.setDisplayHomeAsUpEnabled(true); } - // set up layout FrameLayout root = new FrameLayout(this); root.setId(R.id.content); root.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); setContentView(root); - // we need to create the PreferenceController before the MainFragment - // since the MainFragment depends on the preferenceController already being created - preferenceController = new PreferenceController(preferenceUI); + getSupportFragmentManager().beginTransaction().replace(R.id.content, new MainPreferencesFragment()).commit(); - showPreferenceScreen(R.xml.preferences, false); } - private void showPreferenceScreen(int screen, boolean addHistory) { - PreferenceFragmentCompat prefFragment = new MainFragment(); - preferenceUI.setFragment(prefFragment); - Bundle args = new Bundle(); - args.putInt(PARAM_RESOURCE, screen); - prefFragment.setArguments(args); - if (addHistory) { - getSupportFragmentManager().beginTransaction().replace(R.id.content, prefFragment) - .addToBackStack(getString(PreferenceController.getTitleOfPage(screen))).commit(); - } else { - getSupportFragmentManager().beginTransaction().replace(R.id.content, prefFragment).commit(); + private PreferenceFragmentCompat getPreferenceScreen(int screen) { + PreferenceFragmentCompat prefFragment = null; + + if (screen == R.xml.preferences_user_interface) { + prefFragment = new UserInterfacePreferencesFragment(); + } else if (screen == R.xml.preferences_integrations) { + prefFragment = new IntegrationsPreferencesFragment(); + } else if (screen == R.xml.preferences_network) { + prefFragment = new NetworkPreferencesFragment(); + } else if (screen == R.xml.preferences_storage) { + prefFragment = new StoragePreferencesFragment(); + } else if (screen == R.xml.preferences_autodownload) { + prefFragment = new AutoDownloadPreferencesFragment(); + } else if (screen == R.xml.preferences_gpodder) { + prefFragment = new GpodderPreferencesFragment(); + } else if (screen == R.xml.preferences_flattr) { + prefFragment = new FlattrPreferencesFragment(); + } else if (screen == R.xml.preferences_playback) { + prefFragment = new PlaybackPreferencesFragment(); + } + return prefFragment; + } + + public static int getTitleOfPage(int preferences) { + switch (preferences) { + case R.xml.preferences_network: + return R.string.network_pref; + case R.xml.preferences_autodownload: + return R.string.pref_automatic_download_title; + case R.xml.preferences_playback: + return R.string.playback_pref; + case R.xml.preferences_storage: + return R.string.storage_pref; + case R.xml.preferences_user_interface: + return R.string.user_interface_label; + case R.xml.preferences_integrations: + return R.string.integrations_label; + case R.xml.preferences_flattr: + return R.string.flattr_label; + case R.xml.preferences_gpodder: + return R.string.gpodnet_main_label; + default: + return R.string.settings_label; } } - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - preferenceController.onActivityResult(requestCode, resultCode, data); + public PreferenceFragmentCompat openScreen(int screen) { + PreferenceFragmentCompat fragment = getPreferenceScreen(screen); + getSupportFragmentManager().beginTransaction().replace(R.id.content, fragment) + .addToBackStack(getString(getTitleOfPage(screen))).commit(); + return fragment; } @Override @@ -115,72 +110,20 @@ public class PreferenceActivity extends AppCompatActivity implements SearchPrefe @Override public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - if (getSupportFragmentManager().getBackStackEntryCount() == 0) { - finish(); - } else { - getSupportFragmentManager().popBackStack(); - } - return true; - default: - return false; + if (item.getItemId() == android.R.id.home) { + if (getSupportFragmentManager().getBackStackEntryCount() == 0) { + finish(); + } else { + getSupportFragmentManager().popBackStack(); + } + return true; } + return false; } @Override public void onSearchResultClicked(SearchPreferenceResult result) { - showPreferenceScreen(result.getResourceFile(), true); - result.highlight(preferenceUI.getFragment()); - } - - public static class MainFragment extends PreferenceFragmentCompat { - private int screen; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setRetainInstance(true); - } - - @Override - public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { - screen = getArguments().getInt(PARAM_RESOURCE); - addPreferencesFromResource(screen); - PreferenceActivity activity = instance.get(); - if (activity != null && activity.preferenceController != null) { - activity.preferenceUI.setFragment(this); - activity.preferenceController.onCreate(screen); - } - } - - @Override - public void onResume() { - super.onResume(); - PreferenceActivity activity = instance.get(); - if(activity != null && activity.preferenceController != null) { - activity.setTitle(PreferenceController.getTitleOfPage(screen)); - activity.preferenceUI.setFragment(this); - activity.preferenceController.onResume(screen); - } - } - - @Override - public void onPause() { - PreferenceActivity activity = instance.get(); - if (screen == R.xml.preferences_gpodder) { - activity.preferenceController.unregisterGpodnet(); - } - super.onPause(); - } - - @Override - public void onStop() { - PreferenceActivity activity = instance.get(); - if (screen == R.xml.preferences_storage) { - activity.preferenceController.unsubscribeExportSubscription(); - } - super.onStop(); - } + PreferenceFragmentCompat fragment = openScreen(result.getResourceFile()); + result.highlight(fragment); } } 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 new file mode 100644 index 000000000..bfd94b9a2 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AutoDownloadPreferencesFragment.java @@ -0,0 +1,185 @@ +package de.danoeh.antennapod.fragment.preferences; + +import android.app.Activity; +import android.content.Context; +import android.content.res.Resources; +import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiManager; +import android.os.Bundle; +import android.support.v7.preference.CheckBoxPreference; +import android.support.v7.preference.ListPreference; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceFragmentCompat; +import android.support.v7.preference.PreferenceScreen; +import android.util.Log; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.core.preferences.UserPreferences; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class AutoDownloadPreferencesFragment extends PreferenceFragmentCompat { + private static final String TAG = "AutoDnldPrefFragment"; + private CheckBoxPreference[] selectedNetworks; + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + addPreferencesFromResource(R.xml.preferences_autodownload); + + setupAutoDownloadScreen(); + buildAutodownloadSelectedNetworksPreference(); + setSelectedNetworksEnabled(UserPreferences.isEnableAutodownloadWifiFilter()); + buildEpisodeCleanupPreference(); + } + + @Override + public void onResume() { + super.onResume(); + checkAutodownloadItemVisibility(UserPreferences.isEnableAutodownload()); + } + + private void setupAutoDownloadScreen() { + findPreference(UserPreferences.PREF_ENABLE_AUTODL).setOnPreferenceChangeListener( + (preference, newValue) -> { + if (newValue instanceof Boolean) { + checkAutodownloadItemVisibility((Boolean) newValue); + } + return true; + }); + findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER) + .setOnPreferenceChangeListener( + (preference, newValue) -> { + if (newValue instanceof Boolean) { + setSelectedNetworksEnabled((Boolean) newValue); + return true; + } else { + return false; + } + } + ); + } + + private void checkAutodownloadItemVisibility(boolean autoDownload) { + findPreference(UserPreferences.PREF_EPISODE_CACHE_SIZE).setEnabled(autoDownload); + findPreference(UserPreferences.PREF_ENABLE_AUTODL_ON_BATTERY).setEnabled(autoDownload); + findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER).setEnabled(autoDownload); + findPreference(UserPreferences.PREF_EPISODE_CLEANUP).setEnabled(autoDownload); + findPreference(UserPreferences.PREF_ENABLE_AUTODL_ON_MOBILE).setEnabled(autoDownload); + setSelectedNetworksEnabled(autoDownload && UserPreferences.isEnableAutodownloadWifiFilter()); + } + + private static String blankIfNull(String val) { + return val == null ? "" : val; + } + + private void buildAutodownloadSelectedNetworksPreference() { + final Activity activity = getActivity(); + + if (selectedNetworks != null) { + clearAutodownloadSelectedNetworsPreference(); + } + // get configured networks + WifiManager wifiservice = (WifiManager) activity.getApplicationContext().getSystemService(Context.WIFI_SERVICE); + List networks = wifiservice.getConfiguredNetworks(); + + if (networks == null) { + Log.e(TAG, "Couldn't get list of configure Wi-Fi networks"); + return; + } + Collections.sort(networks, (x, y) -> + blankIfNull(x.SSID).compareTo(blankIfNull(y.SSID))); + selectedNetworks = new CheckBoxPreference[networks.size()]; + List prefValues = Arrays.asList(UserPreferences + .getAutodownloadSelectedNetworks()); + PreferenceScreen prefScreen = getPreferenceScreen(); + Preference.OnPreferenceClickListener clickListener = preference -> { + if (preference instanceof CheckBoxPreference) { + String key = preference.getKey(); + List prefValuesList = new ArrayList<>( + Arrays.asList(UserPreferences + .getAutodownloadSelectedNetworks()) + ); + boolean newValue = ((CheckBoxPreference) preference) + .isChecked(); + Log.d(TAG, "Selected network " + key + ". New state: " + newValue); + + int index = prefValuesList.indexOf(key); + if (index >= 0 && !newValue) { + // remove network + prefValuesList.remove(index); + } else if (index < 0 && newValue) { + prefValuesList.add(key); + } + + UserPreferences.setAutodownloadSelectedNetworks( + prefValuesList.toArray(new String[prefValuesList.size()]) + ); + return true; + } else { + return false; + } + }; + // create preference for each known network. attach listener and set + // value + for (int i = 0; i < networks.size(); i++) { + WifiConfiguration config = networks.get(i); + + CheckBoxPreference pref = new CheckBoxPreference(activity); + String key = Integer.toString(config.networkId); + pref.setTitle(config.SSID); + pref.setKey(key); + pref.setOnPreferenceClickListener(clickListener); + pref.setPersistent(false); + pref.setChecked(prefValues.contains(key)); + selectedNetworks[i] = pref; + prefScreen.addPreference(pref); + } + } + + private void clearAutodownloadSelectedNetworsPreference() { + if (selectedNetworks != null) { + PreferenceScreen prefScreen = getPreferenceScreen(); + + for (CheckBoxPreference network : selectedNetworks) { + if (network != null) { + prefScreen.removePreference(network); + } + } + } + } + + private void buildEpisodeCleanupPreference() { + final Resources res = getActivity().getResources(); + + ListPreference pref = (ListPreference) findPreference(UserPreferences.PREF_EPISODE_CLEANUP); + String[] values = res.getStringArray( + R.array.episode_cleanup_values); + String[] entries = new String[values.length]; + for (int x = 0; x < values.length; x++) { + int v = Integer.parseInt(values[x]); + if (v == UserPreferences.EPISODE_CLEANUP_QUEUE) { + entries[x] = res.getString(R.string.episode_cleanup_queue_removal); + } else if (v == UserPreferences.EPISODE_CLEANUP_NULL){ + entries[x] = res.getString(R.string.episode_cleanup_never); + } else if (v == 0) { + entries[x] = res.getString(R.string.episode_cleanup_after_listening); + } else if (v > 0 && v < 24) { + entries[x] = res.getQuantityString(R.plurals.episode_cleanup_hours_after_listening, v, v); + } else { + int numDays = v / 24; // assume underlying value will be NOT fraction of days, e.g., 36 (hours) + entries[x] = res.getQuantityString(R.plurals.episode_cleanup_days_after_listening, numDays, numDays); + } + } + pref.setEntries(entries); + } + + private void setSelectedNetworksEnabled(boolean b) { + if (selectedNetworks != null) { + for (Preference p : selectedNetworks) { + p.setEnabled(b); + } + } + } +} diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/FlattrPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/FlattrPreferencesFragment.java new file mode 100644 index 000000000..152c3da87 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/FlattrPreferencesFragment.java @@ -0,0 +1,61 @@ +package de.danoeh.antennapod.fragment.preferences; + +import android.os.Bundle; +import android.support.v7.preference.PreferenceFragmentCompat; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.util.flattr.FlattrUtils; +import de.danoeh.antennapod.dialog.AutoFlattrPreferenceDialog; + +public class FlattrPreferencesFragment extends PreferenceFragmentCompat { + private static final String PREF_FLATTR_AUTH = "pref_flattr_authenticate"; + private static final String PREF_FLATTR_REVOKE = "prefRevokeAccess"; + private static final String PREF_AUTO_FLATTR_PREFS = "prefAutoFlattrPrefs"; + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + addPreferencesFromResource(R.xml.preferences_flattr); + setupFlattrScreen(); + } + + @Override + public void onResume() { + super.onResume(); + checkFlattrItemVisibility(); + } + + private void setupFlattrScreen() { + findPreference(PREF_FLATTR_REVOKE).setOnPreferenceClickListener( + preference -> { + FlattrUtils.revokeAccessToken(getActivity()); + checkFlattrItemVisibility(); + return true; + } + ); + + findPreference(PREF_AUTO_FLATTR_PREFS) + .setOnPreferenceClickListener(preference -> { + AutoFlattrPreferenceDialog.newAutoFlattrPreferenceDialog(getActivity(), + new AutoFlattrPreferenceDialog.AutoFlattrPreferenceDialogInterface() { + @Override + public void onCancelled() { + + } + + @Override + public void onConfirmed(boolean autoFlattrEnabled, float autoFlattrValue) { + UserPreferences.setAutoFlattrSettings(autoFlattrEnabled, autoFlattrValue); + checkFlattrItemVisibility(); + } + }); + return true; + }); + } + + private void checkFlattrItemVisibility() { + boolean hasFlattrToken = FlattrUtils.hasToken(); + findPreference(PREF_FLATTR_AUTH).setEnabled(!hasFlattrToken); + findPreference(PREF_FLATTR_REVOKE).setEnabled(hasFlattrToken); + findPreference(PREF_AUTO_FLATTR_PREFS).setEnabled(hasFlattrToken); + } +} 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 new file mode 100644 index 000000000..491922056 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderPreferencesFragment.java @@ -0,0 +1,144 @@ +package de.danoeh.antennapod.fragment.preferences; + +import android.app.Activity; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceFragmentCompat; +import android.text.Html; +import android.text.format.DateUtils; +import android.widget.Toast; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.core.preferences.GpodnetPreferences; +import de.danoeh.antennapod.core.service.GpodnetSyncService; +import de.danoeh.antennapod.dialog.AuthenticationDialog; +import de.danoeh.antennapod.dialog.GpodnetSetHostnameDialog; + +public class GpodderPreferencesFragment extends PreferenceFragmentCompat { + private static final String PREF_GPODNET_LOGIN = "pref_gpodnet_authenticate"; + private static final String PREF_GPODNET_SETLOGIN_INFORMATION = "pref_gpodnet_setlogin_information"; + private static final String PREF_GPODNET_SYNC = "pref_gpodnet_sync"; + private static final String PREF_GPODNET_FORCE_FULL_SYNC = "pref_gpodnet_force_full_sync"; + private static final String PREF_GPODNET_LOGOUT = "pref_gpodnet_logout"; + private static final String PREF_GPODNET_HOSTNAME = "pref_gpodnet_hostname"; + private static final String PREF_GPODNET_NOTIFICATIONS = "pref_gpodnet_notifications"; + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + addPreferencesFromResource(R.xml.preferences_gpodder); + setupGpodderScreen(); + } + + @Override + public void onResume() { + super.onResume(); + GpodnetPreferences.registerOnSharedPreferenceChangeListener(gpoddernetListener); + updateGpodnetPreferenceScreen(); + } + + @Override + public void onPause() { + super.onPause(); + GpodnetPreferences.unregisterOnSharedPreferenceChangeListener(gpoddernetListener); + } + + private final SharedPreferences.OnSharedPreferenceChangeListener gpoddernetListener = + (sharedPreferences, key) -> { + if (GpodnetPreferences.PREF_LAST_SYNC_ATTEMPT_TIMESTAMP.equals(key)) { + updateLastGpodnetSyncReport(GpodnetPreferences.getLastSyncAttemptResult(), + GpodnetPreferences.getLastSyncAttemptTimestamp()); + } + }; + + private void setupGpodderScreen() { + final Activity activity = getActivity(); + + findPreference(PREF_GPODNET_SETLOGIN_INFORMATION) + .setOnPreferenceClickListener(preference -> { + AuthenticationDialog dialog = new AuthenticationDialog(activity, + R.string.pref_gpodnet_setlogin_information_title, false, false, GpodnetPreferences.getUsername(), + null) { + + @Override + protected void onConfirmed(String username, String password, boolean saveUsernamePassword) { + GpodnetPreferences.setPassword(password); + } + }; + dialog.show(); + return true; + }); + findPreference(PREF_GPODNET_SYNC). + setOnPreferenceClickListener(preference -> { + GpodnetSyncService.sendSyncIntent(getActivity().getApplicationContext()); + Toast toast = Toast.makeText(getActivity(), R.string.pref_gpodnet_sync_started, + Toast.LENGTH_SHORT); + toast.show(); + return true; + }); + findPreference(PREF_GPODNET_FORCE_FULL_SYNC). + setOnPreferenceClickListener(preference -> { + GpodnetPreferences.setLastSubscriptionSyncTimestamp(0L); + GpodnetPreferences.setLastEpisodeActionsSyncTimestamp(0L); + GpodnetPreferences.setLastSyncAttempt(false, 0); + updateLastGpodnetSyncReport(false, 0); + GpodnetSyncService.sendSyncIntent(getActivity().getApplicationContext()); + Toast toast = Toast.makeText(getActivity(), R.string.pref_gpodnet_sync_started, + Toast.LENGTH_SHORT); + toast.show(); + return true; + }); + findPreference(PREF_GPODNET_LOGOUT).setOnPreferenceClickListener( + preference -> { + GpodnetPreferences.logout(); + Toast toast = Toast.makeText(activity, R.string.pref_gpodnet_logout_toast, Toast.LENGTH_SHORT); + toast.show(); + updateGpodnetPreferenceScreen(); + return true; + }); + findPreference(PREF_GPODNET_HOSTNAME).setOnPreferenceClickListener( + preference -> { + GpodnetSetHostnameDialog.createDialog(activity).setOnDismissListener(dialog -> updateGpodnetPreferenceScreen()); + return true; + }); + } + + private void updateGpodnetPreferenceScreen() { + final boolean loggedIn = GpodnetPreferences.loggedIn(); + findPreference(PREF_GPODNET_LOGIN).setEnabled(!loggedIn); + findPreference(PREF_GPODNET_SETLOGIN_INFORMATION).setEnabled(loggedIn); + findPreference(PREF_GPODNET_SYNC).setEnabled(loggedIn); + findPreference(PREF_GPODNET_FORCE_FULL_SYNC).setEnabled(loggedIn); + findPreference(PREF_GPODNET_LOGOUT).setEnabled(loggedIn); + findPreference(PREF_GPODNET_NOTIFICATIONS).setEnabled(loggedIn); + if(loggedIn) { + 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)); + updateLastGpodnetSyncReport(GpodnetPreferences.getLastSyncAttemptResult(), + GpodnetPreferences.getLastSyncAttemptTimestamp()); + } else { + findPreference(PREF_GPODNET_LOGOUT).setSummary(null); + updateLastGpodnetSyncReport(false, 0); + } + findPreference(PREF_GPODNET_HOSTNAME).setSummary(GpodnetPreferences.getHostname()); + } + + private void updateLastGpodnetSyncReport(boolean successful, long lastTime) { + Preference sync = findPreference(PREF_GPODNET_SYNC); + if (lastTime != 0) { + sync.setSummary(getActivity().getString(R.string.pref_gpodnet_sync_changes_sum) + "\n" + + getActivity().getString(R.string.pref_gpodnet_sync_sum_last_sync_line, + getActivity().getString(successful ? + R.string.gpodnetsync_pref_report_successful : + R.string.gpodnetsync_pref_report_failed), + DateUtils.getRelativeDateTimeString(getActivity(), + lastTime, + DateUtils.MINUTE_IN_MILLIS, + DateUtils.WEEK_IN_MILLIS, + DateUtils.FORMAT_SHOW_TIME))); + } else { + sync.setSummary(getActivity().getString(R.string.pref_gpodnet_sync_changes_sum)); + } + } +} diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/IntegrationsPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/IntegrationsPreferencesFragment.java new file mode 100644 index 000000000..805d84215 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/IntegrationsPreferencesFragment.java @@ -0,0 +1,35 @@ +package de.danoeh.antennapod.fragment.preferences; + +import android.os.Bundle; +import android.support.v7.preference.PreferenceFragmentCompat; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.activity.PreferenceActivity; +import de.danoeh.antennapod.core.util.flattr.FlattrUtils; + +public class IntegrationsPreferencesFragment extends PreferenceFragmentCompat { + private static final String PREF_SCREEN_FLATTR = "prefFlattrSettings"; + private static final String PREF_SCREEN_GPODDER = "prefGpodderSettings"; + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + addPreferencesFromResource(R.xml.preferences_integrations); + setupIntegrationsScreen(); + } + + private void setupIntegrationsScreen() { + findPreference(PREF_SCREEN_FLATTR).setOnPreferenceClickListener(preference -> { + ((PreferenceActivity) getActivity()).openScreen(R.xml.preferences_flattr); + return true; + }); + findPreference(PREF_SCREEN_GPODDER).setOnPreferenceClickListener(preference -> { + ((PreferenceActivity) getActivity()).openScreen(R.xml.preferences_gpodder); + return true; + }); + } + + @Override + public void onResume() { + super.onResume(); + findPreference(PREF_SCREEN_FLATTR).setEnabled(FlattrUtils.hasAPICredentials()); + } +} 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 new file mode 100644 index 000000000..5a4866206 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/MainPreferencesFragment.java @@ -0,0 +1,150 @@ +package de.danoeh.antennapod.fragment.preferences; + +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.support.v4.content.FileProvider; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.preference.PreferenceFragmentCompat; +import android.util.Log; +import android.widget.Toast; +import com.bytehamster.lib.preferencesearch.SearchConfiguration; +import com.bytehamster.lib.preferencesearch.SearchPreference; +import de.danoeh.antennapod.CrashReportWriter; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.activity.AboutActivity; +import de.danoeh.antennapod.activity.PreferenceActivity; +import de.danoeh.antennapod.activity.StatisticsActivity; + +import java.util.List; + +public class MainPreferencesFragment extends PreferenceFragmentCompat { + private static final String TAG = "MainPreferencesFragment"; + + private static final String PREF_SCREEN_USER_INTERFACE = "prefScreenInterface"; + private static final String PREF_SCREEN_PLAYBACK = "prefScreenPlayback"; + private static final String PREF_SCREEN_NETWORK = "prefScreenNetwork"; + private static final String PREF_SCREEN_INTEGRATIONS = "prefScreenIntegrations"; + private static final String PREF_SCREEN_STORAGE = "prefScreenStorage"; + private static final String PREF_KNOWN_ISSUES = "prefKnownIssues"; + private static final String PREF_FAQ = "prefFaq"; + private static final String PREF_SEND_CRASH_REPORT = "prefSendCrashReport"; + private static final String STATISTICS = "statistics"; + private static final String PREF_ABOUT = "prefAbout"; + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + addPreferencesFromResource(R.xml.preferences); + setupMainScreen(); + setupSearch(); + } + + private void setupMainScreen() { + findPreference(PREF_SCREEN_USER_INTERFACE).setOnPreferenceClickListener(preference -> { + ((PreferenceActivity) getActivity()).openScreen(R.xml.preferences_user_interface); + return true; + }); + findPreference(PREF_SCREEN_PLAYBACK).setOnPreferenceClickListener(preference -> { + ((PreferenceActivity) getActivity()).openScreen(R.xml.preferences_playback); + return true; + }); + findPreference(PREF_SCREEN_NETWORK).setOnPreferenceClickListener(preference -> { + ((PreferenceActivity) getActivity()).openScreen(R.xml.preferences_network); + return true; + }); + findPreference(PREF_SCREEN_INTEGRATIONS).setOnPreferenceClickListener(preference -> { + ((PreferenceActivity) getActivity()).openScreen(R.xml.preferences_integrations); + return true; + }); + findPreference(PREF_SCREEN_STORAGE).setOnPreferenceClickListener(preference -> { + ((PreferenceActivity) getActivity()).openScreen(R.xml.preferences_storage); + return true; + }); + + findPreference(PREF_ABOUT).setOnPreferenceClickListener( + preference -> { + startActivity(new Intent(getActivity(), AboutActivity.class)); + return true; + } + ); + findPreference(STATISTICS).setOnPreferenceClickListener( + preference -> { + startActivity(new Intent(getActivity(), StatisticsActivity.class)); + return true; + } + ); + findPreference(PREF_KNOWN_ISSUES).setOnPreferenceClickListener(preference -> { + openInBrowser("https://github.com/AntennaPod/AntennaPod/labels/bug"); + return true; + }); + findPreference(PREF_FAQ).setOnPreferenceClickListener(preference -> { + openInBrowser("http://antennapod.org/faq.html"); + return true; + }); + findPreference(PREF_SEND_CRASH_REPORT).setOnPreferenceClickListener(preference -> { + Context context = getActivity().getApplicationContext(); + Intent emailIntent = new Intent(Intent.ACTION_SEND); + emailIntent.setType("text/plain"); + emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{"Martin.Fietz@gmail.com"}); + emailIntent.putExtra(Intent.EXTRA_SUBJECT, "AntennaPod Crash Report"); + emailIntent.putExtra(Intent.EXTRA_TEXT, "Please describe what you were doing when the app crashed"); + // the attachment + Uri fileUri = FileProvider.getUriForFile(context, context.getString(R.string.provider_authority), + CrashReportWriter.getFile()); + emailIntent.putExtra(Intent.EXTRA_STREAM, fileUri); + emailIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + String intentTitle = getActivity().getString(R.string.send_email); + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { + List resInfoList = context.getPackageManager().queryIntentActivities(emailIntent, PackageManager.MATCH_DEFAULT_ONLY); + for (ResolveInfo resolveInfo : resInfoList) { + String packageName = resolveInfo.activityInfo.packageName; + context.grantUriPermission(packageName, fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION); + } + } + getActivity().startActivity(Intent.createChooser(emailIntent, intentTitle)); + return true; + }); + } + + private void openInBrowser(String url) { + try { + Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + startActivity(myIntent); + } catch (ActivityNotFoundException e) { + Toast.makeText(getActivity(), R.string.pref_no_browser_found, Toast.LENGTH_LONG).show(); + Log.e(TAG, Log.getStackTraceString(e)); + } + } + + private void setupSearch() { + SearchPreference searchPreference = (SearchPreference) findPreference("searchPreference"); + SearchConfiguration config = searchPreference.getSearchConfiguration(); + config.setActivity((AppCompatActivity) getActivity()); + config.setFragmentContainerViewId(R.id.content); + config.setBreadcrumbsEnabled(true); + + config.index(R.xml.preferences_user_interface) + .addBreadcrumb(PreferenceActivity.getTitleOfPage(R.xml.preferences_user_interface)); + config.index(R.xml.preferences_playback) + .addBreadcrumb(PreferenceActivity.getTitleOfPage(R.xml.preferences_playback)); + config.index(R.xml.preferences_network) + .addBreadcrumb(PreferenceActivity.getTitleOfPage(R.xml.preferences_network)); + config.index(R.xml.preferences_storage) + .addBreadcrumb(PreferenceActivity.getTitleOfPage(R.xml.preferences_storage)); + config.index(R.xml.preferences_autodownload) + .addBreadcrumb(PreferenceActivity.getTitleOfPage(R.xml.preferences_network)) + .addBreadcrumb(R.string.automation) + .addBreadcrumb(PreferenceActivity.getTitleOfPage(R.xml.preferences_autodownload)); + config.index(R.xml.preferences_gpodder) + .addBreadcrumb(PreferenceActivity.getTitleOfPage(R.xml.preferences_integrations)) + .addBreadcrumb(PreferenceActivity.getTitleOfPage(R.xml.preferences_gpodder)); + config.index(R.xml.preferences_flattr) + .addBreadcrumb(PreferenceActivity.getTitleOfPage(R.xml.preferences_integrations)) + .addBreadcrumb(PreferenceActivity.getTitleOfPage(R.xml.preferences_flattr)); + } +} 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 new file mode 100644 index 000000000..ac2436e25 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/NetworkPreferencesFragment.java @@ -0,0 +1,175 @@ +package de.danoeh.antennapod.fragment.preferences; + +import android.app.TimePickerDialog; +import android.content.Context; +import android.content.res.Resources; +import android.os.Bundle; +import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceFragmentCompat; +import android.text.format.DateFormat; +import com.afollestad.materialdialogs.MaterialDialog; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.activity.PreferenceActivity; +import de.danoeh.antennapod.core.preferences.UserPreferences; +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 { + private static final String PREF_SCREEN_AUTODL = "prefAutoDownloadSettings"; + private static final String PREF_PROXY = "prefProxy"; + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + addPreferencesFromResource(R.xml.preferences_network); + setupNetworkScreen(); + } + + @Override + public void onResume() { + super.onResume(); + setUpdateIntervalText(); + setParallelDownloadsText(UserPreferences.getParallelDownloads()); + } + + private void setupNetworkScreen() { + findPreference(PREF_SCREEN_AUTODL).setOnPreferenceClickListener(preference -> { + ((PreferenceActivity) getActivity()).openScreen(R.xml.preferences_autodownload); + return true; + }); + findPreference(UserPreferences.PREF_UPDATE_INTERVAL) + .setOnPreferenceClickListener(preference -> { + showUpdateIntervalTimePreferencesDialog(); + return true; + }); + findPreference(UserPreferences.PREF_PARALLEL_DOWNLOADS) + .setOnPreferenceChangeListener( + (preference, o) -> { + if (o instanceof Integer) { + setParallelDownloadsText((Integer) o); + } + return true; + } + ); + // validate and set correct value: number of downloads between 1 and 50 (inclusive) + findPreference(PREF_PROXY).setOnPreferenceClickListener(preference -> { + ProxyDialog dialog = new ProxyDialog(getActivity()); + dialog.createDialog().show(); + return true; + }); + } + + private void setUpdateIntervalText() { + Context context = getActivity().getApplicationContext(); + String val; + long interval = UserPreferences.getUpdateInterval(); + if(interval > 0) { + int hours = (int) TimeUnit.MILLISECONDS.toHours(interval); + String hoursStr = context.getResources().getQuantityString(R.plurals.time_hours_quantified, hours, hours); + val = String.format(context.getString(R.string.pref_autoUpdateIntervallOrTime_every), hoursStr); + } else { + int[] timeOfDay = UserPreferences.getUpdateTimeOfDay(); + if(timeOfDay.length == 2) { + Calendar cal = new GregorianCalendar(); + 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), + 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??? + } + } + String summary = context.getString(R.string.pref_autoUpdateIntervallOrTime_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 = Integer.toString(downloads) + + res.getString(R.string.parallel_downloads_suffix); + findPreference(UserPreferences.PREF_PARALLEL_DOWNLOADS).setSummary(s); + } + + private void showUpdateIntervalTimePreferencesDialog() { + final Context context = getActivity(); + + MaterialDialog.Builder builder = new MaterialDialog.Builder(context); + builder.title(R.string.pref_autoUpdateIntervallOrTime_title); + builder.content(R.string.pref_autoUpdateIntervallOrTime_message); + builder.positiveText(R.string.pref_autoUpdateIntervallOrTime_Interval); + builder.negativeText(R.string.pref_autoUpdateIntervallOrTime_TimeOfDay); + builder.neutralText(R.string.pref_autoUpdateIntervallOrTime_Disable); + builder.onPositive((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.onNegative((dialog, which) -> { + int hourOfDay = 7, 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.onNeutral((dialog, which) -> { + UserPreferences.disableAutoUpdate(); + 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/java/de/danoeh/antennapod/fragment/preferences/PlaybackPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/PlaybackPreferencesFragment.java new file mode 100644 index 000000000..e1714d4bd --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/PlaybackPreferencesFragment.java @@ -0,0 +1,92 @@ +package de.danoeh.antennapod.fragment.preferences; + +import android.app.Activity; +import android.content.res.Resources; +import android.os.Build; +import android.os.Bundle; +import android.support.v7.preference.ListPreference; +import android.support.v7.preference.PreferenceFragmentCompat; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.activity.MediaplayerActivity; +import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.util.gui.PictureInPictureUtil; +import de.danoeh.antennapod.dialog.VariableSpeedDialog; +import de.danoeh.antennapod.preferences.PreferenceControllerFlavorHelper; + +public class PlaybackPreferencesFragment extends PreferenceFragmentCompat { + private static final String PREF_PLAYBACK_SPEED_LAUNCHER = "prefPlaybackSpeedLauncher"; + private static final String PREF_PLAYBACK_REWIND_DELTA_LAUNCHER = "prefPlaybackRewindDeltaLauncher"; + private static final String PREF_PLAYBACK_FAST_FORWARD_DELTA_LAUNCHER = "prefPlaybackFastForwardDeltaLauncher"; + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + addPreferencesFromResource(R.xml.preferences_playback); + + setupPlaybackScreen(); + PreferenceControllerFlavorHelper.setupFlavoredUI(this); + buildSmartMarkAsPlayedPreference(); + } + + @Override + public void onResume() { + super.onResume(); + checkSonicItemVisibility(); + } + + private void setupPlaybackScreen() { + final Activity activity = getActivity(); + + findPreference(PREF_PLAYBACK_SPEED_LAUNCHER) + .setOnPreferenceClickListener(preference -> { + VariableSpeedDialog.showDialog(activity); + return true; + }); + findPreference(PREF_PLAYBACK_REWIND_DELTA_LAUNCHER) + .setOnPreferenceClickListener(preference -> { + MediaplayerActivity.showSkipPreference(activity, MediaplayerActivity.SkipDirection.SKIP_REWIND); + return true; + }); + findPreference(PREF_PLAYBACK_FAST_FORWARD_DELTA_LAUNCHER) + .setOnPreferenceClickListener(preference -> { + MediaplayerActivity.showSkipPreference(activity, MediaplayerActivity.SkipDirection.SKIP_FORWARD); + return true; + }); + if (!PictureInPictureUtil.supportsPictureInPicture(activity)) { + ListPreference behaviour = (ListPreference) findPreference(UserPreferences.PREF_VIDEO_BEHAVIOR); + behaviour.setEntries(R.array.video_background_behavior_options_without_pip); + behaviour.setEntryValues(R.array.video_background_behavior_values_without_pip); + } + } + + private void buildSmartMarkAsPlayedPreference() { + final Resources res = getActivity().getResources(); + + ListPreference pref = (ListPreference) findPreference(UserPreferences.PREF_SMART_MARK_AS_PLAYED_SECS); + String[] values = res.getStringArray(R.array.smart_mark_as_played_values); + String[] entries = new String[values.length]; + for (int x = 0; x < values.length; x++) { + if(x == 0) { + entries[x] = res.getString(R.string.pref_smart_mark_as_played_disabled); + } else { + Integer v = Integer.parseInt(values[x]); + if(v < 60) { + entries[x] = res.getQuantityString(R.plurals.time_seconds_quantified, v, v); + } else { + v /= 60; + entries[x] = res.getQuantityString(R.plurals.time_minutes_quantified, v, v); + } + } + } + pref.setEntries(entries); + } + + + + private void checkSonicItemVisibility() { + if (Build.VERSION.SDK_INT < 16) { + ListPreference p = (ListPreference) findPreference(UserPreferences.PREF_MEDIA_PLAYER); + p.setEntries(R.array.media_player_options_no_sonic); + p.setEntryValues(R.array.media_player_values_no_sonic); + } + } +} diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/StoragePreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/StoragePreferencesFragment.java new file mode 100644 index 000000000..b4226b546 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/StoragePreferencesFragment.java @@ -0,0 +1,244 @@ +package de.danoeh.antennapod.fragment.preferences; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.app.Activity; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.support.v4.app.ActivityCompat; +import android.support.v4.content.FileProvider; +import android.support.v7.app.AlertDialog; +import android.support.v7.preference.PreferenceFragmentCompat; +import android.util.Log; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.activity.DirectoryChooserActivity; +import de.danoeh.antennapod.activity.ImportExportActivity; +import de.danoeh.antennapod.activity.OpmlImportFromPathActivity; +import de.danoeh.antennapod.asynctask.ExportWorker; +import de.danoeh.antennapod.core.export.ExportWriter; +import de.danoeh.antennapod.core.export.html.HtmlWriter; +import de.danoeh.antennapod.core.export.opml.OpmlWriter; +import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.dialog.ChooseDataFolderDialog; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; + +import java.io.File; +import java.util.List; + +public class StoragePreferencesFragment extends PreferenceFragmentCompat { + private static final String TAG = "StoragePrefFragment"; + private static final String PREF_OPML_EXPORT = "prefOpmlExport"; + private static final String PREF_OPML_IMPORT = "prefOpmlImport"; + private static final String PREF_HTML_EXPORT = "prefHtmlExport"; + private static final String IMPORT_EXPORT = "importExport"; + private static final String PREF_CHOOSE_DATA_DIR = "prefChooseDataDir"; + private static final String[] EXTERNAL_STORAGE_PERMISSIONS = { + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE }; + private static final int PERMISSION_REQUEST_EXTERNAL_STORAGE = 41; + private Disposable disposable; + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + addPreferencesFromResource(R.xml.preferences_storage); + setupStorageScreen(); + } + + @Override + public void onResume() { + super.onResume(); + setDataFolderText(); + } + + private void setupStorageScreen() { + final Activity activity = getActivity(); + + findPreference(IMPORT_EXPORT).setOnPreferenceClickListener( + preference -> { + activity.startActivity(new Intent(activity, ImportExportActivity.class)); + return true; + } + ); + findPreference(PREF_OPML_EXPORT).setOnPreferenceClickListener( + preference -> export(new OpmlWriter())); + findPreference(PREF_HTML_EXPORT).setOnPreferenceClickListener( + preference -> export(new HtmlWriter())); + findPreference(PREF_OPML_IMPORT).setOnPreferenceClickListener( + preference -> { + activity.startActivity(new Intent(activity, OpmlImportFromPathActivity.class)); + return true; + }); + findPreference(PREF_CHOOSE_DATA_DIR).setOnPreferenceClickListener( + preference -> { + if (Build.VERSION_CODES.KITKAT <= Build.VERSION.SDK_INT && + Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) { + showChooseDataFolderDialog(); + } else { + int readPermission = ActivityCompat.checkSelfPermission( + activity, Manifest.permission.READ_EXTERNAL_STORAGE); + int writePermission = ActivityCompat.checkSelfPermission( + activity, Manifest.permission.WRITE_EXTERNAL_STORAGE); + if (readPermission == PackageManager.PERMISSION_GRANTED && + writePermission == PackageManager.PERMISSION_GRANTED) { + openDirectoryChooser(); + } else { + requestPermission(); + } + } + return true; + } + ); + findPreference(PREF_CHOOSE_DATA_DIR) + .setOnPreferenceClickListener( + preference -> { + if (Build.VERSION.SDK_INT >= 19) { + showChooseDataFolderDialog(); + } else { + Intent intent = new Intent(activity, DirectoryChooserActivity.class); + activity.startActivityForResult(intent, + DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED); + } + return true; + } + ); + findPreference(UserPreferences.PREF_IMAGE_CACHE_SIZE).setOnPreferenceChangeListener( + (preference, o) -> { + if (o instanceof String) { + int newValue = Integer.parseInt((String) o) * 1024 * 1024; + if (newValue != UserPreferences.getImageCacheSize()) { + AlertDialog.Builder dialog = new AlertDialog.Builder(getActivity()); + dialog.setTitle(android.R.string.dialog_alert_title); + dialog.setMessage(R.string.pref_restart_required); + dialog.setPositiveButton(android.R.string.ok, null); + dialog.show(); + } + return true; + } + return false; + } + ); + } + + private boolean export(ExportWriter exportWriter) { + Context context = getActivity(); + final ProgressDialog progressDialog = new ProgressDialog(context); + progressDialog.setMessage(context.getString(R.string.exporting_label)); + progressDialog.setIndeterminate(true); + progressDialog.show(); + final AlertDialog.Builder alert = new AlertDialog.Builder(context) + .setNeutralButton(android.R.string.ok, (dialog, which) -> dialog.dismiss()); + Observable observable = new ExportWorker(exportWriter).exportObservable(); + disposable = observable.subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(output -> { + alert.setTitle(R.string.export_success_title); + String message = context.getString(R.string.export_success_sum, output.toString()); + alert.setMessage(message); + alert.setPositiveButton(R.string.send_label, (dialog, which) -> { + Uri fileUri = FileProvider.getUriForFile(context.getApplicationContext(), + context.getString(R.string.provider_authority), output); + Intent sendIntent = new Intent(Intent.ACTION_SEND); + sendIntent.putExtra(Intent.EXTRA_SUBJECT, + context.getResources().getText(R.string.opml_export_label)); + sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri); + sendIntent.setType("text/plain"); + sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { + List resInfoList = context.getPackageManager().queryIntentActivities(sendIntent, PackageManager.MATCH_DEFAULT_ONLY); + for (ResolveInfo resolveInfo : resInfoList) { + String packageName = resolveInfo.activityInfo.packageName; + context.grantUriPermission(packageName, fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION); + } + } + context.startActivity(Intent.createChooser(sendIntent, + context.getResources().getText(R.string.send_label))); + }); + alert.create().show(); + }, error -> { + alert.setTitle(R.string.export_error_label); + alert.setMessage(error.getMessage()); + alert.show(); + }, progressDialog::dismiss); + return true; + } + + public void unsubscribeExportSubscription() { + if (disposable != null) { + disposable.dispose(); + } + } + + @SuppressLint("NewApi") + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (resultCode == Activity.RESULT_OK && + requestCode == DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED) { + String dir = data.getStringExtra(DirectoryChooserActivity.RESULT_SELECTED_DIR); + + File path; + if(dir != null) { + path = new File(dir); + } else { + path = getActivity().getExternalFilesDir(null); + } + String message = null; + final Context context= getActivity().getApplicationContext(); + if(!path.exists()) { + message = String.format(context.getString(R.string.folder_does_not_exist_error), dir); + } else if(!path.canRead()) { + message = String.format(context.getString(R.string.folder_not_readable_error), dir); + } else if(!path.canWrite()) { + message = String.format(context.getString(R.string.folder_not_writable_error), dir); + } + + if(message == null) { + Log.d(TAG, "Setting data folder: " + dir); + UserPreferences.setDataFolder(dir); + setDataFolderText(); + } else { + AlertDialog.Builder ab = new AlertDialog.Builder(getActivity()); + ab.setMessage(message); + ab.setPositiveButton(android.R.string.ok, null); + ab.show(); + } + } + } + + private void setDataFolderText() { + File f = UserPreferences.getDataFolder(null); + if (f != null) { + findPreference(PREF_CHOOSE_DATA_DIR) + .setSummary(f.getAbsolutePath()); + } + } + + private void requestPermission() { + ActivityCompat.requestPermissions(getActivity(), EXTERNAL_STORAGE_PERMISSIONS, + PERMISSION_REQUEST_EXTERNAL_STORAGE); + } + + private void openDirectoryChooser() { + Activity activity = getActivity(); + Intent intent = new Intent(activity, DirectoryChooserActivity.class); + activity.startActivityForResult(intent, DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED); + } + + private void showChooseDataFolderDialog() { + ChooseDataFolderDialog.showDialog( + getActivity(), new ChooseDataFolderDialog.RunnableWithString() { + @Override + public void run(final String folder) { + UserPreferences.setDataFolder(folder); + setDataFolderText(); + } + }); + } +} 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 new file mode 100644 index 000000000..e1d44f7d3 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java @@ -0,0 +1,165 @@ +package de.danoeh.antennapod.fragment.preferences; + +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.support.design.widget.Snackbar; +import android.support.v7.app.AlertDialog; +import android.support.v7.preference.PreferenceFragmentCompat; +import android.widget.ListView; +import android.widget.Toast; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.activity.MainActivity; +import de.danoeh.antennapod.core.preferences.UserPreferences; +import org.apache.commons.lang3.ArrayUtils; + +import java.util.List; + +public class UserInterfacePreferencesFragment extends PreferenceFragmentCompat { + private static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify"; + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + addPreferencesFromResource(R.xml.preferences_user_interface); + setupInterfaceScreen(); + } + + private void setupInterfaceScreen() { + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { + // disable expanded notification option on unsupported android versions + findPreference(PREF_EXPANDED_NOTIFICATION).setEnabled(false); + findPreference(PREF_EXPANDED_NOTIFICATION).setOnPreferenceClickListener( + preference -> { + Toast toast = Toast.makeText(getActivity(), + R.string.pref_expand_notify_unsupport_toast, Toast.LENGTH_SHORT); + toast.show(); + return true; + } + ); + } + findPreference(UserPreferences.PREF_THEME) + .setOnPreferenceChangeListener( + (preference, newValue) -> { + Intent i = new Intent(getActivity(), MainActivity.class); + i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK + | Intent.FLAG_ACTIVITY_NEW_TASK); + getActivity().finish(); + startActivity(i); + return true; + } + ); + findPreference(UserPreferences.PREF_HIDDEN_DRAWER_ITEMS) + .setOnPreferenceClickListener(preference -> { + showDrawerPreferencesDialog(); + return true; + }); + + findPreference(UserPreferences.PREF_COMPACT_NOTIFICATION_BUTTONS) + .setOnPreferenceClickListener(preference -> { + showNotificationButtonsDialog(); + return true; + }); + + findPreference(UserPreferences.PREF_BACK_BUTTON_BEHAVIOR) + .setOnPreferenceChangeListener((preference, newValue) -> { + if (newValue.equals("page")) { + final Context context = 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) { + findPreference(UserPreferences.PREF_EXPANDED_NOTIFICATION).setVisible(false); + } + } + + private void showDrawerPreferencesDialog() { + final Context context = getActivity(); + final List hiddenDrawerItems = UserPreferences.getHiddenDrawerItems(); + final String[] navTitles = context.getResources().getStringArray(R.array.nav_drawer_titles); + final String[] NAV_DRAWER_TAGS = MainActivity.NAV_DRAWER_TAGS; + boolean[] checked = new boolean[MainActivity.NAV_DRAWER_TAGS.length]; + for(int i=0; i < NAV_DRAWER_TAGS.length; i++) { + String tag = NAV_DRAWER_TAGS[i]; + if(!hiddenDrawerItems.contains(tag)) { + checked[i] = true; + } + } + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(R.string.drawer_preferences); + builder.setMultiChoiceItems(navTitles, checked, (dialog, which, isChecked) -> { + if (isChecked) { + hiddenDrawerItems.remove(NAV_DRAWER_TAGS[which]); + } else { + hiddenDrawerItems.add(NAV_DRAWER_TAGS[which]); + } + }); + builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> + UserPreferences.setHiddenDrawerItems(hiddenDrawerItems)); + builder.setNegativeButton(R.string.cancel_label, null); + builder.create().show(); + } + + private void showNotificationButtonsDialog() { + final Context context = getActivity(); + final List preferredButtons = UserPreferences.getCompactNotificationButtons(); + final String[] allButtonNames = context.getResources().getStringArray( + R.array.compact_notification_buttons_options); + boolean[] checked = new boolean[allButtonNames.length]; // booleans default to false in java + + for(int i=0; i < checked.length; i++) { + if(preferredButtons.contains(i)) { + checked[i] = true; + } + } + + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(String.format(context.getResources().getString( + R.string.pref_compact_notification_buttons_dialog_title), 2)); + builder.setMultiChoiceItems(allButtonNames, checked, (dialog, which, isChecked) -> { + checked[which] = isChecked; + + if (isChecked) { + if (preferredButtons.size() < 2) { + preferredButtons.add(which); + } else { + // Only allow a maximum of two selections. This is because the notification + // on the lock screen can only display 3 buttons, and the play/pause button + // is always included. + checked[which] = false; + ListView selectionView = ((AlertDialog) dialog).getListView(); + selectionView.setItemChecked(which, false); + Snackbar.make( + selectionView, + String.format(context.getResources().getString( + R.string.pref_compact_notification_buttons_dialog_error), 2), + Snackbar.LENGTH_SHORT).show(); + } + } else { + preferredButtons.remove((Integer) which); + } + }); + builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> + UserPreferences.setCompactNotificationButtons(preferredButtons)); + builder.setNegativeButton(R.string.cancel_label, null); + builder.create().show(); + } +} diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java deleted file mode 100644 index fdc719ad2..000000000 --- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java +++ /dev/null @@ -1,1190 +0,0 @@ -package de.danoeh.antennapod.preferences; - -import android.Manifest; -import android.annotation.SuppressLint; -import android.app.Activity; -import android.app.ProgressDialog; -import android.app.TimePickerDialog; -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.res.Resources; -import android.net.Uri; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiManager; -import android.os.Build; -import android.os.Bundle; -import android.support.design.widget.Snackbar; -import android.support.v4.app.ActivityCompat; -import android.support.v4.content.FileProvider; -import android.support.v7.app.AlertDialog; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.preference.CheckBoxPreference; -import android.support.v7.preference.ListPreference; -import android.support.v7.preference.Preference; -import android.support.v7.preference.PreferenceFragmentCompat; -import android.support.v7.preference.PreferenceManager; -import android.support.v7.preference.PreferenceScreen; -import android.text.Html; -import android.text.format.DateFormat; -import android.text.format.DateUtils; -import android.util.Log; -import android.widget.ListView; -import android.widget.Toast; - -import com.afollestad.materialdialogs.MaterialDialog; -import com.bytehamster.lib.preferencesearch.SearchConfiguration; -import com.bytehamster.lib.preferencesearch.SearchPreference; - -import org.apache.commons.lang3.ArrayUtils; - -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collections; -import java.util.GregorianCalendar; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import de.danoeh.antennapod.CrashReportWriter; -import de.danoeh.antennapod.R; -import de.danoeh.antennapod.activity.AboutActivity; -import de.danoeh.antennapod.activity.DirectoryChooserActivity; -import de.danoeh.antennapod.activity.ImportExportActivity; -import de.danoeh.antennapod.activity.MainActivity; -import de.danoeh.antennapod.activity.MediaplayerActivity; -import de.danoeh.antennapod.activity.OpmlImportFromPathActivity; -import de.danoeh.antennapod.activity.PreferenceActivity; -import de.danoeh.antennapod.activity.StatisticsActivity; -import de.danoeh.antennapod.asynctask.ExportWorker; -import de.danoeh.antennapod.core.export.ExportWriter; -import de.danoeh.antennapod.core.export.html.HtmlWriter; -import de.danoeh.antennapod.core.export.opml.OpmlWriter; -import de.danoeh.antennapod.core.preferences.GpodnetPreferences; -import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.core.service.GpodnetSyncService; -import de.danoeh.antennapod.core.util.flattr.FlattrUtils; -import de.danoeh.antennapod.core.util.gui.PictureInPictureUtil; -import de.danoeh.antennapod.dialog.AuthenticationDialog; -import de.danoeh.antennapod.dialog.AutoFlattrPreferenceDialog; -import de.danoeh.antennapod.dialog.ChooseDataFolderDialog; -import de.danoeh.antennapod.dialog.GpodnetSetHostnameDialog; -import de.danoeh.antennapod.dialog.ProxyDialog; -import de.danoeh.antennapod.dialog.VariableSpeedDialog; -import io.reactivex.Observable; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.Disposable; -import io.reactivex.schedulers.Schedulers; - -import static de.danoeh.antennapod.activity.PreferenceActivity.PARAM_RESOURCE; - -/** - * Sets up a preference UI that lets the user change user preferences. - */ - -public class PreferenceController implements SharedPreferences.OnSharedPreferenceChangeListener { - - private static final String TAG = "PreferenceController"; - - private static final String PREF_SCREEN_USER_INTERFACE = "prefScreenInterface"; - private static final String PREF_SCREEN_PLAYBACK = "prefScreenPlayback"; - private static final String PREF_SCREEN_NETWORK = "prefScreenNetwork"; - private static final String PREF_SCREEN_INTEGRATIONS = "prefScreenIntegrations"; - private static final String PREF_SCREEN_STORAGE = "prefScreenStorage"; - private static final String PREF_SCREEN_AUTODL = "prefAutoDownloadSettings"; - private static final String PREF_SCREEN_FLATTR = "prefFlattrSettings"; - private static final String PREF_SCREEN_GPODDER = "prefGpodderSettings"; - - private static final String PREF_FLATTR_AUTH = "pref_flattr_authenticate"; - private static final String PREF_FLATTR_REVOKE = "prefRevokeAccess"; - private static final String PREF_AUTO_FLATTR_PREFS = "prefAutoFlattrPrefs"; - private static final String PREF_OPML_EXPORT = "prefOpmlExport"; - private static final String PREF_OPML_IMPORT = "prefOpmlImport"; - private static final String PREF_HTML_EXPORT = "prefHtmlExport"; - private static final String STATISTICS = "statistics"; - private static final String IMPORT_EXPORT = "importExport"; - private static final String PREF_ABOUT = "prefAbout"; - private static final String PREF_CHOOSE_DATA_DIR = "prefChooseDataDir"; - private static final String PREF_PLAYBACK_SPEED_LAUNCHER = "prefPlaybackSpeedLauncher"; - private static final String PREF_PLAYBACK_REWIND_DELTA_LAUNCHER = "prefPlaybackRewindDeltaLauncher"; - private static final String PREF_PLAYBACK_FAST_FORWARD_DELTA_LAUNCHER = "prefPlaybackFastForwardDeltaLauncher"; - private static final String PREF_GPODNET_LOGIN = "pref_gpodnet_authenticate"; - private static final String PREF_GPODNET_SETLOGIN_INFORMATION = "pref_gpodnet_setlogin_information"; - private static final String PREF_GPODNET_SYNC = "pref_gpodnet_sync"; - private static final String PREF_GPODNET_FORCE_FULL_SYNC = "pref_gpodnet_force_full_sync"; - private static final String PREF_GPODNET_LOGOUT = "pref_gpodnet_logout"; - private static final String PREF_GPODNET_HOSTNAME = "pref_gpodnet_hostname"; - private static final String PREF_GPODNET_NOTIFICATIONS = "pref_gpodnet_notifications"; - private static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify"; - private static final String PREF_PROXY = "prefProxy"; - private static final String PREF_KNOWN_ISSUES = "prefKnownIssues"; - private static final String PREF_FAQ = "prefFaq"; - private static final String PREF_SEND_CRASH_REPORT = "prefSendCrashReport"; - private static final String[] EXTERNAL_STORAGE_PERMISSIONS = { - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE }; - private static final int PERMISSION_REQUEST_EXTERNAL_STORAGE = 41; - private final PreferenceUI ui; - private final SharedPreferences.OnSharedPreferenceChangeListener gpoddernetListener = - (sharedPreferences, key) -> { - if (GpodnetPreferences.PREF_LAST_SYNC_ATTEMPT_TIMESTAMP.equals(key)) { - updateLastGpodnetSyncReport(GpodnetPreferences.getLastSyncAttemptResult(), - GpodnetPreferences.getLastSyncAttemptTimestamp()); - } - }; - private CheckBoxPreference[] selectedNetworks; - private Disposable disposable; - - public PreferenceController(PreferenceUI ui) { - this.ui = ui; - PreferenceManager.getDefaultSharedPreferences(ui.getActivity().getApplicationContext()) - .registerOnSharedPreferenceChangeListener(this); - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - - } - - - - public void onCreate(int screen) { - switch (screen) { - case R.xml.preferences: - setupMainScreen(); - break; - case R.xml.preferences_network: - setupNetworkScreen(); - break; - case R.xml.preferences_autodownload: - setupAutoDownloadScreen(); - buildAutodownloadSelectedNetworksPreference(); - setSelectedNetworksEnabled(UserPreferences.isEnableAutodownloadWifiFilter()); - buildEpisodeCleanupPreference(); - break; - case R.xml.preferences_playback: - setupPlaybackScreen(); - PreferenceControllerFlavorHelper.setupFlavoredUI(ui); - buildSmartMarkAsPlayedPreference(); - break; - case R.xml.preferences_integrations: - setupIntegrationsScreen(); - break; - case R.xml.preferences_flattr: - setupFlattrScreen(); - break; - case R.xml.preferences_gpodder: - setupGpodderScreen(); - break; - case R.xml.preferences_storage: - setupStorageScreen(); - break; - case R.xml.preferences_user_interface: - setupInterfaceScreen(); - break; - } - } - - private void setupInterfaceScreen() { - final Activity activity = ui.getActivity(); - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { - // disable expanded notification option on unsupported android versions - ui.findPreference(PreferenceController.PREF_EXPANDED_NOTIFICATION).setEnabled(false); - ui.findPreference(PreferenceController.PREF_EXPANDED_NOTIFICATION).setOnPreferenceClickListener( - preference -> { - Toast toast = Toast.makeText(activity, - R.string.pref_expand_notify_unsupport_toast, Toast.LENGTH_SHORT); - toast.show(); - return true; - } - ); - } - ui.findPreference(UserPreferences.PREF_THEME) - .setOnPreferenceChangeListener( - (preference, newValue) -> { - Intent i = new Intent(activity, MainActivity.class); - i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK - | Intent.FLAG_ACTIVITY_NEW_TASK); - activity.finish(); - activity.startActivity(i); - return true; - } - ); - ui.findPreference(UserPreferences.PREF_HIDDEN_DRAWER_ITEMS) - .setOnPreferenceClickListener(preference -> { - showDrawerPreferencesDialog(); - return true; - }); - - ui.findPreference(UserPreferences.PREF_COMPACT_NOTIFICATION_BUTTONS) - .setOnPreferenceClickListener(preference -> { - showNotificationButtonsDialog(); - 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); - } - } - - private void setupStorageScreen() { - final Activity activity = ui.getActivity(); - - ui.findPreference(PreferenceController.IMPORT_EXPORT).setOnPreferenceClickListener( - preference -> { - activity.startActivity(new Intent(activity, ImportExportActivity.class)); - return true; - } - ); - ui.findPreference(PreferenceController.PREF_OPML_EXPORT).setOnPreferenceClickListener( - preference -> export(new OpmlWriter())); - ui.findPreference(PreferenceController.PREF_HTML_EXPORT).setOnPreferenceClickListener( - preference -> export(new HtmlWriter())); - ui.findPreference(PreferenceController.PREF_OPML_IMPORT).setOnPreferenceClickListener( - preference -> { - activity.startActivity(new Intent(activity, OpmlImportFromPathActivity.class)); - return true; - }); - ui.findPreference(PreferenceController.PREF_CHOOSE_DATA_DIR).setOnPreferenceClickListener( - preference -> { - if (Build.VERSION_CODES.KITKAT <= Build.VERSION.SDK_INT && - Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) { - showChooseDataFolderDialog(); - } else { - int readPermission = ActivityCompat.checkSelfPermission( - activity, Manifest.permission.READ_EXTERNAL_STORAGE); - int writePermission = ActivityCompat.checkSelfPermission( - activity, Manifest.permission.WRITE_EXTERNAL_STORAGE); - if (readPermission == PackageManager.PERMISSION_GRANTED && - writePermission == PackageManager.PERMISSION_GRANTED) { - openDirectoryChooser(); - } else { - requestPermission(); - } - } - return true; - } - ); - ui.findPreference(PreferenceController.PREF_CHOOSE_DATA_DIR) - .setOnPreferenceClickListener( - preference -> { - if (Build.VERSION.SDK_INT >= 19) { - showChooseDataFolderDialog(); - } else { - Intent intent = new Intent(activity, DirectoryChooserActivity.class); - activity.startActivityForResult(intent, - DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED); - } - return true; - } - ); - ui.findPreference(UserPreferences.PREF_IMAGE_CACHE_SIZE).setOnPreferenceChangeListener( - (preference, o) -> { - if (o instanceof String) { - int newValue = Integer.parseInt((String) o) * 1024 * 1024; - if (newValue != UserPreferences.getImageCacheSize()) { - AlertDialog.Builder dialog = new AlertDialog.Builder(ui.getActivity()); - dialog.setTitle(android.R.string.dialog_alert_title); - dialog.setMessage(R.string.pref_restart_required); - dialog.setPositiveButton(android.R.string.ok, null); - dialog.show(); - } - return true; - } - return false; - } - ); - } - - private void setupIntegrationsScreen() { - final AppCompatActivity activity = ui.getActivity(); - - ui.findPreference(PREF_SCREEN_FLATTR).setOnPreferenceClickListener(preference -> { - openScreen(R.xml.preferences_flattr, activity); - return true; - }); - ui.findPreference(PREF_SCREEN_GPODDER).setOnPreferenceClickListener(preference -> { - openScreen(R.xml.preferences_gpodder, activity); - return true; - }); - } - - private void setupFlattrScreen() { - final AppCompatActivity activity = ui.getActivity(); - - ui.findPreference(PreferenceController.PREF_FLATTR_REVOKE).setOnPreferenceClickListener( - preference -> { - FlattrUtils.revokeAccessToken(activity); - checkFlattrItemVisibility(); - return true; - } - ); - - ui.findPreference(PreferenceController.PREF_AUTO_FLATTR_PREFS) - .setOnPreferenceClickListener(preference -> { - AutoFlattrPreferenceDialog.newAutoFlattrPreferenceDialog(activity, - new AutoFlattrPreferenceDialog.AutoFlattrPreferenceDialogInterface() { - @Override - public void onCancelled() { - - } - - @Override - public void onConfirmed(boolean autoFlattrEnabled, float autoFlattrValue) { - UserPreferences.setAutoFlattrSettings(autoFlattrEnabled, autoFlattrValue); - checkFlattrItemVisibility(); - } - }); - return true; - }); - } - - private void setupGpodderScreen() { - final AppCompatActivity activity = ui.getActivity(); - - ui.findPreference(PreferenceController.PREF_GPODNET_SETLOGIN_INFORMATION) - .setOnPreferenceClickListener(preference -> { - AuthenticationDialog dialog = new AuthenticationDialog(activity, - R.string.pref_gpodnet_setlogin_information_title, false, false, GpodnetPreferences.getUsername(), - null) { - - @Override - protected void onConfirmed(String username, String password, boolean saveUsernamePassword) { - GpodnetPreferences.setPassword(password); - } - }; - dialog.show(); - return true; - }); - ui.findPreference(PreferenceController.PREF_GPODNET_SYNC). - setOnPreferenceClickListener(preference -> { - GpodnetSyncService.sendSyncIntent(ui.getActivity().getApplicationContext()); - Toast toast = Toast.makeText(ui.getActivity(), R.string.pref_gpodnet_sync_started, - Toast.LENGTH_SHORT); - toast.show(); - return true; - }); - ui.findPreference(PreferenceController.PREF_GPODNET_FORCE_FULL_SYNC). - setOnPreferenceClickListener(preference -> { - GpodnetPreferences.setLastSubscriptionSyncTimestamp(0L); - GpodnetPreferences.setLastEpisodeActionsSyncTimestamp(0L); - GpodnetPreferences.setLastSyncAttempt(false, 0); - updateLastGpodnetSyncReport(false, 0); - GpodnetSyncService.sendSyncIntent(ui.getActivity().getApplicationContext()); - Toast toast = Toast.makeText(ui.getActivity(), R.string.pref_gpodnet_sync_started, - Toast.LENGTH_SHORT); - toast.show(); - return true; - }); - ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setOnPreferenceClickListener( - preference -> { - GpodnetPreferences.logout(); - Toast toast = Toast.makeText(activity, R.string.pref_gpodnet_logout_toast, Toast.LENGTH_SHORT); - toast.show(); - updateGpodnetPreferenceScreen(); - return true; - }); - ui.findPreference(PreferenceController.PREF_GPODNET_HOSTNAME).setOnPreferenceClickListener( - preference -> { - GpodnetSetHostnameDialog.createDialog(activity).setOnDismissListener(dialog -> updateGpodnetPreferenceScreen()); - return true; - }); - } - - private void setupPlaybackScreen() { - final Activity activity = ui.getActivity(); - - ui.findPreference(PreferenceController.PREF_PLAYBACK_SPEED_LAUNCHER) - .setOnPreferenceClickListener(preference -> { - VariableSpeedDialog.showDialog(activity); - return true; - }); - ui.findPreference(PreferenceController.PREF_PLAYBACK_REWIND_DELTA_LAUNCHER) - .setOnPreferenceClickListener(preference -> { - MediaplayerActivity.showSkipPreference(activity, MediaplayerActivity.SkipDirection.SKIP_REWIND); - return true; - }); - ui.findPreference(PreferenceController.PREF_PLAYBACK_FAST_FORWARD_DELTA_LAUNCHER) - .setOnPreferenceClickListener(preference -> { - MediaplayerActivity.showSkipPreference(activity, MediaplayerActivity.SkipDirection.SKIP_FORWARD); - return true; - }); - if (!PictureInPictureUtil.supportsPictureInPicture(activity)) { - ListPreference behaviour = (ListPreference) ui.findPreference(UserPreferences.PREF_VIDEO_BEHAVIOR); - behaviour.setEntries(R.array.video_background_behavior_options_without_pip); - behaviour.setEntryValues(R.array.video_background_behavior_values_without_pip); - } - } - - private void setupAutoDownloadScreen() { - ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL).setOnPreferenceChangeListener( - (preference, newValue) -> { - if (newValue instanceof Boolean) { - checkAutodownloadItemVisibility((Boolean) newValue); - } - return true; - }); - ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER) - .setOnPreferenceChangeListener( - (preference, newValue) -> { - if (newValue instanceof Boolean) { - setSelectedNetworksEnabled((Boolean) newValue); - return true; - } else { - return false; - } - } - ); - } - - private void setupNetworkScreen() { - final AppCompatActivity activity = ui.getActivity(); - ui.findPreference(PREF_SCREEN_AUTODL).setOnPreferenceClickListener(preference -> { - openScreen(R.xml.preferences_autodownload, activity); - return true; - }); - ui.findPreference(UserPreferences.PREF_UPDATE_INTERVAL) - .setOnPreferenceClickListener(preference -> { - showUpdateIntervalTimePreferencesDialog(); - return true; - }); - ui.findPreference(UserPreferences.PREF_PARALLEL_DOWNLOADS) - .setOnPreferenceChangeListener( - (preference, o) -> { - if (o instanceof Integer) { - setParallelDownloadsText((Integer) o); - } - return true; - } - ); - // validate and set correct value: number of downloads between 1 and 50 (inclusive) - ui.findPreference(PREF_PROXY).setOnPreferenceClickListener(preference -> { - ProxyDialog dialog = new ProxyDialog(ui.getActivity()); - dialog.createDialog().show(); - return true; - }); - } - - private void setupMainScreen() { - final AppCompatActivity activity = ui.getActivity(); - setupSearch(); - ui.findPreference(PREF_SCREEN_USER_INTERFACE).setOnPreferenceClickListener(preference -> { - openScreen(R.xml.preferences_user_interface, activity); - return true; - }); - ui.findPreference(PREF_SCREEN_PLAYBACK).setOnPreferenceClickListener(preference -> { - openScreen(R.xml.preferences_playback, activity); - return true; - }); - ui.findPreference(PREF_SCREEN_NETWORK).setOnPreferenceClickListener(preference -> { - openScreen(R.xml.preferences_network, activity); - return true; - }); - ui.findPreference(PREF_SCREEN_INTEGRATIONS).setOnPreferenceClickListener(preference -> { - openScreen(R.xml.preferences_integrations, activity); - return true; - }); - ui.findPreference(PREF_SCREEN_STORAGE).setOnPreferenceClickListener(preference -> { - openScreen(R.xml.preferences_storage, activity); - return true; - }); - - ui.findPreference(PreferenceController.PREF_ABOUT).setOnPreferenceClickListener( - preference -> { - activity.startActivity(new Intent(activity, AboutActivity.class)); - return true; - } - ); - ui.findPreference(PreferenceController.STATISTICS).setOnPreferenceClickListener( - preference -> { - activity.startActivity(new Intent(activity, StatisticsActivity.class)); - return true; - } - ); - ui.findPreference(PREF_KNOWN_ISSUES).setOnPreferenceClickListener(preference -> { - openInBrowser("https://github.com/AntennaPod/AntennaPod/labels/bug"); - return true; - }); - ui.findPreference(PREF_FAQ).setOnPreferenceClickListener(preference -> { - openInBrowser("http://antennapod.org/faq.html"); - return true; - }); - ui.findPreference(PREF_SEND_CRASH_REPORT).setOnPreferenceClickListener(preference -> { - Context context = ui.getActivity().getApplicationContext(); - Intent emailIntent = new Intent(Intent.ACTION_SEND); - emailIntent.setType("text/plain"); - emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{"Martin.Fietz@gmail.com"}); - emailIntent.putExtra(Intent.EXTRA_SUBJECT, "AntennaPod Crash Report"); - emailIntent.putExtra(Intent.EXTRA_TEXT, "Please describe what you were doing when the app crashed"); - // the attachment - Uri fileUri = FileProvider.getUriForFile(context, context.getString(R.string.provider_authority), - CrashReportWriter.getFile()); - emailIntent.putExtra(Intent.EXTRA_STREAM, fileUri); - emailIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - String intentTitle = ui.getActivity().getString(R.string.send_email); - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { - List resInfoList = context.getPackageManager().queryIntentActivities(emailIntent, PackageManager.MATCH_DEFAULT_ONLY); - for (ResolveInfo resolveInfo : resInfoList) { - String packageName = resolveInfo.activityInfo.packageName; - context.grantUriPermission(packageName, fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION); - } - } - ui.getActivity().startActivity(Intent.createChooser(emailIntent, intentTitle)); - return true; - }); - } - - private void setupSearch() { - final AppCompatActivity activity = ui.getActivity(); - - SearchPreference searchPreference = (SearchPreference) ui.findPreference("searchPreference"); - SearchConfiguration config = searchPreference.getSearchConfiguration(); - config.setActivity(activity); - config.setFragmentContainerViewId(R.id.content); - config.setBreadcrumbsEnabled(true); - - config.index(R.xml.preferences_user_interface) - .addBreadcrumb(getTitleOfPage(R.xml.preferences_user_interface)); - config.index(R.xml.preferences_playback) - .addBreadcrumb(getTitleOfPage(R.xml.preferences_playback)); - config.index(R.xml.preferences_network) - .addBreadcrumb(getTitleOfPage(R.xml.preferences_network)); - config.index(R.xml.preferences_storage) - .addBreadcrumb(getTitleOfPage(R.xml.preferences_storage)); - config.index(R.xml.preferences_autodownload) - .addBreadcrumb(getTitleOfPage(R.xml.preferences_network)) - .addBreadcrumb(R.string.automation) - .addBreadcrumb(getTitleOfPage(R.xml.preferences_autodownload)); - config.index(R.xml.preferences_gpodder) - .addBreadcrumb(getTitleOfPage(R.xml.preferences_integrations)) - .addBreadcrumb(getTitleOfPage(R.xml.preferences_gpodder)); - config.index(R.xml.preferences_flattr) - .addBreadcrumb(getTitleOfPage(R.xml.preferences_integrations)) - .addBreadcrumb(getTitleOfPage(R.xml.preferences_flattr)); - } - - public PreferenceFragmentCompat openScreen(int preferences, AppCompatActivity activity) { - PreferenceFragmentCompat prefFragment = new PreferenceActivity.MainFragment(); - Bundle args = new Bundle(); - args.putInt(PARAM_RESOURCE, preferences); - prefFragment.setArguments(args); - activity.getSupportFragmentManager().beginTransaction() - .replace(R.id.content, prefFragment) - .addToBackStack(TAG).commit(); - return prefFragment; - } - - public static int getTitleOfPage(int preferences) { - switch (preferences) { - case R.xml.preferences_network: - return R.string.network_pref; - case R.xml.preferences_autodownload: - return R.string.pref_automatic_download_title; - case R.xml.preferences_playback: - return R.string.playback_pref; - case R.xml.preferences_storage: - return R.string.storage_pref; - case R.xml.preferences_user_interface: - return R.string.user_interface_label; - case R.xml.preferences_integrations: - return R.string.integrations_label; - case R.xml.preferences_flattr: - return R.string.flattr_label; - case R.xml.preferences_gpodder: - return R.string.gpodnet_main_label; - default: - return R.string.settings_label; - } - } - - private boolean export(ExportWriter exportWriter) { - Context context = ui.getActivity(); - final ProgressDialog progressDialog = new ProgressDialog(context); - progressDialog.setMessage(context.getString(R.string.exporting_label)); - progressDialog.setIndeterminate(true); - progressDialog.show(); - final AlertDialog.Builder alert = new AlertDialog.Builder(context) - .setNeutralButton(android.R.string.ok, (dialog, which) -> dialog.dismiss()); - Observable observable = new ExportWorker(exportWriter).exportObservable(); - disposable = observable.subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(output -> { - alert.setTitle(R.string.export_success_title); - String message = context.getString(R.string.export_success_sum, output.toString()); - alert.setMessage(message); - alert.setPositiveButton(R.string.send_label, (dialog, which) -> { - Uri fileUri = FileProvider.getUriForFile(context.getApplicationContext(), - context.getString(R.string.provider_authority), output); - Intent sendIntent = new Intent(Intent.ACTION_SEND); - sendIntent.putExtra(Intent.EXTRA_SUBJECT, - context.getResources().getText(R.string.opml_export_label)); - sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri); - sendIntent.setType("text/plain"); - sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { - List resInfoList = context.getPackageManager().queryIntentActivities(sendIntent, PackageManager.MATCH_DEFAULT_ONLY); - for (ResolveInfo resolveInfo : resInfoList) { - String packageName = resolveInfo.activityInfo.packageName; - context.grantUriPermission(packageName, fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION); - } - } - context.startActivity(Intent.createChooser(sendIntent, - context.getResources().getText(R.string.send_label))); - }); - alert.create().show(); - }, error -> { - alert.setTitle(R.string.export_error_label); - alert.setMessage(error.getMessage()); - alert.show(); - }, progressDialog::dismiss); - return true; - } - - private void openInBrowser(String url) { - try { - Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - ui.getActivity().startActivity(myIntent); - } catch (ActivityNotFoundException e) { - Toast.makeText(ui.getActivity(), R.string.pref_no_browser_found, Toast.LENGTH_LONG).show(); - Log.e(TAG, Log.getStackTraceString(e)); - } - } - - public void onResume(int screen) { - switch (screen) { - case R.xml.preferences_network: - setUpdateIntervalText(); - setParallelDownloadsText(UserPreferences.getParallelDownloads()); - break; - case R.xml.preferences_autodownload: - checkAutodownloadItemVisibility(UserPreferences.isEnableAutodownload()); - break; - case R.xml.preferences_storage: - setDataFolderText(); - break; - case R.xml.preferences_integrations: - setIntegrationsItemVisibility(); - return; - case R.xml.preferences_flattr: - checkFlattrItemVisibility(); - break; - case R.xml.preferences_gpodder: - GpodnetPreferences.registerOnSharedPreferenceChangeListener(gpoddernetListener); - updateGpodnetPreferenceScreen(); - break; - case R.xml.preferences_playback: - checkSonicItemVisibility(); - break; - } - } - - public void unregisterGpodnet() { - GpodnetPreferences.unregisterOnSharedPreferenceChangeListener(gpoddernetListener); - } - - public void unsubscribeExportSubscription() { - if (disposable != null) { - disposable.dispose(); - } - } - - @SuppressLint("NewApi") - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (resultCode == Activity.RESULT_OK && - requestCode == DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED) { - String dir = data.getStringExtra(DirectoryChooserActivity.RESULT_SELECTED_DIR); - - File path; - if(dir != null) { - path = new File(dir); - } else { - path = ui.getActivity().getExternalFilesDir(null); - } - String message = null; - final Context context= ui.getActivity().getApplicationContext(); - if(!path.exists()) { - message = String.format(context.getString(R.string.folder_does_not_exist_error), dir); - } else if(!path.canRead()) { - message = String.format(context.getString(R.string.folder_not_readable_error), dir); - } else if(!path.canWrite()) { - message = String.format(context.getString(R.string.folder_not_writable_error), dir); - } - - if(message == null) { - Log.d(TAG, "Setting data folder: " + dir); - UserPreferences.setDataFolder(dir); - setDataFolderText(); - } else { - AlertDialog.Builder ab = new AlertDialog.Builder(ui.getActivity()); - ab.setMessage(message); - ab.setPositiveButton(android.R.string.ok, null); - ab.show(); - } - } - } - - - private void updateGpodnetPreferenceScreen() { - final boolean loggedIn = GpodnetPreferences.loggedIn(); - ui.findPreference(PreferenceController.PREF_GPODNET_LOGIN).setEnabled(!loggedIn); - ui.findPreference(PreferenceController.PREF_GPODNET_SETLOGIN_INFORMATION).setEnabled(loggedIn); - ui.findPreference(PreferenceController.PREF_GPODNET_SYNC).setEnabled(loggedIn); - ui.findPreference(PreferenceController.PREF_GPODNET_FORCE_FULL_SYNC).setEnabled(loggedIn); - ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setEnabled(loggedIn); - ui.findPreference(PREF_GPODNET_NOTIFICATIONS).setEnabled(loggedIn); - if(loggedIn) { - String format = ui.getActivity().getString(R.string.pref_gpodnet_login_status); - String summary = String.format(format, GpodnetPreferences.getUsername(), - GpodnetPreferences.getDeviceID()); - ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setSummary(Html.fromHtml(summary)); - updateLastGpodnetSyncReport(GpodnetPreferences.getLastSyncAttemptResult(), - GpodnetPreferences.getLastSyncAttemptTimestamp()); - } else { - ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setSummary(null); - updateLastGpodnetSyncReport(false, 0); - } - ui.findPreference(PreferenceController.PREF_GPODNET_HOSTNAME).setSummary(GpodnetPreferences.getHostname()); - } - - private void updateLastGpodnetSyncReport(boolean successful, long lastTime) { - Preference sync = ui.findPreference(PREF_GPODNET_SYNC); - if (lastTime != 0) { - sync.setSummary(ui.getActivity().getString(R.string.pref_gpodnet_sync_changes_sum) + "\n" + - ui.getActivity().getString(R.string.pref_gpodnet_sync_sum_last_sync_line, - ui.getActivity().getString(successful ? - R.string.gpodnetsync_pref_report_successful : - R.string.gpodnetsync_pref_report_failed), - DateUtils.getRelativeDateTimeString(ui.getActivity(), - lastTime, - DateUtils.MINUTE_IN_MILLIS, - DateUtils.WEEK_IN_MILLIS, - DateUtils.FORMAT_SHOW_TIME))); - } else { - sync.setSummary(ui.getActivity().getString(R.string.pref_gpodnet_sync_changes_sum)); - } - } - - private String[] getUpdateIntervalEntries(final String[] values) { - final Resources res = ui.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; - } - - private void buildEpisodeCleanupPreference() { - final Resources res = ui.getActivity().getResources(); - - ListPreference pref = (ListPreference) ui.findPreference(UserPreferences.PREF_EPISODE_CLEANUP); - String[] values = res.getStringArray( - R.array.episode_cleanup_values); - String[] entries = new String[values.length]; - for (int x = 0; x < values.length; x++) { - int v = Integer.parseInt(values[x]); - if (v == UserPreferences.EPISODE_CLEANUP_QUEUE) { - entries[x] = res.getString(R.string.episode_cleanup_queue_removal); - } else if (v == UserPreferences.EPISODE_CLEANUP_NULL){ - entries[x] = res.getString(R.string.episode_cleanup_never); - } else if (v == 0) { - entries[x] = res.getString(R.string.episode_cleanup_after_listening); - } else if (v > 0 && v < 24) { - entries[x] = res.getQuantityString(R.plurals.episode_cleanup_hours_after_listening, v, v); - } else { - int numDays = v / 24; // assume underlying value will be NOT fraction of days, e.g., 36 (hours) - entries[x] = res.getQuantityString(R.plurals.episode_cleanup_days_after_listening, numDays, numDays); - } - } - pref.setEntries(entries); - } - - private void buildSmartMarkAsPlayedPreference() { - final Resources res = ui.getActivity().getResources(); - - ListPreference pref = (ListPreference) ui.findPreference(UserPreferences.PREF_SMART_MARK_AS_PLAYED_SECS); - String[] values = res.getStringArray(R.array.smart_mark_as_played_values); - String[] entries = new String[values.length]; - for (int x = 0; x < values.length; x++) { - if(x == 0) { - entries[x] = res.getString(R.string.pref_smart_mark_as_played_disabled); - } else { - Integer v = Integer.parseInt(values[x]); - if(v < 60) { - entries[x] = res.getQuantityString(R.plurals.time_seconds_quantified, v, v); - } else { - v /= 60; - entries[x] = res.getQuantityString(R.plurals.time_minutes_quantified, v, v); - } - } - } - pref.setEntries(entries); - } - - private void setSelectedNetworksEnabled(boolean b) { - if (selectedNetworks != null) { - for (Preference p : selectedNetworks) { - p.setEnabled(b); - } - } - } - - private void setIntegrationsItemVisibility() { - ui.findPreference(PreferenceController.PREF_SCREEN_FLATTR).setEnabled(FlattrUtils.hasAPICredentials()); - } - - @SuppressWarnings("deprecation") - private void checkFlattrItemVisibility() { - boolean hasFlattrToken = FlattrUtils.hasToken(); - ui.findPreference(PreferenceController.PREF_FLATTR_AUTH).setEnabled(!hasFlattrToken); - ui.findPreference(PreferenceController.PREF_FLATTR_REVOKE).setEnabled(hasFlattrToken); - ui.findPreference(PreferenceController.PREF_AUTO_FLATTR_PREFS).setEnabled(hasFlattrToken); - } - - private void checkAutodownloadItemVisibility(boolean autoDownload) { - ui.findPreference(UserPreferences.PREF_EPISODE_CACHE_SIZE).setEnabled(autoDownload); - ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_ON_BATTERY).setEnabled(autoDownload); - ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER).setEnabled(autoDownload); - ui.findPreference(UserPreferences.PREF_EPISODE_CLEANUP).setEnabled(autoDownload); - ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_ON_MOBILE).setEnabled(autoDownload); - setSelectedNetworksEnabled(autoDownload && UserPreferences.isEnableAutodownloadWifiFilter()); - } - - private void checkSonicItemVisibility() { - if (Build.VERSION.SDK_INT < 16) { - ListPreference p = (ListPreference) ui.findPreference(UserPreferences.PREF_MEDIA_PLAYER); - p.setEntries(R.array.media_player_options_no_sonic); - p.setEntryValues(R.array.media_player_values_no_sonic); - } - } - - private void setUpdateIntervalText() { - Context context = ui.getActivity().getApplicationContext(); - String val; - long interval = UserPreferences.getUpdateInterval(); - if(interval > 0) { - int hours = (int) TimeUnit.MILLISECONDS.toHours(interval); - String hoursStr = context.getResources().getQuantityString(R.plurals.time_hours_quantified, hours, hours); - val = String.format(context.getString(R.string.pref_autoUpdateIntervallOrTime_every), hoursStr); - } else { - int[] timeOfDay = UserPreferences.getUpdateTimeOfDay(); - if(timeOfDay.length == 2) { - Calendar cal = new GregorianCalendar(); - 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), - 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??? - } - } - String summary = context.getString(R.string.pref_autoUpdateIntervallOrTime_sum) + "\n" - + String.format(context.getString(R.string.pref_current_value), val); - ui.findPreference(UserPreferences.PREF_UPDATE_INTERVAL).setSummary(summary); - } - - private void setParallelDownloadsText(int downloads) { - final Resources res = ui.getActivity().getResources(); - - String s = Integer.toString(downloads) - + res.getString(R.string.parallel_downloads_suffix); - ui.findPreference(UserPreferences.PREF_PARALLEL_DOWNLOADS).setSummary(s); - } - - private void setDataFolderText() { - File f = UserPreferences.getDataFolder(null); - if (f != null) { - ui.findPreference(PreferenceController.PREF_CHOOSE_DATA_DIR) - .setSummary(f.getAbsolutePath()); - } - } - - private static String blankIfNull(String val) { - return val == null ? "" : val; - } - - private void buildAutodownloadSelectedNetworksPreference() { - final Activity activity = ui.getActivity(); - - if (selectedNetworks != null) { - clearAutodownloadSelectedNetworsPreference(); - } - // get configured networks - WifiManager wifiservice = (WifiManager) activity.getApplicationContext().getSystemService(Context.WIFI_SERVICE); - List networks = wifiservice.getConfiguredNetworks(); - - if (networks == null) { - Log.e(TAG, "Couldn't get list of configure Wi-Fi networks"); - return; - } - Collections.sort(networks, (x, y) -> - blankIfNull(x.SSID).compareTo(blankIfNull(y.SSID))); - selectedNetworks = new CheckBoxPreference[networks.size()]; - List prefValues = Arrays.asList(UserPreferences - .getAutodownloadSelectedNetworks()); - PreferenceScreen prefScreen = ui.getPreferenceScreen(); - Preference.OnPreferenceClickListener clickListener = preference -> { - if (preference instanceof CheckBoxPreference) { - String key = preference.getKey(); - List prefValuesList = new ArrayList<>( - Arrays.asList(UserPreferences - .getAutodownloadSelectedNetworks()) - ); - boolean newValue = ((CheckBoxPreference) preference) - .isChecked(); - Log.d(TAG, "Selected network " + key + ". New state: " + newValue); - - int index = prefValuesList.indexOf(key); - if (index >= 0 && !newValue) { - // remove network - prefValuesList.remove(index); - } else if (index < 0 && newValue) { - prefValuesList.add(key); - } - - UserPreferences.setAutodownloadSelectedNetworks( - prefValuesList.toArray(new String[prefValuesList.size()]) - ); - return true; - } else { - return false; - } - }; - // create preference for each known network. attach listener and set - // value - for (int i = 0; i < networks.size(); i++) { - WifiConfiguration config = networks.get(i); - - CheckBoxPreference pref = new CheckBoxPreference(activity); - String key = Integer.toString(config.networkId); - pref.setTitle(config.SSID); - pref.setKey(key); - pref.setOnPreferenceClickListener(clickListener); - pref.setPersistent(false); - pref.setChecked(prefValues.contains(key)); - selectedNetworks[i] = pref; - prefScreen.addPreference(pref); - } - } - - private void clearAutodownloadSelectedNetworsPreference() { - if (selectedNetworks != null) { - PreferenceScreen prefScreen = ui.getPreferenceScreen(); - - for (CheckBoxPreference network : selectedNetworks) { - if (network != null) { - prefScreen.removePreference(network); - } - } - } - } - - private void showDrawerPreferencesDialog() { - final Context context = ui.getActivity(); - final List hiddenDrawerItems = UserPreferences.getHiddenDrawerItems(); - final String[] navTitles = context.getResources().getStringArray(R.array.nav_drawer_titles); - final String[] NAV_DRAWER_TAGS = MainActivity.NAV_DRAWER_TAGS; - boolean[] checked = new boolean[MainActivity.NAV_DRAWER_TAGS.length]; - for(int i=0; i < NAV_DRAWER_TAGS.length; i++) { - String tag = NAV_DRAWER_TAGS[i]; - if(!hiddenDrawerItems.contains(tag)) { - checked[i] = true; - } - } - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(R.string.drawer_preferences); - builder.setMultiChoiceItems(navTitles, checked, (dialog, which, isChecked) -> { - if (isChecked) { - hiddenDrawerItems.remove(NAV_DRAWER_TAGS[which]); - } else { - hiddenDrawerItems.add(NAV_DRAWER_TAGS[which]); - } - }); - builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> - UserPreferences.setHiddenDrawerItems(hiddenDrawerItems)); - builder.setNegativeButton(R.string.cancel_label, null); - builder.create().show(); - } - - private void showNotificationButtonsDialog() { - final Context context = ui.getActivity(); - final List preferredButtons = UserPreferences.getCompactNotificationButtons(); - final String[] allButtonNames = context.getResources().getStringArray( - R.array.compact_notification_buttons_options); - boolean[] checked = new boolean[allButtonNames.length]; // booleans default to false in java - - for(int i=0; i < checked.length; i++) { - if(preferredButtons.contains(i)) { - checked[i] = true; - } - } - - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(String.format(context.getResources().getString( - R.string.pref_compact_notification_buttons_dialog_title), 2)); - builder.setMultiChoiceItems(allButtonNames, checked, (dialog, which, isChecked) -> { - checked[which] = isChecked; - - if (isChecked) { - if (preferredButtons.size() < 2) { - preferredButtons.add(which); - } else { - // Only allow a maximum of two selections. This is because the notification - // on the lock screen can only display 3 buttons, and the play/pause button - // is always included. - checked[which] = false; - ListView selectionView = ((AlertDialog) dialog).getListView(); - selectionView.setItemChecked(which, false); - Snackbar.make( - selectionView, - String.format(context.getResources().getString( - R.string.pref_compact_notification_buttons_dialog_error), 2), - Snackbar.LENGTH_SHORT).show(); - } - } else { - preferredButtons.remove((Integer) which); - } - }); - builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> - UserPreferences.setCompactNotificationButtons(preferredButtons)); - builder.setNegativeButton(R.string.cancel_label, null); - builder.create().show(); - } - - // CHOOSE DATA FOLDER - - private void requestPermission() { - ActivityCompat.requestPermissions(ui.getActivity(), EXTERNAL_STORAGE_PERMISSIONS, - PERMISSION_REQUEST_EXTERNAL_STORAGE); - } - - private void openDirectoryChooser() { - Activity activity = ui.getActivity(); - Intent intent = new Intent(activity, DirectoryChooserActivity.class); - activity.startActivityForResult(intent, DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED); - } - - private void showChooseDataFolderDialog() { - ChooseDataFolderDialog.showDialog( - ui.getActivity(), new ChooseDataFolderDialog.RunnableWithString() { - @Override - public void run(final String folder) { - UserPreferences.setDataFolder(folder); - setDataFolderText(); - } - }); - } - - // UPDATE TIME/INTERVAL DIALOG - - private void showUpdateIntervalTimePreferencesDialog() { - final Context context = ui.getActivity(); - - MaterialDialog.Builder builder = new MaterialDialog.Builder(context); - builder.title(R.string.pref_autoUpdateIntervallOrTime_title); - builder.content(R.string.pref_autoUpdateIntervallOrTime_message); - builder.positiveText(R.string.pref_autoUpdateIntervallOrTime_Interval); - builder.negativeText(R.string.pref_autoUpdateIntervallOrTime_TimeOfDay); - builder.neutralText(R.string.pref_autoUpdateIntervallOrTime_Disable); - builder.onPositive((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.onNegative((dialog, which) -> { - int hourOfDay = 7, 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.onNeutral((dialog, which) -> { - UserPreferences.disableAutoUpdate(); - setUpdateIntervalText(); - }); - builder.show(); - } - - - public interface PreferenceUI { - - void setFragment(PreferenceFragmentCompat fragment); - PreferenceFragmentCompat getFragment(); - - /** - * Finds a preference based on its key. - */ - Preference findPreference(CharSequence key); - - PreferenceScreen getPreferenceScreen(); - - AppCompatActivity getActivity(); - } -} diff --git a/app/src/play/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java b/app/src/play/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java index b9b4e891f..c9d52df0c 100644 --- a/app/src/play/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java +++ b/app/src/play/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java @@ -4,13 +4,14 @@ import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GoogleApiAvailability; import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.fragment.preferences.PlaybackPreferencesFragment; /** * Implements functions from PreferenceController that are flavor dependent. */ public class PreferenceControllerFlavorHelper { - static void setupFlavoredUI(PreferenceController.PreferenceUI ui) { + public static void setupFlavoredUI(PlaybackPreferencesFragment ui) { //checks whether Google Play Services is installed on the device (condition necessary for Cast support) ui.findPreference(UserPreferences.PREF_CAST_ENABLED).setOnPreferenceChangeListener((preference, o) -> { if (o instanceof Boolean && ((Boolean) o)) {