ToneSnap_FSX_Flutter/lib/modules/sideb/home/home_controller.dart
fengshengxiong caded892d9 1.新增瀑布流插页广告
2.新增增埋点
2024-08-14 13:56:43 +08:00

259 lines
10 KiB
Dart

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<HomeController>();
var viewState = ViewState.loading.obs;
var groupList = <BrowseGroupModel>[].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<void> _getIsoCode() async {
BaseModel<IsoCodeModel>? model = await TikUsTokApi.getIsoCode();
if (model != null && model.success && model.data?.isoCode != null) {
AppConfig.isoCode = model.data!.isoCode!;
}
}
/// 首次请求
Future<void> firstBrowse() async {
await _getIsoCode();
Map<String, dynamic> queryParameters = {
'prettyPrint': false,
'browseId': 'FEmusic_home'
};
BrowseModel? browseModel = await MusicApi.browse<BrowseModel>(
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<void> _reBrowse({String? continuation, String? clickTrackingParams}) async {
Map<String, dynamic> queryParameters = {
'ctoken': continuation,
'continuation': continuation,
'type': 'next',
'itct': clickTrackingParams,
'prettyPrint': false
};
BrowseModel? browseModel = await MusicApi.browse<BrowseModel>(
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<SectionListContinuationContent>? 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<ThumbnailElement>? 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));
}
}