Introduce and use SnackbarHelper, and UX fixes

This commit is contained in:
Luna712 2024-07-08 20:27:18 -06:00 committed by GitHub
parent 4bc62f133c
commit e495b3a028
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 133 additions and 80 deletions

View file

@ -149,6 +149,7 @@ import com.lagradost.cloudstream3.utils.DataStoreHelper.migrateResumeWatching
import com.lagradost.cloudstream3.utils.Event
import com.lagradost.cloudstream3.utils.InAppUpdater.Companion.runAutoUpdate
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog
import com.lagradost.cloudstream3.utils.SnackbarHelper.showSnackbar
import com.lagradost.cloudstream3.utils.UIHelper.changeStatusBarState
import com.lagradost.cloudstream3.utils.UIHelper.checkWrite
import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute
@ -1240,17 +1241,13 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricCa
this.setKey(getString(R.string.jsdelivr_proxy_key), false)
} else {
this.setKey(getString(R.string.jsdelivr_proxy_key), true)
val parentView: View = findViewById(android.R.id.content)
Snackbar.make(parentView, R.string.jsdelivr_enabled, Snackbar.LENGTH_LONG)
.let { snackbar ->
snackbar.setAction(R.string.revert) {
showSnackbar(
this@MainActivity,
R.string.jsdelivr_enabled,
Snackbar.LENGTH_LONG,
getString(R.string.revert)) {
setKey(getString(R.string.jsdelivr_proxy_key), false)
}
snackbar.setBackgroundTint(colorFromAttribute(R.attr.primaryGrayBackground))
snackbar.setTextColor(colorFromAttribute(R.attr.textColor))
snackbar.setActionTextColor(colorFromAttribute(R.attr.colorPrimary))
snackbar.show()
}
}
}
}

View file

