feat: add undo action after removing video from playlist

This commit is contained in:
Bnyro 2023-10-26 15:57:17 +02:00
parent ddd6177df5
commit 373b297f97
4 changed files with 62 additions and 14 deletions

View File

@ -4,6 +4,7 @@ import android.app.Activity
import android.content.Context
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.os.bundleOf
import androidx.core.view.isGone
@ -27,9 +28,12 @@ import com.github.libretube.ui.extensions.setWatchProgressLength
import com.github.libretube.ui.sheets.VideoOptionsBottomSheet
import com.github.libretube.ui.sheets.VideoOptionsBottomSheet.Companion.VIDEO_OPTIONS_SHEET_REQUEST_KEY
import com.github.libretube.ui.viewholders.PlaylistViewHolder
import com.github.libretube.util.TextUtils
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
/**
* @param originalFeed original, unsorted feed, needed in order to delete the proper video from
@ -112,29 +116,67 @@ class PlaylistAdapter(
}
}
fun removeFromPlaylist(context: Context, position: Int) {
fun removeFromPlaylist(rootView: View, sortedFeedPosition: Int) {
val video = sortedFeed[sortedFeedPosition]
// get the index of the video in the playlist
// could vary due to playlist sorting by the user
val playlistIndex = originalFeed.indexOfFirst {
it.url == sortedFeed[position].url
}.takeIf { it >= 0 } ?: return
val originalPlaylistPosition = originalFeed
.indexOfFirst { it.url == video.url }
.takeIf { it >= 0 } ?: return
originalFeed.removeAt(playlistIndex)
sortedFeed.removeAt(position)
visibleCount -= 1
(context as Activity).runOnUiThread {
notifyItemRemoved(position)
notifyItemRangeChanged(position, itemCount)
sortedFeed.removeAt(sortedFeedPosition)
originalFeed.removeAt(originalPlaylistPosition)
visibleCount--
(rootView.context as Activity).runOnUiThread {
notifyItemRemoved(sortedFeedPosition)
notifyItemRangeChanged(sortedFeedPosition, itemCount)
}
val appContext = context.applicationContext
val appContext = rootView.context.applicationContext
CoroutineScope(Dispatchers.IO).launch {
// try to remove the video from the playlist and show an undo snackbar if successful
CoroutineScope(Dispatchers.Main).launch {
try {
PlaylistsHelper.removeFromPlaylist(playlistId, playlistIndex)
withContext(Dispatchers.IO) {
PlaylistsHelper.removeFromPlaylist(playlistId, originalPlaylistPosition)
}
val shortTitle = TextUtils.limitTextToLength(video.title.orEmpty(), 50)
val snackBarText = rootView.context.getString(R.string.successfully_removed_from_playlist, shortTitle)
Snackbar.make(rootView, snackBarText, Snackbar.LENGTH_LONG)
.setTextMaxLines(3)
.setAction(R.string.undo) {
reAddToPlaylist(appContext, video, sortedFeedPosition, originalPlaylistPosition)
}
.show()
} catch (e: Exception) {
Log.e(TAG(), e.toString())
appContext.toastFromMainDispatcher(R.string.unknown_error)
}
}
}
private fun reAddToPlaylist(
context: Context,
streamItem: StreamItem,
sortedFeedPosition: Int,
originalPlaylistPosition: Int
) {
CoroutineScope(Dispatchers.IO).launch {
try {
PlaylistsHelper.addToPlaylist(playlistId, streamItem)
sortedFeed.add(sortedFeedPosition, streamItem)
originalFeed.add(originalPlaylistPosition, streamItem)
visibleCount++
withContext(Dispatchers.Main) {
notifyItemInserted(sortedFeedPosition)
}
} catch (e: Exception) {
Log.e(TAG(), e.toString())
context.toastFromMainDispatcher(R.string.unknown_error)
}
}
}
}

View File

@ -358,7 +358,7 @@ class PlaylistFragment : Fragment() {
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
playlistAdapter!!.removeFromPlaylist(
requireContext(),
_binding?.root ?: return,
viewHolder.absoluteAdapterPosition
)
}

View File

@ -102,4 +102,9 @@ object TextUtils {
bitrate ?: return ""
return "${bitrate / 1024}kbps"
}
fun limitTextToLength(text: String, maxLength: Int): String {
if (text.length <= maxLength) return text
return text.take(maxLength) + ""
}
}

View File

@ -491,6 +491,7 @@
<string name="sponsorblock_user_id">SponsorBlock UserID</string>
<string name="filename_too_long">Filename too long!</string>
<string name="remember_playback_speed">Remember playback speed</string>
<string name="successfully_removed_from_playlist">Successfully removed \"%1$s\" from the playlist.</string>
<!-- Notification channel strings -->
<string name="download_channel_name">Download Service</string>