update
This commit is contained in:
parent
ca30bb789a
commit
1156dc4c34
@ -12,7 +12,9 @@ import android.renderscript.ScriptIntrinsicBlur
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
|
import android.widget.ImageView
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.ProgressBar
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
@ -20,39 +22,53 @@ import androidx.annotation.OptIn
|
|||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.net.toUri
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import androidx.media3.common.MediaItem
|
import androidx.media3.common.MediaItem
|
||||||
import androidx.media3.common.Player
|
import androidx.media3.common.Player
|
||||||
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 androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
|
import com.ironsource.be
|
||||||
|
import com.ironsource.vi
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.MainScope
|
import kotlinx.coroutines.MainScope
|
||||||
import kotlinx.coroutines.NonCancellable
|
import kotlinx.coroutines.NonCancellable
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
import kotlinx.coroutines.isActive
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.selects.select
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import melody.offline.music.App
|
import melody.offline.music.App
|
||||||
import melody.offline.music.R
|
import melody.offline.music.R
|
||||||
import melody.offline.music.adapter.NewPlayListAdapter
|
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.FavoriteBean
|
||||||
import melody.offline.music.bean.OfflineBean
|
import melody.offline.music.bean.OfflineBean
|
||||||
import melody.offline.music.bean.Playlist
|
import melody.offline.music.bean.Playlist
|
||||||
import melody.offline.music.bean.PlaylistItem
|
import melody.offline.music.bean.PlaylistItem
|
||||||
import melody.offline.music.fragment.MoMeFragment
|
|
||||||
import melody.offline.music.http.getAppVersionCode
|
import melody.offline.music.http.getAppVersionCode
|
||||||
import melody.offline.music.http.getCountryCode
|
import melody.offline.music.http.getCountryCode
|
||||||
|
import melody.offline.music.innertube.Innertube
|
||||||
import melody.offline.music.media.MediaControllerManager
|
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.sp.AppStore
|
||||||
|
import melody.offline.music.util.AnalysisUtil
|
||||||
import melody.offline.music.util.DownloadUtil
|
import melody.offline.music.util.DownloadUtil
|
||||||
import melody.offline.music.util.FileSizeConverter
|
import melody.offline.music.util.FileSizeConverter
|
||||||
import melody.offline.music.util.LogTag
|
import melody.offline.music.util.LogTag
|
||||||
import melody.offline.music.view.MusicPlayerView
|
import melody.offline.music.view.MusicPlayerView
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
|
||||||
@OptIn(UnstableApi::class)
|
@OptIn(UnstableApi::class)
|
||||||
abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), LifecycleOwner {
|
abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), LifecycleOwner {
|
||||||
private var playerListener: Player.Listener? = null
|
private var playerListener: Player.Listener? = null
|
||||||
@ -69,7 +85,6 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
|
|||||||
private var defer: suspend () -> Unit = {}
|
private var defer: suspend () -> Unit = {}
|
||||||
private var deferRunning = false
|
private var deferRunning = false
|
||||||
private lateinit var musicPlayerView: MusicPlayerView
|
private lateinit var musicPlayerView: MusicPlayerView
|
||||||
private lateinit var bottomAddPlaylistSheetDialog: BottomSheetDialog
|
|
||||||
|
|
||||||
fun defer(operation: suspend () -> Unit) {
|
fun defer(operation: suspend () -> Unit) {
|
||||||
this.defer = operation
|
this.defer = operation
|
||||||
@ -365,7 +380,7 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun showAddPlaylistBottomDialog(favoriteBean: FavoriteBean) {
|
suspend fun showAddPlaylistBottomDialog(favoriteBean: FavoriteBean) {
|
||||||
bottomAddPlaylistSheetDialog = BottomSheetDialog(this)
|
val bottomAddPlaylistSheetDialog = BottomSheetDialog(this)
|
||||||
val view = layoutInflater.inflate(R.layout.add_playlist_layout, null)
|
val view = layoutInflater.inflate(R.layout.add_playlist_layout, null)
|
||||||
bottomAddPlaylistSheetDialog.setContentView(view)
|
bottomAddPlaylistSheetDialog.setContentView(view)
|
||||||
val newPlayListBtn = view.findViewById<LinearLayout>(R.id.newPlayListBtn)
|
val newPlayListBtn = view.findViewById<LinearLayout>(R.id.newPlayListBtn)
|
||||||
@ -397,8 +412,10 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
|
|||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val isOffline = App.appOfflineDBManager.getOfflineBeanByID(favoriteBean.videoId) != null
|
val isOffline =
|
||||||
val isFavorite = App.appFavoriteDBManager.getFavoriteBeanByID(favoriteBean.videoId) != null
|
App.appOfflineDBManager.getOfflineBeanByID(favoriteBean.videoId) != null
|
||||||
|
val isFavorite =
|
||||||
|
App.appFavoriteDBManager.getFavoriteBeanByID(favoriteBean.videoId) != null
|
||||||
App.appPlaylistDBManager.insertOrUpdatePlaylistItem(
|
App.appPlaylistDBManager.insertOrUpdatePlaylistItem(
|
||||||
PlaylistItem(
|
PlaylistItem(
|
||||||
playlistId = playlist[position].id,
|
playlistId = playlist[position].id,
|
||||||
@ -461,8 +478,10 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
|
|||||||
}
|
}
|
||||||
val currentPlaylist = App.appPlaylistDBManager.getPlaylistByTitle(text)
|
val currentPlaylist = App.appPlaylistDBManager.getPlaylistByTitle(text)
|
||||||
if (currentPlaylist != null) {
|
if (currentPlaylist != null) {
|
||||||
val isOffline = App.appOfflineDBManager.getOfflineBeanByID(favoriteBean.videoId) != null//返回非null则为true
|
val isOffline =
|
||||||
val isFavorite = App.appFavoriteDBManager.getFavoriteBeanByID(favoriteBean.videoId) != null
|
App.appOfflineDBManager.getOfflineBeanByID(favoriteBean.videoId) != null//返回非null则为true
|
||||||
|
val isFavorite =
|
||||||
|
App.appFavoriteDBManager.getFavoriteBeanByID(favoriteBean.videoId) != null
|
||||||
val playlistItem = PlaylistItem(
|
val playlistItem = PlaylistItem(
|
||||||
playlistId = currentPlaylist.id,
|
playlistId = currentPlaylist.id,
|
||||||
videoId = favoriteBean.videoId,
|
videoId = favoriteBean.videoId,
|
||||||
@ -484,5 +503,4 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
|
|||||||
ContextCompat.getColor(this, R.color.main_bg_color)
|
ContextCompat.getColor(this, R.color.main_bg_color)
|
||||||
bottomSheetDialog?.show()
|
bottomSheetDialog?.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -2,24 +2,64 @@ package melody.offline.music.activity
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.drawable.ColorDrawable
|
||||||
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
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 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
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
import kotlinx.coroutines.selects.select
|
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.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.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
|
||||||
|
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.LogTag.LogD
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
class MoListDetailsActivity : MoBaseActivity() {
|
@OptIn(UnstableApi::class)
|
||||||
|
class MoListDetailsActivity : MoBaseActivity(), DetailsListAdapter.OnItemMoreClickListener,
|
||||||
|
DetailsListAdapter.OnItemDownloadClickListener {
|
||||||
private val requests: Channel<Request> = Channel(Channel.UNLIMITED)
|
private val requests: Channel<Request> = Channel(Channel.UNLIMITED)
|
||||||
|
|
||||||
enum class Request {
|
sealed class Request {
|
||||||
TryAgain,
|
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 {
|
companion object {
|
||||||
@ -32,7 +72,8 @@ class MoListDetailsActivity : MoBaseActivity() {
|
|||||||
private var adapter: DetailsListAdapter? = null
|
private var adapter: DetailsListAdapter? = null
|
||||||
private var myList: MutableList<Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean> =
|
private var myList: MutableList<Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean> =
|
||||||
mutableListOf()
|
mutableListOf()
|
||||||
|
private var myBean: Innertube.MoPlaylistOrAlbumPage? = null
|
||||||
|
private var currentPosition = -1
|
||||||
override suspend fun main() {
|
override suspend fun main() {
|
||||||
binding = ActivityDetailsBinding.inflate(layoutInflater)
|
binding = ActivityDetailsBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
@ -44,6 +85,7 @@ class MoListDetailsActivity : MoBaseActivity() {
|
|||||||
}
|
}
|
||||||
initView()
|
initView()
|
||||||
LogD(TAG, "browseId->${browseId}")
|
LogD(TAG, "browseId->${browseId}")
|
||||||
|
initDownloadFlow()
|
||||||
initData(browseId!!)
|
initData(browseId!!)
|
||||||
onReceive()
|
onReceive()
|
||||||
}
|
}
|
||||||
@ -64,6 +106,163 @@ class MoListDetailsActivity : MoBaseActivity() {
|
|||||||
Request.TryAgain -> {
|
Request.TryAgain -> {
|
||||||
initData(browseId!!)
|
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 {
|
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() {
|
private fun initView() {
|
||||||
adapter = DetailsListAdapter(this, myList)
|
adapter = DetailsListAdapter(this, myList)
|
||||||
|
adapter?.setOnItemDownloadClickListener(this)
|
||||||
|
adapter?.setOnItemMoreClickListener(this)
|
||||||
binding.rv.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
|
binding.rv.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
|
||||||
binding.rv.adapter = adapter
|
binding.rv.adapter = adapter
|
||||||
|
|
||||||
@ -122,6 +333,30 @@ class MoListDetailsActivity : MoBaseActivity() {
|
|||||||
startActivity(intent)
|
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")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
@ -131,12 +366,13 @@ class MoListDetailsActivity : MoBaseActivity() {
|
|||||||
if (this.isDestroyed || this.isFinishing) {
|
if (this.isDestroyed || this.isFinishing) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
myBean = it
|
||||||
LogD(TAG, "moPlaylistPage onSuccess->${it.moPlaylistOrAlbumListBean}")
|
LogD(TAG, "moPlaylistPage onSuccess->${it.moPlaylistOrAlbumListBean}")
|
||||||
if (it.moPlaylistOrAlbumListBean.isNotEmpty()) {
|
if (it.moPlaylistOrAlbumListBean.isNotEmpty()) {
|
||||||
showDataUi()
|
showDataUi()
|
||||||
Glide.with(this).load(it.thumbnail).into(binding.imageView)
|
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.subtitle.text = it.subtitle
|
||||||
binding.secondSubtitle.text = it.secondSubtitle
|
binding.secondSubtitle.text = it.secondSubtitle
|
||||||
|
|
||||||
@ -166,4 +402,141 @@ class MoListDetailsActivity : MoBaseActivity() {
|
|||||||
binding.loadingLayout.visibility = View.GONE
|
binding.loadingLayout.visibility = View.GONE
|
||||||
binding.noContentLayout.visibility = View.VISIBLE
|
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<TextView>(R.id.dialog_ok_btn)
|
||||||
|
val cancelBtn = dialogView.findViewById<TextView>(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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -103,13 +103,18 @@ class MoPlaylistSongsActivity : MoBaseActivity() {
|
|||||||
adapter?.notifyDataSetChanged()
|
adapter?.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
LolAdWrapper.shared.loadAdShowNativeAd(
|
try {
|
||||||
this,
|
LolAdWrapper.shared.loadAdShowNativeAd(
|
||||||
AdPlacement.NATIVE_ME_PAGE_LIST,
|
this,
|
||||||
binding.frameAd,
|
AdPlacement.NATIVE_ME_PAGE_LIST,
|
||||||
R.layout.ad_layout_admob_banner,
|
binding.frameAd,
|
||||||
R.layout.ad_layout_max_banner
|
R.layout.ad_layout_admob_banner,
|
||||||
)
|
R.layout.ad_layout_max_banner
|
||||||
|
)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initView() {
|
private fun initView() {
|
||||||
|
|||||||
@ -45,11 +45,23 @@ class DetailsListAdapter(
|
|||||||
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_DESC, bean.name)
|
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_DESC, bean.name)
|
||||||
context.startActivity(intent)
|
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
|
override fun getItemCount(): Int = list.size
|
||||||
|
|
||||||
inner class ViewHolder(private val binding: DetailsListItemBinding) :
|
inner class ViewHolder(val binding: DetailsListItemBinding) :
|
||||||
RecyclerView.ViewHolder(binding.root) {
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
@ -110,4 +122,24 @@ class DetailsListAdapter(
|
|||||||
interface OnItemClickListener {
|
interface OnItemClickListener {
|
||||||
fun onItemClick(position: Int)
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -26,7 +26,7 @@ data class Playlist(
|
|||||||
)
|
)
|
||||||
data class PlaylistItem(
|
data class PlaylistItem(
|
||||||
@PrimaryKey(autoGenerate = true) val id: Int = 0,
|
@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 = "videoId") var videoId: String,
|
||||||
@ColumnInfo(name = "title") var title: String,
|
@ColumnInfo(name = "title") var title: String,
|
||||||
@ColumnInfo(name = "name") var name: String,
|
@ColumnInfo(name = "name") var name: String,
|
||||||
|
|||||||
@ -223,6 +223,7 @@ object Innertube {
|
|||||||
val thumbnail: String?,
|
val thumbnail: String?,
|
||||||
val secondSubtitle: String?,
|
val secondSubtitle: String?,
|
||||||
val description: String?,
|
val description: String?,
|
||||||
|
val singerName: String?,
|
||||||
val moPlaylistOrAlbumListBean: List<MoPlaylistOrAlbumListBean>
|
val moPlaylistOrAlbumListBean: List<MoPlaylistOrAlbumListBean>
|
||||||
) {
|
) {
|
||||||
data class MoPlaylistOrAlbumListBean(
|
data class MoPlaylistOrAlbumListBean(
|
||||||
|
|||||||
@ -30,7 +30,8 @@ data class SectionListRenderer(
|
|||||||
val subtitle: Runs?,
|
val subtitle: Runs?,
|
||||||
val secondSubtitle: Runs?,
|
val secondSubtitle: Runs?,
|
||||||
val thumbnail: ThumbnailRenderer?,
|
val thumbnail: ThumbnailRenderer?,
|
||||||
val description: Description?
|
val description: Description?,
|
||||||
|
val straplineTextOne: Runs?
|
||||||
) {
|
) {
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Description(
|
data class Description(
|
||||||
|
|||||||
@ -102,7 +102,7 @@ suspend fun Innertube.moPlaylistPage(browseId: String): Result<Innertube.MoPlayl
|
|||||||
val bean = Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean(
|
val bean = Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean(
|
||||||
title = runs0?.text,
|
title = runs0?.text,
|
||||||
name = runs1?.text ?: musicResponsiveHeaderRenderer
|
name = runs1?.text ?: musicResponsiveHeaderRenderer
|
||||||
?.subtitle
|
?.straplineTextOne
|
||||||
?.runs
|
?.runs
|
||||||
?.map { it.text }
|
?.map { it.text }
|
||||||
?.joinToString(""),
|
?.joinToString(""),
|
||||||
@ -121,7 +121,15 @@ suspend fun Innertube.moPlaylistPage(browseId: String): Result<Innertube.MoPlayl
|
|||||||
params = watchEndpoint?.params,
|
params = watchEndpoint?.params,
|
||||||
musicVideoType = watchEndpoint?.type,
|
musicVideoType = watchEndpoint?.type,
|
||||||
pageType = browseEndpoint?.type,
|
pageType = browseEndpoint?.type,
|
||||||
thumbnailUrl = thumbnailUrl
|
thumbnailUrl = thumbnailUrl ?: musicResponsiveHeaderRenderer
|
||||||
|
?.thumbnail
|
||||||
|
?.musicThumbnailRenderer
|
||||||
|
?.thumbnail
|
||||||
|
?.thumbnails
|
||||||
|
?.let {
|
||||||
|
it.getOrNull(3) ?: it.getOrNull(2) ?: it.getOrNull(1) ?: it.getOrNull(0)
|
||||||
|
}
|
||||||
|
?.url
|
||||||
)
|
)
|
||||||
|
|
||||||
list.add(bean)
|
list.add(bean)
|
||||||
@ -157,6 +165,11 @@ suspend fun Innertube.moPlaylistPage(browseId: String): Result<Innertube.MoPlayl
|
|||||||
?.musicDescriptionShelfRenderer
|
?.musicDescriptionShelfRenderer
|
||||||
?.description
|
?.description
|
||||||
?.text,
|
?.text,
|
||||||
|
singerName = musicResponsiveHeaderRenderer
|
||||||
|
?.straplineTextOne
|
||||||
|
?.runs
|
||||||
|
?.map { it.text }
|
||||||
|
?.joinToString { "" },
|
||||||
moPlaylistOrAlbumListBean = list
|
moPlaylistOrAlbumListBean = list
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -142,7 +142,7 @@
|
|||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/title"
|
android:id="@+id/info_title"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:fontFamily="@font/medium_font"
|
android:fontFamily="@font/medium_font"
|
||||||
@ -220,9 +220,202 @@
|
|||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
android:orientation="vertical" />
|
android:orientation="vertical" />
|
||||||
|
|
||||||
|
|
||||||
</RelativeLayout>
|
</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"
|
||||||
|
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>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|||||||
@ -94,14 +94,27 @@
|
|||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:id="@+id/downloadBtn"
|
android:id="@+id/downloadBtn"
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:visibility="gone"
|
android:visibility="visible"
|
||||||
android:layout_height="40dp">
|
android:layout_height="40dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
android:src="@drawable/download_gray_icon" />
|
android:src="@drawable/download_icon" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/moreBtn"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:visibility="visible"
|
||||||
|
android:layout_height="40dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:src="@drawable/three_dots_icon" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
184
app/src/main/res/layout/list_more_layout.xml
Normal file
184
app/src/main/res/layout/list_more_layout.xml
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<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"
|
||||||
|
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>
|
||||||
@ -32,6 +32,7 @@
|
|||||||
<string name="download">Download</string>
|
<string name="download">Download</string>
|
||||||
<string name="downloads">Downloads</string>
|
<string name="downloads">Downloads</string>
|
||||||
<string name="library">Library</string>
|
<string name="library">Library</string>
|
||||||
|
<string name="like">Like</string>
|
||||||
<string name="liked_songs">Liked songs</string>
|
<string name="liked_songs">Liked songs</string>
|
||||||
<string name="offline_songs">Offline songs</string>
|
<string name="offline_songs">Offline songs</string>
|
||||||
<string name="songs">Songs</string>
|
<string name="songs">Songs</string>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user