mirror of https://github.com/TeamNewPipe/NewPipe
Implementation of player settings page in Settings page redesign
- Added new files for the Fragment and xml related to the player settings page. - Implemented the player settings page per the description in https://github.com/TeamNewPipe/NewPipe/issues/9587. - These changes facilitate easier switching between current and new behaviors. - They also lay the groundwork for easier cleanup when the new design is approved and enabled by default. Video: - https://github.com/TeamNewPipe/NewPipe/assets/87667048/00385bbb-6a2f-4ce5-b6b9-6cf1cb5c5636
This commit is contained in:
parent
89645fab99
commit
5ca85861e7
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -30,11 +30,11 @@ public final class SettingsResourceRegistry {
|
|||
|
||||
private SettingsResourceRegistry() {
|
||||
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);
|
||||
|
|
|
@ -846,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>
|
||||
|
|
|
@ -4,6 +4,11 @@
|
|||
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"
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
<?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:title="@string/settings_category_player_title">
|
||||
|
||||
<PreferenceCategory
|
||||
android:layout="@layout/settings_category_header_layout"
|
||||
android:title="@string/settings_category_resolution_and_format_title"
|
||||
app:iconSpaceReserved="false"
|
||||
app:singleLineTitle="false">
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="@string/default_resolution_value"
|
||||
android:entries="@array/resolution_list_description"
|
||||
android:entryValues="@array/resolution_list_values"
|
||||
android:key="@string/default_resolution_key"
|
||||
android:title="@string/default_resolution_title"
|
||||
app:iconSpaceReserved="false"
|
||||
app:singleLineTitle="false"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="@string/default_popup_resolution_value"
|
||||
android:entries="@array/resolution_list_description"
|
||||
android:entryValues="@array/resolution_list_values"
|
||||
android:key="@string/default_popup_resolution_key"
|
||||
android:title="@string/default_popup_resolution_title"
|
||||
app:iconSpaceReserved="false"
|
||||
app:singleLineTitle="false"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="@string/limit_mobile_data_usage_value"
|
||||
android:entries="@array/limit_data_usage_description_list"
|
||||
android:entryValues="@array/limit_data_usage_values_list"
|
||||
android:key="@string/limit_mobile_data_usage_key"
|
||||
android:title="@string/limit_mobile_data_usage_title"
|
||||
app:iconSpaceReserved="false"
|
||||
app:singleLineTitle="false"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="@string/show_higher_resolutions_key"
|
||||
android:summary="@string/show_higher_resolutions_summary"
|
||||
android:title="@string/show_higher_resolutions_title"
|
||||
app:iconSpaceReserved="false"
|
||||
app:singleLineTitle="false" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="@string/default_video_format_value"
|
||||
android:entries="@array/video_format_description_list"
|
||||
android:entryValues="@array/video_format_values_list"
|
||||
android:key="@string/default_video_format_key"
|
||||
android:title="@string/default_video_format_title"
|
||||
app:iconSpaceReserved="false"
|
||||
app:singleLineTitle="false"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="@string/default_audio_format_value"
|
||||
android:entries="@array/audio_format_description_list"
|
||||
android:entryValues="@array/audio_format_values_list"
|
||||
android:key="@string/default_audio_format_key"
|
||||
android:title="@string/default_audio_format_title"
|
||||
app:iconSpaceReserved="false"
|
||||
app:singleLineTitle="false"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="@string/prefer_original_audio_key"
|
||||
android:summary="@string/prefer_original_audio_summary"
|
||||
android:title="@string/prefer_original_audio_title"
|
||||
app:iconSpaceReserved="false"
|
||||
app:singleLineTitle="false" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="@string/prefer_descriptive_audio_key"
|
||||
android:summary="@string/prefer_descriptive_audio_summary"
|
||||
android:title="@string/prefer_descriptive_audio_title"
|
||||
app:iconSpaceReserved="false"
|
||||
app:singleLineTitle="false" />
|
||||
|
||||
<PreferenceScreen
|
||||
android:fragment="org.schabi.newpipe.settings.ExoPlayerSettingsFragment"
|
||||
android:key="@string/exoplayer_settings_key"
|
||||
android:summary="@string/settings_category_exoplayer_summary"
|
||||
android:title="@string/settings_category_exoplayer_title"
|
||||
app:iconSpaceReserved="false"
|
||||
app:singleLineTitle="false" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:layout="@layout/settings_category_header_layout"
|
||||
android:title="@string/settings_category_player_title"
|
||||
app:iconSpaceReserved="false"
|
||||
app:singleLineTitle="false">
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="@string/use_external_video_player_key"
|
||||
android:summary="@string/use_external_video_player_summary"
|
||||
android:title="@string/use_external_video_player_title"
|
||||
app:iconSpaceReserved="false"
|
||||
app:singleLineTitle="false" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="@string/use_external_audio_player_key"
|
||||
android:title="@string/use_external_audio_player_title"
|
||||
app:iconSpaceReserved="false"
|
||||
app:singleLineTitle="false" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="@string/show_play_with_kodi_key"
|
||||
android:summary="@string/show_play_with_kodi_summary"
|
||||
android:title="@string/show_play_with_kodi_title"
|
||||
app:iconSpaceReserved="false"
|
||||
app:singleLineTitle="false" />
|
||||
|
||||
<ListPreference
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:defaultValue="seekbar_preview_thumbnail_high_quality"
|
||||
android:entries="@array/seekbar_preview_thumbnail_type_description"
|
||||
android:entryValues="@array/seekbar_preview_thumbnail_type_key"
|
||||
android:key="@string/seekbar_preview_thumbnail_key"
|
||||
android:title="@string/seekbar_preview_thumbnail_title"
|
||||
app:iconSpaceReserved="false"
|
||||
app:singleLineTitle="false"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
|
||||
<Preference
|
||||
android:key="@string/caption_settings_key"
|
||||
android:summary="@string/caption_setting_description"
|
||||
android:title="@string/caption_setting_title"
|
||||
app:singleLineTitle="false"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<PreferenceScreen
|
||||
android:key="@string/player_notification_screen_key"
|
||||
android:summary="@string/settings_category_player_notification_summary"
|
||||
android:title="@string/settings_category_player_notification_title"
|
||||
app:iconSpaceReserved="false"
|
||||
app:singleLineTitle="false" />
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
Loading…
Reference in New Issue