This commit is contained in:
ocean 2024-06-27 16:33:31 +08:00
parent 55df7e9988
commit 6aea370d98
13 changed files with 367 additions and 34 deletions

View File

@ -81,6 +81,7 @@ dependencies {
implementation("androidx.media3:media3-ui:1.3.1") implementation("androidx.media3:media3-ui:1.3.1")
implementation("androidx.media3:media3-common:1.3.1") implementation("androidx.media3:media3-common:1.3.1")
implementation("androidx.media3:media3-datasource-cronet:1.3.1") implementation("androidx.media3:media3-datasource-cronet:1.3.1")
implementation("androidx.media3:media3-datasource-okhttp:1.3.1")
implementation("io.coil-kt:coil-compose:2.6.0") implementation("io.coil-kt:coil-compose:2.6.0")
implementation("io.ktor:ktor-client-core:2.3.8") implementation("io.ktor:ktor-client-core:2.3.8")

View File

@ -117,7 +117,7 @@ class MoLikedSongsActivity : MoBaseActivity(), LikedSongsAdapter.OnItemFavorites
val id = it.favoriteBean.videoId val id = it.favoriteBean.videoId
LogTag.LogD(TAG, "OnDownload id->${id}") LogTag.LogD(TAG, "OnDownload id->${id}")
val currentOfflineBean = App.appOfflineDBManager.getOfflineBeanByID(id) val currentOfflineBean = App.appOfflineDBManager.getOfflineBeanByID(id)
if (currentOfflineBean != null) {//判断当前数据库是否有这条数据。 if (currentOfflineBean != null && currentOfflineBean.bytesDownloaded?.let { bytes -> bytes > 0 } == true) {//判断当前数据库是否有这条数据。
if (currentPosition >= 0) { if (currentPosition >= 0) {
val videoId = favoriteBeans[currentPosition].videoId val videoId = favoriteBeans[currentPosition].videoId
showRemoveDownloadDialogHint(videoId) showRemoveDownloadDialogHint(videoId)
@ -185,11 +185,16 @@ class MoLikedSongsActivity : MoBaseActivity(), LikedSongsAdapter.OnItemFavorites
} }
is Request.OnUpdateDownloadUi -> { is Request.OnUpdateDownloadUi -> {
if (App.appOfflineDBManager.getOfflineBeanByID(it.id) != null) { 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.downloadImg.setImageResource(R.drawable.more_downloaded_icon)
binding.downloadTv.text = binding.downloadTv.text =
getString(R.string.download_remove_offline) getString(R.string.download_remove_offline)
} else { } else {
binding.downloadLoading.visibility = View.GONE
binding.downloadImg.visibility = View.VISIBLE
binding.downloadImg.setImageResource(R.drawable.more_download_icon) binding.downloadImg.setImageResource(R.drawable.more_download_icon)
binding.downloadTv.text = getString(R.string.download_save_offline) binding.downloadTv.text = getString(R.string.download_save_offline)
} }
@ -406,8 +411,6 @@ class MoLikedSongsActivity : MoBaseActivity(), LikedSongsAdapter.OnItemFavorites
} }
requests.trySend(Request.UpdateFavorite(bean)) requests.trySend(Request.UpdateFavorite(bean))
requests.trySend(Request.OnUpdateDownloadUi(bean.videoId))
val currentDownload = DownloadUtil.getCurrentIdDownload(bean.videoId) val currentDownload = DownloadUtil.getCurrentIdDownload(bean.videoId)
if (currentDownload != null) { if (currentDownload != null) {
updateDownloadUI(currentDownload) updateDownloadUI(currentDownload)

View File

@ -28,7 +28,6 @@ import melody.offline.music.adapter.DetailsListAdapter
import melody.offline.music.ads.AdPlacement import melody.offline.music.ads.AdPlacement
import melody.offline.music.ads.LolAdWrapper import melody.offline.music.ads.LolAdWrapper
import melody.offline.music.bean.FavoriteBean import melody.offline.music.bean.FavoriteBean
import melody.offline.music.bean.OfflineBean
import melody.offline.music.databinding.ActivityDetailsBinding import melody.offline.music.databinding.ActivityDetailsBinding
import melody.offline.music.innertube.Innertube import melody.offline.music.innertube.Innertube
import melody.offline.music.innertube.requests.moPlaylistPage import melody.offline.music.innertube.requests.moPlaylistPage
@ -36,7 +35,6 @@ import melody.offline.music.service.MyDownloadService
import melody.offline.music.service.ViewModelMain import melody.offline.music.service.ViewModelMain
import melody.offline.music.util.AnalysisUtil import melody.offline.music.util.AnalysisUtil
import melody.offline.music.util.DownloadUtil import melody.offline.music.util.DownloadUtil
import melody.offline.music.util.LogTag
import melody.offline.music.util.LogTag.LogD import melody.offline.music.util.LogTag.LogD
import org.json.JSONObject import org.json.JSONObject
@ -162,9 +160,8 @@ class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreCli
is Request.OnDownload -> { is Request.OnDownload -> {
val id = it.bean.videoId val id = it.bean.videoId
val currentOfflineBean = val offBean = App.appOfflineDBManager.getOfflineBeanByID(id!!)
App.appOfflineDBManager.getOfflineBeanByID(id!!) if (offBean != null && offBean.bytesDownloaded?.let { bytes -> bytes > 0 } == true) {//判断当前数据库是否有这条数据。
if (currentOfflineBean != null) {//判断当前数据库是否有这条数据。
if (currentPosition >= 0) { if (currentPosition >= 0) {
showRemoveDownloadDialogHint(id) showRemoveDownloadDialogHint(id)
} }
@ -244,11 +241,16 @@ class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreCli
} }
is Request.OnUpdateDownloadUi -> { is Request.OnUpdateDownloadUi -> {
if (App.appOfflineDBManager.getOfflineBeanByID(it.id) != null) { 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.downloadImg.setImageResource(R.drawable.more_downloaded_icon)
binding.downloadTv.text = binding.downloadTv.text =
getString(R.string.download_remove_offline) getString(R.string.download_remove_offline)
} else { } else {
binding.downloadLoading.visibility = View.GONE
binding.downloadImg.visibility = View.VISIBLE
binding.downloadImg.setImageResource(R.drawable.more_download_icon) binding.downloadImg.setImageResource(R.drawable.more_download_icon)
binding.downloadTv.text = getString(R.string.download_save_offline) binding.downloadTv.text = getString(R.string.download_save_offline)
} }
@ -436,6 +438,7 @@ class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreCli
} }
private fun updateDownloadUI(download: Download) { private fun updateDownloadUI(download: Download) {
LogD(TAG, "download.state->${download.state}")
when (download.state) { when (download.state) {
Download.STATE_DOWNLOADING -> { Download.STATE_DOWNLOADING -> {
binding.downloadLoading.visibility = View.VISIBLE binding.downloadLoading.visibility = View.VISIBLE
@ -527,11 +530,11 @@ class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreCli
} }
requests.trySend(Request.UpdateFavorite(bean)) requests.trySend(Request.UpdateFavorite(bean))
requests.trySend(Request.OnUpdateDownloadUi(bean.videoId!!)) val currentDownload = DownloadUtil.getCurrentIdDownload(bean.videoId!!)
val currentDownload = DownloadUtil.getCurrentIdDownload(bean.videoId)
if (currentDownload != null) { if (currentDownload != null) {
updateDownloadUI(currentDownload) updateDownloadUI(currentDownload)
} else {
requests.trySend(Request.OnUpdateDownloadUi(bean.videoId))
} }
} }

View File

@ -68,6 +68,7 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
const val PLAY_DETAILS_NAME = "play_details_name" const val PLAY_DETAILS_NAME = "play_details_name"
const val PLAY_DETAILS_DESC = "play_details_desc" const val PLAY_DETAILS_DESC = "play_details_desc"
const val PLAY_DETAILS_COME_FROM = "PLAY_DETAILS_COME_FROM" const val PLAY_DETAILS_COME_FROM = "PLAY_DETAILS_COME_FROM"
const val PLAY_LIST_ID = "play_list_id"
} }
private lateinit var binding: ActivityMoPlayDetailsBinding private lateinit var binding: ActivityMoPlayDetailsBinding
@ -164,6 +165,34 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
} else { } else {
binding.playbackErrorLayout.visibility = View.VISIBLE binding.playbackErrorLayout.visibility = View.VISIBLE
} }
} else if (comeFrom != null && comeFrom == MoPlaylistSongsActivity::class.java) {
LogD(TAG, "从 playlist songs 进入")
binding.nameTv.text = intent.getStringExtra(PLAY_DETAILS_NAME)
binding.descTv.text = intent.getStringExtra(PLAY_DETAILS_DESC)
val playlistID = intent.getIntExtra(PLAY_LIST_ID, -1)
val playlistItems = App.appPlaylistDBManager.getPlaylistItems(playlistID)
//找到当前点击进来的歌曲media
val findCurrentMedia = playlistItems.find { it.videoId == videoId }?.asMediaItem
if (findCurrentMedia != null) {
binding.likeAndDownloadLayout.visibility = View.VISIBLE
updateInfoUi(findCurrentMedia)
binding.playbackErrorLayout.visibility = View.GONE
binding.totalDurationTv.visibility = View.GONE
meController?.let {
it.setMediaItem(findCurrentMedia, true)
it.prepare()
it.play()
val mediaItems =
playlistItems.map { mapAll -> mapAll.asMediaItem }//转换成MediaItem
.filter { filter -> filter.mediaId != videoId }//过滤掉id相等的。
it.addMediaItems(mediaItems)
}
updatePlayListDataAndAdapter()
} else {
binding.playbackErrorLayout.visibility = View.VISIBLE
}
} else { } else {
LogD(TAG, "从点击任意歌曲进入") LogD(TAG, "从点击任意歌曲进入")
binding.nameTv.text = intent.getStringExtra(PLAY_DETAILS_NAME) binding.nameTv.text = intent.getStringExtra(PLAY_DETAILS_NAME)

View File

@ -7,9 +7,14 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.animation.AnimationUtils import android.view.animation.AnimationUtils
import android.widget.TextView import android.widget.TextView
import android.widget.Toast
import androidx.annotation.OptIn import androidx.annotation.OptIn
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.core.net.toUri
import androidx.media3.common.util.UnstableApi import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.offline.Download
import androidx.media3.exoplayer.offline.DownloadRequest
import androidx.media3.exoplayer.offline.DownloadService
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.gyf.immersionbar.ktx.immersionBar import com.gyf.immersionbar.ktx.immersionBar
@ -21,8 +26,15 @@ import melody.offline.music.R
import melody.offline.music.adapter.PlaylistSongsAdapter import melody.offline.music.adapter.PlaylistSongsAdapter
import melody.offline.music.ads.AdPlacement import melody.offline.music.ads.AdPlacement
import melody.offline.music.ads.LolAdWrapper import melody.offline.music.ads.LolAdWrapper
import melody.offline.music.bean.FavoriteBean
import melody.offline.music.bean.PlaylistItem import melody.offline.music.bean.PlaylistItem
import melody.offline.music.databinding.ActivityPlaylistSongsBinding import melody.offline.music.databinding.ActivityPlaylistSongsBinding
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 org.json.JSONObject
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)
class MoPlaylistSongsActivity : MoBaseActivity() { class MoPlaylistSongsActivity : MoBaseActivity() {
@ -35,6 +47,22 @@ class MoPlaylistSongsActivity : MoBaseActivity() {
sealed class Request { sealed class Request {
data object TryAgain : Request() data object TryAgain : 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 id: String) : Request()
data class OnUpdateDownloadUi(val id: String) : Request()
data class OnRemovePlaylist(
val bean: PlaylistItem
) : Request()
} }
private lateinit var binding: ActivityPlaylistSongsBinding private lateinit var binding: ActivityPlaylistSongsBinding
@ -54,6 +82,7 @@ class MoPlaylistSongsActivity : MoBaseActivity() {
initView() initView()
initAdapter() initAdapter()
LolAdWrapper.shared.loadAdIfNotCached(this, AdPlacement.INST_ME_PAGE_LIST) LolAdWrapper.shared.loadAdIfNotCached(this, AdPlacement.INST_ME_PAGE_LIST)
initDownloadFlow()
initData() initData()
onReceive() onReceive()
} }
@ -74,6 +103,158 @@ class MoPlaylistSongsActivity : MoBaseActivity() {
Request.TryAgain -> { Request.TryAgain -> {
initData() initData()
} }
is Request.UpdateFavorite -> {
val currentFavoriteBean =
App.appFavoriteDBManager.getFavoriteBeanByID(it.bean.videoId)
if (currentFavoriteBean != null) {
updateFavoriteUi(currentFavoriteBean.isFavorite)
} else {
updateFavoriteUi(false)
}
}
is Request.OnFavorites -> {
val jsonObject = JSONObject()
jsonObject.put(
"song_title", it.bean.title
)
val songMap = mutableMapOf(
Pair(
AnalysisUtil.PARAM_VALUE, jsonObject.toString()
)
)
val currentFavoriteBean =
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
)
} else {
AnalysisUtil.logEvent(
AnalysisUtil.PLAYER_B_UN_LOVE_CLICK, songMap
)
}
} else {
val b = FavoriteBean(
videoId = it.bean.videoId,
title = it.bean.title,
name = it.bean.name,
thumbnail = it.bean.thumbnail,
isFavorite = true
)
App.appFavoriteDBManager.insertFavoriteBean(b)
AnalysisUtil.logEvent(AnalysisUtil.PLAYER_B_LOVE_CLICK, songMap)
}
requests.trySend(Request.UpdateFavorite(it.bean))
}
is Request.OnDownload -> {
val id = it.bean.videoId
val offBean = App.appOfflineDBManager.getOfflineBeanByID(id)
if (offBean != null && offBean.bytesDownloaded?.let { bytes -> bytes > 0 } == true) {//判断当前数据库是否有这条数据。
if (currentPosition >= 0) {
showRemoveDownloadDialogHint(id)
}
} else {
val isFavorite =
App.appFavoriteDBManager.getFavoriteBeanByID(it.bean.videoId.toString()) != null
//判断是否已经下载了这条数据,已经下载,就直接进行数据库数据存储,反之走下载流程。
if (DownloadUtil.downloadResourceExist(id)) {
val favoriteBean = FavoriteBean(
id,
it.bean.title,
it.bean.name,
it.bean.thumbnail,
isFavorite
)
insertOfflineData(favoriteBean)
requests.trySend(Request.OnUpdateDownloadUi(id))
} else {
val downloadRequest = DownloadRequest.Builder(id, id.toUri())
.setCustomCacheKey(id).build()
val downloadCount = DownloadUtil.getCurrentDownloads()
if (downloadCount >= 3) {
Toast.makeText(
this@MoPlaylistSongsActivity,
getString(R.string.download_tips),
Toast.LENGTH_LONG
).show()
} else {
DownloadService.sendAddDownload(
this@MoPlaylistSongsActivity,
MyDownloadService::class.java,
downloadRequest,
false
)
LolAdWrapper.shared.showAdTiming(
this@MoPlaylistSongsActivity, AdPlacement.INST_DOWNLOAD
)
val favoriteBean = FavoriteBean(
id,
it.bean.title,
it.bean.name,
it.bean.thumbnail,
isFavorite
)
insertOfflineData(favoriteBean)
val jsonObject = JSONObject()
jsonObject.put(
"download_id", favoriteBean.videoId
)
val songMap = mutableMapOf(
Pair(
AnalysisUtil.PARAM_VALUE, jsonObject.toString()
)
)
AnalysisUtil.logEvent(
AnalysisUtil.PLAYER_B_DOWNLOAD_CLICK, songMap
)
LolAdWrapper.shared.loadAdIfNotCached(
this@MoPlaylistSongsActivity, AdPlacement.INST_DOWNLOAD
)
}
}
}
}
is Request.OnDownloadRemove -> {
val currentOfflineBean =
App.appOfflineDBManager.getOfflineBeanByID(it.id)
if (currentOfflineBean != null) {
App.appOfflineDBManager.deleteOfflineBean(currentOfflineBean)
}
requests.trySend(Request.OnUpdateDownloadUi(it.id))
}
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)
}
}
is Request.OnRemovePlaylist -> {
playlistItems.remove(it.bean)
adapter?.notifyDataSetChanged()
App.appPlaylistDBManager.deletePlaylistItem(it.bean)
}
} }
} }
events.onReceive { events.onReceive {
@ -132,17 +313,32 @@ class MoPlaylistSongsActivity : MoBaseActivity() {
binding.bottomBlankLayout.setOnClickListener { binding.bottomBlankLayout.setOnClickListener {
hideBottomLayout() hideBottomLayout()
} }
binding.favoritesBtn.setOnClickListener {
if (currentPosition >= 0) {
requests.trySend(
Request.OnFavorites(
playlistItems[currentPosition]
)
)
}
}
binding.moreDownloadBtn.setOnClickListener { binding.moreDownloadBtn.setOnClickListener {
if (currentPosition >= 0) { if (currentPosition >= 0) {
requests.trySend(
Request.OnDownload(
playlistItems[currentPosition]
)
)
} }
} }
binding.moreAddPlaylistBtn.setOnClickListener { binding.moreAddPlaylistBtn.setOnClickListener {
if (currentPosition >= 0) { if (currentPosition >= 0) {
} requests.trySend(
} Request.OnRemovePlaylist(
binding.favoritesBtn.setOnClickListener { playlistItems[currentPosition]
if (currentPosition >= 0) { )
)
hideBottomLayout()
} }
} }
} }
@ -185,12 +381,85 @@ class MoPlaylistSongsActivity : MoBaseActivity() {
dialog.show() dialog.show()
okBtn.setOnClickListener { okBtn.setOnClickListener {
dialog.dismiss() dialog.dismiss()
requests.trySend(Request.OnDownloadRemove(id))
} }
cancelBtn.setOnClickListener { cancelBtn.setOnClickListener {
dialog.dismiss() dialog.dismiss()
} }
} }
private fun initDownloadFlow() {
ViewModelMain.modelDownloadsFlow.observe(this) { downloads ->
if (currentPosition >= 0) {
val id = playlistItems[currentPosition].videoId
val currentScreenDownloads = downloads[id]
if (currentScreenDownloads != null) {
updateDownloadUI(currentScreenDownloads)
}
}
}
}
private fun updateDownloadUI(download: Download) {
LogTag.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) { private fun updateFavoriteUi(b: Boolean) {
if (b) { if (b) {
binding.favoritesImg.setImageResource(R.drawable.favorited_icon) binding.favoritesImg.setImageResource(R.drawable.favorited_icon)
@ -221,6 +490,15 @@ class MoPlaylistSongsActivity : MoBaseActivity() {
binding.name.visibility = View.VISIBLE binding.name.visibility = View.VISIBLE
binding.name.text = bean.name binding.name.text = bean.name
} }
requests.trySend(Request.UpdateFavorite(bean))
val currentDownload = DownloadUtil.getCurrentIdDownload(bean.videoId)
if (currentDownload != null) {
updateDownloadUI(currentDownload)
} else {
requests.trySend(Request.OnUpdateDownloadUi(bean.videoId))
}
} }
private fun hideBottomLayout() { private fun hideBottomLayout() {

View File

@ -9,12 +9,10 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import melody.offline.music.R import melody.offline.music.R
import melody.offline.music.activity.MoOfflineSongsActivity
import melody.offline.music.activity.MoPlayDetailsActivity import melody.offline.music.activity.MoPlayDetailsActivity
import melody.offline.music.bean.OfflineBean import melody.offline.music.activity.MoPlaylistSongsActivity
import melody.offline.music.bean.PlaylistItem import melody.offline.music.bean.PlaylistItem
import melody.offline.music.databinding.PlayListItemBinding import melody.offline.music.databinding.PlayListItemBinding
import melody.offline.music.media.MediaControllerManager
class PlaylistSongsAdapter( class PlaylistSongsAdapter(
private val context: Context, private val context: Context,
@ -43,14 +41,15 @@ class PlaylistSongsAdapter(
} }
holder.itemView.setOnClickListener { holder.itemView.setOnClickListener {
// val intent = Intent(context, MoPlayDetailsActivity::class.java) val intent = Intent(context, MoPlayDetailsActivity::class.java)
// intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_VIDEO_ID, bean.videoId) intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_VIDEO_ID, bean.videoId)
// intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_NAME, bean.title) intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_NAME, bean.title)
// intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_DESC, bean.name) intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_DESC, bean.name)
// intent.putExtra( intent.putExtra(
// MoPlayDetailsActivity.PLAY_DETAILS_COME_FROM, MoOfflineSongsActivity::class.java MoPlayDetailsActivity.PLAY_DETAILS_COME_FROM, MoPlaylistSongsActivity::class.java
// ) )
// context.startActivity(intent) intent.putExtra(MoPlayDetailsActivity.PLAY_LIST_ID, bean.playlistId)
context.startActivity(intent)
} }
} }

View File

@ -159,8 +159,8 @@ class MoMeFragment : MoBaseFragment<FragmentMoMeBinding>(), NewPlayListAdapter.O
requireActivity(), requireActivity(),
AdPlacement.NATIVE_ME_PAGE_LIST, AdPlacement.NATIVE_ME_PAGE_LIST,
binding.frameAd, binding.frameAd,
R.layout.ad_layout_admob_result, R.layout.ad_layout_admob_banner,
R.layout.ad_layout_max_result R.layout.ad_layout_max_banner
) )
} }
@ -189,6 +189,7 @@ class MoMeFragment : MoBaseFragment<FragmentMoMeBinding>(), NewPlayListAdapter.O
override fun onItemClick(position: Int) { override fun onItemClick(position: Int) {
val intent = Intent(requireActivity(), MoPlaylistSongsActivity::class.java) val intent = Intent(requireActivity(), MoPlaylistSongsActivity::class.java)
intent.putExtra(MoPlaylistSongsActivity.PLAYLIST_ID, playlist[position].id) intent.putExtra(MoPlaylistSongsActivity.PLAYLIST_ID, playlist[position].id)
intent.putExtra(MoPlaylistSongsActivity.PLAYLIST_TITLE, playlist[position].title)
startActivity(intent) startActivity(intent)
} }

