This commit is contained in:
ocean 2024-05-14 19:13:18 +08:00
parent 1c741d22ff
commit 8c4629497c
13 changed files with 556 additions and 36 deletions

View File

@ -84,5 +84,6 @@ dependencies {
implementation("org.brotli:dec:0.1.2") implementation("org.brotli:dec:0.1.2")
implementation("com.google.android.flexbox:flexbox:3.0.0") implementation("com.google.android.flexbox:flexbox:3.0.0")
implementation("io.github.scwang90:refresh-layout-kernel:2.1.0")
implementation("io.github.scwang90:refresh-footer-ball:2.1.0")
} }

View File

@ -59,6 +59,9 @@
<activity <activity
android:name=".activity.MoSingerDetailsActivity" android:name=".activity.MoSingerDetailsActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity
android:name=".activity.MoSearchMoreActivity"
android:screenOrientation="portrait" />
<service <service
android:name=".service.PlaybackService" android:name=".service.PlaybackService"

View File

@ -140,9 +140,8 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
binding.totalDurationTv.text = binding.totalDurationTv.text =
convertMillisToMinutesAndSecondsString(MediaControllerManager.getDuration()) convertMillisToMinutesAndSecondsString(MediaControllerManager.getDuration())
binding.sbProgress.value = MediaControllerManager.getCurrentPosition().toFloat()
binding.sbProgress.valueTo = MediaControllerManager.getDuration().toFloat() binding.sbProgress.valueTo = MediaControllerManager.getDuration().toFloat()
binding.sbProgress.value = MediaControllerManager.getCurrentPosition().toFloat()
updateProgressState() updateProgressState()
binding.progressBar.progress = MediaControllerManager.getBufferedPosition().toInt() binding.progressBar.progress = MediaControllerManager.getBufferedPosition().toInt()

View File

