mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-01-06 01:20:29 +05:30
Merge branch 'master' into import-fix
This commit is contained in:
commit
fd9a07bef3
@ -47,7 +47,9 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
packagingOptions {
|
packagingOptions {
|
||||||
exclude 'lib/armeabi-v7a/*_neon.so'
|
jniLibs {
|
||||||
|
excludes += ['lib/armeabi-v7a/*_neon.so']
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,9 +58,9 @@ dependencies {
|
|||||||
|
|
||||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||||
implementation 'com.google.android.material:material:1.6.0-alpha02'
|
implementation 'com.google.android.material:material:1.6.0-beta01'
|
||||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.4.1'
|
implementation 'androidx.navigation:navigation-fragment-ktx:2.4.2'
|
||||||
implementation 'androidx.navigation:navigation-ui-ktx:2.4.1'
|
implementation 'androidx.navigation:navigation-ui-ktx:2.4.2'
|
||||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||||
implementation 'androidx.preference:preference-ktx:1.2.0'
|
implementation 'androidx.preference:preference-ktx:1.2.0'
|
||||||
|
|
||||||
@ -77,5 +79,11 @@ dependencies {
|
|||||||
|
|
||||||
implementation 'com.arthenica:ffmpeg-kit-min:4.5.1.LTS'
|
implementation 'com.arthenica:ffmpeg-kit-min:4.5.1.LTS'
|
||||||
|
|
||||||
|
|
||||||
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5"
|
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5"
|
||||||
|
implementation 'com.google.android.exoplayer:extension-cronet:2.17.1'
|
||||||
|
implementation 'org.chromium.net:cronet-embedded:98.4758.101'
|
||||||
|
|
||||||
|
implementation 'com.blankj:utilcode:1.30.0'
|
||||||
|
|
||||||
}
|
}
|
@ -19,22 +19,21 @@ class CreatePlaylistDialog : DialogFragment() {
|
|||||||
// Get the layout inflater
|
// Get the layout inflater
|
||||||
val inflater = requireActivity().layoutInflater;
|
val inflater = requireActivity().layoutInflater;
|
||||||
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
|
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
|
||||||
val token = sharedPref?.getString("token", "")
|
val token = sharedPref?.getString("token","")
|
||||||
Log.e("dafaq", token!!)
|
var view: View = inflater.inflate(R.layout.dialog_createplaylist, null)
|
||||||
|
Log.e("dafaq",token!!)
|
||||||
assert(token != "")
|
if(token!=""){
|
||||||
|
val sharedPref2 = context?.getSharedPreferences("username", Context.MODE_PRIVATE)
|
||||||
val sharedPref2 = context?.getSharedPreferences("username", Context.MODE_PRIVATE)
|
val user = sharedPref2?.getString("username","")
|
||||||
val user = sharedPref2?.getString("username", "")
|
view.findViewById<TextView>(R.id.user).text = view.findViewById<TextView>(R.id.user).text.toString()+" ("+user+")"
|
||||||
val view: View = inflater.inflate(R.layout.dialog_logout, null)
|
view.findViewById<Button>(R.id.logout).setOnClickListener {
|
||||||
view.findViewById<TextView>(R.id.user).text =
|
Toast.makeText(context,R.string.loggedout, Toast.LENGTH_SHORT).show()
|
||||||
view.findViewById<TextView>(R.id.user).text.toString() + " (" + user + ")"
|
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
|
||||||
view.findViewById<Button>(R.id.logout).setOnClickListener {
|
with (sharedPref!!.edit()) {
|
||||||
Toast.makeText(context, R.string.loggedout, Toast.LENGTH_SHORT).show()
|
putString("token","")
|
||||||
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
|
apply()
|
||||||
with(sharedPref!!.edit()) {
|
}
|
||||||
putString("token", "")
|
dialog?.dismiss()
|
||||||
apply()
|
|
||||||
}
|
}
|
||||||
dialog?.dismiss()
|
dialog?.dismiss()
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,7 @@ import androidx.fragment.app.Fragment
|
|||||||
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.ImageView
|
import android.widget.*
|
||||||
import android.widget.ScrollView
|
|
||||||
import android.widget.TextView
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
@ -19,6 +16,7 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
|||||||
import com.github.libretube.adapters.ChannelAdapter
|
import com.github.libretube.adapters.ChannelAdapter
|
||||||
import com.github.libretube.adapters.PlaylistsAdapter
|
import com.github.libretube.adapters.PlaylistsAdapter
|
||||||
import com.github.libretube.adapters.SubscriptionAdapter
|
import com.github.libretube.adapters.SubscriptionAdapter
|
||||||
|
import com.github.libretube.obj.Playlists
|
||||||
import com.squareup.picasso.Picasso
|
import com.squareup.picasso.Picasso
|
||||||
import retrofit2.HttpException
|
import retrofit2.HttpException
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
@ -61,6 +59,19 @@ class Library : Fragment() {
|
|||||||
Log.d(TAG,"hmm")
|
Log.d(TAG,"hmm")
|
||||||
fetchPlaylists(view)
|
fetchPlaylists(view)
|
||||||
}
|
}
|
||||||
|
val playlistName = view.findViewById<EditText>(R.id.playlists_name)
|
||||||
|
view.findViewById<Button>(R.id.create_playlist).setOnClickListener {
|
||||||
|
if(playlistName.text.toString()!="") createPlaylist(playlistName.text.toString(),view)
|
||||||
|
}
|
||||||
|
} else{
|
||||||
|
with(view.findViewById<ImageView>(R.id.boogh2)){
|
||||||
|
visibility=View.VISIBLE
|
||||||
|
setImageResource(R.drawable.ic_login)
|
||||||
|
}
|
||||||
|
with(view.findViewById<TextView>(R.id.textLike2)){
|
||||||
|
visibility=View.VISIBLE
|
||||||
|
text = getString(R.string.please_login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,14 +125,14 @@ class Library : Fragment() {
|
|||||||
fun run() {
|
fun run() {
|
||||||
lifecycleScope.launchWhenCreated {
|
lifecycleScope.launchWhenCreated {
|
||||||
val response = try {
|
val response = try {
|
||||||
RetrofitInstance.api.createPlaylist(token, name)
|
RetrofitInstance.api.createPlaylist(token, Playlists(name = name))
|
||||||
}catch(e: IOException) {
|
}catch(e: IOException) {
|
||||||
println(e)
|
println(e)
|
||||||
Log.e(TAG, "IOException, you might not have internet connection")
|
Log.e(TAG, "IOException, you might not have internet connection")
|
||||||
Toast.makeText(context,R.string.unknown_error, Toast.LENGTH_SHORT).show()
|
Toast.makeText(context,R.string.unknown_error, Toast.LENGTH_SHORT).show()
|
||||||
return@launchWhenCreated
|
return@launchWhenCreated
|
||||||
} catch (e: HttpException) {
|
} catch (e: HttpException) {
|
||||||
Log.e(TAG, "HttpException, unexpected response")
|
Log.e(TAG, "HttpException, unexpected response $e")
|
||||||
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
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ interface PipedApi {
|
|||||||
suspend fun deletePlaylist(@Header("Authorization") token: String, @Body playlistId: PlaylistId): Message
|
suspend fun deletePlaylist(@Header("Authorization") token: String, @Body playlistId: PlaylistId): Message
|
||||||
|
|
||||||
@POST("user/playlists/create")
|
@POST("user/playlists/create")
|
||||||
suspend fun createPlaylist(@Header("Authorization") token: String, @Body name: String): PlaylistId
|
suspend fun createPlaylist(@Header("Authorization") token: String, @Body name: Playlists): PlaylistId
|
||||||
|
|
||||||
//only for fetching servers list
|
//only for fetching servers list
|
||||||
@GET
|
@GET
|
||||||
|
@ -40,21 +40,27 @@ import com.google.android.exoplayer2.MediaItem
|
|||||||
import com.google.android.exoplayer2.MediaItem.SubtitleConfiguration
|
import com.google.android.exoplayer2.MediaItem.SubtitleConfiguration
|
||||||
import com.google.android.exoplayer2.MediaItem.fromUri
|
import com.google.android.exoplayer2.MediaItem.fromUri
|
||||||
import com.google.android.exoplayer2.Player
|
import com.google.android.exoplayer2.Player
|
||||||
|
import com.google.android.exoplayer2.ext.cronet.CronetDataSource
|
||||||
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory
|
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory
|
||||||
import com.google.android.exoplayer2.source.MediaSource
|
import com.google.android.exoplayer2.source.MediaSource
|
||||||
import com.google.android.exoplayer2.source.MergingMediaSource
|
import com.google.android.exoplayer2.source.MergingMediaSource
|
||||||
import com.google.android.exoplayer2.source.ProgressiveMediaSource
|
import com.google.android.exoplayer2.source.ProgressiveMediaSource
|
||||||
import com.google.android.exoplayer2.ui.StyledPlayerView
|
import com.google.android.exoplayer2.ui.StyledPlayerView
|
||||||
import com.google.android.exoplayer2.upstream.DataSource
|
import com.google.android.exoplayer2.upstream.DataSource
|
||||||
|
import com.google.android.exoplayer2.upstream.DefaultDataSource
|
||||||
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource
|
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.squareup.picasso.Picasso
|
import com.squareup.picasso.Picasso
|
||||||
|
import org.chromium.net.CronetEngine
|
||||||
import retrofit2.HttpException
|
import retrofit2.HttpException
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.net.URLEncoder
|
import java.net.URLEncoder
|
||||||
|
import java.util.concurrent.Executors
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
|
|
||||||
|
|
||||||
var isFullScreen = false
|
var isFullScreen = false
|
||||||
|
|
||||||
class PlayerFragment : Fragment() {
|
class PlayerFragment : Fragment() {
|
||||||
|
|
||||||
private val TAG = "PlayerFragment"
|
private val TAG = "PlayerFragment"
|
||||||
@ -113,9 +119,15 @@ class PlayerFragment : Fragment() {
|
|||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTransitionChange(motionLayout: MotionLayout?, startId: Int, endId: Int, progress: Float) {
|
override fun onTransitionChange(
|
||||||
|
motionLayout: MotionLayout?,
|
||||||
|
startId: Int,
|
||||||
|
endId: Int,
|
||||||
|
progress: Float
|
||||||
|
) {
|
||||||
val mainActivity = activity as MainActivity
|
val mainActivity = activity as MainActivity
|
||||||
val mainMotionLayout = mainActivity.findViewById<MotionLayout>(R.id.mainMotionLayout)
|
val mainMotionLayout =
|
||||||
|
mainActivity.findViewById<MotionLayout>(R.id.mainMotionLayout)
|
||||||
mainMotionLayout.progress = abs(progress)
|
mainMotionLayout.progress = abs(progress)
|
||||||
eId = endId
|
eId = endId
|
||||||
sId = startId
|
sId = startId
|
||||||
@ -124,7 +136,8 @@ class PlayerFragment : Fragment() {
|
|||||||
override fun onTransitionCompleted(motionLayout: MotionLayout?, currentId: Int) {
|
override fun onTransitionCompleted(motionLayout: MotionLayout?, currentId: Int) {
|
||||||
println(currentId)
|
println(currentId)
|
||||||
val mainActivity = activity as MainActivity
|
val mainActivity = activity as MainActivity
|
||||||
val mainMotionLayout = mainActivity.findViewById<MotionLayout>(R.id.mainMotionLayout)
|
val mainMotionLayout =
|
||||||
|
mainActivity.findViewById<MotionLayout>(R.id.mainMotionLayout)
|
||||||
if (currentId == eId) {
|
if (currentId == eId) {
|
||||||
view.findViewById<ImageButton>(R.id.quality_select).visibility = View.GONE
|
view.findViewById<ImageButton>(R.id.quality_select).visibility = View.GONE
|
||||||
view.findViewById<ImageButton>(R.id.close_imageButton).visibility = View.GONE
|
view.findViewById<ImageButton>(R.id.close_imageButton).visibility = View.GONE
|
||||||
@ -195,8 +208,8 @@ class PlayerFragment : Fragment() {
|
|||||||
view.findViewById<LinearLayout>(R.id.linLayout).visibility = View.GONE
|
view.findViewById<LinearLayout>(R.id.linLayout).visibility = View.GONE
|
||||||
val mainActivity = activity as MainActivity
|
val mainActivity = activity as MainActivity
|
||||||
mainActivity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
|
mainActivity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
|
||||||
isFullScreen=true
|
isFullScreen = true
|
||||||
}else{
|
} else {
|
||||||
with(motionLayout) {
|
with(motionLayout) {
|
||||||
getConstraintSet(R.id.start).constrainHeight(R.id.player, 0)
|
getConstraintSet(R.id.start).constrainHeight(R.id.player, 0)
|
||||||
enableTransition(R.id.yt_transition, true)
|
enableTransition(R.id.yt_transition, true)
|
||||||
@ -209,7 +222,8 @@ class PlayerFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
relatedRecView = view.findViewById(R.id.player_recView)
|
relatedRecView = view.findViewById(R.id.player_recView)
|
||||||
relatedRecView.layoutManager = GridLayoutManager(view.context, resources.getInteger(R.integer.grid_items))
|
relatedRecView.layoutManager =
|
||||||
|
GridLayoutManager(view.context, resources.getInteger(R.integer.grid_items))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
@ -220,7 +234,8 @@ class PlayerFragment : Fragment() {
|
|||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
try {
|
try {
|
||||||
exoPlayer.stop()
|
exoPlayer.stop()
|
||||||
} catch (e: Exception) {}
|
} catch (e: Exception) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchJson(view: View) {
|
private fun fetchJson(view: View) {
|
||||||
@ -231,11 +246,11 @@ class PlayerFragment : Fragment() {
|
|||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
println(e)
|
println(e)
|
||||||
Log.e(TAG, "IOException, you might not have internet connection")
|
Log.e(TAG, "IOException, you might not have internet connection")
|
||||||
Toast.makeText(context,R.string.unknown_error, Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, R.string.unknown_error, Toast.LENGTH_SHORT).show()
|
||||||
return@launchWhenCreated
|
return@launchWhenCreated
|
||||||
} catch (e: HttpException) {
|
} catch (e: HttpException) {
|
||||||
Log.e(TAG, "HttpException, unexpected response")
|
Log.e(TAG, "HttpException, unexpected response")
|
||||||
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
|
||||||
}
|
}
|
||||||
var videosNameArray: Array<CharSequence> = arrayOf()
|
var videosNameArray: Array<CharSequence> = arrayOf()
|
||||||
@ -255,7 +270,19 @@ class PlayerFragment : Fragment() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val cronetEngine: CronetEngine = CronetEngine.Builder(context)
|
||||||
|
.build()
|
||||||
|
val cronetDataSourceFactory: CronetDataSource.Factory =
|
||||||
|
CronetDataSource.Factory(cronetEngine, Executors.newCachedThreadPool())
|
||||||
|
|
||||||
|
val dataSourceFactory = DefaultDataSource.Factory(
|
||||||
|
requireContext(),
|
||||||
|
cronetDataSourceFactory
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
exoPlayer = ExoPlayer.Builder(view.context)
|
exoPlayer = ExoPlayer.Builder(view.context)
|
||||||
|
.setMediaSourceFactory(DefaultMediaSourceFactory(dataSourceFactory))
|
||||||
.setSeekBackIncrementMs(5000)
|
.setSeekBackIncrementMs(5000)
|
||||||
.setSeekForwardIncrementMs(5000)
|
.setSeekForwardIncrementMs(5000)
|
||||||
.build()
|
.build()
|
||||||
@ -265,14 +292,15 @@ class PlayerFragment : Fragment() {
|
|||||||
// exoPlayerView.controllerShowTimeoutMs = 1500
|
// exoPlayerView.controllerShowTimeoutMs = 1500
|
||||||
exoPlayerView.controllerHideOnTouch = true
|
exoPlayerView.controllerHideOnTouch = true
|
||||||
exoPlayerView.player = exoPlayer
|
exoPlayerView.player = exoPlayer
|
||||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
val sharedPreferences =
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||||
val defres = sharedPreferences.getString("default_res", "")!!
|
val defres = sharedPreferences.getString("default_res", "")!!
|
||||||
when {
|
when {
|
||||||
defres!="" -> {
|
defres != "" -> {
|
||||||
var foundRes = false
|
var foundRes = false
|
||||||
run lit@ {
|
run lit@{
|
||||||
response.videoStreams!!.forEachIndexed { index, pipedStream ->
|
response.videoStreams!!.forEachIndexed { index, pipedStream ->
|
||||||
if (pipedStream.quality!!.contains(defres)){
|
if (pipedStream.quality!!.contains(defres)) {
|
||||||
foundRes = true
|
foundRes = true
|
||||||
val dataSourceFactory: DataSource.Factory =
|
val dataSourceFactory: DataSource.Factory =
|
||||||
DefaultHttpDataSource.Factory()
|
DefaultHttpDataSource.Factory()
|
||||||
@ -280,24 +308,35 @@ class PlayerFragment : Fragment() {
|
|||||||
.setUri(response.videoStreams[index].url)
|
.setUri(response.videoStreams[index].url)
|
||||||
.setSubtitleConfigurations(subtitle)
|
.setSubtitleConfigurations(subtitle)
|
||||||
.build()
|
.build()
|
||||||
val videoSource: MediaSource = DefaultMediaSourceFactory(dataSourceFactory)
|
val videoSource: MediaSource =
|
||||||
.createMediaSource(videoItem)
|
DefaultMediaSourceFactory(dataSourceFactory)
|
||||||
var audioSource: MediaSource = DefaultMediaSourceFactory(dataSourceFactory)
|
.createMediaSource(videoItem)
|
||||||
.createMediaSource(fromUri(response.audioStreams!![0].url!!))
|
var audioSource: MediaSource =
|
||||||
|
DefaultMediaSourceFactory(dataSourceFactory)
|
||||||
|
.createMediaSource(fromUri(response.audioStreams!![0].url!!))
|
||||||
if (response.videoStreams[index].quality == "720p" || response.videoStreams[index].quality == "1080p" || response.videoStreams[index].quality == "480p") {
|
if (response.videoStreams[index].quality == "720p" || response.videoStreams[index].quality == "1080p" || response.videoStreams[index].quality == "480p") {
|
||||||
audioSource = ProgressiveMediaSource.Factory(dataSourceFactory)
|
audioSource =
|
||||||
.createMediaSource(fromUri(response.audioStreams!![getMostBitRate(response.audioStreams)].url!!))
|
ProgressiveMediaSource.Factory(dataSourceFactory)
|
||||||
|
.createMediaSource(
|
||||||
|
fromUri(
|
||||||
|
response.audioStreams!![getMostBitRate(
|
||||||
|
response.audioStreams
|
||||||
|
)].url!!
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
val mergeSource: MediaSource = MergingMediaSource(videoSource, audioSource)
|
val mergeSource: MediaSource =
|
||||||
|
MergingMediaSource(videoSource, audioSource)
|
||||||
exoPlayer.setMediaSource(mergeSource)
|
exoPlayer.setMediaSource(mergeSource)
|
||||||
view.findViewById<TextView>(R.id.quality_text).text = videosNameArray[index + 1]
|
view.findViewById<TextView>(R.id.quality_text).text =
|
||||||
|
videosNameArray[index + 1]
|
||||||
return@lit
|
return@lit
|
||||||
}else if (index+1 == response.videoStreams.size){
|
} else if (index + 1 == response.videoStreams.size) {
|
||||||
val mediaItem: MediaItem = MediaItem.Builder()
|
val mediaItem: MediaItem = MediaItem.Builder()
|
||||||
.setUri(response.hls)
|
.setUri(response.hls)
|
||||||
.setSubtitleConfigurations(subtitle)
|
.setSubtitleConfigurations(subtitle)
|
||||||
.build()
|
.build()
|
||||||
exoPlayer.setMediaItem(mediaItem)
|
exoPlayer.setMediaItem(mediaItem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -316,15 +355,24 @@ class PlayerFragment : Fragment() {
|
|||||||
.setUri(response.videoStreams[0].url)
|
.setUri(response.videoStreams[0].url)
|
||||||
.setSubtitleConfigurations(subtitle)
|
.setSubtitleConfigurations(subtitle)
|
||||||
.build()
|
.build()
|
||||||
val videoSource: MediaSource = DefaultMediaSourceFactory(dataSourceFactory)
|
val videoSource: MediaSource =
|
||||||
.createMediaSource(videoItem)
|
DefaultMediaSourceFactory(dataSourceFactory)
|
||||||
var audioSource: MediaSource = DefaultMediaSourceFactory(dataSourceFactory)
|
.createMediaSource(videoItem)
|
||||||
.createMediaSource(fromUri(response.audioStreams!![0].url!!))
|
var audioSource: MediaSource =
|
||||||
|
DefaultMediaSourceFactory(dataSourceFactory)
|
||||||
|
.createMediaSource(fromUri(response.audioStreams!![0].url!!))
|
||||||
if (response.videoStreams[0].quality == "720p" || response.videoStreams[0].quality == "1080p" || response.videoStreams[0].quality == "480p") {
|
if (response.videoStreams[0].quality == "720p" || response.videoStreams[0].quality == "1080p" || response.videoStreams[0].quality == "480p") {
|
||||||
audioSource = ProgressiveMediaSource.Factory(dataSourceFactory)
|
audioSource = ProgressiveMediaSource.Factory(dataSourceFactory)
|
||||||
.createMediaSource(fromUri(response.audioStreams!![getMostBitRate(response.audioStreams)].url!!))
|
.createMediaSource(
|
||||||
|
fromUri(
|
||||||
|
response.audioStreams!![getMostBitRate(
|
||||||
|
response.audioStreams
|
||||||
|
)].url!!
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
val mergeSource: MediaSource = MergingMediaSource(videoSource, audioSource)
|
val mergeSource: MediaSource =
|
||||||
|
MergingMediaSource(videoSource, audioSource)
|
||||||
exoPlayer.setMediaSource(mergeSource)
|
exoPlayer.setMediaSource(mergeSource)
|
||||||
view.findViewById<TextView>(R.id.quality_text).text = videosNameArray[1]
|
view.findViewById<TextView>(R.id.quality_text).text = videosNameArray[1]
|
||||||
}
|
}
|
||||||
@ -371,18 +419,29 @@ class PlayerFragment : Fragment() {
|
|||||||
.setUri(response.videoStreams[which - 1].url)
|
.setUri(response.videoStreams[which - 1].url)
|
||||||
.setSubtitleConfigurations(subtitle)
|
.setSubtitleConfigurations(subtitle)
|
||||||
.build()
|
.build()
|
||||||
val videoSource: MediaSource = DefaultMediaSourceFactory(dataSourceFactory)
|
val videoSource: MediaSource =
|
||||||
.createMediaSource(videoItem)
|
DefaultMediaSourceFactory(dataSourceFactory)
|
||||||
var audioSource: MediaSource = DefaultMediaSourceFactory(dataSourceFactory)
|
.createMediaSource(videoItem)
|
||||||
.createMediaSource(fromUri(response.audioStreams!![0].url!!))
|
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") {
|
if (response.videoStreams[which - 1].quality == "720p" || response.videoStreams[which - 1].quality == "1080p" || response.videoStreams[which - 1].quality == "480p") {
|
||||||
audioSource = ProgressiveMediaSource.Factory(dataSourceFactory)
|
audioSource =
|
||||||
.createMediaSource(fromUri(response.audioStreams!![getMostBitRate(response.audioStreams)].url!!))
|
ProgressiveMediaSource.Factory(dataSourceFactory)
|
||||||
|
.createMediaSource(
|
||||||
|
fromUri(
|
||||||
|
response.audioStreams!![getMostBitRate(
|
||||||
|
response.audioStreams
|
||||||
|
)].url!!
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
val mergeSource: MediaSource = MergingMediaSource(videoSource, audioSource)
|
val mergeSource: MediaSource =
|
||||||
|
MergingMediaSource(videoSource, audioSource)
|
||||||
exoPlayer.setMediaSource(mergeSource)
|
exoPlayer.setMediaSource(mergeSource)
|
||||||
}
|
}
|
||||||
view.findViewById<TextView>(R.id.quality_text).text = videosNameArray[which]
|
view.findViewById<TextView>(R.id.quality_text).text =
|
||||||
|
videosNameArray[which]
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
val dialog: AlertDialog? = builder?.create()
|
val dialog: AlertDialog? = builder?.create()
|
||||||
@ -390,34 +449,42 @@ class PlayerFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
// 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 : com.google.android.exoplayer2.Player.Listener {
|
||||||
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
|
override fun onPlayerStateChanged(
|
||||||
|
playWhenReady: Boolean,
|
||||||
|
playbackState: Int
|
||||||
|
) {
|
||||||
|
|
||||||
exoPlayerView.keepScreenOn = !(
|
exoPlayerView.keepScreenOn = !(
|
||||||
playbackState == Player.STATE_IDLE || playbackState == Player.STATE_ENDED ||
|
playbackState == Player.STATE_IDLE || playbackState == Player.STATE_ENDED ||
|
||||||
!playWhenReady
|
!playWhenReady
|
||||||
)
|
)
|
||||||
|
|
||||||
if (playWhenReady && playbackState == Player.STATE_READY) {
|
if (playWhenReady && playbackState == Player.STATE_READY) {
|
||||||
// media actually playing
|
// media actually playing
|
||||||
view.findViewById<ImageView>(R.id.play_imageView).setImageResource(R.drawable.ic_pause)
|
view.findViewById<ImageView>(R.id.play_imageView)
|
||||||
|
.setImageResource(R.drawable.ic_pause)
|
||||||
} else if (playWhenReady) {
|
} else if (playWhenReady) {
|
||||||
// might be idle (plays after prepare()),
|
// might be idle (plays after prepare()),
|
||||||
// buffering (plays when data available)
|
// buffering (plays when data available)
|
||||||
// or ended (plays when seek away from end)
|
// or ended (plays when seek away from end)
|
||||||
view.findViewById<ImageView>(R.id.play_imageView).setImageResource(R.drawable.ic_play)
|
view.findViewById<ImageView>(R.id.play_imageView)
|
||||||
|
.setImageResource(R.drawable.ic_play)
|
||||||
} else {
|
} else {
|
||||||
// player paused in any state
|
// player paused in any state
|
||||||
view.findViewById<ImageView>(R.id.play_imageView).setImageResource(R.drawable.ic_play)
|
view.findViewById<ImageView>(R.id.play_imageView)
|
||||||
|
.setImageResource(R.drawable.ic_play)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
relatedRecView.adapter = TrendingAdapter(response.relatedStreams!!)
|
relatedRecView.adapter = TrendingAdapter(response.relatedStreams!!)
|
||||||
view.findViewById<TextView>(R.id.player_description).text = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
view.findViewById<TextView>(R.id.player_description).text =
|
||||||
Html.fromHtml(response.description, Html.FROM_HTML_MODE_COMPACT)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
} else {
|
Html.fromHtml(response.description, Html.FROM_HTML_MODE_COMPACT)
|
||||||
Html.fromHtml(response.description)
|
} else {
|
||||||
}
|
Html.fromHtml(response.description)
|
||||||
view.findViewById<TextView>(R.id.player_views_info).text = response.views.formatShort() + " views • " + response.uploadDate
|
}
|
||||||
|
view.findViewById<TextView>(R.id.player_views_info).text =
|
||||||
|
response.views.formatShort() + " views • " + response.uploadDate
|
||||||
view.findViewById<TextView>(R.id.textLike).text = response.likes.formatShort()
|
view.findViewById<TextView>(R.id.textLike).text = response.likes.formatShort()
|
||||||
val channelImage = view.findViewById<ImageView>(R.id.player_channelImage)
|
val channelImage = view.findViewById<ImageView>(R.id.player_channelImage)
|
||||||
Picasso.get().load(response.uploaderAvatar).into(channelImage)
|
Picasso.get().load(response.uploaderAvatar).into(channelImage)
|
||||||
@ -438,11 +505,15 @@ class PlayerFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
// share button
|
// share button
|
||||||
view.findViewById<RelativeLayout>(R.id.relPlayer_share).setOnClickListener {
|
view.findViewById<RelativeLayout>(R.id.relPlayer_share).setOnClickListener {
|
||||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
val sharedPreferences =
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||||
val intent = Intent()
|
val intent = Intent()
|
||||||
intent.action = Intent.ACTION_SEND
|
intent.action = Intent.ACTION_SEND
|
||||||
var url = "https://piped.kavin.rocks/watch?v=$videoId"
|
var url = "https://piped.kavin.rocks/watch?v=$videoId"
|
||||||
val instance = sharedPreferences.getString("instance", "https://pipedapi.kavin.rocks")!!
|
val instance = sharedPreferences.getString(
|
||||||
|
"instance",
|
||||||
|
"https://pipedapi.kavin.rocks"
|
||||||
|
)!!
|
||||||
if (instance != "https://pipedapi.kavin.rocks")
|
if (instance != "https://pipedapi.kavin.rocks")
|
||||||
url += "&instance=${URLEncoder.encode(instance, "UTF-8")}"
|
url += "&instance=${URLEncoder.encode(instance, "UTF-8")}"
|
||||||
intent.putExtra(Intent.EXTRA_TEXT, url)
|
intent.putExtra(Intent.EXTRA_TEXT, url)
|
||||||
@ -450,7 +521,7 @@ class PlayerFragment : Fragment() {
|
|||||||
startActivity(Intent.createChooser(intent, "Share Url To:"))
|
startActivity(Intent.createChooser(intent, "Share Url To:"))
|
||||||
}
|
}
|
||||||
// check if livestream
|
// check if livestream
|
||||||
if (response.duration!!> 0) {
|
if (response.duration!! > 0) {
|
||||||
// download clicked
|
// download clicked
|
||||||
relDownloadVideo.setOnClickListener {
|
relDownloadVideo.setOnClickListener {
|
||||||
if (!IS_DOWNLOAD_RUNNING) {
|
if (!IS_DOWNLOAD_RUNNING) {
|
||||||
@ -473,9 +544,9 @@ class PlayerFragment : Fragment() {
|
|||||||
requireContext(),
|
requireContext(),
|
||||||
Manifest.permission.READ_EXTERNAL_STORAGE
|
Manifest.permission.READ_EXTERNAL_STORAGE
|
||||||
) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(
|
) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(
|
||||||
requireContext(),
|
requireContext(),
|
||||||
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||||
) != PackageManager.PERMISSION_GRANTED
|
) != PackageManager.PERMISSION_GRANTED
|
||||||
) {
|
) {
|
||||||
ActivityCompat.requestPermissions(
|
ActivityCompat.requestPermissions(
|
||||||
mainActivity,
|
mainActivity,
|
||||||
@ -540,7 +611,7 @@ class PlayerFragment : Fragment() {
|
|||||||
Toast.makeText(context, R.string.vlcerror, Toast.LENGTH_SHORT)
|
Toast.makeText(context, R.string.vlcerror, Toast.LENGTH_SHORT)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -554,7 +625,10 @@ class PlayerFragment : Fragment() {
|
|||||||
lifecycleScope.launchWhenCreated {
|
lifecycleScope.launchWhenCreated {
|
||||||
val response = try {
|
val response = try {
|
||||||
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
|
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
|
||||||
RetrofitInstance.api.isSubscribed(channel_id, sharedPref?.getString("token", "")!!)
|
RetrofitInstance.api.isSubscribed(
|
||||||
|
channel_id,
|
||||||
|
sharedPref?.getString("token", "")!!
|
||||||
|
)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
println(e)
|
println(e)
|
||||||
Log.e(TAG, "IOException, you might not have internet connection")
|
Log.e(TAG, "IOException, you might not have internet connection")
|
||||||
@ -594,7 +668,7 @@ class PlayerFragment : Fragment() {
|
|||||||
button.text = getString(R.string.unsubscribe)
|
button.text = getString(R.string.unsubscribe)
|
||||||
button.setTextColor(colorPrimary.data)
|
button.setTextColor(colorPrimary.data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -607,7 +681,10 @@ class PlayerFragment : Fragment() {
|
|||||||
lifecycleScope.launchWhenCreated {
|
lifecycleScope.launchWhenCreated {
|
||||||
val response = try {
|
val response = try {
|
||||||
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
|
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
|
||||||
RetrofitInstance.api.subscribe(sharedPref?.getString("token", "")!!, Subscribe(channel_id))
|
RetrofitInstance.api.subscribe(
|
||||||
|
sharedPref?.getString("token", "")!!,
|
||||||
|
Subscribe(channel_id)
|
||||||
|
)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
println(e)
|
println(e)
|
||||||
Log.e(TAG, "IOException, you might not have internet connection")
|
Log.e(TAG, "IOException, you might not have internet connection")
|
||||||
@ -621,12 +698,16 @@ class PlayerFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
run()
|
run()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun unsubscribe(channel_id: String) {
|
private fun unsubscribe(channel_id: String) {
|
||||||
fun run() {
|
fun run() {
|
||||||
lifecycleScope.launchWhenCreated {
|
lifecycleScope.launchWhenCreated {
|
||||||
val response = try {
|
val response = try {
|
||||||
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
|
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
|
||||||
RetrofitInstance.api.unsubscribe(sharedPref?.getString("token", "")!!, Subscribe(channel_id))
|
RetrofitInstance.api.unsubscribe(
|
||||||
|
sharedPref?.getString("token", "")!!,
|
||||||
|
Subscribe(channel_id)
|
||||||
|
)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
println(e)
|
println(e)
|
||||||
Log.e(TAG, "IOException, you might not have internet connection")
|
Log.e(TAG, "IOException, you might not have internet connection")
|
||||||
@ -652,7 +733,7 @@ class PlayerFragment : Fragment() {
|
|||||||
var index = 0
|
var index = 0
|
||||||
for ((i, audio) in audios.withIndex()) {
|
for ((i, audio) in audios.withIndex()) {
|
||||||
val q = audio.quality!!.replace(" kbps", "").toInt()
|
val q = audio.quality!!.replace(" kbps", "").toInt()
|
||||||
if (q> bitrate) {
|
if (q > bitrate) {
|
||||||
bitrate = q
|
bitrate = q
|
||||||
index = i
|
index = i
|
||||||
}
|
}
|
||||||
|
52
app/src/main/res/layout/dialog_createplaylist.xml
Normal file
52
app/src/main/res/layout/dialog_createplaylist.xml
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
>
|
||||||
|
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:src="@drawable/ic_libretube_foreground"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:scaleType="center"
|
||||||
|
android:background="#CD5757"
|
||||||
|
android:contentDescription="@string/app_name" />
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:hintEnabled="false"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginLeft="7dp"
|
||||||
|
android:layout_marginRight="7dp"
|
||||||
|
android:layout_marginBottom="4dp"
|
||||||
|
>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/username"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/playlistName"
|
||||||
|
android:inputType="text"
|
||||||
|
android:padding="12dp" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center">
|
||||||
|
<Button
|
||||||
|
android:id="@+id/create_playlist_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/createPlaylist"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:layout_margin="8dp"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -1,5 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
@ -46,6 +48,34 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/outlinedTextField"
|
||||||
|
style="@style/Widget.Material3.CardView.Filled"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
android:layout_margin="5dp"
|
||||||
|
>
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:hintEnabled="false"
|
||||||
|
android:layout_marginRight="20dp"
|
||||||
|
android:layout_marginLeft="20dp"
|
||||||
|
android:background="@android:color/transparent">
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/playlists_name"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:hint="@string/playlistName"/>
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/create_playlist"
|
android:id="@+id/create_playlist"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -45,4 +45,5 @@
|
|||||||
<string name="areYouSure">Are you sure you want to delete this playlist?</string>
|
<string name="areYouSure">Are you sure you want to delete this playlist?</string>
|
||||||
<string name="createPlaylist">Create Playlist</string>
|
<string name="createPlaylist">Create Playlist</string>
|
||||||
<string name="playlistCreated">Playlist created!</string>
|
<string name="playlistCreated">Playlist created!</string>
|
||||||
|
<string name="playlistName">Playlist Name</string>
|
||||||
</resources>
|
</resources>
|
@ -5,7 +5,7 @@ buildscript {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.1.1'
|
classpath 'com.android.tools.build:gradle:7.1.3'
|
||||||
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10'
|
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10'
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
|
Loading…
Reference in New Issue
Block a user