add exoplayer settings

This commit is contained in:
Ida Delphine
2026-10-07 16:59:43 +08:00
committed by Aayush Gupta
parent 561afbf5a6
commit a663449f05
9 changed files with 364 additions and 7 deletions
@@ -23,7 +23,7 @@
<string name="website_title">Website</string>
<string name="website_encouragement">Visit the NewPipe Website for more info and news.</string>
<string name="privacy_policy_title">NewPipe's Privacy Policy</string>
<string name="privacy_policy_encouragement">The NewPipe project takes your privacy very seriously. Therefore, the app does not collect any data without your consent.\nNewPipe\'s privacy policy explains in detail what data is sent and stored when you send a crash report.</string>
<string name="privacy_policy_encouragement">The NewPipe project takes your privacy very seriously. Therefore, the app does not collect any data without your consent.\nNewPipe's privacy policy explains in detail what data is sent and stored when you send a crash report.</string>
<string name="read_privacy_policy">Read privacy policy</string>
<string name="app_license_title">NewPipe's License</string>
<string name="app_license">NewPipe is copyleft libre software: You can use, study, share, and improve it at will. Specifically you can redistribute and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.</string>
@@ -59,7 +59,7 @@
<string name="night_theme_available">This option is only available if %1$s is selected for Theme</string>
<string name="select_night_theme_toast">You can select your favorite night theme below</string>
<string name="show_hold_to_append_title">Show "Hold to enqueue" tip</string>
<string name="show_hold_to_append_summary">Show tip when pressing the background or the popup button in video \"Details:\"</string>
<string name="show_hold_to_append_summary">Show tip when pressing the background or the popup button in video "Details:"</string>
<string name="tablet_mode_title">Tablet mode</string>
<string name="list_view_mode">List view mode</string>
<string name="caption_setting_title">Captions</string>
@@ -99,7 +99,7 @@
<string name="seekbar_preview_thumbnail_title">Seekbar thumbnail preview</string>
<string name="high_quality_larger">High quality (larger)</string>
<string name="low_quality_smaller">Low quality (smaller)</string>
<string name="dont_show">Don\'t show</string>
<string name="dont_show">Don't show</string>
<!-- Video/Audio Settings: Behavior section -->
<string name="settings_category_player_behavior_title">Behavior</string>
@@ -139,7 +139,7 @@
<string name="popup_remember_size_pos_title">Remember popup properties</string>
<string name="popup_remember_size_pos_summary">Remember last size and position of popup</string>
<string name="use_inexact_seek_title">Use fast inexact seek</string>
<string name="use_inexact_seek_summary">Inexact seek allows the player to seek to positions faster with reduced precision. Seeking for 5, 15 or 25 seconds doesn\'t work with this</string>
<string name="use_inexact_seek_summary">Inexact seek allows the player to seek to positions faster with reduced precision. Seeking for 5, 15 or 25 seconds doesn't work with this</string>
<string name="seek_duration_title">Fast-forward/-rewind seek duration</string>
<string name="new_seek_duration_toast">Due to ExoPlayer constraints the seek duration was set to %1$d seconds</string>
<string name="clear_queue_confirmation_title">Ask for confirmation before clearing a queue</string>
@@ -151,5 +151,19 @@
<item quantity="other">%1$d seconds</item>
</plurals>
<!-- ExoPlayer Settings -->
<string name="settings_category_exoplayer_title">ExoPlayer settings</string>
<string name="settings_category_exoplayer_summary">Manage some ExoPlayer settings. These changes require a player restart to take effect</string>
<string name="progressive_load_interval_title">Playback load interval size</string>
<string name="progressive_load_interval_summary">Change the load interval size on progressive contents (currently %1$s). A lower value may speed up their initial loading</string>
<string name="progressive_load_interval_exoplayer_default">ExoPlayer default</string>
<string name="use_exoplayer_decoder_fallback_title">Use ExoPlayer's decoder fallback feature</string>
<string name="use_exoplayer_decoder_fallback_summary">Enable this option if you have decoder initialization issues, which falls back to lower-priority decoders if primary decoders initialization fail. This may result in poor playback performance than when using primary decoders</string>
<string name="disable_media_tunneling_title">Disable media tunneling</string>
<string name="disable_media_tunneling_summary">Disable media tunneling if you experience a black screen or stuttering on video playback.</string>
<string name="disable_media_tunneling_automatic_info">Media tunneling was disabled by default on your device because your device model is known to not support it.</string>
<string name="always_use_exoplayer_set_output_surface_workaround_title">Always use ExoPlayer's video output surface setting workaround</string>
<string name="always_use_exoplayer_set_output_surface_workaround_summary">This workaround releases and re-instantiates video codecs when a surface change occurs, instead of setting the surface to the codec directly. Already used by ExoPlayer on some devices with this issue, this setting has only an effect on Android 6 and higher\n\nEnabling this option may prevent playback errors when switching the current video player or switching to fullscreen</string>
</resources>
@@ -15,6 +15,9 @@ import net.newpipe.app.model.License
@Serializable
sealed interface Destination : NavKey {
@Serializable
data object ExoPlayerSettings : Destination
@Serializable
data object VideoAudioSettings : Destination
@@ -9,6 +9,7 @@ import androidx.compose.runtime.mutableStateListOf
import co.touchlab.kermit.Logger
import net.newpipe.app.screen.about.AboutScreen
import net.newpipe.app.screen.settings.AppearanceSettingsScreen
import net.newpipe.app.screen.settings.ExoPlayerSettingsScreen
import net.newpipe.app.screen.settings.SettingsHomeScreen
import net.newpipe.app.screen.settings.VideoAudioSettingsScreen
import org.koin.core.annotation.KoinExperimentalAPI
@@ -42,6 +43,10 @@ fun navModule() = module {
navigation<Destination.VideoAudioSettings> {
VideoAudioSettingsScreen()
}
navigation<Destination.ExoPlayerSettings> {
ExoPlayerSettingsScreen()
}
}
/**
@@ -0,0 +1,27 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package net.newpipe.app.preferences
object ExoPlayerPreferences {
const val KEY_PROGRESSIVE_LOAD_INTERVAL = "progressive_load_interval"
const val KEY_USE_EXOPLAYER_DECODER_FALLBACK = "use_exoplayer_decoder_fallback_key"
const val KEY_DISABLE_MEDIA_TUNNELING = "disable_media_tunneling_key"
const val KEY_DISABLED_MEDIA_TUNNELING_AUTOMATICALLY = "disabled_media_tunneling_automatically_key"
const val KEY_ALWAYS_USE_SET_OUTPUT_SURFACE_WORKAROUND = "always_use_exoplayer_set_output_surface_workaround_key"
const val PROGRESSIVE_LOAD_INTERVAL_EXOPLAYER_DEFAULT = "exoplayer_default"
const val DEFAULT_PROGRESSIVE_LOAD_INTERVAL = "64"
const val DEFAULT_USE_EXOPLAYER_DECODER_FALLBACK = false
const val DEFAULT_DISABLE_MEDIA_TUNNELING = false
const val DEFAULT_ALWAYS_USE_SET_OUTPUT_SURFACE_WORKAROUND = false
const val MEDIA_TUNNELING_AUTO_DISABLED = 1
const val MEDIA_TUNNELING_USER_MANAGED = 0
const val MEDIA_TUNNELING_FLAG_UNSET = -1
val PROGRESSIVE_LOAD_INTERVALS = listOf("1", "16", "64", "256", PROGRESSIVE_LOAD_INTERVAL_EXOPLAYER_DEFAULT)
}
@@ -0,0 +1,151 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package net.newpipe.app.screen.settings
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.tooling.preview.PreviewWrapper
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import net.newpipe.app.composable.ListPreference
import net.newpipe.app.composable.ListPreferenceEntry
import net.newpipe.app.composable.SwitchPreference
import net.newpipe.app.composable.TopAppBar
import net.newpipe.app.navigation.Navigator
import net.newpipe.app.preferences.ExoPlayerPreferences
import net.newpipe.app.preview.ThemePreviewProvider
import net.newpipe.app.viewmodel.settings.ExoPlayerSettingsViewModel
import newpipe.shared.generated.resources.Res
import newpipe.shared.generated.resources.always_use_exoplayer_set_output_surface_workaround_summary
import newpipe.shared.generated.resources.always_use_exoplayer_set_output_surface_workaround_title
import newpipe.shared.generated.resources.disable_media_tunneling_automatic_info
import newpipe.shared.generated.resources.disable_media_tunneling_summary
import newpipe.shared.generated.resources.disable_media_tunneling_title
import newpipe.shared.generated.resources.progressive_load_interval_exoplayer_default
import newpipe.shared.generated.resources.progressive_load_interval_summary
import newpipe.shared.generated.resources.progressive_load_interval_title
import newpipe.shared.generated.resources.settings_category_exoplayer_title
import newpipe.shared.generated.resources.use_exoplayer_decoder_fallback_summary
import newpipe.shared.generated.resources.use_exoplayer_decoder_fallback_title
import org.jetbrains.compose.resources.stringResource
import org.koin.compose.koinInject
import org.koin.compose.viewmodel.koinViewModel
@Composable
fun ExoPlayerSettingsScreen(
navigator: Navigator = koinInject(),
viewModel: ExoPlayerSettingsViewModel = koinViewModel()
) {
val progressiveLoadInterval by viewModel.progressiveLoadInterval.collectAsStateWithLifecycle()
val useExoplayerDecoderFallback by viewModel.useExoplayerDecoderFallback.collectAsStateWithLifecycle()
val disableMediaTunneling by viewModel.disableMediaTunneling.collectAsStateWithLifecycle()
val mediaTunnelingAutoDisabled by viewModel.mediaTunnelingAutoDisabled.collectAsStateWithLifecycle()
val alwaysUseSetOutputSurfaceWorkaround by viewModel.alwaysUseSetOutputSurfaceWorkaround.collectAsStateWithLifecycle()
ExoPlayerSettingsScreenContent(
progressiveLoadInterval = progressiveLoadInterval,
useExoplayerDecoderFallback = useExoplayerDecoderFallback,
disableMediaTunneling = disableMediaTunneling,
mediaTunnelingAutoDisabled = mediaTunnelingAutoDisabled,
alwaysUseSetOutputSurfaceWorkaround = alwaysUseSetOutputSurfaceWorkaround,
onProgressiveLoadIntervalChange = viewModel::setProgressiveLoadInterval,
onUseExoplayerDecoderFallbackChange = viewModel::setUseExoplayerDecoderFallback,
onDisableMediaTunnelingChange = viewModel::setDisableMediaTunneling,
onAlwaysUseSetOutputSurfaceWorkaroundChange = viewModel::setAlwaysUseSetOutputSurfaceWorkaround,
onNavigateUp = { navigator.navigateUp() }
)
}
@Composable
fun ExoPlayerSettingsScreenContent(
progressiveLoadInterval: String = ExoPlayerPreferences.DEFAULT_PROGRESSIVE_LOAD_INTERVAL,
useExoplayerDecoderFallback: Boolean = ExoPlayerPreferences.DEFAULT_USE_EXOPLAYER_DECODER_FALLBACK,
disableMediaTunneling: Boolean = ExoPlayerPreferences.DEFAULT_DISABLE_MEDIA_TUNNELING,
mediaTunnelingAutoDisabled: Boolean = false,
alwaysUseSetOutputSurfaceWorkaround: Boolean = ExoPlayerPreferences.DEFAULT_ALWAYS_USE_SET_OUTPUT_SURFACE_WORKAROUND,
onProgressiveLoadIntervalChange: (String) -> Unit = {},
onUseExoplayerDecoderFallbackChange: (Boolean) -> Unit = {},
onDisableMediaTunnelingChange: (Boolean) -> Unit = {},
onAlwaysUseSetOutputSurfaceWorkaroundChange: (Boolean) -> Unit = {},
onNavigateUp: () -> Unit = {}
) {
val exoPlayerDefaultLabel = stringResource(Res.string.progressive_load_interval_exoplayer_default)
val loadIntervalEntries = ExoPlayerPreferences.PROGRESSIVE_LOAD_INTERVALS.map { value ->
ListPreferenceEntry(
value = value,
title = if (value == ExoPlayerPreferences.PROGRESSIVE_LOAD_INTERVAL_EXOPLAYER_DEFAULT) exoPlayerDefaultLabel else "$value KiB"
)
}
val selectedLoadIntervalTitle = loadIntervalEntries.firstOrNull { it.value == progressiveLoadInterval }?.title.orEmpty()
val tunnelingBaseSummary = stringResource(Res.string.disable_media_tunneling_summary)
val tunnelingSummary = if (mediaTunnelingAutoDisabled) {
tunnelingBaseSummary + " " + stringResource(Res.string.disable_media_tunneling_automatic_info)
} else {
tunnelingBaseSummary
}
Scaffold(
topBar = {
TopAppBar(
title = stringResource(Res.string.settings_category_exoplayer_title),
onNavigateUp = onNavigateUp
)
}
) { paddingValues ->
Column(
modifier = Modifier
.fillMaxSize()
.padding(top = paddingValues.calculateTopPadding())
.verticalScroll(rememberScrollState())
.padding(WindowInsets.navigationBars.asPaddingValues())
) {
ListPreference(
title = stringResource(Res.string.progressive_load_interval_title),
entries = loadIntervalEntries,
selectedValue = progressiveLoadInterval,
onValueSelected = onProgressiveLoadIntervalChange,
summary = stringResource(Res.string.progressive_load_interval_summary, selectedLoadIntervalTitle)
)
SwitchPreference(
title = stringResource(Res.string.use_exoplayer_decoder_fallback_title),
summary = stringResource(Res.string.use_exoplayer_decoder_fallback_summary),
checked = useExoplayerDecoderFallback,
onCheckedChange = onUseExoplayerDecoderFallbackChange
)
SwitchPreference(
title = stringResource(Res.string.disable_media_tunneling_title),
summary = tunnelingSummary,
checked = disableMediaTunneling,
onCheckedChange = onDisableMediaTunnelingChange
)
SwitchPreference(
title = stringResource(Res.string.always_use_exoplayer_set_output_surface_workaround_title),
summary = stringResource(Res.string.always_use_exoplayer_set_output_surface_workaround_summary),
checked = alwaysUseSetOutputSurfaceWorkaround,
onCheckedChange = onAlwaysUseSetOutputSurfaceWorkaroundChange
)
}
}
}
@PreviewWrapper(ThemePreviewProvider::class)
@PreviewLightDark
@Composable
private fun ExoPlayerSettingsScreenPreview() {
ExoPlayerSettingsScreenContent()
}
@@ -28,8 +28,10 @@ import kotlinx.coroutines.launch
import net.newpipe.app.composable.ListPreference
import net.newpipe.app.composable.ListPreferenceEntry
import net.newpipe.app.composable.PreferenceCategoryTitle
import net.newpipe.app.composable.PreferenceRow
import net.newpipe.app.composable.SwitchPreference
import net.newpipe.app.composable.TopAppBar
import net.newpipe.app.navigation.Destination
import net.newpipe.app.navigation.Navigator
import net.newpipe.app.preferences.VideoAudioPreferences
import net.newpipe.app.preview.ThemePreviewProvider
@@ -86,6 +88,8 @@ import newpipe.shared.generated.resources.right_gesture_control_title
import newpipe.shared.generated.resources.seconds
import newpipe.shared.generated.resources.seek_duration_title
import newpipe.shared.generated.resources.seekbar_preview_thumbnail_title
import newpipe.shared.generated.resources.settings_category_exoplayer_summary
import newpipe.shared.generated.resources.settings_category_exoplayer_title
import newpipe.shared.generated.resources.settings_category_player_behavior_title
import newpipe.shared.generated.resources.settings_category_player_title
import newpipe.shared.generated.resources.settings_category_video_audio_title
@@ -206,6 +210,7 @@ fun VideoAudioSettingsScreen(
onSeekDurationChange = viewModel::setSeekDuration,
onClearQueueConfirmationChange = viewModel::setClearQueueConfirmation,
onIgnoreHardwareMediaButtonsChange = viewModel::setIgnoreHardwareMediaButtons,
onOpenExoPlayerSettings = { navigator.navigateTo(Destination.ExoPlayerSettings) },
onNavigateUp = { navigator.navigateUp() }
)
}
@@ -265,6 +270,7 @@ fun VideoAudioSettingsScreenContent(
onSeekDurationChange: (String) -> Unit = {},
onClearQueueConfirmationChange: (Boolean) -> Unit = {},
onIgnoreHardwareMediaButtonsChange: (Boolean) -> Unit = {},
onOpenExoPlayerSettings: () -> Unit = {},
onNavigateUp: () -> Unit = {}
) {
val scope = rememberCoroutineScope()
@@ -393,7 +399,11 @@ fun VideoAudioSettingsScreenContent(
onCheckedChange = onPreferDescriptiveAudioChange
)
// TODO: ExoPlayer settings sub-screen link goes here once that screen is migrated.
PreferenceRow(
title = stringResource(Res.string.settings_category_exoplayer_title),
summary = stringResource(Res.string.settings_category_exoplayer_summary),
onClick = onOpenExoPlayerSettings
)
PreferenceCategoryTitle(title = stringResource(Res.string.settings_category_player_title))
SwitchPreference(
@@ -497,8 +507,6 @@ fun VideoAudioSettingsScreenContent(
summary = stringResource(Res.string.use_inexact_seek_summary),
checked = useInexactSeek,
onCheckedChange = { checked ->
// The view model applies the same adjustment. this only decides whether to
// tell the user about it, mirroring the legacy toast.
VideoAudioPreferences.adjustedSeekDurationMs(seekDuration, checked)?.let { adjustedMs ->
val newSeconds = VideoAudioPreferences.seekDurationSeconds(adjustedMs)
scope.launch {
@@ -0,0 +1,68 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package net.newpipe.app.viewmodel.settings
import androidx.lifecycle.ViewModel
import com.russhwolf.settings.Settings
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import net.newpipe.app.preferences.ExoPlayerPreferences
import org.koin.core.annotation.KoinViewModel
@KoinViewModel
class ExoPlayerSettingsViewModel(private val settings: Settings) : ViewModel() {
val progressiveLoadInterval: StateFlow<String>
field = stringFlow(ExoPlayerPreferences.KEY_PROGRESSIVE_LOAD_INTERVAL, ExoPlayerPreferences.DEFAULT_PROGRESSIVE_LOAD_INTERVAL)
val useExoplayerDecoderFallback: StateFlow<Boolean>
field = booleanFlow(ExoPlayerPreferences.KEY_USE_EXOPLAYER_DECODER_FALLBACK, ExoPlayerPreferences.DEFAULT_USE_EXOPLAYER_DECODER_FALLBACK)
val disableMediaTunneling: StateFlow<Boolean>
field = booleanFlow(ExoPlayerPreferences.KEY_DISABLE_MEDIA_TUNNELING, ExoPlayerPreferences.DEFAULT_DISABLE_MEDIA_TUNNELING)
val alwaysUseSetOutputSurfaceWorkaround: StateFlow<Boolean>
field = booleanFlow(ExoPlayerPreferences.KEY_ALWAYS_USE_SET_OUTPUT_SURFACE_WORKAROUND, ExoPlayerPreferences.DEFAULT_ALWAYS_USE_SET_OUTPUT_SURFACE_WORKAROUND)
val mediaTunnelingAutoDisabled: StateFlow<Boolean>
field = MutableStateFlow(
settings.getInt(
ExoPlayerPreferences.KEY_DISABLED_MEDIA_TUNNELING_AUTOMATICALLY,
ExoPlayerPreferences.MEDIA_TUNNELING_FLAG_UNSET
) == ExoPlayerPreferences.MEDIA_TUNNELING_AUTO_DISABLED
)
fun setProgressiveLoadInterval(value: String) = progressiveLoadInterval.persist(ExoPlayerPreferences.KEY_PROGRESSIVE_LOAD_INTERVAL, value)
fun setUseExoplayerDecoderFallback(value: Boolean) = useExoplayerDecoderFallback.persist(ExoPlayerPreferences.KEY_USE_EXOPLAYER_DECODER_FALLBACK, value)
fun setDisableMediaTunneling(value: Boolean) {
disableMediaTunneling.persist(ExoPlayerPreferences.KEY_DISABLE_MEDIA_TUNNELING, value)
if (!value) {
settings.putInt(
ExoPlayerPreferences.KEY_DISABLED_MEDIA_TUNNELING_AUTOMATICALLY,
ExoPlayerPreferences.MEDIA_TUNNELING_USER_MANAGED
)
mediaTunnelingAutoDisabled.value = false
}
}
fun setAlwaysUseSetOutputSurfaceWorkaround(value: Boolean) = alwaysUseSetOutputSurfaceWorkaround.persist(ExoPlayerPreferences.KEY_ALWAYS_USE_SET_OUTPUT_SURFACE_WORKAROUND, value)
private fun stringFlow(key: String, defaultValue: String) = MutableStateFlow(settings.getString(key, defaultValue))
private fun booleanFlow(key: String, defaultValue: Boolean) = MutableStateFlow(settings.getBoolean(key, defaultValue))
private fun MutableStateFlow<String>.persist(key: String, newValue: String) {
settings.putString(key, newValue)
value = newValue
}
private fun MutableStateFlow<Boolean>.persist(key: String, newValue: Boolean) {
settings.putBoolean(key, newValue)
value = newValue
}
}
@@ -0,0 +1,67 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package net.newpipe.app.screen.settings
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performScrollTo
import androidx.compose.ui.test.v2.runComposeUiTest
import com.russhwolf.settings.MapSettings
import com.russhwolf.settings.Settings
import kotlin.test.Test
import net.newpipe.app.extensions.withKoin
import newpipe.shared.generated.resources.Res
import newpipe.shared.generated.resources.disable_media_tunneling_automatic_info
import newpipe.shared.generated.resources.progressive_load_interval_summary
import newpipe.shared.generated.resources.progressive_load_interval_title
import newpipe.shared.generated.resources.settings_category_exoplayer_title
import org.jetbrains.compose.resources.getString
import org.koin.dsl.module
@OptIn(ExperimentalTestApi::class)
class ExoPlayerSettingsScreenTest {
private val emptySettings = module {
single<Settings> { MapSettings() }
}
@Test
fun rendersTitleAndLoadIntervalRow() = runComposeUiTest {
withKoin(
modules = listOf(emptySettings),
content = { ExoPlayerSettingsScreenContent() },
onContent = {
onNodeWithText(getString(Res.string.settings_category_exoplayer_title)).assertIsDisplayed()
onNodeWithText(getString(Res.string.progressive_load_interval_title)).assertIsDisplayed()
}
)
}
@Test
fun loadIntervalSummaryShowsSelectedEntryLabel() = runComposeUiTest {
withKoin(
modules = listOf(emptySettings),
content = { ExoPlayerSettingsScreenContent() },
onContent = {
onNodeWithText(getString(Res.string.progressive_load_interval_summary, "64 KiB")).assertIsDisplayed()
}
)
}
@Test
fun mediaTunnelingInfoShownOnlyWhenAutoDisabled() = runComposeUiTest {
withKoin(
modules = listOf(emptySettings),
content = { ExoPlayerSettingsScreenContent(mediaTunnelingAutoDisabled = true) },
onContent = {
onNodeWithText(getString(Res.string.disable_media_tunneling_automatic_info), substring = true)
.performScrollTo()
.assertIsDisplayed()
}
)
}
}
@@ -18,6 +18,7 @@ import net.newpipe.app.preferences.VideoAudioPreferences
import newpipe.shared.generated.resources.Res
import newpipe.shared.generated.resources.best_resolution
import newpipe.shared.generated.resources.default_resolution_title
import newpipe.shared.generated.resources.settings_category_exoplayer_title
import newpipe.shared.generated.resources.settings_category_player_title
import newpipe.shared.generated.resources.settings_category_video_audio_title
import org.jetbrains.compose.resources.getString
@@ -67,4 +68,17 @@ class VideoAudioSettingsScreenTest {
}
)
}
@Test
fun rendersExoPlayerSettingsLink() = runComposeUiTest {
withKoin(
modules = listOf(emptySettings),
content = { VideoAudioSettingsScreenContent() },
onContent = {
onNodeWithText(getString(Res.string.settings_category_exoplayer_title))
.performScrollTo()
.assertIsDisplayed()
}
)
}
}