This commit is contained in:
Bnyro 2022-05-20 00:22:10 +02:00
parent 5c420b773c
commit a2339672c6
44 changed files with 624 additions and 677 deletions

View File

@ -1,13 +1,11 @@
package com.github.libretube package com.github.libretube
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Assert.*
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.junit.Assert.*
/** /**
* Instrumented test, which will execute on an Android device. * Instrumented test, which will execute on an Android device.
* *

View File

@ -10,10 +10,9 @@ import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.github.libretube.adapters.PlaylistsAdapter
import com.github.libretube.obj.PlaylistId import com.github.libretube.obj.PlaylistId
import retrofit2.HttpException
import java.io.IOException import java.io.IOException
import retrofit2.HttpException
class AddtoPlaylistDialog : DialogFragment() { class AddtoPlaylistDialog : DialogFragment() {
private val TAG = "AddToPlaylistDialog" private val TAG = "AddToPlaylistDialog"
@ -26,7 +25,7 @@ class AddtoPlaylistDialog : DialogFragment() {
videoId = arguments?.getString("videoId")!! videoId = arguments?.getString("videoId")!!
val builder = AlertDialog.Builder(it) val builder = AlertDialog.Builder(it)
// 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)
token = sharedPref?.getString("token", "")!! token = sharedPref?.getString("token", "")!!
var view: View = inflater.inflate(R.layout.dialog_addtoplaylist, null) var view: View = inflater.inflate(R.layout.dialog_addtoplaylist, null)
@ -68,9 +67,7 @@ class AddtoPlaylistDialog : DialogFragment() {
} }
} }
} else { } else {
} }
} }
} }
run() run()
@ -96,7 +93,6 @@ class AddtoPlaylistDialog : DialogFragment() {
} else { } else {
Toast.makeText(context, R.string.fail, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.fail, Toast.LENGTH_SHORT).show()
} }
} }
} }
run() run()

View File

@ -1,13 +1,10 @@
package com.github.libretube package com.github.libretube
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.text.TextUtils.substring import android.text.TextUtils.substring
import android.util.Log import android.util.Log
import android.util.TypedValue
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@ -23,9 +20,8 @@ import com.github.libretube.adapters.ChannelAdapter
import com.github.libretube.obj.Subscribe import com.github.libretube.obj.Subscribe
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 retrofit2.HttpException
import java.io.IOException import java.io.IOException
import retrofit2.HttpException
class ChannelFragment : Fragment() { class ChannelFragment : Fragment() {
@ -45,13 +41,12 @@ class ChannelFragment : Fragment() {
} }
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
// Inflate the layout for this fragment // Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_channel, container, false) return inflater.inflate(R.layout.fragment_channel, container, false)
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -81,18 +76,16 @@ class ChannelFragment : Fragment() {
scrollView.viewTreeObserver scrollView.viewTreeObserver
.addOnScrollChangedListener { .addOnScrollChangedListener {
if (scrollView.getChildAt(0).bottom if (scrollView.getChildAt(0).bottom
== (scrollView.height + scrollView.scrollY)) { == (scrollView.height + scrollView.scrollY)
) {
// scroll view is at bottom // scroll view is at bottom
if (nextPage != null && !isLoading) { if (nextPage != null && !isLoading) {
isLoading = true isLoading = true
refreshLayout?.isRefreshing = true; refreshLayout?.isRefreshing = true
fetchNextPage() fetchNextPage()
} }
} }
} }
} }
private fun isSubscribed(button: MaterialButton) { private fun isSubscribed(button: MaterialButton) {
@ -125,7 +118,8 @@ class ChannelFragment : Fragment() {
subscribe() subscribe()
button.text = getString(R.string.unsubscribe) button.text = getString(R.string.unsubscribe)
} }
}} }
}
} }
} }
} }
@ -177,18 +171,18 @@ class ChannelFragment : Fragment() {
val response = try { val response = try {
RetrofitInstance.api.getChannel(channel_id!!) RetrofitInstance.api.getChannel(channel_id!!)
} catch (e: IOException) { } catch (e: IOException) {
refreshLayout?.isRefreshing = false; refreshLayout?.isRefreshing = false
println(e) println(e)
Log.e(TAG, "IOException, you might not have internet connection") Log.e(TAG, "IOException, you might not have internet connection")
return@launchWhenCreated return@launchWhenCreated
} catch (e: HttpException) { } catch (e: HttpException) {
refreshLayout?.isRefreshing = false; refreshLayout?.isRefreshing = false
Log.e(TAG, "HttpException, unexpected response") Log.e(TAG, "HttpException, unexpected response")
return@launchWhenCreated return@launchWhenCreated
} }
nextPage = response.nextpage nextPage = response.nextpage
isLoading = false isLoading = false
refreshLayout?.isRefreshing = false; refreshLayout?.isRefreshing = false
runOnUiThread { runOnUiThread {
view.findViewById<ScrollView>(R.id.channel_scrollView).visibility = View.VISIBLE view.findViewById<ScrollView>(R.id.channel_scrollView).visibility = View.VISIBLE
val channelName = view.findViewById<TextView>(R.id.channel_name) val channelName = view.findViewById<TextView>(R.id.channel_name)
@ -204,7 +198,6 @@ class ChannelFragment : Fragment() {
Picasso.get().load(response.avatarUrl).into(channelImage) Picasso.get().load(response.avatarUrl).into(channelImage)
channelAdapter = ChannelAdapter(response.relatedStreams!!.toMutableList()) channelAdapter = ChannelAdapter(response.relatedStreams!!.toMutableList())
view.findViewById<RecyclerView>(R.id.channel_recView).adapter = channelAdapter view.findViewById<RecyclerView>(R.id.channel_recView).adapter = channelAdapter
} }
} }
} }

View File

@ -30,8 +30,7 @@ class CreatePlaylistDialog : DialogFragment() {
if (listName != "") { if (listName != "") {
setFragmentResult("key_parent", bundleOf("playlistName" to "$listName")) setFragmentResult("key_parent", bundleOf("playlistName" to "$listName"))
dismiss() dismiss()
} } else {
else {
Toast.makeText(context, R.string.emptyPlaylistName, Toast.LENGTH_LONG).show() Toast.makeText(context, R.string.emptyPlaylistName, Toast.LENGTH_LONG).show()
} }
} }

View File

@ -4,12 +4,11 @@ import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.MotionEvent import android.view.MotionEvent
import com.google.android.exoplayer2.ui.PlayerView
import com.google.android.exoplayer2.ui.StyledPlayerControlView
import com.google.android.exoplayer2.ui.StyledPlayerView import com.google.android.exoplayer2.ui.StyledPlayerView
internal class CustomExoPlayerView( internal class CustomExoPlayerView(
context: Context, attributeSet: AttributeSet? = null context: Context,
attributeSet: AttributeSet? = null
) : StyledPlayerView(context, attributeSet) { ) : StyledPlayerView(context, attributeSet) {
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")

View File

@ -9,7 +9,6 @@ import android.widget.*
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
class DownloadDialog : DialogFragment() { class DownloadDialog : DialogFragment() {
private val TAG = "DownloadDialog" private val TAG = "DownloadDialog"
var vidName = arrayListOf<String>() var vidName = arrayListOf<String>()

View File

@ -16,7 +16,6 @@ import androidx.core.app.NotificationManagerCompat
import com.arthenica.ffmpegkit.FFmpegKit import com.arthenica.ffmpegkit.FFmpegKit
import java.io.File import java.io.File
var IS_DOWNLOAD_RUNNING = false var IS_DOWNLOAD_RUNNING = false
class DownloadService : Service() { class DownloadService : Service() {
val TAG = "DownloadService" val TAG = "DownloadService"
@ -46,8 +45,10 @@ class DownloadService : Service(){
service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val channelId = val channelId =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val chan = NotificationChannel("service", val chan = NotificationChannel(
"DownloadService", NotificationManager.IMPORTANCE_NONE) "service",
"DownloadService", NotificationManager.IMPORTANCE_NONE
)
chan.lightColor = Color.BLUE chan.lightColor = Color.BLUE
chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
service.createNotificationChannel(chan) service.createNotificationChannel(chan)
@ -128,11 +129,10 @@ class DownloadService : Service(){
val downloadManager: DownloadManager = val downloadManager: DownloadManager =
applicationContext.getSystemService(DOWNLOAD_SERVICE) as DownloadManager applicationContext.getSystemService(DOWNLOAD_SERVICE) as DownloadManager
downloadManager.enqueue(request) downloadManager.enqueue(request)
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "audio download error $e") Log.e(TAG, "audio download error $e")
stopService(Intent(this,DownloadService::class.java))} stopService(Intent(this, DownloadService::class.java))
}
} }
} }
@ -166,17 +166,18 @@ class DownloadService : Service(){
} }
var command: String = when { var command: String = when {
videoUrl == "" -> { videoUrl == "" -> {
"-y -i $audioDir -c copy ${libreTube}/${videoId}-audio$extension" "-y -i $audioDir -c copy $libreTube/$videoId-audio$extension"
} }
audioUrl == "" -> { audioUrl == "" -> {
"-y -i $videoDir -c copy ${libreTube}/${videoId}-video$extension" "-y -i $videoDir -c copy $libreTube/$videoId-video$extension"
} }
else -> { else -> {
"-y -i $videoDir -i $audioDir -c copy ${libreTube}/${videoId}$extension" "-y -i $videoDir -i $audioDir -c copy $libreTube/${videoId}$extension"
} }
} }
notification.setContentTitle("Muxing") notification.setContentTitle("Muxing")
FFmpegKit.executeAsync(command, FFmpegKit.executeAsync(
command,
{ session -> { session ->
val state = session.state val state = session.state
val returnCode = session.returnCode val returnCode = session.returnCode
@ -211,7 +212,8 @@ class DownloadService : Service(){
}, { }, {
// CALLED WHEN SESSION PRINTS LOGS // CALLED WHEN SESSION PRINTS LOGS
Log.e(TAG, it.message.toString()) Log.e(TAG, it.message.toString())
}) { }
) {
// CALLED WHEN SESSION GENERATES STATISTICS // CALLED WHEN SESSION GENERATES STATISTICS
Log.e(TAG + "stat", it.time.toString()) Log.e(TAG + "stat", it.time.toString())
/*val progress = it.time/(10*duration!!) /*val progress = it.time/(10*duration!!)
@ -221,7 +223,6 @@ class DownloadService : Service(){
service.notify(1,notification.build()) service.notify(1,notification.build())
}*/ }*/
} }
} }
} }
} }
@ -250,5 +251,4 @@ class DownloadService : Service(){
Log.d(TAG, "dl finished!") Log.d(TAG, "dl finished!")
super.onDestroy() super.onDestroy()
} }
} }

