mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-27 23:40:33 +05:30
Fix all linting errors.
This commit is contained in:
parent
940a3b20e7
commit
057cf3f02f
@ -2,7 +2,7 @@ package com.github.libretube
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
|
@ -6,15 +6,19 @@ import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import android.widget.*
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.Button
|
||||
import android.widget.Spinner
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.core.text.HtmlCompat
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.github.libretube.obj.PlaylistId
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
import retrofit2.HttpException
|
||||
|
||||
class AddtoPlaylistDialog : DialogFragment() {
|
||||
private val TAG = "AddToPlaylistDialog"
|
||||
@ -49,6 +53,7 @@ class AddtoPlaylistDialog : DialogFragment() {
|
||||
builder.create()
|
||||
} ?: throw IllegalStateException("Activity cannot be null")
|
||||
}
|
||||
|
||||
private fun fetchPlaylists() {
|
||||
fun run() {
|
||||
lifecycleScope.launchWhenCreated {
|
||||
@ -69,8 +74,11 @@ class AddtoPlaylistDialog : DialogFragment() {
|
||||
for (playlist in response) {
|
||||
names.add(playlist.name!!)
|
||||
}
|
||||
val arrayAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, names)
|
||||
arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
val arrayAdapter =
|
||||
ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, names)
|
||||
arrayAdapter.setDropDownViewResource(
|
||||
android.R.layout.simple_spinner_dropdown_item
|
||||
)
|
||||
spinner.adapter = arrayAdapter
|
||||
runOnUiThread {
|
||||
button.setOnClickListener {
|
||||
@ -83,6 +91,7 @@ class AddtoPlaylistDialog : DialogFragment() {
|
||||
}
|
||||
run()
|
||||
}
|
||||
|
||||
private fun addToPlaylist(playlistId: String) {
|
||||
fun run() {
|
||||
lifecycleScope.launchWhenCreated {
|
||||
@ -108,6 +117,7 @@ class AddtoPlaylistDialog : DialogFragment() {
|
||||
}
|
||||
run()
|
||||
}
|
||||
|
||||
private fun Fragment?.runOnUiThread(action: () -> Unit) {
|
||||
this ?: return
|
||||
if (!isAdded) return // Fragment not attached to an Activity
|
||||
|
@ -3,7 +3,6 @@ package com.github.libretube
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils.substring
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
@ -94,7 +93,10 @@ class ChannelFragment : Fragment() {
|
||||
lifecycleScope.launchWhenCreated {
|
||||
val response = try {
|
||||
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) {
|
||||
println(e)
|
||||
Log.e(TAG, "IOException, you might not have internet connection")
|
||||
@ -131,7 +133,10 @@ class ChannelFragment : Fragment() {
|
||||
lifecycleScope.launchWhenCreated {
|
||||
val response = try {
|
||||
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) {
|
||||
println(e)
|
||||
Log.e(TAG, "IOException, you might not have internet connection")
|
||||
@ -145,12 +150,16 @@ class ChannelFragment : Fragment() {
|
||||
}
|
||||
run()
|
||||
}
|
||||
|
||||
private fun unsubscribe() {
|
||||
fun run() {
|
||||
lifecycleScope.launchWhenCreated {
|
||||
val response = try {
|
||||
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) {
|
||||
println(e)
|
||||
Log.e(TAG, "IOException, you might not have internet connection")
|
||||
@ -186,12 +195,19 @@ class ChannelFragment : Fragment() {
|
||||
runOnUiThread {
|
||||
view.findViewById<ScrollView>(R.id.channel_scrollView).visibility = View.VISIBLE
|
||||
val channelName = view.findViewById<TextView>(R.id.channel_name)
|
||||
channelName.text = if (response.name?.length!! > 18) response.name.toString().substring(0, 16) + "..." else response.name
|
||||
channelName.text = if (response.name?.length!! > 18) response.name.toString()
|
||||
.substring(0, 16) + "..." else response.name
|
||||
val channelVerified = view.findViewById<ImageView>(R.id.channel_verified)
|
||||
if (response.verified) channelVerified.visibility = View.VISIBLE
|
||||
view.findViewById<TextView>(R.id.channel_subs).text = resources.getString(R.string.subscribers, response.subscriberCount.formatShort())
|
||||
view.findViewById<TextView>(R.id.channel_subs).text = resources.getString(
|
||||
R.string.subscribers,
|
||||
response.subscriberCount.formatShort()
|
||||
)
|
||||
val channelDescription = view.findViewById<TextView>(R.id.channel_description)
|
||||
if (response.description?.trim() == "") channelDescription.visibility = View.GONE else channelDescription.text = response.description?.trim()
|
||||
if (response.description?.trim() == "")
|
||||
channelDescription.visibility = View.GONE
|
||||
else
|
||||
channelDescription.text = response.description?.trim()
|
||||
val bannerImage = view.findViewById<ImageView>(R.id.channel_banner)
|
||||
val channelImage = view.findViewById<ImageView>(R.id.channel_image)
|
||||
Picasso.get().load(response.bannerUrl).into(bannerImage)
|
||||
@ -203,6 +219,7 @@ class ChannelFragment : Fragment() {
|
||||
}
|
||||
run()
|
||||
}
|
||||
|
||||
private fun fetchNextPage() {
|
||||
fun run() {
|
||||
|
||||
@ -227,6 +244,7 @@ class ChannelFragment : Fragment() {
|
||||
}
|
||||
run()
|
||||
}
|
||||
|
||||
private fun Fragment?.runOnUiThread(action: () -> Unit) {
|
||||
this ?: return
|
||||
if (!isAdded) return // Fragment not attached to an Activity
|
||||
|
@ -12,6 +12,7 @@ import androidx.core.os.bundleOf
|
||||
import androidx.core.text.HtmlCompat
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.setFragmentResult
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
|
||||
class CreatePlaylistDialog : DialogFragment() {
|
||||
override fun onCreateView(
|
||||
@ -35,7 +36,7 @@ class CreatePlaylistDialog : DialogFragment() {
|
||||
dismiss()
|
||||
}
|
||||
|
||||
val playlistName = rootView.findViewById<com.google.android.material.textfield.TextInputEditText>(R.id.playlist_name)
|
||||
val playlistName = rootView.findViewById<TextInputEditText>(R.id.playlist_name)
|
||||
val createPlaylistBtn = rootView.findViewById<Button>(R.id.create_new_playlist)
|
||||
createPlaylistBtn.setOnClickListener {
|
||||
var listName = playlistName.text.toString()
|
||||
|
@ -6,7 +6,13 @@ import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import android.widget.*
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.Button
|
||||
import android.widget.RadioButton
|
||||
import android.widget.RadioGroup
|
||||
import android.widget.Spinner
|
||||
import android.widget.TextView
|
||||
import androidx.core.text.HtmlCompat
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
@ -35,7 +41,11 @@ class DownloadDialog : DialogFragment() {
|
||||
val inflater = requireActivity().layoutInflater
|
||||
var view: View = inflater.inflate(R.layout.dialog_download, null)
|
||||
val videoSpinner = view.findViewById<Spinner>(R.id.video_spinner)
|
||||
val videoArrayAdapter = ArrayAdapter<String>(requireContext(), android.R.layout.simple_spinner_item, vidName)
|
||||
val videoArrayAdapter = ArrayAdapter<String>(
|
||||
requireContext(),
|
||||
android.R.layout.simple_spinner_item,
|
||||
vidName
|
||||
)
|
||||
videoArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
videoSpinner.adapter = videoArrayAdapter
|
||||
videoSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
@ -48,10 +58,15 @@ class DownloadDialog : DialogFragment() {
|
||||
selectedVideo = position
|
||||
Log.d(TAG, selectedVideo.toString())
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
}
|
||||
val audioSpinner = view.findViewById<Spinner>(R.id.audio_spinner)
|
||||
val audioArrayAdapter = ArrayAdapter<String>(requireContext(), android.R.layout.simple_spinner_item, audioName)
|
||||
val audioArrayAdapter = ArrayAdapter(
|
||||
requireContext(),
|
||||
android.R.layout.simple_spinner_item,
|
||||
audioName
|
||||
)
|
||||
audioArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
audioSpinner.adapter = audioArrayAdapter
|
||||
audioSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
@ -64,6 +79,7 @@ class DownloadDialog : DialogFragment() {
|
||||
selectedAudio = position
|
||||
Log.d(TAG, selectedAudio.toString())
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
}
|
||||
val radioGroup = view.findViewById<RadioGroup>(R.id.radioGp)
|
||||
@ -97,6 +113,7 @@ class DownloadDialog : DialogFragment() {
|
||||
builder.create()
|
||||
} ?: throw IllegalStateException("Activity cannot be null")
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
vidName.clear()
|
||||
vidUrl.clear()
|
||||
|
@ -1,6 +1,11 @@
|
||||
package com.github.libretube
|
||||
|
||||
import android.app.*
|
||||
import android.app.DownloadManager
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.app.Service
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
@ -9,6 +14,7 @@ import android.graphics.Color
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.os.Environment.DIRECTORY_DOWNLOADS
|
||||
import android.os.IBinder
|
||||
import android.util.Log
|
||||
import androidx.core.app.NotificationCompat
|
||||
@ -17,6 +23,7 @@ import com.arthenica.ffmpegkit.FFmpegKit
|
||||
import java.io.File
|
||||
|
||||
var IS_DOWNLOAD_RUNNING = false
|
||||
|
||||
class DownloadService : Service() {
|
||||
val TAG = "DownloadService"
|
||||
private var downloadId: Long = -1
|
||||
@ -25,6 +32,7 @@ class DownloadService : Service() {
|
||||
private lateinit var audioUrl: String
|
||||
private lateinit var extension: String
|
||||
private var duration: Int = 0
|
||||
|
||||
// private lateinit var command: String
|
||||
private lateinit var audioDir: File
|
||||
private lateinit var videoDir: File
|
||||
@ -81,6 +89,7 @@ class DownloadService : Service() {
|
||||
|
||||
return super.onStartCommand(intent, flags, startId)
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent?): IBinder? {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
@ -101,7 +110,10 @@ class DownloadService : Service() {
|
||||
videoDir = File(f, "$videoId-video")
|
||||
try {
|
||||
Log.e(TAG, "Directory make")
|
||||
registerReceiver(onDownloadComplete, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
|
||||
registerReceiver(
|
||||
onDownloadComplete,
|
||||
IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
|
||||
)
|
||||
val request: DownloadManager.Request =
|
||||
DownloadManager.Request(Uri.parse(videoUrl))
|
||||
.setTitle("Video") // Title of the Download Notification
|
||||
@ -113,7 +125,9 @@ class DownloadService : Service() {
|
||||
val downloadManager: DownloadManager =
|
||||
applicationContext.getSystemService(DOWNLOAD_SERVICE) as DownloadManager
|
||||
downloadId = downloadManager.enqueue(request)
|
||||
if (audioUrl == "") { downloadId = 0L }
|
||||
if (audioUrl == "") {
|
||||
downloadId = 0L
|
||||
}
|
||||
} catch (e: IllegalArgumentException) {
|
||||
Log.e(TAG, "download error $e")
|
||||
try {
|
||||
@ -155,9 +169,12 @@ class DownloadService : Service() {
|
||||
val downloadManager: DownloadManager =
|
||||
applicationContext.getSystemService(DOWNLOAD_SERVICE) as DownloadManager
|
||||
downloadManager.enqueue(request)
|
||||
} catch (e: Exception) {}
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
} else if (downloadId == 0L) {
|
||||
val libreTube = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "LibreTube")
|
||||
val libreTube = File(
|
||||
Environment.getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS), "LibreTube"
|
||||
)
|
||||
if (!libreTube.exists()) {
|
||||
libreTube.mkdirs()
|
||||
Log.e(TAG, "libreTube Directory make")
|
||||
@ -191,7 +208,8 @@ class DownloadService : Service() {
|
||||
session.failStackTrace
|
||||
)
|
||||
)
|
||||
val path = applicationContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
|
||||
val path =
|
||||
applicationContext.getExternalFilesDir(DIRECTORY_DOWNLOADS)
|
||||
val folder_main = ".tmp"
|
||||
val f = File(path, folder_main)
|
||||
f.deleteRecursively()
|
||||
@ -243,10 +261,12 @@ class DownloadService : Service() {
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
try {
|
||||
unregisterReceiver(onDownloadComplete)
|
||||
} catch (e: Exception) {}
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
IS_DOWNLOAD_RUNNING = false
|
||||
Log.d(TAG, "dl finished!")
|
||||
super.onDestroy()
|
||||
|
@ -15,7 +15,6 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import com.github.libretube.adapters.TrendingAdapter
|
||||
import java.io.IOException
|
||||
import okhttp3.*
|
||||
import retrofit2.HttpException
|
||||
|
||||
class Home : Fragment() {
|
||||
@ -42,7 +41,10 @@ class Home : Fragment() {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
val recyclerView = view.findViewById<RecyclerView>(R.id.recview)
|
||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
val grid = sharedPreferences.getString("grid", resources.getInteger(R.integer.grid_items).toString())!!
|
||||
val grid = sharedPreferences.getString(
|
||||
"grid",
|
||||
resources.getInteger(R.integer.grid_items).toString()
|
||||
)!!
|
||||
recyclerView.layoutManager = GridLayoutManager(view.context, grid.toInt())
|
||||
val progressbar = view.findViewById<ProgressBar>(R.id.progressBar)
|
||||
fetchJson(progressbar, recyclerView)
|
||||
@ -58,7 +60,8 @@ class Home : Fragment() {
|
||||
fun run() {
|
||||
lifecycleScope.launchWhenCreated {
|
||||
val response = try {
|
||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
val sharedPreferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
RetrofitInstance.api.getTrending(sharedPreferences.getString("region", "US")!!)
|
||||
} catch (e: IOException) {
|
||||
println(e)
|
||||
@ -80,6 +83,7 @@ class Home : Fragment() {
|
||||
}
|
||||
run()
|
||||
}
|
||||
|
||||
private fun Fragment?.runOnUiThread(action: () -> Unit) {
|
||||
this ?: return
|
||||
if (!isAdded) return // Fragment not attached to an Activity
|
||||
|
@ -52,8 +52,8 @@ class Library : Fragment() {
|
||||
view.findViewById<ImageView>(R.id.boogh2).visibility = View.GONE
|
||||
view.findViewById<TextView>(R.id.textLike2).visibility = View.GONE
|
||||
fetchPlaylists(view)
|
||||
refreshLayout?.isEnabled = true
|
||||
refreshLayout?.setOnRefreshListener {
|
||||
refreshLayout.isEnabled = true
|
||||
refreshLayout.setOnRefreshListener {
|
||||
Log.d(TAG, "hmm")
|
||||
fetchPlaylists(view)
|
||||
}
|
||||
@ -66,7 +66,7 @@ class Library : Fragment() {
|
||||
createPlaylist("$playlistName", view)
|
||||
}
|
||||
} else {
|
||||
refreshLayout?.isEnabled = false
|
||||
refreshLayout.isEnabled = false
|
||||
view.findViewById<Button>(R.id.create_playlist).visibility = View.GONE
|
||||
with(view.findViewById<ImageView>(R.id.boogh2)) {
|
||||
visibility = View.VISIBLE
|
||||
@ -81,7 +81,7 @@ class Library : Fragment() {
|
||||
|
||||
private fun fetchPlaylists(view: View) {
|
||||
fun run() {
|
||||
refreshLayout?.isRefreshing = true
|
||||
refreshLayout.isRefreshing = true
|
||||
lifecycleScope.launchWhenCreated {
|
||||
val response = try {
|
||||
RetrofitInstance.api.playlists(token)
|
||||
@ -95,7 +95,7 @@ class Library : Fragment() {
|
||||
Toast.makeText(context, R.string.server_error, Toast.LENGTH_SHORT).show()
|
||||
return@launchWhenCreated
|
||||
} finally {
|
||||
refreshLayout?.isRefreshing = false
|
||||
refreshLayout.isRefreshing = false
|
||||
}
|
||||
if (response.isNotEmpty()) {
|
||||
runOnUiThread {
|
||||
@ -106,7 +106,10 @@ class Library : Fragment() {
|
||||
visibility = View.GONE
|
||||
}
|
||||
}
|
||||
val playlistsAdapter = PlaylistsAdapter(response.toMutableList(), requireActivity())
|
||||
val playlistsAdapter = PlaylistsAdapter(
|
||||
response.toMutableList(),
|
||||
requireActivity()
|
||||
)
|
||||
playlistRecyclerView.adapter = playlistsAdapter
|
||||
} else {
|
||||
runOnUiThread {
|
||||
@ -124,6 +127,7 @@ class Library : Fragment() {
|
||||
}
|
||||
run()
|
||||
}
|
||||
|
||||
private fun createPlaylist(name: String, view: View) {
|
||||
fun run() {
|
||||
lifecycleScope.launchWhenCreated {
|
||||
|
@ -15,8 +15,8 @@ import androidx.fragment.app.DialogFragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.github.libretube.obj.Login
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
import retrofit2.HttpException
|
||||
|
||||
class LoginDialog : DialogFragment() {
|
||||
private val TAG = "LoginDialog"
|
||||
@ -35,7 +35,8 @@ class LoginDialog : DialogFragment() {
|
||||
val sharedPref2 = context?.getSharedPreferences("username", Context.MODE_PRIVATE)
|
||||
val user = sharedPref2?.getString("username", "")
|
||||
view = inflater.inflate(R.layout.dialog_logout, null)
|
||||
view.findViewById<TextView>(R.id.user).text = view.findViewById<TextView>(R.id.user).text.toString() + " (" + user + ")"
|
||||
view.findViewById<TextView>(R.id.user).text =
|
||||
view.findViewById<TextView>(R.id.user).text.toString() + " (" + user + ")"
|
||||
view.findViewById<Button>(R.id.logout).setOnClickListener {
|
||||
Toast.makeText(context, R.string.loggedout, Toast.LENGTH_SHORT).show()
|
||||
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
|
||||
@ -76,11 +77,11 @@ class LoginDialog : DialogFragment() {
|
||||
)
|
||||
view.findViewById<TextView>(R.id.title).text = appName
|
||||
|
||||
|
||||
builder.setView(view)
|
||||
builder.create()
|
||||
} ?: throw IllegalStateException("Activity cannot be null")
|
||||
}
|
||||
|
||||
private fun login(login: Login) {
|
||||
fun run() {
|
||||
lifecycleScope.launchWhenCreated {
|
||||
@ -108,7 +109,8 @@ class LoginDialog : DialogFragment() {
|
||||
putString("token", response.token)
|
||||
apply()
|
||||
}
|
||||
val sharedPref2 = context?.getSharedPreferences("username", Context.MODE_PRIVATE)
|
||||
val sharedPref2 =
|
||||
context?.getSharedPreferences("username", Context.MODE_PRIVATE)
|
||||
with(sharedPref2!!.edit()) {
|
||||
putString("username", login.username)
|
||||
apply()
|
||||
@ -119,6 +121,7 @@ class LoginDialog : DialogFragment() {
|
||||
}
|
||||
run()
|
||||
}
|
||||
|
||||
private fun register(login: Login) {
|
||||
fun run() {
|
||||
lifecycleScope.launchWhenCreated {
|
||||
@ -146,7 +149,8 @@ class LoginDialog : DialogFragment() {
|
||||
putString("token", response.token)
|
||||
apply()
|
||||
}
|
||||
val sharedPref2 = context?.getSharedPreferences("username", Context.MODE_PRIVATE)
|
||||
val sharedPref2 =
|
||||
context?.getSharedPreferences("username", Context.MODE_PRIVATE)
|
||||
with(sharedPref2!!.edit()) {
|
||||
putString("username", login.username)
|
||||
apply()
|
||||
|
@ -12,7 +12,10 @@ import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.util.Log
|
||||
import android.util.TypedValue
|
||||
import android.view.*
|
||||
import android.view.View
|
||||
import android.view.WindowInsets
|
||||
import android.view.WindowInsetsController
|
||||
import android.view.WindowManager
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.Button
|
||||
import android.widget.LinearLayout
|
||||
@ -40,25 +43,33 @@ class MainActivity : AppCompatActivity() {
|
||||
DynamicColors.applyToActivityIfAvailable(this)
|
||||
super.onCreate(savedInstanceState)
|
||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
RetrofitInstance.url = sharedPreferences.getString("instance", "https://pipedapi.kavin.rocks/")!!
|
||||
SponsorBlockSettings.sponsorBlockEnabled = sharedPreferences.getBoolean("sponsorblock_enabled_key", false)
|
||||
SponsorBlockSettings.introEnabled = sharedPreferences.getBoolean("intro_category_key", false)
|
||||
SponsorBlockSettings.selfPromoEnabled = sharedPreferences.getBoolean("selfpromo_category_key", false)
|
||||
SponsorBlockSettings.interactionEnabled = sharedPreferences.getBoolean("interaction_category_key", false)
|
||||
SponsorBlockSettings.sponsorsEnabled = sharedPreferences.getBoolean("sponsors_category_key", false)
|
||||
SponsorBlockSettings.outroEnabled = sharedPreferences.getBoolean("outro_category_key", false)
|
||||
RetrofitInstance.url =
|
||||
sharedPreferences.getString("instance", "https://pipedapi.kavin.rocks/")!!
|
||||
SponsorBlockSettings.sponsorBlockEnabled =
|
||||
sharedPreferences.getBoolean("sponsorblock_enabled_key", false)
|
||||
SponsorBlockSettings.introEnabled =
|
||||
sharedPreferences.getBoolean("intro_category_key", false)
|
||||
SponsorBlockSettings.selfPromoEnabled =
|
||||
sharedPreferences.getBoolean("selfpromo_category_key", false)
|
||||
SponsorBlockSettings.interactionEnabled =
|
||||
sharedPreferences.getBoolean("interaction_category_key", false)
|
||||
SponsorBlockSettings.sponsorsEnabled =
|
||||
sharedPreferences.getBoolean("sponsors_category_key", false)
|
||||
SponsorBlockSettings.outroEnabled =
|
||||
sharedPreferences.getBoolean("outro_category_key", false)
|
||||
|
||||
updateAccentColor(this)
|
||||
updateThemeMode(this)
|
||||
updateLanguage(this)
|
||||
|
||||
val connectivityManager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
val connectivityManager =
|
||||
this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
val networkInfo = connectivityManager.activeNetworkInfo
|
||||
val isConnected = networkInfo != null && networkInfo.isConnected
|
||||
|
||||
if (!isConnected) {
|
||||
setContentView(R.layout.activity_nointernet)
|
||||
findViewById<Button>(R.id.retry_button).setOnClickListener() {
|
||||
findViewById<Button>(R.id.retry_button).setOnClickListener {
|
||||
recreate()
|
||||
}
|
||||
} else {
|
||||
@ -137,10 +148,13 @@ class MainActivity : AppCompatActivity() {
|
||||
if (data.host != null) {
|
||||
if (data.path != null) {
|
||||
// channel
|
||||
if (data.path!!.contains("/channel/") || data.path!!.contains("/c/") || data.path!!.contains("/user/")) {
|
||||
if (data.path!!.contains("/channel/") ||
|
||||
data.path!!.contains("/c/") ||
|
||||
data.path!!.contains("/user/")
|
||||
) {
|
||||
var channel = data.path
|
||||
channel = channel!!.replace("/c/", "")
|
||||
channel = channel!!.replace("/user/", "")
|
||||
channel = channel.replace("/user/", "")
|
||||
val bundle = bundleOf("channel_id" to channel)
|
||||
navController.navigate(R.id.channel, bundle)
|
||||
} else if (data.path!!.contains("/playlist")) {
|
||||
@ -157,11 +171,17 @@ class MainActivity : AppCompatActivity() {
|
||||
playlist = playlist.replace("list=", "")
|
||||
val bundle = bundleOf("playlist_id" to playlist)
|
||||
navController.navigate(R.id.playlistFragment, bundle)
|
||||
} else if (data.path!!.contains("/shorts/") || data.path!!.contains("/embed/") || data.path!!.contains("/v/")) {
|
||||
var watch = data.path!!.replace("/shorts/", "").replace("/v/", "").replace("/embed/", "")
|
||||
var bundle = Bundle()
|
||||
} else if (data.path!!.contains("/shorts/") ||
|
||||
data.path!!.contains("/embed/") ||
|
||||
data.path!!.contains("/v/")
|
||||
) {
|
||||
val watch = data.path!!
|
||||
.replace("/shorts/", "")
|
||||
.replace("/v/", "")
|
||||
.replace("/embed/", "")
|
||||
val bundle = Bundle()
|
||||
bundle.putString("videoId", watch)
|
||||
var frag = PlayerFragment()
|
||||
val frag = PlayerFragment()
|
||||
frag.arguments = bundle
|
||||
supportFragmentManager.beginTransaction()
|
||||
.remove(PlayerFragment())
|
||||
@ -241,7 +261,9 @@ class MainActivity : AppCompatActivity() {
|
||||
isFullScreen = false
|
||||
} else {
|
||||
navController.popBackStack()
|
||||
if (navController.currentBackStackEntry == null && (parent as View).id != R.id.settings) {
|
||||
if (navController.currentBackStackEntry == null &&
|
||||
(parent as View).id != R.id.settings
|
||||
) {
|
||||
super.onBackPressed()
|
||||
}
|
||||
}
|
||||
@ -250,6 +272,7 @@ class MainActivity : AppCompatActivity() {
|
||||
moveTaskToBack(true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
val orientation = newConfig.orientation
|
||||
@ -261,6 +284,7 @@ class MainActivity : AppCompatActivity() {
|
||||
setFullscreen()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setFullscreen() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
window.attributes.layoutInDisplayCutoutMode =
|
||||
@ -285,6 +309,7 @@ class MainActivity : AppCompatActivity() {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun unsetFullscreen() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
window.attributes.layoutInDisplayCutoutMode =
|
||||
@ -299,7 +324,8 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
@Suppress("DEPRECATION")
|
||||
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_VISIBLE or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
|
||||
window.decorView.systemUiVisibility =
|
||||
(View.SYSTEM_UI_FLAG_VISIBLE or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
|
||||
}
|
||||
}
|
||||
|
||||
@ -310,6 +336,7 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Fragment.hideKeyboard() {
|
||||
view?.let { activity?.hideKeyboard(it) }
|
||||
}
|
||||
|
@ -1,7 +1,28 @@
|
||||
package com.github.libretube
|
||||
|
||||
import com.github.libretube.obj.*
|
||||
import retrofit2.http.*
|
||||
import com.github.libretube.obj.Channel
|
||||
import com.github.libretube.obj.CommentsPage
|
||||
import com.github.libretube.obj.Instances
|
||||
import com.github.libretube.obj.Login
|
||||
import com.github.libretube.obj.Message
|
||||
import com.github.libretube.obj.Playlist
|
||||
import com.github.libretube.obj.PlaylistId
|
||||
import com.github.libretube.obj.Playlists
|
||||
import com.github.libretube.obj.SearchResult
|
||||
import com.github.libretube.obj.Segments
|
||||
import com.github.libretube.obj.StreamItem
|
||||
import com.github.libretube.obj.Streams
|
||||
import com.github.libretube.obj.Subscribe
|
||||
import com.github.libretube.obj.Subscribed
|
||||
import com.github.libretube.obj.Subscription
|
||||
import com.github.libretube.obj.Token
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Header
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.Path
|
||||
import retrofit2.http.Query
|
||||
import retrofit2.http.Url
|
||||
|
||||
interface PipedApi {
|
||||
@GET("trending")
|
||||
@ -14,7 +35,10 @@ interface PipedApi {
|
||||
suspend fun getComments(@Path("videoId") videoId: String): CommentsPage
|
||||
|
||||
@GET("sponsors/{videoId}")
|
||||
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}")
|
||||
suspend fun getCommentsNextPage(
|
||||
@ -75,10 +99,16 @@ interface PipedApi {
|
||||
suspend fun subscriptions(@Header("Authorization") token: String): List<Subscription>
|
||||
|
||||
@POST("subscribe")
|
||||
suspend fun subscribe(@Header("Authorization") token: String, @Body subscribe: Subscribe): Message
|
||||
suspend fun subscribe(
|
||||
@Header("Authorization") token: String,
|
||||
@Body subscribe: Subscribe
|
||||
): Message
|
||||
|
||||
@POST("unsubscribe")
|
||||
suspend fun unsubscribe(@Header("Authorization") token: String, @Body subscribe: Subscribe): Message
|
||||
suspend fun unsubscribe(
|
||||
@Header("Authorization") token: String,
|
||||
@Body subscribe: Subscribe
|
||||
): Message
|
||||
|
||||
@POST("import")
|
||||
suspend fun importSubscriptions(
|
||||
@ -91,13 +121,22 @@ interface PipedApi {
|
||||
suspend fun playlists(@Header("Authorization") token: String): List<Playlists>
|
||||
|
||||
@POST("user/playlists/delete")
|
||||
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")
|
||||
suspend fun createPlaylist(@Header("Authorization") token: String, @Body name: Playlists): PlaylistId
|
||||
suspend fun createPlaylist(
|
||||
@Header("Authorization") token: String,
|
||||
@Body name: Playlists
|
||||
): PlaylistId
|
||||
|
||||
@POST("user/playlists/add")
|
||||
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")
|
||||
suspend fun removeFromPlaylist(
|
||||
|
@ -1,12 +1,8 @@
|
||||
package com.github.libretube
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import com.google.android.material.color.DynamicColors
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import android.os.Bundle
|
||||
import com.google.android.material.color.DynamicColors
|
||||
|
||||
class Player : Activity() {
|
||||
|
||||
|
@ -22,7 +22,14 @@ import android.view.ViewGroup
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.view.animation.RotateAnimation
|
||||
import android.widget.*
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageButton
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.RelativeLayout
|
||||
import android.widget.ScrollView
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.constraintlayout.motion.widget.MotionLayout
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.app.ActivityCompat
|
||||
@ -61,12 +68,12 @@ import com.google.android.exoplayer2.util.RepeatModeUtil
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.squareup.picasso.Picasso
|
||||
import org.chromium.net.CronetEngine
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
import java.net.URLEncoder
|
||||
import java.util.concurrent.Executors
|
||||
import kotlin.math.abs
|
||||
import org.chromium.net.CronetEngine
|
||||
import retrofit2.HttpException
|
||||
|
||||
var isFullScreen = false
|
||||
|
||||
@ -207,34 +214,37 @@ class PlayerFragment : Fragment() {
|
||||
}
|
||||
|
||||
view.findViewById<RelativeLayout>(R.id.player_title_layout).setOnClickListener {
|
||||
if (playerDescription.isVisible){
|
||||
val image = view.findViewById<ImageView>(R.id.player_description_arrow)
|
||||
image.clearAnimation()
|
||||
playerDescription.visibility = View.GONE
|
||||
} else {
|
||||
//toggle button
|
||||
val rotate = RotateAnimation(
|
||||
0F,
|
||||
180F,
|
||||
Animation.RELATIVE_TO_SELF,
|
||||
0.5f,
|
||||
Animation.RELATIVE_TO_SELF,
|
||||
0.5f
|
||||
)
|
||||
rotate.duration = 100
|
||||
rotate.interpolator = LinearInterpolator()
|
||||
rotate.fillAfter = true
|
||||
val image = view.findViewById<ImageView>(R.id.player_description_arrow)
|
||||
image.startAnimation(rotate)
|
||||
playerDescription.visibility = View.VISIBLE
|
||||
}
|
||||
if (playerDescription.isVisible) {
|
||||
val image = view.findViewById<ImageView>(R.id.player_description_arrow)
|
||||
image.clearAnimation()
|
||||
playerDescription.visibility = View.GONE
|
||||
} else {
|
||||
// toggle button
|
||||
val rotate = RotateAnimation(
|
||||
0F,
|
||||
180F,
|
||||
Animation.RELATIVE_TO_SELF,
|
||||
0.5f,
|
||||
Animation.RELATIVE_TO_SELF,
|
||||
0.5f
|
||||
)
|
||||
rotate.duration = 100
|
||||
rotate.interpolator = LinearInterpolator()
|
||||
rotate.fillAfter = true
|
||||
val image = view.findViewById<ImageView>(R.id.player_description_arrow)
|
||||
image.startAnimation(rotate)
|
||||
playerDescription.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
view.findViewById<com.google.android.material.card.MaterialCardView>(R.id.comments_toggle).setOnClickListener {
|
||||
commentsRecView.visibility = if (commentsRecView.isVisible) View.GONE else View.VISIBLE
|
||||
relatedRecView.visibility = if (relatedRecView.isVisible) View.GONE else View.VISIBLE
|
||||
if (!commentsLoaded!!) fetchComments()
|
||||
}
|
||||
view.findViewById<com.google.android.material.card.MaterialCardView>(R.id.comments_toggle)
|
||||
.setOnClickListener {
|
||||
commentsRecView.visibility =
|
||||
if (commentsRecView.isVisible) View.GONE else View.VISIBLE
|
||||
relatedRecView.visibility =
|
||||
if (relatedRecView.isVisible) View.GONE else View.VISIBLE
|
||||
if (!commentsLoaded!!) fetchComments()
|
||||
}
|
||||
|
||||
// FullScreen button trigger
|
||||
view.findViewById<ImageButton>(R.id.fullscreen).setOnClickListener {
|
||||
@ -266,8 +276,9 @@ class PlayerFragment : Fragment() {
|
||||
scrollView.viewTreeObserver
|
||||
.addOnScrollChangedListener {
|
||||
if (scrollView.getChildAt(0).bottom
|
||||
== (scrollView.height + scrollView.scrollY)
|
||||
&& nextPage != null) {
|
||||
== (scrollView.height + scrollView.scrollY) &&
|
||||
nextPage != null
|
||||
) {
|
||||
fetchNextComments()
|
||||
}
|
||||
}
|
||||
@ -276,8 +287,8 @@ class PlayerFragment : Fragment() {
|
||||
commentsRecView.layoutManager = LinearLayoutManager(view.context)
|
||||
|
||||
commentsRecView.setItemViewCacheSize(20)
|
||||
commentsRecView.setDrawingCacheEnabled(true)
|
||||
commentsRecView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH)
|
||||
commentsRecView.isDrawingCacheEnabled = true
|
||||
commentsRecView.drawingCacheQuality = View.DRAWING_CACHE_QUALITY_HIGH
|
||||
|
||||
relatedRecView = view.findViewById(R.id.player_recView)
|
||||
relatedRecView.layoutManager =
|
||||
@ -287,7 +298,8 @@ class PlayerFragment : Fragment() {
|
||||
override fun onStop() {
|
||||
try {
|
||||
exoPlayer.release()
|
||||
}catch (e: Exception){}
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
@ -310,7 +322,7 @@ class PlayerFragment : Fragment() {
|
||||
|
||||
segmentData.segments.forEach { segment: Segment ->
|
||||
val segmentStart = (segment.segment!![0] * 1000.0f).toLong()
|
||||
val segmentEnd = (segment.segment!![1] * 1000.0f).toLong()
|
||||
val segmentEnd = (segment.segment[1] * 1000.0f).toLong()
|
||||
val currentPosition = exoPlayer.currentPosition
|
||||
if (currentPosition in segmentStart until segmentEnd) {
|
||||
Toast.makeText(context, R.string.segment_skipped, Toast.LENGTH_SHORT).show()
|
||||
@ -383,10 +395,10 @@ class PlayerFragment : Fragment() {
|
||||
runOnUiThread {
|
||||
var subtitle = mutableListOf<SubtitleConfiguration>()
|
||||
if (response.subtitles!!.isNotEmpty()) {
|
||||
subtitle?.add(
|
||||
SubtitleConfiguration.Builder(response.subtitles!![0].url!!.toUri())
|
||||
.setMimeType(response.subtitles!![0].mimeType!!) // The correct MIME type (required).
|
||||
.setLanguage(response.subtitles!![0].code) // The subtitle language (optional).
|
||||
subtitle.add(
|
||||
SubtitleConfiguration.Builder(response.subtitles[0].url!!.toUri())
|
||||
.setMimeType(response.subtitles[0].mimeType!!) // The correct MIME type (required).
|
||||
.setLanguage(response.subtitles[0].code) // The subtitle language (optional).
|
||||
.build()
|
||||
)
|
||||
}
|
||||
@ -426,7 +438,7 @@ class PlayerFragment : Fragment() {
|
||||
defres != "" -> {
|
||||
var foundRes = false
|
||||
run lit@{
|
||||
response.videoStreams!!.forEachIndexed { index, pipedStream ->
|
||||
response.videoStreams.forEachIndexed { index, pipedStream ->
|
||||
if (pipedStream.quality!!.contains(defres)) {
|
||||
foundRes = true
|
||||
val dataSourceFactory: DataSource.Factory =
|
||||
@ -440,13 +452,18 @@ class PlayerFragment : Fragment() {
|
||||
.createMediaSource(videoItem)
|
||||
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") {
|
||||
.createMediaSource(
|
||||
fromUri(response.audioStreams!![0].url!!)
|
||||
)
|
||||
if (response.videoStreams[index].quality == "720p" ||
|
||||
response.videoStreams[index].quality == "1080p" ||
|
||||
response.videoStreams[index].quality == "480p"
|
||||
) {
|
||||
audioSource =
|
||||
ProgressiveMediaSource.Factory(dataSourceFactory)
|
||||
.createMediaSource(
|
||||
fromUri(
|
||||
response.audioStreams!![
|
||||
response.audioStreams[
|
||||
getMostBitRate(
|
||||
response.audioStreams
|
||||
)
|
||||
@ -490,11 +507,14 @@ class PlayerFragment : Fragment() {
|
||||
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)
|
||||
.createMediaSource(
|
||||
fromUri(
|
||||
response.audioStreams!![
|
||||
response.audioStreams[
|
||||
getMostBitRate(
|
||||
response.audioStreams
|
||||
)
|
||||
@ -528,13 +548,15 @@ class PlayerFragment : Fragment() {
|
||||
videosNameArray,
|
||||
DialogInterface.OnClickListener { _, which ->
|
||||
whichQuality = which
|
||||
if (response.subtitles!!.isNotEmpty()) {
|
||||
if (response.subtitles.isNotEmpty()) {
|
||||
var subtitle =
|
||||
mutableListOf<SubtitleConfiguration>()
|
||||
subtitle?.add(
|
||||
SubtitleConfiguration.Builder(response.subtitles!![0].url!!.toUri())
|
||||
.setMimeType(response.subtitles!![0].mimeType!!) // The correct MIME type (required).
|
||||
.setLanguage(response.subtitles!![0].code) // The subtitle language (optional).
|
||||
subtitle.add(
|
||||
SubtitleConfiguration.Builder(
|
||||
response.subtitles[0].url!!.toUri()
|
||||
)
|
||||
.setMimeType(response.subtitles[0].mimeType!!) // The correct MIME type (required).
|
||||
.setLanguage(response.subtitles[0].code) // The subtitle language (optional).
|
||||
.build()
|
||||
)
|
||||
}
|
||||
@ -556,13 +578,18 @@ class PlayerFragment : Fragment() {
|
||||
.createMediaSource(videoItem)
|
||||
var audioSource: MediaSource =
|
||||
DefaultMediaSourceFactory(dataSourceFactory)
|
||||
.createMediaSource(fromUri(response.audioStreams!![0].url!!))
|
||||
if (response.videoStreams[which - 1].quality == "720p" || response.videoStreams[which - 1].quality == "1080p" || response.videoStreams[which - 1].quality == "480p") {
|
||||
.createMediaSource(
|
||||
fromUri(response.audioStreams!![0].url!!)
|
||||
)
|
||||
if (response.videoStreams[which - 1].quality == "720p" ||
|
||||
response.videoStreams[which - 1].quality == "1080p" ||
|
||||
response.videoStreams[which - 1].quality == "480p"
|
||||
) {
|
||||
audioSource =
|
||||
ProgressiveMediaSource.Factory(dataSourceFactory)
|
||||
.createMediaSource(
|
||||
fromUri(
|
||||
response.audioStreams!![
|
||||
response.audioStreams[
|
||||
getMostBitRate(
|
||||
response.audioStreams
|
||||
)
|
||||
@ -579,14 +606,17 @@ class PlayerFragment : Fragment() {
|
||||
videosNameArray[which]
|
||||
}
|
||||
)
|
||||
val dialog = builder?.create()
|
||||
dialog?.show()
|
||||
val dialog = builder.create()
|
||||
dialog.show()
|
||||
}
|
||||
// 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) {
|
||||
if (isPlaying && SponsorBlockSettings.sponsorBlockEnabled) {
|
||||
exoPlayerView.postDelayed(this@PlayerFragment::checkForSegments, 100)
|
||||
exoPlayerView.postDelayed(
|
||||
this@PlayerFragment::checkForSegments,
|
||||
100
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -596,7 +626,8 @@ class PlayerFragment : Fragment() {
|
||||
) {
|
||||
|
||||
exoPlayerView.keepScreenOn = !(
|
||||
playbackState == Player.STATE_IDLE || playbackState == Player.STATE_ENDED ||
|
||||
playbackState == Player.STATE_IDLE ||
|
||||
playbackState == Player.STATE_ENDED ||
|
||||
!playWhenReady
|
||||
)
|
||||
|
||||
@ -692,7 +723,8 @@ class PlayerFragment : Fragment() {
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
requireContext(),
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE
|
||||
) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(
|
||||
) != PackageManager.PERMISSION_GRANTED ||
|
||||
ActivityCompat.checkSelfPermission(
|
||||
requireContext(),
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
@ -711,7 +743,7 @@ class PlayerFragment : Fragment() {
|
||||
vidName.add("No video")
|
||||
var vidUrl = arrayListOf<String>()
|
||||
vidUrl.add("")
|
||||
for (vid in response.videoStreams!!) {
|
||||
for (vid in response.videoStreams) {
|
||||
val name = vid.quality + " " + vid.format
|
||||
vidName.add(name)
|
||||
vidUrl.add(vid.url!!)
|
||||
@ -874,10 +906,6 @@ class PlayerFragment : Fragment() {
|
||||
return index
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
}
|
||||
|
||||
private fun fetchComments() {
|
||||
lifecycleScope.launchWhenCreated {
|
||||
val commentsResponse = try {
|
||||
@ -914,7 +942,7 @@ class PlayerFragment : Fragment() {
|
||||
return@launchWhenCreated
|
||||
}
|
||||
nextPage = response.nextpage
|
||||
commentsAdapter?.updateItems(response.comments!!)
|
||||
commentsAdapter?.updateItems(response.comments)
|
||||
isLoading = false
|
||||
}
|
||||
}
|
||||
@ -950,7 +978,12 @@ class PlayerFragment : Fragment() {
|
||||
val scrollView = view?.findViewById<ScrollView>(R.id.player_scrollView)
|
||||
scrollView?.getHitRect(bounds)
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ class PlaylistFragment : Fragment() {
|
||||
|
||||
fetchPlaylist(view)
|
||||
}
|
||||
|
||||
private fun fetchPlaylist(view: View) {
|
||||
fun run() {
|
||||
lifecycleScope.launchWhenCreated {
|
||||
@ -66,14 +67,21 @@ class PlaylistFragment : Fragment() {
|
||||
runOnUiThread {
|
||||
view.findViewById<TextView>(R.id.playlist_name).text = response.name
|
||||
view.findViewById<TextView>(R.id.playlist_uploader).text = response.uploader
|
||||
view.findViewById<TextView>(R.id.playlist_totVideos).text = response.videos.toString() + " Videos"
|
||||
val sharedPref2 = context?.getSharedPreferences("username", Context.MODE_PRIVATE)
|
||||
view.findViewById<TextView>(R.id.playlist_totVideos).text =
|
||||
response.videos.toString() + " Videos"
|
||||
val sharedPref2 =
|
||||
context?.getSharedPreferences("username", Context.MODE_PRIVATE)
|
||||
val user = sharedPref2?.getString("username", "")
|
||||
var isOwner = false
|
||||
if (response.uploaderUrl == null && response.uploader.equals(user, true)) {
|
||||
isOwner = true
|
||||
}
|
||||
playlistAdapter = PlaylistAdapter(response.relatedStreams!!.toMutableList(), playlist_id!!, isOwner, requireActivity())
|
||||
playlistAdapter = PlaylistAdapter(
|
||||
response.relatedStreams!!.toMutableList(),
|
||||
playlist_id!!,
|
||||
isOwner,
|
||||
requireActivity()
|
||||
)
|
||||
view.findViewById<RecyclerView>(R.id.playlist_recView).adapter = playlistAdapter
|
||||
val scrollView = view.findViewById<ScrollView>(R.id.playlist_scrollview)
|
||||
scrollView.viewTreeObserver
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.github.libretube
|
||||
|
||||
import java.util.*
|
||||
import java.util.LinkedList
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class ResettableLazyManager {
|
||||
@ -25,8 +25,10 @@ interface Resettable {
|
||||
fun reset()
|
||||
}
|
||||
|
||||
class ResettableLazy<PROPTYPE>(val manager: ResettableLazyManager, val init: () -> PROPTYPE) : Resettable {
|
||||
@Volatile var lazyHolder = makeInitBlock()
|
||||
class ResettableLazy<PROPTYPE>(val manager: ResettableLazyManager, val init: () -> PROPTYPE) :
|
||||
Resettable {
|
||||
@Volatile
|
||||
var lazyHolder = makeInitBlock()
|
||||
|
||||
operator fun getValue(thisRef: Any?, property: KProperty<*>): PROPTYPE {
|
||||
return lazyHolder.value
|
||||
@ -44,7 +46,8 @@ class ResettableLazy<PROPTYPE>(val manager: ResettableLazyManager, val init: ()
|
||||
}
|
||||
}
|
||||
|
||||
fun <PROPTYPE> resettableLazy(manager: ResettableLazyManager, init: () -> PROPTYPE): ResettableLazy<PROPTYPE> {
|
||||
fun <PROPTYPE> resettableLazy(manager: ResettableLazyManager, init: () -> PROPTYPE):
|
||||
ResettableLazy<PROPTYPE> {
|
||||
return ResettableLazy(manager, init)
|
||||
}
|
||||
|
||||
|
@ -9,13 +9,15 @@ import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.AutoCompleteTextView
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView.*
|
||||
import android.widget.TextView.GONE
|
||||
import android.widget.TextView.OnEditorActionListener
|
||||
import android.widget.TextView.VISIBLE
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.PreferenceManager
|
||||
@ -25,11 +27,11 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import com.github.libretube.adapters.SearchAdapter
|
||||
import com.github.libretube.adapters.SearchHistoryAdapter
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import java.io.IOException
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
|
||||
class SearchFragment : Fragment() {
|
||||
private val TAG = "SearchFragment"
|
||||
@ -83,8 +85,7 @@ class SearchFragment : Fragment() {
|
||||
.setTitle(getString(R.string.choose_filter))
|
||||
.setSingleChoiceItems(
|
||||
filterOptions, selectedFilter,
|
||||
DialogInterface.OnClickListener {
|
||||
_, id ->
|
||||
DialogInterface.OnClickListener { _, id ->
|
||||
tempSelectedItem = id
|
||||
}
|
||||
)
|
||||
@ -154,8 +155,13 @@ class SearchFragment : Fragment() {
|
||||
GlobalScope.launch {
|
||||
fetchSuggestions(s.toString(), autoTextView)
|
||||
delay(1000)
|
||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
if (sharedPreferences.getBoolean("search_history_toggle", true)) addtohistory(s.toString())
|
||||
val sharedPreferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
if (sharedPreferences.getBoolean(
|
||||
"search_history_toggle",
|
||||
true
|
||||
)
|
||||
) addtohistory(s.toString())
|
||||
fetchSearch(s.toString())
|
||||
}
|
||||
}
|
||||
@ -200,10 +206,12 @@ class SearchFragment : Fragment() {
|
||||
Log.e(TAG, "HttpException, unexpected response")
|
||||
return@launchWhenCreated
|
||||
}
|
||||
val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, response)
|
||||
val adapter =
|
||||
ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, response)
|
||||
autoTextView.setAdapter(adapter)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchSearch(query: String) {
|
||||
lifecycleScope.launchWhenCreated {
|
||||
val response = try {
|
||||
@ -232,7 +240,11 @@ class SearchFragment : Fragment() {
|
||||
if (!isLoading) {
|
||||
isLoading = true
|
||||
val response = try {
|
||||
RetrofitInstance.api.getSearchResultsNextPage(query, apiSearchFilter, nextPage!!)
|
||||
RetrofitInstance.api.getSearchResultsNextPage(
|
||||
query,
|
||||
apiSearchFilter,
|
||||
nextPage!!
|
||||
)
|
||||
} catch (e: IOException) {
|
||||
println(e)
|
||||
Log.e(TAG, "IOException, you might not have internet connection")
|
||||
@ -256,7 +268,7 @@ class SearchFragment : Fragment() {
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
requireActivity().window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)
|
||||
requireActivity().window.setSoftInputMode(SOFT_INPUT_STATE_ALWAYS_HIDDEN)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
|
@ -1,7 +1,11 @@
|
||||
package com.github.libretube
|
||||
|
||||
import android.Manifest
|
||||
import android.content.*
|
||||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
@ -24,13 +28,13 @@ import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.google.android.material.color.DynamicColors
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.json.JSONObject
|
||||
import org.json.JSONTokener
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
import org.json.JSONObject
|
||||
import org.json.JSONTokener
|
||||
import retrofit2.HttpException
|
||||
|
||||
class SettingsActivity :
|
||||
AppCompatActivity(),
|
||||
@ -61,7 +65,11 @@ class SettingsActivity :
|
||||
.registerOnSharedPreferenceChangeListener(this)
|
||||
}
|
||||
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, rootKey: String?) {}
|
||||
override fun onSharedPreferenceChanged(
|
||||
sharedPreferences: SharedPreferences?,
|
||||
rootKey: String?
|
||||
) {
|
||||
}
|
||||
|
||||
class SettingsFragment : PreferenceFragmentCompat() {
|
||||
val TAG = "Settings"
|
||||
@ -71,66 +79,72 @@ class SettingsActivity :
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
|
||||
if (uri != null) {
|
||||
try {
|
||||
// Open a specific media item using ParcelFileDescriptor.
|
||||
val resolver: ContentResolver =
|
||||
requireActivity()
|
||||
.contentResolver
|
||||
getContent =
|
||||
registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
|
||||
if (uri != null) {
|
||||
try {
|
||||
// Open a specific media item using ParcelFileDescriptor.
|
||||
val resolver: ContentResolver =
|
||||
requireActivity()
|
||||
.contentResolver
|
||||
|
||||
// "rw" for read-and-write;
|
||||
// "rwt" for truncating or overwriting existing file contents.
|
||||
// val readOnlyMode = "r"
|
||||
// uri - I have got from onActivityResult
|
||||
val type = resolver.getType(uri)
|
||||
// "rw" for read-and-write;
|
||||
// "rwt" for truncating or overwriting existing file contents.
|
||||
// val readOnlyMode = "r"
|
||||
// uri - I have got from onActivityResult
|
||||
val type = resolver.getType(uri)
|
||||
|
||||
var inputStream: InputStream? = resolver.openInputStream(uri)
|
||||
val channels = ArrayList<String>()
|
||||
if (type == "application/json") {
|
||||
val json = inputStream?.bufferedReader()?.readLines()?.get(0)
|
||||
val jsonObject = JSONTokener(json).nextValue() as JSONObject
|
||||
Log.e(TAG, jsonObject.getJSONArray("subscriptions").toString())
|
||||
for (i in 0 until jsonObject.getJSONArray("subscriptions").length()) {
|
||||
var url = jsonObject.getJSONArray("subscriptions").getJSONObject(i).getString("url")
|
||||
url = url.replace("https://www.youtube.com/channel/", "")
|
||||
Log.e(TAG, url)
|
||||
channels.add(url)
|
||||
}
|
||||
} else {
|
||||
if (type == "application/zip") {
|
||||
val zis = ZipInputStream(inputStream)
|
||||
var entry: ZipEntry? = zis.nextEntry
|
||||
while (entry != null) {
|
||||
if (entry.name.endsWith(".csv")) {
|
||||
inputStream = zis
|
||||
break
|
||||
var inputStream: InputStream? = resolver.openInputStream(uri)
|
||||
val channels = ArrayList<String>()
|
||||
if (type == "application/json") {
|
||||
val json = inputStream?.bufferedReader()?.readLines()?.get(0)
|
||||
val jsonObject = JSONTokener(json).nextValue() as JSONObject
|
||||
Log.e(TAG, jsonObject.getJSONArray("subscriptions").toString())
|
||||
for (
|
||||
i in 0 until jsonObject.getJSONArray("subscriptions")
|
||||
.length()
|
||||
) {
|
||||
var url =
|
||||
jsonObject.getJSONArray("subscriptions").getJSONObject(i)
|
||||
.getString("url")
|
||||
url = url.replace("https://www.youtube.com/channel/", "")
|
||||
Log.e(TAG, url)
|
||||
channels.add(url)
|
||||
}
|
||||
} else {
|
||||
if (type == "application/zip") {
|
||||
val zis = ZipInputStream(inputStream)
|
||||
var entry: ZipEntry? = zis.nextEntry
|
||||
while (entry != null) {
|
||||
if (entry.name.endsWith(".csv")) {
|
||||
inputStream = zis
|
||||
break
|
||||
}
|
||||
entry = zis.nextEntry
|
||||
}
|
||||
entry = zis.nextEntry
|
||||
}
|
||||
}
|
||||
|
||||
inputStream?.bufferedReader()?.readLines()?.forEach {
|
||||
if (it.isNotBlank()) {
|
||||
val channelId = it.substringBefore(",")
|
||||
if (channelId.length == 24)
|
||||
channels.add(channelId)
|
||||
inputStream?.bufferedReader()?.readLines()?.forEach {
|
||||
if (it.isNotBlank()) {
|
||||
val channelId = it.substringBefore(",")
|
||||
if (channelId.length == 24)
|
||||
channels.add(channelId)
|
||||
}
|
||||
}
|
||||
}
|
||||
inputStream?.close()
|
||||
|
||||
subscribe(channels)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, e.toString())
|
||||
Toast.makeText(
|
||||
context,
|
||||
R.string.error,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
inputStream?.close()
|
||||
|
||||
subscribe(channels)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, e.toString())
|
||||
Toast.makeText(
|
||||
context,
|
||||
R.string.error,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
@ -155,7 +169,6 @@ class SettingsActivity :
|
||||
val login = findPreference<Preference>("login_register")
|
||||
login?.setOnPreferenceClickListener {
|
||||
|
||||
|
||||
val newFragment = LoginDialog()
|
||||
newFragment.show(childFragmentManager, "Login")
|
||||
true
|
||||
@ -200,7 +213,8 @@ class SettingsActivity :
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
requireContext(),
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE
|
||||
) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(
|
||||
) != PackageManager.PERMISSION_GRANTED ||
|
||||
ActivityCompat.checkSelfPermission(
|
||||
requireContext(),
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
@ -245,7 +259,8 @@ class SettingsActivity :
|
||||
|
||||
val clearHistory = findPreference<Preference>("clear_history")
|
||||
clearHistory?.setOnPreferenceClickListener {
|
||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
val sharedPreferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
sharedPreferences.edit().remove("search_history").commit()
|
||||
true
|
||||
}
|
||||
@ -269,7 +284,10 @@ class SettingsActivity :
|
||||
Html.fromHtml(licenseString)
|
||||
}
|
||||
MaterialAlertDialogBuilder(view?.context!!)
|
||||
.setPositiveButton(getString(R.string.okay), DialogInterface.OnClickListener { _, _ -> })
|
||||
.setPositiveButton(
|
||||
getString(R.string.okay),
|
||||
DialogInterface.OnClickListener { _, _ -> }
|
||||
)
|
||||
.setMessage(licenseHtml)
|
||||
.create()
|
||||
.show()
|
||||
@ -327,7 +345,8 @@ class SettingsActivity :
|
||||
fun run() {
|
||||
lifecycleScope.launchWhenCreated {
|
||||
val response = try {
|
||||
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
|
||||
val sharedPref =
|
||||
context?.getSharedPreferences("token", Context.MODE_PRIVATE)
|
||||
RetrofitInstance.api.importSubscriptions(
|
||||
false,
|
||||
sharedPref?.getString("token", "")!!,
|
||||
@ -359,5 +378,4 @@ class SettingsActivity :
|
||||
intent = Intent(this, MainActivity::class.java)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,7 +14,8 @@ import androidx.constraintlayout.motion.widget.MotionLayout
|
||||
*
|
||||
*/
|
||||
|
||||
class SingleViewTouchableMotionLayout(context: Context, attributeSet: AttributeSet? = null) : MotionLayout(context, attributeSet) {
|
||||
class SingleViewTouchableMotionLayout(context: Context, attributeSet: AttributeSet? = null) :
|
||||
MotionLayout(context, attributeSet) {
|
||||
|
||||
private val viewToDetectTouch by lazy {
|
||||
findViewById<View>(R.id.main_container) // TODO move to Attributes
|
||||
|
@ -6,6 +6,7 @@ import androidx.preference.SwitchPreferenceCompat
|
||||
|
||||
class SponsorBlockSettings : PreferenceFragmentCompat() {
|
||||
private val TAG = "SponsorBlockDialog"
|
||||
|
||||
companion object {
|
||||
var sponsorBlockEnabled: Boolean = false
|
||||
var sponsorsEnabled: Boolean = false
|
||||
|
@ -9,7 +9,12 @@ import android.view.ViewGroup
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.view.animation.RotateAnimation
|
||||
import android.widget.*
|
||||
import android.widget.ImageView
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.RelativeLayout
|
||||
import android.widget.ScrollView
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
@ -19,9 +24,8 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import com.github.libretube.adapters.SubscriptionAdapter
|
||||
import com.github.libretube.adapters.SubscriptionChannelAdapter
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
|
||||
import retrofit2.HttpException
|
||||
|
||||
class Subscriptions : Fragment() {
|
||||
val TAG = "SubFragment"
|
||||
@ -60,7 +64,9 @@ class Subscriptions : Fragment() {
|
||||
|
||||
var feedRecView = view.findViewById<RecyclerView>(R.id.sub_feed)
|
||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
val grid = sharedPreferences.getString("grid", resources.getInteger(R.integer.grid_items).toString())!!
|
||||
val grid = sharedPreferences.getString(
|
||||
"grid", resources.getInteger(R.integer.grid_items).toString()
|
||||
)!!
|
||||
feedRecView.layoutManager = GridLayoutManager(view.context, grid.toInt())
|
||||
fetchFeed(feedRecView, progressBar, view)
|
||||
|
||||
@ -82,7 +88,7 @@ class Subscriptions : Fragment() {
|
||||
channelRecView.visibility = View.VISIBLE
|
||||
feedRecView.visibility = View.GONE
|
||||
|
||||
//toggle button
|
||||
// toggle button
|
||||
val rotate = RotateAnimation(
|
||||
0F,
|
||||
180F,
|
||||
@ -96,12 +102,11 @@ class Subscriptions : Fragment() {
|
||||
rotate.fillAfter = true
|
||||
val image = view.findViewById<ImageView>(R.id.toggle)
|
||||
image.startAnimation(rotate)
|
||||
|
||||
} else {
|
||||
channelRecView.visibility = View.GONE
|
||||
feedRecView.visibility = View.VISIBLE
|
||||
|
||||
//toggle button
|
||||
// toggle button
|
||||
val image = view.findViewById<ImageView>(R.id.toggle)
|
||||
image.clearAnimation()
|
||||
}
|
||||
@ -143,7 +148,7 @@ class Subscriptions : Fragment() {
|
||||
}
|
||||
if (response.isNotEmpty()) {
|
||||
subscriptionAdapter = SubscriptionAdapter(response)
|
||||
feedRecView?.adapter = subscriptionAdapter
|
||||
feedRecView.adapter = subscriptionAdapter
|
||||
subscriptionAdapter?.updateItems()
|
||||
} else {
|
||||
runOnUiThread {
|
||||
@ -155,7 +160,8 @@ class Subscriptions : Fragment() {
|
||||
visibility = View.VISIBLE
|
||||
text = getString(R.string.emptyList)
|
||||
}
|
||||
view.findViewById<RelativeLayout>(R.id.loginOrRegister).visibility = View.VISIBLE
|
||||
view.findViewById<RelativeLayout>(R.id.loginOrRegister)
|
||||
.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
progressBar.visibility = View.GONE
|
||||
@ -181,7 +187,7 @@ class Subscriptions : Fragment() {
|
||||
refreshLayout?.isRefreshing = false
|
||||
}
|
||||
if (response.isNotEmpty()) {
|
||||
channelRecView?.adapter = SubscriptionChannelAdapter(response.toMutableList())
|
||||
channelRecView.adapter = SubscriptionChannelAdapter(response.toMutableList())
|
||||
} else {
|
||||
Toast.makeText(context, R.string.subscribeIsEmpty, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
@ -189,12 +195,14 @@ class Subscriptions : Fragment() {
|
||||
}
|
||||
run()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
Log.e(TAG, "Destroyed")
|
||||
super.onDestroy()
|
||||
subscriptionAdapter = null
|
||||
view?.findViewById<RecyclerView>(R.id.sub_feed)?.adapter = null
|
||||
}
|
||||
|
||||
private fun Fragment?.runOnUiThread(action: () -> Unit) {
|
||||
this ?: return
|
||||
if (!isAdded) return // Fragment not attached to an Activity
|
||||
|
@ -3,10 +3,11 @@ package com.github.libretube
|
||||
import android.content.Context
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.preference.PreferenceManager
|
||||
import java.util.*
|
||||
import java.util.Locale
|
||||
|
||||
fun updateAccentColor(context: Context) {
|
||||
val colorAccent = PreferenceManager.getDefaultSharedPreferences(context).getString("accent_color", "red")
|
||||
val colorAccent =
|
||||
PreferenceManager.getDefaultSharedPreferences(context).getString("accent_color", "red")
|
||||
when (colorAccent) {
|
||||
"my" -> context.setTheme(R.style.Theme_MY)
|
||||
"red" -> context.setTheme(R.style.Theme_Red)
|
||||
@ -18,7 +19,8 @@ fun updateAccentColor(context: Context) {
|
||||
}
|
||||
|
||||
fun updateThemeMode(context: Context) {
|
||||
val themeMode = PreferenceManager.getDefaultSharedPreferences(context).getString("theme_togglee", "A")
|
||||
val themeMode =
|
||||
PreferenceManager.getDefaultSharedPreferences(context).getString("theme_togglee", "A")
|
||||
when (themeMode) {
|
||||
"A" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
||||
"L" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
|
||||
|
@ -15,10 +15,12 @@ import com.github.libretube.formatShort
|
||||
import com.github.libretube.obj.StreamItem
|
||||
import com.squareup.picasso.Picasso
|
||||
|
||||
class ChannelAdapter(private val videoFeed: MutableList<StreamItem>) : RecyclerView.Adapter<ChannelViewHolder>() {
|
||||
class ChannelAdapter(private val videoFeed: MutableList<StreamItem>) :
|
||||
RecyclerView.Adapter<ChannelViewHolder>() {
|
||||
override fun getItemCount(): Int {
|
||||
return videoFeed.size
|
||||
}
|
||||
|
||||
fun updateItems(newItems: List<StreamItem>) {
|
||||
videoFeed.addAll(newItems)
|
||||
notifyDataSetChanged()
|
||||
@ -33,8 +35,11 @@ class ChannelAdapter(private val videoFeed: MutableList<StreamItem>) : RecyclerV
|
||||
override fun onBindViewHolder(holder: ChannelViewHolder, position: Int) {
|
||||
val trending = videoFeed[position]
|
||||
holder.v.findViewById<TextView>(R.id.channel_description).text = trending.title
|
||||
holder.v.findViewById<TextView>(R.id.channel_views).text = trending.views.formatShort() + " • " + DateUtils.getRelativeTimeSpanString(trending.uploaded!!)
|
||||
holder.v.findViewById<TextView>(R.id.channel_duration).text = DateUtils.formatElapsedTime(trending.duration!!)
|
||||
holder.v.findViewById<TextView>(R.id.channel_views).text =
|
||||
trending.views.formatShort() + " • " +
|
||||
DateUtils.getRelativeTimeSpanString(trending.uploaded!!)
|
||||
holder.v.findViewById<TextView>(R.id.channel_duration).text =
|
||||
DateUtils.formatElapsedTime(trending.duration!!)
|
||||
val thumbnailImage = holder.v.findViewById<ImageView>(R.id.channel_thumbnail)
|
||||
Picasso.get().load(trending.thumbnail).into(thumbnailImage)
|
||||
holder.v.setOnClickListener {
|
||||
@ -52,6 +57,7 @@ class ChannelAdapter(private val videoFeed: MutableList<StreamItem>) : RecyclerV
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ChannelViewHolder(val v: View) : RecyclerView.ViewHolder(v) {
|
||||
init {
|
||||
}
|
||||
|
@ -14,7 +14,8 @@ import com.github.libretube.formatShort
|
||||
import com.github.libretube.obj.Comment
|
||||
import com.squareup.picasso.Picasso
|
||||
|
||||
class CommentsAdapter(private val comments: MutableList<Comment>) : RecyclerView.Adapter<ViewHolder>() {
|
||||
class CommentsAdapter(private val comments: MutableList<Comment>) :
|
||||
RecyclerView.Adapter<ViewHolder>() {
|
||||
|
||||
fun updateItems(newItems: List<Comment>) {
|
||||
var commentsSize = comments.size
|
||||
@ -23,16 +24,21 @@ class CommentsAdapter(private val comments: MutableList<Comment>) : RecyclerView
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
var commentsView = LayoutInflater.from(parent.context).inflate(R.layout.comments_row, parent, false)
|
||||
var commentsView =
|
||||
LayoutInflater.from(parent.context).inflate(R.layout.comments_row, parent, false)
|
||||
return ViewHolder(commentsView)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
holder.v.findViewById<TextView>(R.id.comment_infos).text = comments[position].author.toString() + " • " + comments[position].commentedTime.toString()
|
||||
holder.v.findViewById<TextView>(R.id.comment_text).text = comments[position].commentText.toString()
|
||||
holder.v.findViewById<TextView>(R.id.comment_infos).text =
|
||||
comments[position].author.toString() +
|
||||
" • " + comments[position].commentedTime.toString()
|
||||
holder.v.findViewById<TextView>(R.id.comment_text).text =
|
||||
comments[position].commentText.toString()
|
||||
val channelImage = holder.v.findViewById<ImageView>(R.id.commentor_image)
|
||||
Picasso.get().load(comments[position].thumbnail).fit().centerCrop().into(channelImage)
|
||||
holder.v.findViewById<TextView>(R.id.likes_textView).text = comments[position].likeCount?.toLong().formatShort()
|
||||
holder.v.findViewById<TextView>(R.id.likes_textView).text =
|
||||
comments[position].likeCount?.toLong().formatShort()
|
||||
if (comments[position].verified == true) {
|
||||
holder.v.findViewById<ImageView>(R.id.verified_imageView).visibility = View.VISIBLE
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ class PlaylistAdapter(
|
||||
override fun getItemCount(): Int {
|
||||
return videoFeed.size
|
||||
}
|
||||
|
||||
fun updateItems(newItems: List<StreamItem>) {
|
||||
videoFeed.addAll(newItems)
|
||||
notifyDataSetChanged()
|
||||
@ -48,7 +49,8 @@ class PlaylistAdapter(
|
||||
val streamItem = videoFeed[position]
|
||||
holder.v.findViewById<TextView>(R.id.playlist_title).text = streamItem.title
|
||||
holder.v.findViewById<TextView>(R.id.playlist_description).text = streamItem.uploaderName
|
||||
holder.v.findViewById<TextView>(R.id.playlist_duration).text = DateUtils.formatElapsedTime(streamItem.duration!!)
|
||||
holder.v.findViewById<TextView>(R.id.playlist_duration).text =
|
||||
DateUtils.formatElapsedTime(streamItem.duration!!)
|
||||
val thumbnailImage = holder.v.findViewById<ImageView>(R.id.playlist_thumbnail)
|
||||
Picasso.get().load(streamItem.thumbnail).into(thumbnailImage)
|
||||
holder.v.setOnClickListener {
|
||||
@ -68,17 +70,24 @@ class PlaylistAdapter(
|
||||
val delete = holder.v.findViewById<ImageView>(R.id.delete_playlist)
|
||||
delete.visibility = View.VISIBLE
|
||||
delete.setOnClickListener {
|
||||
val sharedPref = holder.v.context.getSharedPreferences("token", Context.MODE_PRIVATE)
|
||||
val sharedPref = holder.v.context.getSharedPreferences(
|
||||
"token",
|
||||
Context.MODE_PRIVATE
|
||||
)
|
||||
val token = sharedPref?.getString("token", "")!!
|
||||
removeFromPlaylist(token, position)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeFromPlaylist(token: String, position: Int) {
|
||||
fun run() {
|
||||
GlobalScope.launch {
|
||||
val response = try {
|
||||
RetrofitInstance.api.removeFromPlaylist(token, PlaylistId(playlistId = playlistId, index = position))
|
||||
RetrofitInstance.api.removeFromPlaylist(
|
||||
token,
|
||||
PlaylistId(playlistId = playlistId, index = position)
|
||||
)
|
||||
} catch (e: IOException) {
|
||||
println(e)
|
||||
Log.e(TAG, "IOException, you might not have internet connection")
|
||||
@ -107,6 +116,7 @@ class PlaylistAdapter(
|
||||
run()
|
||||
}
|
||||
}
|
||||
|
||||
class PlaylistViewHolder(val v: View) : RecyclerView.ViewHolder(v) {
|
||||
init {
|
||||
}
|
||||
|
@ -17,10 +17,10 @@ import com.github.libretube.obj.PlaylistId
|
||||
import com.github.libretube.obj.Playlists
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.squareup.picasso.Picasso
|
||||
import java.io.IOException
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
|
||||
class PlaylistsAdapter(
|
||||
private val playlists: MutableList<Playlists>,
|
||||
@ -30,6 +30,7 @@ class PlaylistsAdapter(
|
||||
override fun getItemCount(): Int {
|
||||
return playlists.size
|
||||
}
|
||||
|
||||
fun updateItems(newItems: List<Playlists>) {
|
||||
playlists.addAll(newItems)
|
||||
notifyDataSetChanged()
|
||||
@ -51,7 +52,10 @@ class PlaylistsAdapter(
|
||||
builder.setTitle(R.string.deletePlaylist)
|
||||
builder.setMessage(R.string.areYouSure)
|
||||
builder.setPositiveButton(R.string.yes) { dialog, which ->
|
||||
val sharedPref = holder.v.context.getSharedPreferences("token", Context.MODE_PRIVATE)
|
||||
val sharedPref = holder.v.context.getSharedPreferences(
|
||||
"token",
|
||||
Context.MODE_PRIVATE
|
||||
)
|
||||
val token = sharedPref?.getString("token", "")!!
|
||||
deletePlaylist(playlist.id!!, token, position)
|
||||
}
|
||||
@ -66,6 +70,7 @@ class PlaylistsAdapter(
|
||||
activity.navController.navigate(R.id.playlistFragment, bundle)
|
||||
}
|
||||
}
|
||||
|
||||
private fun deletePlaylist(id: String, token: String, position: Int) {
|
||||
fun run() {
|
||||
GlobalScope.launch {
|
||||
@ -99,6 +104,7 @@ class PlaylistsAdapter(
|
||||
run()
|
||||
}
|
||||
}
|
||||
|
||||
class PlaylistsViewHolder(val v: View) : RecyclerView.ViewHolder(v) {
|
||||
init {
|
||||
}
|
||||
|
@ -17,7 +17,8 @@ import com.github.libretube.formatShort
|
||||
import com.github.libretube.obj.SearchItem
|
||||
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>) {
|
||||
var searchItemsSize = searchItems.size
|
||||
@ -54,6 +55,7 @@ class SearchAdapter(private val searchItems: MutableList<SearchItem>) : Recycler
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CustomViewHolder1(private val v: View) : RecyclerView.ViewHolder(v) {
|
||||
|
||||
private fun bindWatch(item: SearchItem) {
|
||||
@ -64,11 +66,16 @@ class CustomViewHolder1(private val v: View) : RecyclerView.ViewHolder(v) {
|
||||
val channelImage = v.findViewById<ImageView>(R.id.search_channel_image)
|
||||
Picasso.get().load(item.uploaderAvatar).fit().centerCrop().into(channelImage)
|
||||
val title = v.findViewById<TextView>(R.id.search_description)
|
||||
title.text = if (item.title!!.length > 60) item.title?.substring(0, 60) + "..." else item.title
|
||||
title.text =
|
||||
if (item.title!!.length > 60) item.title?.substring(0, 60) + "..." else item.title
|
||||
val views = v.findViewById<TextView>(R.id.search_views)
|
||||
val viewsString = if (item.views?.toInt() != -1) item.views.formatShort() else ""
|
||||
val uploadDate = if (item.uploadedDate != null) item.uploadedDate else ""
|
||||
views.text = if (viewsString != "" && uploadDate != "") viewsString + " • " + uploadDate else viewsString + uploadDate
|
||||
views.text =
|
||||
if (viewsString != "" && uploadDate != "")
|
||||
"$viewsString • $uploadDate"
|
||||
else
|
||||
viewsString + uploadDate
|
||||
val channelName = v.findViewById<TextView>(R.id.search_channel_name)
|
||||
channelName.text = item.uploaderName
|
||||
v.setOnClickListener {
|
||||
@ -90,13 +97,17 @@ class CustomViewHolder1(private val v: View) : RecyclerView.ViewHolder(v) {
|
||||
activity.navController.navigate(R.id.channel, bundle)
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindChannel(item: SearchItem) {
|
||||
val channelImage = v.findViewById<ImageView>(R.id.search_channel_image)
|
||||
Picasso.get().load(item.thumbnail).fit().centerCrop().into(channelImage)
|
||||
val channelName = v.findViewById<TextView>(R.id.search_channel_name)
|
||||
channelName.text = item.name
|
||||
val channelViews = v.findViewById<TextView>(R.id.search_views)
|
||||
channelViews.text = v.context.getString(R.string.subscribers, item.subscribers.formatShort()) + " • " + v.context.getString(R.string.videoCount, item.videos.toString())
|
||||
channelViews.text = v.context.getString(
|
||||
R.string.subscribers,
|
||||
item.subscribers.formatShort()
|
||||
) + " • " + v.context.getString(R.string.videoCount, item.videos.toString())
|
||||
v.setOnClickListener {
|
||||
val activity = v.context as MainActivity
|
||||
val bundle = bundleOf("channel_id" to item.url)
|
||||
@ -104,6 +115,7 @@ class CustomViewHolder1(private val v: View) : RecyclerView.ViewHolder(v) {
|
||||
}
|
||||
// todo sub button
|
||||
}
|
||||
|
||||
private fun bindPlaylist(item: SearchItem) {
|
||||
val playlistImage = v.findViewById<ImageView>(R.id.search_thumbnail)
|
||||
Picasso.get().load(item.thumbnail).fit().centerCrop().into(playlistImage)
|
||||
@ -114,7 +126,9 @@ class CustomViewHolder1(private val v: View) : RecyclerView.ViewHolder(v) {
|
||||
val playlistChannelName = v.findViewById<TextView>(R.id.search_name)
|
||||
playlistChannelName.text = item.uploaderName
|
||||
val playlistVideosNumber = v.findViewById<TextView>(R.id.search_playlist_videos)
|
||||
if (item.videos?.toInt() != -1) playlistVideosNumber.text = v.context.getString(R.string.videoCount, item.videos.toString())
|
||||
if (item.videos?.toInt() != -1)
|
||||
playlistVideosNumber.text =
|
||||
v.context.getString(R.string.videoCount, item.videos.toString())
|
||||
v.setOnClickListener {
|
||||
// playlist clicked
|
||||
val activity = v.context as MainActivity
|
||||
|
@ -18,7 +18,8 @@ import com.github.libretube.formatShort
|
||||
import com.github.libretube.obj.StreamItem
|
||||
import com.squareup.picasso.Picasso
|
||||
|
||||
class SubscriptionAdapter(private val videoFeed: List<StreamItem>) : RecyclerView.Adapter<SubscriptionViewHolder>() {
|
||||
class SubscriptionAdapter(private val videoFeed: List<StreamItem>) :
|
||||
RecyclerView.Adapter<SubscriptionViewHolder>() {
|
||||
// private var limitedVideoFeed: MutableList<String> = [""].toMutableList()
|
||||
var i = 0
|
||||
override fun getItemCount(): Int {
|
||||
@ -42,9 +43,13 @@ class SubscriptionAdapter(private val videoFeed: List<StreamItem>) : RecyclerVie
|
||||
override fun onBindViewHolder(holder: SubscriptionViewHolder, position: Int) {
|
||||
val trending = videoFeed[position]
|
||||
holder.v.findViewById<TextView>(R.id.textView_title).text = trending.title
|
||||
holder.v.findViewById<TextView>(R.id.textView_channel).text = trending.uploaderName + " • " + trending.views.formatShort() + " • " + DateUtils.getRelativeTimeSpanString(trending.uploaded!!)
|
||||
holder.v.findViewById<TextView>(R.id.textView_channel).text =
|
||||
trending.uploaderName + " • " +
|
||||
trending.views.formatShort() + " • " +
|
||||
DateUtils.getRelativeTimeSpanString(trending.uploaded!!)
|
||||
val thumbnailImage = holder.v.findViewById<ImageView>(R.id.thumbnail)
|
||||
holder.v.findViewById<TextView>(R.id.thumbnail_duration).text = DateUtils.formatElapsedTime(trending.duration!!)
|
||||
holder.v.findViewById<TextView>(R.id.thumbnail_duration).text =
|
||||
DateUtils.formatElapsedTime(trending.duration!!)
|
||||
val channelImage = holder.v.findViewById<ImageView>(R.id.channel_image)
|
||||
channelImage.setOnClickListener {
|
||||
val activity = holder.v.context as MainActivity
|
||||
@ -76,6 +81,7 @@ class SubscriptionAdapter(private val videoFeed: List<StreamItem>) : RecyclerVie
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SubscriptionViewHolder(val v: View) : RecyclerView.ViewHolder(v) {
|
||||
init {
|
||||
}
|
||||
|
@ -12,12 +12,14 @@ import com.github.libretube.R
|
||||
import com.github.libretube.obj.Subscription
|
||||
import com.squareup.picasso.Picasso
|
||||
|
||||
class SubscriptionChannelAdapter(private val subscriptions: MutableList<Subscription>) : RecyclerView.Adapter<SubscriptionChannelViewHolder>() {
|
||||
class SubscriptionChannelAdapter(private val subscriptions: MutableList<Subscription>) :
|
||||
RecyclerView.Adapter<SubscriptionChannelViewHolder>() {
|
||||
override fun getItemCount(): Int {
|
||||
return subscriptions.size
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SubscriptionChannelViewHolder {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):
|
||||
SubscriptionChannelViewHolder {
|
||||
val layoutInflater = LayoutInflater.from(parent.context)
|
||||
val cell = layoutInflater.inflate(R.layout.channel_subscription_row, parent, false)
|
||||
return SubscriptionChannelViewHolder(cell)
|
||||
@ -35,6 +37,7 @@ class SubscriptionChannelAdapter(private val subscriptions: MutableList<Subscrip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SubscriptionChannelViewHolder(val v: View) : RecyclerView.ViewHolder(v) {
|
||||
init {
|
||||
}
|
||||
|
@ -18,7 +18,8 @@ import com.github.libretube.formatShort
|
||||
import com.github.libretube.obj.StreamItem
|
||||
import com.squareup.picasso.Picasso
|
||||
|
||||
class TrendingAdapter(private val videoFeed: List<StreamItem>) : RecyclerView.Adapter<CustomViewHolder>() {
|
||||
class TrendingAdapter(private val videoFeed: List<StreamItem>) :
|
||||
RecyclerView.Adapter<CustomViewHolder>() {
|
||||
override fun getItemCount(): Int {
|
||||
return videoFeed.size
|
||||
}
|
||||
@ -32,9 +33,13 @@ class TrendingAdapter(private val videoFeed: List<StreamItem>) : RecyclerView.Ad
|
||||
override fun onBindViewHolder(holder: CustomViewHolder, position: Int) {
|
||||
val trending = videoFeed[position]
|
||||
holder.v.findViewById<TextView>(R.id.textView_title).text = trending.title
|
||||
holder.v.findViewById<TextView>(R.id.textView_channel).text = trending.uploaderName + " • " + trending.views.formatShort() + " • " + DateUtils.getRelativeTimeSpanString(trending.uploaded!!)
|
||||
holder.v.findViewById<TextView>(R.id.textView_channel).text =
|
||||
trending.uploaderName + " • " +
|
||||
trending.views.formatShort() + " • " +
|
||||
DateUtils.getRelativeTimeSpanString(trending.uploaded!!)
|
||||
val thumbnailImage = holder.v.findViewById<ImageView>(R.id.thumbnail)
|
||||
holder.v.findViewById<TextView>(R.id.thumbnail_duration).text = DateUtils.formatElapsedTime(trending.duration!!)
|
||||
holder.v.findViewById<TextView>(R.id.thumbnail_duration).text =
|
||||
DateUtils.formatElapsedTime(trending.duration!!)
|
||||
val channelImage = holder.v.findViewById<ImageView>(R.id.channel_image)
|
||||
channelImage.setOnClickListener {
|
||||
val activity = holder.v.context as MainActivity
|
||||
@ -73,6 +78,7 @@ class TrendingAdapter(private val videoFeed: List<StreamItem>) : RecyclerView.Ad
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CustomViewHolder(val v: View) : RecyclerView.ViewHolder(v) {
|
||||
init {
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.github.libretube
|
||||
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user