270 lines
9.6 KiB
Dart
270 lines
9.6 KiB
Dart
import 'package:get/get.dart';
|
||
import 'package:hgdj/hj_model/video_model.dart';
|
||
import 'package:hgdj/hj_page/pre_sale/pre_sale_page.dart';
|
||
import 'package:hgdj/hj_page/pre_sale/pre_sale_provider.dart';
|
||
import 'package:hgdj/hj_page/user_center_page/user_center_page.dart';
|
||
import 'package:hgdj/hj_page/video/video_page.dart';
|
||
import 'package:hgdj/tools_base/debug_log.dart';
|
||
import 'package:hgdj/tools_base/event_bus/events.dart';
|
||
import 'package:hgdj/tools_base/headphone_monitor.dart';
|
||
import 'package:hgdj/tools_base/loading/loading_helper.dart';
|
||
import 'package:hgdj/tools_base/toast.dart';
|
||
import 'package:url_launcher/url_launcher.dart';
|
||
|
||
import '../config/config.dart';
|
||
import '../hj_model/cartoon_media_info.dart';
|
||
import '../hj_page/cartoon/cartoon_detail_page.dart';
|
||
import '../hj_page/cartoon/novel_detail_page.dart';
|
||
import '../hj_page/community/post_detail_page/post_detail_page.dart';
|
||
import '../hj_page/community/publish_page/publish_page.dart';
|
||
import '../hj_page/find/acg_game_detail_page.dart';
|
||
import '../hj_page/find/rank_module/rank_main_page.dart';
|
||
import '../hj_page/mine/mine_setting/bing_phone_page.dart';
|
||
import '../hj_page/mine/mine_share/mine_share_page.dart';
|
||
import '../hj_page/mine/mine_vip/mine_charge_coin_page.dart';
|
||
import '../hj_page/mine/mine_vip/mine_charge_vip_page.dart';
|
||
import '../hj_page/mine/mine_vip/pay_order_source.dart';
|
||
import '../hj_page/mine/welfare/welfare_home_page.dart';
|
||
import '../hj_page/short_video/short_video_page.dart';
|
||
import '../hj_page/web_page/h5_page.dart';
|
||
import '../hj_utils/api_service/vid_service.dart';
|
||
import '../tools_base/event_bus/event_bus_util.dart';
|
||
|
||
/// 跳转视频/动漫/短视频详情页
|
||
/// - [isCartoon] 优先级最高 → 长视频页(标记动漫)
|
||
/// - newsType == SEED_LINK → ACG 游戏详情页
|
||
/// - playTime < 300 且非 0 → 短视频
|
||
/// - 其余 → 长视频
|
||
/// - [videoModel] / [videoId] 必传其一
|
||
Future? pushToVideoPage({
|
||
String? videoId,
|
||
VideoModel? videoModel,
|
||
bool isCartoon = false,
|
||
String? videoCover,
|
||
List<VideoModel>? videoArr,
|
||
}) {
|
||
// 1. 动漫优先:跳长视频
|
||
if (isCartoon) {
|
||
return Get.to(
|
||
() => VideoPage(
|
||
id: videoModel?.id ?? videoId,
|
||
isCartoon: true,
|
||
videoCover: videoCover ?? videoModel?.cover,
|
||
),
|
||
preventDuplicates: false,
|
||
);
|
||
}
|
||
|
||
// 2. SEED_LINK:跳 ACG 游戏详情
|
||
if (videoModel?.newsType == 'SEED_LINK') {
|
||
return Get.to(() => AcgGameDetailPage(id: videoModel?.id ?? ''),
|
||
preventDuplicates: false);
|
||
}
|
||
|
||
// 3. 短视频:playTime < 300 且非 0(此分支 videoModel 必非 null,playTime 取自它)
|
||
final playTime = videoModel?.playTime ?? 1000;
|
||
if (playTime < 300 && playTime != 0) {
|
||
final list = videoArr?.isNotEmpty == true ? videoArr! : [videoModel!];
|
||
final idx = list.indexWhere((e) => e.id == videoModel?.id);
|
||
return Get.to(
|
||
() => ShortVideoPage(
|
||
type: VideoListType.SECOND,
|
||
videoList: list,
|
||
pageIndex: idx < 0 ? 0 : idx,
|
||
),
|
||
preventDuplicates: false,
|
||
);
|
||
}
|
||
|
||
// 4. 默认:长视频
|
||
return Get.to(() => VideoPage(
|
||
id: videoId ?? videoModel?.id,
|
||
videoCover: videoCover ?? videoModel?.cover,
|
||
model: videoModel,
|
||
));
|
||
}
|
||
|
||
/// 跳转卡通详情:按 mediaType 分发
|
||
void pushToCartoonPage(CartoonMediaInfo? info) {
|
||
switch (info?.mediaType) {
|
||
case 'image':
|
||
Get.to(
|
||
CartoonDetailPage(id: info?.id ?? '', heroTag: info?.heroTag),
|
||
preventDuplicates: false,
|
||
);
|
||
return;
|
||
case 'text':
|
||
Get.to(NovelDetailPage(info?.id), preventDuplicates: false);
|
||
return;
|
||
case 'video':
|
||
pushToVideoPage(
|
||
videoId: info?.id ?? '', isCartoon: true, videoCover: info?.coverV);
|
||
return;
|
||
}
|
||
}
|
||
|
||
/// 解析 deeplink/h5 链接并执行跳转
|
||
/// [sourcePage] 链接落到会员/金币页时的下单来源(如首页浮窗),不传走 pushToWalletPage 的默认
|
||
Future? pushToPageByLink(String? url,
|
||
{Map<String, dynamic>? arguments, PaySourcePage? sourcePage}) async {
|
||
if (url?.isNotEmpty != true) return null;
|
||
|
||
Uri? uri;
|
||
try {
|
||
uri = Uri.parse(url!);
|
||
} catch (e) {
|
||
debugLog("go func", e.toString());
|
||
}
|
||
if (uri == null) return null;
|
||
|
||
arguments ??= {};
|
||
arguments.addAll(uri.queryParameters);
|
||
|
||
final host = uri.host.toLowerCase().removeAllWhitespace;
|
||
|
||
if (uri.scheme == "yinseinner") {
|
||
return _handleYinseInnerLink(host, arguments, sourcePage);
|
||
}
|
||
// http(s):默认走外部浏览器;带 inner=1 走内部 H5
|
||
if (uri.scheme.startsWith("http")) {
|
||
if (uri.queryParameters["inner"] == "1") {
|
||
// InAppWebView 是 PlatformView,创建时会重建渲染 Surface;视频在播放(Texture持续产帧)会导致部分机型画面放大/闪烁,先暂停所有播放
|
||
HeadphoneMonitor.instance.pauseAll();
|
||
return Get.to(H5Page(url: url!, showTitle: false, showClose: true),
|
||
popGesture: true);
|
||
}
|
||
return launchUrlToWeb(url!);
|
||
}
|
||
showToast("未知链接");
|
||
return null;
|
||
}
|
||
|
||
/// 处理 yinseinner:// 内部 scheme 跳转
|
||
Future? _handleYinseInnerLink(String host, Map<String, dynamic> arguments,
|
||
[PaySourcePage? sourcePage]) async {
|
||
switch (host) {
|
||
case "submodule": // 亚模块分类
|
||
eventBus.emit(YinseinnerModel(routeName: "module", id: arguments["id"]));
|
||
return null;
|
||
case "navigation_bar": // 导航栏 亚模块菜单弹出
|
||
eventBus.emit(YinseinnerModel(routeName: "navigation_bar"));
|
||
return null;
|
||
case "community_module": // 社区
|
||
eventBus.emit(
|
||
YinseinnerModel(routeName: "community_module", id: arguments["id"]));
|
||
return null;
|
||
case "vip_page": // 会员中心
|
||
return pushToWalletPage(vipId: arguments['id'], sourcePage: sourcePage);
|
||
case "wallet_page": // 金币购买
|
||
return pushToWalletPage(tabPosition: 1, sourcePage: sourcePage);
|
||
case "universal_agent": // 分享推广
|
||
return Get.to(() => MineSharePage(), preventDuplicates: false);
|
||
case "lottery": // 抽奖
|
||
presaleProvider.openLuckyDraw();
|
||
return null;
|
||
case "rankinglist": // 排行榜
|
||
return Get.to(RankMainPage(), preventDuplicates: false);
|
||
case "postdetail": // 帖子详情
|
||
return Get.to(() => PostDetailPage(
|
||
argument: PostDetailPageArgument(id: arguments["id"])));
|
||
case "video_page": // 长视频播放页
|
||
return Get.to(() => VideoPage(id: arguments["id"]),
|
||
preventDuplicates: false);
|
||
case "taskhall": // 福利任务
|
||
return Get.to(() => const WelfareHomePage(index: 1),
|
||
preventDuplicates: false);
|
||
case "advancepage": // 预售
|
||
return Get.to(() => const PreSalePage());
|
||
case "live_streaming": // 直播
|
||
eventBus.emit(YinseinnerModel(routeName: "live_streaming"));
|
||
return null;
|
||
case "shop_page": // 原味商店
|
||
if (!Config.isStoreOpen) return null;
|
||
try {
|
||
LoadingHelper.showLoading();
|
||
final result = await VidService.getShopAddress();
|
||
LoadingHelper.dismissLoading();
|
||
if (result is String && result.isEmpty) {
|
||
showToast("获取商店地址失败~");
|
||
return null;
|
||
}
|
||
HeadphoneMonitor.instance.pauseAll();
|
||
return Get.to(H5Page(url: result), popGesture: true);
|
||
} catch (e) {
|
||
LoadingHelper.dismissLoading();
|
||
debugLog(e);
|
||
return null;
|
||
}
|
||
case "userhomepage": // 跳转博主
|
||
final uid = arguments["uid"] ?? 0;
|
||
if (uid == 0) return null;
|
||
return pushToPersonCenter(uid);
|
||
case "publish_page": // 发布
|
||
return Get.to(() => const PublishPage(type: PublishType.homeImgText));
|
||
case "binding_page": // 绑定手机
|
||
return Get.to(() => const BindPhonePage(pageType: PhonePageType.bind));
|
||
case "science": // AI
|
||
eventBus.emit(YinseinnerModel(routeName: "ai"));
|
||
return null;
|
||
default:
|
||
showToast("未处理链接");
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/// 浏览器跳转(先 externalApplication,再 platformDefault 兜底)
|
||
Future launchUrlToWeb(String url, {String? tip}) async {
|
||
final uri = Uri.tryParse(url);
|
||
if (uri == null) {
|
||
debugLog('launchUrlToWeb invalid url: $url');
|
||
return;
|
||
}
|
||
|
||
const launchModes = <LaunchMode>[
|
||
LaunchMode.externalApplication,
|
||
LaunchMode.platformDefault,
|
||
];
|
||
|
||
try {
|
||
for (final mode in launchModes) {
|
||
final launched = await launchUrl(uri, mode: mode);
|
||
if (launched) {
|
||
if (tip?.isNotEmpty == true) showToast(tip!);
|
||
return;
|
||
}
|
||
}
|
||
debugLog('launchUrlToWeb failed: $url');
|
||
} catch (e) {
|
||
debugLog(e);
|
||
}
|
||
}
|
||
|
||
/// 跳转个人中心
|
||
/// [type]==1 历史业务(ActressMainPage)已下线
|
||
/// [id] 深链传进来可能是字符串,统一收敛成 int
|
||
Future? pushToPersonCenter(dynamic id, {int? type}) {
|
||
if (type == 1) return null;
|
||
final uid = id is int ? id : int.tryParse('$id') ?? 0;
|
||
return Get.to(() => UserCenterPage(uid: uid), preventDuplicates: false);
|
||
}
|
||
|
||
/// 跳转到充值/会员页(tabPosition==1 → 金币,否则 → 会员)
|
||
/// [sourcePage] 落地页下单时的来源。不传时各分支用各自的默认:会员页记会员中心
|
||
/// (绝大多数入口都是「跳进会员页再下单」),金币页记 UNKNOWN(没有专属枚举,别拿会员的顶上);
|
||
/// 有独立来源的(H5 活动等)自己传
|
||
Future pushToWalletPage(
|
||
{int? tabPosition, String? vipId, PaySourcePage? sourcePage}) async {
|
||
if (tabPosition == 1) {
|
||
return Get.to(
|
||
MineChargeCoinPage(sourcePage: sourcePage ?? PaySourcePage.unknown),
|
||
preventDuplicates: false);
|
||
}
|
||
return Get.to(
|
||
MineChargeVipPage(
|
||
vipID: vipId?.isNotEmpty == true ? vipId : null,
|
||
sourcePage: sourcePage ?? PaySourcePage.vipCenter,
|
||
),
|
||
preventDuplicates: false,
|
||
);
|
||
}
|