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.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<LinearLayout>(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()
|
||||
}
|
||||
|
||||
}
|
||||
@ -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<Request> = 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<Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean> =
|
||||
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<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()
|
||||
}
|
||||
|
||||
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() {
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
@ -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,
|
||||
|
||||
@ -223,6 +223,7 @@ object Innertube {
|
||||
val thumbnail: String?,
|
||||
val secondSubtitle: String?,
|
||||
val description: String?,
|
||||
val singerName: String?,
|
||||
val moPlaylistOrAlbumListBean: List<MoPlaylistOrAlbumListBean>
|
||||
) {
|
||||
data class MoPlaylistOrAlbumListBean(
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -102,7 +102,7 @@ suspend fun Innertube.moPlaylistPage(browseId: String): Result<Innertube.MoPlayl
|
||||
val bean = Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean(
|
||||
title = runs0?.text,
|
||||
name = runs1?.text ?: musicResponsiveHeaderRenderer
|
||||
?.subtitle
|
||||
?.straplineTextOne
|
||||
?.runs
|
||||
?.map { it.text }
|
||||
?.joinToString(""),
|
||||
@ -121,7 +121,15 @@ suspend fun Innertube.moPlaylistPage(browseId: String): Result<Innertube.MoPlayl
|
||||
params = watchEndpoint?.params,
|
||||
musicVideoType = watchEndpoint?.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)
|
||||
@ -157,6 +165,11 @@ suspend fun Innertube.moPlaylistPage(browseId: String): Result<Innertube.MoPlayl
|
||||
?.musicDescriptionShelfRenderer
|
||||
?.description
|
||||
?.text,
|
||||
singerName = musicResponsiveHeaderRenderer
|
||||
?.straplineTextOne
|
||||
?.runs
|
||||
?.map { it.text }
|
||||
?.joinToString { "" },
|
||||
moPlaylistOrAlbumListBean = list
|
||||
)
|
||||
}
|
||||
@ -142,7 +142,7 @@
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:id="@+id/info_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/medium_font"
|
||||
@ -220,9 +220,202 @@
|
||||
android:layout_alignParentBottom="true"
|
||||
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_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>
|
||||
|
||||
|
||||
@ -94,14 +94,27 @@
|
||||
<RelativeLayout
|
||||
android:id="@+id/downloadBtn"
|
||||
android:layout_width="40dp"
|
||||
android:visibility="gone"
|
||||
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/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>
|
||||
|
||||
</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="downloads">Downloads</string>
|
||||
<string name="library">Library</string>
|
||||
<string name="like">Like</string>
|
||||
<string name="liked_songs">Liked songs</string>
|
||||
<string name="offline_songs">Offline songs</string>
|
||||
<string name="songs">Songs</string>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user