mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-29 08:20:32 +05:30
Merge pull request #4277 from Bnyro/master
chore: fix project formatting
This commit is contained in:
commit
06bf6eefdb
@ -4,7 +4,6 @@ import android.app.Application
|
|||||||
import androidx.core.app.NotificationChannelCompat
|
import androidx.core.app.NotificationChannelCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.work.ExistingPeriodicWorkPolicy
|
import androidx.work.ExistingPeriodicWorkPolicy
|
||||||
import com.github.libretube.api.RetrofitInstance
|
|
||||||
import com.github.libretube.constants.BACKGROUND_CHANNEL_ID
|
import com.github.libretube.constants.BACKGROUND_CHANNEL_ID
|
||||||
import com.github.libretube.constants.DOWNLOAD_CHANNEL_ID
|
import com.github.libretube.constants.DOWNLOAD_CHANNEL_ID
|
||||||
import com.github.libretube.constants.PUSH_CHANNEL_ID
|
import com.github.libretube.constants.PUSH_CHANNEL_ID
|
||||||
|
@ -11,10 +11,12 @@ import retrofit2.create
|
|||||||
object RetrofitInstance {
|
object RetrofitInstance {
|
||||||
private val url get() = PreferenceHelper.getString(PreferenceKeys.FETCH_INSTANCE, PIPED_API_URL)
|
private val url get() = PreferenceHelper.getString(PreferenceKeys.FETCH_INSTANCE, PIPED_API_URL)
|
||||||
private val authUrl
|
private val authUrl
|
||||||
get() = when (PreferenceHelper.getBoolean(
|
get() = when (
|
||||||
PreferenceKeys.AUTH_INSTANCE_TOGGLE,
|
PreferenceHelper.getBoolean(
|
||||||
false
|
PreferenceKeys.AUTH_INSTANCE_TOGGLE,
|
||||||
)) {
|
false
|
||||||
|
)
|
||||||
|
) {
|
||||||
true -> PreferenceHelper.getString(
|
true -> PreferenceHelper.getString(
|
||||||
PreferenceKeys.AUTH_INSTANCE,
|
PreferenceKeys.AUTH_INSTANCE,
|
||||||
PIPED_API_URL
|
PIPED_API_URL
|
||||||
|
@ -8,4 +8,4 @@ data class DeArrowContent(
|
|||||||
val titles: List<DeArrowTitle>,
|
val titles: List<DeArrowTitle>,
|
||||||
val randomTime: Float?,
|
val randomTime: Float?,
|
||||||
val videoDuration: Float?
|
val videoDuration: Float?
|
||||||
)
|
)
|
||||||
|
@ -10,4 +10,4 @@ data class DeArrowThumbnail(
|
|||||||
val thumbnail: String? = null,
|
val thumbnail: String? = null,
|
||||||
val timestamp: Float?,
|
val timestamp: Float?,
|
||||||
val votes: Int
|
val votes: Int
|
||||||
)
|
)
|
||||||
|
@ -9,4 +9,4 @@ data class DeArrowTitle(
|
|||||||
val original: Boolean,
|
val original: Boolean,
|
||||||
val title: String,
|
val title: String,
|
||||||
val votes: Int
|
val votes: Int
|
||||||
)
|
)
|
||||||
|
@ -20,15 +20,15 @@ data class WatchHistoryItem(
|
|||||||
@ColumnInfo var thumbnailUrl: String? = null,
|
@ColumnInfo var thumbnailUrl: String? = null,
|
||||||
@ColumnInfo val duration: Long? = null
|
@ColumnInfo val duration: Long? = null
|
||||||
) {
|
) {
|
||||||
fun toStreamItem() = StreamItem(
|
fun toStreamItem() = StreamItem(
|
||||||
url = videoId,
|
url = videoId,
|
||||||
type = "stream",
|
type = "stream",
|
||||||
title = title,
|
title = title,
|
||||||
thumbnail = thumbnailUrl,
|
thumbnail = thumbnailUrl,
|
||||||
uploaderName = uploader,
|
uploaderName = uploader,
|
||||||
uploaded = uploadDate?.toMillis(),
|
uploaded = uploadDate?.toMillis(),
|
||||||
uploaderAvatar = uploaderAvatar,
|
uploaderAvatar = uploaderAvatar,
|
||||||
uploaderUrl = uploaderUrl,
|
uploaderUrl = uploaderUrl,
|
||||||
duration = duration
|
duration = duration
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,9 @@ fun Int.formatAsFileSize(): String {
|
|||||||
fun Long.formatAsFileSize(): String {
|
fun Long.formatAsFileSize(): String {
|
||||||
return log2(if (this != 0L) toDouble() else 1.0).toInt().div(10).let {
|
return log2(if (this != 0L) toDouble() else 1.0).toInt().div(10).let {
|
||||||
val precision = when (it) {
|
val precision = when (it) {
|
||||||
0 -> 0; 1 -> 1; else -> 2
|
0 -> 0
|
||||||
|
1 -> 1
|
||||||
|
else -> 2
|
||||||
}
|
}
|
||||||
val prefix = arrayOf("", "K", "M", "G", "T", "P", "E", "Z", "Y")
|
val prefix = arrayOf("", "K", "M", "G", "T", "P", "E", "Z", "Y")
|
||||||
String.format("%.${precision}f ${prefix[it]}B", toDouble() / 2.0.pow(it * 10.0))
|
String.format("%.${precision}f ${prefix[it]}B", toDouble() / 2.0.pow(it * 10.0))
|
||||||
|
@ -4,4 +4,4 @@ import kotlinx.datetime.LocalDate
|
|||||||
import kotlinx.datetime.TimeZone
|
import kotlinx.datetime.TimeZone
|
||||||
import kotlinx.datetime.atStartOfDayIn
|
import kotlinx.datetime.atStartOfDayIn
|
||||||
|
|
||||||
fun LocalDate.toMillis() = this.atStartOfDayIn(TimeZone.UTC).toEpochMilliseconds()
|
fun LocalDate.toMillis() = this.atStartOfDayIn(TimeZone.UTC).toEpochMilliseconds()
|
||||||
|
@ -92,7 +92,10 @@ object BackupHelper {
|
|||||||
is Int -> {
|
is Int -> {
|
||||||
when {
|
when {
|
||||||
// we only use integers for SponsorBlock colors and the start fragment
|
// we only use integers for SponsorBlock colors and the start fragment
|
||||||
key == PreferenceKeys.START_FRAGMENT || key.orEmpty().contains("_color") -> putInt(key, value)
|
key == PreferenceKeys.START_FRAGMENT || key.orEmpty().contains("_color") -> putInt(
|
||||||
|
key,
|
||||||
|
value
|
||||||
|
)
|
||||||
else -> putLong(key, value.toLong())
|
else -> putLong(key, value.toLong())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,10 +41,10 @@ import com.github.libretube.enums.SbSkipOptions
|
|||||||
import com.github.libretube.extensions.updateParameters
|
import com.github.libretube.extensions.updateParameters
|
||||||
import com.github.libretube.obj.PreviewFrame
|
import com.github.libretube.obj.PreviewFrame
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
||||||
object PlayerHelper {
|
object PlayerHelper {
|
||||||
private const val ACTION_MEDIA_CONTROL = "media_control"
|
private const val ACTION_MEDIA_CONTROL = "media_control"
|
||||||
@ -662,12 +662,15 @@ object PlayerHelper {
|
|||||||
val audioLanguage = audioLanguageAndRoleFlags.first
|
val audioLanguage = audioLanguageAndRoleFlags.first
|
||||||
return context.getString(R.string.audio_track_format)
|
return context.getString(R.string.audio_track_format)
|
||||||
.format(
|
.format(
|
||||||
if (audioLanguage == null) context.getString(R.string.unknown_audio_language)
|
if (audioLanguage == null) {
|
||||||
else Locale.forLanguageTag(audioLanguage)
|
context.getString(R.string.unknown_audio_language)
|
||||||
.getDisplayLanguage(
|
} else {
|
||||||
LocaleHelper.getAppLocale()
|
Locale.forLanguageTag(audioLanguage)
|
||||||
)
|
.getDisplayLanguage(
|
||||||
.ifEmpty { context.getString(R.string.unknown_audio_language) },
|
LocaleHelper.getAppLocale()
|
||||||
|
)
|
||||||
|
.ifEmpty { context.getString(R.string.unknown_audio_language) }
|
||||||
|
},
|
||||||
getDisplayAudioTrackTypeFromFormat(context, audioLanguageAndRoleFlags.second)
|
getDisplayAudioTrackTypeFromFormat(context, audioLanguageAndRoleFlags.second)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -691,12 +694,15 @@ object PlayerHelper {
|
|||||||
// Filter unsupported tracks and keep only selected tracks if requested
|
// Filter unsupported tracks and keep only selected tracks if requested
|
||||||
// Use a lambda expression to avoid checking on each audio format if we keep only selected
|
// Use a lambda expression to avoid checking on each audio format if we keep only selected
|
||||||
// tracks or not
|
// tracks or not
|
||||||
val trackFilter = if (keepOnlySelectedTracks)
|
val trackFilter = if (keepOnlySelectedTracks) {
|
||||||
{ group: Tracks.Group, trackIndex: Int ->
|
{ group: Tracks.Group, trackIndex: Int ->
|
||||||
group.isTrackSupported(trackIndex) && group.isTrackSelected(
|
group.isTrackSupported(trackIndex) && group.isTrackSelected(
|
||||||
trackIndex
|
trackIndex
|
||||||
)
|
)
|
||||||
} else { group: Tracks.Group, trackIndex: Int -> group.isTrackSupported(trackIndex) }
|
}
|
||||||
|
} else {
|
||||||
|
{ group: Tracks.Group, trackIndex: Int -> group.isTrackSupported(trackIndex) }
|
||||||
|
}
|
||||||
|
|
||||||
return groups.filter {
|
return groups.filter {
|
||||||
it.type == C.TRACK_TYPE_AUDIO
|
it.type == C.TRACK_TYPE_AUDIO
|
||||||
@ -729,9 +735,9 @@ object PlayerHelper {
|
|||||||
* @return whether the provided ExoPlayer flags contain a flag used for audio track types
|
* @return whether the provided ExoPlayer flags contain a flag used for audio track types
|
||||||
*/
|
*/
|
||||||
fun haveAudioTrackRoleFlagSet(@C.RoleFlags roleFlags: Int): Boolean {
|
fun haveAudioTrackRoleFlagSet(@C.RoleFlags roleFlags: Int): Boolean {
|
||||||
return isFlagSet(roleFlags, C.ROLE_FLAG_DESCRIBES_VIDEO)
|
return isFlagSet(roleFlags, C.ROLE_FLAG_DESCRIBES_VIDEO) ||
|
||||||
|| isFlagSet(roleFlags, C.ROLE_FLAG_DUB)
|
isFlagSet(roleFlags, C.ROLE_FLAG_DUB) ||
|
||||||
|| isFlagSet(roleFlags, C.ROLE_FLAG_MAIN)
|
isFlagSet(roleFlags, C.ROLE_FLAG_MAIN) ||
|
||||||
|| isFlagSet(roleFlags, C.ROLE_FLAG_ALTERNATE)
|
isFlagSet(roleFlags, C.ROLE_FLAG_ALTERNATE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package com.github.libretube.helpers
|
package com.github.libretube.helpers
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import com.github.libretube.api.CronetHelper
|
import com.github.libretube.api.CronetHelper
|
||||||
import com.github.libretube.api.RetrofitInstance
|
import com.github.libretube.api.RetrofitInstance
|
||||||
import com.github.libretube.constants.PreferenceKeys
|
import com.github.libretube.constants.PreferenceKeys
|
||||||
|
@ -47,6 +47,11 @@ import java.net.URL
|
|||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.StandardOpenOption
|
import java.nio.file.StandardOpenOption
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
|
import kotlin.io.path.absolute
|
||||||
|
import kotlin.io.path.createFile
|
||||||
|
import kotlin.io.path.deleteIfExists
|
||||||
|
import kotlin.io.path.fileSize
|
||||||
|
import kotlin.math.min
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -61,11 +66,6 @@ import kotlinx.coroutines.withContext
|
|||||||
import okio.buffer
|
import okio.buffer
|
||||||
import okio.sink
|
import okio.sink
|
||||||
import okio.source
|
import okio.source
|
||||||
import kotlin.io.path.absolute
|
|
||||||
import kotlin.io.path.createFile
|
|
||||||
import kotlin.io.path.deleteIfExists
|
|
||||||
import kotlin.io.path.fileSize
|
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Download service with custom implementation of downloading using [HttpURLConnection].
|
* Download service with custom implementation of downloading using [HttpURLConnection].
|
||||||
@ -206,7 +206,7 @@ class DownloadService : LifecycleService() {
|
|||||||
notificationBuilder
|
notificationBuilder
|
||||||
.setContentText(
|
.setContentText(
|
||||||
totalRead.formatAsFileSize() + " / " +
|
totalRead.formatAsFileSize() + " / " +
|
||||||
item.downloadSize.formatAsFileSize()
|
item.downloadSize.formatAsFileSize()
|
||||||
)
|
)
|
||||||
.setProgress(
|
.setProgress(
|
||||||
item.downloadSize.toInt(),
|
item.downloadSize.toInt(),
|
||||||
|
@ -303,7 +303,9 @@ class OnlinePlayerService : LifecycleService() {
|
|||||||
val streams = streams ?: return
|
val streams = streams ?: return
|
||||||
|
|
||||||
val (uri, mimeType) = if (streams.audioStreams.isNotEmpty()) {
|
val (uri, mimeType) = if (streams.audioStreams.isNotEmpty()) {
|
||||||
val disableProxy = ProxyHelper.useYouTubeSourceWithoutProxy(streams.videoStreams.first().url!!)
|
val disableProxy = ProxyHelper.useYouTubeSourceWithoutProxy(
|
||||||
|
streams.videoStreams.first().url!!
|
||||||
|
)
|
||||||
PlayerHelper.createDashSource(
|
PlayerHelper.createDashSource(
|
||||||
streams,
|
streams,
|
||||||
this,
|
this,
|
||||||
|
@ -20,10 +20,10 @@ import com.github.libretube.ui.sheets.DownloadOptionsBottomSheet
|
|||||||
import com.github.libretube.ui.viewholders.DownloadsViewHolder
|
import com.github.libretube.ui.viewholders.DownloadsViewHolder
|
||||||
import com.github.libretube.util.TextUtils
|
import com.github.libretube.util.TextUtils
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import kotlin.io.path.deleteIfExists
|
import kotlin.io.path.deleteIfExists
|
||||||
import kotlin.io.path.fileSize
|
import kotlin.io.path.fileSize
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
||||||
class DownloadsAdapter(
|
class DownloadsAdapter(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
|
@ -104,8 +104,12 @@ class AddToPlaylistDialog(
|
|||||||
appContext.toastFromMainDispatcher(R.string.unknown_error)
|
appContext.toastFromMainDispatcher(R.string.unknown_error)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (success) appContext.toastFromMainDispatcher(
|
if (success) {
|
||||||
appContext.getString(R.string.added_to_playlist, playlistName)
|
appContext.toastFromMainDispatcher(
|
||||||
) else appContext.toastFromMainDispatcher(R.string.fail)
|
appContext.getString(R.string.added_to_playlist, playlistName)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
appContext.toastFromMainDispatcher(R.string.fail)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ import android.text.format.DateUtils
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.constraintlayout.motion.widget.MotionLayout
|
import androidx.constraintlayout.motion.widget.MotionLayout
|
||||||
import androidx.constraintlayout.motion.widget.TransitionAdapter
|
import androidx.constraintlayout.motion.widget.TransitionAdapter
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
@ -25,12 +25,12 @@ import com.github.libretube.receivers.DownloadReceiver
|
|||||||
import com.github.libretube.services.DownloadService
|
import com.github.libretube.services.DownloadService
|
||||||
import com.github.libretube.ui.adapters.DownloadsAdapter
|
import com.github.libretube.ui.adapters.DownloadsAdapter
|
||||||
import com.github.libretube.ui.viewholders.DownloadsViewHolder
|
import com.github.libretube.ui.viewholders.DownloadsViewHolder
|
||||||
|
import kotlin.io.path.fileSize
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlin.io.path.fileSize
|
|
||||||
|
|
||||||
class DownloadsFragment : Fragment() {
|
class DownloadsFragment : Fragment() {
|
||||||
private var _binding: FragmentDownloadsBinding? = null
|
private var _binding: FragmentDownloadsBinding? = null
|
||||||
@ -113,7 +113,7 @@ class DownloadsFragment : Fragment() {
|
|||||||
|
|
||||||
binding.downloads.adapter = adapter
|
binding.downloads.adapter = adapter
|
||||||
|
|
||||||
val itemTouchCallback = object: ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
|
val itemTouchCallback = object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
|
||||||
override fun getMovementFlags(
|
override fun getMovementFlags(
|
||||||
recyclerView: RecyclerView,
|
recyclerView: RecyclerView,
|
||||||
viewHolder: RecyclerView.ViewHolder
|
viewHolder: RecyclerView.ViewHolder
|
||||||
@ -196,7 +196,7 @@ class DownloadsFragment : Fragment() {
|
|||||||
if (progressBar.isIndeterminate) return
|
if (progressBar.isIndeterminate) return
|
||||||
progressBar.incrementProgressBy(status.progress.toInt())
|
progressBar.incrementProgressBy(status.progress.toInt())
|
||||||
val progressInfo = progressBar.progress.formatAsFileSize() +
|
val progressInfo = progressBar.progress.formatAsFileSize() +
|
||||||
" /\n" + progressBar.max.formatAsFileSize()
|
" /\n" + progressBar.max.formatAsFileSize()
|
||||||
fileSize.text = progressInfo
|
fileSize.text = progressInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,16 +115,16 @@ import com.github.libretube.util.TextUtils
|
|||||||
import com.github.libretube.util.TextUtils.toTimeInSeconds
|
import com.github.libretube.util.TextUtils.toTimeInSeconds
|
||||||
import com.github.libretube.util.YoutubeHlsPlaylistParser
|
import com.github.libretube.util.YoutubeHlsPlaylistParser
|
||||||
import com.github.libretube.util.deArrow
|
import com.github.libretube.util.deArrow
|
||||||
|
import java.io.IOException
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
import kotlin.math.abs
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import retrofit2.HttpException
|
import retrofit2.HttpException
|
||||||
import java.io.IOException
|
|
||||||
import java.util.*
|
|
||||||
import java.util.concurrent.Executors
|
|
||||||
import kotlin.math.abs
|
|
||||||
|
|
||||||
@androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
|
@androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
|
||||||
class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
||||||
@ -755,7 +755,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
if (binding.playerMotionLayout.progress != 1.0f) {
|
if (binding.playerMotionLayout.progress != 1.0f) {
|
||||||
// show controllers when not in picture in picture mode
|
// show controllers when not in picture in picture mode
|
||||||
val inPipMode = PlayerHelper.pipEnabled &&
|
val inPipMode = PlayerHelper.pipEnabled &&
|
||||||
PictureInPictureCompat.isInPictureInPictureMode(requireActivity())
|
PictureInPictureCompat.isInPictureInPictureMode(requireActivity())
|
||||||
if (!inPipMode) {
|
if (!inPipMode) {
|
||||||
binding.player.useController = true
|
binding.player.useController = true
|
||||||
}
|
}
|
||||||
@ -1298,9 +1298,11 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
) && streams.videoStreams.isNotEmpty() -> {
|
) && streams.videoStreams.isNotEmpty() -> {
|
||||||
// only use the dash manifest generated by YT if either it's a livestream or no other source is available
|
// only use the dash manifest generated by YT if either it's a livestream or no other source is available
|
||||||
val dashUri =
|
val dashUri =
|
||||||
if (streams.livestream && streams.dash != null) ProxyHelper.unwrapStreamUrl(
|
if (streams.livestream && streams.dash != null) {
|
||||||
streams.dash!!
|
ProxyHelper.unwrapStreamUrl(
|
||||||
).toUri() else {
|
streams.dash!!
|
||||||
|
).toUri()
|
||||||
|
} else {
|
||||||
// skip LBRY urls when checking whether the stream source is usable
|
// skip LBRY urls when checking whether the stream source is usable
|
||||||
val urlToTest = streams.videoStreams.firstOrNull {
|
val urlToTest = streams.videoStreams.firstOrNull {
|
||||||
!it.quality.orEmpty().contains("LBRY")
|
!it.quality.orEmpty().contains("LBRY")
|
||||||
@ -1324,7 +1326,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
val mediaSource = hlsMediaSourceFactory.createMediaSource(
|
val mediaSource = hlsMediaSourceFactory.createMediaSource(
|
||||||
createMediaItem(
|
createMediaItem(
|
||||||
ProxyHelper.unwrapStreamUrl(streams.hls!!).toUri(),
|
ProxyHelper.unwrapStreamUrl(streams.hls!!).toUri(),
|
||||||
MimeTypes.APPLICATION_M3U8,
|
MimeTypes.APPLICATION_M3U8
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
exoPlayer.setMediaSource(mediaSource)
|
exoPlayer.setMediaSource(mediaSource)
|
||||||
@ -1448,7 +1450,8 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
override fun onAudioStreamClicked() {
|
override fun onAudioStreamClicked() {
|
||||||
val context = requireContext()
|
val context = requireContext()
|
||||||
val audioLanguagesAndRoleFlags = PlayerHelper.getAudioLanguagesAndRoleFlagsFromTrackGroups(
|
val audioLanguagesAndRoleFlags = PlayerHelper.getAudioLanguagesAndRoleFlagsFromTrackGroups(
|
||||||
exoPlayer.currentTracks.groups, false
|
exoPlayer.currentTracks.groups,
|
||||||
|
false
|
||||||
)
|
)
|
||||||
val audioLanguages = audioLanguagesAndRoleFlags.map {
|
val audioLanguages = audioLanguagesAndRoleFlags.map {
|
||||||
PlayerHelper.getAudioTrackNameFromFormat(context, it)
|
PlayerHelper.getAudioTrackNameFromFormat(context, it)
|
||||||
@ -1460,9 +1463,9 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
listOf(context.getString(R.string.unknown_or_no_audio)),
|
listOf(context.getString(R.string.unknown_or_no_audio)),
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
} else if (audioLanguagesAndRoleFlags.size == 1
|
} else if (audioLanguagesAndRoleFlags.size == 1 &&
|
||||||
&& audioLanguagesAndRoleFlags[0].first == null
|
audioLanguagesAndRoleFlags[0].first == null &&
|
||||||
&& !PlayerHelper.haveAudioTrackRoleFlagSet(
|
!PlayerHelper.haveAudioTrackRoleFlagSet(
|
||||||
audioLanguagesAndRoleFlags[0].second
|
audioLanguagesAndRoleFlags[0].second
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
|
@ -2,12 +2,10 @@ package com.github.libretube.ui.fragments
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.ViewGroup.MarginLayoutParams
|
import android.view.ViewGroup.MarginLayoutParams
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.core.view.children
|
import androidx.core.view.children
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
@ -11,7 +11,6 @@ import com.github.libretube.helpers.NavigationHelper
|
|||||||
import com.github.libretube.obj.ShareData
|
import com.github.libretube.obj.ShareData
|
||||||
import com.github.libretube.services.OfflinePlayerService
|
import com.github.libretube.services.OfflinePlayerService
|
||||||
import com.github.libretube.ui.dialogs.ShareDialog
|
import com.github.libretube.ui.dialogs.ShareDialog
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|
||||||
|
|
||||||
class DownloadOptionsBottomSheet(
|
class DownloadOptionsBottomSheet(
|
||||||
private val download: Download,
|
private val download: Download,
|
||||||
|
@ -84,7 +84,6 @@ open class CustomExoPlayerView(
|
|||||||
updateCurrentPosition()
|
updateCurrentPosition()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preferences
|
* Preferences
|
||||||
*/
|
*/
|
||||||
|
@ -28,41 +28,41 @@ class OnlinePlayerView(
|
|||||||
@androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
|
@androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
|
||||||
override fun getOptionsMenuItems(): List<BottomSheetItem> {
|
override fun getOptionsMenuItems(): List<BottomSheetItem> {
|
||||||
return super.getOptionsMenuItems() +
|
return super.getOptionsMenuItems() +
|
||||||
listOf(
|
listOf(
|
||||||
BottomSheetItem(
|
BottomSheetItem(
|
||||||
context.getString(R.string.quality),
|
context.getString(R.string.quality),
|
||||||
R.drawable.ic_hd,
|
R.drawable.ic_hd,
|
||||||
{ "${player?.videoSize?.height}p" }
|
{ "${player?.videoSize?.height}p" }
|
||||||
) {
|
) {
|
||||||
playerOptions?.onQualityClicked()
|
playerOptions?.onQualityClicked()
|
||||||
},
|
},
|
||||||
BottomSheetItem(
|
BottomSheetItem(
|
||||||
context.getString(R.string.audio_track),
|
context.getString(R.string.audio_track),
|
||||||
R.drawable.ic_audio,
|
R.drawable.ic_audio,
|
||||||
{ getCurrentAudioTrackTitle() }
|
{ getCurrentAudioTrackTitle() }
|
||||||
) {
|
) {
|
||||||
playerOptions?.onAudioStreamClicked()
|
playerOptions?.onAudioStreamClicked()
|
||||||
},
|
},
|
||||||
BottomSheetItem(
|
BottomSheetItem(
|
||||||
context.getString(R.string.captions),
|
context.getString(R.string.captions),
|
||||||
R.drawable.ic_caption,
|
R.drawable.ic_caption,
|
||||||
{
|
{
|
||||||
if (trackSelector != null && trackSelector!!.parameters.preferredTextLanguages.isNotEmpty()) {
|
if (trackSelector != null && trackSelector!!.parameters.preferredTextLanguages.isNotEmpty()) {
|
||||||
trackSelector!!.parameters.preferredTextLanguages[0]
|
trackSelector!!.parameters.preferredTextLanguages[0]
|
||||||
} else {
|
} else {
|
||||||
context.getString(R.string.none)
|
context.getString(R.string.none)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
) {
|
|
||||||
playerOptions?.onCaptionsClicked()
|
|
||||||
},
|
|
||||||
BottomSheetItem(
|
|
||||||
context.getString(R.string.stats_for_nerds),
|
|
||||||
R.drawable.ic_info
|
|
||||||
) {
|
|
||||||
playerOptions?.onStatsClicked()
|
|
||||||
}
|
}
|
||||||
)
|
) {
|
||||||
|
playerOptions?.onCaptionsClicked()
|
||||||
|
},
|
||||||
|
BottomSheetItem(
|
||||||
|
context.getString(R.string.stats_for_nerds),
|
||||||
|
R.drawable.ic_info
|
||||||
|
) {
|
||||||
|
playerOptions?.onStatsClicked()
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCurrentAudioTrackTitle(): String {
|
private fun getCurrentAudioTrackTitle(): String {
|
||||||
@ -86,9 +86,9 @@ class OnlinePlayerView(
|
|||||||
// format or quality
|
// format or quality
|
||||||
val firstSelectedAudioFormat = selectedAudioLanguagesAndRoleFlags[0]
|
val firstSelectedAudioFormat = selectedAudioLanguagesAndRoleFlags[0]
|
||||||
|
|
||||||
if (selectedAudioLanguagesAndRoleFlags.size == 1
|
if (selectedAudioLanguagesAndRoleFlags.size == 1 &&
|
||||||
&& firstSelectedAudioFormat.first == null
|
firstSelectedAudioFormat.first == null &&
|
||||||
&& !PlayerHelper.haveAudioTrackRoleFlagSet(
|
!PlayerHelper.haveAudioTrackRoleFlagSet(
|
||||||
firstSelectedAudioFormat.second
|
firstSelectedAudioFormat.second
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
|
@ -86,4 +86,4 @@ suspend fun List<StreamItem>.deArrow() = DeArrowUtil.deArrowStreamItems(this)
|
|||||||
* provided by the DeArrow project
|
* provided by the DeArrow project
|
||||||
*/
|
*/
|
||||||
@JvmName("deArrowContentItems")
|
@JvmName("deArrowContentItems")
|
||||||
suspend fun List<ContentItem>.deArrow() = DeArrowUtil.deArrowContentItems(this)
|
suspend fun List<ContentItem>.deArrow() = DeArrowUtil.deArrowContentItems(this)
|
||||||
|
@ -121,7 +121,9 @@ class NowPlayingNotification(
|
|||||||
private fun processBitmap(bitmap: Bitmap): Bitmap {
|
private fun processBitmap(bitmap: Bitmap): Bitmap {
|
||||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
bitmap
|
bitmap
|
||||||
} else ImageHelper.getSquareBitmap(bitmap)
|
} else {
|
||||||
|
ImageHelper.getSquareBitmap(bitmap)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val legacyNotificationButtons
|
private val legacyNotificationButtons
|
||||||
|
Loading…
x
Reference in New Issue
Block a user