mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-15 06:40:30 +05:30
Merge branch 'libre-tube:master' into master
This commit is contained in:
commit
332c65e51b
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@ -10,7 +10,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 1
|
fetch-depth: 1
|
||||||
- name: ktlint
|
- name: ktlint
|
||||||
uses: ScaCap/action-ktlint@1.3
|
uses: ScaCap/action-ktlint@1.4
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
reporter: github-pr-check
|
reporter: github-pr-check
|
||||||
|
@ -3,6 +3,7 @@ package com.github.libretube
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.support.v4.media.session.MediaSessionCompat
|
import android.support.v4.media.session.MediaSessionCompat
|
||||||
import com.github.libretube.obj.Streams
|
import com.github.libretube.obj.Streams
|
||||||
|
import com.github.libretube.util.DescriptionAdapter
|
||||||
import com.github.libretube.util.RetrofitInstance
|
import com.github.libretube.util.RetrofitInstance
|
||||||
import com.google.android.exoplayer2.C
|
import com.google.android.exoplayer2.C
|
||||||
import com.google.android.exoplayer2.ExoPlayer
|
import com.google.android.exoplayer2.ExoPlayer
|
||||||
@ -10,6 +11,7 @@ import com.google.android.exoplayer2.MediaItem
|
|||||||
import com.google.android.exoplayer2.audio.AudioAttributes
|
import com.google.android.exoplayer2.audio.AudioAttributes
|
||||||
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
|
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
|
||||||
import com.google.android.exoplayer2.ui.PlayerNotificationManager
|
import com.google.android.exoplayer2.ui.PlayerNotificationManager
|
||||||
|
import gen._base._base_java__rjava_resources.srcjar.R.id.title
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
||||||
@ -66,13 +68,20 @@ class BackgroundMode {
|
|||||||
/**
|
/**
|
||||||
* Initializes the [playerNotification] attached to the [player] and shows it.
|
* Initializes the [playerNotification] attached to the [player] and shows it.
|
||||||
*/
|
*/
|
||||||
private fun initializePlayerNotification(c: Context) {
|
private fun initializePlayerNotification(c: Context, streams: Streams) {
|
||||||
playerNotification = PlayerNotificationManager
|
playerNotification = PlayerNotificationManager
|
||||||
.Builder(c, 1, "background_mode").build()
|
.Builder(c, 1, "background_mode")
|
||||||
playerNotification.setPlayer(player)
|
// set the description of the notification
|
||||||
playerNotification.setUsePreviousAction(false)
|
.setMediaDescriptionAdapter(
|
||||||
playerNotification.setUseNextAction(false)
|
DescriptionAdapter(streams.title!!, streams.uploader!!, streams.thumbnailUrl!!)
|
||||||
playerNotification.setMediaSessionToken(mediaSession.sessionToken)
|
)
|
||||||
|
.build()
|
||||||
|
playerNotification.apply {
|
||||||
|
setPlayer(player)
|
||||||
|
setUsePreviousAction(false)
|
||||||
|
setUseNextAction(false)
|
||||||
|
setMediaSessionToken(mediaSession.sessionToken)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,7 +113,7 @@ class BackgroundMode {
|
|||||||
job.join()
|
job.join()
|
||||||
|
|
||||||
initializePlayer(c)
|
initializePlayer(c)
|
||||||
initializePlayerNotification(c)
|
initializePlayerNotification(c, response!!)
|
||||||
|
|
||||||
player?.apply {
|
player?.apply {
|
||||||
playWhenReady = playWhenReadyPlayer
|
playWhenReady = playWhenReadyPlayer
|
||||||
|
@ -10,6 +10,7 @@ import android.net.Uri
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@ -68,6 +69,12 @@ class MainActivity : AppCompatActivity() {
|
|||||||
sharedPreferences.getBoolean("sponsors_category_key", false)
|
sharedPreferences.getBoolean("sponsors_category_key", false)
|
||||||
SponsorBlockSettings.outroEnabled =
|
SponsorBlockSettings.outroEnabled =
|
||||||
sharedPreferences.getBoolean("outro_category_key", false)
|
sharedPreferences.getBoolean("outro_category_key", false)
|
||||||
|
SponsorBlockSettings.fillerEnabled =
|
||||||
|
sharedPreferences.getBoolean("filler_category_key", false)
|
||||||
|
SponsorBlockSettings.musicOfftopicEnabled =
|
||||||
|
sharedPreferences.getBoolean("music_offtopic_category_key", false)
|
||||||
|
SponsorBlockSettings.previewEnabled =
|
||||||
|
sharedPreferences.getBoolean("preview_category_key", false)
|
||||||
|
|
||||||
ThemeHelper().updateTheme(this)
|
ThemeHelper().updateTheme(this)
|
||||||
LocaleHelper().updateLanguage(this)
|
LocaleHelper().updateLanguage(this)
|
||||||
@ -199,19 +206,12 @@ class MainActivity : AppCompatActivity() {
|
|||||||
.replace("/embed/", "")
|
.replace("/embed/", "")
|
||||||
val bundle = Bundle()
|
val bundle = Bundle()
|
||||||
bundle.putString("videoId", watch)
|
bundle.putString("videoId", watch)
|
||||||
val frag = PlayerFragment()
|
// for time stamped links
|
||||||
frag.arguments = bundle
|
if (data.query != null && data.query?.contains("t=")!!) {
|
||||||
supportFragmentManager.beginTransaction()
|
val timeStamp = data.query.toString().split("t=")[1]
|
||||||
.remove(PlayerFragment())
|
bundle.putLong("timeStamp", timeStamp.toLong())
|
||||||
.commit()
|
}
|
||||||
supportFragmentManager.beginTransaction()
|
loadWatch(bundle)
|
||||||
.replace(R.id.container, frag)
|
|
||||||
.commitNow()
|
|
||||||
Handler().postDelayed({
|
|
||||||
val motionLayout = findViewById<MotionLayout>(R.id.playerMotionLayout)
|
|
||||||
motionLayout.transitionToEnd()
|
|
||||||
motionLayout.transitionToStart()
|
|
||||||
}, 100)
|
|
||||||
} else if (data.path!!.contains("/watch") && data.query != null) {
|
} else if (data.path!!.contains("/watch") && data.query != null) {
|
||||||
Log.d("dafaq", data.query!!)
|
Log.d("dafaq", data.query!!)
|
||||||
var watch = data.query!!
|
var watch = data.query!!
|
||||||
@ -226,39 +226,41 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
var bundle = Bundle()
|
var bundle = Bundle()
|
||||||
bundle.putString("videoId", watch.replace("v=", ""))
|
bundle.putString("videoId", watch.replace("v=", ""))
|
||||||
var frag = PlayerFragment()
|
// for time stamped links
|
||||||
frag.arguments = bundle
|
if (data.query != null && data.query?.contains("t=")!!) {
|
||||||
supportFragmentManager.beginTransaction()
|
val timeStamp = data.query.toString().split("t=")[1]
|
||||||
.remove(PlayerFragment())
|
bundle.putLong("timeStamp", timeStamp.toLong())
|
||||||
.commit()
|
}
|
||||||
supportFragmentManager.beginTransaction()
|
loadWatch(bundle)
|
||||||
.replace(R.id.container, frag)
|
|
||||||
.commitNow()
|
|
||||||
Handler().postDelayed({
|
|
||||||
val motionLayout = findViewById<MotionLayout>(R.id.playerMotionLayout)
|
|
||||||
motionLayout.transitionToEnd()
|
|
||||||
motionLayout.transitionToStart()
|
|
||||||
}, 100)
|
|
||||||
} else {
|
} else {
|
||||||
var watch = data.path!!.replace("/", "")
|
var watch = data.path!!.replace("/", "")
|
||||||
var bundle = Bundle()
|
var bundle = Bundle()
|
||||||
bundle.putString("videoId", watch)
|
bundle.putString("videoId", watch)
|
||||||
var frag = PlayerFragment()
|
// for time stamped links
|
||||||
frag.arguments = bundle
|
if (data.query != null && data.query?.contains("t=")!!) {
|
||||||
supportFragmentManager.beginTransaction()
|
val timeStamp = data.query.toString().split("t=")[1]
|
||||||
.remove(PlayerFragment())
|
bundle.putLong("timeStamp", timeStamp.toLong())
|
||||||
.commit()
|
}
|
||||||
supportFragmentManager.beginTransaction()
|
loadWatch(bundle)
|
||||||
.replace(R.id.container, frag)
|
|
||||||
.commitNow()
|
|
||||||
Handler().postDelayed({
|
|
||||||
val motionLayout = findViewById<MotionLayout>(R.id.playerMotionLayout)
|
|
||||||
motionLayout.transitionToEnd()
|
|
||||||
motionLayout.transitionToStart()
|
|
||||||
}, 100)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun loadWatch(bundle: Bundle) {
|
||||||
|
var frag = PlayerFragment()
|
||||||
|
frag.arguments = bundle
|
||||||
|
supportFragmentManager.beginTransaction()
|
||||||
|
.remove(PlayerFragment())
|
||||||
|
.commit()
|
||||||
|
supportFragmentManager.beginTransaction()
|
||||||
|
.replace(R.id.container, frag)
|
||||||
|
.commitNow()
|
||||||
|
Handler(Looper.getMainLooper()).postDelayed({
|
||||||
|
val motionLayout = findViewById<MotionLayout>(R.id.playerMotionLayout)
|
||||||
|
motionLayout.transitionToEnd()
|
||||||
|
motionLayout.transitionToStart()
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onBackPressed() {
|
override fun onBackPressed() {
|
||||||
try {
|
try {
|
||||||
val mainMotionLayout = findViewById<MotionLayout>(R.id.mainMotionLayout)
|
val mainMotionLayout = findViewById<MotionLayout>(R.id.mainMotionLayout)
|
||||||
|
@ -8,14 +8,19 @@ import android.view.ViewGroup
|
|||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
|
import com.github.libretube.dialogs.VideoOptionsDialog
|
||||||
import com.github.libretube.fragments.PlayerFragment
|
import com.github.libretube.fragments.PlayerFragment
|
||||||
import com.github.libretube.obj.StreamItem
|
import com.github.libretube.obj.StreamItem
|
||||||
import com.github.libretube.util.formatShort
|
import com.github.libretube.util.formatShort
|
||||||
import com.squareup.picasso.Picasso
|
import com.squareup.picasso.Picasso
|
||||||
|
|
||||||
class ChannelAdapter(private val videoFeed: MutableList<StreamItem>) :
|
class ChannelAdapter(
|
||||||
|
private val videoFeed: MutableList<StreamItem>,
|
||||||
|
private val childFragmentManager: FragmentManager
|
||||||
|
) :
|
||||||
RecyclerView.Adapter<ChannelViewHolder>() {
|
RecyclerView.Adapter<ChannelViewHolder>() {
|
||||||
override fun getItemCount(): Int {
|
override fun getItemCount(): Int {
|
||||||
return videoFeed.size
|
return videoFeed.size
|
||||||
@ -55,6 +60,12 @@ class ChannelAdapter(private val videoFeed: MutableList<StreamItem>) :
|
|||||||
.replace(R.id.container, frag)
|
.replace(R.id.container, frag)
|
||||||
.commitNow()
|
.commitNow()
|
||||||
}
|
}
|
||||||
|
holder.v.setOnLongClickListener {
|
||||||
|
val videoId = trending.url!!.replace("/watch?v=", "")
|
||||||
|
VideoOptionsDialog(videoId, holder.v.context)
|
||||||
|
.show(childFragmentManager, VideoOptionsDialog.TAG)
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,48 @@
|
|||||||
|
package com.github.libretube.adapters
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.github.libretube.R
|
||||||
|
import com.github.libretube.obj.ChapterSegment
|
||||||
|
import com.google.android.exoplayer2.ExoPlayer
|
||||||
|
import com.squareup.picasso.Picasso
|
||||||
|
|
||||||
|
class ChaptersAdapter(
|
||||||
|
private val chapters: List<ChapterSegment>,
|
||||||
|
private val exoPlayer: ExoPlayer
|
||||||
|
) : RecyclerView.Adapter<ChaptersViewHolder>() {
|
||||||
|
val TAG = "ChaptersAdapter"
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChaptersViewHolder {
|
||||||
|
val layoutInflater = LayoutInflater.from(parent.context)
|
||||||
|
val cell = layoutInflater.inflate(R.layout.chapter_column, parent, false)
|
||||||
|
return ChaptersViewHolder(cell)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ChaptersViewHolder, position: Int) {
|
||||||
|
val chapter = chapters[position]
|
||||||
|
val chapterImage = holder.v.findViewById<ImageView>(R.id.chapter_image)
|
||||||
|
Picasso.get().load(chapter.image).fit().centerCrop().into(chapterImage)
|
||||||
|
|
||||||
|
val chapterTitle = holder.v.findViewById<TextView>(R.id.chapter_title)
|
||||||
|
chapterTitle.text = chapter.title
|
||||||
|
|
||||||
|
holder.v.setOnClickListener {
|
||||||
|
val chapterStart = chapter.start!!.toLong() * 1000 // multiply by thousand for ms -> s
|
||||||
|
exoPlayer.seekTo(chapterStart)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int {
|
||||||
|
return chapters.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChaptersViewHolder(val v: View) : RecyclerView.ViewHolder(v) {
|
||||||
|
init {
|
||||||
|
}
|
||||||
|
}
|
@ -67,7 +67,8 @@ class VideoOptionsDialog(private val videoId: String, context: Context) : Dialog
|
|||||||
}
|
}
|
||||||
2 -> {
|
2 -> {
|
||||||
val shareDialog = ShareDialog(videoId)
|
val shareDialog = ShareDialog(videoId)
|
||||||
shareDialog.show(childFragmentManager, "ShareDialog")
|
// using parentFragmentManager is important here
|
||||||
|
shareDialog.show(parentFragmentManager, "ShareDialog")
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
|
@ -218,7 +218,10 @@ class ChannelFragment : Fragment() {
|
|||||||
val channelImage = view.findViewById<ImageView>(R.id.channel_image)
|
val channelImage = view.findViewById<ImageView>(R.id.channel_image)
|
||||||
Picasso.get().load(response.bannerUrl).into(bannerImage)
|
Picasso.get().load(response.bannerUrl).into(bannerImage)
|
||||||
Picasso.get().load(response.avatarUrl).into(channelImage)
|
Picasso.get().load(response.avatarUrl).into(channelImage)
|
||||||
channelAdapter = ChannelAdapter(response.relatedStreams!!.toMutableList())
|
channelAdapter = ChannelAdapter(
|
||||||
|
response.relatedStreams!!.toMutableList(),
|
||||||
|
childFragmentManager
|
||||||
|
)
|
||||||
view.findViewById<RecyclerView>(R.id.channel_recView).adapter = channelAdapter
|
view.findViewById<RecyclerView>(R.id.channel_recView).adapter = channelAdapter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package com.github.libretube.fragments
|
|||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.DialogInterface
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.ActivityInfo
|
import android.content.pm.ActivityInfo
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
@ -18,9 +17,6 @@ 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.animation.Animation
|
|
||||||
import android.view.animation.LinearInterpolator
|
|
||||||
import android.view.animation.RotateAnimation
|
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import android.widget.ImageButton
|
import android.widget.ImageButton
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
@ -43,6 +39,7 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import com.github.libretube.IS_DOWNLOAD_RUNNING
|
import com.github.libretube.IS_DOWNLOAD_RUNNING
|
||||||
import com.github.libretube.MainActivity
|
import com.github.libretube.MainActivity
|
||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
|
import com.github.libretube.adapters.ChaptersAdapter
|
||||||
import com.github.libretube.adapters.CommentsAdapter
|
import com.github.libretube.adapters.CommentsAdapter
|
||||||
import com.github.libretube.adapters.TrendingAdapter
|
import com.github.libretube.adapters.TrendingAdapter
|
||||||
import com.github.libretube.dialogs.AddtoPlaylistDialog
|
import com.github.libretube.dialogs.AddtoPlaylistDialog
|
||||||
@ -57,6 +54,7 @@ import com.github.libretube.obj.Streams
|
|||||||
import com.github.libretube.obj.Subscribe
|
import com.github.libretube.obj.Subscribe
|
||||||
import com.github.libretube.preferences.SponsorBlockSettings
|
import com.github.libretube.preferences.SponsorBlockSettings
|
||||||
import com.github.libretube.util.CronetHelper
|
import com.github.libretube.util.CronetHelper
|
||||||
|
import com.github.libretube.util.DescriptionAdapter
|
||||||
import com.github.libretube.util.RetrofitInstance
|
import com.github.libretube.util.RetrofitInstance
|
||||||
import com.github.libretube.util.formatShort
|
import com.github.libretube.util.formatShort
|
||||||
import com.google.android.exoplayer2.C
|
import com.google.android.exoplayer2.C
|
||||||
@ -102,7 +100,7 @@ class PlayerFragment : Fragment() {
|
|||||||
private var whichQuality = 0
|
private var whichQuality = 0
|
||||||
private var isZoomed: Boolean = false
|
private var isZoomed: Boolean = false
|
||||||
|
|
||||||
var isSubscribed: Boolean = false
|
private var isSubscribed: Boolean = false
|
||||||
|
|
||||||
private lateinit var relatedRecView: RecyclerView
|
private lateinit var relatedRecView: RecyclerView
|
||||||
private lateinit var commentsRecView: RecyclerView
|
private lateinit var commentsRecView: RecyclerView
|
||||||
@ -122,6 +120,10 @@ class PlayerFragment : Fragment() {
|
|||||||
private lateinit var mediaSessionConnector: MediaSessionConnector
|
private lateinit var mediaSessionConnector: MediaSessionConnector
|
||||||
private lateinit var playerNotification: PlayerNotificationManager
|
private lateinit var playerNotification: PlayerNotificationManager
|
||||||
|
|
||||||
|
private lateinit var title: String
|
||||||
|
private lateinit var uploader: String
|
||||||
|
private lateinit var thumbnailUrl: String
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
arguments?.let {
|
arguments?.let {
|
||||||
@ -142,6 +144,11 @@ class PlayerFragment : Fragment() {
|
|||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
hideKeyboard()
|
hideKeyboard()
|
||||||
|
|
||||||
|
initializeTransitionLayout(view)
|
||||||
|
fetchJsonAndInitPlayer(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initializeTransitionLayout(view: View) {
|
||||||
val playerDescription = view.findViewById<TextView>(R.id.player_description)
|
val playerDescription = view.findViewById<TextView>(R.id.player_description)
|
||||||
videoId = videoId!!.replace("/watch?v=", "")
|
videoId = videoId!!.replace("/watch?v=", "")
|
||||||
relDownloadVideo = view.findViewById(R.id.relPlayer_download)
|
relDownloadVideo = view.findViewById(R.id.relPlayer_download)
|
||||||
@ -208,7 +215,7 @@ class PlayerFragment : Fragment() {
|
|||||||
|
|
||||||
playerMotionLayout.progress = 1.toFloat()
|
playerMotionLayout.progress = 1.toFloat()
|
||||||
playerMotionLayout.transitionToStart()
|
playerMotionLayout.transitionToStart()
|
||||||
fetchJson(view)
|
|
||||||
view.findViewById<ImageView>(R.id.close_imageView).setOnClickListener {
|
view.findViewById<ImageView>(R.id.close_imageView).setOnClickListener {
|
||||||
motionLayout.transitionToEnd()
|
motionLayout.transitionToEnd()
|
||||||
val mainActivity = activity as MainActivity
|
val mainActivity = activity as MainActivity
|
||||||
@ -239,25 +246,11 @@ class PlayerFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
view.findViewById<RelativeLayout>(R.id.player_title_layout).setOnClickListener {
|
view.findViewById<RelativeLayout>(R.id.player_title_layout).setOnClickListener {
|
||||||
|
val image = view.findViewById<ImageView>(R.id.player_description_arrow)
|
||||||
|
image.animate().rotationBy(180F).setDuration(100).start()
|
||||||
if (playerDescription.isVisible) {
|
if (playerDescription.isVisible) {
|
||||||
val image = view.findViewById<ImageView>(R.id.player_description_arrow)
|
|
||||||
image.clearAnimation()
|
|
||||||
playerDescription.visibility = View.GONE
|
playerDescription.visibility = View.GONE
|
||||||
} else {
|
} else {
|
||||||
// toggle button
|
|
||||||
val rotate = RotateAnimation(
|
|
||||||
0F,
|
|
||||||
180F,
|
|
||||||
Animation.RELATIVE_TO_SELF,
|
|
||||||
0.5f,
|
|
||||||
Animation.RELATIVE_TO_SELF,
|
|
||||||
0.5f
|
|
||||||
)
|
|
||||||
rotate.duration = 100
|
|
||||||
rotate.interpolator = LinearInterpolator()
|
|
||||||
rotate.fillAfter = true
|
|
||||||
val image = view.findViewById<ImageView>(R.id.player_description_arrow)
|
|
||||||
image.startAnimation(rotate)
|
|
||||||
playerDescription.visibility = View.VISIBLE
|
playerDescription.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -319,8 +312,6 @@ class PlayerFragment : Fragment() {
|
|||||||
commentsRecView.layoutManager = LinearLayoutManager(view.context)
|
commentsRecView.layoutManager = LinearLayoutManager(view.context)
|
||||||
|
|
||||||
commentsRecView.setItemViewCacheSize(20)
|
commentsRecView.setItemViewCacheSize(20)
|
||||||
commentsRecView.isDrawingCacheEnabled = true
|
|
||||||
commentsRecView.drawingCacheQuality = View.DRAWING_CACHE_QUALITY_HIGH
|
|
||||||
|
|
||||||
relatedRecView = view.findViewById(R.id.player_recView)
|
relatedRecView = view.findViewById(R.id.player_recView)
|
||||||
relatedRecView.layoutManager =
|
relatedRecView.layoutManager =
|
||||||
@ -372,7 +363,7 @@ class PlayerFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchJson(view: View) {
|
private fun fetchJsonAndInitPlayer(view: View) {
|
||||||
fun run() {
|
fun run() {
|
||||||
lifecycleScope.launchWhenCreated {
|
lifecycleScope.launchWhenCreated {
|
||||||
val response = try {
|
val response = try {
|
||||||
@ -387,6 +378,40 @@ class PlayerFragment : Fragment() {
|
|||||||
Toast.makeText(context, R.string.server_error, Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, R.string.server_error, Toast.LENGTH_SHORT).show()
|
||||||
return@launchWhenCreated
|
return@launchWhenCreated
|
||||||
}
|
}
|
||||||
|
// for the notification description adapter
|
||||||
|
title = response.title!!
|
||||||
|
uploader = response.uploader!!
|
||||||
|
thumbnailUrl = response.thumbnailUrl!!
|
||||||
|
|
||||||
|
// check whether related streams are enabled
|
||||||
|
val sharedPreferences = PreferenceManager
|
||||||
|
.getDefaultSharedPreferences(requireContext())
|
||||||
|
relatedStreamsEnabled = sharedPreferences.getBoolean("related_streams_toggle", true)
|
||||||
|
runOnUiThread {
|
||||||
|
createExoPlayer(view)
|
||||||
|
prepareExoPlayerView()
|
||||||
|
if (response.chapters != null) initializeChapters(response.chapters)
|
||||||
|
setResolutionAndSubtitles(view, response)
|
||||||
|
// support for time stamped links
|
||||||
|
if (arguments?.getLong("timeStamp") != null) {
|
||||||
|
val position = arguments?.getLong("timeStamp")!! * 1000
|
||||||
|
exoPlayer.seekTo(position)
|
||||||
|
}
|
||||||
|
exoPlayer.prepare()
|
||||||
|
exoPlayer.play()
|
||||||
|
initializePlayerView(view, response)
|
||||||
|
initializePlayerNotification(requireContext())
|
||||||
|
fetchSponsorBlockSegments()
|
||||||
|
if (!relatedStreamsEnabled) toggleComments()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
run()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fetchSponsorBlockSegments() {
|
||||||
|
fun run() {
|
||||||
|
lifecycleScope.launchWhenCreated {
|
||||||
if (SponsorBlockSettings.sponsorBlockEnabled) {
|
if (SponsorBlockSettings.sponsorBlockEnabled) {
|
||||||
val categories: ArrayList<String> = arrayListOf()
|
val categories: ArrayList<String> = arrayListOf()
|
||||||
if (SponsorBlockSettings.introEnabled) {
|
if (SponsorBlockSettings.introEnabled) {
|
||||||
@ -404,6 +429,15 @@ class PlayerFragment : Fragment() {
|
|||||||
if (SponsorBlockSettings.outroEnabled) {
|
if (SponsorBlockSettings.outroEnabled) {
|
||||||
categories.add("outro")
|
categories.add("outro")
|
||||||
}
|
}
|
||||||
|
if (SponsorBlockSettings.fillerEnabled) {
|
||||||
|
categories.add("filler")
|
||||||
|
}
|
||||||
|
if (SponsorBlockSettings.musicOfftopicEnabled) {
|
||||||
|
categories.add("music_offtopic")
|
||||||
|
}
|
||||||
|
if (SponsorBlockSettings.previewEnabled) {
|
||||||
|
categories.add("preview")
|
||||||
|
}
|
||||||
if (categories.size > 0) {
|
if (categories.size > 0) {
|
||||||
segmentData = try {
|
segmentData = try {
|
||||||
|
|
||||||
@ -425,20 +459,6 @@ class PlayerFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// check whether related streams are enabled
|
|
||||||
val sharedPreferences = PreferenceManager
|
|
||||||
.getDefaultSharedPreferences(requireContext())
|
|
||||||
relatedStreamsEnabled = sharedPreferences.getBoolean("related_streams_toggle", true)
|
|
||||||
runOnUiThread {
|
|
||||||
createExoPlayer(view)
|
|
||||||
prepareExoPlayerView()
|
|
||||||
if (response.chapters != null) initializeChapters(response.chapters)
|
|
||||||
setResolutionAndSubtitles(view, response)
|
|
||||||
exoPlayer.prepare()
|
|
||||||
exoPlayer.play()
|
|
||||||
initializePlayerView(view, response)
|
|
||||||
if (!relatedStreamsEnabled) toggleComments()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
run()
|
run()
|
||||||
@ -470,7 +490,7 @@ class PlayerFragment : Fragment() {
|
|||||||
view.findViewById<TextView>(R.id.player_description).text = response.description
|
view.findViewById<TextView>(R.id.player_description).text = response.description
|
||||||
|
|
||||||
// Listener for play and pause icon change
|
// Listener for play and pause icon change
|
||||||
exoPlayer.addListener(object : com.google.android.exoplayer2.Player.Listener {
|
exoPlayer.addListener(object : Player.Listener {
|
||||||
override fun onIsPlayingChanged(isPlaying: Boolean) {
|
override fun onIsPlayingChanged(isPlaying: Boolean) {
|
||||||
if (isPlaying && SponsorBlockSettings.sponsorBlockEnabled) {
|
if (isPlaying && SponsorBlockSettings.sponsorBlockEnabled) {
|
||||||
exoPlayerView.postDelayed(
|
exoPlayerView.postDelayed(
|
||||||
@ -479,7 +499,7 @@ class PlayerFragment : Fragment() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@Deprecated(message = "Deprecated", level = DeprecationLevel.HIDDEN)
|
||||||
override fun onPlayerStateChanged(
|
override fun onPlayerStateChanged(
|
||||||
playWhenReady: Boolean,
|
playWhenReady: Boolean,
|
||||||
playbackState: Int
|
playbackState: Int
|
||||||
@ -520,7 +540,7 @@ class PlayerFragment : Fragment() {
|
|||||||
relDownloadVideo.setOnClickListener {
|
relDownloadVideo.setOnClickListener {
|
||||||
if (!IS_DOWNLOAD_RUNNING) {
|
if (!IS_DOWNLOAD_RUNNING) {
|
||||||
val newFragment = DownloadDialog()
|
val newFragment = DownloadDialog()
|
||||||
var bundle = Bundle()
|
val bundle = Bundle()
|
||||||
bundle.putString("video_id", videoId)
|
bundle.putString("video_id", videoId)
|
||||||
bundle.putParcelable("streams", response)
|
bundle.putParcelable("streams", response)
|
||||||
newFragment.arguments = bundle
|
newFragment.arguments = bundle
|
||||||
@ -588,7 +608,7 @@ class PlayerFragment : Fragment() {
|
|||||||
isSubscribed(subButton, channelId!!)
|
isSubscribed(subButton, channelId!!)
|
||||||
view.findViewById<LinearLayout>(R.id.save).setOnClickListener {
|
view.findViewById<LinearLayout>(R.id.save).setOnClickListener {
|
||||||
val newFragment = AddtoPlaylistDialog()
|
val newFragment = AddtoPlaylistDialog()
|
||||||
var bundle = Bundle()
|
val bundle = Bundle()
|
||||||
bundle.putString("videoId", videoId)
|
bundle.putString("videoId", videoId)
|
||||||
newFragment.arguments = bundle
|
newFragment.arguments = bundle
|
||||||
newFragment.show(childFragmentManager, "AddToPlaylist")
|
newFragment.show(childFragmentManager, "AddToPlaylist")
|
||||||
@ -597,8 +617,28 @@ class PlayerFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun initializeChapters(chapters: List<ChapterSegment>) {
|
private fun initializeChapters(chapters: List<ChapterSegment>) {
|
||||||
chapters.forEach { chapter ->
|
val chaptersToggle = view?.findViewById<LinearLayout>(R.id.chapters_toggle)
|
||||||
Log.e(TAG, chapter.title!!)
|
val chaptersRecView = view?.findViewById<RecyclerView>(R.id.chapters_recView)
|
||||||
|
val chaptersToggleText = view?.findViewById<TextView>(R.id.chapters_toggle_text)
|
||||||
|
val chaptersToggleArrow = view?.findViewById<ImageView>(R.id.chapters_toggle_arrow)
|
||||||
|
|
||||||
|
if (chapters.isNotEmpty()) {
|
||||||
|
chaptersToggle?.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
chaptersToggle?.setOnClickListener {
|
||||||
|
if (chaptersRecView?.isVisible!!) {
|
||||||
|
chaptersRecView?.visibility = View.GONE
|
||||||
|
chaptersToggleText?.text = getString(R.string.show_chapters)
|
||||||
|
} else {
|
||||||
|
chaptersRecView?.visibility = View.VISIBLE
|
||||||
|
chaptersToggleText?.text = getString(R.string.hide_chapters)
|
||||||
|
}
|
||||||
|
chaptersToggleArrow!!.animate().setDuration(100).rotationBy(180F).start()
|
||||||
|
}
|
||||||
|
|
||||||
|
chaptersRecView?.layoutManager =
|
||||||
|
LinearLayoutManager(this.context, LinearLayoutManager.HORIZONTAL, false)
|
||||||
|
chaptersRecView?.adapter = ChaptersAdapter(chapters, exoPlayer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -609,7 +649,7 @@ class PlayerFragment : Fragment() {
|
|||||||
val name = vid.quality + " " + vid.format
|
val name = vid.quality + " " + vid.format
|
||||||
videosNameArray += name
|
videosNameArray += name
|
||||||
}
|
}
|
||||||
var subtitle = mutableListOf<SubtitleConfiguration>()
|
val subtitle = mutableListOf<SubtitleConfiguration>()
|
||||||
if (response.subtitles!!.isNotEmpty()) {
|
if (response.subtitles!!.isNotEmpty()) {
|
||||||
subtitle.add(
|
subtitle.add(
|
||||||
SubtitleConfiguration.Builder(response.subtitles[0].url!!.toUri())
|
SubtitleConfiguration.Builder(response.subtitles[0].url!!.toUri())
|
||||||
@ -719,70 +759,69 @@ class PlayerFragment : Fragment() {
|
|||||||
val builder: MaterialAlertDialogBuilder? = activity?.let {
|
val builder: MaterialAlertDialogBuilder? = activity?.let {
|
||||||
MaterialAlertDialogBuilder(it)
|
MaterialAlertDialogBuilder(it)
|
||||||
}
|
}
|
||||||
var lastPosition = exoPlayer.currentPosition
|
val lastPosition = exoPlayer.currentPosition
|
||||||
builder!!.setTitle(R.string.choose_quality_dialog)
|
builder!!.setTitle(R.string.choose_quality_dialog)
|
||||||
.setItems(
|
.setItems(
|
||||||
videosNameArray,
|
videosNameArray
|
||||||
DialogInterface.OnClickListener { _, which ->
|
) { _, which ->
|
||||||
whichQuality = which
|
whichQuality = which
|
||||||
if (response.subtitles.isNotEmpty()) {
|
if (response.subtitles.isNotEmpty()) {
|
||||||
var subtitle =
|
val subtitle =
|
||||||
mutableListOf<SubtitleConfiguration>()
|
mutableListOf<SubtitleConfiguration>()
|
||||||
subtitle.add(
|
subtitle.add(
|
||||||
SubtitleConfiguration.Builder(
|
SubtitleConfiguration.Builder(
|
||||||
response.subtitles[0].url!!.toUri()
|
response.subtitles[0].url!!.toUri()
|
||||||
)
|
|
||||||
.setMimeType(response.subtitles[0].mimeType!!) // The correct MIME type (required).
|
|
||||||
.setLanguage(response.subtitles[0].code) // The subtitle language (optional).
|
|
||||||
.build()
|
|
||||||
)
|
)
|
||||||
}
|
.setMimeType(response.subtitles[0].mimeType!!) // The correct MIME type (required).
|
||||||
if (which == 0) {
|
.setLanguage(response.subtitles[0].code) // The subtitle language (optional).
|
||||||
val mediaItem: MediaItem = MediaItem.Builder()
|
|
||||||
.setUri(response.hls)
|
|
||||||
.setSubtitleConfigurations(subtitle)
|
|
||||||
.build()
|
.build()
|
||||||
exoPlayer.setMediaItem(mediaItem)
|
)
|
||||||
} else {
|
|
||||||
val dataSourceFactory: DataSource.Factory =
|
|
||||||
DefaultHttpDataSource.Factory()
|
|
||||||
val videoItem: MediaItem = MediaItem.Builder()
|
|
||||||
.setUri(response.videoStreams[which - 1].url)
|
|
||||||
.setSubtitleConfigurations(subtitle)
|
|
||||||
.build()
|
|
||||||
val videoSource: MediaSource =
|
|
||||||
DefaultMediaSourceFactory(dataSourceFactory)
|
|
||||||
.createMediaSource(videoItem)
|
|
||||||
var audioSource: MediaSource =
|
|
||||||
DefaultMediaSourceFactory(dataSourceFactory)
|
|
||||||
.createMediaSource(
|
|
||||||
fromUri(response.audioStreams!![0].url!!)
|
|
||||||
)
|
|
||||||
if (response.videoStreams[which - 1].quality == "720p" ||
|
|
||||||
response.videoStreams[which - 1].quality == "1080p" ||
|
|
||||||
response.videoStreams[which - 1].quality == "480p"
|
|
||||||
) {
|
|
||||||
audioSource =
|
|
||||||
ProgressiveMediaSource.Factory(dataSourceFactory)
|
|
||||||
.createMediaSource(
|
|
||||||
fromUri(
|
|
||||||
response.audioStreams[
|
|
||||||
getMostBitRate(
|
|
||||||
response.audioStreams
|
|
||||||
)
|
|
||||||
].url!!
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
val mergeSource: MediaSource =
|
|
||||||
MergingMediaSource(videoSource, audioSource)
|
|
||||||
exoPlayer.setMediaSource(mergeSource)
|
|
||||||
}
|
|
||||||
exoPlayer.seekTo(lastPosition)
|
|
||||||
view.findViewById<TextView>(R.id.quality_text).text =
|
|
||||||
videosNameArray[which]
|
|
||||||
}
|
}
|
||||||
)
|
if (which == 0) {
|
||||||
|
val mediaItem: MediaItem = MediaItem.Builder()
|
||||||
|
.setUri(response.hls)
|
||||||
|
.setSubtitleConfigurations(subtitle)
|
||||||
|
.build()
|
||||||
|
exoPlayer.setMediaItem(mediaItem)
|
||||||
|
} else {
|
||||||
|
val dataSourceFactory: DataSource.Factory =
|
||||||
|
DefaultHttpDataSource.Factory()
|
||||||
|
val videoItem: MediaItem = MediaItem.Builder()
|
||||||
|
.setUri(response.videoStreams[which - 1].url)
|
||||||
|
.setSubtitleConfigurations(subtitle)
|
||||||
|
.build()
|
||||||
|
val videoSource: MediaSource =
|
||||||
|
DefaultMediaSourceFactory(dataSourceFactory)
|
||||||
|
.createMediaSource(videoItem)
|
||||||
|
var audioSource: MediaSource =
|
||||||
|
DefaultMediaSourceFactory(dataSourceFactory)
|
||||||
|
.createMediaSource(
|
||||||
|
fromUri(response.audioStreams!![0].url!!)
|
||||||
|
)
|
||||||
|
if (response.videoStreams[which - 1].quality == "720p" ||
|
||||||
|
response.videoStreams[which - 1].quality == "1080p" ||
|
||||||
|
response.videoStreams[which - 1].quality == "480p"
|
||||||
|
) {
|
||||||
|
audioSource =
|
||||||
|
ProgressiveMediaSource.Factory(dataSourceFactory)
|
||||||
|
.createMediaSource(
|
||||||
|
fromUri(
|
||||||
|
response.audioStreams[
|
||||||
|
getMostBitRate(
|
||||||
|
response.audioStreams
|
||||||
|
)
|
||||||
|
].url!!
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val mergeSource: MediaSource =
|
||||||
|
MergingMediaSource(videoSource, audioSource)
|
||||||
|
exoPlayer.setMediaSource(mergeSource)
|
||||||
|
}
|
||||||
|
exoPlayer.seekTo(lastPosition)
|
||||||
|
view.findViewById<TextView>(R.id.quality_text).text =
|
||||||
|
videosNameArray[which]
|
||||||
|
}
|
||||||
val dialog = builder.create()
|
val dialog = builder.create()
|
||||||
dialog.show()
|
dialog.show()
|
||||||
}
|
}
|
||||||
@ -822,8 +861,6 @@ class PlayerFragment : Fragment() {
|
|||||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||||
val playbackSpeed = sharedPreferences.getString("playback_speed", "1F")?.toFloat()
|
val playbackSpeed = sharedPreferences.getString("playback_speed", "1F")?.toFloat()
|
||||||
exoPlayer.setPlaybackSpeed(playbackSpeed!!)
|
exoPlayer.setPlaybackSpeed(playbackSpeed!!)
|
||||||
|
|
||||||
initializePlayerNotification(requireContext())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initializePlayerNotification(c: Context) {
|
private fun initializePlayerNotification(c: Context) {
|
||||||
@ -838,6 +875,9 @@ class PlayerFragment : Fragment() {
|
|||||||
|
|
||||||
playerNotification = PlayerNotificationManager
|
playerNotification = PlayerNotificationManager
|
||||||
.Builder(c, 1, "background_mode")
|
.Builder(c, 1, "background_mode")
|
||||||
|
.setMediaDescriptionAdapter(
|
||||||
|
DescriptionAdapter(title, uploader, thumbnailUrl)
|
||||||
|
)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
playerNotification.apply {
|
playerNotification.apply {
|
||||||
|
@ -198,7 +198,6 @@ class SearchFragment : Fragment() {
|
|||||||
lifecycleScope.launchWhenCreated {
|
lifecycleScope.launchWhenCreated {
|
||||||
isFetchingSearch = true
|
isFetchingSearch = true
|
||||||
hideKeyboard()
|
hideKeyboard()
|
||||||
Log.e("here", "here")
|
|
||||||
val response = try {
|
val response = try {
|
||||||
RetrofitInstance.api.getSearchResults(query, apiSearchFilter)
|
RetrofitInstance.api.getSearchResults(query, apiSearchFilter)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
|
@ -29,40 +29,42 @@ class AboutFragment : Fragment() {
|
|||||||
val topBarText = activity?.findViewById<TextView>(R.id.topBar_textView)
|
val topBarText = activity?.findViewById<TextView>(R.id.topBar_textView)
|
||||||
topBarText?.text = getString(R.string.about)
|
topBarText?.text = getString(R.string.about)
|
||||||
|
|
||||||
val appVersion = view?.findViewById<TextView>(R.id.app_version)
|
val appVersion = view.findViewById<TextView>(R.id.app_version)
|
||||||
appVersion.text = BuildConfig.VERSION_NAME
|
appVersion.text = BuildConfig.VERSION_NAME
|
||||||
|
|
||||||
val website = view?.findViewById<LinearLayout>(R.id.website)
|
val website = view.findViewById<LinearLayout>(R.id.website)
|
||||||
website?.setOnClickListener {
|
website.setOnClickListener {
|
||||||
openLinkFromHref("https://libre-tube.github.io/")
|
openLinkFromHref("https://libre-tube.github.io/")
|
||||||
}
|
}
|
||||||
val authors = view?.findViewById<LinearLayout>(R.id.authors)
|
val authors = view.findViewById<LinearLayout>(R.id.authors)
|
||||||
authors?.setOnClickListener {
|
authors.setOnClickListener {
|
||||||
openLinkFromHref("https://github.com/libre-tube/LibreTube/graphs/contributors")
|
openLinkFromHref("https://github.com/libre-tube/LibreTube/graphs/contributors")
|
||||||
}
|
}
|
||||||
val donate = view?.findViewById<LinearLayout>(R.id.donate)
|
val donate = view.findViewById<LinearLayout>(R.id.donate)
|
||||||
donate?.setOnClickListener {
|
donate.setOnClickListener {
|
||||||
openLinkFromHref("https://libre-tube.github.io/#donate")
|
openLinkFromHref("https://libre-tube.github.io/#donate")
|
||||||
}
|
}
|
||||||
val contributing = view?.findViewById<LinearLayout>(R.id.contributing)
|
val contributing = view.findViewById<LinearLayout>(R.id.contributing)
|
||||||
contributing?.setOnClickListener {
|
contributing.setOnClickListener {
|
||||||
openLinkFromHref("https://github.com/libre-tube/LibreTube")
|
openLinkFromHref("https://github.com/libre-tube/LibreTube")
|
||||||
}
|
}
|
||||||
val license = view.findViewById<LinearLayout>(R.id.license)
|
val license = view.findViewById<LinearLayout>(R.id.license)
|
||||||
license?.setOnClickListener {
|
license.setOnClickListener {
|
||||||
val licenseString = view?.context?.assets!!
|
val licenseString = view.context.assets
|
||||||
.open("gpl3.html").bufferedReader().use {
|
.open("gpl3.html").bufferedReader().use {
|
||||||
it.readText()
|
it.readText()
|
||||||
}
|
}
|
||||||
val licenseHtml = if (Build.VERSION.SDK_INT >= 24) Html.fromHtml(licenseString, 1)
|
val licenseHtml = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
else Html.fromHtml(licenseString)
|
Html.fromHtml(licenseString, 1)
|
||||||
|
} else {
|
||||||
|
Html.fromHtml(licenseString)
|
||||||
|
}
|
||||||
|
|
||||||
MaterialAlertDialogBuilder(view?.context!!)
|
MaterialAlertDialogBuilder(view.context!!)
|
||||||
.setPositiveButton(getString(R.string.okay)) { _, _ -> }
|
.setPositiveButton(getString(R.string.okay)) { _, _ -> }
|
||||||
.setMessage(licenseHtml)
|
.setMessage(licenseHtml)
|
||||||
.create()
|
.create()
|
||||||
.show()
|
.show()
|
||||||
true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,6 @@ import android.widget.TextView
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.app.ActivityCompat.recreate
|
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
@ -30,7 +29,6 @@ import java.io.IOException
|
|||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.util.zip.ZipEntry
|
import java.util.zip.ZipEntry
|
||||||
import java.util.zip.ZipInputStream
|
import java.util.zip.ZipInputStream
|
||||||
import org.chromium.base.ThreadUtils.runOnUiThread
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import org.json.JSONTokener
|
import org.json.JSONTokener
|
||||||
import retrofit2.HttpException
|
import retrofit2.HttpException
|
||||||
|
@ -17,6 +17,9 @@ class SponsorBlockSettings : PreferenceFragmentCompat() {
|
|||||||
var interactionEnabled: Boolean = false
|
var interactionEnabled: Boolean = false
|
||||||
var introEnabled: Boolean = false
|
var introEnabled: Boolean = false
|
||||||
var outroEnabled: Boolean = false
|
var outroEnabled: Boolean = false
|
||||||
|
var fillerEnabled: Boolean = false
|
||||||
|
var musicOfftopicEnabled: Boolean = false
|
||||||
|
var previewEnabled: Boolean = false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
@ -65,5 +68,23 @@ class SponsorBlockSettings : PreferenceFragmentCompat() {
|
|||||||
outroEnabled = newValue as Boolean
|
outroEnabled = newValue as Boolean
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val fillerToggle = findPreference<SwitchPreferenceCompat>("filler_category_key")
|
||||||
|
fillerToggle?.setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
fillerEnabled = newValue as Boolean
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
val musicToggle = findPreference<SwitchPreferenceCompat>("music_offtopic_category_key")
|
||||||
|
musicToggle?.setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
musicOfftopicEnabled = newValue as Boolean
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
val previewToggle = findPreference<SwitchPreferenceCompat>("preview_category_key")
|
||||||
|
previewToggle?.setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
previewEnabled = newValue as Boolean
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,55 @@
|
|||||||
|
package com.github.libretube.util
|
||||||
|
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
|
import com.google.android.exoplayer2.Player
|
||||||
|
import com.google.android.exoplayer2.ui.PlayerNotificationManager
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
|
// used to show title and thumbnail of the video in the notification
|
||||||
|
class DescriptionAdapter(
|
||||||
|
private val title: String,
|
||||||
|
private val channelName: String,
|
||||||
|
private val thumbnailUrl: String
|
||||||
|
) :
|
||||||
|
PlayerNotificationManager.MediaDescriptionAdapter {
|
||||||
|
override fun getCurrentContentTitle(player: Player): CharSequence {
|
||||||
|
// return controller.metadata.description.title.toString()
|
||||||
|
return title
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createCurrentContentIntent(player: Player): PendingIntent? {
|
||||||
|
// return controller.sessionActivity
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getCurrentContentText(player: Player): CharSequence? {
|
||||||
|
// return controller.metadata.description.subtitle.toString()
|
||||||
|
return channelName
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getCurrentLargeIcon(
|
||||||
|
player: Player,
|
||||||
|
callback: PlayerNotificationManager.BitmapCallback
|
||||||
|
): Bitmap? {
|
||||||
|
lateinit var bitmap: Bitmap
|
||||||
|
val thread = Thread {
|
||||||
|
try {
|
||||||
|
// try to parse the thumbnailUrl to a Bitmap
|
||||||
|
val inputStream = URL(thumbnailUrl).openStream()
|
||||||
|
bitmap = BitmapFactory.decodeStream(inputStream)
|
||||||
|
} catch (ex: java.lang.Exception) {
|
||||||
|
ex.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
thread.start()
|
||||||
|
thread.join()
|
||||||
|
// return bitmap if initialized
|
||||||
|
return try {
|
||||||
|
bitmap
|
||||||
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,9 +3,9 @@
|
|||||||
android:height="144dp"
|
android:height="144dp"
|
||||||
android:viewportWidth="143"
|
android:viewportWidth="143"
|
||||||
android:viewportHeight="144"
|
android:viewportHeight="144"
|
||||||
android:tint="?android:attr/colorControlNormal" >
|
android:tint="?android:attr/colorControlNormal">
|
||||||
<path
|
<path
|
||||||
android:pathData="M35.74,87.66L35.74,41.39c0,-1.44 0.54,-2.7 1.61,-3.78 1.07,-1.08 2.32,-1.62 3.75,-1.62h45.95v5.4L41.11,41.39L41.11,87.66ZM46.47,98.47L46.47,52.2c0,-1.44 0.54,-2.7 1.61,-3.78 1.07,-1.08 2.32,-1.62 3.75,-1.62h45.95v5.4L51.83,52.2L51.83,98.47ZM101.89,108.01L62.56,108.01c-1.43,0 -2.68,-0.54 -3.75,-1.62 -1.07,-1.08 -1.61,-2.34 -1.61,-3.78L57.2,63c0,-1.44 0.54,-2.7 1.61,-3.78 1.07,-1.08 2.32,-1.62 3.75,-1.62h39.33c1.43,0 2.68,0.54 3.75,1.62 1.07,1.08 1.61,2.34 1.61,3.78v39.61c0,1.44 -0.54,2.7 -1.61,3.78 -1.07,1.08 -2.32,1.62 -3.75,1.62zM101.89,102.61L101.89,63L62.56,63L62.56,102.61ZM62.56,63v39.61z"
|
android:pathData="M35.74,87.66L35.74,41.39c0,-1.44 0.54,-2.7 1.61,-3.78 1.07,-1.08 2.32,-1.62 3.75,-1.62h45.95v5.4L41.11,41.39L41.11,87.66ZM46.47,98.47L46.47,52.2c0,-1.44 0.54,-2.7 1.61,-3.78 1.07,-1.08 2.32,-1.62 3.75,-1.62h45.95v5.4L51.83,52.2L51.83,98.47ZM101.89,108.01L62.56,108.01c-1.43,0 -2.68,-0.54 -3.75,-1.62 -1.07,-1.08 -1.61,-2.34 -1.61,-3.78L57.2,63c0,-1.44 0.54,-2.7 1.61,-3.78 1.07,-1.08 2.32,-1.62 3.75,-1.62h39.33c1.43,0 2.68,0.54 3.75,1.62 1.07,1.08 1.61,2.34 1.61,3.78v39.61c0,1.44 -0.54,2.7 -1.61,3.78 -1.07,1.08 -2.32,1.62 -3.75,1.62zM101.89,102.61L101.89,63L62.56,63L62.56,102.61ZM62.56,63v39.61z"
|
||||||
android:strokeWidth="1"
|
android:strokeWidth="1"
|
||||||
android:fillColor="#120807"/>
|
android:fillColor="#120807" />
|
||||||
</vector>
|
</vector>
|
||||||
|
24
app/src/main/res/layout/chapter_column.xml
Normal file
24
app/src/main/res/layout/chapter_column.xml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_marginHorizontal="10dp"
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/chapter_image"
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="45dp"
|
||||||
|
android:src="@mipmap/ic_launcher" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/chapter_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="3dp"
|
||||||
|
android:maxLines="3"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:text="Title"
|
||||||
|
android:textSize="13sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -9,105 +9,106 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
<LinearLayout
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingBottom="16dp">
|
|
||||||
|
|
||||||
<de.hdodenhof.circleimageview.CircleImageView
|
|
||||||
android:id="@+id/commentor_image"
|
|
||||||
android:layout_width="30dp"
|
|
||||||
android:layout_height="30dp"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
app:srcCompat="@mipmap/ic_launcher" />
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:paddingBottom="16dp">
|
||||||
|
|
||||||
|
<de.hdodenhof.circleimageview.CircleImageView
|
||||||
|
android:id="@+id/commentor_image"
|
||||||
|
android:layout_width="30dp"
|
||||||
|
android:layout_height="30dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
app:srcCompat="@mipmap/ic_launcher" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/comment_infos"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:maxLines="2"
|
|
||||||
android:text="Author and Time"
|
|
||||||
android:textSize="15sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/verified_imageView"
|
|
||||||
android:layout_width="16dp"
|
|
||||||
android:layout_height="16dp"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:layout_marginLeft="4dp"
|
|
||||||
app:srcCompat="@drawable/ic_verified"
|
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/pinned_imageView"
|
|
||||||
android:layout_width="16dp"
|
|
||||||
android:layout_height="16dp"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:layout_marginLeft="4dp"
|
|
||||||
app:srcCompat="@drawable/ic_pinned"
|
|
||||||
android:visibility="gone" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/comment_text"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="4dp"
|
android:orientation="vertical">
|
||||||
android:autoLink="web"
|
|
||||||
android:text="Comment Text" />
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<ImageView
|
<TextView
|
||||||
android:id="@+id/likes_imageView"
|
android:id="@+id/comment_infos"
|
||||||
android:layout_width="16dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="16dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginRight="6dp"
|
android:ellipsize="end"
|
||||||
android:layout_marginTop="2dp"
|
android:maxLines="2"
|
||||||
app:srcCompat="@drawable/ic_thumb_up" />
|
android:text="Author and Time"
|
||||||
|
android:textSize="15sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/verified_imageView"
|
||||||
|
android:layout_width="16dp"
|
||||||
|
android:layout_height="16dp"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:layout_marginLeft="4dp"
|
||||||
|
app:srcCompat="@drawable/ic_verified"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/pinned_imageView"
|
||||||
|
android:layout_width="16dp"
|
||||||
|
android:layout_height="16dp"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:layout_marginLeft="4dp"
|
||||||
|
app:srcCompat="@drawable/ic_pinned"
|
||||||
|
android:visibility="gone" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/likes_textView"
|
android:id="@+id/comment_text"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="LikeCount" />
|
android:layout_marginBottom="4dp"
|
||||||
|
android:autoLink="web"
|
||||||
|
android:text="Comment Text" />
|
||||||
|
|
||||||
<ImageView
|
<LinearLayout
|
||||||
android:id="@+id/hearted_imageView"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="14dp"
|
android:layout_height="match_parent"
|
||||||
android:layout_height="14dp"
|
android:orientation="horizontal">
|
||||||
android:layout_marginLeft="8dp"
|
|
||||||
android:layout_marginTop="3dp"
|
<ImageView
|
||||||
app:srcCompat="@drawable/ic_hearted"
|
android:id="@+id/likes_imageView"
|
||||||
android:visibility="gone" />
|
android:layout_width="16dp"
|
||||||
|
android:layout_height="16dp"
|
||||||
|
android:layout_marginRight="6dp"
|
||||||
|
android:layout_marginTop="2dp"
|
||||||
|
app:srcCompat="@drawable/ic_thumb_up" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/likes_textView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="LikeCount" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/hearted_imageView"
|
||||||
|
android:layout_width="14dp"
|
||||||
|
android:layout_height="14dp"
|
||||||
|
android:layout_marginLeft="8dp"
|
||||||
|
android:layout_marginTop="3dp"
|
||||||
|
app:srcCompat="@drawable/ic_hearted"
|
||||||
|
android:visibility="gone" />
|
||||||
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/replies_recView"
|
android:id="@+id/replies_recView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="16dp"
|
android:layout_marginLeft="16dp"
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:nestedScrollingEnabled="false" />
|
android:nestedScrollingEnabled="false" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
@ -39,7 +39,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingHorizontal="20dp" android:paddingVertical="10dp">
|
android:paddingHorizontal="20dp"
|
||||||
|
android:paddingVertical="10dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -59,7 +60,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingHorizontal="20dp" android:paddingVertical="10dp">
|
android:paddingHorizontal="20dp"
|
||||||
|
android:paddingVertical="10dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -79,7 +81,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingHorizontal="20dp" android:paddingVertical="10dp">
|
android:paddingHorizontal="20dp"
|
||||||
|
android:paddingVertical="10dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -99,7 +102,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingHorizontal="20dp" android:paddingVertical="10dp">
|
android:paddingHorizontal="20dp"
|
||||||
|
android:paddingVertical="10dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -119,7 +123,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingHorizontal="20dp" android:paddingVertical="10dp">
|
android:paddingHorizontal="20dp"
|
||||||
|
android:paddingVertical="10dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -26,15 +26,16 @@
|
|||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
|
android:id="@+id/player_title_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/player_title_layout"
|
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/player_title"
|
android:id="@+id/player_title"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:layout_marginEnd="30dp"
|
android:layout_marginEnd="30dp"
|
||||||
@ -54,14 +55,54 @@
|
|||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<TextView
|
<RelativeLayout
|
||||||
android:id="@+id/player_views_info"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="10dp"
|
android:layout_marginHorizontal="10dp"
|
||||||
android:layout_marginTop="5dp"
|
android:layout_marginTop="5dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/player_views_info"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="10M views 2 days ago " />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/chapters_toggle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/chapters_toggle_text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/show_chapters" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/chapters_toggle_arrow"
|
||||||
|
android:layout_width="16dp"
|
||||||
|
android:layout_height="16dp"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:src="@drawable/ic_arrow_down" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/chapters_recView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/comments_toggle"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
android:layout_marginRight="10dp"
|
android:layout_marginRight="10dp"
|
||||||
android:text="10M views 2 days ago " />
|
android:nestedScrollingEnabled="false"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/player_description"
|
android:id="@+id/player_description"
|
||||||
@ -146,10 +187,10 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:autoSizeTextType="uniform"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="@string/download"
|
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:autoSizeTextType="uniform" />
|
android:text="@string/download" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@ -203,8 +244,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:layout_marginTop="15dp"
|
android:layout_marginTop="15dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_marginBottom="15dp"
|
android:layout_marginBottom="15dp"
|
||||||
android:background="?android:attr/selectableItemBackground"
|
android:background="?android:attr/selectableItemBackground"
|
||||||
android:paddingLeft="8dp"
|
android:paddingLeft="8dp"
|
||||||
@ -294,10 +335,10 @@
|
|||||||
android:id="@+id/comments_recView"
|
android:id="@+id/comments_recView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="20dp"
|
|
||||||
android:layout_marginLeft="20dp"
|
|
||||||
android:layout_marginRight="20dp"
|
|
||||||
android:layout_below="@id/comments_toggle"
|
android:layout_below="@id/comments_toggle"
|
||||||
|
android:layout_marginLeft="20dp"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:layout_marginRight="20dp"
|
||||||
android:nestedScrollingEnabled="false"
|
android:nestedScrollingEnabled="false"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="8dp"
|
android:layout_marginHorizontal="8dp"
|
||||||
android:paddingVertical="6dp"
|
android:paddingVertical="8dp"
|
||||||
android:background="?android:attr/selectableItemBackground">
|
android:background="?android:attr/selectableItemBackground">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
|
@ -100,6 +100,12 @@
|
|||||||
<string name="category_intro_description">An interval without actual content. Could be a pause, static frame, repeating animation. Should not be used for transitions containing info.</string>
|
<string name="category_intro_description">An interval without actual content. Could be a pause, static frame, repeating animation. Should not be used for transitions containing info.</string>
|
||||||
<string name="category_outro">End cards and credits</string>
|
<string name="category_outro">End cards and credits</string>
|
||||||
<string name="category_outro_description">Info following the ending. Not for conclusions with info.</string>
|
<string name="category_outro_description">Info following the ending. Not for conclusions with info.</string>
|
||||||
|
<string name="category_filler">Filler Tangent/Jokes</string>
|
||||||
|
<string name="category_filler_description">This is for tangential scenes added only for filler or humor that are not required to understand the main content of the video.</string>
|
||||||
|
<string name="category_music_offtopic">Music: Non-Music Section</string>
|
||||||
|
<string name="category_music_offtopic_description">This is only for use in music videos. It should cover parts of the video not part of official mixes. In the end, the video should resemble the Spotify or any other mix version as closely as possible, or should reduce talking or other distractions.</string>
|
||||||
|
<string name="category_preview">Preview/Recap</string>
|
||||||
|
<string name="category_preview_description">For segments that show what is coming up in this or future videos of the same series, but do not provide additional information. If it includes clips that only appear here, this is very likely not the right category.</string>
|
||||||
<string name="license">License</string>
|
<string name="license">License</string>
|
||||||
<string name="color_accent">Accents</string>
|
<string name="color_accent">Accents</string>
|
||||||
<string name="color_red">Resting red</string>
|
<string name="color_red">Resting red</string>
|
||||||
@ -173,4 +179,6 @@
|
|||||||
<string name="about_summary">Get to know team LibreTube and how it all happens.</string>
|
<string name="about_summary">Get to know team LibreTube and how it all happens.</string>
|
||||||
<string name="related_streams">Related streams</string>
|
<string name="related_streams">Related streams</string>
|
||||||
<string name="related_streams_summary">Show related streams to videos.</string>
|
<string name="related_streams_summary">Show related streams to videos.</string>
|
||||||
|
<string name="show_chapters">Show chapters</string>
|
||||||
|
<string name="hide_chapters">Hide chapters</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -5,21 +5,21 @@
|
|||||||
<PreferenceCategory app:title="@string/player">
|
<PreferenceCategory app:title="@string/player">
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
app:title="@string/defres"
|
android:icon="@drawable/ic_hd"
|
||||||
app:key="default_res"
|
app:defaultValue=""
|
||||||
app:entries="@array/defres"
|
app:entries="@array/defres"
|
||||||
app:entryValues="@array/defresValue"
|
app:entryValues="@array/defresValue"
|
||||||
app:defaultValue=""
|
app:key="default_res"
|
||||||
android:icon="@drawable/ic_hd"
|
app:title="@string/defres"
|
||||||
app:useSimpleSummaryProvider="true" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
app:title="@string/playback_speed"
|
android:icon="@drawable/ic_play"
|
||||||
app:key="playback_speed"
|
app:defaultValue="1F"
|
||||||
app:entries="@array/playbackSpeed"
|
app:entries="@array/playbackSpeed"
|
||||||
app:entryValues="@array/playbackSpeedValues"
|
app:entryValues="@array/playbackSpeedValues"
|
||||||
app:defaultValue="1F"
|
app:key="playback_speed"
|
||||||
android:icon="@drawable/ic_play"
|
app:title="@string/playback_speed"
|
||||||
app:useSimpleSummaryProvider="true" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
@ -27,55 +27,44 @@
|
|||||||
<PreferenceCategory app:title="@string/downloads">
|
<PreferenceCategory app:title="@string/downloads">
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
app:key="video_format"
|
app:defaultValue=".mp4"
|
||||||
app:title="@string/video_format"
|
|
||||||
app:entries="@array/videoFormats"
|
app:entries="@array/videoFormats"
|
||||||
app:entryValues="@array/videoFormatsValues"
|
app:entryValues="@array/videoFormatsValues"
|
||||||
app:defaultValue=".mp4"
|
app:icon="@drawable/ic_videocam"
|
||||||
|
app:key="video_format"
|
||||||
app:summary="@string/video_format_summary"
|
app:summary="@string/video_format_summary"
|
||||||
app:icon="@drawable/ic_videocam" />
|
app:title="@string/video_format" />
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
app:key="download_location"
|
|
||||||
app:title="@string/download_directory"
|
|
||||||
app:summary="@string/download_directory_summary"
|
|
||||||
android:defaultValue="downloads"
|
android:defaultValue="downloads"
|
||||||
android:entries="@array/downloadLocation"
|
android:entries="@array/downloadLocation"
|
||||||
android:entryValues="@array/downloadLocationValues"
|
android:entryValues="@array/downloadLocationValues"
|
||||||
app:icon="@drawable/ic_download" />
|
app:icon="@drawable/ic_download"
|
||||||
|
app:key="download_location"
|
||||||
|
app:summary="@string/download_directory_summary"
|
||||||
|
app:title="@string/download_directory" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
app:key="download_folder"
|
android:defaultValue="LibreTube"
|
||||||
app:title="@string/download_folder"
|
|
||||||
app:summary="@string/download_folder_summary"
|
|
||||||
app:icon="@drawable/ic_folder"
|
app:icon="@drawable/ic_folder"
|
||||||
android:defaultValue="LibreTube" />
|
app:key="download_folder"
|
||||||
|
app:summary="@string/download_folder_summary"
|
||||||
|
app:title="@string/download_folder" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory app:title="@string/search_history">
|
<PreferenceCategory app:title="@string/search_history">
|
||||||
|
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
app:title="@string/search_history"
|
|
||||||
app:key="search_history_toggle"
|
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
android:icon="@drawable/ic_history" />
|
android:icon="@drawable/ic_history"
|
||||||
|
app:key="search_history_toggle"
|
||||||
|
app:title="@string/search_history" />
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
app:title="@string/clear_history"
|
android:icon="@drawable/ic_trash"
|
||||||
app:key="clear_history"
|
app:key="clear_history"
|
||||||
android:icon="@drawable/ic_trash" />
|
app:title="@string/clear_history" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
|
||||||
|
|
||||||
<PreferenceCategory>
|
|
||||||
|
|
||||||
<SwitchPreference
|
|
||||||
app:key="related_streams_toggle"
|
|
||||||
app:title="@string/related_streams"
|
|
||||||
app:summary="@string/related_streams_summary"
|
|
||||||
android:defaultValue="true"
|
|
||||||
android:icon="@drawable/ic_list"/>
|
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
@ -5,30 +5,30 @@
|
|||||||
<PreferenceCategory app:title="@string/appearance">
|
<PreferenceCategory app:title="@string/appearance">
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
app:title="@string/app_theme"
|
android:icon="@drawable/ic_theme"
|
||||||
app:key="theme_togglee"
|
app:defaultValue="A"
|
||||||
app:entries="@array/themes"
|
app:entries="@array/themes"
|
||||||
app:entryValues="@array/themesValue"
|
app:entryValues="@array/themesValue"
|
||||||
app:defaultValue="A"
|
app:key="theme_togglee"
|
||||||
android:icon="@drawable/ic_theme"
|
app:title="@string/app_theme"
|
||||||
app:useSimpleSummaryProvider="true" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
app:title="@string/color_accent"
|
android:icon="@drawable/ic_color"
|
||||||
app:key="accent_color"
|
app:defaultValue="red"
|
||||||
app:entries="@array/accents"
|
app:entries="@array/accents"
|
||||||
app:entryValues="@array/accentsValue"
|
app:entryValues="@array/accentsValue"
|
||||||
app:defaultValue="red"
|
app:key="accent_color"
|
||||||
android:icon="@drawable/ic_color"
|
app:title="@string/color_accent"
|
||||||
app:useSimpleSummaryProvider="true" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
app:title="@string/app_icon"
|
android:icon="@drawable/ic_frame"
|
||||||
app:key="icon_change"
|
app:defaultValue="MainActivity"
|
||||||
app:entries="@array/icons"
|
app:entries="@array/icons"
|
||||||
app:entryValues="@array/iconsValue"
|
app:entryValues="@array/iconsValue"
|
||||||
app:defaultValue="MainActivity"
|
app:key="icon_change"
|
||||||
android:icon="@drawable/ic_frame"
|
app:title="@string/app_icon"
|
||||||
app:useSimpleSummaryProvider="true" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
@ -36,23 +36,34 @@
|
|||||||
<PreferenceCategory app:title="@string/app_behavior">
|
<PreferenceCategory app:title="@string/app_behavior">
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
app:title="@string/defaultTab"
|
android:icon="@drawable/ic_home"
|
||||||
app:key="default_tab"
|
app:defaultValue="home"
|
||||||
app:entries="@array/tabs"
|
app:entries="@array/tabs"
|
||||||
app:entryValues="@array/tabsValue"
|
app:entryValues="@array/tabsValue"
|
||||||
app:defaultValue="home"
|
app:key="default_tab"
|
||||||
android:icon="@drawable/ic_home"
|
app:title="@string/defaultTab"
|
||||||
app:useSimpleSummaryProvider="true" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
app:title="@string/grid"
|
android:icon="@drawable/ic_grid"
|
||||||
app:key="grid"
|
app:defaultValue="@integer/grid_items"
|
||||||
app:entries="@array/grid"
|
app:entries="@array/grid"
|
||||||
app:entryValues="@array/grid"
|
app:entryValues="@array/grid"
|
||||||
app:defaultValue="@integer/grid_items"
|
app:key="grid"
|
||||||
android:icon="@drawable/ic_grid"
|
app:title="@string/grid"
|
||||||
app:useSimpleSummaryProvider="true" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<PreferenceCategory>
|
||||||
|
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:icon="@drawable/ic_list"
|
||||||
|
app:key="related_streams_toggle"
|
||||||
|
app:summary="@string/related_streams_summary"
|
||||||
|
app:title="@string/related_streams" />
|
||||||
|
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
@ -41,6 +41,21 @@
|
|||||||
app:title="@string/category_outro"
|
app:title="@string/category_outro"
|
||||||
app:summary="@string/category_outro_description" />
|
app:summary="@string/category_outro_description" />
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
app:key="filler_category_key"
|
||||||
|
app:title="@string/category_filler"
|
||||||
|
app:summary="@string/category_filler_description" />
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
app:key="music_offtopic_category_key"
|
||||||
|
app:title="@string/category_music_offtopic"
|
||||||
|
app:summary="@string/category_music_offtopic_description" />
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
app:key="preview_category_key"
|
||||||
|
app:title="@string/category_preview"
|
||||||
|
app:summary="@string/category_preview_description" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
@ -6,7 +6,7 @@ buildscript {
|
|||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.2.1'
|
classpath 'com.android.tools.build:gradle:7.2.1'
|
||||||
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21'
|
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.0'
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
|
Loading…
Reference in New Issue
Block a user