update
This commit is contained in:
parent
8c4629497c
commit
9b91074eeb
@ -62,6 +62,9 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".activity.MoSearchMoreActivity"
|
android:name=".activity.MoSearchMoreActivity"
|
||||||
android:screenOrientation="portrait" />
|
android:screenOrientation="portrait" />
|
||||||
|
<activity
|
||||||
|
android:name=".activity.MoSingerMoreSongActivity"
|
||||||
|
android:screenOrientation="portrait" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".service.PlaybackService"
|
android:name=".service.PlaybackService"
|
||||||
|
|||||||
@ -3,19 +3,19 @@ package com.player.musicoo.activity
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.Color
|
||||||
|
import android.graphics.drawable.ColorDrawable
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.renderscript.Allocation
|
import android.renderscript.Allocation
|
||||||
import android.renderscript.Element
|
import android.renderscript.Element
|
||||||
import android.renderscript.RenderScript
|
import android.renderscript.RenderScript
|
||||||
import android.renderscript.ScriptIntrinsicBlur
|
import android.renderscript.ScriptIntrinsicBlur
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.widget.RelativeLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.bumptech.glide.Glide
|
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.R
|
||||||
import com.player.musicoo.media.MediaControllerManager
|
import com.player.musicoo.media.MediaControllerManager
|
||||||
import com.player.musicoo.sp.AppStore
|
import com.player.musicoo.sp.AppStore
|
||||||
@ -137,15 +137,20 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
|
|||||||
title.text = getString(R.string.description)
|
title.text = getString(R.string.description)
|
||||||
val content = dialogView.findViewById<TextView>(R.id.dialog_content)
|
val content = dialogView.findViewById<TextView>(R.id.dialog_content)
|
||||||
content.text = description
|
content.text = description
|
||||||
val okBtn = dialogView.findViewById<TextView>(R.id.dialog_ok_btn)
|
val close = dialogView.findViewById<RelativeLayout>(R.id.closeBtn)
|
||||||
val dialogBuilder = AlertDialog.Builder(this)
|
val dialogBuilder = AlertDialog.Builder(this)
|
||||||
.setView(dialogView)
|
.setView(dialogView)
|
||||||
val dialog = dialogBuilder.create()
|
val dialog = dialogBuilder.create()
|
||||||
|
dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||||
dialog.show()
|
dialog.show()
|
||||||
okBtn.setOnClickListener {
|
close.setOnClickListener {
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun extractTextBeforeNewline(text: String): String {
|
||||||
|
// 用换行符分割文本,取第一个部分
|
||||||
|
return text.split("\n\n")[0]
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -75,6 +75,10 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
|||||||
if (comeFrom != null && comeFrom == PrimaryActivity::class.java) {
|
if (comeFrom != null && comeFrom == PrimaryActivity::class.java) {
|
||||||
// 处理来自 PrimaryActivity 的情况
|
// 处理来自 PrimaryActivity 的情况
|
||||||
updateCurrentMediaItemInfo()
|
updateCurrentMediaItemInfo()
|
||||||
|
} else {
|
||||||
|
if (meController != null && meController.currentMediaItem != null && videoId == meController.currentMediaItem?.mediaId) {
|
||||||
|
//进入的id与当前的id一样就不重新去获取播放
|
||||||
|
updateCurrentMediaItemInfo()
|
||||||
} else {
|
} else {
|
||||||
binding.nameTv.text = intent.getStringExtra(PLAY_DETAILS_NAME)
|
binding.nameTv.text = intent.getStringExtra(PLAY_DETAILS_NAME)
|
||||||
binding.descTv.text = intent.getStringExtra(PLAY_DETAILS_DESC)
|
binding.descTv.text = intent.getStringExtra(PLAY_DETAILS_DESC)
|
||||||
@ -94,6 +98,8 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
onReceive()
|
onReceive()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +136,8 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
|||||||
binding.playbackErrorLayout.visibility = View.GONE
|
binding.playbackErrorLayout.visibility = View.GONE
|
||||||
binding.loadingView.visibility = View.GONE
|
binding.loadingView.visibility = View.GONE
|
||||||
binding.disableClicksLayout.visibility = View.GONE
|
binding.disableClicksLayout.visibility = View.GONE
|
||||||
val currentString = convertMillisToMinutesAndSecondsString(MediaControllerManager.getCurrentPosition())
|
val currentString =
|
||||||
|
convertMillisToMinutesAndSecondsString(MediaControllerManager.getCurrentPosition())
|
||||||
binding.progressDurationTv.text = currentString
|
binding.progressDurationTv.text = currentString
|
||||||
if (MediaControllerManager.getDuration() > 0) {
|
if (MediaControllerManager.getDuration() > 0) {
|
||||||
binding.totalDurationTv.visibility = View.VISIBLE
|
binding.totalDurationTv.visibility = View.VISIBLE
|
||||||
|
|||||||
@ -83,8 +83,11 @@ class MoSearchMoreActivity : MoBaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Request.MoreData -> {
|
Request.MoreData -> {
|
||||||
LogD(TAG, "Request.MoreData")
|
if (!currentContinuation.isNullOrEmpty()) {
|
||||||
currentContinuation?.let { it1 -> initDataMore(it1) }
|
initDataMore(currentContinuation!!)
|
||||||
|
}else{
|
||||||
|
binding.refreshLayout.finishLoadMoreWithNoMoreData()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,8 +141,10 @@ class MoSearchMoreActivity : MoBaseActivity() {
|
|||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private suspend fun initDataMore(continuation: String) {
|
private suspend fun initDataMore(continuation: String) {
|
||||||
Innertube.moSearchPage(ContinuationBody(continuation = continuation))?.onSuccess { result ->
|
Innertube.moSearchPage(ContinuationBody(continuation = continuation))?.onSuccess { result ->
|
||||||
LogD(TAG, "initDataMore result->$result")
|
|
||||||
currentContinuation = result.continuation
|
currentContinuation = result.continuation
|
||||||
|
if (currentContinuation.isNullOrEmpty()) {
|
||||||
|
binding.refreshLayout.finishLoadMoreWithNoMoreData()
|
||||||
|
}
|
||||||
if (result.searchResultList.isNotEmpty()) {
|
if (result.searchResultList.isNotEmpty()) {
|
||||||
list.addAll(result.searchResultList)
|
list.addAll(result.searchResultList)
|
||||||
if (!isFinishing) {
|
if (!isFinishing) {
|
||||||
@ -147,10 +152,10 @@ class MoSearchMoreActivity : MoBaseActivity() {
|
|||||||
}
|
}
|
||||||
binding.refreshLayout.finishLoadMore(true)
|
binding.refreshLayout.finishLoadMore(true)
|
||||||
} else {
|
} else {
|
||||||
binding.refreshLayout.finishLoadMore(2000, true, false)
|
binding.refreshLayout.finishLoadMoreWithNoMoreData()
|
||||||
}
|
}
|
||||||
}?.onFailure {
|
}?.onFailure {
|
||||||
binding.refreshLayout.finishLoadMore(2000, false, false)
|
binding.refreshLayout.finishLoadMoreWithNoMoreData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,10 @@
|
|||||||
package com.player.musicoo.activity
|
package com.player.musicoo.activity
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
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 com.player.musicoo.adapter.DetailsListAdapter
|
|
||||||
import com.player.musicoo.databinding.ActivityDetailsBinding
|
|
||||||
import com.player.musicoo.databinding.ActivitySingerDetailsBinding
|
import com.player.musicoo.databinding.ActivitySingerDetailsBinding
|
||||||
import com.player.musicoo.fragment.MoHomeFragment
|
|
||||||
import com.player.musicoo.innertube.Innertube
|
import com.player.musicoo.innertube.Innertube
|
||||||
import com.player.musicoo.innertube.requests.moPlaylistPage
|
|
||||||
import com.player.musicoo.innertube.requests.moSingerListPage
|
import com.player.musicoo.innertube.requests.moSingerListPage
|
||||||
import com.player.musicoo.util.LogTag.LogD
|
import com.player.musicoo.util.LogTag.LogD
|
||||||
import com.player.musicoo.view.SingerDetailsOtherView
|
import com.player.musicoo.view.SingerDetailsOtherView
|
||||||
@ -75,6 +70,9 @@ class MoSingerDetailsActivity : MoBaseActivity() {
|
|||||||
binding.tryAgainBtn.setOnClickListener {
|
binding.tryAgainBtn.setOnClickListener {
|
||||||
requests.trySend(Request.TryAgain)
|
requests.trySend(Request.TryAgain)
|
||||||
}
|
}
|
||||||
|
binding.singerDescExpand.setOnClickListener {
|
||||||
|
showSongDescriptionDialog(binding.singerDesc.text.toString())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun initData(browseId: String) {
|
private suspend fun initData(browseId: String) {
|
||||||
@ -86,7 +84,14 @@ class MoSingerDetailsActivity : MoBaseActivity() {
|
|||||||
.load(it.thumbnail)
|
.load(it.thumbnail)
|
||||||
.into(binding.singerImg)
|
.into(binding.singerImg)
|
||||||
binding.singerName.text = it.title
|
binding.singerName.text = it.title
|
||||||
binding.singerDesc.text = it.description
|
if (it.description.isNullOrEmpty()) {
|
||||||
|
binding.singerDesc.visibility = View.GONE
|
||||||
|
binding.singerDescExpand.visibility = View.GONE
|
||||||
|
} else {
|
||||||
|
binding.singerDesc.visibility = View.VISIBLE
|
||||||
|
binding.singerDescExpand.visibility = View.VISIBLE
|
||||||
|
binding.singerDesc.text = extractTextBeforeNewline(it.description)
|
||||||
|
}
|
||||||
if (it.list != null) {
|
if (it.list != null) {
|
||||||
for (bean: Innertube.SingerDetailsListPage in it.list) {
|
for (bean: Innertube.SingerDetailsListPage in it.list) {
|
||||||
if (bean.contents?.musicShelfContentList != null && bean.contents.musicShelfContentList.isNotEmpty()) {
|
if (bean.contents?.musicShelfContentList != null && bean.contents.musicShelfContentList.isNotEmpty()) {
|
||||||
|
|||||||
@ -0,0 +1,170 @@
|
|||||||
|
package com.player.musicoo.activity
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.view.View
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.gyf.immersionbar.ktx.immersionBar
|
||||||
|
import com.player.musicoo.adapter.SingerMoreSongAdapter
|
||||||
|
import com.player.musicoo.databinding.ActivitySearchMoreBinding
|
||||||
|
import com.player.musicoo.innertube.Innertube
|
||||||
|
import com.player.musicoo.innertube.models.bodies.BrowseBody
|
||||||
|
import com.player.musicoo.innertube.models.bodies.ContinuationBody
|
||||||
|
import com.player.musicoo.innertube.requests.moSingerDetailsMoreLoadMorePage
|
||||||
|
import com.player.musicoo.innertube.requests.moSingerDetailsMorePage
|
||||||
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
import kotlinx.coroutines.isActive
|
||||||
|
import kotlinx.coroutines.selects.select
|
||||||
|
|
||||||
|
class MoSingerMoreSongActivity : MoBaseActivity() {
|
||||||
|
private val requests: Channel<Request> = Channel(Channel.UNLIMITED)
|
||||||
|
|
||||||
|
enum class Request {
|
||||||
|
TryAgain,
|
||||||
|
MoreData,
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val SINGER_MORE_SONG_BROWSE_ID = "singer_more_song_browse_id"
|
||||||
|
const val SINGER_MORE_SONG_PARAMS = "singer_more_song_params"
|
||||||
|
const val SINGER_MORE_TYPE = "singer_more_type"
|
||||||
|
}
|
||||||
|
|
||||||
|
private lateinit var binding: ActivitySearchMoreBinding
|
||||||
|
private var browseId: String? = null
|
||||||
|
private var params: String? = null
|
||||||
|
private var type: String? = null
|
||||||
|
private var list: MutableList<Innertube.BaseSingleColumnBrowseSongResults.SingleColumnBrowseSongResults> =
|
||||||
|
mutableListOf()
|
||||||
|
private var currentContinuation: String? = null
|
||||||
|
private var adapter: SingerMoreSongAdapter? = null
|
||||||
|
|
||||||
|
override suspend fun main() {
|
||||||
|
binding = ActivitySearchMoreBinding.inflate(layoutInflater)
|
||||||
|
setContentView(binding.root)
|
||||||
|
browseId = intent.getStringExtra(SINGER_MORE_SONG_BROWSE_ID)
|
||||||
|
params = intent.getStringExtra(SINGER_MORE_SONG_PARAMS)
|
||||||
|
type = intent.getStringExtra(SINGER_MORE_TYPE)
|
||||||
|
if (browseId.isNullOrEmpty() || params.isNullOrEmpty()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
initImmersionBar()
|
||||||
|
initView()
|
||||||
|
initAdapter()
|
||||||
|
initData(browseId!!, params!!)
|
||||||
|
onReceive()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initImmersionBar() {
|
||||||
|
immersionBar {
|
||||||
|
statusBarDarkFont(false)
|
||||||
|
statusBarView(binding.view)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun onReceive() {
|
||||||
|
while (isActive) {
|
||||||
|
select<Unit> {
|
||||||
|
requests.onReceive {
|
||||||
|
when (it) {
|
||||||
|
Request.TryAgain -> {
|
||||||
|
initData(browseId!!, params!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
Request.MoreData -> {
|
||||||
|
if (!currentContinuation.isNullOrEmpty()) {
|
||||||
|
initDataMore(currentContinuation!!)
|
||||||
|
}else{
|
||||||
|
binding.refreshLayout.finishLoadMoreWithNoMoreData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initView() {
|
||||||
|
binding.backBtn.setOnClickListener {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
binding.tryAgainBtn.setOnClickListener {
|
||||||
|
requests.trySend(Request.TryAgain)
|
||||||
|
}
|
||||||
|
binding.refreshLayout.setEnableRefresh(false)
|
||||||
|
binding.refreshLayout.setEnableLoadMore(true)
|
||||||
|
binding.refreshLayout.setOnLoadMoreListener {
|
||||||
|
requests.trySend(Request.MoreData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initAdapter() {
|
||||||
|
adapter = SingerMoreSongAdapter(this, list, type)
|
||||||
|
if (type == "MUSIC_PAGE_TYPE_ARTIST_DISCOGRAPHY") {
|
||||||
|
binding.rv.layoutManager = GridLayoutManager(this, 2)
|
||||||
|
} else {
|
||||||
|
binding.rv.layoutManager =
|
||||||
|
LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
|
||||||
|
}
|
||||||
|
binding.rv.adapter = adapter
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun initData(browseId: String, params: String) {
|
||||||
|
showLoadingUi()
|
||||||
|
Innertube.moSingerDetailsMorePage(BrowseBody(browseId = browseId, params = params))
|
||||||
|
?.onSuccess { result ->
|
||||||
|
showDataUi()
|
||||||
|
val title = result.title
|
||||||
|
if (title.isNullOrEmpty()) {
|
||||||
|
binding.title.visibility = View.GONE
|
||||||
|
} else {
|
||||||
|
binding.title.visibility = View.VISIBLE
|
||||||
|
binding.title.text = title
|
||||||
|
}
|
||||||
|
currentContinuation = result.continuation
|
||||||
|
list.clear()
|
||||||
|
list.addAll(result.songList)
|
||||||
|
|
||||||
|
}?.onFailure {
|
||||||
|
showNoContentUi()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
private suspend fun initDataMore(continuation: String) {
|
||||||
|
Innertube.moSingerDetailsMoreLoadMorePage(ContinuationBody(continuation = continuation))
|
||||||
|
?.onSuccess { result ->
|
||||||
|
currentContinuation = result.continuation
|
||||||
|
if (currentContinuation.isNullOrEmpty()) {
|
||||||
|
binding.refreshLayout.finishLoadMoreWithNoMoreData()
|
||||||
|
}
|
||||||
|
if (result.songList.isNotEmpty()) {
|
||||||
|
list.addAll(result.songList)
|
||||||
|
if (!isFinishing) {
|
||||||
|
adapter?.notifyDataSetChanged()
|
||||||
|
binding.refreshLayout.finishLoadMore(true)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
binding.refreshLayout.finishLoadMoreWithNoMoreData()
|
||||||
|
}
|
||||||
|
}?.onFailure {
|
||||||
|
binding.refreshLayout.finishLoadMoreWithNoMoreData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun showDataUi() {
|
||||||
|
binding.loadingLayout.visibility = View.GONE
|
||||||
|
binding.noContentLayout.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showLoadingUi() {
|
||||||
|
binding.loadingLayout.visibility = View.VISIBLE
|
||||||
|
binding.noContentLayout.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showNoContentUi() {
|
||||||
|
binding.loadingLayout.visibility = View.GONE
|
||||||
|
binding.noContentLayout.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,145 @@
|
|||||||
|
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.media3.common.C
|
||||||
|
import androidx.media3.common.MediaItem
|
||||||
|
import androidx.media3.common.Player
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.player.musicoo.R
|
||||||
|
import com.player.musicoo.activity.MoListDetailsActivity
|
||||||
|
import com.player.musicoo.activity.MoPlayDetailsActivity
|
||||||
|
import com.player.musicoo.activity.MoSingerDetailsActivity
|
||||||
|
import com.player.musicoo.databinding.MusicTowRowItemBinding
|
||||||
|
import com.player.musicoo.databinding.PlayListItemBinding
|
||||||
|
import com.player.musicoo.databinding.SearchResultOtherItemBinding
|
||||||
|
import com.player.musicoo.databinding.SearchResultOtherLayoutBinding
|
||||||
|
import com.player.musicoo.innertube.Innertube
|
||||||
|
import com.player.musicoo.media.MediaControllerManager
|
||||||
|
import com.player.musicoo.util.LogTag
|
||||||
|
|
||||||
|
class SingerMoreSongAdapter(
|
||||||
|
private val context: Context,
|
||||||
|
private val list: List<Innertube.BaseSingleColumnBrowseSongResults.SingleColumnBrowseSongResults>,
|
||||||
|
private val type: String? = null,
|
||||||
|
) :
|
||||||
|
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
|
return when (viewType) {
|
||||||
|
TYPE_ONE -> {
|
||||||
|
val binding =
|
||||||
|
SearchResultOtherItemBinding.inflate(
|
||||||
|
LayoutInflater.from(context),
|
||||||
|
parent,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
ViewHolderOne(binding)
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPE_TWO -> {
|
||||||
|
val binding =
|
||||||
|
MusicTowRowItemBinding.inflate(LayoutInflater.from(context), parent, false)
|
||||||
|
ViewHolderTow(binding)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> throw IllegalArgumentException("Invalid view type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||||
|
val bean = list[position]
|
||||||
|
when (holder.itemViewType) {
|
||||||
|
TYPE_ONE -> {
|
||||||
|
val typeOneHolder = holder as ViewHolderOne
|
||||||
|
typeOneHolder.bind(bean)
|
||||||
|
typeOneHolder.itemView.setOnClickListener {
|
||||||
|
val intent = Intent(context, MoPlayDetailsActivity::class.java)
|
||||||
|
intent.putExtra(
|
||||||
|
MoPlayDetailsActivity.PLAY_DETAILS_VIDEO_ID,
|
||||||
|
bean.videoId
|
||||||
|
)
|
||||||
|
intent.putExtra(
|
||||||
|
MoPlayDetailsActivity.PLAY_DETAILS_PLAY_LIST_ID,
|
||||||
|
bean.playlistId
|
||||||
|
)
|
||||||
|
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_NAME, bean.title)
|
||||||
|
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_DESC, bean.name)
|
||||||
|
context.startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPE_TWO -> {
|
||||||
|
val typeTwoHolder = holder as ViewHolderTow
|
||||||
|
typeTwoHolder.bind(bean)
|
||||||
|
typeTwoHolder.itemView.setOnClickListener {
|
||||||
|
val intent = Intent(context, MoListDetailsActivity::class.java)
|
||||||
|
intent.putExtra(
|
||||||
|
MoListDetailsActivity.PLAY_LIST_PAGE_BROWSE_ID,
|
||||||
|
bean.browseId
|
||||||
|
)
|
||||||
|
context.startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val TYPE_ONE = 1
|
||||||
|
private val TYPE_TWO = 2
|
||||||
|
override fun getItemViewType(position: Int): Int {
|
||||||
|
return if (type == "MUSIC_PAGE_TYPE_ARTIST_DISCOGRAPHY") {
|
||||||
|
TYPE_TWO
|
||||||
|
} else {
|
||||||
|
TYPE_ONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = list.size
|
||||||
|
|
||||||
|
inner class ViewHolderOne(private val binding: SearchResultOtherItemBinding) :
|
||||||
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
fun bind(bean: Innertube.BaseSingleColumnBrowseSongResults.SingleColumnBrowseSongResults) {
|
||||||
|
|
||||||
|
binding.apply {
|
||||||
|
Glide.with(context)
|
||||||
|
.load(bean.thumbnail)
|
||||||
|
.into(image)
|
||||||
|
title.text = bean.title
|
||||||
|
name.text = bean.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class ViewHolderTow(private val binding: MusicTowRowItemBinding) :
|
||||||
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
fun bind(bean: Innertube.BaseSingleColumnBrowseSongResults.SingleColumnBrowseSongResults) {
|
||||||
|
|
||||||
|
binding.apply {
|
||||||
|
Glide.with(context)
|
||||||
|
.load(bean.thumbnail)
|
||||||
|
.into(image)
|
||||||
|
nameTv.text = bean.title
|
||||||
|
descTv.text = bean.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var itemClickListener: OnItemClickListener? = null
|
||||||
|
|
||||||
|
fun setOnItemClickListener(listener: OnItemClickListener) {
|
||||||
|
itemClickListener = listener
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OnItemClickListener {
|
||||||
|
fun onItemClick(position: Int)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
package com.player.musicoo.adapter
|
package com.player.musicoo.adapter
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
@ -8,11 +9,12 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.player.musicoo.activity.MoListDetailsActivity
|
import com.player.musicoo.activity.MoListDetailsActivity
|
||||||
import com.player.musicoo.activity.MoPlayDetailsActivity
|
import com.player.musicoo.activity.MoPlayDetailsActivity
|
||||||
|
import com.player.musicoo.activity.MoSingerDetailsActivity
|
||||||
import com.player.musicoo.databinding.MusicTowRowItemBinding
|
import com.player.musicoo.databinding.MusicTowRowItemBinding
|
||||||
import com.player.musicoo.innertube.models.MusicCarouselShelfRenderer
|
import com.player.musicoo.innertube.models.MusicCarouselShelfRenderer
|
||||||
|
|
||||||
class TowRowListAdapter(
|
class TowRowListAdapter(
|
||||||
private val context: Context,
|
private val context: Activity,
|
||||||
private val list: List<MusicCarouselShelfRenderer.Content>,
|
private val list: List<MusicCarouselShelfRenderer.Content>,
|
||||||
) :
|
) :
|
||||||
RecyclerView.Adapter<TowRowListAdapter.ViewHolder>() {
|
RecyclerView.Adapter<TowRowListAdapter.ViewHolder>() {
|
||||||
@ -35,6 +37,8 @@ class TowRowListAdapter(
|
|||||||
|
|
||||||
val browseId = browseEndpoint?.browseId
|
val browseId = browseEndpoint?.browseId
|
||||||
|
|
||||||
|
val pageType = browseEndpoint?.type
|
||||||
|
|
||||||
val watchEndpoint = bean.musicTwoRowItemRenderer
|
val watchEndpoint = bean.musicTwoRowItemRenderer
|
||||||
?.navigationEndpoint
|
?.navigationEndpoint
|
||||||
?.watchEndpoint
|
?.watchEndpoint
|
||||||
@ -80,6 +84,17 @@ class TowRowListAdapter(
|
|||||||
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_NAME, name)
|
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_NAME, name)
|
||||||
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_DESC, desc)
|
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_DESC, desc)
|
||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
|
} else {
|
||||||
|
if (pageType == "MUSIC_PAGE_TYPE_ARTIST") {
|
||||||
|
val intent = Intent(context, MoSingerDetailsActivity::class.java)
|
||||||
|
intent.putExtra(
|
||||||
|
MoSingerDetailsActivity.SINGER_DETAILS_PAGE_BROWSE_ID,
|
||||||
|
browseId
|
||||||
|
)
|
||||||
|
context.startActivity(intent)
|
||||||
|
if (context is MoSingerDetailsActivity) {
|
||||||
|
context.finish()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
val intent = Intent(context, MoListDetailsActivity::class.java)
|
val intent = Intent(context, MoListDetailsActivity::class.java)
|
||||||
intent.putExtra(MoListDetailsActivity.PLAY_LIST_PAGE_BROWSE_ID, browseId)
|
intent.putExtra(MoListDetailsActivity.PLAY_LIST_PAGE_BROWSE_ID, browseId)
|
||||||
@ -87,6 +102,7 @@ class TowRowListAdapter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int = list.size
|
override fun getItemCount(): Int = list.size
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
package com.player.musicoo.innertube
|
package com.player.musicoo.innertube
|
||||||
|
|
||||||
import com.player.musicoo.innertube.models.MusicCarouselShelfRenderer
|
import com.player.musicoo.innertube.models.MusicCarouselShelfRenderer
|
||||||
import com.player.musicoo.innertube.models.MusicResponsiveListItemRenderer
|
|
||||||
import com.player.musicoo.innertube.models.MusicShelfRenderer
|
import com.player.musicoo.innertube.models.MusicShelfRenderer
|
||||||
import com.player.musicoo.innertube.models.MusicTwoRowItemRenderer
|
import com.player.musicoo.innertube.models.NavigationEndpoint
|
||||||
|
import com.player.musicoo.innertube.models.Runs
|
||||||
|
import com.player.musicoo.innertube.models.Thumbnail
|
||||||
|
import com.player.musicoo.innertube.utils.brotli
|
||||||
|
import com.player.musicoo.util.LogTag
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.client.engine.okhttp.OkHttp
|
import io.ktor.client.engine.okhttp.OkHttp
|
||||||
import io.ktor.client.plugins.BrowserUserAgent
|
import io.ktor.client.plugins.BrowserUserAgent
|
||||||
@ -15,11 +18,6 @@ import io.ktor.client.request.header
|
|||||||
import io.ktor.http.ContentType
|
import io.ktor.http.ContentType
|
||||||
import io.ktor.http.HttpHeaders
|
import io.ktor.http.HttpHeaders
|
||||||
import io.ktor.serialization.kotlinx.json.json
|
import io.ktor.serialization.kotlinx.json.json
|
||||||
import com.player.musicoo.innertube.models.NavigationEndpoint
|
|
||||||
import com.player.musicoo.innertube.models.Runs
|
|
||||||
import com.player.musicoo.innertube.models.Thumbnail
|
|
||||||
import com.player.musicoo.innertube.utils.brotli
|
|
||||||
import com.player.musicoo.util.LogTag
|
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
@ -176,7 +174,10 @@ object Innertube {
|
|||||||
)
|
)
|
||||||
|
|
||||||
data class SingerDetailsListPage(
|
data class SingerDetailsListPage(
|
||||||
|
val pageType: String? = null,
|
||||||
val title: String?,
|
val title: String?,
|
||||||
|
val browseId: String? = null,
|
||||||
|
val params: String? = null,
|
||||||
val contents: SingerDetailsContent?
|
val contents: SingerDetailsContent?
|
||||||
) {
|
) {
|
||||||
data class SingerDetailsContent(
|
data class SingerDetailsContent(
|
||||||
@ -240,6 +241,24 @@ object Innertube {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class BaseSingleColumnBrowseSongResults(
|
||||||
|
val title: String? = null,
|
||||||
|
val continuation: String? = null,
|
||||||
|
val songList: List<SingleColumnBrowseSongResults>
|
||||||
|
) {
|
||||||
|
data class SingleColumnBrowseSongResults(
|
||||||
|
val title: String?,
|
||||||
|
val name: String?,
|
||||||
|
val thumbnail: String?,
|
||||||
|
val videoId: String? = null,
|
||||||
|
val playlistId: String? = null,
|
||||||
|
val browseId: String? = null,
|
||||||
|
val params: String? = null,
|
||||||
|
val pageType: String? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
data class ArtistPage(
|
data class ArtistPage(
|
||||||
val name: String?,
|
val name: String?,
|
||||||
val description: String?,
|
val description: String?,
|
||||||
|
|||||||
@ -34,7 +34,13 @@ data class BrowseResponse(
|
|||||||
@JsonNames("musicVisualHeaderRenderer")
|
@JsonNames("musicVisualHeaderRenderer")
|
||||||
val musicImmersiveHeaderRenderer: MusicImmersiveHeaderRenderer?,
|
val musicImmersiveHeaderRenderer: MusicImmersiveHeaderRenderer?,
|
||||||
val musicDetailHeaderRenderer: MusicDetailHeaderRenderer?,
|
val musicDetailHeaderRenderer: MusicDetailHeaderRenderer?,
|
||||||
|
val musicHeaderRenderer: MusicHeaderRenderer?
|
||||||
) {
|
) {
|
||||||
|
@Serializable
|
||||||
|
data class MusicHeaderRenderer(
|
||||||
|
val title: Runs?
|
||||||
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class MusicDetailHeaderRenderer(
|
data class MusicDetailHeaderRenderer(
|
||||||
val title: Runs?,
|
val title: Runs?,
|
||||||
|
|||||||
@ -2,10 +2,13 @@ package com.player.musicoo.innertube.requests
|
|||||||
|
|
||||||
import com.player.musicoo.innertube.Innertube
|
import com.player.musicoo.innertube.Innertube
|
||||||
import com.player.musicoo.innertube.models.BrowseResponse
|
import com.player.musicoo.innertube.models.BrowseResponse
|
||||||
|
import com.player.musicoo.innertube.models.ContinuationResponse
|
||||||
|
import com.player.musicoo.innertube.models.GridRenderer
|
||||||
import com.player.musicoo.innertube.models.MusicCarouselShelfRenderer
|
import com.player.musicoo.innertube.models.MusicCarouselShelfRenderer
|
||||||
import com.player.musicoo.innertube.models.MusicShelfRenderer
|
import com.player.musicoo.innertube.models.MusicShelfRenderer
|
||||||
import com.player.musicoo.innertube.models.SectionListRenderer
|
import com.player.musicoo.innertube.models.SectionListRenderer
|
||||||
import com.player.musicoo.innertube.models.bodies.BrowseBody
|
import com.player.musicoo.innertube.models.bodies.BrowseBody
|
||||||
|
import com.player.musicoo.innertube.models.bodies.ContinuationBody
|
||||||
import com.player.musicoo.innertube.utils.runCatchingNonCancellable
|
import com.player.musicoo.innertube.utils.runCatchingNonCancellable
|
||||||
import com.player.musicoo.util.LogTag
|
import com.player.musicoo.util.LogTag
|
||||||
import io.ktor.client.call.body
|
import io.ktor.client.call.body
|
||||||
@ -53,6 +56,9 @@ suspend fun Innertube.moSingerListPage(browseId: String): Result<Innertube.Singe
|
|||||||
if (sectionListRendererContents != null) {
|
if (sectionListRendererContents != null) {
|
||||||
for (content: SectionListRenderer.Content in sectionListRendererContents) {
|
for (content: SectionListRenderer.Content in sectionListRendererContents) {
|
||||||
var title = ""
|
var title = ""
|
||||||
|
var browseId = ""
|
||||||
|
var params = ""
|
||||||
|
var pageType = ""
|
||||||
val musicShelfRendererContents: MutableList<MusicShelfRenderer.Content> =
|
val musicShelfRendererContents: MutableList<MusicShelfRenderer.Content> =
|
||||||
mutableListOf()
|
mutableListOf()
|
||||||
val musicCarouselShelfContents: MutableList<MusicCarouselShelfRenderer.Content> =
|
val musicCarouselShelfContents: MutableList<MusicCarouselShelfRenderer.Content> =
|
||||||
@ -64,6 +70,14 @@ suspend fun Innertube.moSingerListPage(browseId: String): Result<Innertube.Singe
|
|||||||
musicShelfRendererContents.clear()
|
musicShelfRendererContents.clear()
|
||||||
musicShelfRendererContents.addAll(content.musicShelfRenderer.contents)
|
musicShelfRendererContents.addAll(content.musicShelfRenderer.contents)
|
||||||
}
|
}
|
||||||
|
val browseEndpoint = content.musicShelfRenderer.title
|
||||||
|
?.runs
|
||||||
|
?.firstOrNull()
|
||||||
|
?.navigationEndpoint
|
||||||
|
?.browseEndpoint
|
||||||
|
|
||||||
|
browseId = browseEndpoint?.browseId ?: ""
|
||||||
|
params = browseEndpoint?.params ?: ""
|
||||||
}
|
}
|
||||||
if (content.musicCarouselShelfRenderer != null) {
|
if (content.musicCarouselShelfRenderer != null) {
|
||||||
title = content.musicCarouselShelfRenderer.header
|
title = content.musicCarouselShelfRenderer.header
|
||||||
@ -75,6 +89,17 @@ suspend fun Innertube.moSingerListPage(browseId: String): Result<Innertube.Singe
|
|||||||
musicCarouselShelfContents.clear()
|
musicCarouselShelfContents.clear()
|
||||||
musicCarouselShelfContents.addAll(content.musicCarouselShelfRenderer.contents)
|
musicCarouselShelfContents.addAll(content.musicCarouselShelfRenderer.contents)
|
||||||
}
|
}
|
||||||
|
val browseEndpoint = content.musicCarouselShelfRenderer.header
|
||||||
|
?.musicCarouselShelfBasicHeaderRenderer
|
||||||
|
?.title
|
||||||
|
?.runs
|
||||||
|
?.firstOrNull()
|
||||||
|
?.navigationEndpoint
|
||||||
|
?.browseEndpoint
|
||||||
|
|
||||||
|
browseId = browseEndpoint?.browseId ?: ""
|
||||||
|
params = browseEndpoint?.params ?: ""
|
||||||
|
pageType = browseEndpoint?.type ?: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
val singerDetailsContent = Innertube.SingerDetailsListPage.SingerDetailsContent(
|
val singerDetailsContent = Innertube.SingerDetailsListPage.SingerDetailsContent(
|
||||||
@ -83,20 +108,13 @@ suspend fun Innertube.moSingerListPage(browseId: String): Result<Innertube.Singe
|
|||||||
)
|
)
|
||||||
|
|
||||||
val singerDetails =
|
val singerDetails =
|
||||||
Innertube.SingerDetailsListPage(title = title, contents = singerDetailsContent)
|
Innertube.SingerDetailsListPage(
|
||||||
|
title = title,
|
||||||
// LogTag.LogD(TAG, "title->${singerDetails.title}")
|
contents = singerDetailsContent,
|
||||||
// LogTag.LogD(
|
browseId = browseId,
|
||||||
// TAG,
|
params = params,
|
||||||
// "musicShelfContentList size->${singerDetails.contents?.musicShelfContentList?.size}"
|
pageType = pageType,
|
||||||
// )
|
)
|
||||||
// LogTag.LogD(
|
|
||||||
// TAG,
|
|
||||||
// "musicCarouselShelfContentList size->${singerDetails.contents?.musicCarouselShelfContentList?.size}"
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// LogTag.LogD(TAG, "--------------------------------------------")
|
|
||||||
|
|
||||||
if (title.isNotEmpty()) {
|
if (title.isNotEmpty()) {
|
||||||
list.add(singerDetails)
|
list.add(singerDetails)
|
||||||
}
|
}
|
||||||
@ -110,3 +128,183 @@ suspend fun Innertube.moSingerListPage(browseId: String): Result<Innertube.Singe
|
|||||||
list
|
list
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
suspend fun Innertube.moSingerDetailsMorePage(body: BrowseBody): Result<Innertube.BaseSingleColumnBrowseSongResults>? =
|
||||||
|
runCatchingNonCancellable {
|
||||||
|
val response = client.post(browse) {
|
||||||
|
setBody(body)
|
||||||
|
}.body<BrowseResponse>()
|
||||||
|
|
||||||
|
val gridRenderer = response.contents
|
||||||
|
?.singleColumnBrowseResultsRenderer
|
||||||
|
?.tabs?.firstOrNull()
|
||||||
|
?.tabRenderer
|
||||||
|
?.content
|
||||||
|
?.sectionListRenderer
|
||||||
|
?.contents
|
||||||
|
?.firstOrNull()
|
||||||
|
?.gridRenderer
|
||||||
|
|
||||||
|
|
||||||
|
val musicPlaylistShelfRenderer = response.contents
|
||||||
|
?.singleColumnBrowseResultsRenderer
|
||||||
|
?.tabs
|
||||||
|
?.firstOrNull()
|
||||||
|
?.tabRenderer
|
||||||
|
?.content
|
||||||
|
?.sectionListRenderer
|
||||||
|
?.contents
|
||||||
|
?.firstOrNull()
|
||||||
|
?.musicShelfRenderer
|
||||||
|
|
||||||
|
val title = response.header?.musicHeaderRenderer?.title?.text
|
||||||
|
val continuation = musicPlaylistShelfRenderer
|
||||||
|
?.continuations
|
||||||
|
?.firstOrNull()
|
||||||
|
?.nextContinuationData
|
||||||
|
?.continuation
|
||||||
|
|
||||||
|
val songList: MutableList<Innertube.BaseSingleColumnBrowseSongResults.SingleColumnBrowseSongResults> =
|
||||||
|
mutableListOf()
|
||||||
|
|
||||||
|
val contentList = musicPlaylistShelfRenderer?.contents
|
||||||
|
val contentGridItems = gridRenderer?.items
|
||||||
|
if (contentList != null) {
|
||||||
|
for (content: MusicShelfRenderer.Content in contentList) {
|
||||||
|
val contentTitle = content.musicResponsiveListItemRenderer
|
||||||
|
?.flexColumns
|
||||||
|
?.firstOrNull()
|
||||||
|
?.musicResponsiveListItemFlexColumnRenderer
|
||||||
|
?.text?.text
|
||||||
|
|
||||||
|
val name = content.musicResponsiveListItemRenderer
|
||||||
|
?.flexColumns
|
||||||
|
?.get(1)
|
||||||
|
?.musicResponsiveListItemFlexColumnRenderer
|
||||||
|
?.text?.text
|
||||||
|
|
||||||
|
val thumbnail = content.musicResponsiveListItemRenderer
|
||||||
|
?.thumbnail
|
||||||
|
?.musicThumbnailRenderer
|
||||||
|
?.thumbnail
|
||||||
|
?.thumbnails?.let {
|
||||||
|
it.getOrNull(2) ?: it.getOrNull(1) ?: it.getOrNull(0)
|
||||||
|
}?.url
|
||||||
|
|
||||||
|
val navigationEndpoint = content.musicResponsiveListItemRenderer
|
||||||
|
?.flexColumns
|
||||||
|
?.firstOrNull()
|
||||||
|
?.musicResponsiveListItemFlexColumnRenderer
|
||||||
|
?.text
|
||||||
|
?.runs
|
||||||
|
?.firstOrNull()
|
||||||
|
?.navigationEndpoint
|
||||||
|
|
||||||
|
val videoId = navigationEndpoint?.watchEndpoint?.videoId
|
||||||
|
val playlistId = navigationEndpoint?.watchEndpoint?.playlistId
|
||||||
|
|
||||||
|
|
||||||
|
songList.add(
|
||||||
|
Innertube.BaseSingleColumnBrowseSongResults.SingleColumnBrowseSongResults(
|
||||||
|
title = contentTitle,
|
||||||
|
name = name,
|
||||||
|
thumbnail = thumbnail,
|
||||||
|
videoId = videoId,
|
||||||
|
playlistId = playlistId
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (contentGridItems != null) {
|
||||||
|
for (content: GridRenderer.Item in contentGridItems) {
|
||||||
|
songList.add(
|
||||||
|
Innertube.BaseSingleColumnBrowseSongResults.SingleColumnBrowseSongResults(
|
||||||
|
title = content.musicTwoRowItemRenderer?.title?.runs?.firstOrNull()?.text,
|
||||||
|
name = content.musicTwoRowItemRenderer?.subtitle?.text,
|
||||||
|
thumbnail = content.musicTwoRowItemRenderer
|
||||||
|
?.thumbnailRenderer
|
||||||
|
?.musicThumbnailRenderer
|
||||||
|
?.thumbnail
|
||||||
|
?.thumbnails?.let {
|
||||||
|
it.getOrNull(2) ?: it.getOrNull(1) ?: it.getOrNull(0)
|
||||||
|
}?.url,
|
||||||
|
browseId = content.musicTwoRowItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId,
|
||||||
|
params = content.musicTwoRowItemRenderer?.navigationEndpoint?.browseEndpoint?.params,
|
||||||
|
pageType = content.musicTwoRowItemRenderer?.navigationEndpoint?.browseEndpoint?.type
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Innertube.BaseSingleColumnBrowseSongResults(
|
||||||
|
title = title,
|
||||||
|
songList = songList,
|
||||||
|
continuation = continuation
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun Innertube.moSingerDetailsMoreLoadMorePage(body: ContinuationBody): Result<Innertube.BaseSingleColumnBrowseSongResults>? =
|
||||||
|
runCatchingNonCancellable {
|
||||||
|
val response = client.post(browse) {
|
||||||
|
setBody(body)
|
||||||
|
}.body<ContinuationResponse>()
|
||||||
|
|
||||||
|
val continuation = response.continuationContents
|
||||||
|
?.musicShelfContinuation
|
||||||
|
?.continuations
|
||||||
|
?.firstOrNull()
|
||||||
|
?.nextContinuationData
|
||||||
|
?.continuation
|
||||||
|
|
||||||
|
val songList: MutableList<Innertube.BaseSingleColumnBrowseSongResults.SingleColumnBrowseSongResults> =
|
||||||
|
mutableListOf()
|
||||||
|
|
||||||
|
val contentList = response.continuationContents?.musicShelfContinuation?.contents
|
||||||
|
if (contentList != null) {
|
||||||
|
for (content: MusicShelfRenderer.Content in contentList) {
|
||||||
|
val title = content.musicResponsiveListItemRenderer
|
||||||
|
?.flexColumns
|
||||||
|
?.firstOrNull()
|
||||||
|
?.musicResponsiveListItemFlexColumnRenderer
|
||||||
|
?.text?.text
|
||||||
|
|
||||||
|
val name = content.musicResponsiveListItemRenderer
|
||||||
|
?.flexColumns
|
||||||
|
?.get(1)
|
||||||
|
?.musicResponsiveListItemFlexColumnRenderer
|
||||||
|
?.text?.text
|
||||||
|
|
||||||
|
val thumbnail = content.musicResponsiveListItemRenderer
|
||||||
|
?.thumbnail
|
||||||
|
?.musicThumbnailRenderer
|
||||||
|
?.thumbnail
|
||||||
|
?.thumbnails?.let {
|
||||||
|
it.getOrNull(2) ?: it.getOrNull(1) ?: it.getOrNull(0)
|
||||||
|
}?.url
|
||||||
|
|
||||||
|
val navigationEndpoint = content.musicResponsiveListItemRenderer
|
||||||
|
?.flexColumns
|
||||||
|
?.firstOrNull()
|
||||||
|
?.musicResponsiveListItemFlexColumnRenderer
|
||||||
|
?.text
|
||||||
|
?.runs
|
||||||
|
?.firstOrNull()
|
||||||
|
?.navigationEndpoint
|
||||||
|
|
||||||
|
val videoId = navigationEndpoint?.watchEndpoint?.videoId
|
||||||
|
val playlistId = navigationEndpoint?.watchEndpoint?.playlistId
|
||||||
|
|
||||||
|
|
||||||
|
songList.add(
|
||||||
|
Innertube.BaseSingleColumnBrowseSongResults.SingleColumnBrowseSongResults(
|
||||||
|
title, name, thumbnail, videoId, playlistId
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Innertube.BaseSingleColumnBrowseSongResults(
|
||||||
|
continuation = continuation,
|
||||||
|
songList = songList
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
package com.player.musicoo.view
|
package com.player.musicoo.view
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
@ -12,7 +13,7 @@ import com.player.musicoo.adapter.TowRowListAdapter
|
|||||||
import com.player.musicoo.innertube.Innertube
|
import com.player.musicoo.innertube.Innertube
|
||||||
|
|
||||||
@SuppressLint("ViewConstructor")
|
@SuppressLint("ViewConstructor")
|
||||||
class MusicTowRowListView(context: Context, homePage: Innertube.HomePage) : ModuleView(context) {
|
class MusicTowRowListView(context: Activity, homePage: Innertube.HomePage) : ModuleView(context) {
|
||||||
init {
|
init {
|
||||||
contentView = inflate(getContext(), R.layout.music_list_layout, this)
|
contentView = inflate(getContext(), R.layout.music_list_layout, this)
|
||||||
val title = contentView?.findViewById<TextView>(R.id.title)
|
val title = contentView?.findViewById<TextView>(R.id.title)
|
||||||
|
|||||||
@ -1,21 +1,50 @@
|
|||||||
package com.player.musicoo.view
|
package com.player.musicoo.view
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.player.musicoo.R
|
import com.player.musicoo.R
|
||||||
|
import com.player.musicoo.activity.MoSearchMoreActivity
|
||||||
|
import com.player.musicoo.activity.MoSingerMoreSongActivity
|
||||||
import com.player.musicoo.adapter.TowRowListAdapter
|
import com.player.musicoo.adapter.TowRowListAdapter
|
||||||
import com.player.musicoo.innertube.Innertube
|
import com.player.musicoo.innertube.Innertube
|
||||||
|
|
||||||
@SuppressLint("ViewConstructor")
|
@SuppressLint("ViewConstructor")
|
||||||
class SingerDetailsOtherView (context: Context, bean: Innertube.SingerDetailsListPage) :
|
class SingerDetailsOtherView(context: Activity, bean: Innertube.SingerDetailsListPage) :
|
||||||
ModuleView(context) {
|
ModuleView(context) {
|
||||||
init {
|
init {
|
||||||
contentView = inflate(getContext(), R.layout.singer_music_list_layout, this)
|
contentView = inflate(getContext(), R.layout.singer_music_list_layout, this)
|
||||||
val title = contentView?.findViewById<TextView>(R.id.title)
|
val title = contentView?.findViewById<TextView>(R.id.title)
|
||||||
title?.text = bean.title
|
title?.text = bean.title
|
||||||
|
val moreBtn = contentView?.findViewById<LinearLayout>(R.id.moreBtn)
|
||||||
|
moreBtn?.setOnClickListener {
|
||||||
|
val intent = Intent(context, MoSingerMoreSongActivity::class.java)
|
||||||
|
intent.putExtra(
|
||||||
|
MoSingerMoreSongActivity.SINGER_MORE_SONG_BROWSE_ID,
|
||||||
|
bean.browseId
|
||||||
|
)
|
||||||
|
intent.putExtra(MoSingerMoreSongActivity.SINGER_MORE_SONG_PARAMS, bean.params)
|
||||||
|
intent.putExtra(MoSingerMoreSongActivity.SINGER_MORE_TYPE, bean.pageType)
|
||||||
|
context.startActivity(intent)
|
||||||
|
}
|
||||||
|
when (bean.pageType) {
|
||||||
|
"MUSIC_PAGE_TYPE_ARTIST_DISCOGRAPHY" -> {
|
||||||
|
moreBtn?.visibility = VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
"MUSIC_PAGE_TYPE_PLAYLIST" -> {
|
||||||
|
moreBtn?.visibility = VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
moreBtn?.visibility = GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val rv = contentView?.findViewById<RecyclerView>(R.id.rv)
|
val rv = contentView?.findViewById<RecyclerView>(R.id.rv)
|
||||||
|
|
||||||
|
|||||||
@ -2,11 +2,14 @@ package com.player.musicoo.view
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.player.musicoo.R
|
import com.player.musicoo.R
|
||||||
|
import com.player.musicoo.activity.MoSingerMoreSongActivity
|
||||||
import com.player.musicoo.adapter.SingerDetailsSongListAdapter
|
import com.player.musicoo.adapter.SingerDetailsSongListAdapter
|
||||||
import com.player.musicoo.innertube.Innertube
|
import com.player.musicoo.innertube.Innertube
|
||||||
|
|
||||||
@ -18,6 +21,14 @@ class SingerDetailsSongView(context: Context, bean: Innertube.SingerDetailsListP
|
|||||||
val title = contentView?.findViewById<TextView>(R.id.title)
|
val title = contentView?.findViewById<TextView>(R.id.title)
|
||||||
title?.text = bean.title
|
title?.text = bean.title
|
||||||
|
|
||||||
|
val moreBtn = contentView?.findViewById<LinearLayout>(R.id.moreBtn)
|
||||||
|
moreBtn?.setOnClickListener {
|
||||||
|
val intent = Intent(context, MoSingerMoreSongActivity::class.java)
|
||||||
|
intent.putExtra(MoSingerMoreSongActivity.SINGER_MORE_SONG_BROWSE_ID, bean.browseId)
|
||||||
|
intent.putExtra(MoSingerMoreSongActivity.SINGER_MORE_SONG_PARAMS, bean.params)
|
||||||
|
context.startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
val rv = contentView?.findViewById<RecyclerView>(R.id.rv)
|
val rv = contentView?.findViewById<RecyclerView>(R.id.rv)
|
||||||
|
|
||||||
val adapter = SingerDetailsSongListAdapter(context, bean.contents?.musicShelfContentList!!)
|
val adapter = SingerDetailsSongListAdapter(context, bean.contents?.musicShelfContentList!!)
|
||||||
|
|||||||
8
app/src/main/res/drawable/drw_dialog_bg.xml
Normal file
8
app/src/main/res/drawable/drw_dialog_bg.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
|
||||||
|
<solid android:color="@color/main_bg_color" />
|
||||||
|
<corners android:radius="16dp" />
|
||||||
|
|
||||||
|
</shape>
|
||||||
@ -54,10 +54,10 @@
|
|||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
android:indeterminateTint="@color/green"
|
android:indeterminateTint="@color/green"
|
||||||
android:progressBackgroundTint="@color/green"
|
android:progressBackgroundTint="@color/green"
|
||||||
android:progressTint="@color/green"
|
android:progressTint="@color/green" />
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -176,10 +176,13 @@
|
|||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/rv"
|
android:id="@+id/rv"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:scrollbars="none"
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
android:overScrollMode="never"
|
android:overScrollMode="never"
|
||||||
android:layout_height="wrap_content"
|
android:scrollbars="none" />
|
||||||
android:layout_margin="16dp" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@ -118,9 +118,7 @@
|
|||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:overScrollMode="never"
|
android:overScrollMode="never"
|
||||||
android:scrollbars="none"
|
android:scrollbars="none" />
|
||||||
tools:itemCount="10"
|
|
||||||
tools:listitem="@layout/music_responsive_item" />
|
|
||||||
|
|
||||||
<com.scwang.smart.refresh.footer.BallPulseFooter
|
<com.scwang.smart.refresh.footer.BallPulseFooter
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:paddingBottom="12dp"
|
android:paddingTop="12dp"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
|
|||||||
@ -1,29 +1,29 @@
|
|||||||
<!-- custom_dialog_layout.xml -->
|
<!-- custom_dialog_layout.xml -->
|
||||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout 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_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:padding="16dp"
|
||||||
android:elevation="0dp"
|
android:layout_height="wrap_content">
|
||||||
android:orientation="vertical"
|
|
||||||
app:cardCornerRadius="16dp"
|
|
||||||
app:cardElevation="0dp">
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
android:background="@drawable/drw_dialog_bg"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/main_bg_color"
|
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="16dp">
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical">
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="56dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="56dp"
|
android:layout_height="48dp"
|
||||||
android:src="@mipmap/musicoo_logo_img" />
|
android:src="@mipmap/musicoo_logo_img" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -38,19 +38,41 @@
|
|||||||
android:textSize="16dp" />
|
android:textSize="16dp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/closeBtn"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_alignParentEnd="true">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:src="@drawable/cha_icon" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginBottom="16dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/dialog_content"
|
android:id="@+id/dialog_content"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
android:fontFamily="@font/regular_font"
|
android:fontFamily="@font/regular_font"
|
||||||
android:text="@string/app_name"
|
android:text="@string/app_name"
|
||||||
android:textColor="@color/white_60"
|
android:textColor="@color/white_60"
|
||||||
android:textSize="14dp" />
|
android:textSize="14dp" />
|
||||||
|
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
android:visibility="gone"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:gravity="center_vertical">
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
@ -88,4 +110,4 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.cardview.widget.CardView>
|
</LinearLayout>
|
||||||
|
|||||||
@ -6,9 +6,14 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:ignore="MissingDefaultResource">
|
tools:ignore="MissingDefaultResource">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/title"
|
android:id="@+id/title"
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
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"
|
||||||
@ -16,6 +21,29 @@
|
|||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:textSize="18dp" />
|
android:textSize="18dp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/moreBtn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/regular_font"
|
||||||
|
android:text="@string/more"
|
||||||
|
android:textColor="@color/white_60"
|
||||||
|
android:textSize="12dp" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="16dp"
|
||||||
|
android:layout_height="16dp"
|
||||||
|
android:rotation="270"
|
||||||
|
android:src="@drawable/arrow_bottom_grey_icon" />
|
||||||
|
</LinearLayout>
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/rv"
|
android:id="@+id/rv"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user