@ -94,6 +94,20 @@ class DownloadAdapter(
val data = card.data
binding.apply {
episodeHolder.apply {
if (isMultiDeleteState) {
setOnClickListener {
toggleIsChecked(deleteCheckbox, card)
}
}
setOnLongClickListener {
multiDeleteStateCallback.invoke(card)
toggleIsChecked(deleteCheckbox, card)
true
}
}
downloadHeaderPoster.apply {
setImage(data.poster)
if (isMultiDeleteState) {
@ -108,6 +122,7 @@ class DownloadAdapter(
setOnLongClickListener {
multiDeleteStateCallback.invoke(card)
toggleIsChecked(deleteCheckbox, card)
true
}
}
@ -162,27 +177,11 @@ class DownloadAdapter(
downloadButton.setDefaultClickListener(card.child, downloadHeaderInfo, mediaClickCallback)
downloadButton.isVisible = !isMultiDeleteState
downloadButton.setOnLongClickListener {
multiDeleteStateCallback.invoke(card)
true
}
episodeHolder.apply {
if (isMultiDeleteState) {
setOnClickListener {
toggleIsChecked(deleteCheckbox, card)
}
} else {
setOnClickListener {
if (!isMultiDeleteState) {
episodeHolder.setOnClickListener {
mediaClickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, card.child))
}
}
setOnLongClickListener {
multiDeleteStateCallback.invoke(card)
true
}
}
}
@SuppressLint("SetTextI18n")
@ -204,22 +203,11 @@ class DownloadAdapter(
logError(e)
}
episodeHolder.apply {
if (isMultiDeleteState) {
setOnClickListener {
toggleIsChecked(deleteCheckbox, card)
}
} else {
setOnClickListener {
if (!isMultiDeleteState) {
episodeHolder.setOnClickListener {
headerClickCallback.invoke(DownloadHeaderClickEvent(DOWNLOAD_ACTION_GO_TO_CHILD, card.data))
}
}
setOnLongClickListener {
multiDeleteStateCallback.invoke(card)
true
}
}
}
private fun bindChild(card: VisualDownloadCached.Child?) {
@ -260,11 +248,6 @@ class DownloadAdapter(
downloadButton.setDefaultClickListener(data, downloadChildEpisodeTextExtra, mediaClickCallback)
downloadButton.isVisible = !isMultiDeleteState
downloadButton.setOnLongClickListener {
multiDeleteStateCallback.invoke(card)
true
}
downloadChildEpisodeText.apply {
text = context.getNameFull(data.name, data.episode, data.season)
isSelected = true // Needed for text repeating
@ -275,18 +258,22 @@ class DownloadAdapter(
}
downloadChildEpisodeHolder.apply {
if (isMultiDeleteState) {
when {
isMultiDeleteState -> {
setOnClickListener {
toggleIsChecked(deleteCheckbox, card)
}
} else {
}
else -> {
setOnClickListener {
mediaClickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, data))
}
}
}
setOnLongClickListener {
multiDeleteStateCallback.invoke(card)
toggleIsChecked(deleteCheckbox, card)
true
}
}
@ -338,16 +325,6 @@ class DownloadAdapter(
} else notifyItemRangeChanged(0, itemCount)
}
fun updateSelectedItem(id: Int, isSelected: Boolean) {
if (isSelected) {
selectedIds[id] = true
} else selectedIds.remove(id)
val position = currentList.indexOfFirst { it.data.id == id }
if (position != -1) {
notifyItemChanged(position)
}
}
fun selectAllItems() {
currentList.forEachIndexed { index, item ->
val id = item.data.id

View file

@ -2,6 +2,7 @@ package com.lagradost.cloudstream3.ui.download
import android.content.DialogInterface
import androidx.appcompat.app.AlertDialog
import com.google.android.material.snackbar.Snackbar
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
import com.lagradost.cloudstream3.CommonActivity.activity
import com.lagradost.cloudstream3.R
@ -12,6 +13,7 @@ import com.lagradost.cloudstream3.ui.player.GeneratorPlayer
import com.lagradost.cloudstream3.utils.AppContextUtils.getNameFull
import com.lagradost.cloudstream3.utils.AppContextUtils.setDefaultFocus
import com.lagradost.cloudstream3.utils.DOWNLOAD_HEADER_CACHE
import com.lagradost.cloudstream3.utils.SnackbarHelper.showSnackbar
import com.lagradost.cloudstream3.utils.UIHelper.navigate
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
import com.lagradost.cloudstream3.utils.VideoDownloadManager
@ -78,6 +80,23 @@ object DownloadButtonSetup {
}
}
}
DOWNLOAD_ACTION_LONG_CLICK -> {
activity?.let { act ->
val length =
VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(
act,
click.data.id
)?.fileLength
?: 0
if (length > 0) {
showSnackbar(
act,
R.string.offline_file,
Snackbar.LENGTH_LONG
)
}
}
}
DOWNLOAD_ACTION_PLAY_FILE -> {
activity?.let { act ->
val info =

View file

@ -42,6 +42,7 @@ class DownloadChildFragment : Fragment() {
override fun onDestroyView() {
downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent -= it }
downloadDeleteEventListener = null
detachBackPressedCallback()
binding = null
super.onDestroyView()
}
@ -131,13 +132,7 @@ class DownloadChildFragment : Fragment() {
downloadsViewModel.addSelected(card)
} else downloadsViewModel.removeSelected(card)
},
{ card ->
downloadsViewModel.addSelected(card)
(binding?.downloadChildList?.adapter as? DownloadAdapter)?.updateSelectedItem(
card.data.id,
true
)
}
{ card -> downloadsViewModel.addSelected(card) }
)
binding?.downloadChildList?.apply {

View file

@ -68,6 +68,7 @@ class DownloadFragment : Fragment() {
override fun onDestroyView() {
downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent -= it }
downloadDeleteEventListener = null
detachBackPressedCallback()
binding = null
super.onDestroyView()
}
@ -130,13 +131,7 @@ class DownloadFragment : Fragment() {
downloadsViewModel.addSelected(card)
} else downloadsViewModel.removeSelected(card)
},
{ card ->
downloadsViewModel.addSelected(card)
(binding?.downloadList?.adapter as? DownloadAdapter)?.updateSelectedItem(
card.data.id,
true
)
}
{ card -> downloadsViewModel.addSelected(card) }
)
binding?.downloadList?.apply {

View file

@ -0,0 +1,69 @@
package com.lagradost.cloudstream3.utils
import android.app.Activity
import android.view.View
import androidx.annotation.MainThread
import androidx.annotation.StringRes
import com.google.android.material.snackbar.Snackbar
import com.lagradost.api.Log
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute
object SnackbarHelper {
private const val TAG = "COMPACT"
private var currentSnackbar: Snackbar? = null
@MainThread
fun showSnackbar(
act: Activity?,
@StringRes message: Int,
duration: Int = Snackbar.LENGTH_SHORT,
actionText: String? = null,
actionCallback: (() -> Unit)? = null
) {
if (act == null) return
showSnackbar(act, act.getString(message), duration, actionText, actionCallback)
}
@MainThread
fun showSnackbar(
act: Activity?,
message: String?,
duration: Int = Snackbar.LENGTH_SHORT,
actionText: String? = null,
actionCallback: (() -> Unit)? = null
) {
if (act == null || message == null) {
Log.w(TAG, "Invalid showSnackbar: act = $act, message = $message")
return
}
Log.i(TAG, "showSnackbar: $message")
try {
currentSnackbar?.dismiss()
} catch (e: Exception) {
logError(e)
}
try {
val parentView = act.findViewById<View>(android.R.id.content)
val snackbar = Snackbar.make(parentView, message, duration)
actionCallback?.let {
snackbar.setAction(actionText) { actionCallback.invoke() }
}
snackbar.show()
currentSnackbar = snackbar
snackbar.setBackgroundTint(act.colorFromAttribute(R.attr.primaryBlackBackground))
snackbar.setTextColor(act.colorFromAttribute(R.attr.textColor))
snackbar.setActionTextColor(act.colorFromAttribute(R.attr.colorPrimary))
} catch (e: Exception) {
logError(e)
}
}
}

View file

@ -150,6 +150,7 @@
<string name="download_done">Download Done</string>
<string name="download_format" translatable="false">%s - %s</string>
<string name="downloads_empty">There are currently no downloads.</string>
<string name="offline_file">Available for watching offline</string>
<string name="select_all">Select All</string>
<string name="update_started">Update Started</string>
<string name="stream">Network stream</string>