1.1.1数据结构更新
This commit is contained in:
parent
45455e7c6d
commit
130fefd189
@ -1312,7 +1312,9 @@ extension MP_NetWorkManager {
|
||||
content.musicCarouselShelfRenderer?.contents?.forEach({ content in
|
||||
//设置标题、歌手、专辑/列表
|
||||
if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer {
|
||||
browse.items.append(.init(parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer)))
|
||||
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||
browse.items.append(.init(item))
|
||||
}
|
||||
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
|
||||
browse.items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)))
|
||||
}
|
||||
@ -1392,7 +1394,9 @@ extension MP_NetWorkManager {
|
||||
content.musicCarouselShelfRenderer?.contents?.forEach({ content in
|
||||
//设置标题、歌手、专辑/列表
|
||||
if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer {
|
||||
browse.items.append(.init(parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer)))
|
||||
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||
browse.items.append(.init(item))
|
||||
}
|
||||
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
|
||||
browse.items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)))
|
||||
}
|
||||
@ -1421,7 +1425,9 @@ extension MP_NetWorkManager {
|
||||
musicPlaylistShelfRenderer.contents?.forEach({ content in
|
||||
//设置标题、歌手、专辑/列表
|
||||
if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer {
|
||||
items.append(.init(parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer)))
|
||||
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||
items.append(.init(item))
|
||||
}
|
||||
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
|
||||
items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)))
|
||||
}
|
||||
@ -1430,7 +1436,9 @@ extension MP_NetWorkManager {
|
||||
musicShelfRenderer.contents?.forEach({ content in
|
||||
//设置标题、歌手、专辑/列表
|
||||
if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer {
|
||||
items.append(.init(parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer)))
|
||||
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||
items.append(.init(item))
|
||||
}
|
||||
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
|
||||
items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)))
|
||||
}
|
||||
@ -1449,7 +1457,9 @@ extension MP_NetWorkManager {
|
||||
musicPlaylistShelfRenderer.contents?.forEach({ content in
|
||||
//设置标题、歌手、专辑/列表
|
||||
if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer {
|
||||
items.append(.init(parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer)))
|
||||
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||
items.append(.init(item))
|
||||
}
|
||||
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
|
||||
items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)))
|
||||
}
|
||||
@ -1458,7 +1468,9 @@ extension MP_NetWorkManager {
|
||||
musicShelfRenderer.contents?.forEach({ content in
|
||||
//设置标题、歌手、专辑/列表
|
||||
if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer {
|
||||
items.append(.init(parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer)))
|
||||
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||
items.append(.init(item))
|
||||
}
|
||||
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
|
||||
items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)))
|
||||
}
|
||||
@ -1540,8 +1552,8 @@ extension MP_NetWorkManager {
|
||||
params = musicShelfRenderer.title?.runs?.first?.navigationEndpoint?.browseEndpoint?.params
|
||||
//解析模块内容
|
||||
musicShelfRenderer.contents?.forEach({ item in
|
||||
if item.musicResponsiveListItemRenderer != nil {
|
||||
itemViews.append(.init(parsingMusicResponsiveListItemRenderer(item.musicResponsiveListItemRenderer!)))
|
||||
if let musicResponsiveListItemRenderer = item.musicResponsiveListItemRenderer, let asd = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||
itemViews.append(.init(asd))
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -1573,7 +1585,9 @@ extension MP_NetWorkManager {
|
||||
//是音视频
|
||||
musicPlaylistShelfRenderer.contents?.forEach({ item in
|
||||
if let musicResponsiveListItemRenderer = item.musicResponsiveListItemRenderer {
|
||||
array.append(.init(parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer)))
|
||||
if let asd = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||
array.append(.init(asd))
|
||||
}
|
||||
}
|
||||
})
|
||||
continuation = musicPlaylistShelfRenderer.continuations?.first?.nextContinuationData?.continuation
|
||||
@ -1601,7 +1615,9 @@ extension MP_NetWorkManager {
|
||||
if let contents = musicPlaylistShelfContinuation.contents {
|
||||
contents.forEach { item in
|
||||
if let musicResponsiveListItemRenderer = item.musicResponsiveListItemRenderer {
|
||||
array.append(.init(parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer)))
|
||||
if let asd = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||
array.append(.init(asd))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1810,9 +1826,10 @@ extension MP_NetWorkManager {
|
||||
let list = MPPositive_RecommendListViewModel()
|
||||
list.title = section.musicCarouselShelfRenderer?.header?.musicCarouselShelfBasicHeaderRenderer?.title?.runs?.reduce("", { $0 + ($1.text ?? "")})
|
||||
section.musicCarouselShelfRenderer?.contents?.forEach({ content in
|
||||
if content.musicResponsiveListItemRenderer != nil {
|
||||
let item = parsingMusicResponsiveListItemRenderer(content.musicResponsiveListItemRenderer!)
|
||||
list.items.append(.init(item))
|
||||
if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer{
|
||||
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||
list.items.append(.init(item))
|
||||
}
|
||||
}else if content.musicTwoRowItemRenderer != nil {
|
||||
let item = parsingMusicTwoRowItemRenderer(content.musicTwoRowItemRenderer!)
|
||||
list.items.append(.init(item))
|
||||
@ -1968,45 +1985,7 @@ extension MP_NetWorkManager {
|
||||
//设置内容块
|
||||
musicShelfRenderer.contents?.forEach({ content in
|
||||
//专辑/列表/单曲视频/艺术家
|
||||
let item = MPPositive_BrowseItemModel()
|
||||
if (content.musicResponsiveListItemRenderer?.playlistItemData != nil || content.musicResponsiveListItemRenderer?.navigationEndpoint != nil) && (content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE") {
|
||||
//设置内容块的封面
|
||||
item.coverUrls = content.musicResponsiveListItemRenderer?.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.map({$0.url ?? ""})
|
||||
//设置一级标题与二级标题
|
||||
for (index, flexColumn) in (content.musicResponsiveListItemRenderer?.flexColumns ?? []).enumerated() {
|
||||
if index == 0 {
|
||||
//一级标题
|
||||
item.title = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")})
|
||||
item.pageType = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.first?.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType
|
||||
}else {
|
||||
//二级标题
|
||||
item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "")
|
||||
}
|
||||
}
|
||||
item.playListId = content.musicResponsiveListItemRenderer?.menu?.menuRenderer?.items?.first?.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId
|
||||
//设置id和类型
|
||||
if content.musicResponsiveListItemRenderer?.playlistItemData != nil {
|
||||
//是单曲
|
||||
item.itemType = .single
|
||||
item.videoId = content.musicResponsiveListItemRenderer?.playlistItemData?.videoId
|
||||
}else {
|
||||
//是专辑列表/艺术家
|
||||
item.browseId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId
|
||||
let pageType = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType
|
||||
if youTubeKeys.contains(pageType ?? "") == true && pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" {
|
||||
//判断细分
|
||||
if pageType == "MUSIC_PAGE_TYPE_ARTIST" {
|
||||
item.artistId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId
|
||||
//是艺术家
|
||||
item.itemType = .artist
|
||||
}else {
|
||||
//是列表/专辑
|
||||
item.itemType = .list
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if item.itemType != nil, item.title != nil, item.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" {
|
||||
if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer, let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||
resultList.previewItemViews.append(.init(item))
|
||||
}
|
||||
})
|
||||
@ -2146,55 +2125,87 @@ extension MP_NetWorkManager {
|
||||
return (array, continuation, clickTrackingParams)
|
||||
}
|
||||
//MARK: - 解析具体内容形式
|
||||
//解析musicResponsiveListItemRenderer(通常是音视频内容)
|
||||
private func parsingMusicResponsiveListItemRenderer(_ musicResponsiveListItemRenderer: RootMusicResponsiveListItemRenderer) -> MPPositive_BrowseItemModel {
|
||||
//解析musicResponsiveListItemRenderer(四组件内容)
|
||||
private func parsingMusicResponsiveListItemRenderer(_ musicResponsiveListItemRenderer: RootMusicResponsiveListItemRenderer) -> MPPositive_BrowseItemModel? {
|
||||
//生成一个音乐模型接收数据
|
||||
let item = MPPositive_BrowseItemModel()
|
||||
//预览图片路径
|
||||
item.coverUrls = musicResponsiveListItemRenderer.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.compactMap({$0.url})
|
||||
//设置主副标题
|
||||
if let flexColumns = musicResponsiveListItemRenderer.flexColumns {
|
||||
for (index,flexColumn) in flexColumns.enumerated() {
|
||||
if index == 0 {
|
||||
//添加主标题
|
||||
item.title = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")})
|
||||
item.playListId = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.first?.navigationEndpoint?.watchEndpoint?.playlistId
|
||||
}else{
|
||||
item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "")
|
||||
}
|
||||
}
|
||||
}
|
||||
if item.playListId == nil {
|
||||
//通过操作菜单获取playListId
|
||||
item.playListId = musicResponsiveListItemRenderer.menu?.menuRenderer?.items?.first?.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId
|
||||
}
|
||||
//判断这个内容是音视频还是专辑列表艺术家
|
||||
//判断预览项性质,并继续补完数据
|
||||
if let playlistItemData = musicResponsiveListItemRenderer.playlistItemData {
|
||||
//是音视频
|
||||
//当前预览项是视频/单曲
|
||||
item.itemType = .single
|
||||
item.videoId = playlistItemData.videoId
|
||||
item.pageType = "MUSIC_VIDEO_TYPE_ATV"
|
||||
}
|
||||
if let navigationEndpoint = musicResponsiveListItemRenderer.navigationEndpoint {
|
||||
//是专辑列表艺术家
|
||||
if navigationEndpoint.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType == "MUSIC_PAGE_TYPE_ARTIST" && navigationEndpoint.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" {
|
||||
//是艺术家
|
||||
item.itemType = .artist
|
||||
item.artistId = navigationEndpoint.browseEndpoint?.browseId
|
||||
item.pageType = "MUSIC_PAGE_TYPE_ARTIST"
|
||||
}else {
|
||||
if navigationEndpoint.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" {
|
||||
//是专辑列表
|
||||
item.itemType = .list
|
||||
item.pageType = navigationEndpoint.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType
|
||||
item.browseId = navigationEndpoint.browseEndpoint?.browseId
|
||||
item.params = navigationEndpoint.browseEndpoint?.params
|
||||
}
|
||||
//设置主副标题
|
||||
guard var flexColumns = musicResponsiveListItemRenderer.flexColumns, flexColumns.isEmpty != true else {
|
||||
return nil
|
||||
}
|
||||
//主标题为第一位,同时VideoId,PlayListId,pageType都以第一个flexColumn为主
|
||||
let first = flexColumns.removeFirst()
|
||||
item.title = first.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")})
|
||||
//判断watchEndpoint(资源导向)是否存在
|
||||
guard let watchEndpoint = first.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.first?.navigationEndpoint?.watchEndpoint else {return nil}
|
||||
//watchEndpoint内容赋值给item
|
||||
item.playListId = watchEndpoint.playlistId
|
||||
item.pageType = watchEndpoint.watchEndpointMusicSupportedConfigs?.watchEndpointMusicConfig?.musicVideoType
|
||||
//设置副标题,通常为作者/专辑
|
||||
flexColumns.forEach { flexColumn in
|
||||
item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "")
|
||||
}
|
||||
//继续补完videoId,检索是否具备playListId,当playListId为空时,说明并没有成功补完,需要使用菜单结构补全内容
|
||||
guard (item.playListId ?? "").isEmpty == true else {
|
||||
//不为空,说明需要的数据已经补完了
|
||||
return item
|
||||
}
|
||||
//未补完,继续
|
||||
if let watchItem = musicResponsiveListItemRenderer.menu?.menuRenderer?.items?.first(where: {$0.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint != nil}) {
|
||||
item.playListId = watchItem.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId
|
||||
return item
|
||||
}else {
|
||||
//补完失败
|
||||
return nil
|
||||
}
|
||||
}else if let navigationEndpoint = musicResponsiveListItemRenderer.navigationEndpoint {
|
||||
//是专辑/艺术家/歌单
|
||||
//设置主副标题
|
||||
guard var flexColumns = musicResponsiveListItemRenderer.flexColumns, flexColumns.isEmpty != true else {
|
||||
return nil
|
||||
}
|
||||
//主标题为第一位,其余内容都是副标题
|
||||
let first = flexColumns.removeFirst()
|
||||
item.title = first.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")})
|
||||
//设置副标题,通常为作者/专辑
|
||||
flexColumns.forEach { flexColumn in
|
||||
item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "")
|
||||
}
|
||||
//设置预览Id
|
||||
guard let browseEndpoint = navigationEndpoint.browseEndpoint else {
|
||||
return nil
|
||||
}
|
||||
item.browseId = browseEndpoint.browseId
|
||||
//根据pageType确定导航至何处
|
||||
guard let pageType = browseEndpoint.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType else {return nil}
|
||||
item.pageType = pageType
|
||||
if pageType == "MUSIC_PAGE_TYPE_ALBUM" {
|
||||
//专辑
|
||||
item.itemType = .list
|
||||
return item
|
||||
}else if pageType == "MUSIC_PAGE_TYPE_PLAYLIST" {
|
||||
//列表
|
||||
item.itemType = .list
|
||||
return item
|
||||
}else if pageType == "MUSIC_PAGE_TYPE_ARTIST" {
|
||||
//艺术家
|
||||
item.itemType = .artist
|
||||
return item
|
||||
}else {
|
||||
return nil
|
||||
}
|
||||
}else {
|
||||
return nil
|
||||
}
|
||||
return item
|
||||
}
|
||||
//解析musicResponsiveListItemRenderer(是列表专辑内容)
|
||||
//解析musicResponsiveListItemRenderer(三组件结构)
|
||||
private func parsingMusicTwoRowItemRenderer(_ musicTwoRowItemRenderer: RootMusicTwoRowItemRenderer) -> MPPositive_BrowseItemModel {
|
||||
//生成一个音乐模型接收数据
|
||||
let item = MPPositive_BrowseItemModel()
|
||||
@ -2224,7 +2235,6 @@ extension MP_NetWorkManager {
|
||||
item.itemType = .list
|
||||
item.pageType = browseEndpoint.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType
|
||||
item.browseId = browseEndpoint.browseId
|
||||
item.params = browseEndpoint.params
|
||||
}
|
||||
}
|
||||
return item
|
||||
|
||||
@ -469,32 +469,33 @@ struct JsonBrowses: Codable {
|
||||
}
|
||||
|
||||
//MARK: - 图像信息数据结构
|
||||
///单曲/视频结构(通常是四组件构成,封面,一级标题,二级标题,额外包含ID内容)
|
||||
///四组件结构(通常是四组件构成,封面,一级标题,二级标题,额外包含ID内容),根据playlistItemData和navigationEndpoint两者来敲定该预览项属于(播放/导航)一种,并继续下分
|
||||
struct RootMusicResponsiveListItemRenderer: Codable {
|
||||
///指向封面图像
|
||||
let thumbnail:Thumbnail?
|
||||
///指向标题歌手专辑(通常有多位,0位是标题,后续都为副标题)
|
||||
let flexColumns:[FlexColumn]?
|
||||
///菜单操作(某些情况下flexColumns无法拿到playListId)
|
||||
let menu:Menu?
|
||||
///单曲/视频ID(playlistItemData存在说明这条数据单曲/视频)
|
||||
let playlistItemData:PlaylistItemData?
|
||||
///专辑/歌单ID(navigationEndpoint存在说明这条数据是专辑/歌单)
|
||||
///页面导向(navigationEndpoint存在时,说明这条数据将会作为跳转内容导向一个页面)
|
||||
let navigationEndpoint:NavigationEndpoint?
|
||||
///菜单(当playlistItemData存在,且无法通过flexColumns获得PlayListID时,调用菜单强制获得playListId)
|
||||
let menu:Menu?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case thumbnail = "thumbnail"
|
||||
case flexColumns = "flexColumns"
|
||||
case menu = "menu"
|
||||
case playlistItemData = "playlistItemData"
|
||||
case navigationEndpoint = "navigationEndpoint"
|
||||
case menu = "menu"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
thumbnail = try values.decodeIfPresent(Thumbnail.self, forKey: .thumbnail)
|
||||
flexColumns = try values.decodeIfPresent([FlexColumn].self, forKey: .flexColumns)
|
||||
menu = try values.decodeIfPresent(Menu.self, forKey: .menu)
|
||||
playlistItemData = try values.decodeIfPresent(PlaylistItemData.self, forKey: .playlistItemData)
|
||||
navigationEndpoint = try values.decodeIfPresent(NavigationEndpoint.self, forKey: .navigationEndpoint)
|
||||
menu = try values.decodeIfPresent(Menu.self, forKey: .menu)
|
||||
}
|
||||
//含有封面图像
|
||||
struct Thumbnail: Codable {
|
||||
@ -573,6 +574,7 @@ struct RootMusicResponsiveListItemRenderer: Codable {
|
||||
struct Run: Codable {
|
||||
///标题文本
|
||||
let text:String?
|
||||
///文本导航
|
||||
let navigationEndpoint:NavigationEndpoint?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case text = "text"
|
||||
@ -583,60 +585,54 @@ struct RootMusicResponsiveListItemRenderer: Codable {
|
||||
text = try values.decodeIfPresent(String.self, forKey: .text)
|
||||
navigationEndpoint = try values.decodeIfPresent(NavigationEndpoint.self, forKey: .navigationEndpoint)
|
||||
}
|
||||
//文本导航
|
||||
struct NavigationEndpoint: Codable {
|
||||
///资源特化
|
||||
let watchEndpoint:WatchEndpoint?
|
||||
let browseEndpoint:BrowseEndpoint?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case watchEndpoint = "watchEndpoint"
|
||||
case browseEndpoint = "browseEndpoint"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
watchEndpoint = try values.decodeIfPresent(WatchEndpoint.self, forKey: .watchEndpoint)
|
||||
browseEndpoint = try values.decodeIfPresent(BrowseEndpoint.self, forKey: .browseEndpoint)
|
||||
}
|
||||
//导向播放
|
||||
struct WatchEndpoint: Codable {
|
||||
///资源ID
|
||||
let videoId:String?
|
||||
///对应歌单ID(未必存在)
|
||||
let playlistId:String?
|
||||
///指向资源类型
|
||||
let watchEndpointMusicSupportedConfigs:WatchEndpointMusicSupportedConfigs?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case videoId = "videoId"
|
||||
case playlistId = "playlistId"
|
||||
case watchEndpointMusicSupportedConfigs = "watchEndpointMusicSupportedConfigs"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
videoId = try values.decodeIfPresent(String.self, forKey: .videoId)
|
||||
playlistId = try values.decodeIfPresent(String.self, forKey: .playlistId)
|
||||
watchEndpointMusicSupportedConfigs = try values.decodeIfPresent(WatchEndpointMusicSupportedConfigs.self, forKey: .watchEndpointMusicSupportedConfigs)
|
||||
}
|
||||
}
|
||||
struct BrowseEndpoint: Codable {
|
||||
let browseId:String?
|
||||
let params:String?
|
||||
let browseEndpointContextSupportedConfigs:BrowseEndpointContextSupportedConfigs?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case browseId = "browseId"
|
||||
case params = "params"
|
||||
case browseEndpointContextSupportedConfigs = "browseEndpointContextSupportedConfigs"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
browseId = try values.decodeIfPresent(String.self, forKey: .browseId)
|
||||
params = try values.decodeIfPresent(String.self, forKey: .params)
|
||||
browseEndpointContextSupportedConfigs = try values.decodeIfPresent(BrowseEndpointContextSupportedConfigs.self, forKey: .browseEndpointContextSupportedConfigs)
|
||||
}
|
||||
struct BrowseEndpointContextSupportedConfigs: Codable {
|
||||
let browseEndpointContextMusicConfig:BrowseEndpointContextMusicConfig?
|
||||
struct WatchEndpointMusicSupportedConfigs: Codable {
|
||||
let watchEndpointMusicConfig:WatchEndpointMusicConfig?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case browseEndpointContextMusicConfig = "browseEndpointContextMusicConfig"
|
||||
case watchEndpointMusicConfig = "watchEndpointMusicConfig"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
browseEndpointContextMusicConfig = try values.decodeIfPresent(BrowseEndpointContextMusicConfig.self, forKey: .browseEndpointContextMusicConfig)
|
||||
watchEndpointMusicConfig = try values.decodeIfPresent(WatchEndpointMusicConfig.self, forKey: .watchEndpointMusicConfig)
|
||||
}
|
||||
struct BrowseEndpointContextMusicConfig: Codable {
|
||||
let pageType:String?
|
||||
struct WatchEndpointMusicConfig: Codable {
|
||||
///资源类型
|
||||
let musicVideoType:String?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case pageType = "pageType"
|
||||
case musicVideoType = "musicVideoType"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
pageType = try values.decodeIfPresent(String.self, forKey: .pageType)
|
||||
musicVideoType = try values.decodeIfPresent(String.self, forKey: .musicVideoType)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -646,68 +642,7 @@ struct RootMusicResponsiveListItemRenderer: Codable {
|
||||
}
|
||||
}
|
||||
}
|
||||
//菜单操作
|
||||
struct Menu: Codable {
|
||||
let menuRenderer:MenuRenderer?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case menuRenderer = "menuRenderer"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
menuRenderer = try values.decodeIfPresent(MenuRenderer.self, forKey: .menuRenderer)
|
||||
}
|
||||
struct MenuRenderer: Codable {
|
||||
let items:[Item]?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case items = "items"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
items = try values.decodeIfPresent([Item].self, forKey: .items)
|
||||
}
|
||||
struct Item: Codable {
|
||||
let menuNavigationItemRenderer:MenuNavigationItemRenderer?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case menuNavigationItemRenderer = "menuNavigationItemRenderer"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
menuNavigationItemRenderer = try values.decodeIfPresent(MenuNavigationItemRenderer.self, forKey: .menuNavigationItemRenderer)
|
||||
}
|
||||
struct MenuNavigationItemRenderer: Codable {
|
||||
let navigationEndpoint:NavigationEndpoint?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case navigationEndpoint = "navigationEndpoint"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
navigationEndpoint = try values.decodeIfPresent(NavigationEndpoint.self, forKey: .navigationEndpoint)
|
||||
}
|
||||
|
||||
struct NavigationEndpoint: Codable {
|
||||
let watchEndpoint:WatchEndpoint?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case watchEndpoint = "watchEndpoint"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
watchEndpoint = try values.decodeIfPresent(WatchEndpoint.self, forKey: .watchEndpoint)
|
||||
}
|
||||
struct WatchEndpoint: Codable {
|
||||
let playlistId:String?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case playlistId = "playlistId"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
playlistId = try values.decodeIfPresent(String.self, forKey: .playlistId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//歌曲详细数据内容
|
||||
struct PlaylistItemData: Codable {
|
||||
let videoId:String?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
@ -718,6 +653,7 @@ struct RootMusicResponsiveListItemRenderer: Codable {
|
||||
videoId = try values.decodeIfPresent(String.self, forKey: .videoId)
|
||||
}
|
||||
}
|
||||
//页面导向
|
||||
struct NavigationEndpoint: Codable {
|
||||
let browseEndpoint:BrowseEndpoint?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
@ -728,18 +664,16 @@ struct RootMusicResponsiveListItemRenderer: Codable {
|
||||
browseEndpoint = try values.decodeIfPresent(BrowseEndpoint.self, forKey: .browseEndpoint)
|
||||
}
|
||||
struct BrowseEndpoint: Codable {
|
||||
///预览ID,根据类型不同,视作不同作用
|
||||
let browseId:String?
|
||||
let params:String?
|
||||
let browseEndpointContextSupportedConfigs:BrowseEndpointContextSupportedConfigs?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case browseId = "browseId"
|
||||
case params = "params"
|
||||
case browseEndpointContextSupportedConfigs = "browseEndpointContextSupportedConfigs"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
browseId = try values.decodeIfPresent(String.self, forKey: .browseId)
|
||||
params = try values.decodeIfPresent(String.self, forKey: .params)
|
||||
browseEndpointContextSupportedConfigs = try values.decodeIfPresent(BrowseEndpointContextSupportedConfigs.self, forKey: .browseEndpointContextSupportedConfigs)
|
||||
}
|
||||
struct BrowseEndpointContextSupportedConfigs: Codable {
|
||||
@ -752,6 +686,7 @@ struct RootMusicResponsiveListItemRenderer: Codable {
|
||||
browseEndpointContextMusicConfig = try values.decodeIfPresent(BrowseEndpointContextMusicConfig.self, forKey: .browseEndpointContextMusicConfig)
|
||||
}
|
||||
struct BrowseEndpointContextMusicConfig: Codable {
|
||||
///预览类型
|
||||
let pageType:String?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case pageType = "pageType"
|
||||
@ -763,11 +698,106 @@ struct RootMusicResponsiveListItemRenderer: Codable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//菜单
|
||||
struct Menu: Codable {
|
||||
let menuRenderer:MenuRenderer?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case menuRenderer = "menuRenderer"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
menuRenderer = try values.decodeIfPresent(MenuRenderer.self, forKey: .menuRenderer)
|
||||
}
|
||||
struct MenuRenderer: Codable {
|
||||
///菜单选项
|
||||
let items:[Item]?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case items = "items"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
items = try values.decodeIfPresent([Item].self, forKey: .items)
|
||||
}
|
||||
struct Item: Codable {
|
||||
///具备播放功能的选项(默认取包含watchEndpoint)
|
||||
let menuNavigationItemRenderer:MenuNavigationItemRenderer?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case menuNavigationItemRenderer = "menuNavigationItemRenderer"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
menuNavigationItemRenderer = try values.decodeIfPresent(MenuNavigationItemRenderer.self, forKey: .menuNavigationItemRenderer)
|
||||
}
|
||||
struct MenuNavigationItemRenderer: Codable {
|
||||
///文本导航
|
||||
let navigationEndpoint:NavigationEndpoint?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case navigationEndpoint = "navigationEndpoint"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
navigationEndpoint = try values.decodeIfPresent(NavigationEndpoint.self, forKey: .navigationEndpoint)
|
||||
}
|
||||
//文本导航
|
||||
struct NavigationEndpoint: Codable {
|
||||
///资源特化
|
||||
let watchEndpoint:WatchEndpoint?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case watchEndpoint = "watchEndpoint"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
watchEndpoint = try values.decodeIfPresent(WatchEndpoint.self, forKey: .watchEndpoint)
|
||||
}
|
||||
//导向播放
|
||||
struct WatchEndpoint: Codable {
|
||||
///资源ID
|
||||
let videoId:String?
|
||||
///对应歌单ID(未必存在)
|
||||
let playlistId:String?
|
||||
///指向资源类型
|
||||
let watchEndpointMusicSupportedConfigs:WatchEndpointMusicSupportedConfigs?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case videoId = "videoId"
|
||||
case playlistId = "playlistId"
|
||||
case watchEndpointMusicSupportedConfigs = "watchEndpointMusicSupportedConfigs"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
videoId = try values.decodeIfPresent(String.self, forKey: .videoId)
|
||||
playlistId = try values.decodeIfPresent(String.self, forKey: .playlistId)
|
||||
watchEndpointMusicSupportedConfigs = try values.decodeIfPresent(WatchEndpointMusicSupportedConfigs.self, forKey: .watchEndpointMusicSupportedConfigs)
|
||||
}
|
||||
struct WatchEndpointMusicSupportedConfigs: Codable {
|
||||
let watchEndpointMusicConfig:WatchEndpointMusicConfig?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case watchEndpointMusicConfig = "watchEndpointMusicConfig"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
watchEndpointMusicConfig = try values.decodeIfPresent(WatchEndpointMusicConfig.self, forKey: .watchEndpointMusicConfig)
|
||||
}
|
||||
struct WatchEndpointMusicConfig: Codable {
|
||||
///资源类型
|
||||
let musicVideoType:String?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case musicVideoType = "musicVideoType"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
musicVideoType = try values.decodeIfPresent(String.self, forKey: .musicVideoType)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
///列表/专辑结构(通常是三组件构成,封面,一级标题,二级标题,额外包含ID内容)
|
||||
///列表/专辑/歌手结构(通常是三组件构成,封面,一级标题,二级标题,额外包含ID内容)
|
||||
struct RootMusicTwoRowItemRenderer: Codable {
|
||||
///内容预览图片
|
||||
let thumbnailRenderer:ThumbnailRenderer?
|
||||
|
||||
@ -20,9 +20,7 @@ class MPPositive_BrowseItemModel: NSObject, Codable {
|
||||
var playListId:String?
|
||||
///列表专辑预览ID
|
||||
var browseId:String?
|
||||
///列表专辑预览参数
|
||||
var params:String?
|
||||
///艺术家Id
|
||||
///艺术家Id(当pageType == “MUSIC_PAGE_TYPE_ARTIST”时,与browseId等价)
|
||||
var artistId:String?
|
||||
///页面类型
|
||||
var pageType:String?
|
||||
|
||||
@ -72,7 +72,7 @@ class MPPositive_BaseViewController: MP_BaseViewController, UIGestureRecognizerD
|
||||
}
|
||||
//pop上一个页面
|
||||
@objc func popActionClick(_ sender:UIButton) {
|
||||
MPPositive_Debouncer.shared.call {
|
||||
MPPositive_Debouncer.shared.call(0.1) {
|
||||
[weak self] in
|
||||
guard let self = self else {return}
|
||||
navigationController?.popViewController(animated: true)
|
||||
|
||||
@ -137,7 +137,6 @@ class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewContro
|
||||
func presentGuide() {
|
||||
guard UserDefaults.standard.bool(forKey: "isGuide") != true else {
|
||||
//已经评论过了
|
||||
print("已经评论过了")
|
||||
return
|
||||
}
|
||||
//检索活跃天数是否达到3天
|
||||
@ -267,7 +266,7 @@ extension MPPositive_HomeViewController: UITableViewDataSource, UITableViewDeleg
|
||||
cell.requestNextBlock = {
|
||||
[weak self] (item) in
|
||||
guard let self = self else {return}
|
||||
MP_AnalyticsManager.shared.home_b_module_clickAction(MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.section].title ?? "")
|
||||
MP_AnalyticsManager.shared.home_b_module_clickAction(item.browseItem.pageType ?? "")
|
||||
switch item.browseItem.itemType {
|
||||
case .single:
|
||||
//单曲/视频跳转
|
||||
@ -299,7 +298,7 @@ extension MPPositive_HomeViewController: UITableViewDataSource, UITableViewDeleg
|
||||
case .list:
|
||||
isFirstAppearance = false
|
||||
//列表专辑
|
||||
let listVC = MPPositive_ListShowViewController(item.browseItem.browseId ?? "", params: item.browseItem.params ?? "", title: item.title ?? "", subtitle: item.subtitle ?? "")
|
||||
let listVC = MPPositive_ListShowViewController(item.browseItem.browseId ?? "", params: "", title: item.title ?? "", subtitle: item.subtitle ?? "")
|
||||
navigationController?.pushViewController(listVC, animated: true)
|
||||
case .artist:
|
||||
isFirstAppearance = false
|
||||
|
||||
@ -166,7 +166,7 @@ extension MPPositive_MoreContentViewController: UICollectionViewDataSource, UICo
|
||||
navigationController?.pushViewController(artistVC, animated: true)
|
||||
default:
|
||||
//列表专辑
|
||||
let listVC = MPPositive_ListShowViewController(browseModuleList.items[indexPath.row].browseItem.browseId ?? "", params: browseModuleList.items[indexPath.row].browseItem.params ?? "", title: browseModuleList.items[indexPath.row].title ?? "", subtitle: browseModuleList.items[indexPath.row].subtitle ?? "")
|
||||
let listVC = MPPositive_ListShowViewController(browseModuleList.items[indexPath.row].browseItem.browseId ?? "", params: "", title: browseModuleList.items[indexPath.row].title ?? "", subtitle: browseModuleList.items[indexPath.row].subtitle ?? "")
|
||||
navigationController?.pushViewController(listVC, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,27 +36,9 @@ class MPPositive_HomeSinglesTableViewCell: UITableViewCell, UIViewControllerTran
|
||||
didSet{
|
||||
titleLabel.text = browseViewModel.title
|
||||
collectionView.reloadData()
|
||||
// let groupSize = browseViewModel.items.count / 3 // 每组的元素数量
|
||||
// var remainder = browseViewModel.items.count % 3 // 不完整组的元素数量
|
||||
// let numberOfGroups = 3 // 组数
|
||||
// var groups = [[MPPositive_BrowseItemViewModel]]() // 存储分组结果的数组
|
||||
// var start = 0
|
||||
// for _ in 0..<numberOfGroups {
|
||||
// let end = start + groupSize + (remainder > 0 ? 1 : 0)
|
||||
// let group = Array(browseViewModel.items[start..<end])
|
||||
// groups.append(group)
|
||||
// start = end
|
||||
// remainder -= 1
|
||||
// }
|
||||
// items = groups
|
||||
}
|
||||
}
|
||||
///刷新数据组
|
||||
// private var items:[[MPPositive_BrowseItemViewModel]] = []{
|
||||
// didSet{
|
||||
// collectionView.reloadData()
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
@ -143,6 +125,7 @@ extension MPPositive_HomeSinglesTableViewCell:UICollectionViewDataSource, UIColl
|
||||
return
|
||||
}
|
||||
let item = self.browseViewModel.items[indexPath.row]
|
||||
MP_AnalyticsManager.shared.home_b_module_clickAction(item.browseItem.pageType ?? "")
|
||||
MP_AnalyticsManager.shared.song_clickAction("Home")
|
||||
//优先清除数据
|
||||
MP_PlayerManager.shared.loadPlayer = nil
|
||||
|
||||
Loading…
Reference in New Issue
Block a user