This commit is contained in:
ocean 2024-07-01 14:59:45 +08:00
parent 0487ed7713
commit 10e5df4fb2
7 changed files with 193 additions and 542 deletions

View File

@ -6,8 +6,6 @@ import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.view.LayoutInflater
import android.view.View
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.widget.TextView
import android.widget.Toast
import androidx.annotation.OptIn
@ -29,6 +27,7 @@ import melody.offline.music.adapter.DetailsListAdapter
import melody.offline.music.ads.AdPlacement
import melody.offline.music.ads.LolAdWrapper
import melody.offline.music.bean.FavoriteBean
import melody.offline.music.bean.PlaylistItem
import melody.offline.music.databinding.ActivityDetailsBinding
import melody.offline.music.innertube.Innertube
import melody.offline.music.innertube.requests.moPlaylistPage
@ -36,34 +35,28 @@ import melody.offline.music.service.MyDownloadService
import melody.offline.music.service.ViewModelMain
import melody.offline.music.util.AnalysisUtil
import melody.offline.music.util.DownloadUtil
import melody.offline.music.util.LogTag
import melody.offline.music.util.LogTag.LogD
import melody.offline.music.util.asMediaItem
import melody.offline.music.util.asPlaylistItem
import melody.offline.music.view.ListMoreBottomSheetDialog
import org.json.JSONObject
@OptIn(UnstableApi::class)
class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreClickListener,
DetailsListAdapter.OnItemDownloadClickListener {
DetailsListAdapter.OnItemDownloadClickListener, ListMoreBottomSheetDialog.ListMoreViewListener,
ListMoreBottomSheetDialog.UpdateAdapterListener {
private val requests: Channel<Request> = Channel(Channel.UNLIMITED)
sealed class Request {
data object TryAgain : Request()
data class UpdateFavorite(val bean: Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean) :
Request()
data class OnFavorites(
val bean: Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean, val imgUrl: String
) : Request()
data class OnDownload(
val bean: Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean, val imgUrl: String
) : Request()
data class OnDownloadRemove(val id: String) : Request()
data class OnUpdateDownloadUi(val id: String) : Request()
data class OnAddPlaylist(
val bean: Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean,
val imgUrl: String
) :
Request()
data class UpdateFavorite(val bean: PlaylistItem) : Request()
data class OnFavorites(val bean: PlaylistItem) : Request()
data class OnDownload(val bean: PlaylistItem) : Request()
data class OnDownloadRemove(val bean: PlaylistItem) : Request()
data class OnUpdateDownloadUi(val bean: PlaylistItem) : Request()
data class OnAddPlaylist(val bean: PlaylistItem) : Request()
data class OnUpdateCurrentListItem(val bean: PlaylistItem):Request()
}
companion object {
@ -76,9 +69,9 @@ class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreCli
private var adapter: DetailsListAdapter? = null
private var myList: MutableList<Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean> =
mutableListOf()
private var myBean: Innertube.MoPlaylistOrAlbumPage? = null
private var currentPosition = -1
private var isAnimationRunning = false//动画是否正在进行
private var moreDialog: ListMoreBottomSheetDialog? = null
override suspend fun main() {
binding = ActivityDetailsBinding.inflate(layoutInflater)
setContentView(binding.root)
@ -90,7 +83,6 @@ class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreCli
}
initView()
LogD(TAG, "browseId->${browseId}")
initDownloadFlow()
initData(browseId!!)
onReceive()
}
@ -114,12 +106,13 @@ class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreCli
is Request.UpdateFavorite -> {
val currentFavoriteBean =
App.appFavoriteDBManager.getFavoriteBeanByID(it.bean.videoId!!)
App.appFavoriteDBManager.getFavoriteBeanByID(it.bean.videoId)
if (currentFavoriteBean != null) {
updateFavoriteUi(currentFavoriteBean.isFavorite)
} else {
updateFavoriteUi(false)
}
requests.trySend(Request.OnUpdateCurrentListItem(it.bean))
}
is Request.OnFavorites -> {
@ -133,14 +126,12 @@ class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreCli
)
)
val currentFavoriteBean =
App.appFavoriteDBManager.getFavoriteBeanByID(it.bean.videoId!!)
App.appFavoriteDBManager.getFavoriteBeanByID(it.bean.videoId)
if (currentFavoriteBean != null) {
currentFavoriteBean.isFavorite = !currentFavoriteBean.isFavorite
App.appFavoriteDBManager.updateFavoriteBean(currentFavoriteBean)
if (currentFavoriteBean.isFavorite) {
AnalysisUtil.logEvent(
AnalysisUtil.PLAYER_B_LOVE_CLICK, songMap
)
AnalysisUtil.logEvent(AnalysisUtil.PLAYER_B_LOVE_CLICK, songMap)
} else {
AnalysisUtil.logEvent(
AnalysisUtil.PLAYER_B_UN_LOVE_CLICK, songMap
@ -149,9 +140,9 @@ class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreCli
} else {
val b = FavoriteBean(
videoId = it.bean.videoId,
title = it.bean.title.toString(),
name = it.bean.name.toString(),
thumbnail = it.bean.thumbnailUrl ?: it.imgUrl,
title = it.bean.title,
name = it.bean.name,
thumbnail = it.bean.thumbnail,
isFavorite = true
)
App.appFavoriteDBManager.insertFavoriteBean(b)
@ -162,25 +153,26 @@ class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreCli
is Request.OnDownload -> {
val id = it.bean.videoId
val offBean = App.appOfflineDBManager.getOfflineBeanByID(id!!)
val offBean =
App.appOfflineDBManager.getOfflineBeanByID(id)//得到当前ID的本地数据
if (offBean != null && offBean.bytesDownloaded?.let { bytes -> bytes > 0 } == true) {//判断当前数据库是否有这条数据。
if (currentPosition >= 0) {
showRemoveDownloadDialogHint(id)
}
showRemoveDownloadDialogHint(it.bean)
} else {
val isFavorite =
App.appFavoriteDBManager.getFavoriteBeanByID(it.bean.videoId.toString()) != null
App.appFavoriteDBManager.getFavoriteBeanByID(it.bean.videoId)
//判断是否已经下载了这条数据,已经下载,就直接进行数据库数据存储,反之走下载流程。
if (DownloadUtil.downloadResourceExist(id)) {
val favoriteBean = FavoriteBean(
id,
it.bean.title.toString(),
it.bean.name.toString(),
it.bean.thumbnailUrl ?: it.imgUrl,
isFavorite
it.bean.title,
it.bean.name,
it.bean.thumbnail,
isFavorite?.isFavorite ?: false
)
insertOfflineData(favoriteBean)
requests.trySend(Request.OnUpdateDownloadUi(id))
it.bean.isOffline = true//更改状态
requests.trySend(Request.OnUpdateDownloadUi(it.bean))
requests.trySend(Request.OnUpdateCurrentListItem(it.bean))
} else {
val downloadRequest = DownloadRequest.Builder(id, id.toUri())
.setCustomCacheKey(id).build()
@ -205,10 +197,10 @@ class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreCli
)
val favoriteBean = FavoriteBean(
id,
it.bean.title.toString(),
it.bean.name.toString(),
it.bean.thumbnailUrl ?: it.imgUrl,
isFavorite
it.bean.title,
it.bean.name,
it.bean.thumbnail,
isFavorite?.isFavorite ?: false
)
insertOfflineData(favoriteBean)
val jsonObject = JSONObject()
@ -234,43 +226,38 @@ class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreCli
is Request.OnDownloadRemove -> {
val currentOfflineBean =
App.appOfflineDBManager.getOfflineBeanByID(it.id)
App.appOfflineDBManager.getOfflineBeanByID(it.bean.videoId)
if (currentOfflineBean != null) {
App.appOfflineDBManager.deleteOfflineBean(currentOfflineBean)
}
requests.trySend(Request.OnUpdateDownloadUi(it.id))
it.bean.isOffline = false
}
requests.trySend(Request.OnUpdateDownloadUi(it.bean))
requests.trySend(Request.OnUpdateCurrentListItem(it.bean))
}
is Request.OnUpdateDownloadUi -> {
val offBean = App.appOfflineDBManager.getOfflineBeanByID(it.id)
if (offBean != null && offBean.bytesDownloaded?.let { bytes -> bytes > 0 } == true) {
binding.downloadLoading.visibility = View.GONE
binding.downloadImg.visibility = View.VISIBLE
binding.downloadImg.setImageResource(R.drawable.more_downloaded_icon)
binding.downloadTv.text =
getString(R.string.download_remove_offline)
} else {
binding.downloadLoading.visibility = View.GONE
binding.downloadImg.visibility = View.VISIBLE
binding.downloadImg.setImageResource(R.drawable.more_download_icon)
binding.downloadTv.text = getString(R.string.download_save_offline)
}
moreDialog?.updateDownloadBtnUi(it.bean.isOffline)//更新对话框的ui
}
is Request.OnAddPlaylist -> {
val isFavorite =
App.appFavoriteDBManager.getFavoriteBeanByID(it.bean.videoId.toString()) != null
App.appFavoriteDBManager.getFavoriteBeanByID(it.bean.videoId) != null
showAddPlaylistBottomDialog(
FavoriteBean(
videoId = it.bean.videoId.toString(),
title = it.bean.title.toString(),
name = it.bean.name.toString(),
thumbnail = it.bean.thumbnailUrl ?: it.imgUrl,
videoId = it.bean.videoId,
title = it.bean.title,
name = it.bean.name,
thumbnail = it.bean.thumbnail,
isFavorite
)
)
}
is Request.OnUpdateCurrentListItem -> {
//更新数据集合当前的item数据
updateCurrentItem(it.bean.videoId)
}
}
}
events.onReceive {
@ -307,10 +294,36 @@ class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreCli
}
override fun onItemMoreClick(position: Int) {
currentPosition = position
if (!isAnimationRunning) {
toggleBottomLayout(position)
}
val bean = myList[position]
LogD(TAG,"MoListDetailsActivity onItemMoreClick -> ${bean.asPlaylistItem}")
moreDialog = ListMoreBottomSheetDialog(
this@MoListDetailsActivity,
bean.asPlaylistItem,
this@MoListDetailsActivity,
this@MoListDetailsActivity
)
moreDialog?.setListMoreViewListener(this@MoListDetailsActivity)
moreDialog?.show()
}
override fun onFavoritesClicked(playlistItem: PlaylistItem) {
requests.trySend(Request.OnFavorites(playlistItem))
}
override fun onDownloadClicked(playlistItem: PlaylistItem) {
requests.trySend(Request.OnDownload(playlistItem))
}
override fun onAddToPlaylistClicked(playlistItem: PlaylistItem) {
requests.trySend(Request.OnAddPlaylist(playlistItem))
}
@SuppressLint("NotifyDataSetChanged")
override fun onUpdateAdapterListener(download: Download, playlistItem: PlaylistItem) {
requests.trySend(Request.OnUpdateCurrentListItem(playlistItem))
}
private fun initView() {
@ -343,45 +356,6 @@ class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreCli
startActivity(intent)
}
}
binding.layoutInfo.setOnClickListener { }
binding.bottomCloseBtn.setOnClickListener {
hideBottomLayout()
}
binding.bottomBlankLayout.setOnClickListener {
hideBottomLayout()
}
binding.favoritesBtn.setOnClickListener {
if (currentPosition >= 0) {
requests.trySend(
Request.OnFavorites(
myList[currentPosition],
myBean?.thumbnail.toString()
)
)
}
}
binding.moreDownloadBtn.setOnClickListener {
if (currentPosition >= 0) {
requests.trySend(
Request.OnDownload(
myList[currentPosition],
myBean?.thumbnail.toString()
)
)
}
}
binding.moreAddPlaylistBtn.setOnClickListener {
if (currentPosition >= 0) {
requests.trySend(
Request.OnAddPlaylist(
myList[currentPosition],
myBean?.thumbnail.toString()
)
)
hideBottomLayout()
}
}
}
@SuppressLint("NotifyDataSetChanged")
@ -391,7 +365,6 @@ class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreCli
if (this.isDestroyed || this.isFinishing) {
return
}
myBean = it
LogD(TAG, "moPlaylistPage onSuccess->${it.moPlaylistOrAlbumListBean}")
if (it.moPlaylistOrAlbumListBean.isNotEmpty()) {
showDataUi()
@ -401,8 +374,20 @@ class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreCli
binding.subtitle.text = it.subtitle
binding.secondSubtitle.text = it.secondSubtitle
val mapList = it.moPlaylistOrAlbumListBean.map { item ->
val offlineBean = App.appOfflineDBManager.getOfflineBeanByID(item.videoId!!)
val favoriteBean = App.appFavoriteDBManager.getFavoriteBeanByID(item.videoId)
LogD(TAG,"offlineBean->$offlineBean")
item.copy(
isOffline = offlineBean?.isOffline ?: false,
isFavorite = favoriteBean?.isFavorite ?: false,
bytesDownloaded = offlineBean?.bytesDownloaded,
size = offlineBean?.size
)
}
myList.clear()
myList.addAll(it.moPlaylistOrAlbumListBean)
myList.addAll(mapList)
adapter?.notifyDataSetChanged()
} else {
showNoContentUi()
@ -413,6 +398,25 @@ class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreCli
}
}
private suspend fun updateCurrentItem(id: String) {
//更新当前界面的数据集合
myList.forEach { item ->
if (item.videoId == id) {
val favoriteBean = App.appFavoriteDBManager.getFavoriteBeanByID(item.videoId)
val offlineBean = App.appOfflineDBManager.getOfflineBeanByID(item.videoId)
item.isFavorite = favoriteBean?.isFavorite ?: false
item.isOffline = offlineBean?.isOffline ?: false
item.bytesDownloaded = offlineBean?.bytesDownloaded
item.size = offlineBean?.size
}
}
myList.forEach { item ->
if (item.videoId == id) {
LogD(TAG,"updateCurrentItem -> $item")
}
}
}
private fun showDataUi() {
binding.loadingLayout.visibility = View.GONE
binding.noContentLayout.visibility = View.GONE
@ -428,176 +432,13 @@ class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreCli
binding.noContentLayout.visibility = View.VISIBLE
}
private fun initDownloadFlow() {
ViewModelMain.modelDownloadsFlow.observe(this) { downloads ->
if (currentPosition >= 0) {
val id = myList[currentPosition].videoId
val currentScreenDownloads = downloads[id]
if (currentScreenDownloads != null) {
updateDownloadUI(currentScreenDownloads)
}
}
}
}
private fun updateDownloadUI(download: Download) {
LogD(TAG, "download.state->${download.state}")
when (download.state) {
Download.STATE_DOWNLOADING -> {
binding.downloadLoading.visibility = View.VISIBLE
binding.downloadImg.setImageResource(R.drawable.more_download_icon)
binding.downloadImg.visibility = View.GONE
binding.downloadTv.text = getString(R.string.download_saving)
binding.moreDownloadBtn.isClickable = false
binding.moreDownloadBtn.isEnabled = false
}
Download.STATE_COMPLETED -> {
binding.downloadLoading.visibility = View.GONE
binding.downloadImg.setImageResource(R.drawable.more_downloaded_icon)
binding.downloadImg.visibility = View.VISIBLE
binding.downloadTv.text = getString(R.string.download_remove_offline)
binding.moreDownloadBtn.isClickable = true
binding.moreDownloadBtn.isEnabled = true
val jsonObject = JSONObject()
jsonObject.put(
"download_id", download.request.id
)
val songMap = mutableMapOf(
Pair(
AnalysisUtil.PARAM_VALUE, jsonObject.toString()
)
)
AnalysisUtil.logEvent(AnalysisUtil.PLAYER_B_DOWNLOAD_SUCCESS_ACTION, songMap)
}
Download.STATE_FAILED -> {
binding.downloadLoading.visibility = View.GONE
binding.downloadImg.setImageResource(R.drawable.error)
binding.downloadImg.visibility = View.VISIBLE
binding.downloadTv.text = getString(R.string.download_save_offline)
binding.moreDownloadBtn.isClickable = true
binding.moreDownloadBtn.isEnabled = true
}
else -> {
binding.downloadLoading.visibility = View.GONE
binding.downloadImg.setImageResource(R.drawable.more_download_icon)
binding.downloadImg.visibility = View.VISIBLE
binding.downloadTv.text = getString(R.string.download_save_offline)
binding.moreDownloadBtn.isClickable = true
binding.moreDownloadBtn.isEnabled = true
}
}
}
private fun updateFavoriteUi(b: Boolean) {
if (b) {
binding.favoritesImg.setImageResource(R.drawable.favorited_icon)
} else {
binding.favoritesImg.setImageResource(R.drawable.not_favorited_icon)
if (moreDialog != null) {
moreDialog?.updateFavoriteUi(b)
}
}
private fun toggleBottomLayout(position: Int) {
if (binding.bottomLayout.visibility == View.VISIBLE) {
hideBottomLayout()
} else {
showBottomLayout(position)
}
}
private fun showBottomLayout(position: Int) {
val slideUpAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_up)
slideUpAnimation.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) {
isAnimationRunning = true
// 动画开始时禁用按钮
animationLoadingNotClick(false)
}
override fun onAnimationEnd(animation: Animation) {
isAnimationRunning = false
// 动画结束时启用按钮
animationLoadingNotClick(true)
}
override fun onAnimationRepeat(animation: Animation) {
// 可选:处理动画重复的情况
}
})
binding.bottomLayout.startAnimation(slideUpAnimation)
binding.bottomLayout.visibility = View.VISIBLE
val bean = myList[position]
val imgUrl = bean.thumbnailUrl ?: myBean?.thumbnail
Glide.with(this).load(imgUrl).into(binding.songImg)
binding.title.text = bean.title
if (bean.name?.isEmpty() == true) {
binding.name.visibility = View.GONE
} else {
binding.name.visibility = View.VISIBLE
binding.name.text = bean.name
}
requests.trySend(Request.UpdateFavorite(bean))
val currentDownload = DownloadUtil.getCurrentIdDownload(bean.videoId!!)
if (currentDownload != null) {
//是否下载过资源下载过资源就不走download的ui更新因为 它肯定状态为3
if(DownloadUtil.downloadResourceExist(bean.videoId)){
requests.trySend(Request.OnUpdateDownloadUi(bean.videoId))
}else{
updateDownloadUI(currentDownload)
}
} else {
requests.trySend(Request.OnUpdateDownloadUi(bean.videoId))
}
}
private fun hideBottomLayout() {
val slideDownAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_down)
slideDownAnimation.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation?) {
isAnimationRunning = true
animationLoadingNotClick(false)
}
override fun onAnimationEnd(animation: Animation?) {
isAnimationRunning = false
animationLoadingNotClick(true)
}
override fun onAnimationRepeat(animation: Animation?) {
}
})
binding.bottomLayout.startAnimation(slideDownAnimation)
binding.bottomLayout.visibility = View.GONE
//隐藏布局后则,解除点击限制
binding.moreDownloadBtn.isClickable = true
binding.moreDownloadBtn.isEnabled = true
}
private fun animationLoadingNotClick(b: Boolean) {
binding.layoutInfo.isClickable = b
binding.bottomCloseBtn.isClickable = b
binding.bottomBlankLayout.isClickable = b
binding.moreDownloadBtn.isClickable = b
binding.moreAddPlaylistBtn.isClickable = b
binding.favoritesBtn.isClickable = b
}
private fun showRemoveDownloadDialogHint(id: String) {
private fun showRemoveDownloadDialogHint(playlistItem: PlaylistItem) {
val inflater = LayoutInflater.from(this)
val dialogView = inflater.inflate(R.layout.dialog_hint, null)
val okBtn = dialogView.findViewById<TextView>(R.id.dialog_ok_btn)
@ -608,7 +449,7 @@ class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreCli
dialog.show()
okBtn.setOnClickListener {
dialog.dismiss()
requests.trySend(Request.OnDownloadRemove(id))
requests.trySend(Request.OnDownloadRemove(playlistItem))
}
cancelBtn.setOnClickListener {
dialog.dismiss()

View File

@ -1,5 +1,6 @@
package melody.offline.music.innertube
import androidx.room.ColumnInfo
import melody.offline.music.innertube.models.MusicCarouselShelfRenderer
import melody.offline.music.innertube.models.MusicShelfRenderer
import melody.offline.music.innertube.models.NavigationEndpoint
@ -238,7 +239,12 @@ object Innertube {
val params: String? = null,
val musicVideoType: String?,
val pageType: String?,
val thumbnailUrl: String?
val thumbnailUrl: String?,
var bytesDownloaded: Long? = null,
var size: String? = null,
var isOffline: Boolean? = null,
var isFavorite: Boolean? = null,
var backupThumbnailUrl: String? = null,
)
}

View File

@ -121,7 +121,14 @@ suspend fun Innertube.moPlaylistPage(browseId: String): Result<Innertube.MoPlayl
params = watchEndpoint?.params,
musicVideoType = watchEndpoint?.type,
pageType = browseEndpoint?.type,
thumbnailUrl = thumbnailUrl
thumbnailUrl = thumbnailUrl,
backupThumbnailUrl = musicResponsiveHeaderRenderer
?.thumbnail
?.musicThumbnailRenderer
?.thumbnail
?.thumbnails
?.let { it.getOrNull(3) ?: it.getOrNull(2) ?: it.getOrNull(1) ?: it.getOrNull(0) }
?.url
)
list.add(bean)

View File

@ -18,63 +18,32 @@ import melody.offline.music.innertube.requests.playlistPage
import melody.offline.music.innertube.utils.plus
val OfflineBean.asMediaItem: MediaItem
@OptIn(UnstableApi::class)
get() = MediaItem.Builder()
.setMediaId(videoId)
.setUri(videoId)
.setCustomCacheKey(videoId)
.setMediaMetadata(
MediaMetadata.Builder()
.setTitle(title)
.setArtist(name)
.setArtworkUri(thumbnail?.toUri())
.build()
)
.build()
@OptIn(UnstableApi::class) get() = MediaItem.Builder().setMediaId(videoId).setUri(videoId)
.setCustomCacheKey(videoId).setMediaMetadata(
MediaMetadata.Builder().setTitle(title).setArtist(name)
.setArtworkUri(thumbnail?.toUri()).build()
).build()
val FavoriteBean.asMediaItem: MediaItem
@OptIn(UnstableApi::class)
get() = MediaItem.Builder()
.setMediaId(videoId)
.setUri(videoId)
.setCustomCacheKey(videoId)
.setMediaMetadata(
MediaMetadata.Builder()
.setTitle(title)
.setArtist(name)
.setArtworkUri(thumbnail?.toUri())
.build()
)
.build()
@OptIn(UnstableApi::class) get() = MediaItem.Builder().setMediaId(videoId).setUri(videoId)
.setCustomCacheKey(videoId).setMediaMetadata(
MediaMetadata.Builder().setTitle(title).setArtist(name)
.setArtworkUri(thumbnail?.toUri()).build()
).build()
val PlaylistItem.asMediaItem: MediaItem
@OptIn(UnstableApi::class)
get() = MediaItem.Builder()
.setMediaId(videoId)
.setUri(videoId)
.setCustomCacheKey(videoId)
.setMediaMetadata(
MediaMetadata.Builder()
.setTitle(title)
.setArtist(name)
.setArtworkUri(thumbnail?.toUri())
.build()
)
.build()
@OptIn(UnstableApi::class) get() = MediaItem.Builder().setMediaId(videoId).setUri(videoId)
.setCustomCacheKey(videoId).setMediaMetadata(
MediaMetadata.Builder().setTitle(title).setArtist(name)
.setArtworkUri(thumbnail?.toUri()).build()
).build()
val Innertube.SongItem.asMediaItem: MediaItem
@OptIn(UnstableApi::class)
get() = MediaItem.Builder()
.setMediaId(key)
.setUri(key)
.setCustomCacheKey(key)
.setMediaMetadata(
MediaMetadata.Builder()
.setTitle(info?.name)
.setArtist(authors?.joinToString("") { it.name ?: "" })
.setAlbumTitle(album?.name)
.setArtworkUri(bigThumbnail?.url?.toUri())
.setExtras(
@OptIn(UnstableApi::class) get() = MediaItem.Builder().setMediaId(key).setUri(key)
.setCustomCacheKey(key).setMediaMetadata(
MediaMetadata.Builder().setTitle(info?.name)
.setArtist(authors?.joinToString("") { it.name ?: "" }).setAlbumTitle(album?.name)
.setArtworkUri(bigThumbnail?.url?.toUri()).setExtras(
bundleOf(
"albumId" to album?.endpoint?.browseId,
"durationText" to durationText,
@ -82,10 +51,20 @@ val Innertube.SongItem.asMediaItem: MediaItem
?.mapNotNull { it.name },
"artistIds" to authors?.mapNotNull { it.endpoint?.browseId },
)
)
.build()
)
.build()
).build()
).build()
val Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean.asPlaylistItem: PlaylistItem
get() = PlaylistItem(
videoId = videoId ?: "",
title = title ?: "",
name = name ?: "",
thumbnail = thumbnailUrl ?: backupThumbnailUrl,
bytesDownloaded = bytesDownloaded,
size = size,
isOffline = isOffline ?: false,
isFavorite = isFavorite ?: false
)
fun String?.thumbnail(size: Int): String? {
return when {

View File

@ -11,18 +11,16 @@ import android.widget.TextView
import androidx.annotation.OptIn
import androidx.core.content.ContextCompat
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.Observer
import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.offline.Download
import com.bumptech.glide.Glide
import com.google.android.material.bottomsheet.BottomSheetDialog
import melody.offline.music.App
import melody.offline.music.R
import melody.offline.music.activity.MoPlaylistSongsActivity
import melody.offline.music.bean.PlaylistItem
import melody.offline.music.service.ViewModelMain
import melody.offline.music.util.AnalysisUtil
import melody.offline.music.util.DownloadUtil
import melody.offline.music.util.FileSizeConverter
import melody.offline.music.util.LogTag
import org.json.JSONObject
@ -46,17 +44,18 @@ class ListMoreBottomSheetDialog(
private var bottomDialogDownloadTv: TextView? = null
private var bottomDialogMoreAddPlaylistBtn: LinearLayout? = null
private var bottomDialogAddPlaylistTv: TextView? = null
private lateinit var observer: Observer<Map<String, Download>>
@SuppressLint("MissingInflatedId")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.list_more_layout)
initDownloadFlow()
window?.setBackgroundDrawableResource(android.R.color.transparent)
window?.navigationBarColor = ContextCompat.getColor(context, R.color.main_bg_color)
initView()
initInfoUi()
initClick()
initDownloadFlow()
}
private fun initView() {
@ -85,20 +84,26 @@ class ListMoreBottomSheetDialog(
bottomDialogName?.visibility = View.VISIBLE
bottomDialogName?.text = bean.name
}
LogTag.LogD(LogTag.VO_TEST_ONLY, "$playlistItem")
updateFavoriteUi(playlistItem.isFavorite)
LogTag.LogD(LogTag.VO_TEST_ONLY, "more dialog ->$bean")
updateFavoriteUi(bean.isFavorite)
//获取当前ID的下载记录
val currentDownload = DownloadUtil.getCurrentIdDownload(bean.videoId)
if (currentDownload != null) {
LogTag.LogD(LogTag.VO_TEST_ONLY, "000->${currentDownload.state}")
//是否下载过资源下载过资源就不走download的ui更新因为 它肯定状态为3
if (DownloadUtil.downloadResourceExist(bean.videoId)) {
updateDownloadBtnUi(playlistItem.isOffline)
updateDownloadBtnUi(bean.isOffline)
LogTag.LogD(LogTag.VO_TEST_ONLY, "11更新 ui")
} else {
updateDownloadUI(currentDownload)
LogTag.LogD(LogTag.VO_TEST_ONLY, "22更新 ui")
}
} else {
updateDownloadBtnUi(playlistItem.isOffline)
updateDownloadBtnUi(bean.isOffline)
LogTag.LogD(LogTag.VO_TEST_ONLY, "33 更新btn ui")
}
}
@ -132,6 +137,7 @@ class ListMoreBottomSheetDialog(
}
fun updateDownloadBtnUi(b: Boolean) {
LogTag.LogD(LogTag.VO_TEST_ONLY,"more dialog updateDownloadBtnUi ->$b")
if (b) {
bottomDialogDownloadLoading?.visibility = View.GONE
bottomDialogDownloadImg?.visibility = View.VISIBLE
@ -146,16 +152,24 @@ class ListMoreBottomSheetDialog(
}
private fun initDownloadFlow() {
ViewModelMain.modelDownloadsFlow.observe(lifecycleOwner) { downloads ->
observer = Observer { downloads ->
val id = playlistItem.videoId
val currentScreenDownloads = downloads[id]
if (currentScreenDownloads != null) {
LogTag.LogD(LogTag.VO_TEST_ONLY, "more dialog initDownloadFlow")
updateDownloadUI(currentScreenDownloads)
}
}
ViewModelMain.modelDownloadsFlow.observe(lifecycleOwner, observer)
}
override fun dismiss() {
super.dismiss()
ViewModelMain.modelDownloadsFlow.removeObserver(observer)
}
private fun updateDownloadUI(download: Download) {
LogTag.LogD(LogTag.VO_TEST_ONLY, "more dialog download->${download.state}")
when (download.state) {
Download.STATE_DOWNLOADING -> {
bottomDialogDownloadLoading?.visibility = View.VISIBLE

View File

@ -223,200 +223,4 @@
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/bottom_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:orientation="vertical"
android:visibility="gone">
<View
android:id="@+id/bottom_blank_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="68dp"
android:layout_weight="3" />
<LinearLayout
android:id="@+id/layout_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/drw_bottom_layout_bg"
android:orientation="vertical"
android:paddingBottom="32dp"
android:visibility="visible">
<LinearLayout
android:id="@+id/bottomCloseBtn"
android:layout_width="match_parent"
android:layout_height="32dp"
android:gravity="center">
<TextView
android:layout_width="30dp"
android:layout_height="4dp"
android:background="@drawable/drw_bottom_close_btn_bg"
android:gravity="center" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="18dp"
android:paddingEnd="18dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<androidx.cardview.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="0dp"
app:cardBackgroundColor="@color/transparent"
app:cardCornerRadius="10dp"
app:cardElevation="0dp">
<ImageView
android:id="@+id/songImg"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@mipmap/app_logo" />
</androidx.cardview.widget.CardView>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="vertical">
<melody.offline.music.view.MarqueeTextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/regular_font"
android:maxLines="1"
android:text="@string/app_name"
android:textColor="@color/white"
android:textSize="14dp" />
<melody.offline.music.view.MarqueeTextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/regular_font"
android:maxLines="1"
android:text="@string/app_name"
android:textColor="@color/white_60"
android:textSize="12dp" />
</LinearLayout>
<LinearLayout
android:id="@+id/favoritesBtn"
android:layout_width="32dp"
android:layout_height="32dp"
android:background="@drawable/drw_round_48_bg"
android:gravity="center">
<ImageView
android:id="@+id/favoritesImg"
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/not_favorited_icon" />
</LinearLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="16dp"
android:background="@color/liner_color" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/moreDownloadBtn"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginTop="4dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/downloadImg"
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/more_download_icon" />
<ProgressBar
android:id="@+id/downloadLoading"
android:layout_width="24dp"
android:layout_height="24dp"
android:indeterminateTint="@color/green"
android:progressBackgroundTint="@color/green"
android:progressTint="@color/green"
android:visibility="gone" />
</RelativeLayout>
<TextView
android:id="@+id/downloadTv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="@string/download_save_offline"
android:textColor="@color/white"
android:textSize="14dp" />
</LinearLayout>
<LinearLayout
android:id="@+id/moreAddPlaylistBtn"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginTop="4dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/more_add_playlist_icon" />
<TextView
android:id="@+id/addPlaylistTv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="@string/add_to_playlist"
android:textColor="@color/white"
android:textSize="14dp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</RelativeLayout>

View File

@ -136,7 +136,7 @@
android:id="@+id/bottomDialogDownloadImg"
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/more_downloaded_icon" />
android:src="@drawable/more_download_icon" />
<ProgressBar
android:id="@+id/bottomDialogDownloadLoading"
@ -155,7 +155,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="@string/download_remove_offline"
android:text="@string/download_save_offline"
android:textColor="@color/white"
android:textSize="14dp" />