mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-27 15:30:31 +05:30
Merge branch 'master' into KotlinX_Serialization
# Conflicts: # gradle/libs.versions.toml
This commit is contained in:
commit
187c7ac0e9
@ -275,7 +275,7 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions {
|
|||||||
*/
|
*/
|
||||||
private fun showBottomBar() {
|
private fun showBottomBar() {
|
||||||
if (this::playerBinding.isInitialized && !binding.player.isPlayerLocked) {
|
if (this::playerBinding.isInitialized && !binding.player.isPlayerLocked) {
|
||||||
playerBinding.exoBottomBar.visibility = View.VISIBLE
|
playerBinding.bottomBar.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
handler.postDelayed(this::showBottomBar, 100)
|
handler.postDelayed(this::showBottomBar, 100)
|
||||||
}
|
}
|
||||||
@ -817,11 +817,6 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions {
|
|||||||
|
|
||||||
private fun prepareExoPlayerView() {
|
private fun prepareExoPlayerView() {
|
||||||
exoPlayerView.apply {
|
exoPlayerView.apply {
|
||||||
setShowSubtitleButton(false)
|
|
||||||
setShowNextButton(false)
|
|
||||||
setShowPreviousButton(false)
|
|
||||||
// controllerShowTimeoutMs = 1500
|
|
||||||
controllerHideOnTouch = true
|
|
||||||
useController = false
|
useController = false
|
||||||
player = exoPlayer
|
player = exoPlayer
|
||||||
}
|
}
|
||||||
@ -851,7 +846,9 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions {
|
|||||||
this,
|
this,
|
||||||
doubleTapOverlayBinding,
|
doubleTapOverlayBinding,
|
||||||
playerGestureControlsViewBinding,
|
playerGestureControlsViewBinding,
|
||||||
trackSelector
|
trackSelector,
|
||||||
|
viewModel,
|
||||||
|
viewLifecycleOwner
|
||||||
)
|
)
|
||||||
|
|
||||||
binding.apply {
|
binding.apply {
|
||||||
@ -1498,7 +1495,7 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions {
|
|||||||
fun getPipParams(): PictureInPictureParams = PictureInPictureParams.Builder()
|
fun getPipParams(): PictureInPictureParams = PictureInPictureParams.Builder()
|
||||||
.setActions(PlayerHelper.getPiPModeActions(requireActivity(), exoPlayer.isPlaying))
|
.setActions(PlayerHelper.getPiPModeActions(requireActivity(), exoPlayer.isPlaying))
|
||||||
.apply {
|
.apply {
|
||||||
if (SDK_INT >= Build.VERSION_CODES.S) {
|
if (SDK_INT >= Build.VERSION_CODES.S && PlayerHelper.pipEnabled) {
|
||||||
setAutoEnterEnabled(true)
|
setAutoEnterEnabled(true)
|
||||||
}
|
}
|
||||||
if (exoPlayer.isPlaying) {
|
if (exoPlayer.isPlaying) {
|
||||||
|
@ -14,6 +14,7 @@ import android.widget.FrameLayout
|
|||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
import com.github.libretube.constants.PreferenceKeys
|
import com.github.libretube.constants.PreferenceKeys
|
||||||
import com.github.libretube.databinding.DoubleTapOverlayBinding
|
import com.github.libretube.databinding.DoubleTapOverlayBinding
|
||||||
@ -27,6 +28,7 @@ import com.github.libretube.ui.base.BaseActivity
|
|||||||
import com.github.libretube.ui.interfaces.OnlinePlayerOptions
|
import com.github.libretube.ui.interfaces.OnlinePlayerOptions
|
||||||
import com.github.libretube.ui.interfaces.PlayerGestureOptions
|
import com.github.libretube.ui.interfaces.PlayerGestureOptions
|
||||||
import com.github.libretube.ui.interfaces.PlayerOptions
|
import com.github.libretube.ui.interfaces.PlayerOptions
|
||||||
|
import com.github.libretube.ui.models.PlayerViewModel
|
||||||
import com.github.libretube.ui.sheets.BaseBottomSheet
|
import com.github.libretube.ui.sheets.BaseBottomSheet
|
||||||
import com.github.libretube.ui.sheets.PlaybackSpeedSheet
|
import com.github.libretube.ui.sheets.PlaybackSpeedSheet
|
||||||
import com.github.libretube.util.AudioHelper
|
import com.github.libretube.util.AudioHelper
|
||||||
@ -61,6 +63,7 @@ internal class CustomExoPlayerView(
|
|||||||
private lateinit var brightnessHelper: BrightnessHelper
|
private lateinit var brightnessHelper: BrightnessHelper
|
||||||
private lateinit var audioHelper: AudioHelper
|
private lateinit var audioHelper: AudioHelper
|
||||||
private var doubleTapOverlayBinding: DoubleTapOverlayBinding? = null
|
private var doubleTapOverlayBinding: DoubleTapOverlayBinding? = null
|
||||||
|
private var playerViewModel: PlayerViewModel? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Objects from the parent fragment
|
* Objects from the parent fragment
|
||||||
@ -79,6 +82,9 @@ internal class CustomExoPlayerView(
|
|||||||
|
|
||||||
private var resizeModePref = PlayerHelper.resizeModePref
|
private var resizeModePref = PlayerHelper.resizeModePref
|
||||||
|
|
||||||
|
private val windowHelper
|
||||||
|
get() = (context as? MainActivity)?.windowHelper
|
||||||
|
|
||||||
private val supportFragmentManager
|
private val supportFragmentManager
|
||||||
get() = (context as BaseActivity).supportFragmentManager
|
get() = (context as BaseActivity).supportFragmentManager
|
||||||
|
|
||||||
@ -89,16 +95,23 @@ internal class CustomExoPlayerView(
|
|||||||
// saved to only load the playback speed once (for the first video)
|
// saved to only load the playback speed once (for the first video)
|
||||||
private var playbackPrefSet = false
|
private var playbackPrefSet = false
|
||||||
|
|
||||||
|
private val hideControllerRunnable = Runnable {
|
||||||
|
hideController()
|
||||||
|
}
|
||||||
|
|
||||||
fun initialize(
|
fun initialize(
|
||||||
playerViewInterface: OnlinePlayerOptions?,
|
playerViewInterface: OnlinePlayerOptions?,
|
||||||
doubleTapOverlayBinding: DoubleTapOverlayBinding,
|
doubleTapOverlayBinding: DoubleTapOverlayBinding,
|
||||||
playerGestureControlsViewBinding: PlayerGestureControlsViewBinding,
|
playerGestureControlsViewBinding: PlayerGestureControlsViewBinding,
|
||||||
trackSelector: TrackSelector?
|
trackSelector: TrackSelector?,
|
||||||
|
playerViewModel: PlayerViewModel? = null,
|
||||||
|
viewLifecycleOwner: LifecycleOwner? = null
|
||||||
) {
|
) {
|
||||||
this.playerOptionsInterface = playerViewInterface
|
this.playerOptionsInterface = playerViewInterface
|
||||||
this.doubleTapOverlayBinding = doubleTapOverlayBinding
|
this.doubleTapOverlayBinding = doubleTapOverlayBinding
|
||||||
this.trackSelector = trackSelector
|
this.trackSelector = trackSelector
|
||||||
this.gestureViewBinding = playerGestureControlsViewBinding
|
this.gestureViewBinding = playerGestureControlsViewBinding
|
||||||
|
this.playerViewModel = playerViewModel
|
||||||
this.playerGestureController = PlayerGestureController(context as BaseActivity, this)
|
this.playerGestureController = PlayerGestureController(context as BaseActivity, this)
|
||||||
this.brightnessHelper = BrightnessHelper(context as Activity)
|
this.brightnessHelper = BrightnessHelper(context as Activity)
|
||||||
this.audioHelper = AudioHelper(context)
|
this.audioHelper = AudioHelper(context)
|
||||||
@ -111,6 +124,9 @@ internal class CustomExoPlayerView(
|
|||||||
applyCaptionsStyle()
|
applyCaptionsStyle()
|
||||||
initializeAdvancedOptions(context)
|
initializeAdvancedOptions(context)
|
||||||
|
|
||||||
|
// don't let the player view hide its controls automatically
|
||||||
|
controllerShowTimeoutMs = -1
|
||||||
|
|
||||||
if (!playbackPrefSet) {
|
if (!playbackPrefSet) {
|
||||||
player?.playbackParameters = PlaybackParameters(
|
player?.playbackParameters = PlaybackParameters(
|
||||||
PlayerHelper.playbackSpeed.toFloat(),
|
PlayerHelper.playbackSpeed.toFloat(),
|
||||||
@ -179,6 +195,14 @@ internal class CustomExoPlayerView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
playerViewModel?.isFullscreen?.observe(viewLifecycleOwner!!) { isFullscreen ->
|
||||||
|
if (isFullscreen) {
|
||||||
|
windowHelper?.setFullscreen()
|
||||||
|
} else {
|
||||||
|
windowHelper?.unsetFullscreen()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updatePlayPauseButton() {
|
private fun updatePlayPauseButton() {
|
||||||
@ -195,11 +219,24 @@ internal class CustomExoPlayerView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun hideController() {
|
override fun hideController() {
|
||||||
if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
// remove the callback to hide the controller
|
||||||
// hide all the navigation bars that potentially could have been reopened manually ba the user
|
handler.removeCallbacks(hideControllerRunnable)
|
||||||
(context as? MainActivity)?.windowHelper?.setFullscreen()
|
|
||||||
}
|
|
||||||
super.hideController()
|
super.hideController()
|
||||||
|
|
||||||
|
// hide system bars if in fullscreen
|
||||||
|
playerViewModel?.let {
|
||||||
|
if (it.isFullscreen.value == true) {
|
||||||
|
windowHelper?.setFullscreen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showController() {
|
||||||
|
// remove the previous callback from the queue to prevent a flashing behavior
|
||||||
|
handler.removeCallbacks(hideControllerRunnable)
|
||||||
|
// automatically hide the controller after 2 seconds
|
||||||
|
handler.postDelayed(hideControllerRunnable, 2000)
|
||||||
|
super.showController()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTouchEvent(event: MotionEvent): Boolean {
|
override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||||
@ -327,7 +364,7 @@ internal class CustomExoPlayerView(
|
|||||||
|
|
||||||
binding.exoTopBarRight.visibility = visibility
|
binding.exoTopBarRight.visibility = visibility
|
||||||
binding.exoCenterControls.visibility = visibility
|
binding.exoCenterControls.visibility = visibility
|
||||||
binding.exoBottomBar.visibility = visibility
|
binding.bottomBar.visibility = visibility
|
||||||
binding.closeImageButton.visibility = visibility
|
binding.closeImageButton.visibility = visibility
|
||||||
binding.exoTitle.visibility = visibility
|
binding.exoTitle.visibility = visibility
|
||||||
binding.playPauseBTN.visibility = visibility
|
binding.playPauseBTN.visibility = visibility
|
||||||
@ -554,27 +591,37 @@ internal class CustomExoPlayerView(
|
|||||||
it.layoutParams = params
|
it.layoutParams = params
|
||||||
}
|
}
|
||||||
|
|
||||||
// add a margin to the top and the bottom bar in landscape mode for notches
|
// add padding to the top bar to not overlap the status bar
|
||||||
val newMargin = if (
|
binding.topBar.let {
|
||||||
newConfig?.orientation == Configuration.ORIENTATION_LANDSCAPE
|
setPadding(
|
||||||
) {
|
it.paddingLeft,
|
||||||
LANDSCAPE_MARGIN_HORIZONTAL
|
(if (newConfig?.orientation == Configuration.ORIENTATION_LANDSCAPE) 25 else 5).toPixel().toInt(),
|
||||||
} else {
|
it.paddingRight,
|
||||||
0
|
it.paddingBottom
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
listOf(binding.exoTopBar, binding.exoBottomBar).forEach {
|
// don't add extra padding if there's no cutout
|
||||||
val params = it.layoutParams as MarginLayoutParams
|
if ((context as? MainActivity)?.windowHelper?.hasCutout() == false) return
|
||||||
params.marginStart = newMargin
|
|
||||||
params.marginEnd = newMargin
|
// add a margin to the top and the bottom bar in landscape mode for notches
|
||||||
it.layoutParams = params
|
val newMargin = when (newConfig?.orientation) {
|
||||||
|
Configuration.ORIENTATION_LANDSCAPE -> LANDSCAPE_MARGIN_HORIZONTAL
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
|
||||||
|
listOf(binding.topBar, binding.bottomBar).forEach {
|
||||||
|
it.layoutParams = (it.layoutParams as MarginLayoutParams).apply {
|
||||||
|
marginStart = newMargin
|
||||||
|
marginEnd = newMargin
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the captions style according to the users preferences
|
* Load the captions style according to the users preferences
|
||||||
*/
|
*/
|
||||||
fun applyCaptionsStyle() {
|
private fun applyCaptionsStyle() {
|
||||||
val captionStyle = PlayerHelper.getCaptionStyle(context)
|
val captionStyle = PlayerHelper.getCaptionStyle(context)
|
||||||
subtitleView?.apply {
|
subtitleView?.apply {
|
||||||
setApplyEmbeddedFontSizes(false)
|
setApplyEmbeddedFontSizes(false)
|
||||||
@ -662,6 +709,6 @@ internal class CustomExoPlayerView(
|
|||||||
companion object {
|
companion object {
|
||||||
private const val SUBTITLE_BOTTOM_PADDING_FRACTION = 0.158f
|
private const val SUBTITLE_BOTTOM_PADDING_FRACTION = 0.158f
|
||||||
private const val ANIMATION_DURATION = 100L
|
private const val ANIMATION_DURATION = 100L
|
||||||
private val LANDSCAPE_MARGIN_HORIZONTAL = (30).toPixel().toInt()
|
private val LANDSCAPE_MARGIN_HORIZONTAL = (20).toPixel().toInt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,4 +46,12 @@ class WindowHelper(private val activity: BaseActivity) {
|
|||||||
|
|
||||||
window.clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
|
window.clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun hasCutout(): Boolean {
|
||||||
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
|
activity.window.decorView.rootWindowInsets.displayCutout != null
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
android:background="@color/exo_black_opacity_60" />
|
android:background="@color/exo_black_opacity_60" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/exo_top_bar"
|
android:id="@+id/top_bar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="top"
|
android:layout_gravity="top"
|
||||||
@ -190,7 +190,7 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@id/exo_bottom_bar"
|
android:id="@+id/bottom_bar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom"
|
android:layout_gravity="bottom"
|
||||||
@ -301,7 +301,7 @@
|
|||||||
android:layout_marginBottom="10dp">
|
android:layout_marginBottom="10dp">
|
||||||
|
|
||||||
<com.github.libretube.ui.views.MarkableTimeBar
|
<com.github.libretube.ui.views.MarkableTimeBar
|
||||||
android:id="@id/exo_progress"
|
android:id="@+id/exo_progress"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="16dp"
|
android:layout_height="16dp"
|
||||||
app:bar_height="2dp"
|
app:bar_height="2dp"
|
||||||
|
@ -448,4 +448,6 @@
|
|||||||
<string name="audio_only_mode_summary">Proměňte LibreTube v hudební přehrávač.</string>
|
<string name="audio_only_mode_summary">Proměňte LibreTube v hudební přehrávač.</string>
|
||||||
<string name="sleep_timer">Časovač spánku</string>
|
<string name="sleep_timer">Časovač spánku</string>
|
||||||
<string name="skip_silence">Přeskočit ticho</string>
|
<string name="skip_silence">Přeskočit ticho</string>
|
||||||
|
<string name="help">Nápověda</string>
|
||||||
|
<string name="faq">Často kladené dotazy</string>
|
||||||
</resources>
|
</resources>
|
@ -446,4 +446,8 @@
|
|||||||
<string name="resume">Lanjutkan</string>
|
<string name="resume">Lanjutkan</string>
|
||||||
<string name="download_completed">Unduhan selesai</string>
|
<string name="download_completed">Unduhan selesai</string>
|
||||||
<string name="concurrent_downloads">Unduhan berlangsungan maksimal</string>
|
<string name="concurrent_downloads">Unduhan berlangsungan maksimal</string>
|
||||||
|
<string name="sleep_timer">Pewaktu tidur</string>
|
||||||
|
<string name="skip_silence">Lewati keheningan</string>
|
||||||
|
<string name="help">Bantuan</string>
|
||||||
|
<string name="faq">SSD</string>
|
||||||
</resources>
|
</resources>
|
@ -429,4 +429,25 @@
|
|||||||
<string name="playlistUrl">Spilleliste-nettadresse</string>
|
<string name="playlistUrl">Spilleliste-nettadresse</string>
|
||||||
<string name="pause_on_quit">Pause ved avslutning</string>
|
<string name="pause_on_quit">Pause ved avslutning</string>
|
||||||
<string name="shuffle">Stokk om</string>
|
<string name="shuffle">Stokk om</string>
|
||||||
|
<string name="rewind">Spol tilbake</string>
|
||||||
|
<string name="pause">Pause</string>
|
||||||
|
<string name="alternative_pip_controls">Alternative BiB-kontroller</string>
|
||||||
|
<string name="alternative_pip_controls_summary">Vis kun lyd og hopp over kontroller i PiP istedenfor spoling tilbake og forover</string>
|
||||||
|
<string name="audio_player">Lydspiller</string>
|
||||||
|
<string name="audio_only_mode">Modus for kun lyd</string>
|
||||||
|
<string name="no_subtitle">Ingen undertekst</string>
|
||||||
|
<string name="download_paused">Nedlasting pauset</string>
|
||||||
|
<string name="download_completed">Nedlasting fullført</string>
|
||||||
|
<string name="concurrent_downloads">Maks. samtidige nedlastinger</string>
|
||||||
|
<string name="concurrent_downloads_limit_reached">Utfører maks. antall samtidige nedlastinger</string>
|
||||||
|
<string name="unknown">Ukjent</string>
|
||||||
|
<string name="resume">Fortsett</string>
|
||||||
|
<string name="forward">Spol forover</string>
|
||||||
|
<string name="audio_only_mode_summary">Gjør LibreTube til en musikkspiller.</string>
|
||||||
|
<string name="sleep_timer">Søvntidsur</string>
|
||||||
|
<string name="skip_silence">Hopp over stillhet</string>
|
||||||
|
<string name="help">Hjelp</string>
|
||||||
|
<string name="faq">O-S-S</string>
|
||||||
|
<string name="add_to_bookmarks">Bokmerk</string>
|
||||||
|
<string name="remove_bookmark">Fjern bokmerke</string>
|
||||||
</resources>
|
</resources>
|
@ -448,4 +448,6 @@
|
|||||||
<string name="audio_only_mode">Tryb „tylko dźwięk”</string>
|
<string name="audio_only_mode">Tryb „tylko dźwięk”</string>
|
||||||
<string name="sleep_timer">Wyłącz po czasie</string>
|
<string name="sleep_timer">Wyłącz po czasie</string>
|
||||||
<string name="skip_silence">Pomiń cisze</string>
|
<string name="skip_silence">Pomiń cisze</string>
|
||||||
|
<string name="help">Pomoc</string>
|
||||||
|
<string name="faq">Często zadawane pytania</string>
|
||||||
</resources>
|
</resources>
|
@ -446,4 +446,8 @@
|
|||||||
<string name="resume">Продолжить</string>
|
<string name="resume">Продолжить</string>
|
||||||
<string name="audio_only_mode">Режим только аудио</string>
|
<string name="audio_only_mode">Режим только аудио</string>
|
||||||
<string name="audio_only_mode_summary">Превратите LibreTube в музыкальный проигрыватель.</string>
|
<string name="audio_only_mode_summary">Превратите LibreTube в музыкальный проигрыватель.</string>
|
||||||
|
<string name="sleep_timer">Таймер сна</string>
|
||||||
|
<string name="skip_silence">Пропускать тишину</string>
|
||||||
|
<string name="help">Помощь</string>
|
||||||
|
<string name="faq">FAQ</string>
|
||||||
</resources>
|
</resources>
|
@ -386,7 +386,7 @@
|
|||||||
<string name="open_queue_from_notification">Bildirimden kuyruğu aç</string>
|
<string name="open_queue_from_notification">Bildirimden kuyruğu aç</string>
|
||||||
<string name="trends">Trendler</string>
|
<string name="trends">Trendler</string>
|
||||||
<string name="featured">Öne Çıkanlar</string>
|
<string name="featured">Öne Çıkanlar</string>
|
||||||
<string name="trending">Şu anda trend olan şey</string>
|
<string name="trending">Şu anda popüler</string>
|
||||||
<string name="bookmarks">Yer imleri</string>
|
<string name="bookmarks">Yer imleri</string>
|
||||||
<string name="bookmark">Yer imi</string>
|
<string name="bookmark">Yer imi</string>
|
||||||
<string name="clear_bookmarks">Yer imlerini temizle</string>
|
<string name="clear_bookmarks">Yer imlerini temizle</string>
|
||||||
|
@ -447,7 +447,7 @@
|
|||||||
<string name="download_completed">Завантаження завершено</string>
|
<string name="download_completed">Завантаження завершено</string>
|
||||||
<string name="resume">Продовжити</string>
|
<string name="resume">Продовжити</string>
|
||||||
<string name="help">Довідка</string>
|
<string name="help">Довідка</string>
|
||||||
<string name="faq">ЧаП</string>
|
<string name="faq">ЧаПи</string>
|
||||||
<string name="sleep_timer">Таймер сну</string>
|
<string name="sleep_timer">Таймер сну</string>
|
||||||
<string name="skip_silence">Пропускати тишу</string>
|
<string name="skip_silence">Пропускати тишу</string>
|
||||||
</resources>
|
</resources>
|
@ -446,4 +446,8 @@
|
|||||||
<string name="unknown">未知</string>
|
<string name="unknown">未知</string>
|
||||||
<string name="resume">恢复</string>
|
<string name="resume">恢复</string>
|
||||||
<string name="audio_only_mode">仅音频模式</string>
|
<string name="audio_only_mode">仅音频模式</string>
|
||||||
|
<string name="sleep_timer">睡眠定时器</string>
|
||||||
|
<string name="skip_silence">跳过静音</string>
|
||||||
|
<string name="help">帮助</string>
|
||||||
|
<string name="faq">常见问题</string>
|
||||||
</resources>
|
</resources>
|
@ -11,7 +11,7 @@ espresso = "3.5.1"
|
|||||||
workRuntime = "2.7.1"
|
workRuntime = "2.7.1"
|
||||||
exoplayer = "2.18.2"
|
exoplayer = "2.18.2"
|
||||||
retrofit = "2.9.0"
|
retrofit = "2.9.0"
|
||||||
desugaring = "1.2.2"
|
desugaring = "2.0.0"
|
||||||
cronetEmbedded = "108.5359.79"
|
cronetEmbedded = "108.5359.79"
|
||||||
cronetOkHttp = "0.1.0"
|
cronetOkHttp = "0.1.0"
|
||||||
coil = "2.2.2"
|
coil = "2.2.2"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user