View File

@ -2,23 +2,21 @@ package com.github.libretube
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
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.ProgressBar import android.widget.ProgressBar
import android.widget.Toast import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import okhttp3.*
import retrofit2.HttpException
import com.github.libretube.adapters.TrendingAdapter import com.github.libretube.adapters.TrendingAdapter
import java.io.IOException import java.io.IOException
import okhttp3.*
import retrofit2.HttpException
class Home : Fragment() { class Home : Fragment() {
@ -31,13 +29,13 @@ class Home : Fragment() {
} }
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
// Inflate the layout for this fragment // Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_home, container, false) return inflater.inflate(R.layout.fragment_home, container, false)
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -54,12 +52,8 @@ class Home : Fragment() {
Log.d(TAG, "hmm") Log.d(TAG, "hmm")
fetchJson(progressbar, recyclerView) fetchJson(progressbar, recyclerView)
} }
} }
private fun fetchJson(progressBar: ProgressBar, recyclerView: RecyclerView) { private fun fetchJson(progressBar: ProgressBar, recyclerView: RecyclerView) {
fun run() { fun run() {
lifecycleScope.launchWhenCreated { lifecycleScope.launchWhenCreated {
@ -85,7 +79,6 @@ class Home : Fragment() {
} }
} }
run() run()
} }
private fun Fragment?.runOnUiThread(action: () -> Unit) { private fun Fragment?.runOnUiThread(action: () -> Unit) {
this ?: return this ?: return

View File

@ -17,9 +17,8 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.github.libretube.adapters.PlaylistsAdapter import com.github.libretube.adapters.PlaylistsAdapter
import com.github.libretube.obj.Playlists import com.github.libretube.obj.Playlists
import retrofit2.HttpException
import java.io.IOException import java.io.IOException
import retrofit2.HttpException
class Library : Fragment() { class Library : Fragment() {
@ -30,12 +29,12 @@ class Library : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
arguments?.let { arguments?.let {
} }
} }
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
// Inflate the layout for this fragment // Inflate the layout for this fragment
@ -64,7 +63,7 @@ class Library : Fragment() {
} }
childFragmentManager.setFragmentResultListener("key_parent", this) { _, result -> childFragmentManager.setFragmentResultListener("key_parent", this) { _, result ->
val playlistName = result.getString("playlistName") val playlistName = result.getString("playlistName")
createPlaylist("$playlistName", view); createPlaylist("$playlistName", view)
} }
} else { } else {
refreshLayout?.isEnabled = false refreshLayout?.isEnabled = false
@ -121,7 +120,6 @@ class Library : Fragment() {
} }
} }
} }
} }
} }
run() run()
@ -145,9 +143,7 @@ class Library : Fragment() {
Toast.makeText(context, R.string.playlistCreated, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.playlistCreated, Toast.LENGTH_SHORT).show()
fetchPlaylists(view) fetchPlaylists(view)
} else { } else {
} }
} }
} }
run() run()