@ -0,0 +1,172 @@
package com.player.musicoo.activity
import android.annotation.SuppressLint
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.gyf.immersionbar.ktx.immersionBar
import com.player.musicoo.R
import com.player.musicoo.adapter.DetailsListAdapter
import com.player.musicoo.adapter.SearchResultOtherAdapter
import com.player.musicoo.databinding.ActivityDetailsBinding
import com.player.musicoo.databinding.ActivitySearchMoreBinding
import com.player.musicoo.databinding.ActivitySingerDetailsBinding
import com.player.musicoo.fragment.MoHomeFragment
import com.player.musicoo.innertube.Innertube
import com.player.musicoo.innertube.models.bodies.ContinuationBody
import com.player.musicoo.innertube.models.bodies.SearchBody
import com.player.musicoo.innertube.requests.moPlaylistPage
import com.player.musicoo.innertube.requests.moSearchPage
import com.player.musicoo.innertube.requests.moSingerListPage
import com.player.musicoo.util.LogTag
import com.player.musicoo.util.LogTag.LogD
import com.player.musicoo.view.SearchResultOptimalView
import com.player.musicoo.view.SearchResultOtherView
import com.player.musicoo.view.SingerDetailsOtherView
import com.player.musicoo.view.SingerDetailsSongView
import com.scwang.smart.refresh.layout.api.RefreshLayout
import com.scwang.smart.refresh.layout.listener.OnLoadMoreListener
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.isActive
import kotlinx.coroutines.selects.select
class MoSearchMoreActivity : MoBaseActivity() {
private val requests: Channel<Request> = Channel(Channel.UNLIMITED)
enum class Request {
TryAgain,
MoreData,
}
companion object {
const val SEARCH_MORE_QUERY = "search_more_query"
const val SEARCH_MORE_PARAMS = "search_more_params"
}
private lateinit var binding: ActivitySearchMoreBinding
private var query: String? = null
private var params: String? = null
private var list: MutableList<Innertube.SearchDataPage.SearchResult> = mutableListOf()
private var currentContinuation: String? = null
private var adapter: SearchResultOtherAdapter? = null
override suspend fun main() {
binding = ActivitySearchMoreBinding.inflate(layoutInflater)
setContentView(binding.root)
query = intent.getStringExtra(SEARCH_MORE_QUERY)
params = intent.getStringExtra(SEARCH_MORE_PARAMS)
if (query.isNullOrEmpty() || params.isNullOrEmpty()) {
return
}
initImmersionBar()
initView()
initAdapter()
initData(query!!, 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(query!!, params!!)
}
Request.MoreData -> {
LogD(TAG, "Request.MoreData")
currentContinuation?.let { it1 -> initDataMore(it1) }
}
}
}
}
}
}
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 = SearchResultOtherAdapter(this, list)
binding.rv.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
binding.rv.adapter = adapter
}
private suspend fun initData(query: String, params: String) {
showLoadingUi()
Innertube.moSearchPage(SearchBody(query = query, params = params))?.onSuccess { result ->
if (result.isNotEmpty()) {
showDataUi()
val title = result[0].title
if (title.isNullOrEmpty()) {
binding.title.visibility = View.GONE
} else {
binding.title.visibility = View.VISIBLE
binding.title.text = title
}
currentContinuation = result[0].continuation
list.clear()
list.addAll(result[0].searchResultList)
} else {
showNoContentUi()
}
}?.onFailure {
showNoContentUi()
}
}
@SuppressLint("NotifyDataSetChanged")
private suspend fun initDataMore(continuation: String) {
Innertube.moSearchPage(ContinuationBody(continuation = continuation))?.onSuccess { result ->
LogD(TAG, "initDataMore result->$result")
currentContinuation = result.continuation
if (result.searchResultList.isNotEmpty()) {
list.addAll(result.searchResultList)
if (!isFinishing) {
adapter?.notifyDataSetChanged()
}
binding.refreshLayout.finishLoadMore(true)
} else {
binding.refreshLayout.finishLoadMore(2000, true, false)
}
}?.onFailure {
binding.refreshLayout.finishLoadMore(2000, false, false)
}
}
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
}
}

View File

@ -2,6 +2,7 @@ package com.player.musicoo.adapter
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.Intent
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@ -11,11 +12,15 @@ import androidx.media3.common.Player
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.player.musicoo.R 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.PlayListItemBinding import com.player.musicoo.databinding.PlayListItemBinding
import com.player.musicoo.databinding.SearchResultOtherItemBinding import com.player.musicoo.databinding.SearchResultOtherItemBinding
import com.player.musicoo.databinding.SearchResultOtherLayoutBinding import com.player.musicoo.databinding.SearchResultOtherLayoutBinding
import com.player.musicoo.innertube.Innertube import com.player.musicoo.innertube.Innertube
import com.player.musicoo.media.MediaControllerManager import com.player.musicoo.media.MediaControllerManager
import com.player.musicoo.util.LogTag
class SearchResultOtherAdapter( class SearchResultOtherAdapter(
private val context: Context, private val context: Context,
@ -24,7 +29,8 @@ class SearchResultOtherAdapter(
RecyclerView.Adapter<SearchResultOtherAdapter.ViewHolder>() { RecyclerView.Adapter<SearchResultOtherAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = SearchResultOtherItemBinding.inflate(LayoutInflater.from(context), parent, false) val binding =
SearchResultOtherItemBinding.inflate(LayoutInflater.from(context), parent, false)
return ViewHolder(binding) return ViewHolder(binding)
} }
@ -33,7 +39,40 @@ class SearchResultOtherAdapter(
holder.bind(bean) holder.bind(bean)
holder.itemView.setOnClickListener { holder.itemView.setOnClickListener {
LogTag.LogD(
LogTag.VO_ACT_LOG,
"SearchResultOtherAdapter bean.pageType->${bean.pageType}"
)
if (!bean.videoId.isNullOrEmpty()) {
val intent = Intent(context, MoPlayDetailsActivity::class.java)
intent.putExtra(
MoPlayDetailsActivity.PLAY_DETAILS_VIDEO_ID,
bean.videoId
)
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_NAME, bean.title)
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_DESC, bean.desc)
context.startActivity(intent)
} else if (!bean.browseId.isNullOrEmpty()) {
when (bean.pageType) {
"MUSIC_PAGE_TYPE_ARTIST" -> {
val intent = Intent(context, MoSingerDetailsActivity::class.java)
intent.putExtra(
MoSingerDetailsActivity.SINGER_DETAILS_PAGE_BROWSE_ID,
bean.browseId
)
context.startActivity(intent)
}
else -> {
val intent = Intent(context, MoListDetailsActivity::class.java)
intent.putExtra(
MoListDetailsActivity.PLAY_LIST_PAGE_BROWSE_ID,
bean.browseId
)
context.startActivity(intent)
}
}
}
} }
} }

