Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setting page redesign player page #10850

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.schabi.newpipe.settings

import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import androidx.activity.ComponentActivity
import androidx.core.view.MenuProvider
import androidx.preference.Preference
import org.schabi.newpipe.R

/**
* Provides main settings page, entry point to the NewPipe app settings.
*/
class MainSettingsV2Fragment : BasePreferenceFragment(), MenuProvider {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResourceRegistry()

(activity as? ComponentActivity)?.addMenuProvider(this, this)

// Hide debug preferences in RELEASE build variant
if (!DEBUG) {
findPreference<Preference>(getString(R.string.debug_pref_screen_key))?.let(
preferenceScreen::removePreference,
)
}
}

override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
// -- Link settings activity and register menu --
menuInflater.inflate(R.menu.menu_settings_main_fragment, menu)
val menuSearchItem = menu.getItem(0)
(activity as? SettingsActivity)?.setMenuSearchItem(menuSearchItem)
}

override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
if (menuItem.itemId == R.id.action_search) {
(activity as? SettingsActivity)?.setSearchActive(true)
return true
}
return false
}

override fun onDestroy() {
// Unlink activity so that we don't get memory problems
(activity as? SettingsActivity)?.setMenuSearchItem(null)
super.onDestroy()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
package org.schabi.newpipe.settings

import android.content.ActivityNotFoundException
import android.content.Intent
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
import android.content.res.Resources.NotFoundException
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.text.format.DateUtils
import android.widget.Toast
import androidx.preference.ListPreference
import androidx.preference.Preference
import com.google.android.material.snackbar.Snackbar
import org.schabi.newpipe.R
import org.schabi.newpipe.util.ListHelper
import org.schabi.newpipe.util.PermissionHelper
import java.util.LinkedList

class PlayerSettingsFragment : BasePreferenceFragment() {
private lateinit var listener: OnSharedPreferenceChangeListener

override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResourceRegistry()
updateSeekOptions()
updateResolutionOptions()
listener = OnSharedPreferenceChangeListener { sharedPreferences, key ->
// on M and above, if user chooses to minimise to popup player on exit and the app
// doesn't have display over other apps permission, show a snack bar to let the user
// give permission
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
getString(R.string.minimize_on_exit_key) == key
) {
sharedPreferences.getString(key, null)
?.takeIf {
getString(R.string.minimize_on_exit_popup_key) == it &&
!Settings.canDrawOverlays(context)
}?.let {
Snackbar.make(
listView,
R.string.permission_display_over_apps,
Snackbar.LENGTH_INDEFINITE,
).setAction(R.string.settings) {
PermissionHelper.checkSystemAlertWindowPermission(context)
}.show()
}
} else if (getString(R.string.use_inexact_seek_key) == key) {
updateSeekOptions()
} else if (getString(R.string.show_higher_resolutions_key) == key) {
updateResolutionOptions()
}
}
}

