From 9b91074eebdaf64cc22e48d03dd613d880a0466b Mon Sep 17 00:00:00 2001 From: ocean <503259349@qq.com> Date: Thu, 16 May 2024 11:37:58 +0800 Subject: [PATCH] update --- app/src/main/AndroidManifest.xml | 3 + .../player/musicoo/activity/MoBaseActivity.kt | 15 +- .../musicoo/activity/MoPlayDetailsActivity.kt | 37 +-- .../musicoo/activity/MoSearchMoreActivity.kt | 15 +- .../activity/MoSingerDetailsActivity.kt | 17 +- .../activity/MoSingerMoreSongActivity.kt | 170 +++++++++++++ .../musicoo/adapter/SingerMoreSongAdapter.kt | 145 +++++++++++ .../musicoo/adapter/TowRowListAdapter.kt | 24 +- .../com/player/musicoo/innertube/Innertube.kt | 33 ++- .../innertube/models/BrowseResponse.kt | 8 +- .../innertube/requests/MoSingerlistPage.kt | 226 ++++++++++++++++-- .../musicoo/view/MusicTowRowListView.kt | 3 +- .../musicoo/view/SingerDetailsOtherView.kt | 31 ++- .../musicoo/view/SingerDetailsSongView.kt | 11 + app/src/main/res/drawable/drw_dialog_bg.xml | 8 + app/src/main/res/layout/activity_details.xml | 13 +- .../main/res/layout/activity_search_more.xml | 4 +- app/src/main/res/layout/details_list_item.xml | 2 +- .../main/res/layout/dialog_description.xml | 88 ++++--- .../res/layout/singer_music_list_layout.xml | 46 +++- 20 files changed, 789 insertions(+), 110 deletions(-) create mode 100644 app/src/main/java/com/player/musicoo/activity/MoSingerMoreSongActivity.kt create mode 100644 app/src/main/java/com/player/musicoo/adapter/SingerMoreSongAdapter.kt create mode 100644 app/src/main/res/drawable/drw_dialog_bg.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0ac0368..0f751ca 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -62,6 +62,9 @@ + (R.id.dialog_content) content.text = description - val okBtn = dialogView.findViewById(R.id.dialog_ok_btn) + val close = dialogView.findViewById(R.id.closeBtn) val dialogBuilder = AlertDialog.Builder(this) .setView(dialogView) val dialog = dialogBuilder.create() + dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) dialog.show() - okBtn.setOnClickListener { + close.setOnClickListener { dialog.dismiss() } } + fun extractTextBeforeNewline(text: String): String { + // 用换行符分割文本,取第一个部分 + return text.split("\n\n")[0] + } } \ No newline at end of file diff --git a/app/src/main/java/com/player/musicoo/activity/MoPlayDetailsActivity.kt b/app/src/main/java/com/player/musicoo/activity/MoPlayDetailsActivity.kt index 017929b..e9454a5 100644 --- a/app/src/main/java/com/player/musicoo/activity/MoPlayDetailsActivity.kt +++ b/app/src/main/java/com/player/musicoo/activity/MoPlayDetailsActivity.kt @@ -76,22 +76,28 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener { // 处理来自 PrimaryActivity 的情况 updateCurrentMediaItemInfo() } else { - binding.nameTv.text = intent.getStringExtra(PLAY_DETAILS_NAME) - binding.descTv.text = intent.getStringExtra(PLAY_DETAILS_DESC) + if (meController != null && meController.currentMediaItem != null && videoId == meController.currentMediaItem?.mediaId) { + //进入的id与当前的id一样就不重新去获取播放 + updateCurrentMediaItemInfo() + } else { + binding.nameTv.text = intent.getStringExtra(PLAY_DETAILS_NAME) + binding.descTv.text = intent.getStringExtra(PLAY_DETAILS_DESC) - if (videoId.isNullOrEmpty()) { - finish() - return + if (videoId.isNullOrEmpty()) { + finish() + return + } + //传入进来的ID,就是进入此界面的当前ID + currentVideoID = videoId + //根据进来界面的当前ID来获取资源。 + initData( + videoId, + playlistId, + playlistSetVideoId, + params + ) } - //传入进来的ID,就是进入此界面的当前ID - currentVideoID = videoId - //根据进来界面的当前ID来获取资源。 - initData( - videoId, - playlistId, - playlistSetVideoId, - params - ) + } onReceive() @@ -130,7 +136,8 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener { binding.playbackErrorLayout.visibility = View.GONE binding.loadingView.visibility = View.GONE binding.disableClicksLayout.visibility = View.GONE - val currentString = convertMillisToMinutesAndSecondsString(MediaControllerManager.getCurrentPosition()) + val currentString = + convertMillisToMinutesAndSecondsString(MediaControllerManager.getCurrentPosition()) binding.progressDurationTv.text = currentString if (MediaControllerManager.getDuration() > 0) { binding.totalDurationTv.visibility = View.VISIBLE diff --git a/app/src/main/java/com/player/musicoo/activity/MoSearchMoreActivity.kt b/app/src/main/java/com/player/musicoo/activity/MoSearchMoreActivity.kt index 6da55e2..d3e1a60 100644 --- a/app/src/main/java/com/player/musicoo/activity/MoSearchMoreActivity.kt +++ b/app/src/main/java/com/player/musicoo/activity/MoSearchMoreActivity.kt @@ -83,8 +83,11 @@ class MoSearchMoreActivity : MoBaseActivity() { } Request.MoreData -> { - LogD(TAG, "Request.MoreData") - currentContinuation?.let { it1 -> initDataMore(it1) } + if (!currentContinuation.isNullOrEmpty()) { + initDataMore(currentContinuation!!) + }else{ + binding.refreshLayout.finishLoadMoreWithNoMoreData() + } } } } @@ -138,8 +141,10 @@ class MoSearchMoreActivity : MoBaseActivity() { @SuppressLint("NotifyDataSetChanged") private suspend fun initDataMore(continuation: String) { Innertube.moSearchPage(ContinuationBody(continuation = continuation))?.onSuccess { result -> - LogD(TAG, "initDataMore result->$result") currentContinuation = result.continuation + if (currentContinuation.isNullOrEmpty()) { + binding.refreshLayout.finishLoadMoreWithNoMoreData() + } if (result.searchResultList.isNotEmpty()) { list.addAll(result.searchResultList) if (!isFinishing) { @@ -147,10 +152,10 @@ class MoSearchMoreActivity : MoBaseActivity() { } binding.refreshLayout.finishLoadMore(true) } else { - binding.refreshLayout.finishLoadMore(2000, true, false) + binding.refreshLayout.finishLoadMoreWithNoMoreData() } }?.onFailure { - binding.refreshLayout.finishLoadMore(2000, false, false) + binding.refreshLayout.finishLoadMoreWithNoMoreData() } } diff --git a/app/src/main/java/com/player/musicoo/activity/MoSingerDetailsActivity.kt b/app/src/main/java/com/player/musicoo/activity/MoSingerDetailsActivity.kt index 0402d4a..d2f72c9 100644 --- a/app/src/main/java/com/player/musicoo/activity/MoSingerDetailsActivity.kt +++ b/app/src/main/java/com/player/musicoo/activity/MoSingerDetailsActivity.kt @@ -1,15 +1,10 @@ package com.player.musicoo.activity import android.view.View -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.databinding.ActivitySingerDetailsBinding -import com.player.musicoo.fragment.MoHomeFragment import com.player.musicoo.innertube.Innertube -import com.player.musicoo.innertube.requests.moPlaylistPage import com.player.musicoo.innertube.requests.moSingerListPage import com.player.musicoo.util.LogTag.LogD import com.player.musicoo.view.SingerDetailsOtherView @@ -75,6 +70,9 @@ class MoSingerDetailsActivity : MoBaseActivity() { binding.tryAgainBtn.setOnClickListener { requests.trySend(Request.TryAgain) } + binding.singerDescExpand.setOnClickListener { + showSongDescriptionDialog(binding.singerDesc.text.toString()) + } } private suspend fun initData(browseId: String) { @@ -86,7 +84,14 @@ class MoSingerDetailsActivity : MoBaseActivity() { .load(it.thumbnail) .into(binding.singerImg) 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) { for (bean: Innertube.SingerDetailsListPage in it.list) { if (bean.contents?.musicShelfContentList != null && bean.contents.musicShelfContentList.isNotEmpty()) { diff --git a/app/src/main/java/com/player/musicoo/activity/MoSingerMoreSongActivity.kt b/app/src/main/java/com/player/musicoo/activity/MoSingerMoreSongActivity.kt new file mode 100644 index 0000000..bb59c7b --- /dev/null +++ b/app/src/main/java/com/player/musicoo/activity/MoSingerMoreSongActivity.kt @@ -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 = 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 = + 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 { + 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 + } +} \ No newline at end of file diff --git a/app/src/main/java/com/player/musicoo/adapter/SingerMoreSongAdapter.kt b/app/src/main/java/com/player/musicoo/adapter/SingerMoreSongAdapter.kt new file mode 100644 index 0000000..4b1588a --- /dev/null +++ b/app/src/main/java/com/player/musicoo/adapter/SingerMoreSongAdapter.kt @@ -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, + private val type: String? = null, +) : + RecyclerView.Adapter() { + + 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) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/player/musicoo/adapter/TowRowListAdapter.kt b/app/src/main/java/com/player/musicoo/adapter/TowRowListAdapter.kt index 982d00a..fafc948 100644 --- a/app/src/main/java/com/player/musicoo/adapter/TowRowListAdapter.kt +++ b/app/src/main/java/com/player/musicoo/adapter/TowRowListAdapter.kt @@ -1,5 +1,6 @@ package com.player.musicoo.adapter +import android.app.Activity import android.content.Context import android.content.Intent import android.view.LayoutInflater @@ -8,11 +9,12 @@ import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide 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.innertube.models.MusicCarouselShelfRenderer class TowRowListAdapter( - private val context: Context, + private val context: Activity, private val list: List, ) : RecyclerView.Adapter() { @@ -35,6 +37,8 @@ class TowRowListAdapter( val browseId = browseEndpoint?.browseId + val pageType = browseEndpoint?.type + val watchEndpoint = bean.musicTwoRowItemRenderer ?.navigationEndpoint ?.watchEndpoint @@ -81,9 +85,21 @@ class TowRowListAdapter( intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_DESC, desc) context.startActivity(intent) } else { - val intent = Intent(context, MoListDetailsActivity::class.java) - intent.putExtra(MoListDetailsActivity.PLAY_LIST_PAGE_BROWSE_ID, browseId) - context.startActivity(intent) + 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 { + val intent = Intent(context, MoListDetailsActivity::class.java) + intent.putExtra(MoListDetailsActivity.PLAY_LIST_PAGE_BROWSE_ID, browseId) + context.startActivity(intent) + } } } } diff --git a/app/src/main/java/com/player/musicoo/innertube/Innertube.kt b/app/src/main/java/com/player/musicoo/innertube/Innertube.kt index 999e40a..4b5e1e5 100644 --- a/app/src/main/java/com/player/musicoo/innertube/Innertube.kt +++ b/app/src/main/java/com/player/musicoo/innertube/Innertube.kt @@ -1,9 +1,12 @@ package com.player.musicoo.innertube 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.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.engine.okhttp.OkHttp 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.HttpHeaders 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.json.Json @@ -176,7 +174,10 @@ object Innertube { ) data class SingerDetailsListPage( + val pageType: String? = null, val title: String?, + val browseId: String? = null, + val params: String? = null, val contents: SingerDetailsContent? ) { data class SingerDetailsContent( @@ -240,6 +241,24 @@ object Innertube { ) } + data class BaseSingleColumnBrowseSongResults( + val title: String? = null, + val continuation: String? = null, + val songList: List + ) { + 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( val name: String?, val description: String?, diff --git a/app/src/main/java/com/player/musicoo/innertube/models/BrowseResponse.kt b/app/src/main/java/com/player/musicoo/innertube/models/BrowseResponse.kt index 227ebf7..7fbd014 100644 --- a/app/src/main/java/com/player/musicoo/innertube/models/BrowseResponse.kt +++ b/app/src/main/java/com/player/musicoo/innertube/models/BrowseResponse.kt @@ -26,7 +26,7 @@ data class BrowseResponse( @Serializable data class ContinuationContents( - val sectionListContinuation : SectionListContinuation? + val sectionListContinuation: SectionListContinuation? ) @Serializable @@ -34,7 +34,13 @@ data class BrowseResponse( @JsonNames("musicVisualHeaderRenderer") val musicImmersiveHeaderRenderer: MusicImmersiveHeaderRenderer?, val musicDetailHeaderRenderer: MusicDetailHeaderRenderer?, + val musicHeaderRenderer: MusicHeaderRenderer? ) { + @Serializable + data class MusicHeaderRenderer( + val title: Runs? + ) + @Serializable data class MusicDetailHeaderRenderer( val title: Runs?, diff --git a/app/src/main/java/com/player/musicoo/innertube/requests/MoSingerlistPage.kt b/app/src/main/java/com/player/musicoo/innertube/requests/MoSingerlistPage.kt index 2586c31..8f7d4d2 100644 --- a/app/src/main/java/com/player/musicoo/innertube/requests/MoSingerlistPage.kt +++ b/app/src/main/java/com/player/musicoo/innertube/requests/MoSingerlistPage.kt @@ -2,10 +2,13 @@ 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.ContinuationResponse +import com.player.musicoo.innertube.models.GridRenderer import com.player.musicoo.innertube.models.MusicCarouselShelfRenderer import com.player.musicoo.innertube.models.MusicShelfRenderer import com.player.musicoo.innertube.models.SectionListRenderer 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.util.LogTag import io.ktor.client.call.body @@ -53,6 +56,9 @@ suspend fun Innertube.moSingerListPage(browseId: String): Result = mutableListOf() val musicCarouselShelfContents: MutableList = @@ -64,6 +70,14 @@ suspend fun Innertube.moSingerListPage(browseId: String): Result${singerDetails.title}") -// LogTag.LogD( -// TAG, -// "musicShelfContentList size->${singerDetails.contents?.musicShelfContentList?.size}" -// ) -// LogTag.LogD( -// TAG, -// "musicCarouselShelfContentList size->${singerDetails.contents?.musicCarouselShelfContentList?.size}" -// ) -// -// LogTag.LogD(TAG, "--------------------------------------------") - + Innertube.SingerDetailsListPage( + title = title, + contents = singerDetailsContent, + browseId = browseId, + params = params, + pageType = pageType, + ) if (title.isNotEmpty()) { list.add(singerDetails) } @@ -109,4 +127,184 @@ suspend fun Innertube.moSingerListPage(browseId: String): Result? = + runCatchingNonCancellable { + val response = client.post(browse) { + setBody(body) + }.body() + + 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 = + 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? = + runCatchingNonCancellable { + val response = client.post(browse) { + setBody(body) + }.body() + + val continuation = response.continuationContents + ?.musicShelfContinuation + ?.continuations + ?.firstOrNull() + ?.nextContinuationData + ?.continuation + + val songList: MutableList = + 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 + ) } \ No newline at end of file diff --git a/app/src/main/java/com/player/musicoo/view/MusicTowRowListView.kt b/app/src/main/java/com/player/musicoo/view/MusicTowRowListView.kt index 8c1d6d7..5817ea9 100644 --- a/app/src/main/java/com/player/musicoo/view/MusicTowRowListView.kt +++ b/app/src/main/java/com/player/musicoo/view/MusicTowRowListView.kt @@ -1,6 +1,7 @@ package com.player.musicoo.view import android.annotation.SuppressLint +import android.app.Activity import android.content.Context import android.widget.TextView import androidx.recyclerview.widget.GridLayoutManager @@ -12,7 +13,7 @@ import com.player.musicoo.adapter.TowRowListAdapter import com.player.musicoo.innertube.Innertube @SuppressLint("ViewConstructor") -class MusicTowRowListView(context: Context, homePage: Innertube.HomePage) : ModuleView(context) { +class MusicTowRowListView(context: Activity, homePage: Innertube.HomePage) : ModuleView(context) { init { contentView = inflate(getContext(), R.layout.music_list_layout, this) val title = contentView?.findViewById(R.id.title) diff --git a/app/src/main/java/com/player/musicoo/view/SingerDetailsOtherView.kt b/app/src/main/java/com/player/musicoo/view/SingerDetailsOtherView.kt index ac89771..93554e4 100644 --- a/app/src/main/java/com/player/musicoo/view/SingerDetailsOtherView.kt +++ b/app/src/main/java/com/player/musicoo/view/SingerDetailsOtherView.kt @@ -1,21 +1,50 @@ package com.player.musicoo.view import android.annotation.SuppressLint +import android.app.Activity import android.content.Context +import android.content.Intent +import android.widget.LinearLayout import android.widget.TextView import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView 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.innertube.Innertube @SuppressLint("ViewConstructor") -class SingerDetailsOtherView (context: Context, bean: Innertube.SingerDetailsListPage) : +class SingerDetailsOtherView(context: Activity, bean: Innertube.SingerDetailsListPage) : ModuleView(context) { init { contentView = inflate(getContext(), R.layout.singer_music_list_layout, this) val title = contentView?.findViewById(R.id.title) title?.text = bean.title + val moreBtn = contentView?.findViewById(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(R.id.rv) diff --git a/app/src/main/java/com/player/musicoo/view/SingerDetailsSongView.kt b/app/src/main/java/com/player/musicoo/view/SingerDetailsSongView.kt index 07899f1..8c4e0c6 100644 --- a/app/src/main/java/com/player/musicoo/view/SingerDetailsSongView.kt +++ b/app/src/main/java/com/player/musicoo/view/SingerDetailsSongView.kt @@ -2,11 +2,14 @@ package com.player.musicoo.view import android.annotation.SuppressLint import android.content.Context +import android.content.Intent +import android.widget.LinearLayout import android.widget.TextView import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.player.musicoo.R +import com.player.musicoo.activity.MoSingerMoreSongActivity import com.player.musicoo.adapter.SingerDetailsSongListAdapter import com.player.musicoo.innertube.Innertube @@ -18,6 +21,14 @@ class SingerDetailsSongView(context: Context, bean: Innertube.SingerDetailsListP val title = contentView?.findViewById(R.id.title) title?.text = bean.title + val moreBtn = contentView?.findViewById(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(R.id.rv) val adapter = SingerDetailsSongListAdapter(context, bean.contents?.musicShelfContentList!!) diff --git a/app/src/main/res/drawable/drw_dialog_bg.xml b/app/src/main/res/drawable/drw_dialog_bg.xml new file mode 100644 index 0000000..0350839 --- /dev/null +++ b/app/src/main/res/drawable/drw_dialog_bg.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_details.xml b/app/src/main/res/layout/activity_details.xml index 62eac86..478b2f7 100644 --- a/app/src/main/res/layout/activity_details.xml +++ b/app/src/main/res/layout/activity_details.xml @@ -54,10 +54,10 @@ + android:progressTint="@color/green" /> @@ -176,10 +176,13 @@ + android:scrollbars="none" /> diff --git a/app/src/main/res/layout/activity_search_more.xml b/app/src/main/res/layout/activity_search_more.xml index 87ee8ee..28a7897 100644 --- a/app/src/main/res/layout/activity_search_more.xml +++ b/app/src/main/res/layout/activity_search_more.xml @@ -118,9 +118,7 @@ android:layout_marginStart="16dp" android:layout_marginEnd="16dp" android:overScrollMode="never" - android:scrollbars="none" - tools:itemCount="10" - tools:listitem="@layout/music_responsive_item" /> + android:scrollbars="none" /> - + android:padding="16dp" + android:layout_height="wrap_content"> - - - - - + android:gravity="center_vertical"> - + + + + + + + + + + + + + android:layout_marginBottom="16dp"> + + + + @@ -88,4 +110,4 @@ - + diff --git a/app/src/main/res/layout/singer_music_list_layout.xml b/app/src/main/res/layout/singer_music_list_layout.xml index 7c3e903..da9b3ac 100644 --- a/app/src/main/res/layout/singer_music_list_layout.xml +++ b/app/src/main/res/layout/singer_music_list_layout.xml @@ -6,15 +6,43 @@ android:orientation="vertical" tools:ignore="MissingDefaultResource"> - + + + + + + + + + + +