This commit is contained in:
ocean 2024-07-02 16:17:38 +08:00
parent 207f2e32ae
commit 43399079c8
6 changed files with 139 additions and 358 deletions

View File

@ -5,14 +5,12 @@ 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 androidx.annotation.OptIn
import androidx.appcompat.app.AlertDialog
import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.offline.Download
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
@ -24,29 +22,33 @@ 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.PlaylistItem
import melody.offline.music.databinding.ActivityOfflineSongsBinding
import melody.offline.music.util.AnalysisUtil
import melody.offline.music.util.LogTag
import melody.offline.music.view.ListMoreBottomSheetDialog
import org.json.JSONObject
@OptIn(UnstableApi::class)
class MoOfflineSongsActivity : MoBaseActivity() {
class MoOfflineSongsActivity : MoBaseActivity(), ListMoreBottomSheetDialog.ListMoreViewListener,
ListMoreBottomSheetDialog.UpdateAdapterListener {
private val requests: Channel<Request> = Channel(Channel.UNLIMITED)
sealed class Request {
data object TryAgain : Request()
data class OnFavorites(val bean: OfflineBean) : Request()
data class OnDownloadRemove(val id: String) : Request()
data class UpdateFavorite(val id: String) : Request()
data class OnAddPlaylist(val bean: OfflineBean) : Request()
data class OnFavorites(val bean: PlaylistItem) : Request()
data class OnDownloadRemove(val bean: PlaylistItem) : Request()
data class UpdateFavorite(val bean: PlaylistItem) : Request()
data class OnAddPlaylist(val bean: PlaylistItem) : Request()
data class OnUpdateCurrentListItem(val bean: PlaylistItem) : Request()
}
private lateinit var binding: ActivityOfflineSongsBinding
private var adapter: OfflineSongsAdapter? = null
private var offlineList: MutableList<OfflineBean> = mutableListOf()
private var myList: MutableList<PlaylistItem> = mutableListOf()
private var moreDialog: ListMoreBottomSheetDialog? = null
private var currentPosition = -1
private var isAnimationRunning = false//动画是否正在进行
override suspend fun main() {
binding = ActivityOfflineSongsBinding.inflate(layoutInflater)
@ -89,7 +91,7 @@ class MoOfflineSongsActivity : MoBaseActivity() {
)
val currentFavoriteBean =
App.appFavoriteDBManager.getFavoriteBeanByID(it.bean.videoId)
if (currentFavoriteBean != null) {
if (currentFavoriteBean != null) {//先获取数据库是否有这条数据
currentFavoriteBean.isFavorite = !currentFavoriteBean.isFavorite
App.appFavoriteDBManager.updateFavoriteBean(currentFavoriteBean)
if (currentFavoriteBean.isFavorite) {
@ -102,34 +104,47 @@ class MoOfflineSongsActivity : MoBaseActivity() {
)
}
} else {
insertFavoriteData(it.bean)
insertFavoriteData(OfflineBean(
videoId = it.bean.videoId,
title = it.bean.title,
name = it.bean.name,
thumbnail = it.bean.thumbnail,
bytesDownloaded = it.bean.bytesDownloaded,
size = it.bean.size,
isOffline = it.bean.isOffline,
isFavorite = it.bean.isFavorite
))
AnalysisUtil.logEvent(AnalysisUtil.PLAYER_B_LOVE_CLICK, songMap)
}
requests.trySend(Request.UpdateFavorite(it.bean.videoId))
}
is Request.OnDownloadRemove -> {
val currentOfflineBean =
App.appOfflineDBManager.getOfflineBeanByID(it.id)
if (currentOfflineBean != null) {
App.appOfflineDBManager.deleteOfflineBean(currentOfflineBean)
}
if (currentPosition >= 0) {
offlineList.remove(offlineList[currentPosition])
}
adapter?.notifyDataSetChanged()
hideBottomLayout()
requests.trySend(Request.UpdateFavorite(it.bean))
}
is Request.UpdateFavorite -> {
val currentFavoriteBean =
App.appFavoriteDBManager.getFavoriteBeanByID(it.id)
val currentFavoriteBean = App.appFavoriteDBManager.getFavoriteBeanByID(it.bean.videoId)
if (currentFavoriteBean != null) {
updateFavoriteUi(currentFavoriteBean.isFavorite)
} else {
updateFavoriteUi(false)
}
requests.trySend(Request.OnUpdateCurrentListItem(it.bean))
}
is Request.OnDownloadRemove -> {
val currentOfflineBean =
App.appOfflineDBManager.getOfflineBeanByID(it.bean.videoId)
if (currentOfflineBean != null) {
App.appOfflineDBManager.deleteOfflineBean(currentOfflineBean)
}
if (currentPosition >= 0) {
myList.remove(myList[currentPosition])
}
adapter?.notifyDataSetChanged()
moreDialog?.dismiss()
requests.trySend(Request.OnUpdateCurrentListItem(it.bean))
}
is Request.OnAddPlaylist -> {
@ -143,6 +158,10 @@ class MoOfflineSongsActivity : MoBaseActivity() {
)
)
}
is Request.OnUpdateCurrentListItem -> {
updateCurrentItem(it.bean.videoId)
}
}
}
events.onReceive {
@ -182,46 +201,27 @@ class MoOfflineSongsActivity : MoBaseActivity() {
}
private fun initView() {
binding.layoutInfo.setOnClickListener { }
binding.backBtn.setOnClickListener {
finish()
}
binding.tryAgainBtn.setOnClickListener {
requests.trySend(Request.TryAgain)
}
binding.bottomCloseBtn.setOnClickListener {
hideBottomLayout()
}
binding.bottomBlankLayout.setOnClickListener {
hideBottomLayout()
}
binding.moreDownloadBtn.setOnClickListener {
if (currentPosition >= 0) {
val videoId = offlineList[currentPosition].videoId
showRemoveDownloadDialogHint(videoId)
}
}
binding.moreAddPlaylistBtn.setOnClickListener {
if (currentPosition >= 0) {
requests.trySend(Request.OnAddPlaylist(offlineList[currentPosition]))
hideBottomLayout()
}
}
binding.favoritesBtn.setOnClickListener {
if (currentPosition >= 0) {
requests.trySend(Request.OnFavorites(offlineList[currentPosition]))
}
}
}
private fun initAdapter() {
adapter = OfflineSongsAdapter(this, offlineList)
adapter = OfflineSongsAdapter(this, myList)
adapter?.setOnMoreClickListener(object : OfflineSongsAdapter.OnMoreClickListener {
override fun onMoreClick(position: Int) {
currentPosition = position
if (!isAnimationRunning) {
toggleBottomLayout(position)
}
moreDialog = ListMoreBottomSheetDialog(
this@MoOfflineSongsActivity,
myList[position],
this@MoOfflineSongsActivity,
this@MoOfflineSongsActivity
)
moreDialog?.setListMoreViewListener(this@MoOfflineSongsActivity)
moreDialog?.show()
}
})
binding.rv.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
@ -231,35 +231,84 @@ class MoOfflineSongsActivity : MoBaseActivity() {
@SuppressLint("NotifyDataSetChanged")
private suspend fun initData() {
showLoadingUi()
offlineList.clear()
val offlineBeans = App.appOfflineDBManager.getAllOfflineBeans()
// 更新
offlineBeans.forEach { offlineBean ->
val favoriteBean = App.appFavoriteDBManager.getFavoriteBeanByID(offlineBean.videoId)
if (favoriteBean != null) {
if (offlineBean.id == favoriteBean.id) {
offlineBean.isFavorite = favoriteBean.isFavorite
App.appOfflineDBManager.updateOfflineBean(offlineBean)
if (offlineBeans.isNotEmpty()) {
myList.clear()
offlineBeans.forEach { offlineBean ->
val favoriteItem = App.appFavoriteDBManager.getFavoriteBeanByID(offlineBean.videoId)
if (offlineBean.bytesDownloaded?.let { bytes -> bytes > 0 } == true) {
myList.add(
PlaylistItem(
videoId = offlineBean.videoId,
title = offlineBean.title,
name = offlineBean.name,
thumbnail = offlineBean.thumbnail,
isOffline = offlineBean.isOffline,
isFavorite = favoriteItem?.isFavorite ?: false,
bytesDownloaded = offlineBean.bytesDownloaded,
size = offlineBean.size
)
)
}
}
}
val filteredBeans =
offlineBeans.filter { it.bytesDownloaded?.let { bytes -> bytes > 0 } == true }
offlineList.addAll(filteredBeans)
if (offlineList.size > 0) {
showDataUi()
if (myList.size > 0) {
showDataUi()
} else {
showNoContentUi()
}
} else {
showNoContentUi()
}
if (adapter != null) {
adapter?.notifyDataSetChanged()
}
}
private fun updateFavoriteUi(b: Boolean) {
if (moreDialog != null) {
moreDialog?.updateFavoriteUi(b)
}
}
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) {
LogTag.LogD(TAG, "updateCurrentItem -> $item")
}
}
}
override fun onFavoritesClicked(playlistItem: PlaylistItem) {
requests.trySend(Request.OnFavorites(playlistItem))
}
override fun onDownloadClicked(playlistItem: PlaylistItem) {
//下载列表只有删除删除后更新adapter
showRemoveDownloadDialogHint(playlistItem)
}
override fun onAddToPlaylistClicked(playlistItem: PlaylistItem) {
requests.trySend(Request.OnAddPlaylist(playlistItem))
}
override fun onUpdateAdapterListener(download: Download, playlistItem: PlaylistItem) {
}
private fun showRemoveDownloadDialogHint(id: String) {
LogTag.LogD(TAG, "showRemoveDownloadDialogHint")
private fun showRemoveDownloadDialogHint(bean: 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)
@ -270,93 +319,13 @@ class MoOfflineSongsActivity : MoBaseActivity() {
dialog.show()
okBtn.setOnClickListener {
dialog.dismiss()
requests.trySend(Request.OnDownloadRemove(id))
requests.trySend(Request.OnDownloadRemove(bean))
}
cancelBtn.setOnClickListener {
dialog.dismiss()
}
}
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)
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 = offlineList[position]
Glide.with(this).load(bean.thumbnail).into(binding.songImg)
binding.title.text = bean.title
if (bean.name.isEmpty()) {
binding.name.visibility = View.GONE
} else {
binding.name.visibility = View.VISIBLE
binding.name.text = bean.name
}
requests.trySend(Request.UpdateFavorite(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
}
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 showDataUi() {
binding.loadingLayout.visibility = View.GONE
binding.noContentLayout.visibility = View.GONE

View File

@ -339,7 +339,8 @@ class MoPlaylistSongsActivity : MoBaseActivity(), ListMoreBottomSheetDialog.List
this@MoPlaylistSongsActivity,
playlistItems[position],
this@MoPlaylistSongsActivity,
this@MoPlaylistSongsActivity
this@MoPlaylistSongsActivity,
true
)
moreDialog?.setListMoreViewListener(this@MoPlaylistSongsActivity)
moreDialog?.show()

View File

@ -11,13 +11,13 @@ import com.bumptech.glide.Glide
import melody.offline.music.R
import melody.offline.music.activity.MoOfflineSongsActivity
import melody.offline.music.activity.MoPlayDetailsActivity
import melody.offline.music.bean.OfflineBean
import melody.offline.music.bean.PlaylistItem
import melody.offline.music.databinding.OfflineListItemBinding
import melody.offline.music.media.MediaControllerManager
class OfflineSongsAdapter(
private val context: Context,
private val list: List<OfflineBean>,
private val list: List<PlaylistItem>,
) : RecyclerView.Adapter<OfflineSongsAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
@ -54,7 +54,7 @@ class OfflineSongsAdapter(
RecyclerView.ViewHolder(binding.root) {
@SuppressLint("SetTextI18n")
fun bind(bean: OfflineBean) {
fun bind(bean: PlaylistItem) {
binding.apply {
Glide.with(context).load(bean.thumbnail).into(image)

View File

@ -29,7 +29,8 @@ class ListMoreBottomSheetDialog(
private val context: Activity,
private val playlistItem: PlaylistItem,
private val lifecycleOwner: LifecycleOwner,
private val updateAdapterListener: UpdateAdapterListener
private val updateAdapterListener: UpdateAdapterListener,
private val isPlayList: Boolean? = null
) : BottomSheetDialog(context) {
private var bottomDialogBottomLayout: LinearLayout? = null
private var bottomDialogBottomCloseBtn: LinearLayout? = null
@ -75,6 +76,12 @@ class ListMoreBottomSheetDialog(
}
private fun initInfoUi() {
if (isPlayList == true) {//如果是playlist点击进入则为remove
bottomDialogAddPlaylistTv?.text = context.getString(R.string.remove_from_playlist)
} else {
bottomDialogAddPlaylistTv?.text = context.getString(R.string.add_to_playlist)
}
val bean = playlistItem
Glide.with(context).load(bean.thumbnail).into(bottomDialogSongImg!!)
bottomDialogTitle?.text = bean.title
@ -137,7 +144,7 @@ class ListMoreBottomSheetDialog(
}
fun updateDownloadBtnUi(b: Boolean) {
LogTag.LogD(LogTag.VO_TEST_ONLY,"more dialog updateDownloadBtnUi ->$b")
LogTag.LogD(LogTag.VO_TEST_ONLY, "more dialog updateDownloadBtnUi ->$b")
if (b) {
bottomDialogDownloadLoading?.visibility = View.GONE
bottomDialogDownloadImg?.visibility = View.VISIBLE

View File

@ -149,200 +149,4 @@
android:orientation="vertical" />
</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_downloaded_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_remove_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

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