mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Introduce and use SnackbarHelper, and UX fixes
This commit is contained in:
parent
4bc62f133c
commit
e495b3a028
7 changed files with 133 additions and 80 deletions
|
@ -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) {
|
||||
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()
|
||||
}
|
||||
showSnackbar(
|
||||
this@MainActivity,
|
||||
R.string.jsdelivr_enabled,
|
||||
Snackbar.LENGTH_LONG,
|
||||
getString(R.string.revert)) {
|
||||
setKey(getString(R.string.jsdelivr_proxy_key), false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,25 +177,9 @@ 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 {
|
||||
mediaClickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, card.child))
|
||||
}
|
||||
}
|
||||
|
||||
setOnLongClickListener {
|
||||
multiDeleteStateCallback.invoke(card)
|
||||
true
|
||||
if (!isMultiDeleteState) {
|
||||
episodeHolder.setOnClickListener {
|
||||
mediaClickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, card.child))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -204,20 +203,9 @@ class DownloadAdapter(
|
|||
logError(e)
|
||||
}
|
||||
|
||||
episodeHolder.apply {
|
||||
if (isMultiDeleteState) {
|
||||
setOnClickListener {
|
||||
toggleIsChecked(deleteCheckbox, card)
|
||||
}
|
||||
} else {
|
||||
setOnClickListener {
|
||||
headerClickCallback.invoke(DownloadHeaderClickEvent(DOWNLOAD_ACTION_GO_TO_CHILD, card.data))
|
||||
}
|
||||
}
|
||||
|
||||
setOnLongClickListener {
|
||||
multiDeleteStateCallback.invoke(card)
|
||||
true
|
||||
if (!isMultiDeleteState) {
|
||||
episodeHolder.setOnClickListener {
|
||||
headerClickCallback.invoke(DownloadHeaderClickEvent(DOWNLOAD_ACTION_GO_TO_CHILD, card.data))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
setOnClickListener {
|
||||
toggleIsChecked(deleteCheckbox, card)
|
||||
when {
|
||||
isMultiDeleteState -> {
|
||||
setOnClickListener {
|
||||
toggleIsChecked(deleteCheckbox, card)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setOnClickListener {
|
||||
mediaClickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, data))
|
||||
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
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue