diff --git a/app/src/main/java/melody/offline/music/activity/MoBaseActivity.kt b/app/src/main/java/melody/offline/music/activity/MoBaseActivity.kt
index 98b25c1..cb15a57 100644
--- a/app/src/main/java/melody/offline/music/activity/MoBaseActivity.kt
+++ b/app/src/main/java/melody/offline/music/activity/MoBaseActivity.kt
@@ -12,7 +12,9 @@ import android.renderscript.ScriptIntrinsicBlur
import android.view.LayoutInflater
import android.view.View
import android.widget.EditText
+import android.widget.ImageView
import android.widget.LinearLayout
+import android.widget.ProgressBar
import android.widget.RelativeLayout
import android.widget.TextView
import android.widget.Toast
@@ -20,39 +22,53 @@ import androidx.annotation.OptIn
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
+import androidx.core.net.toUri
import androidx.lifecycle.LifecycleOwner
import androidx.media3.common.MediaItem
import androidx.media3.common.Player
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.RecyclerView
+import com.bumptech.glide.Glide
import com.google.android.material.bottomsheet.BottomSheetDialog
+import com.ironsource.be
+import com.ironsource.vi
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
+import kotlinx.coroutines.selects.select
import kotlinx.coroutines.withContext
import melody.offline.music.App
import melody.offline.music.R
import melody.offline.music.adapter.NewPlayListAdapter
+import melody.offline.music.ads.AdPlacement
+import melody.offline.music.ads.LolAdWrapper
import melody.offline.music.bean.FavoriteBean
import melody.offline.music.bean.OfflineBean
import melody.offline.music.bean.Playlist
import melody.offline.music.bean.PlaylistItem
-import melody.offline.music.fragment.MoMeFragment
import melody.offline.music.http.getAppVersionCode
import melody.offline.music.http.getCountryCode
+import melody.offline.music.innertube.Innertube
import melody.offline.music.media.MediaControllerManager
+import melody.offline.music.service.MyDownloadService
+import melody.offline.music.service.ViewModelMain
import melody.offline.music.sp.AppStore
+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 melody.offline.music.view.MusicPlayerView
import org.json.JSONObject
+
@OptIn(UnstableApi::class)
abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), LifecycleOwner {
private var playerListener: Player.Listener? = null
@@ -69,7 +85,6 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
private var defer: suspend () -> Unit = {}
private var deferRunning = false
private lateinit var musicPlayerView: MusicPlayerView
- private lateinit var bottomAddPlaylistSheetDialog: BottomSheetDialog
fun defer(operation: suspend () -> Unit) {
this.defer = operation
@@ -365,7 +380,7 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
}
suspend fun showAddPlaylistBottomDialog(favoriteBean: FavoriteBean) {
- bottomAddPlaylistSheetDialog = BottomSheetDialog(this)
+ val bottomAddPlaylistSheetDialog = BottomSheetDialog(this)
val view = layoutInflater.inflate(R.layout.add_playlist_layout, null)
bottomAddPlaylistSheetDialog.setContentView(view)
val newPlayListBtn = view.findViewById(R.id.newPlayListBtn)
@@ -397,8 +412,10 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
).show()
}
} else {
- val isOffline = App.appOfflineDBManager.getOfflineBeanByID(favoriteBean.videoId) != null
- val isFavorite = App.appFavoriteDBManager.getFavoriteBeanByID(favoriteBean.videoId) != null
+ val isOffline =
+ App.appOfflineDBManager.getOfflineBeanByID(favoriteBean.videoId) != null
+ val isFavorite =
+ App.appFavoriteDBManager.getFavoriteBeanByID(favoriteBean.videoId) != null
App.appPlaylistDBManager.insertOrUpdatePlaylistItem(
PlaylistItem(
playlistId = playlist[position].id,
@@ -461,8 +478,10 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
}
val currentPlaylist = App.appPlaylistDBManager.getPlaylistByTitle(text)
if (currentPlaylist != null) {
- val isOffline = App.appOfflineDBManager.getOfflineBeanByID(favoriteBean.videoId) != null//返回非null则为true
- val isFavorite = App.appFavoriteDBManager.getFavoriteBeanByID(favoriteBean.videoId) != null
+ val isOffline =
+ App.appOfflineDBManager.getOfflineBeanByID(favoriteBean.videoId) != null//返回非null则为true
+ val isFavorite =
+ App.appFavoriteDBManager.getFavoriteBeanByID(favoriteBean.videoId) != null
val playlistItem = PlaylistItem(
playlistId = currentPlaylist.id,
videoId = favoriteBean.videoId,
@@ -484,5 +503,4 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
ContextCompat.getColor(this, R.color.main_bg_color)
bottomSheetDialog?.show()
}
-
}
\ No newline at end of file
diff --git a/app/src/main/java/melody/offline/music/activity/MoListDetailsActivity.kt b/app/src/main/java/melody/offline/music/activity/MoListDetailsActivity.kt
index f82f149..afca611 100644
--- a/app/src/main/java/melody/offline/music/activity/MoListDetailsActivity.kt
+++ b/app/src/main/java/melody/offline/music/activity/MoListDetailsActivity.kt
@@ -2,24 +2,64 @@ package melody.offline.music.activity
import android.annotation.SuppressLint
import android.content.Intent
+import android.graphics.Color
+import android.graphics.drawable.ColorDrawable
+import android.view.LayoutInflater
import android.view.View
+import android.view.animation.AnimationUtils
+import android.widget.TextView
+import android.widget.Toast
+import androidx.annotation.OptIn
+import androidx.appcompat.app.AlertDialog
+import androidx.core.net.toUri
+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 com.bumptech.glide.Glide
import com.gyf.immersionbar.ktx.immersionBar
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.isActive
import kotlinx.coroutines.selects.select
+import melody.offline.music.App
+import melody.offline.music.R
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.OfflineBean
import melody.offline.music.databinding.ActivityDetailsBinding
import melody.offline.music.innertube.Innertube
import melody.offline.music.innertube.requests.moPlaylistPage
+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 org.json.JSONObject
-class MoListDetailsActivity : MoBaseActivity() {
+@OptIn(UnstableApi::class)
+class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreClickListener,
+ DetailsListAdapter.OnItemDownloadClickListener {
private val requests: Channel = Channel(Channel.UNLIMITED)
- enum class Request {
- TryAgain,
+ sealed class Request {
+ data object TryAgain : Request()
+ data class UpdateFavorite(val bean: Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean) :
+ Request()
+
+ data class OnFavorites(val bean: Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean) :
+ Request()
+
+ data class OnDownload(val bean: Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean) :
+ Request()
+
+ data class OnDownloadRemove(val id: String) : Request()
+ data class OnUpdateDownloadUi(val id: String) : Request()
+ data class OnAddPlaylist(val bean: Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean) :
+ Request()
}
companion object {
@@ -32,7 +72,8 @@ class MoListDetailsActivity : MoBaseActivity() {
private var adapter: DetailsListAdapter? = null
private var myList: MutableList =
mutableListOf()
-
+ private var myBean: Innertube.MoPlaylistOrAlbumPage? = null
+ private var currentPosition = -1
override suspend fun main() {
binding = ActivityDetailsBinding.inflate(layoutInflater)
setContentView(binding.root)
@@ -44,6 +85,7 @@ class MoListDetailsActivity : MoBaseActivity() {
}
initView()
LogD(TAG, "browseId->${browseId}")
+ initDownloadFlow()
initData(browseId!!)
onReceive()
}
@@ -64,6 +106,163 @@ class MoListDetailsActivity : MoBaseActivity() {
Request.TryAgain -> {
initData(browseId!!)
}
+
+ 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.toString(),
+ name = it.bean.name.toString(),
+ thumbnail = it.bean.thumbnailUrl,
+ 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 currentOfflineBean =
+ App.appOfflineDBManager.getOfflineBeanByID(id!!)
+ if (currentOfflineBean != null) {//判断当前数据库是否有这条数据。
+ 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.toString(),
+ it.bean.name.toString(),
+ it.bean.thumbnailUrl,
+ 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@MoListDetailsActivity,
+ getString(R.string.download_tips),
+ Toast.LENGTH_LONG
+ ).show()
+ } else {
+ DownloadService.sendAddDownload(
+ this@MoListDetailsActivity,
+ MyDownloadService::class.java,
+ downloadRequest,
+ false
+ )
+
+
+ LolAdWrapper.shared.showAdTiming(
+ this@MoListDetailsActivity, AdPlacement.INST_DOWNLOAD
+ )
+ val favoriteBean = FavoriteBean(
+ id,
+ it.bean.title.toString(),
+ it.bean.name.toString(),
+ it.bean.thumbnailUrl,
+ 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@MoListDetailsActivity, 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 -> {
+ if (App.appOfflineDBManager.getOfflineBeanByID(it.id) != null) {
+ binding.downloadImg.setImageResource(R.drawable.more_downloaded_icon)
+ binding.downloadTv.text =
+ getString(R.string.download_remove_offline)
+ } else {
+ binding.downloadImg.setImageResource(R.drawable.more_download_icon)
+ binding.downloadTv.text = getString(R.string.download_save_offline)
+ }
+ }
+
+ is Request.OnAddPlaylist -> {
+ val isFavorite =
+ App.appFavoriteDBManager.getFavoriteBeanByID(it.bean.videoId.toString()) != null
+ showAddPlaylistBottomDialog(
+ FavoriteBean(
+ videoId = it.bean.videoId.toString(),
+ title = it.bean.title.toString(),
+ name = it.bean.name.toString(),
+ thumbnail = it.bean.thumbnailUrl.toString(),
+ isFavorite
+ )
+ )
+ }
}
}
events.onReceive {
@@ -94,8 +293,20 @@ class MoListDetailsActivity : MoBaseActivity() {
}
}
+
+ override fun onItemDownloadClick(position: Int) {
+
+ }
+
+ override fun onItemMoreClick(position: Int) {
+ currentPosition = position
+ toggleBottomLayout(position)
+ }
+
private fun initView() {
adapter = DetailsListAdapter(this, myList)
+ adapter?.setOnItemDownloadClickListener(this)
+ adapter?.setOnItemMoreClickListener(this)
binding.rv.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
binding.rv.adapter = adapter
@@ -122,6 +333,30 @@ class MoListDetailsActivity : MoBaseActivity() {
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]))
+ }
+ }
+ binding.moreDownloadBtn.setOnClickListener {
+ if (currentPosition >= 0) {
+ requests.trySend(Request.OnDownload(myList[currentPosition]))
+ }
+ }
+ binding.moreAddPlaylistBtn.setOnClickListener {
+ if (currentPosition >= 0) {
+ requests.trySend(Request.OnAddPlaylist(myList[currentPosition]))
+ hideBottomLayout()
+ }
+ }
}
@SuppressLint("NotifyDataSetChanged")
@@ -131,12 +366,13 @@ class MoListDetailsActivity : MoBaseActivity() {
if (this.isDestroyed || this.isFinishing) {
return
}
+ myBean = it
LogD(TAG, "moPlaylistPage onSuccess->${it.moPlaylistOrAlbumListBean}")
if (it.moPlaylistOrAlbumListBean.isNotEmpty()) {
showDataUi()
Glide.with(this).load(it.thumbnail).into(binding.imageView)
- binding.title.text = it.title
+ binding.infoTitle.text = it.title
binding.subtitle.text = it.subtitle
binding.secondSubtitle.text = it.secondSubtitle
@@ -166,4 +402,141 @@ class MoListDetailsActivity : MoBaseActivity() {
binding.loadingLayout.visibility = View.GONE
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) {
+ 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)
+ }
+ }
+
+ 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)
+ binding.bottomLayout.startAnimation(slideUpAnimation)
+ binding.bottomLayout.visibility = View.VISIBLE
+
+ val bean = myList[position]
+ Glide.with(this).load(bean.thumbnailUrl).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))
+
+ requests.trySend(Request.OnUpdateDownloadUi(bean.videoId!!))
+
+ val currentDownload = DownloadUtil.getCurrentIdDownload(bean.videoId)
+ if (currentDownload != null) {
+ updateDownloadUI(currentDownload)
+ }
+ }
+
+ private fun hideBottomLayout() {
+ val slideDownAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_down)
+ binding.bottomLayout.startAnimation(slideDownAnimation)
+ binding.bottomLayout.visibility = View.GONE
+ }
+
+ private fun showRemoveDownloadDialogHint(id: String) {
+ val inflater = LayoutInflater.from(this)
+ val dialogView = inflater.inflate(R.layout.dialog_hint, null)
+ val okBtn = dialogView.findViewById(R.id.dialog_ok_btn)
+ val cancelBtn = dialogView.findViewById(R.id.dialog_cancel_btn)
+ val dialogBuilder = AlertDialog.Builder(this).setView(dialogView)
+ val dialog = dialogBuilder.create()
+ dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
+ dialog.show()
+ okBtn.setOnClickListener {
+ dialog.dismiss()
+ requests.trySend(Request.OnDownloadRemove(id))
+ }
+ cancelBtn.setOnClickListener {
+ dialog.dismiss()
+ }
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/melody/offline/music/activity/MoPlaylistSongsActivity.kt b/app/src/main/java/melody/offline/music/activity/MoPlaylistSongsActivity.kt
index 0c95e40..554ba13 100644
--- a/app/src/main/java/melody/offline/music/activity/MoPlaylistSongsActivity.kt
+++ b/app/src/main/java/melody/offline/music/activity/MoPlaylistSongsActivity.kt
@@ -103,13 +103,18 @@ class MoPlaylistSongsActivity : MoBaseActivity() {
adapter?.notifyDataSetChanged()
}
- LolAdWrapper.shared.loadAdShowNativeAd(
- this,
- AdPlacement.NATIVE_ME_PAGE_LIST,
- binding.frameAd,
- R.layout.ad_layout_admob_banner,
- R.layout.ad_layout_max_banner
- )
+ try {
+ LolAdWrapper.shared.loadAdShowNativeAd(
+ this,
+ AdPlacement.NATIVE_ME_PAGE_LIST,
+ binding.frameAd,
+ R.layout.ad_layout_admob_banner,
+ R.layout.ad_layout_max_banner
+ )
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+
}
private fun initView() {
diff --git a/app/src/main/java/melody/offline/music/adapter/DetailsListAdapter.kt b/app/src/main/java/melody/offline/music/adapter/DetailsListAdapter.kt
index 523ad07..97a4274 100644
--- a/app/src/main/java/melody/offline/music/adapter/DetailsListAdapter.kt
+++ b/app/src/main/java/melody/offline/music/adapter/DetailsListAdapter.kt
@@ -45,11 +45,23 @@ class DetailsListAdapter(
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_DESC, bean.name)
context.startActivity(intent)
}
+
+ holder.binding.downloadBtn.setOnClickListener {
+ if (itemDownloadClickListener != null) {
+ itemDownloadClickListener?.onItemDownloadClick(position)
+ }
+ }
+
+ holder.binding.moreBtn.setOnClickListener {
+ if (itemMoreClickListener != null) {
+ itemMoreClickListener?.onItemMoreClick(position)
+ }
+ }
}
override fun getItemCount(): Int = list.size
- inner class ViewHolder(private val binding: DetailsListItemBinding) :
+ inner class ViewHolder(val binding: DetailsListItemBinding) :
RecyclerView.ViewHolder(binding.root) {
@SuppressLint("SetTextI18n")
@@ -110,4 +122,24 @@ class DetailsListAdapter(
interface OnItemClickListener {
fun onItemClick(position: Int)
}
+
+ private var itemDownloadClickListener: OnItemDownloadClickListener? = null
+
+ fun setOnItemDownloadClickListener(listener: OnItemDownloadClickListener) {
+ itemDownloadClickListener = listener
+ }
+
+ interface OnItemDownloadClickListener {
+ fun onItemDownloadClick(position: Int)
+ }
+
+ private var itemMoreClickListener: OnItemMoreClickListener? = null
+
+ fun setOnItemMoreClickListener(listener: OnItemMoreClickListener) {
+ itemMoreClickListener = listener
+ }
+
+ interface OnItemMoreClickListener {
+ fun onItemMoreClick(position: Int)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/melody/offline/music/bean/playlist.kt b/app/src/main/java/melody/offline/music/bean/playlist.kt
index 47b1eb2..7cd4ee2 100644
--- a/app/src/main/java/melody/offline/music/bean/playlist.kt
+++ b/app/src/main/java/melody/offline/music/bean/playlist.kt
@@ -26,7 +26,7 @@ data class Playlist(
)
data class PlaylistItem(
@PrimaryKey(autoGenerate = true) val id: Int = 0,
- @ColumnInfo(name = "playlist_id") val playlistId: Int,
+ @ColumnInfo(name = "playlist_id") val playlistId: Int? = null,
@ColumnInfo(name = "videoId") var videoId: String,
@ColumnInfo(name = "title") var title: String,
@ColumnInfo(name = "name") var name: String,
diff --git a/app/src/main/java/melody/offline/music/innertube/Innertube.kt b/app/src/main/java/melody/offline/music/innertube/Innertube.kt
index 73e7c1d..6eb41e3 100644
--- a/app/src/main/java/melody/offline/music/innertube/Innertube.kt
+++ b/app/src/main/java/melody/offline/music/innertube/Innertube.kt
@@ -223,6 +223,7 @@ object Innertube {
val thumbnail: String?,
val secondSubtitle: String?,
val description: String?,
+ val singerName: String?,
val moPlaylistOrAlbumListBean: List
) {
data class MoPlaylistOrAlbumListBean(
diff --git a/app/src/main/java/melody/offline/music/innertube/models/SectionListRenderer.kt b/app/src/main/java/melody/offline/music/innertube/models/SectionListRenderer.kt
index 0839f39..9f72bf4 100644
--- a/app/src/main/java/melody/offline/music/innertube/models/SectionListRenderer.kt
+++ b/app/src/main/java/melody/offline/music/innertube/models/SectionListRenderer.kt
@@ -30,7 +30,8 @@ data class SectionListRenderer(
val subtitle: Runs?,
val secondSubtitle: Runs?,
val thumbnail: ThumbnailRenderer?,
- val description: Description?
+ val description: Description?,
+ val straplineTextOne: Runs?
) {
@Serializable
data class Description(
diff --git a/app/src/main/java/melody/offline/music/innertube/requests/MoPlaylistPage.kt b/app/src/main/java/melody/offline/music/innertube/requests/MoPlaylistPage.kt
index c0698fe..8d6d88c 100644
--- a/app/src/main/java/melody/offline/music/innertube/requests/MoPlaylistPage.kt
+++ b/app/src/main/java/melody/offline/music/innertube/requests/MoPlaylistPage.kt
@@ -102,7 +102,7 @@ suspend fun Innertube.moPlaylistPage(browseId: String): Result
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/details_list_item.xml b/app/src/main/res/layout/details_list_item.xml
index 45100d8..406a22f 100644
--- a/app/src/main/res/layout/details_list_item.xml
+++ b/app/src/main/res/layout/details_list_item.xml
@@ -94,14 +94,27 @@
+ android:src="@drawable/download_icon" />
+
+
+
+
+
diff --git a/app/src/main/res/layout/list_more_layout.xml b/app/src/main/res/layout/list_more_layout.xml
new file mode 100644
index 0000000..8135645
--- /dev/null
+++ b/app/src/main/res/layout/list_more_layout.xml
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index b501f80..bf9cde2 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -32,6 +32,7 @@
Download
Downloads
Library
+ Like
Liked songs
Offline songs
Songs