Merge pull request #724 from Bnyro/master

Add playlist options to the playlist fragment
This commit is contained in:
Bnyro 2022-07-08 14:26:59 +02:00 committed by GitHub
commit d77a585725
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 95 additions and 29 deletions

View File

@ -15,7 +15,8 @@ import com.github.libretube.preferences.PreferenceHelper
import com.github.libretube.util.RetrofitInstance import com.github.libretube.util.RetrofitInstance
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException import java.io.IOException
@ -74,7 +75,7 @@ class PlaylistsAdapter(
private fun deletePlaylist(id: String, token: String, position: Int) { private fun deletePlaylist(id: String, token: String, position: Int) {
fun run() { fun run() {
GlobalScope.launch { CoroutineScope(Dispatchers.IO).launch {
val response = try { val response = try {
RetrofitInstance.authApi.deletePlaylist(token, PlaylistId(id)) RetrofitInstance.authApi.deletePlaylist(token, PlaylistId(id))
} catch (e: IOException) { } catch (e: IOException) {
@ -84,7 +85,6 @@ class PlaylistsAdapter(
} catch (e: HttpException) { } catch (e: HttpException) {
Log.e(TAG, "HttpException, unexpected response") Log.e(TAG, "HttpException, unexpected response")
return@launch return@launch
} finally {
} }
try { try {
if (response.message == "ok") { if (response.message == "ok") {

View File

@ -155,7 +155,7 @@ class SearchAdapter(
} }
root.setOnLongClickListener { root.setOnLongClickListener {
val playlistId = item.url!!.replace("/playlist?list=", "") val playlistId = item.url!!.replace("/playlist?list=", "")
PlaylistOptionsDialog(playlistId, root.context) PlaylistOptionsDialog(playlistId, false, root.context)
.show(childFragmentManager, "PlaylistOptionsDialog") .show(childFragmentManager, "PlaylistOptionsDialog")
true true
} }

View File

@ -84,6 +84,7 @@ class LoginDialog : DialogFragment() {
PreferenceHelper.setUsername(requireContext(), login.username!!) PreferenceHelper.setUsername(requireContext(), login.username!!)
requireMainActivityRestart = true requireMainActivityRestart = true
dialog?.dismiss() dialog?.dismiss()
activity?.recreate()
} }
} }
} }

View File

@ -29,6 +29,7 @@ class LogoutDialog : DialogFragment() {
Toast.makeText(context, R.string.loggedout, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.loggedout, Toast.LENGTH_SHORT).show()
PreferenceHelper.setToken(requireContext(), "") PreferenceHelper.setToken(requireContext(), "")
dialog?.dismiss() dialog?.dismiss()
activity?.recreate()
} }
binding.title.text = ThemeHelper.getStyledAppName(requireContext()) binding.title.text = ThemeHelper.getStyledAppName(requireContext())

View File

@ -20,16 +20,23 @@ import java.io.IOException
class PlaylistOptionsDialog( class PlaylistOptionsDialog(
private val playlistId: String, private val playlistId: String,
private val isOwner: Boolean,
context: Context context: Context
) : DialogFragment() { ) : DialogFragment() {
val TAG = "PlaylistOptionsDialog" val TAG = "PlaylistOptionsDialog"
private val optionsList = listOf( private var optionsList = listOf(
context.getString(R.string.clonePlaylist), context.getString(R.string.clonePlaylist),
context.getString(R.string.share) context.getString(R.string.share)
) )
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
if (isOwner) {
optionsList = optionsList +
context?.getString(R.string.deletePlaylist)!! -
context?.getString(R.string.clonePlaylist)!!
}
val dialog = MaterialAlertDialogBuilder(requireContext()) val dialog = MaterialAlertDialogBuilder(requireContext())
.setNegativeButton(R.string.cancel) { dialog, _ -> .setNegativeButton(R.string.cancel) { dialog, _ ->
dialog.dismiss() dialog.dismiss()
@ -41,12 +48,12 @@ class PlaylistOptionsDialog(
optionsList optionsList
) )
) { _, which -> ) { _, which ->
when (which) { when (optionsList[which]) {
// Clone the playlist to the users Piped account // Clone the playlist to the users Piped account
0 -> { context?.getString(R.string.clonePlaylist) -> {
val token = PreferenceHelper.getToken(requireContext()) val token = PreferenceHelper.getToken(requireContext())
if (token != "") { if (token != "") {
importPlaylist(token!!, playlistId) importPlaylist(token, playlistId)
} else { } else {
Toast.makeText( Toast.makeText(
context, context,
@ -56,11 +63,15 @@ class PlaylistOptionsDialog(
} }
} }
// share the playlist // share the playlist
1 -> { context?.getString(R.string.share) -> {
val shareDialog = ShareDialog(playlistId, true) val shareDialog = ShareDialog(playlistId, true)
// using parentFragmentManager is important here // using parentFragmentManager, childFragmentManager doesn't work here
shareDialog.show(parentFragmentManager, "ShareDialog") shareDialog.show(parentFragmentManager, "ShareDialog")
} }
context?.getString(R.string.deletePlaylist) -> {
val token = PreferenceHelper.getToken(requireContext())
deletePlaylist(playlistId, token)
}
} }
} }
return dialog.show() return dialog.show()
@ -82,4 +93,22 @@ class PlaylistOptionsDialog(
} }
run() run()
} }
private fun deletePlaylist(id: String, token: String) {
fun run() {
CoroutineScope(Dispatchers.IO).launch {
val response = try {
RetrofitInstance.authApi.deletePlaylist(token, PlaylistId(id))
} catch (e: IOException) {
println(e)
Log.e(TAG, "IOException, you might not have internet connection")
return@launch
} catch (e: HttpException) {
Log.e(TAG, "HttpException, unexpected response")
return@launch
}
}
}
run()
}
} }

View File

@ -43,14 +43,14 @@ class VideoOptionsDialog(private val videoId: String, context: Context) : Dialog
) { _, which -> ) { _, which ->
// For now, this checks the position of the option with the position that is in the // For now, this checks the position of the option with the position that is in the
// list. I don't like it, but we will do like this for now. // list. I don't like it, but we will do like this for now.
when (which) { when (optionsList[which]) {
// This for example will be the "Background mode" option // This for example will be the "Background mode" option
0 -> { context?.getString(R.string.playOnBackground) -> {
BackgroundMode.getInstance() BackgroundMode.getInstance()
.playOnBackgroundMode(requireContext(), videoId) .playOnBackgroundMode(requireContext(), videoId)
} }
// Add Video to Playlist Dialog // Add Video to Playlist Dialog
1 -> { context?.getString(R.string.addToPlaylist) -> {
val token = PreferenceHelper.getToken(requireContext()) val token = PreferenceHelper.getToken(requireContext())
if (token != "") { if (token != "") {
val newFragment = AddtoPlaylistDialog() val newFragment = AddtoPlaylistDialog()
@ -62,7 +62,7 @@ class VideoOptionsDialog(private val videoId: String, context: Context) : Dialog
Toast.makeText(context, R.string.login_first, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.login_first, Toast.LENGTH_SHORT).show()
} }
} }
2 -> { context?.getString(R.string.share) -> {
val shareDialog = ShareDialog(videoId, false) val shareDialog = ShareDialog(videoId, false)
// using parentFragmentManager is important here // using parentFragmentManager is important here
shareDialog.show(parentFragmentManager, "ShareDialog") shareDialog.show(parentFragmentManager, "ShareDialog")

View File

@ -11,6 +11,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import com.github.libretube.R import com.github.libretube.R
import com.github.libretube.adapters.PlaylistAdapter import com.github.libretube.adapters.PlaylistAdapter
import com.github.libretube.databinding.FragmentPlaylistBinding import com.github.libretube.databinding.FragmentPlaylistBinding
import com.github.libretube.dialogs.PlaylistOptionsDialog
import com.github.libretube.preferences.PreferenceHelper import com.github.libretube.preferences.PreferenceHelper
import com.github.libretube.util.RetrofitInstance import com.github.libretube.util.RetrofitInstance
import retrofit2.HttpException import retrofit2.HttpException
@ -72,11 +73,18 @@ class PlaylistFragment : Fragment() {
binding.playlistUploader.text = response.uploader binding.playlistUploader.text = response.uploader
binding.playlistTotVideos.text = binding.playlistTotVideos.text =
getString(R.string.videoCount, response.videos.toString()) getString(R.string.videoCount, response.videos.toString())
val user = PreferenceHelper.getUsername(requireContext()) val user = PreferenceHelper.getUsername(requireContext())
var isOwner = false // check whether the user owns the playlist
if (response.uploaderUrl == null && response.uploader.equals(user, true)) { val isOwner = response.uploaderUrl == null &&
isOwner = true response.uploader.equals(user, true)
// show playlist options
binding.optionsMenu.setOnClickListener {
val optionsDialog = PlaylistOptionsDialog(playlistId!!, isOwner, requireContext())
optionsDialog.show(childFragmentManager, "PlaylistOptionsDialog")
} }
playlistAdapter = PlaylistAdapter( playlistAdapter = PlaylistAdapter(
response.relatedStreams!!.toMutableList(), response.relatedStreams!!.toMutableList(),
playlistId!!, playlistId!!,

View File

@ -171,8 +171,9 @@ class InstanceSettings : PreferenceFragmentCompat() {
} }
val login = findPreference<Preference>("login_register") val login = findPreference<Preference>("login_register")
login?.setOnPreferenceClickListener {
val token = PreferenceHelper.getToken(requireContext()) val token = PreferenceHelper.getToken(requireContext())
if (token != "") login?.setTitle(R.string.logout)
login?.setOnPreferenceClickListener {
if (token == "") { if (token == "") {
val newFragment = LoginDialog() val newFragment = LoginDialog()
newFragment.show(childFragmentManager, "Login") newFragment.show(childFragmentManager, "Login")

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:fillColor="@android:color/black"
android:pathData="M9.5,13a1.5,1.5 0,1 1,-3 0,1.5 1.5,0 0,1 3,0zM9.5,8a1.5,1.5 0,1 1,-3 0,1.5 1.5,0 0,1 3,0zM9.5,3a1.5,1.5 0,1 1,-3 0,1.5 1.5,0 0,1 3,0z" />
</vector>

View File

@ -9,9 +9,7 @@
<RelativeLayout <RelativeLayout
android:id="@+id/loginOrRegister2" android:id="@+id/loginOrRegister2"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
android:layout_centerHorizontal="true"
android:layout_centerVertical="true">
<ImageView <ImageView
android:id="@+id/boogh" android:id="@+id/boogh"
@ -25,6 +23,7 @@
android:id="@+id/text_like" android:id="@+id/text_like"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_below="@id/boogh" android:layout_below="@id/boogh"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:gravity="center" android:gravity="center"
@ -45,7 +44,7 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout <LinearLayout
@ -61,13 +60,13 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginLeft="10dp" android:layout_marginStart="10dp"
android:src="@drawable/ic_time_outlined" /> android:src="@drawable/ic_time_outlined" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="15dp" android:layout_marginStart="15dp"
android:text="@string/watch_history" android:text="@string/watch_history"
android:textSize="18sp" android:textSize="18sp"
android:textStyle="bold" /> android:textStyle="bold" />

View File

@ -23,15 +23,31 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<TextView <LinearLayout
android:id="@+id/playlist_name"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="8dp" android:padding="8dp"
android:orientation="horizontal">
<TextView
android:id="@+id/playlist_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="" android:text=""
android:textSize="24sp" android:textSize="24sp"
android:textStyle="bold" /> android:textStyle="bold" />
<ImageView
android:id="@+id/optionsMenu"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginRight="10dp"
android:layout_gravity="center"
android:src="@drawable/ic_three_dots" />
</LinearLayout>
<TextView <TextView
android:id="@+id/playlist_uploader" android:id="@+id/playlist_uploader"
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -33,6 +33,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/boogh" android:layout_below="@id/boogh"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:layout_marginHorizontal="10dp"
android:gravity="center" android:gravity="center"
android:text="@string/please_login" android:text="@string/please_login"
android:textSize="20sp" android:textSize="20sp"