View File

@ -2,7 +2,6 @@ package com.github.libretube
import android.app.Dialog import android.app.Dialog
import android.content.Context import android.content.Context
import android.content.DialogInterface
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.View import android.view.View
@ -13,14 +12,10 @@ import android.widget.Toast
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.preference.PreferenceManager
import com.github.libretube.adapters.TrendingAdapter
import com.github.libretube.obj.Login import com.github.libretube.obj.Login
import org.w3c.dom.Text
import retrofit2.HttpException
import java.io.IOException import java.io.IOException
import java.lang.Exception import java.lang.Exception
import kotlin.math.log import retrofit2.HttpException
class LoginDialog : DialogFragment() { class LoginDialog : DialogFragment() {
private val TAG = "LoginDialog" private val TAG = "LoginDialog"
@ -30,7 +25,7 @@ class LoginDialog : DialogFragment() {
return activity?.let { return activity?.let {
val builder = AlertDialog.Builder(it) val builder = AlertDialog.Builder(it)
// 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", "")
var view: View var view: View
@ -108,7 +103,6 @@ class LoginDialog : DialogFragment() {
} }
dialog?.dismiss() dialog?.dismiss()
} }
} }
} }
run() run()
@ -147,10 +141,8 @@ class LoginDialog : DialogFragment() {
} }
dialog?.dismiss() dialog?.dismiss()
} }
} }
} }
run() run()
} }
} }

View File

