forked from TeamNewPipe/NewPipe
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 TeamNewPipe#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
- Loading branch information
Showing
5 changed files
with
369 additions
and
1 deletion.
There are no files selected for viewing
211 changes: 211 additions & 0 deletions
211
app/src/main/java/org/schabi/newpipe/settings/PlayerSettingsFragment.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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> |