/**
* Update default resolution, default popup resolution & mobile data resolution options.
* <br></br>
* Show high resolutions when "Show higher resolution" option is enabled.
* Set default resolution to "best resolution" when "Show higher resolution" option
* is disabled.
*/
private fun updateResolutionOptions() {
val resources = resources
val showHigherResolutions = preferenceManager.getSharedPreferences()
?.getBoolean(resources.getString(R.string.show_higher_resolutions_key), false) ?: false

// get sorted resolution lists
val resolutionListDescriptions = ListHelper.getSortedResolutionList(
resources,
R.array.resolution_list_description,
R.array.high_resolution_list_descriptions,
showHigherResolutions,
)
val resolutionListValues = ListHelper.getSortedResolutionList(
resources,
R.array.resolution_list_values,
R.array.high_resolution_list_values,
showHigherResolutions,
)
val limitDataUsageResolutionValues = ListHelper.getSortedResolutionList(
resources,
R.array.limit_data_usage_values_list,
R.array.high_resolution_limit_data_usage_values_list,
showHigherResolutions,
)
val limitDataUsageResolutionDescriptions = ListHelper
.getSortedResolutionList(
resources,
R.array.limit_data_usage_description_list,
R.array.high_resolution_list_descriptions,
showHigherResolutions,
)

// get resolution preferences
val defaultResolution = findPreference<ListPreference>(
getString(R.string.default_resolution_key)
)
val defaultPopupResolution = findPreference<ListPreference>(
getString(R.string.default_popup_resolution_key)
)
val mobileDataResolution = findPreference<ListPreference>(
getString(R.string.limit_mobile_data_usage_key)
)

// update resolution preferences with new resolutions, entries & values for each
defaultResolution?.entries = resolutionListDescriptions.toTypedArray<String>()
defaultResolution?.entryValues = resolutionListValues.toTypedArray<String>()
defaultPopupResolution?.entries = resolutionListDescriptions.toTypedArray<String>()
defaultPopupResolution?.entryValues = resolutionListValues.toTypedArray<String>()
mobileDataResolution?.entries = limitDataUsageResolutionDescriptions.toTypedArray<String>()
mobileDataResolution?.entryValues =
limitDataUsageResolutionValues.toTypedArray<String>()

// if "Show higher resolution" option is disabled,
// set default resolution to "best resolution"
if (!showHigherResolutions) {
if (defaultResolution != null && ListHelper.isHighResolutionSelected(
defaultResolution.value,
R.array.high_resolution_list_values,
resources
)
) {
defaultResolution.setValueIndex(0)
}
if (defaultPopupResolution != null && ListHelper.isHighResolutionSelected(
defaultPopupResolution.value,
R.array.high_resolution_list_values,
resources,
)
) {
defaultPopupResolution.setValueIndex(0)
}
if (mobileDataResolution != null && ListHelper.isHighResolutionSelected(
mobileDataResolution.value,
R.array.high_resolution_limit_data_usage_values_list,
resources,
)
) {
mobileDataResolution.setValueIndex(0)
}
}
}

/**
* Update fast-forward/-rewind seek duration options
* according to language and inexact seek setting.
* Exoplayer can't seek 5 seconds in audio when using inexact seek.
*/
private fun updateSeekOptions() {
// initializing R.array.seek_duration_description to display the translation of seconds
val durationsValues = resources.getStringArray(R.array.seek_duration_value)
val displayedDurationValues = LinkedList<String>()
val displayedDescriptionValues = LinkedList<String>()
val inexactSeek = preferenceManager.getSharedPreferences()
?.getBoolean(resources.getString(R.string.use_inexact_seek_key), false) ?: false
for (durationsValue in durationsValues) {
val currentDurationValue = durationsValue.toInt() / DateUtils.SECOND_IN_MILLIS.toInt()
if (inexactSeek && currentDurationValue % 10 == 5) {
continue
}
displayedDurationValues.add(durationsValue)
try {
displayedDescriptionValues.add(
String.format(
resources.getQuantityString(R.plurals.seconds, currentDurationValue),
currentDurationValue
)
)
} catch (ignored: NotFoundException) {
// if this happens, the translation is missing,
// and the english string will be displayed instead
}
}
findPreference<ListPreference>(getString(R.string.seek_duration_key))?.apply {
entryValues = displayedDurationValues.toTypedArray<CharSequence>()
entries = displayedDescriptionValues.toTypedArray<CharSequence>()
val selectedDuration = value.toLong()
if (inexactSeek && selectedDuration / DateUtils.SECOND_IN_MILLIS % 10 == 5L) {
val newDuration = selectedDuration / DateUtils.SECOND_IN_MILLIS + 5
value = (newDuration * DateUtils.SECOND_IN_MILLIS).toString()
Toast.makeText(
context,
getString(R.string.new_seek_duration_toast, newDuration),
Toast.LENGTH_LONG,
).show()
}
}
}

override fun onResume() {
super.onResume()
preferenceManager.getSharedPreferences()?.registerOnSharedPreferenceChangeListener(listener)
}

override fun onPause() {
super.onPause()
preferenceManager.getSharedPreferences()?.unregisterOnSharedPreferenceChangeListener(listener)
}