@ -17,7 +17,10 @@ interface PipedApi {
suspend fun getSegments(@Path("videoId") videoId: String, @Query("category") category: String): Segments suspend fun getSegments(@Path("videoId") videoId: String, @Query("category") category: String): Segments
@GET("nextpage/comments/{videoId}") @GET("nextpage/comments/{videoId}")
suspend fun getCommentsNextPage(@Path("videoId") videoId: String, @Query("nextpage") nextPage: String): CommentsPage suspend fun getCommentsNextPage(
@Path("videoId") videoId: String,
@Query("nextpage") nextPage: String
): CommentsPage
@GET("search") @GET("search")
suspend fun getSearchResults( suspend fun getSearchResults(
@ -39,13 +42,19 @@ interface PipedApi {
suspend fun getChannel(@Path("channelId") channelId: String): Channel suspend fun getChannel(@Path("channelId") channelId: String): Channel
@GET("nextpage/channel/{channelId}") @GET("nextpage/channel/{channelId}")
suspend fun getChannelNextPage(@Path("channelId") channelId: String, @Query("nextpage") nextPage: String): Channel suspend fun getChannelNextPage(
@Path("channelId") channelId: String,
@Query("nextpage") nextPage: String
): Channel
@GET("playlists/{playlistId}") @GET("playlists/{playlistId}")
suspend fun getPlaylist(@Path("playlistId") playlistId: String): Playlist suspend fun getPlaylist(@Path("playlistId") playlistId: String): Playlist
@GET("nextpage/playlists/{playlistId}") @GET("nextpage/playlists/{playlistId}")
suspend fun getPlaylistNextPage(@Path("playlistId") playlistId: String, @Query("nextpage") nextPage: String): Playlist suspend fun getPlaylistNextPage(
@Path("playlistId") playlistId: String,
@Query("nextpage") nextPage: String
): Playlist
@POST("login") @POST("login")
suspend fun login(@Body login: Login): Token suspend fun login(@Body login: Login): Token
@ -57,7 +66,10 @@ interface PipedApi {
suspend fun getFeed(@Query("authToken") token: String?): List<StreamItem> suspend fun getFeed(@Query("authToken") token: String?): List<StreamItem>
@GET("subscribed") @GET("subscribed")
suspend fun isSubscribed(@Query("channelId") channelId: String, @Header("Authorization") token: String): Subscribed suspend fun isSubscribed(
@Query("channelId") channelId: String,
@Header("Authorization") token: String
): Subscribed
@GET("subscriptions") @GET("subscriptions")
suspend fun subscriptions(@Header("Authorization") token: String): List<Subscription> suspend fun subscriptions(@Header("Authorization") token: String): List<Subscription>
@ -69,7 +81,11 @@ interface PipedApi {
suspend fun unsubscribe(@Header("Authorization") token: String, @Body subscribe: Subscribe): Message suspend fun unsubscribe(@Header("Authorization") token: String, @Body subscribe: Subscribe): Message
@POST("import") @POST("import")
suspend fun importSubscriptions(@Query("override") override: Boolean, @Header("Authorization") token: String, @Body channels: List<String>): Message suspend fun importSubscriptions(
@Query("override") override: Boolean,
@Header("Authorization") token: String,
@Body channels: List<String>
): Message
@GET("user/playlists") @GET("user/playlists")
suspend fun playlists(@Header("Authorization") token: String): List<Playlists> suspend fun playlists(@Header("Authorization") token: String): List<Playlists>
@ -84,12 +100,12 @@ interface PipedApi {
suspend fun addToPlaylist(@Header("Authorization") token: String, @Body playlistId: PlaylistId): Message suspend fun addToPlaylist(@Header("Authorization") token: String, @Body playlistId: PlaylistId): Message
@POST("user/playlists/remove") @POST("user/playlists/remove")
suspend fun removeFromPlaylist(@Header("Authorization") token: String, @Body playlistId: PlaylistId): Message suspend fun removeFromPlaylist(
@Header("Authorization") token: String,
@Body playlistId: PlaylistId
): Message
// only for fetching servers list // only for fetching servers list
@GET @GET
suspend fun getInstances(@Url url: String): List<Instances> suspend fun getInstances(@Url url: String): List<Instances>
} }

View File

@ -1,25 +1,12 @@
package com.github.libretube package com.github.libretube
import android.app.Activity import android.app.Activity
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle import android.os.Bundle
class Player : Activity() { class Player : Activity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_player) setContentView(R.layout.activity_player)
} }
} }

View File

@ -58,13 +58,12 @@ import com.google.android.exoplayer2.upstream.DefaultHttpDataSource
import com.google.android.exoplayer2.util.RepeatModeUtil import com.google.android.exoplayer2.util.RepeatModeUtil
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 java.io.IOException import java.io.IOException
import java.net.URLEncoder import java.net.URLEncoder
import java.util.concurrent.Executors import java.util.concurrent.Executors
import kotlin.math.abs import kotlin.math.abs
import org.chromium.net.CronetEngine
import retrofit2.HttpException
var isFullScreen = false var isFullScreen = false
@ -247,7 +246,6 @@ class PlayerFragment : Fragment() {
) { ) {
fetchNextComments() fetchNextComments()
} }
} }
commentsRecView = view.findViewById(R.id.comments_recView) commentsRecView = view.findViewById(R.id.comments_recView)
@ -274,8 +272,7 @@ class PlayerFragment : Fragment() {
} }
} }
private fun checkForSegments() private fun checkForSegments() {
{
if (!exoPlayer.isPlaying || !SponsorBlockSettings.sponsorBlockEnabled) return if (!exoPlayer.isPlaying || !SponsorBlockSettings.sponsorBlockEnabled) return
exoPlayerView.postDelayed(this::checkForSegments, 100) exoPlayerView.postDelayed(this::checkForSegments, 100)
@ -289,7 +286,7 @@ class PlayerFragment : Fragment() {
val currentPosition = exoPlayer.currentPosition val currentPosition = exoPlayer.currentPosition
if (currentPosition in segmentStart until segmentEnd) { if (currentPosition in segmentStart until segmentEnd) {
Toast.makeText(context, R.string.segment_skipped, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.segment_skipped, Toast.LENGTH_SHORT).show()
exoPlayer.seekTo(segmentEnd); exoPlayer.seekTo(segmentEnd)
} }
} }
} }
@ -401,10 +398,10 @@ class PlayerFragment : Fragment() {
exoPlayerView.setShowSubtitleButton(true) exoPlayerView.setShowSubtitleButton(true)
exoPlayerView.setShowNextButton(false) exoPlayerView.setShowNextButton(false)
exoPlayerView.setShowPreviousButton(false) exoPlayerView.setShowPreviousButton(false)
exoPlayerView.setRepeatToggleModes(RepeatModeUtil.REPEAT_TOGGLE_MODE_ALL); exoPlayerView.setRepeatToggleModes(RepeatModeUtil.REPEAT_TOGGLE_MODE_ALL)
// exoPlayerView.controllerShowTimeoutMs = 1500 // exoPlayerView.controllerShowTimeoutMs = 1500
exoPlayerView.controllerHideOnTouch = true exoPlayerView.controllerHideOnTouch = true
exoPlayer.setAudioAttributes(audioAttributes,true); exoPlayer.setAudioAttributes(audioAttributes, true)
exoPlayerView.player = exoPlayer exoPlayerView.player = exoPlayer
val sharedPreferences = val sharedPreferences =
PreferenceManager.getDefaultSharedPreferences(requireContext()) PreferenceManager.getDefaultSharedPreferences(requireContext())
@ -433,9 +430,11 @@ class PlayerFragment : Fragment() {
ProgressiveMediaSource.Factory(dataSourceFactory) ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource( .createMediaSource(
fromUri( fromUri(
response.audioStreams!![getMostBitRate( response.audioStreams!![
getMostBitRate(
response.audioStreams response.audioStreams
)].url!! )
].url!!
) )
) )
} }
@ -479,9 +478,11 @@ class PlayerFragment : Fragment() {
audioSource = ProgressiveMediaSource.Factory(dataSourceFactory) audioSource = ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource( .createMediaSource(
fromUri( fromUri(
response.audioStreams!![getMostBitRate( response.audioStreams!![
getMostBitRate(
response.audioStreams response.audioStreams
)].url!! )
].url!!
) )
) )
} }
@ -545,9 +546,11 @@ class PlayerFragment : Fragment() {
ProgressiveMediaSource.Factory(dataSourceFactory) ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource( .createMediaSource(
fromUri( fromUri(
response.audioStreams!![getMostBitRate( response.audioStreams!![
getMostBitRate(
response.audioStreams response.audioStreams
)].url!! )
].url!!
) )
) )
} }
@ -555,7 +558,7 @@ class PlayerFragment : Fragment() {
MergingMediaSource(videoSource, audioSource) MergingMediaSource(videoSource, audioSource)
exoPlayer.setMediaSource(mergeSource) exoPlayer.setMediaSource(mergeSource)
} }
exoPlayer.seekTo(lastPosition); exoPlayer.seekTo(lastPosition)
view.findViewById<TextView>(R.id.quality_text).text = view.findViewById<TextView>(R.id.quality_text).text =
videosNameArray[which] videosNameArray[which]
} }
@ -566,8 +569,7 @@ 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 onIsPlayingChanged(isPlaying: Boolean) { override fun onIsPlayingChanged(isPlaying: Boolean) {
if(isPlaying && SponsorBlockSettings.sponsorBlockEnabled) if (isPlaying && SponsorBlockSettings.sponsorBlockEnabled) {
{
exoPlayerView.postDelayed(this@PlayerFragment::checkForSegments, 100) exoPlayerView.postDelayed(this@PlayerFragment::checkForSegments, 100)
} }
} }
@ -772,7 +774,6 @@ class PlayerFragment : Fragment() {
return@launchWhenCreated return@launchWhenCreated
} }
runOnUiThread { runOnUiThread {
if (response.subscribed == true) { if (response.subscribed == true) {
isSubscribed = true isSubscribed = true
@ -898,7 +899,7 @@ class PlayerFragment : Fragment() {
view?.findViewById<FrameLayout>(R.id.top_bar)?.visibility = View.GONE view?.findViewById<FrameLayout>(R.id.top_bar)?.visibility = View.GONE
val mainActivity = activity as MainActivity val mainActivity = activity as MainActivity
mainActivity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT mainActivity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
isFullScreen = false; isFullScreen = false
} else { } else {
with(motionLayout) { with(motionLayout) {
getConstraintSet(R.id.start).constrainHeight(R.id.player, 0) getConstraintSet(R.id.start).constrainHeight(R.id.player, 0)
@ -917,6 +918,6 @@ class PlayerFragment : Fragment() {
if (SDK_INT >= Build.VERSION_CODES.N && exoPlayer.isPlaying && (scrollView?.getLocalVisibleRect(bounds) == true || isFullScreen)) { if (SDK_INT >= Build.VERSION_CODES.N && exoPlayer.isPlaying && (scrollView?.getLocalVisibleRect(bounds) == true || isFullScreen)) {
requireActivity().enterPictureInPictureMode() requireActivity().enterPictureInPictureMode()
}; }
} }
} }

View File

@ -3,22 +3,18 @@ package com.github.libretube
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
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.ScrollView import android.widget.ScrollView
import android.widget.TextView import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.adapters.ChannelAdapter
import com.github.libretube.adapters.PlaylistAdapter import com.github.libretube.adapters.PlaylistAdapter
import com.squareup.picasso.Picasso
import retrofit2.HttpException
import java.io.IOException import java.io.IOException
import retrofit2.HttpException
class PlaylistFragment : Fragment() { class PlaylistFragment : Fragment() {
private var playlist_id: String? = null private var playlist_id: String? = null
@ -34,7 +30,8 @@ class PlaylistFragment : Fragment() {
} }
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
// Inflate the layout for this fragment // Inflate the layout for this fragment
@ -82,13 +79,13 @@ class PlaylistFragment : Fragment() {
scrollView.viewTreeObserver scrollView.viewTreeObserver
.addOnScrollChangedListener { .addOnScrollChangedListener {
if (scrollView.getChildAt(0).bottom if (scrollView.getChildAt(0).bottom
== (scrollView.height + scrollView.scrollY)) { == (scrollView.height + scrollView.scrollY)
) {
// scroll view is at bottom // scroll view is at bottom
if (nextPage != null && !isLoading) { if (nextPage != null && !isLoading) {
isLoading = true isLoading = true
fetchNextPage() fetchNextPage()
} }
} else { } else {
// scroll view is not at bottom // scroll view is not at bottom
} }
@ -116,7 +113,6 @@ class PlaylistFragment : Fragment() {
nextPage = response.nextpage nextPage = response.nextpage
playlistAdapter?.updateItems(response.relatedStreams!!) playlistAdapter?.updateItems(response.relatedStreams!!)
isLoading = false isLoading = false
} }
} }
run() run()

View File

@ -13,5 +13,4 @@ object RetrofitInstance {
.build() .build()
.create(PipedApi::class.java) .create(PipedApi::class.java)
} }
} }

View File

@ -23,11 +23,11 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.adapters.SearchAdapter import com.github.libretube.adapters.SearchAdapter
import com.github.libretube.adapters.SearchHistoryAdapter import com.github.libretube.adapters.SearchHistoryAdapter
import java.io.IOException
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException
class SearchFragment : Fragment() { class SearchFragment : Fragment() {
private val TAG = "SearchFragment" private val TAG = "SearchFragment"
@ -41,19 +41,18 @@ class SearchFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
arguments?.let { arguments?.let {
} }
} }
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
// Inflate the layout for this fragment // Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_search, container, false) return inflater.inflate(R.layout.fragment_search, container, false)
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
searchRecView = view.findViewById<RecyclerView>(R.id.search_recycler) searchRecView = view.findViewById<RecyclerView>(R.id.search_recycler)
@ -80,10 +79,16 @@ class SearchFragment : Fragment() {
AlertDialog.Builder(view.context) AlertDialog.Builder(view.context)
.setTitle(getString(R.string.choose_filter)) .setTitle(getString(R.string.choose_filter))
.setSingleChoiceItems(filterOptions, selectedFilter, DialogInterface.OnClickListener { .setSingleChoiceItems(
_, id -> tempSelectedItem = id filterOptions, selectedFilter,
}) DialogInterface.OnClickListener {
.setPositiveButton(getString(R.string.okay), DialogInterface.OnClickListener { _, _ -> _, id ->
tempSelectedItem = id
}
)
.setPositiveButton(
getString(R.string.okay),
DialogInterface.OnClickListener { _, _ ->
selectedFilter = tempSelectedItem selectedFilter = tempSelectedItem
apiSearchFilter = when (selectedFilter) { apiSearchFilter = when (selectedFilter) {
0 -> "all" 0 -> "all"
@ -97,7 +102,8 @@ class SearchFragment : Fragment() {
else -> "all" else -> "all"
} }
fetchSearch(autoTextView.text.toString()) fetchSearch(autoTextView.text.toString())
}) }
)
.setNegativeButton(getString(R.string.cancel), null) .setNegativeButton(getString(R.string.cancel), null)
.create() .create()
.show() .show()
@ -128,7 +134,6 @@ class SearchFragment : Fragment() {
count: Int, count: Int,
after: Int after: Int
) { ) {
} }
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
@ -142,7 +147,6 @@ class SearchFragment : Fragment() {
if (!searchRecView.canScrollVertically(1)) { if (!searchRecView.canScrollVertically(1)) {
fetchNextSearchItems(autoTextView.text.toString()) fetchNextSearchItems(autoTextView.text.toString())
} }
} }
GlobalScope.launch { GlobalScope.launch {
@ -166,16 +170,17 @@ class SearchFragment : Fragment() {
} }
} }
} }
}) })
autoTextView.setOnEditorActionListener(OnEditorActionListener { _, actionId, _ -> autoTextView.setOnEditorActionListener(
OnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_SEARCH) { if (actionId == EditorInfo.IME_ACTION_SEARCH) {
hideKeyboard() hideKeyboard()
autoTextView.dismissDropDown() autoTextView.dismissDropDown()
return@OnEditorActionListener true return@OnEditorActionListener true
} }
false false
}) }
)
autoTextView.setOnItemClickListener { _, _, _, _ -> autoTextView.setOnItemClickListener { _, _, _, _ ->
hideKeyboard() hideKeyboard()
} }
@ -262,18 +267,14 @@ class SearchFragment : Fragment() {
var historyList = getHistory() var historyList = getHistory()
if (historyList.size != 0 && query == historyList.get(historyList.size - 1)) { if (historyList.size != 0 && query == historyList.get(historyList.size - 1)) {
return return
} else if (query == "") { } else if (query == "") {
return return
} else { } else {
historyList = historyList + query historyList = historyList + query
} }
if (historyList.size > 10) { if (historyList.size > 10) {
historyList = historyList.takeLast(10) historyList = historyList.takeLast(10)
} }
@ -292,7 +293,5 @@ class SearchFragment : Fragment() {
} catch (e: Exception) { } catch (e: Exception) {
return emptyList() return emptyList()
} }
} }
} }