View File

@ -24,6 +24,7 @@ import com.player.musicoo.adapter.SearchHistoryAdapter
import com.player.musicoo.adapter.SearchSuggestionsAdapter import com.player.musicoo.adapter.SearchSuggestionsAdapter
import com.player.musicoo.databinding.FragmentSearchBinding import com.player.musicoo.databinding.FragmentSearchBinding
import com.player.musicoo.innertube.Innertube import com.player.musicoo.innertube.Innertube
import com.player.musicoo.innertube.models.bodies.SearchBody
import com.player.musicoo.innertube.models.bodies.SearchSuggestionsBody import com.player.musicoo.innertube.models.bodies.SearchSuggestionsBody
import com.player.musicoo.innertube.requests.moSearchPage import com.player.musicoo.innertube.requests.moSearchPage
import com.player.musicoo.innertube.requests.searchSuggestions import com.player.musicoo.innertube.requests.searchSuggestions
@ -176,9 +177,10 @@ class SearchFragment : MoBaseFragment<FragmentSearchBinding>(), TextWatcher,
appStore.searchHistoryStore = searchHistorySet appStore.searchHistoryStore = searchHistorySet
updateHistoryUi() updateHistoryUi()
Innertube.moSearchPage(input)?.onSuccess { result -> Innertube.moSearchPage(SearchBody(query = input))?.onSuccess { result ->
showResultContent() showResultContent()
for (dataPage: Innertube.SearchDataPage in result) { for (dataPage: Innertube.SearchDataPage in result) {
LogTag.LogD(TAG,"moSearchPage dataPage->$dataPage")
if (dataPage.type == 1) {//type为1的是最佳结果。 if (dataPage.type == 1) {//type为1的是最佳结果。
binding.contentLayout.addView( binding.contentLayout.addView(
SearchResultOptimalView(requireActivity(), dataPage) SearchResultOptimalView(requireActivity(), dataPage)
@ -238,7 +240,7 @@ class SearchFragment : MoBaseFragment<FragmentSearchBinding>(), TextWatcher,
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if (s.isNullOrEmpty()) { if (s.isNullOrEmpty()) {//没有输入内容,隐藏删除按钮,展示历史记录,重新获取焦点弹出键盘。
binding.deleteInputBtn.visibility = View.GONE binding.deleteInputBtn.visibility = View.GONE
showSearchHistory() showSearchHistory()
updateHistoryUi() updateHistoryUi()

View File

@ -178,7 +178,7 @@ object Innertube {
data class SingerDetailsListPage( data class SingerDetailsListPage(
val title: String?, val title: String?,
val contents: SingerDetailsContent? val contents: SingerDetailsContent?
){ ) {
data class SingerDetailsContent( data class SingerDetailsContent(
val musicShelfContentList: List<MusicShelfRenderer.Content>?, val musicShelfContentList: List<MusicShelfRenderer.Content>?,
val musicCarouselShelfContentList: List<MusicCarouselShelfRenderer.Content>?, val musicCarouselShelfContentList: List<MusicCarouselShelfRenderer.Content>?,
@ -186,9 +186,12 @@ object Innertube {
} }
data class SearchDataPage( data class SearchDataPage(
val type: Int?, val type: Int? = null,
val title: String?, val title: String? = null,
val searchResultList: List<SearchResult> val searchResultList: List<SearchResult>,
val query: String? = null,
val params: String? = null,
val continuation: String? = null
) { ) {
data class SearchResult( data class SearchResult(
val title: String?, val title: String?,
@ -196,6 +199,7 @@ object Innertube {
val thumbnail: String?, val thumbnail: String?,
val videoId: String?, val videoId: String?,
val browseId: String?, val browseId: String?,
val pageType: String?,
) )
} }

View File

@ -2,10 +2,12 @@ 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.MusicShelfRenderer import com.player.musicoo.innertube.models.MusicShelfRenderer
import com.player.musicoo.innertube.models.SearchResponse import com.player.musicoo.innertube.models.SearchResponse
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.models.bodies.SearchBody import com.player.musicoo.innertube.models.bodies.SearchBody
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
@ -13,11 +15,11 @@ import io.ktor.client.call.body
import io.ktor.client.request.post import io.ktor.client.request.post
import io.ktor.client.request.setBody import io.ktor.client.request.setBody
suspend fun Innertube.moSearchPage(query: String): Result<List<Innertube.SearchDataPage>>? = suspend fun Innertube.moSearchPage(body: SearchBody): Result<List<Innertube.SearchDataPage>>? =
runCatchingNonCancellable { runCatchingNonCancellable {
val response = client.post(search) { val response = client.post(search) {
setBody(SearchBody(query = query)) setBody(body)
}.body<SearchResponse>() }.body<SearchResponse>()
val searchDataPageList: MutableList<Innertube.SearchDataPage> = mutableListOf() val searchDataPageList: MutableList<Innertube.SearchDataPage> = mutableListOf()
@ -32,6 +34,9 @@ suspend fun Innertube.moSearchPage(query: String): Result<List<Innertube.SearchD
?.contents ?.contents
var type = -1 var type = -1
var title = "" var title = ""
var query = ""
var params = ""
var continuation = ""
if (contents != null) { if (contents != null) {
for (content: SectionListRenderer.Content in contents) { for (content: SectionListRenderer.Content in contents) {
//保证每次循环都是一个新的集合 //保证每次循环都是一个新的集合
@ -82,12 +87,21 @@ suspend fun Innertube.moSearchPage(query: String): Result<List<Innertube.SearchD
?.browseEndpoint ?.browseEndpoint
?.browseId ?.browseId
val pageType = content.musicCardShelfRenderer
.title
?.runs
?.firstOrNull()
?.navigationEndpoint
?.browseEndpoint
?.type
val result = Innertube.SearchDataPage.SearchResult( val result = Innertube.SearchDataPage.SearchResult(
title = searchResultTitle, title = searchResultTitle,
desc = searchResultDesc, desc = searchResultDesc,
thumbnail = searchResultThumbnail, thumbnail = searchResultThumbnail,
videoId = searchResultVideoId, videoId = searchResultVideoId,
browseId = searchResultBrowseId browseId = searchResultBrowseId,
pageType = pageType
) )
searchResultItemList.add(result) searchResultItemList.add(result)
} else { } else {
@ -95,10 +109,22 @@ suspend fun Innertube.moSearchPage(query: String): Result<List<Innertube.SearchD
type = 2 type = 2
title = content.musicShelfRenderer.title title = content.musicShelfRenderer.title
?.text ?: "" ?.text ?: ""
query = content.musicShelfRenderer.bottomEndpoint
?.searchEndpoint
?.query ?: ""
params = content.musicShelfRenderer.bottomEndpoint
?.searchEndpoint
?.params ?: ""
continuation = content.musicShelfRenderer
.continuations
?.firstOrNull()
?.nextContinuationData
?.continuation ?: ""
val itemContents = content.musicShelfRenderer.contents val itemContents = content.musicShelfRenderer.contents
if (itemContents != null) { if (itemContents != null) {
for (itemContent: MusicShelfRenderer.Content in itemContents) { for (itemContent: MusicShelfRenderer.Content in itemContents) {
val item = Innertube.SearchDataPage.SearchResult( val item = Innertube.SearchDataPage.SearchResult(
title = itemContent title = itemContent
.musicResponsiveListItemRenderer .musicResponsiveListItemRenderer
@ -134,15 +160,35 @@ suspend fun Innertube.moSearchPage(query: String): Result<List<Innertube.SearchD
?.navigationEndpoint ?.navigationEndpoint
?.watchEndpoint ?.watchEndpoint
?.videoId, ?.videoId,
browseId = itemContent.musicResponsiveListItemRenderer browseId = itemContent.musicResponsiveListItemRenderer
?.navigationEndpoint ?.navigationEndpoint
?.browseEndpoint ?.browseEndpoint
?.browseId ?: "" ?.browseId ?: "",
pageType = itemContent.musicResponsiveListItemRenderer
?.navigationEndpoint
?.browseEndpoint
?.type,
) )
//这两个ID必须有一个id是存在的否则就不进入添加数据
if (!item.videoId.isNullOrBlank() || !item.browseId.isNullOrBlank()) { if (!item.videoId.isNullOrBlank() || !item.browseId.isNullOrBlank()) {
when (item.pageType) {
"MUSIC_PAGE_TYPE_PODCAST_SHOW_DETAIL_PAGE" -> {
//不add博客数据
}
"MUSIC_PAGE_TYPE_USER_CHANNEL" -> {
//不add个人资料数据
}
else -> {
searchResultItemList.add(item) searchResultItemList.add(item)
} }
} }
}
}
} }
} }
} }
@ -150,10 +196,105 @@ suspend fun Innertube.moSearchPage(query: String): Result<List<Innertube.SearchD
Innertube.SearchDataPage( Innertube.SearchDataPage(
type, type,
title = title, title = title,
searchResultList = searchResultItemList searchResultList = searchResultItemList,
query = query,
params = params,
continuation = continuation
) )
searchDataPageList.add(dataPage) searchDataPageList.add(dataPage)
} }
} }
searchDataPageList searchDataPageList
} }
suspend fun Innertube.moSearchPage(body: ContinuationBody): Result<Innertube.SearchDataPage>? =
runCatchingNonCancellable {
val response = client.post(search) {
setBody(body)
}.body<ContinuationResponse>()
val searchResultItemList: MutableList<Innertube.SearchDataPage.SearchResult> =
mutableListOf()
val musicShelfContinuation = response.continuationContents
?.musicShelfContinuation
val itemContents = musicShelfContinuation
?.contents
if (itemContents != null) {
for (itemContent: MusicShelfRenderer.Content in itemContents) {
val item = Innertube.SearchDataPage.SearchResult(
title = itemContent
.musicResponsiveListItemRenderer
?.flexColumns
?.firstOrNull()
?.musicResponsiveListItemFlexColumnRenderer
?.text
?.runs
?.firstOrNull()
?.text,
desc = itemContent.musicResponsiveListItemRenderer
?.flexColumns
?.get(1)
?.musicResponsiveListItemFlexColumnRenderer
?.text
?.runs
?.map { it.text }
?.joinToString("") ?: "",
thumbnail = itemContent.musicResponsiveListItemRenderer
?.thumbnail
?.musicThumbnailRenderer
?.thumbnail
?.thumbnails
?.let { it.getOrNull(1) ?: it.getOrNull(0) }
?.url,
videoId = itemContent.musicResponsiveListItemRenderer
?.flexColumns
?.firstOrNull()
?.musicResponsiveListItemFlexColumnRenderer
?.text
?.runs
?.firstOrNull()
?.navigationEndpoint
?.watchEndpoint
?.videoId,
browseId = itemContent.musicResponsiveListItemRenderer
?.navigationEndpoint
?.browseEndpoint
?.browseId ?: "",
pageType = itemContent.musicResponsiveListItemRenderer
?.navigationEndpoint
?.browseEndpoint
?.type,
)
//这两个ID必须有一个id是存在的否则就不进入添加数据
if (!item.videoId.isNullOrBlank() || !item.browseId.isNullOrBlank()) {
when (item.pageType) {
"MUSIC_PAGE_TYPE_PODCAST_SHOW_DETAIL_PAGE" -> {
//不add博客数据
}
"MUSIC_PAGE_TYPE_USER_CHANNEL" -> {
//不add个人资料数据
}
else -> {
searchResultItemList.add(item)
}
}
}
}
}
Innertube.SearchDataPage(
searchResultList = searchResultItemList,
continuation = musicShelfContinuation
?.continuations
?.firstOrNull()
?.nextContinuationData
?.continuation
)
}

View File

@ -85,17 +85,17 @@ suspend fun Innertube.moSingerListPage(browseId: String): Result<Innertube.Singe
val singerDetails = val singerDetails =
Innertube.SingerDetailsListPage(title = title, contents = singerDetailsContent) Innertube.SingerDetailsListPage(title = title, contents = singerDetailsContent)
LogTag.LogD(TAG, "title->${singerDetails.title}") // LogTag.LogD(TAG, "title->${singerDetails.title}")
LogTag.LogD( // LogTag.LogD(
TAG, // TAG,
"musicShelfContentList size->${singerDetails.contents?.musicShelfContentList?.size}" // "musicShelfContentList size->${singerDetails.contents?.musicShelfContentList?.size}"
) // )
LogTag.LogD( // LogTag.LogD(
TAG, // TAG,
"musicCarouselShelfContentList size->${singerDetails.contents?.musicCarouselShelfContentList?.size}" // "musicCarouselShelfContentList size->${singerDetails.contents?.musicCarouselShelfContentList?.size}"
) // )
//
LogTag.LogD(TAG, "--------------------------------------------") // LogTag.LogD(TAG, "--------------------------------------------")
if (title.isNotEmpty()) { if (title.isNotEmpty()) {
list.add(singerDetails) list.add(singerDetails)

View File

@ -8,6 +8,7 @@ import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.player.musicoo.R import com.player.musicoo.R
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.activity.MoSingerDetailsActivity
import com.player.musicoo.innertube.Innertube import com.player.musicoo.innertube.Innertube
@ -47,6 +48,16 @@ class SearchResultOptimalView(context: Context, data: Innertube.SearchDataPage)
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_DESC, optimalBean.desc) intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_DESC, optimalBean.desc)
context.startActivity(intent) context.startActivity(intent)
} else if (!optimalBean.browseId.isNullOrEmpty()) { } else if (!optimalBean.browseId.isNullOrEmpty()) {
when (optimalBean.pageType) {
"MUSIC_PAGE_TYPE_ALBUM" -> {
val intent = Intent(context, MoListDetailsActivity::class.java)
intent.putExtra(
MoListDetailsActivity.PLAY_LIST_PAGE_BROWSE_ID,
optimalBean.browseId
)
context.startActivity(intent)
}
else -> {
val intent = Intent(context, MoSingerDetailsActivity::class.java) val intent = Intent(context, MoSingerDetailsActivity::class.java)
intent.putExtra( intent.putExtra(
MoSingerDetailsActivity.SINGER_DETAILS_PAGE_BROWSE_ID, MoSingerDetailsActivity.SINGER_DETAILS_PAGE_BROWSE_ID,
@ -57,4 +68,6 @@ class SearchResultOptimalView(context: Context, data: Innertube.SearchDataPage)
} }
} }
} }
}
}
} }

View File

@ -2,25 +2,37 @@ 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.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.adapter.SearchResultOtherAdapter import com.player.musicoo.adapter.SearchResultOtherAdapter
import com.player.musicoo.innertube.Innertube import com.player.musicoo.innertube.Innertube
@SuppressLint("ViewConstructor") @SuppressLint("ViewConstructor")
class SearchResultOtherView (context: Context, data: Innertube.SearchDataPage) : class SearchResultOtherView(context: Context, data: Innertube.SearchDataPage) :
ModuleView(context) { ModuleView(context) {
init { init {
contentView = inflate(getContext(), R.layout.search_result_other_layout, this) contentView = inflate(getContext(), R.layout.search_result_other_layout, this)
val title = contentView?.findViewById<TextView>(R.id.title) val title = contentView?.findViewById<TextView>(R.id.title)
title?.text = data.title title?.text = data.title
val moreBtn = contentView?.findViewById<LinearLayout>(R.id.moreBtn)
moreBtn?.setOnClickListener {
val intent = Intent(context, MoSearchMoreActivity::class.java)
intent.putExtra(MoSearchMoreActivity.SEARCH_MORE_QUERY, data.query)
intent.putExtra(MoSearchMoreActivity.SEARCH_MORE_PARAMS, data.params)
context.startActivity(intent)
}
val rv = contentView?.findViewById<RecyclerView>(R.id.rv) val rv = contentView?.findViewById<RecyclerView>(R.id.rv)
val adapter = SearchResultOtherAdapter(context, data.searchResultList) val adapter = SearchResultOtherAdapter(context, data.searchResultList)
rv?.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) rv?.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
rv?.adapter = adapter rv?.adapter = adapter
} }
} }

View File

@ -0,0 +1,133 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/main_bg_color"
android:orientation="vertical">
<View
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="0dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/view"
android:orientation="vertical">
<LinearLayout
android:id="@+id/title_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:orientation="horizontal">
<RelativeLayout
android:id="@+id/back_btn"
android:layout_width="42dp"
android:layout_height="42dp"
android:background="@drawable/drw_back_bg">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/back_icon" />
</RelativeLayout>
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="16dp"
android:fontFamily="@font/medium_font"
android:gravity="center_vertical"
android:text="@string/app_name"
android:textColor="@color/white"
android:textSize="18dp"
android:visibility="gone" />
</LinearLayout>
<LinearLayout
android:id="@+id/loadingLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateTint="@color/green"
android:progressBackgroundTint="@color/green"
android:progressTint="@color/green" />
</LinearLayout>
<LinearLayout
android:id="@+id/no_content_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<ImageView
android:id="@+id/no_content_iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/no_content_img" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:fontFamily="@font/medium_font"
android:gravity="center"
android:text="@string/content_loading_failed"
android:textSize="14dp" />
<TextView
android:id="@+id/tryAgainBtn"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_marginTop="16dp"
android:background="@drawable/drw_btn_bg"
android:fontFamily="@font/medium_font"
android:gravity="center"
android:paddingStart="32dp"
android:paddingEnd="32dp"
android:text="@string/try_again"
android:textColor="@color/black"
android:textSize="16dp" />
</LinearLayout>
<com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/refreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:overScrollMode="never"
android:scrollbars="none"
tools:itemCount="10"
tools:listitem="@layout/music_responsive_item" />
<com.scwang.smart.refresh.footer.BallPulseFooter
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:srlAnimatingColor="@color/green" />
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
</LinearLayout>
</RelativeLayout>

View File

@ -21,3 +21,4 @@ kotlin.code.style=official
# resources declared in the library itself and none from the library's dependencies, # resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library # thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true android.nonTransitiveRClass=true
android.enableJetifier=true