override fun onPreferenceTreeClick(preference: Preference): Boolean {
if (getString(R.string.caption_settings_key) == preference.key) {
try {
startActivity(Intent(Settings.ACTION_CAPTIONING_SETTINGS))
} catch (error: ActivityNotFoundException) {
Toast.makeText(requireContext(), R.string.general_error, Toast.LENGTH_SHORT).show()
}
}

return super.onPreferenceTreeClick(preference)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceManager;

import com.jakewharton.rxbinding4.widget.RxTextView;

Expand Down Expand Up @@ -112,8 +113,14 @@ protected void onCreate(final Bundle savedInstanceBundle) {
}
}
} else {
final boolean shouldDisplaySettingsRedesign = PreferenceManager
.getDefaultSharedPreferences(this)
.getBoolean(getString(R.string.settings_layout_redesign_key), false);
final BasePreferenceFragment mainSettingsFragment =
shouldDisplaySettingsRedesign
? new MainSettingsV2Fragment() : new MainSettingsFragment();
getSupportFragmentManager().beginTransaction()
.replace(R.id.settings_fragment_holder, new MainSettingsFragment())
.replace(R.id.settings_fragment_holder, mainSettingsFragment)
.commit();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,12 @@ public final class SettingsResourceRegistry {
private final Set<SettingRegistryEntry> registeredEntries = new HashSet<>();

private SettingsResourceRegistry() {
add(MainSettingsFragment.class, R.xml.main_settings).setSearchable(false);
add(MainSettingsV2Fragment.class, R.xml.main_settings_v2).setSearchable(false);
add(PlayerSettingsFragment.class, R.xml.player_settings);

// Before redesign settings arrangement. These should be cleared once the
// settings_layout_redesign_key is approved and enabled by default.
add(MainSettingsFragment.class, R.xml.main_settings).setSearchable(false);
add(AppearanceSettingsFragment.class, R.xml.appearance_settings);
add(ContentSettingsFragment.class, R.xml.content_settings);
add(DebugSettingsFragment.class, R.xml.debug_settings).setSearchable(false);
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/settings_keys.xml
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@
<string name="crash_the_app_key">crash_the_app_key</string>
<string name="show_error_snackbar_key">show_error_snackbar_key</string>
<string name="create_error_notification_key">create_error_notification_key</string>
<string name="settings_layout_redesign_key">settings_layout_redesign_key</string>

<!-- THEMES -->
<string name="theme_key">theme</string>
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,7 @@
<string name="crash_the_app">Crash the app</string>
<string name="show_error_snackbar">Show an error snackbar</string>
<string name="create_error_notification">Create an error notification</string>
<string name="settings_layout_redesign">Enable the Redesigned Settings page</string>
<!-- Subscriptions import/export -->
<string name="import_title">Import</string>
<string name="import_from">Import from</string>
Expand Down Expand Up @@ -845,4 +846,6 @@
</plurals>
<string name="show_more">Show more</string>
<string name="show_less">Show less</string>
<!-- Settings redesign -->
<string name="settings_category_resolution_and_format_title">Resolution and format</string>
</resources>
7 changes: 7 additions & 0 deletions app/src/main/res/xml/debug_settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,11 @@
android:title="@string/create_error_notification"
app:singleLineTitle="false"
app:iconSpaceReserved="false" />

<SwitchPreferenceCompat
android:defaultValue="false"
android:key="@string/settings_layout_redesign_key"
android:title="@string/settings_layout_redesign"
app:iconSpaceReserved="false"
app:singleLineTitle="false" />
</PreferenceScreen>
17 changes: 17 additions & 0 deletions app/src/main/res/xml/main_settings_v2.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:key="general_preferences"
android:title="@string/settings">

<PreferenceScreen
android:fragment="org.schabi.newpipe.settings.PlayerSettingsFragment"
android:title="@string/settings_category_player_title"
app:iconSpaceReserved="false" />

<PreferenceScreen
android:fragment="org.schabi.newpipe.settings.DebugSettingsFragment"
android:key="@string/debug_pref_screen_key"
android:title="@string/settings_category_debug_title"
app:iconSpaceReserved="false" />
</PreferenceScreen>
Loading
Loading