View File

@ -24,13 +24,13 @@ import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.google.android.material.color.DynamicColors import com.google.android.material.color.DynamicColors
import org.json.JSONObject
import org.json.JSONTokener
import retrofit2.HttpException
import java.io.IOException 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.json.JSONObject
import org.json.JSONTokener
import retrofit2.HttpException
class SettingsActivity : class SettingsActivity :
AppCompatActivity(), AppCompatActivity(),

View File

@ -3,13 +3,10 @@ package com.github.libretube
import android.content.Context import android.content.Context
import android.graphics.Rect import android.graphics.Rect
import android.util.AttributeSet import android.util.AttributeSet
import android.util.Log
import android.view.GestureDetector import android.view.GestureDetector
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
import androidx.constraintlayout.motion.widget.MotionLayout import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.recyclerview.widget.RecyclerView
/** /**
* *
@ -33,7 +30,6 @@ class SingleViewTouchableMotionLayout(context: Context, attributeSet: AttributeS
startId: Int, startId: Int,
endId: Int endId: Int
) { ) {
} }
override fun onTransitionChange(p0: MotionLayout?, p1: Int, p2: Int, p3: Float) { override fun onTransitionChange(p0: MotionLayout?, p1: Int, p2: Int, p3: Float) {
@ -49,7 +45,6 @@ class SingleViewTouchableMotionLayout(context: Context, attributeSet: AttributeS
positive: Boolean, positive: Boolean,
progress: Float progress: Float
) { ) {
} }
}) })
@ -59,7 +54,6 @@ class SingleViewTouchableMotionLayout(context: Context, attributeSet: AttributeS
startId: Int, startId: Int,
endId: Int endId: Int
) { ) {
} }
override fun onTransitionChange(p0: MotionLayout?, p1: Int, p2: Int, p3: Float) { override fun onTransitionChange(p0: MotionLayout?, p1: Int, p2: Int, p3: Float) {
@ -78,7 +72,6 @@ class SingleViewTouchableMotionLayout(context: Context, attributeSet: AttributeS
positive: Boolean, positive: Boolean,
progress: Float progress: Float
) { ) {
} }
}) })
} }
@ -91,12 +84,15 @@ class SingleViewTouchableMotionLayout(context: Context, attributeSet: AttributeS
transitionListenerList += listener transitionListenerList += listener
} }
private val gestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() { private val gestureDetector = GestureDetector(
context,
object : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapConfirmed(e: MotionEvent?): Boolean { override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
transitionToEnd() transitionToEnd()
return false return false
} }
}) }
)
override fun onTouchEvent(event: MotionEvent): Boolean { override fun onTouchEvent(event: MotionEvent): Boolean {
// gestureDetector.onTouchEvent(event) // gestureDetector.onTouchEvent(event)

View File

@ -3,23 +3,22 @@ package com.github.libretube
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
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.* import android.widget.*
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.github.libretube.adapters.SubscriptionAdapter import com.github.libretube.adapters.SubscriptionAdapter
import com.github.libretube.adapters.SubscriptionChannelAdapter import com.github.libretube.adapters.SubscriptionChannelAdapter
import java.io.IOException
import org.chromium.base.ThreadUtils.runOnUiThread import org.chromium.base.ThreadUtils.runOnUiThread
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException
class Subscriptions : Fragment() { class Subscriptions : Fragment() {
val TAG = "SubFragment" val TAG = "SubFragment"
@ -34,7 +33,8 @@ class Subscriptions : Fragment() {
} }
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
// Inflate the layout for this fragment // Inflate the layout for this fragment
@ -78,8 +78,7 @@ class Subscriptions : Fragment() {
} }
channelRecView.visibility = View.VISIBLE channelRecView.visibility = View.VISIBLE
feedRecView.visibility = View.GONE feedRecView.visibility = View.GONE
} } else {
else {
channelRecView.visibility = View.GONE channelRecView.visibility = View.GONE
feedRecView.visibility = View.VISIBLE feedRecView.visibility = View.VISIBLE
} }
@ -89,14 +88,14 @@ class Subscriptions : Fragment() {
scrollView.viewTreeObserver scrollView.viewTreeObserver
.addOnScrollChangedListener { .addOnScrollChangedListener {
if (scrollView.getChildAt(0).bottom if (scrollView.getChildAt(0).bottom
== (scrollView.height + scrollView.scrollY)) { == (scrollView.height + scrollView.scrollY)
) {
// scroll view is at bottom // scroll view is at bottom
if (isLoaded) { if (isLoaded) {
refreshLayout?.isRefreshing = true refreshLayout?.isRefreshing = true
subscriptionAdapter?.updateItems() subscriptionAdapter?.updateItems()
refreshLayout?.isRefreshing = false refreshLayout?.isRefreshing = false
} }
} }
} }
} else { } else {
@ -178,5 +177,4 @@ class Subscriptions : Fragment() {
if (!isAdded) return // Fragment not attached to an Activity if (!isAdded) return // Fragment not attached to an Activity
activity?.runOnUiThread(action) activity?.runOnUiThread(action)
} }
} }

View File

@ -1,6 +1,5 @@
package com.github.libretube.adapters package com.github.libretube.adapters
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
@ -54,7 +53,6 @@ class CommentsAdapter(private val comments: MutableList<Comment>): RecyclerView
activity.findViewById<MotionLayout>(R.id.playerMotionLayout).transitionToEnd() activity.findViewById<MotionLayout>(R.id.playerMotionLayout).transitionToEnd()
} }
} catch (e: Exception) { } catch (e: Exception) {
} }
} }
} }
@ -62,7 +60,6 @@ class CommentsAdapter(private val comments: MutableList<Comment>): RecyclerView
override fun getItemCount(): Int { override fun getItemCount(): Int {
return comments.size return comments.size
} }
} }
class ViewHolder(val v: View) : RecyclerView.ViewHolder(v) { class ViewHolder(val v: View) : RecyclerView.ViewHolder(v) {

View File

@ -18,12 +18,17 @@ import com.github.libretube.RetrofitInstance
import com.github.libretube.obj.PlaylistId import com.github.libretube.obj.PlaylistId
import com.github.libretube.obj.StreamItem import com.github.libretube.obj.StreamItem
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import java.io.IOException
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException
class PlaylistAdapter(private val videoFeed: MutableList<StreamItem>, private val playlistId: String, private val isOwner: Boolean, private val activity: Activity): RecyclerView.Adapter<PlaylistViewHolder>() { class PlaylistAdapter(
private val videoFeed: MutableList<StreamItem>,
private val playlistId: String,
private val isOwner: Boolean,
private val activity: Activity
) : RecyclerView.Adapter<PlaylistViewHolder>() {
private val TAG = "PlaylistAdapter" private val TAG = "PlaylistAdapter"
override fun getItemCount(): Int { override fun getItemCount(): Int {
return videoFeed.size return videoFeed.size
@ -82,7 +87,6 @@ class PlaylistAdapter(private val videoFeed: MutableList<StreamItem>, private va
Log.e(TAG, "HttpException, unexpected response") Log.e(TAG, "HttpException, unexpected response")
return@launch return@launch
} finally { } finally {
} }
try { try {
if (response.message == "ok") { if (response.message == "ok") {
@ -98,11 +102,9 @@ class PlaylistAdapter(private val videoFeed: MutableList<StreamItem>, private va
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, e.toString()) Log.e(TAG, e.toString())
} }
} }
} }
run() run()
} }
} }
class PlaylistViewHolder(val v: View) : RecyclerView.ViewHolder(v) { class PlaylistViewHolder(val v: View) : RecyclerView.ViewHolder(v) {

View File

@ -17,13 +17,15 @@ import com.github.libretube.RetrofitInstance
import com.github.libretube.obj.PlaylistId import com.github.libretube.obj.PlaylistId
import com.github.libretube.obj.Playlists import com.github.libretube.obj.Playlists
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import java.io.IOException
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException
class PlaylistsAdapter(
class PlaylistsAdapter(private val playlists: MutableList<Playlists>, private val activity: Activity): RecyclerView.Adapter<PlaylistsViewHolder>() { private val playlists: MutableList<Playlists>,
private val activity: Activity
) : RecyclerView.Adapter<PlaylistsViewHolder>() {
val TAG = "PlaylistsAdapter" val TAG = "PlaylistsAdapter"
override fun getItemCount(): Int { override fun getItemCount(): Int {
return playlists.size return playlists.size
@ -63,7 +65,6 @@ class PlaylistsAdapter(private val playlists: MutableList<Playlists>, private va
val bundle = bundleOf("playlist_id" to playlist.id) val bundle = bundleOf("playlist_id" to playlist.id)
activity.navController.navigate(R.id.playlistFragment, bundle) activity.navController.navigate(R.id.playlistFragment, bundle)
} }
} }
private fun deletePlaylist(id: String, token: String, position: Int) { private fun deletePlaylist(id: String, token: String, position: Int) {
fun run() { fun run() {
@ -78,7 +79,6 @@ class PlaylistsAdapter(private val playlists: MutableList<Playlists>, private va
Log.e(TAG, "HttpException, unexpected response") Log.e(TAG, "HttpException, unexpected response")
return@launch return@launch
} finally { } finally {
} }
try { try {
if (response.message == "ok") { if (response.message == "ok") {
@ -94,13 +94,10 @@ class PlaylistsAdapter(private val playlists: MutableList<Playlists>, private va
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, e.toString()) Log.e(TAG, e.toString())
} }
} }
} }
run() run()
} }
} }
class PlaylistsViewHolder(val v: View) : RecyclerView.ViewHolder(v) { class PlaylistsViewHolder(val v: View) : RecyclerView.ViewHolder(v) {
init { init {

View File

@ -17,7 +17,6 @@ import com.github.libretube.formatShort
import com.github.libretube.obj.SearchItem import com.github.libretube.obj.SearchItem
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
class SearchAdapter(private val searchItems: MutableList<SearchItem>) : RecyclerView.Adapter<CustomViewHolder1>() { class SearchAdapter(private val searchItems: MutableList<SearchItem>) : RecyclerView.Adapter<CustomViewHolder1>() {
fun updateItems(newItems: List<SearchItem>) { fun updateItems(newItems: List<SearchItem>) {

View File

@ -11,16 +11,17 @@ import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.R import com.github.libretube.R
import com.google.android.material.imageview.ShapeableImageView import com.google.android.material.imageview.ShapeableImageView
class SearchHistoryAdapter(
class SearchHistoryAdapter(private val context: Context, private var historyList: List<String> , private val editText : AutoCompleteTextView) : private val context: Context,
private var historyList: List<String>,
private val editText: AutoCompleteTextView
) :
RecyclerView.Adapter<SearchHistoryViewHolder>() { RecyclerView.Adapter<SearchHistoryViewHolder>() {
override fun getItemCount(): Int { override fun getItemCount(): Int {
return historyList.size return historyList.size
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchHistoryViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchHistoryViewHolder {
val layoutInflater = LayoutInflater.from(parent.context) val layoutInflater = LayoutInflater.from(parent.context)
val cell = layoutInflater.inflate(R.layout.searchhistory_row, parent, false) val cell = layoutInflater.inflate(R.layout.searchhistory_row, parent, false)
@ -31,7 +32,6 @@ class SearchHistoryAdapter(private val context: Context, private var historyList
val history = historyList[position] val history = historyList[position]
holder.v.findViewById<TextView>(R.id.history_text).text = history holder.v.findViewById<TextView>(R.id.history_text).text = history
holder.v.findViewById<ShapeableImageView>(R.id.delete_history).setOnClickListener { holder.v.findViewById<ShapeableImageView>(R.id.delete_history).setOnClickListener {
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)

View File

@ -57,7 +57,6 @@ class SubscriptionAdapter(private val videoFeed: List<StreamItem>): RecyclerView
activity.findViewById<MotionLayout>(R.id.playerMotionLayout).transitionToEnd() activity.findViewById<MotionLayout>(R.id.playerMotionLayout).transitionToEnd()
} }
} catch (e: Exception) { } catch (e: Exception) {
} }
} }
Picasso.get().load(trending.thumbnail).into(thumbnailImage) Picasso.get().load(trending.thumbnail).into(thumbnailImage)

View File

@ -47,7 +47,6 @@ class TrendingAdapter(private val videoFeed: List<StreamItem>): RecyclerView.Ada
activity.findViewById<MotionLayout>(R.id.playerMotionLayout).transitionToEnd() activity.findViewById<MotionLayout>(R.id.playerMotionLayout).transitionToEnd()
} }
} catch (e: Exception) { } catch (e: Exception) {
} }
} }
if (trending.thumbnail!!.isEmpty()) { if (trending.thumbnail!!.isEmpty()) {
@ -59,7 +58,6 @@ class TrendingAdapter(private val videoFeed: List<StreamItem>): RecyclerView.Ada
Picasso.get().load(trending.uploaderAvatar).into(channelImage) Picasso.get().load(trending.uploaderAvatar).into(channelImage)
} }
holder.v.setOnClickListener { holder.v.setOnClickListener {
var bundle = Bundle() var bundle = Bundle()
bundle.putString("videoId", trending.url!!.replace("/watch?v=", "")) bundle.putString("videoId", trending.url!!.replace("/watch?v=", ""))

View File

@ -2,6 +2,4 @@ package com.github.libretube
import android.app.Application import android.app.Application
class myApp : Application() { class myApp : Application()
}

View File

@ -17,4 +17,3 @@ data class Comment(
) { ) {
constructor() : this("", "", "", "", "", null, 0, null, "", null) constructor() : this("", "", "", "", "", null, 0, null, "", null)
} }

View File

@ -27,6 +27,8 @@ data class Streams(
val proxyUrl: String?, val proxyUrl: String?,
val chapters: List<ChapterSegment>? val chapters: List<ChapterSegment>?
) { ) {
constructor(): this("","","","","","","","","","",null,-1,-1,-1,-1, emptyList(), emptyList(), constructor() : this(
emptyList(), emptyList(), null,"", emptyList()) "", "", "", "", "", "", "", "", "", "", null, -1, -1, -1, -1, emptyList(), emptyList(),
emptyList(), emptyList(), null, "", emptyList()
)
} }

View File

@ -1,8 +1,7 @@
package com.github.libretube package com.github.libretube
import org.junit.Test
import org.junit.Assert.* import org.junit.Assert.*
import org.junit.Test
/** /**
* Example local unit test, which will execute on the development machine (host). * Example local unit test, which will execute on the development machine (host).