View File

@ -11,6 +11,7 @@ import androidx.media3.common.MediaMetadata
import androidx.media3.common.util.UnstableApi import androidx.media3.common.util.UnstableApi
import melody.offline.music.bean.FavoriteBean import melody.offline.music.bean.FavoriteBean
import melody.offline.music.bean.OfflineBean import melody.offline.music.bean.OfflineBean
import melody.offline.music.bean.PlaylistItem
import melody.offline.music.innertube.Innertube import melody.offline.music.innertube.Innertube
import melody.offline.music.innertube.models.bodies.ContinuationBody import melody.offline.music.innertube.models.bodies.ContinuationBody
import melody.offline.music.innertube.requests.playlistPage import melody.offline.music.innertube.requests.playlistPage
@ -46,6 +47,21 @@ val FavoriteBean.asMediaItem: MediaItem
) )
.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()
val Innertube.SongItem.asMediaItem: MediaItem val Innertube.SongItem.asMediaItem: MediaItem
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)
get() = MediaItem.Builder() get() = MediaItem.Builder()

View File

@ -383,7 +383,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="12dp" android:layout_marginStart="12dp"
android:text="@string/download" android:text="@string/download_save_offline"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="14dp" /> android:textSize="14dp" />

View File

@ -57,6 +57,7 @@
android:textSize="18dp" /> android:textSize="18dp" />
<RelativeLayout <RelativeLayout
android:visibility="gone"
android:id="@+id/playlist_title_more_btn" android:id="@+id/playlist_title_more_btn"
android:layout_width="42dp" android:layout_width="42dp"
android:layout_height="42dp"> android:layout_height="42dp">
@ -347,7 +348,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="12dp" android:layout_marginStart="12dp"
android:text="@string/add_to_playlist" android:text="@string/remove_from_playlist"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="14dp" /> android:textSize="14dp" />

View File

@ -94,7 +94,7 @@
<RelativeLayout <RelativeLayout
android:id="@+id/downloadBtn" android:id="@+id/downloadBtn"
android:layout_width="40dp" android:layout_width="40dp"
android:visibility="visible" android:visibility="gone"
android:layout_height="40dp"> android:layout_height="40dp">
<ImageView <ImageView

View File

@ -119,6 +119,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<LinearLayout <LinearLayout
android:visibility="gone"
android:id="@+id/downloadBtn" android:id="@+id/downloadBtn"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"

View File

@ -44,6 +44,7 @@
<string name="play">PLAY</string> <string name="play">PLAY</string>
<string name="download_tips">There are additional download tasks in progress, please wait a moment.</string> <string name="download_tips">There are additional download tasks in progress, please wait a moment.</string>
<string name="add_to_playlist">Add to playlist</string> <string name="add_to_playlist">Add to playlist</string>
<string name="remove_from_playlist">Remove from playlist</string>
<string name="download_saving">Saving</string> <string name="download_saving">Saving</string>
<string name="download_save_offline">Save to Offline</string> <string name="download_save_offline">Save to Offline</string>
<string name="download_remove_offline">Remove from offline</string> <string name="download_remove_offline">Remove from offline</string>