update
This commit is contained in:
parent
1c741d22ff
commit
8c4629497c
@ -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")
|
||||||
}
|
}
|
||||||
@ -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"
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
@ -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?,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -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)
|
||||||
|
|||||||
@ -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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -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
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
133
app/src/main/res/layout/activity_search_more.xml
Normal file
133
app/src/main/res/layout/activity_search_more.xml
Normal 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>
|
||||||
@ -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
|
||||||
Loading…
Reference in New Issue
Block a user