update
This commit is contained in:
parent
8f15461f14
commit
830ad770eb
@ -47,6 +47,9 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".activity.AboutActivity"
|
android:name=".activity.AboutActivity"
|
||||||
android:screenOrientation="portrait" />
|
android:screenOrientation="portrait" />
|
||||||
|
<activity
|
||||||
|
android:name=".activity.DetailsActivity"
|
||||||
|
android:screenOrientation="portrait" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".service.PlaybackService"
|
android:name=".service.PlaybackService"
|
||||||
|
|||||||
@ -0,0 +1,67 @@
|
|||||||
|
package com.player.musicoo.activity
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.gyf.immersionbar.ktx.immersionBar
|
||||||
|
import com.player.musicoo.adapter.DetailsListAdapter
|
||||||
|
import com.player.musicoo.databinding.ActivityDetailsBinding
|
||||||
|
import com.player.musicoo.innertube.Innertube
|
||||||
|
import com.player.musicoo.innertube.requests.moPlaylistPage
|
||||||
|
|
||||||
|
class DetailsActivity : MoBaseActivity() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PLAY_LIST_PAGE_BROWSE_ID = "play_list_page_browse_id"
|
||||||
|
}
|
||||||
|
|
||||||
|
private lateinit var binding: ActivityDetailsBinding
|
||||||
|
|
||||||
|
override suspend fun main() {
|
||||||
|
binding = ActivityDetailsBinding.inflate(layoutInflater)
|
||||||
|
setContentView(binding.root)
|
||||||
|
initImmersionBar()
|
||||||
|
val browseId = intent.getStringExtra(PLAY_LIST_PAGE_BROWSE_ID)
|
||||||
|
if (browseId.isNullOrEmpty() || browseId == "null") {
|
||||||
|
finish()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
initView()
|
||||||
|
Log.d(TAG, "browseId->${browseId}")
|
||||||
|
initData(browseId)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initImmersionBar() {
|
||||||
|
immersionBar {
|
||||||
|
statusBarDarkFont(false)
|
||||||
|
statusBarView(binding.view)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initView() {
|
||||||
|
binding.backBtn.setOnClickListener {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun initData(browseId: String) {
|
||||||
|
Innertube.moPlaylistPage(browseId)
|
||||||
|
?.onSuccess {
|
||||||
|
Glide.with(this)
|
||||||
|
.load(it.thumbnail)
|
||||||
|
.into(binding.imageView)
|
||||||
|
|
||||||
|
binding.title.text = it.title
|
||||||
|
binding.subtitle.text = it.subtitle
|
||||||
|
binding.secondSubtitle.text = it.secondSubtitle
|
||||||
|
|
||||||
|
val adapter = DetailsListAdapter(this, it.moPlaylistOrAlbumListBean)
|
||||||
|
binding.rv.layoutManager =
|
||||||
|
LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
|
||||||
|
binding.rv.adapter = adapter
|
||||||
|
|
||||||
|
}?.onFailure {
|
||||||
|
Log.d(TAG, "moPlaylistPage onFailure->${it}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,15 +1,33 @@
|
|||||||
package com.player.musicoo.activity
|
package com.player.musicoo.activity
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.renderscript.Allocation
|
||||||
|
import android.renderscript.Element
|
||||||
|
import android.renderscript.RenderScript
|
||||||
|
import android.renderscript.ScriptIntrinsicBlur
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.bumptech.glide.request.target.CustomTarget
|
||||||
|
import com.bumptech.glide.request.transition.Transition
|
||||||
|
import com.player.musicoo.R
|
||||||
import com.player.musicoo.sp.AppStore
|
import com.player.musicoo.sp.AppStore
|
||||||
import com.player.musicoo.util.LogTag
|
import com.player.musicoo.util.LogTag
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
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.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope() {
|
abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope() {
|
||||||
|
|
||||||
@ -70,4 +88,63 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun loadBitmapWithGlide(imageUrl: String): Bitmap? {
|
||||||
|
return withContext(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
Glide.with(this@MoBaseActivity)
|
||||||
|
.asBitmap()
|
||||||
|
.load(imageUrl)
|
||||||
|
.submit() // 异步加载Bitmap
|
||||||
|
.get() // 阻塞等待获取Bitmap
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun applyGaussianBlur(inputBitmap: Bitmap, radius: Float, context: Context): Bitmap {
|
||||||
|
val rsContext = RenderScript.create(context)
|
||||||
|
val outputBitmap =
|
||||||
|
Bitmap.createBitmap(inputBitmap.width, inputBitmap.height, inputBitmap.config)
|
||||||
|
val blurScript = ScriptIntrinsicBlur.create(rsContext, Element.U8_4(rsContext))
|
||||||
|
val tmpIn = Allocation.createFromBitmap(rsContext, inputBitmap)
|
||||||
|
val tmpOut = Allocation.createFromBitmap(rsContext, outputBitmap)
|
||||||
|
blurScript.setRadius(radius)
|
||||||
|
blurScript.setInput(tmpIn)
|
||||||
|
blurScript.forEach(tmpOut)
|
||||||
|
tmpOut.copyTo(outputBitmap)
|
||||||
|
rsContext.finish()
|
||||||
|
return outputBitmap
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadBitmapFromAsset(id: Int): Bitmap {
|
||||||
|
return try {
|
||||||
|
val inputStream: InputStream = resources.openRawResource(id)
|
||||||
|
BitmapFactory.decodeStream(inputStream)
|
||||||
|
} catch (e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
throw RuntimeException("Could not load bitmap from asset")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showSongDescriptionDialog(description: String) {
|
||||||
|
val inflater = LayoutInflater.from(this)
|
||||||
|
val dialogView = inflater.inflate(R.layout.dialog_description, null)
|
||||||
|
val title = dialogView.findViewById<TextView>(R.id.dialog_title)
|
||||||
|
title.text = getString(R.string.description)
|
||||||
|
val content = dialogView.findViewById<TextView>(R.id.dialog_content)
|
||||||
|
content.text = description
|
||||||
|
val okBtn = dialogView.findViewById<TextView>(R.id.dialog_ok_btn)
|
||||||
|
val dialogBuilder = AlertDialog.Builder(this)
|
||||||
|
.setView(dialogView)
|
||||||
|
val dialog = dialogBuilder.create()
|
||||||
|
dialog.show()
|
||||||
|
okBtn.setOnClickListener {
|
||||||
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
package com.player.musicoo.adapter
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.player.musicoo.App
|
||||||
|
import com.player.musicoo.R
|
||||||
|
import com.player.musicoo.activity.PlayDetailsActivity
|
||||||
|
import com.player.musicoo.bean.Audio
|
||||||
|
import com.player.musicoo.databinding.DetailsListItemBinding
|
||||||
|
import com.player.musicoo.databinding.MusicResponsiveItemBinding
|
||||||
|
import com.player.musicoo.databinding.SoundsOfAppliancesLayoutBinding
|
||||||
|
import com.player.musicoo.databinding.SoundsOfNatureLayoutBinding
|
||||||
|
import com.player.musicoo.innertube.Innertube
|
||||||
|
import com.player.musicoo.innertube.models.MusicCarouselShelfRenderer
|
||||||
|
import com.player.musicoo.util.convertMillisToMinutesAndSecondsString
|
||||||
|
import com.player.musicoo.util.getAudioDurationFromAssets
|
||||||
|
|
||||||
|
class DetailsListAdapter(
|
||||||
|
private val context: Context,
|
||||||
|
private val list: List<Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean>,
|
||||||
|
) :
|
||||||
|
RecyclerView.Adapter<DetailsListAdapter.ViewHolder>() {
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
val binding = DetailsListItemBinding.inflate(LayoutInflater.from(context), parent, false)
|
||||||
|
return ViewHolder(binding)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
val bean = list[position]
|
||||||
|
holder.bind(bean)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = list.size
|
||||||
|
|
||||||
|
inner class ViewHolder(private val binding: DetailsListItemBinding) :
|
||||||
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
fun bind(bean: Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean) {
|
||||||
|
|
||||||
|
binding.apply {
|
||||||
|
if (!bean.thumbnailUrl.isNullOrEmpty()) {
|
||||||
|
image.visibility = View.VISIBLE
|
||||||
|
Glide.with(context)
|
||||||
|
.load(bean.thumbnailUrl)
|
||||||
|
.into(image)
|
||||||
|
sortTv.visibility = View.GONE
|
||||||
|
} else {
|
||||||
|
image.visibility = View.GONE
|
||||||
|
sortTv.visibility = View.VISIBLE
|
||||||
|
sortTv.text = "${bindingAdapterPosition + 1}"
|
||||||
|
}
|
||||||
|
|
||||||
|
title.text = bean.title
|
||||||
|
if (bean.name.isNullOrEmpty()) {
|
||||||
|
name.visibility = View.GONE
|
||||||
|
} else {
|
||||||
|
name.visibility = View.VISIBLE
|
||||||
|
name.text = bean.name
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var itemClickListener: OnItemClickListener? = null
|
||||||
|
|
||||||
|
fun setOnItemClickListener(listener: OnItemClickListener) {
|
||||||
|
itemClickListener = listener
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OnItemClickListener {
|
||||||
|
fun onItemClick(position: Int)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@ package com.player.musicoo.adapter
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@ -9,6 +10,7 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.player.musicoo.App
|
import com.player.musicoo.App
|
||||||
import com.player.musicoo.R
|
import com.player.musicoo.R
|
||||||
|
import com.player.musicoo.activity.DetailsActivity
|
||||||
import com.player.musicoo.activity.PlayDetailsActivity
|
import com.player.musicoo.activity.PlayDetailsActivity
|
||||||
import com.player.musicoo.bean.Audio
|
import com.player.musicoo.bean.Audio
|
||||||
import com.player.musicoo.databinding.MusicResponsiveItemBinding
|
import com.player.musicoo.databinding.MusicResponsiveItemBinding
|
||||||
@ -16,6 +18,7 @@ import com.player.musicoo.databinding.MusicTowRowItemBinding
|
|||||||
import com.player.musicoo.databinding.SoundsOfAppliancesLayoutBinding
|
import com.player.musicoo.databinding.SoundsOfAppliancesLayoutBinding
|
||||||
import com.player.musicoo.databinding.SoundsOfNatureLayoutBinding
|
import com.player.musicoo.databinding.SoundsOfNatureLayoutBinding
|
||||||
import com.player.musicoo.innertube.models.MusicCarouselShelfRenderer
|
import com.player.musicoo.innertube.models.MusicCarouselShelfRenderer
|
||||||
|
import com.player.musicoo.util.LogTag
|
||||||
import com.player.musicoo.util.convertMillisToMinutesAndSecondsString
|
import com.player.musicoo.util.convertMillisToMinutesAndSecondsString
|
||||||
import com.player.musicoo.util.getAudioDurationFromAssets
|
import com.player.musicoo.util.getAudioDurationFromAssets
|
||||||
|
|
||||||
@ -33,7 +36,23 @@ class TowRowListAdapter(
|
|||||||
|
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
val bean = list[position]
|
val bean = list[position]
|
||||||
|
|
||||||
|
val browseEndpoint = bean.musicTwoRowItemRenderer
|
||||||
|
?.title
|
||||||
|
?.runs
|
||||||
|
?.firstOrNull()
|
||||||
|
?.navigationEndpoint
|
||||||
|
?.browseEndpoint
|
||||||
|
|
||||||
|
val browseId = browseEndpoint?.browseId
|
||||||
|
|
||||||
holder.bind(bean)
|
holder.bind(bean)
|
||||||
|
|
||||||
|
holder.itemView.setOnClickListener {
|
||||||
|
val intent = Intent(context, DetailsActivity::class.java)
|
||||||
|
intent.putExtra(DetailsActivity.PLAY_LIST_PAGE_BROWSE_ID, browseId)
|
||||||
|
context.startActivity(intent)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int = list.size
|
override fun getItemCount(): Int = list.size
|
||||||
|
|||||||
@ -177,6 +177,28 @@ object Innertube {
|
|||||||
val contents: List<MusicCarouselShelfRenderer.Content>
|
val contents: List<MusicCarouselShelfRenderer.Content>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class MoPlaylistOrAlbumPage(
|
||||||
|
val title: String?,
|
||||||
|
val subtitle: String?,
|
||||||
|
val thumbnail: String?,
|
||||||
|
val secondSubtitle: String?,
|
||||||
|
val description: String?,
|
||||||
|
val moPlaylistOrAlbumListBean: List<MoPlaylistOrAlbumListBean>
|
||||||
|
) {
|
||||||
|
data class MoPlaylistOrAlbumListBean(
|
||||||
|
val title: String?,
|
||||||
|
val name: String?,
|
||||||
|
val desc: String?,
|
||||||
|
val timeText: String?,
|
||||||
|
val browseId: String,
|
||||||
|
val videoId: String?,
|
||||||
|
val playlistId: String?,
|
||||||
|
val musicVideoType: String?,
|
||||||
|
val pageType: String?,
|
||||||
|
val thumbnailUrl: String?
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
data class ArtistPage(
|
data class ArtistPage(
|
||||||
val name: String?,
|
val name: String?,
|
||||||
val description: String?,
|
val description: String?,
|
||||||
|
|||||||
@ -41,6 +41,7 @@ data class BrowseResponse(
|
|||||||
val subtitle: Runs?,
|
val subtitle: Runs?,
|
||||||
val secondSubtitle: Runs?,
|
val secondSubtitle: Runs?,
|
||||||
val thumbnail: ThumbnailRenderer?,
|
val thumbnail: ThumbnailRenderer?,
|
||||||
|
val description: Runs?
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
|||||||
@ -0,0 +1,135 @@
|
|||||||
|
package com.player.musicoo.innertube.requests
|
||||||
|
|
||||||
|
import com.player.musicoo.innertube.Innertube
|
||||||
|
import com.player.musicoo.innertube.models.BrowseResponse
|
||||||
|
import com.player.musicoo.innertube.models.MusicShelfRenderer
|
||||||
|
import com.player.musicoo.innertube.models.bodies.BrowseBody
|
||||||
|
import com.player.musicoo.innertube.utils.runCatchingNonCancellable
|
||||||
|
import io.ktor.client.call.body
|
||||||
|
import io.ktor.client.request.post
|
||||||
|
import io.ktor.client.request.setBody
|
||||||
|
|
||||||
|
suspend fun Innertube.moPlaylistPage(browseId: String): Result<Innertube.MoPlaylistOrAlbumPage>? =
|
||||||
|
runCatchingNonCancellable {
|
||||||
|
val response = client.post(browse) {
|
||||||
|
setBody(BrowseBody(browseId = browseId))
|
||||||
|
}.body<BrowseResponse>()
|
||||||
|
|
||||||
|
|
||||||
|
val musicDetailHeaderRenderer = response
|
||||||
|
.header
|
||||||
|
?.musicDetailHeaderRenderer
|
||||||
|
|
||||||
|
val sectionListRendererContents = response
|
||||||
|
.contents
|
||||||
|
?.singleColumnBrowseResultsRenderer
|
||||||
|
?.tabs
|
||||||
|
?.firstOrNull()
|
||||||
|
?.tabRenderer
|
||||||
|
?.content
|
||||||
|
?.sectionListRenderer
|
||||||
|
?.contents
|
||||||
|
|
||||||
|
val musicShelfRenderer = sectionListRendererContents
|
||||||
|
?.firstOrNull()
|
||||||
|
?.musicShelfRenderer
|
||||||
|
|
||||||
|
val musicCarouselShelfRenderer = sectionListRendererContents
|
||||||
|
?.getOrNull(1)
|
||||||
|
?.musicCarouselShelfRenderer
|
||||||
|
|
||||||
|
val list: MutableList<Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean> =
|
||||||
|
mutableListOf()
|
||||||
|
list.clear()
|
||||||
|
val contents = musicShelfRenderer?.contents
|
||||||
|
if (contents != null) {
|
||||||
|
for (content: MusicShelfRenderer.Content in contents) {
|
||||||
|
val runs0 = content.musicResponsiveListItemRenderer
|
||||||
|
?.flexColumns
|
||||||
|
?.getOrNull(0)
|
||||||
|
?.musicResponsiveListItemFlexColumnRenderer
|
||||||
|
?.text
|
||||||
|
?.runs
|
||||||
|
?.firstOrNull()
|
||||||
|
val watchEndpoint = runs0?.navigationEndpoint?.watchEndpoint
|
||||||
|
val runs1 = content.musicResponsiveListItemRenderer
|
||||||
|
?.flexColumns
|
||||||
|
?.getOrNull(1)
|
||||||
|
?.musicResponsiveListItemFlexColumnRenderer
|
||||||
|
?.text
|
||||||
|
?.runs
|
||||||
|
?.firstOrNull()
|
||||||
|
val browseEndpoint = runs1?.navigationEndpoint?.browseEndpoint
|
||||||
|
|
||||||
|
val runs2 = content.musicResponsiveListItemRenderer
|
||||||
|
?.flexColumns
|
||||||
|
?.getOrNull(2)
|
||||||
|
?.musicResponsiveListItemFlexColumnRenderer
|
||||||
|
?.text
|
||||||
|
?.runs
|
||||||
|
?.firstOrNull()
|
||||||
|
|
||||||
|
val thumbnailUrl = content.musicResponsiveListItemRenderer
|
||||||
|
?.thumbnail
|
||||||
|
?.musicThumbnailRenderer
|
||||||
|
?.thumbnail
|
||||||
|
?.thumbnails
|
||||||
|
?.firstOrNull()
|
||||||
|
?.url
|
||||||
|
|
||||||
|
|
||||||
|
val bean = Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean(
|
||||||
|
title = runs0?.text,
|
||||||
|
name = runs1?.text,
|
||||||
|
desc = runs2?.text,
|
||||||
|
timeText = content.musicResponsiveListItemRenderer
|
||||||
|
?.fixedColumns?.firstOrNull()
|
||||||
|
?.musicResponsiveListItemFlexColumnRenderer
|
||||||
|
?.text
|
||||||
|
?.runs
|
||||||
|
?.firstOrNull()
|
||||||
|
?.text,
|
||||||
|
browseId = browseEndpoint?.browseId.toString(),
|
||||||
|
videoId = watchEndpoint?.videoId,
|
||||||
|
playlistId = watchEndpoint?.playlistId,
|
||||||
|
musicVideoType = watchEndpoint?.type,
|
||||||
|
pageType = browseEndpoint?.type,
|
||||||
|
thumbnailUrl = thumbnailUrl
|
||||||
|
)
|
||||||
|
|
||||||
|
list.add(bean)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Innertube.MoPlaylistOrAlbumPage(
|
||||||
|
title = musicDetailHeaderRenderer
|
||||||
|
?.title
|
||||||
|
?.runs
|
||||||
|
?.firstOrNull()
|
||||||
|
?.text,
|
||||||
|
subtitle = musicDetailHeaderRenderer
|
||||||
|
?.subtitle
|
||||||
|
?.runs
|
||||||
|
?.map { it.text }
|
||||||
|
?.joinToString(""),
|
||||||
|
thumbnail = musicDetailHeaderRenderer
|
||||||
|
?.thumbnail
|
||||||
|
?.musicThumbnailRenderer
|
||||||
|
?.thumbnail
|
||||||
|
?.thumbnails
|
||||||
|
?.let { it.getOrNull(3) ?: it.getOrNull(2) ?: it.getOrNull(1) ?: it.getOrNull(0) }
|
||||||
|
?.url,
|
||||||
|
secondSubtitle = musicDetailHeaderRenderer
|
||||||
|
?.secondSubtitle
|
||||||
|
?.runs
|
||||||
|
?.map { it.text }
|
||||||
|
?.joinToString(""),
|
||||||
|
description = musicDetailHeaderRenderer
|
||||||
|
?.description
|
||||||
|
?.runs
|
||||||
|
?.firstOrNull()
|
||||||
|
?.text,
|
||||||
|
moPlaylistOrAlbumListBean = list
|
||||||
|
)
|
||||||
|
}
|
||||||
122
app/src/main/res/layout/activity_details.xml
Normal file
122
app/src/main/res/layout/activity_details.xml
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/main_bg_color"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:src="@mipmap/settings_bg_img" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/title_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/view"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/back_btn"
|
||||||
|
android:layout_width="42dp"
|
||||||
|
android:layout_height="42dp"
|
||||||
|
android:background="@drawable/drw_back_bg">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:src="@drawable/back_icon" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_below="@+id/title_layout"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
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:cardCornerRadius="10dp"
|
||||||
|
app:cardElevation="0dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imageView"
|
||||||
|
android:layout_width="160dp"
|
||||||
|
android:layout_height="160dp"
|
||||||
|
android:src="@mipmap/musicoo_logo_img" />
|
||||||
|
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/medium_font"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="18dp" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/subtitle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:fontFamily="@font/medium_font"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:text="@string/ready_to_sleep"
|
||||||
|
android:textColor="@color/white_60"
|
||||||
|
android:textSize="12dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/secondSubtitle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="2dp"
|
||||||
|
android:fontFamily="@font/regular_font"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textColor="@color/white_60"
|
||||||
|
android:textSize="12dp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rv"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="16dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
80
app/src/main/res/layout/details_list_item.xml
Normal file
80
app/src/main/res/layout/details_list_item.xml
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:ignore="MissingDefaultResource">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:paddingBottom="12dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="16dp">
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:elevation="0dp"
|
||||||
|
android:visibility="visible"
|
||||||
|
app:cardCornerRadius="4dp"
|
||||||
|
app:cardElevation="0dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/image"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:src="@mipmap/musicoo_logo_img" />
|
||||||
|
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/sort_tv"
|
||||||
|
android:layout_width="22dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:fontFamily="@font/medium_font"
|
||||||
|
android:text="1"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="16dp" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.player.musicoo.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" />
|
||||||
|
|
||||||
|
<com.player.musicoo.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>
|
||||||
|
</LinearLayout>
|
||||||
91
app/src/main/res/layout/dialog_description.xml
Normal file
91
app/src/main/res/layout/dialog_description.xml
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<!-- custom_dialog_layout.xml -->
|
||||||
|
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:elevation="0dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:cardCornerRadius="16dp"
|
||||||
|
app:cardElevation="0dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/main_bg_color"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="56dp"
|
||||||
|
android:layout_height="56dp"
|
||||||
|
android:src="@mipmap/musicoo_logo_img" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/dialog_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:fontFamily="@font/medium_font"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="16dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/dialog_content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:fontFamily="@font/regular_font"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textColor="@color/white_60"
|
||||||
|
android:textSize="14dp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/dialog_cancel_btn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:fontFamily="@font/medium_font"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
android:text="@string/cancel"
|
||||||
|
android:textColor="@color/white_60"
|
||||||
|
android:textSize="16dp"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/dialog_ok_btn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:fontFamily="@font/medium_font"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
android:text="@string/ok"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="16dp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
@ -4,6 +4,7 @@
|
|||||||
<color name="black_60">#99000000</color>
|
<color name="black_60">#99000000</color>
|
||||||
<color name="white">#FFFFFFFF</color>
|
<color name="white">#FFFFFFFF</color>
|
||||||
<color name="white_60">#99FFFFFF</color>
|
<color name="white_60">#99FFFFFF</color>
|
||||||
|
<color name="white_80">#CCFFFFFF</color>
|
||||||
<color name="main_bg_color">#151718</color>
|
<color name="main_bg_color">#151718</color>
|
||||||
<color name="green">#FF80F988</color>
|
<color name="green">#FF80F988</color>
|
||||||
</resources>
|
</resources>
|
||||||
@ -16,4 +16,6 @@
|
|||||||
<string name="terms_of_service">Terms of Service</string>
|
<string name="terms_of_service">Terms of Service</string>
|
||||||
<string name="listen_music_anytime">Listen Music Anytime</string>
|
<string name="listen_music_anytime">Listen Music Anytime</string>
|
||||||
<string name="resource_loading">Resource Loading…</string>
|
<string name="resource_loading">Resource Loading…</string>
|
||||||
|
<string name="expand">EXPAND</string>
|
||||||
|
<string name="description">Description</string>
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
Reference in New Issue
Block a user