import 'package:easy_refresh/easy_refresh.dart'; import 'package:get/get.dart'; import 'package:tone_snap/ads/interstitial_ad_manager.dart'; import 'package:tone_snap/components/view_state_widget.dart'; import 'package:tone_snap/data/api/music_api.dart'; import 'package:tone_snap/data/api/tikustok_api.dart'; import 'package:tone_snap/data/enum/ad_scenes.dart'; import 'package:tone_snap/data/enum/music_type.dart'; import 'package:tone_snap/data/models/base_model.dart'; import 'package:tone_snap/data/models/browse_group_model.dart'; import 'package:tone_snap/data/models/browse_model.dart'; import 'package:tone_snap/data/models/isocode_model.dart'; import 'package:tone_snap/data/models/music_model.dart'; import 'package:tone_snap/data/network/base_error.dart'; import 'package:tone_snap/firebase/firebase_analytics_manager.dart'; import 'package:tone_snap/global/app_config.dart'; import 'package:tone_snap/routes/app_routes.dart'; import 'package:tone_snap/utils/obj_util.dart'; class HomeController extends GetxController { static HomeController get to => Get.find(); var viewState = ViewState.loading.obs; var groupList = [].obs; String? visitorData; var refreshController = EasyRefreshController( controlFinishRefresh: true, ); var isRefresh = false; @override void onReady() { super.onReady(); firstBrowse(); } @override void onClose() { refreshController.dispose(); super.onClose(); } void onRefresh() { isRefresh = true; refreshController.callRefresh(); firstBrowse(); } void onTapTryAgain() { viewState.value = ViewState.loading; firstBrowse(); } /// 获取所在区域 Future _getIsoCode() async { BaseModel? model = await TikUsTokApi.getIsoCode(); if (model != null && model.success && model.data?.isoCode != null) { AppConfig.isoCode = model.data!.isoCode!; } } /// 首次请求 Future firstBrowse() async { await _getIsoCode(); Map queryParameters = { 'prettyPrint': false, 'browseId': 'FEmusic_home' }; BrowseModel? browseModel = await MusicApi.browse( queryParameters: queryParameters, formJson: BrowseModel.fromMap, fail: (BaseError baseError) { refreshController.finishRefresh(IndicatorResult.fail); FirebaseAnalyticsManager.logHomeBModuleFailAction('${baseError.code},${baseError.message}'); }, ); if (browseModel != null) { refreshController.finishRefresh(); _extractAssemblyData(browseModel); // 获取 visitorData visitorData = browseModel.responseContext?.visitorData; // 获取 continuation、clickTrackingParams var continuations = browseModel.contents?.singleColumnBrowseResultsRenderer?.tabs?[0].tabRenderer?.content?.sectionListRenderer?.continuations; String? continuation; String? clickTrackingParams; if (continuations != null && continuations.isNotEmpty) { continuation = continuations[0].nextContinuationData?.continuation; clickTrackingParams = continuations[0].nextContinuationData?.clickTrackingParams; } _reBrowse(continuation: continuation, clickTrackingParams: clickTrackingParams); if (groupList.isNotEmpty) { FirebaseAnalyticsManager.logHomeBModuleShowsuccesAction(); } else { FirebaseAnalyticsManager.logHomeBModuleFailAction('无数据'); } } viewState.value = groupList.isNotEmpty ? ViewState.normal : ViewState.empty; } /// 复用请求 Future _reBrowse({String? continuation, String? clickTrackingParams}) async { Map queryParameters = { 'ctoken': continuation, 'continuation': continuation, 'type': 'next', 'itct': clickTrackingParams, 'prettyPrint': false }; BrowseModel? browseModel = await MusicApi.browse( visitorData: visitorData, queryParameters: queryParameters, formJson: BrowseModel.fromMap, ); if (browseModel != null) { _extractAssemblyData(browseModel); var continuations = browseModel.continuationContents?.sectionListContinuation?.continuations; if (continuations != null && continuations.isNotEmpty) { // continuation、clickTrackingParams 若不为空,继续请求 if (continuations[0].nextContinuationData?.continuation != null && continuations[0].nextContinuationData?.clickTrackingParams != null) { _reBrowse(continuation: continuations[0].nextContinuationData?.continuation, clickTrackingParams: continuations[0].nextContinuationData?.clickTrackingParams); } } } } /// 提取首页数据,组装展示数据 void _extractAssemblyData(BrowseModel browseModel) { List? contents; if (browseModel.contents?.singleColumnBrowseResultsRenderer?.tabs?[0].tabRenderer?.content != null) { contents = browseModel.contents?.singleColumnBrowseResultsRenderer?.tabs?[0].tabRenderer?.content?.sectionListRenderer?.contents; } else if (browseModel.continuationContents != null) { contents = browseModel.continuationContents?.sectionListContinuation?.contents; } if (contents != null && contents.isNotEmpty) { for (var e1 in contents) { var browseGroupModel = BrowseGroupModel(); // 获取头部标题 var runs = e1.musicCarouselShelfRenderer?.header?.musicCarouselShelfBasicHeaderRenderer?.title?.runs; if (runs != null && runs.isNotEmpty) { browseGroupModel.groupTitle = runs[0].text; } var contents = e1.musicCarouselShelfRenderer?.contents; if (contents != null) { browseGroupModel.browseList ??= []; for (var e2 in contents) { var musicModel = MusicModel(); // 获取封面缩略图 List? thumbnails; if (e2.musicResponsiveListItemRenderer != null) { thumbnails = e2.musicResponsiveListItemRenderer?.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails; var flexColumns = e2.musicResponsiveListItemRenderer?.flexColumns; if (flexColumns != null) { for (var e3 in flexColumns) { var runs = e3.musicResponsiveListItemFlexColumnRenderer?.text?.runs; if (flexColumns.indexOf(e3) == 0) { if (runs != null && runs.isNotEmpty) { // 获取主标题 musicModel.title = runs[0].text; // 获取数据类型 if (runs[0].navigationEndpoint?.watchEndpoint != null) { browseGroupModel.musicType = runs[0].navigationEndpoint?.watchEndpoint?.watchEndpointMusicSupportedConfigs?.watchEndpointMusicConfig?.musicVideoType; musicModel.videoId = runs[0].navigationEndpoint?.watchEndpoint?.videoId; musicModel.playlistId = runs[0].navigationEndpoint?.watchEndpoint?.playlistId; } else if (runs[0].navigationEndpoint?.browseEndpoint != null) { browseGroupModel.musicType = runs[0].navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType; musicModel.browseId = runs[0].navigationEndpoint?.browseEndpoint?.browseId; musicModel.params = runs[0].navigationEndpoint?.browseEndpoint?.params; } } } else { // 获取副标题 if (runs != null && runs.isNotEmpty) { musicModel.subtitle = runs.map((e) => e.text).join(); } } } } } else if (e2.musicTwoRowItemRenderer != null) { thumbnails = e2.musicTwoRowItemRenderer?.thumbnailRenderer?.musicThumbnailRenderer?.thumbnail?.thumbnails; // 获取主标题 var runs = e2.musicTwoRowItemRenderer?.title?.runs; if (runs != null && runs.isNotEmpty) { musicModel.title = runs[0].text; } // 获取副标题 var subtitleRuns = e2.musicTwoRowItemRenderer?.subtitle?.runs; if (subtitleRuns != null && subtitleRuns.isNotEmpty) { musicModel.subtitle = subtitleRuns.map((e) => e.text).join(); } // 获取数据类型 if (e2.musicTwoRowItemRenderer?.navigationEndpoint != null) { browseGroupModel.musicType = e2.musicTwoRowItemRenderer?.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType; musicModel.browseId = e2.musicTwoRowItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId; musicModel.params = e2.musicTwoRowItemRenderer?.navigationEndpoint?.browseEndpoint?.params; } } if (thumbnails != null && thumbnails.isNotEmpty) { musicModel.coverUrl = thumbnails.last.url; } browseGroupModel.browseList?.add(musicModel); } } // 根据类型判断是否添加 if (MusicTypeExtension.isThereAny(browseGroupModel.musicType)) { if (isRefresh) { groupList.clear(); isRefresh = false; } groupList.add(browseGroupModel); } } } } void openSearch() { FirebaseAnalyticsManager.logSearchFromAction('来自首页'); Get.toNamed(AppRoutes.searchResult); } void openSetting() { Get.toNamed(AppRoutes.setting); } void openPlayPage(BrowseGroupModel browseGroupModel, MusicModel musicModel) { InterstitialAdManager().showAdIfAvailable( AdScenes.play.name, onTap: () { Get.toNamed(AppRoutes.playPage, arguments: { 'videoId': musicModel.videoId, 'playlistId': musicModel.playlistId, }); }, ); FirebaseAnalyticsManager.logHomeBModuleClick(ObjUtil.getStr(browseGroupModel.groupTitle)); FirebaseAnalyticsManager.logSongClick('来自首页'); } void openAlbumSong(BrowseGroupModel browseGroupModel, MusicModel musicModel) { Get.toNamed(AppRoutes.albumSongList, arguments: { 'musicType': browseGroupModel.musicType, 'browseId': musicModel.browseId, 'params': musicModel.params, 'coverUrl': musicModel.coverUrl, 'title': musicModel.title, 'subtitle': musicModel.subtitle, }); FirebaseAnalyticsManager.logHomeBModuleClick(ObjUtil.getStr(browseGroupModel.groupTitle)); } }