You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1992 lines
69 KiB
1992 lines
69 KiB
|
3 weeks ago
|
import { assetManager, game, sys } from "cc";
|
||
|
|
import { BYTEDANCE, DEBUG, DEV, EDITOR, WECHAT } from "cc/env";
|
||
|
|
import { RewardedVideoAd } from "./functions/RewardedVideoAd";
|
||
|
|
import { sdkConfig } from "./sdkConfig";
|
||
|
|
|
||
|
|
/** SDK 流程跟踪(默认关,sdkConfig.enableSdkTraceLog) */
|
||
|
|
const sdkTrace = (...args: unknown[]): void => {
|
||
|
|
if (!sdkConfig.enableSdkTraceLog) return;
|
||
|
|
const parts: string[] = [];
|
||
|
|
for (let i = 0; i < args.length; i++) {
|
||
|
|
const a = args[i];
|
||
|
|
if (a !== null && typeof a === 'object') continue;
|
||
|
|
parts.push(String(a));
|
||
|
|
}
|
||
|
|
if (parts.length > 0) console.log(parts.join(' '));
|
||
|
|
};
|
||
|
|
import GEMgr from "./GEMgr";
|
||
|
|
import { InterstitialAd } from "./functions/InterstitialAd";
|
||
|
|
import { VivoAd } from "./functions/VivoAd";
|
||
|
|
import TTRecording from "./functions/TTRecording";
|
||
|
|
import { Share } from "./functions/Share";
|
||
|
|
import Vibrate from "./functions/VibrateMgr";
|
||
|
|
import { TTRank } from "./functions/TTRank";
|
||
|
|
import { Singleton } from "../../mx/tools/Singleton";
|
||
|
|
import {
|
||
|
|
createMembershipSet,
|
||
|
|
membershipAdd,
|
||
|
|
membershipHas,
|
||
|
|
type MembershipSet,
|
||
|
|
} from "../../mx/tools/MembershipSet";
|
||
|
|
import { ConstNumType, ItemNumType, StatisticsType, StatusType, TaskType, OtherDataType } from "../game/GameData";
|
||
|
|
import { GEvent } from "../../mx/module/event/GEvent";
|
||
|
|
import { MemoryDowngrade } from "../game/MemoryDowngrade";
|
||
|
|
import { PerfReport } from "../game/PerfReport";
|
||
|
|
import { UpdatePipeline } from "../../mx/module/boot/UpdatePipeline";
|
||
|
|
import { RankDataManager } from "../manager/RankDataManager";
|
||
|
|
import { MiniGamePf } from "../../mx/tools/MiniGameHostInfo";
|
||
|
|
|
||
|
|
/** 30r SDK 实例类型(实现见 Sdk30rWechat.ts,仅微信包加载) */
|
||
|
|
type Sdk30rInstance = {
|
||
|
|
track(event: string, msg: unknown): void;
|
||
|
|
onTutorialFinish(): void;
|
||
|
|
onRegister?(): void;
|
||
|
|
setOpenId(uid: string): void;
|
||
|
|
getInitResult(): { inited: boolean };
|
||
|
|
};
|
||
|
|
|
||
|
|
/** 订阅消息场景(对应 platformConf.subscribeTmpl) */
|
||
|
|
type SubscribeTmplScene = 'offlineEarnings' | 'vigourRecovery' | 'versionUpdate';
|
||
|
|
|
||
|
|
/** 宿主启动 / onShow 参数(侧边栏、桌面场景) */
|
||
|
|
type PfLaunchRes = {
|
||
|
|
from?: unknown;
|
||
|
|
launch_from?: unknown;
|
||
|
|
location?: unknown;
|
||
|
|
scene?: unknown;
|
||
|
|
query?: unknown;
|
||
|
|
};
|
||
|
|
|
||
|
|
/** game.js 抢先缓存的 onShow */
|
||
|
|
type PfShowStore = {
|
||
|
|
__pfShowCaptured?: boolean;
|
||
|
|
__pfLastShow?: PfLaunchRes | null;
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* SDK管理器
|
||
|
|
*/
|
||
|
|
export class SDKManager extends Singleton {
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 抖音头条录屏相关
|
||
|
|
*/
|
||
|
|
private Recording: TTRecording = null;
|
||
|
|
/**
|
||
|
|
* 分享相关
|
||
|
|
*/
|
||
|
|
Share: Share = new Share();
|
||
|
|
/**
|
||
|
|
* 震动
|
||
|
|
*/
|
||
|
|
Vibrate = Vibrate;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 当前平台
|
||
|
|
*/
|
||
|
|
pf = null;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 平台获取的查询参数
|
||
|
|
*/
|
||
|
|
query = "";
|
||
|
|
|
||
|
|
showAd = true;
|
||
|
|
|
||
|
|
upTestData = false;
|
||
|
|
|
||
|
|
levelS: number[] = [];
|
||
|
|
|
||
|
|
serverTime: number = 0;
|
||
|
|
|
||
|
|
timer: number | null = null;
|
||
|
|
|
||
|
|
sdk30r: Sdk30rInstance | null = null;
|
||
|
|
|
||
|
|
adCount = 0;
|
||
|
|
|
||
|
|
/** 推荐流直玩启动 */
|
||
|
|
private _feedDirectPlayLaunch = false;
|
||
|
|
/** feed_game_channel:1 复访,2 获客 */
|
||
|
|
private _feedGameChannel = 0;
|
||
|
|
/** feed_game_scene:0 获客,1 离线收益,2 体力,3 重要事件 */
|
||
|
|
private _feedGameScene = -1;
|
||
|
|
/** feed_game_content_id */
|
||
|
|
private _feedGameContentId = "";
|
||
|
|
/** 是否已真实进入(feedEnter) */
|
||
|
|
private _feedActuallyEntered = false;
|
||
|
|
/** reportScene(7001) 幂等 */
|
||
|
|
private _feedReportSceneDone = false;
|
||
|
|
private _feedReportSceneInFlight = false;
|
||
|
|
/** 预启动进关延后扣体力 */
|
||
|
|
private _feedPendingVigourDeduct = false;
|
||
|
|
/** 最近一次 onShow 是否侧边栏进入(快手 from / 抖音 launch_from / B 站 021036) */
|
||
|
|
private _fromSidebar = false;
|
||
|
|
/** 最近一次 onShow 是否 B 站桌面快捷方式(scene=10002) */
|
||
|
|
private _fromDesk = false;
|
||
|
|
/** 分享最小停留(微信无回调) */
|
||
|
|
private _shareTimeLimit = 0;
|
||
|
|
/** 分享结果回调 */
|
||
|
|
private _shareResultCb: Function | null = null;
|
||
|
|
/** 添加桌面检测回调 */
|
||
|
|
private _addDeskCb: Function | undefined;
|
||
|
|
/** 添加桌面操作回调 */
|
||
|
|
private _addShortcutCb: Function | undefined;
|
||
|
|
/** vivo installShortcut 已成功,complete 不再当成取消 */
|
||
|
|
private _vivoShortcutOk = false;
|
||
|
|
/** 侧边栏跳转回调 */
|
||
|
|
private _enterSidebarCb: Function | undefined;
|
||
|
|
/** 侧边栏可用性回调 */
|
||
|
|
private _sidebarCheckCb: Function | undefined;
|
||
|
|
/** 内存警告业务回调 */
|
||
|
|
private _memWarnCb: Function | null = null;
|
||
|
|
/** getUserInfo Promise resolve */
|
||
|
|
private _userInfoResolve: ((v: unknown) => void) | null = null;
|
||
|
|
/** 本会话已调起过的订阅场景(版本更新用存档按版本去重) */
|
||
|
|
private _subscribePrompted: MembershipSet<string> = createMembershipSet<string>();
|
||
|
|
private _feedStatusHandler: ((res: { type?: string }) => void) | null = null;
|
||
|
|
private _feedTouchFallbackBound: (() => void) | null = null;
|
||
|
|
/** 本进程是否已拉起过推荐流订阅面板(避免进大厅反复弹) */
|
||
|
|
private _feedSubscribePrompted = false;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 初始化
|
||
|
|
*/
|
||
|
|
async init() {
|
||
|
|
if (EDITOR || DEBUG || sys.isBrowser) {
|
||
|
|
this.upTestData = true;
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
this.pf = MiniGamePf.api();
|
||
|
|
if (!this.pf) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!MiniGamePf.isKs()) {
|
||
|
|
this.initUpdate();
|
||
|
|
}
|
||
|
|
|
||
|
|
this.capturePfShow();
|
||
|
|
if (typeof this.pf.onShow === 'function') {
|
||
|
|
this.pf.onShow(this.onPfShow.bind(this));
|
||
|
|
} else {
|
||
|
|
console.warn('[SDKManager] 宿主无 onShow');
|
||
|
|
}
|
||
|
|
if (typeof this.pf.onHide === 'function') {
|
||
|
|
this.pf.onHide(this.onPfHide.bind(this));
|
||
|
|
} else {
|
||
|
|
console.warn('[SDKManager] 宿主无 onHide');
|
||
|
|
}
|
||
|
|
this._applyLaunchOptions(this._readLatestLaunch());
|
||
|
|
this.setupFeedDirectPlay();
|
||
|
|
|
||
|
|
this.serverTime = new Date().getTime();
|
||
|
|
|
||
|
|
RewardedVideoAd.init(sdkConfig.config.platformConf.video);
|
||
|
|
InterstitialAd.init(sdkConfig.config.platformConf.interstitialAd);
|
||
|
|
this.Share.init(sdkConfig.config.platformConf.shareData);
|
||
|
|
this.openWXShareMenu()
|
||
|
|
if (sys.platform == sys.Platform.BYTEDANCE_MINI_GAME) {
|
||
|
|
this.Recording = TTRecording.Ins;
|
||
|
|
this.Recording.init(sdkConfig.config.platformConf);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MiniGamePf.isMy()) {
|
||
|
|
console.warn('[SDKManager] 支付宝不走 ZYSDK,云存档与登录不可用,使用本地存档');
|
||
|
|
this._bindMemoryWarning();
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
ZYSDK.ZYSDK.initSdk(sdkConfig.config.pointData.gid)
|
||
|
|
|
||
|
|
let serverData = null;
|
||
|
|
let uid: any = "123456";
|
||
|
|
while (serverData == null) {
|
||
|
|
gg.ui.showToast("获取游戏存档...");
|
||
|
|
uid = await ZYSDK.ZYSDK.getUserId();
|
||
|
|
sdkTrace("whileUid", uid);
|
||
|
|
if (uid == null || uid == 1 || uid == "")
|
||
|
|
await ZYSDK.ZYSDK.initSdk(sdkConfig.config.pointData.gid);
|
||
|
|
serverData = await this.getServerData();
|
||
|
|
}
|
||
|
|
|
||
|
|
let fun = () => {
|
||
|
|
let str = serverData;
|
||
|
|
if (serverData.length > 350) {
|
||
|
|
str = serverData.substring(0, 350);
|
||
|
|
}
|
||
|
|
gg.sdk.reportDY("inLevel", `存档异常-${str}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (serverData == "") {
|
||
|
|
gg.sdk.reportDY("inLevel", `新玩家-${uid}`);
|
||
|
|
}
|
||
|
|
else if (serverData == undefined) {
|
||
|
|
gg.sdk.reportDY("inLevel", `存档异常-undefined`);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
try {
|
||
|
|
let sd = JSON.parse(serverData);
|
||
|
|
if (!Object.hasOwnProperty.call(sd, "uid")) {
|
||
|
|
fun();
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
fun();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
let v = ZYSDK.ZYSDK.getCustomValue();
|
||
|
|
|
||
|
|
if (v == 0) this.upTestData = false;
|
||
|
|
else if (v == 100) this.upTestData = true;
|
||
|
|
else {
|
||
|
|
this.upTestData = Math.random() <= v / 100;
|
||
|
|
}
|
||
|
|
|
||
|
|
let lvs = await ZYSDK.ZYSDK.getLevel();
|
||
|
|
|
||
|
|
if (lvs && lvs.length > 0) {
|
||
|
|
this.levelS = lvs;
|
||
|
|
}
|
||
|
|
|
||
|
|
// this.pf.login({
|
||
|
|
// force: true,
|
||
|
|
// success(res) {
|
||
|
|
// console.log(`login 调用成功${res.code} ${res.anonymousCode}`);
|
||
|
|
// },
|
||
|
|
// fail(res) {
|
||
|
|
// console.log(`login 调用失败`);
|
||
|
|
// },
|
||
|
|
// });
|
||
|
|
|
||
|
|
if (this.timer != null) {
|
||
|
|
window.clearInterval(this.timer);
|
||
|
|
this.timer = null;
|
||
|
|
}
|
||
|
|
if (sdkConfig.serverTimeCheckInterval > 0) {
|
||
|
|
await this.updateServerTime();
|
||
|
|
this.timer = window.setInterval(() => {
|
||
|
|
this.updateServerTime();
|
||
|
|
}, sdkConfig.serverTimeCheckInterval);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
this.checkTime((curentTime) => {
|
||
|
|
if (curentTime) {
|
||
|
|
console.error("时间异常");
|
||
|
|
gg.ui.showToast("时间异常,请检查时间设置");
|
||
|
|
gg.sdk.reportDY("inLevel", `时间异常-本地时间${curentTime}`);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
this._bindMemoryWarning();
|
||
|
|
return serverData
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 监听宿主内存警告。支付宝用 my.onMemoryWarning + my.getSystemInfoSync */
|
||
|
|
private _bindMemoryWarning(): void {
|
||
|
|
this.onMemoryWarning(this._onMemoryWarnReport);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 内存警告:记机型并降级 */
|
||
|
|
private _onMemoryWarnReport = (): void => {
|
||
|
|
try {
|
||
|
|
const res = this.pf.getSystemInfoSync();
|
||
|
|
const brand = res.brand || res.system || '';
|
||
|
|
const model = res.model || '';
|
||
|
|
this.pfLog(`内存不足, 手机型号为 ${brand} ${model}`);
|
||
|
|
MemoryDowngrade.onMemoryWarning();
|
||
|
|
PerfReport.reportMemWarn(MemoryDowngrade.warnCountInPhase, MemoryDowngrade.level);
|
||
|
|
} catch (error) {
|
||
|
|
sdkTrace(`获取系统信息失败`);
|
||
|
|
MemoryDowngrade.onMemoryWarning();
|
||
|
|
PerfReport.reportMemWarn(MemoryDowngrade.warnCountInPhase, MemoryDowngrade.level);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
/** 30r / DataNexus 仅微信小游戏;源码在 tools/wechat-only/,微信构建前由 tools 扩展复制进 assets */
|
||
|
|
initSdk30r() {
|
||
|
|
if (!WECHAT || MiniGamePf.isKs() || MiniGamePf.isBl() || DEV || EDITOR || sys.isBrowser) return;
|
||
|
|
const dnCfg = sdkConfig.config.dnSdk30r;
|
||
|
|
if (!dnCfg?.user_action_set_id || !dnCfg?.secret_key) return;
|
||
|
|
try {
|
||
|
|
// 模块由 tools/wechat-only 在微信构建时复制进来;编辑期不存在,故用 ts-ignore
|
||
|
|
// @ts-ignore - Sdk30rWechat 仅微信构建期存在
|
||
|
|
const { createSdk30r } = require('./Sdk30rWechat');
|
||
|
|
this.sdk30r = createSdk30r({
|
||
|
|
user_action_set_id: dnCfg.user_action_set_id,
|
||
|
|
secret_key: dnCfg.secret_key,
|
||
|
|
appid: sdkConfig.config.platformConf.appid,
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
console.error('initSdk30r error', String(error));
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
const initResult = this.sdk30r?.getInitResult();
|
||
|
|
if (!initResult?.inited) {
|
||
|
|
console.log('30r sdk 初始化失败', initResult);
|
||
|
|
} else {
|
||
|
|
sdkTrace('30r sdk 初始化成功');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
checkTime(callback: Function = null) {
|
||
|
|
if (!gg.sdk.pf || DEV || DEBUG || sys.isBrowser) {
|
||
|
|
if (callback) {
|
||
|
|
callback();
|
||
|
|
}
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
ZYSDK.ZYSDK.getTimestamp((res) => {
|
||
|
|
if (res && res.ts) {
|
||
|
|
let curentTime = new Date().getTime();
|
||
|
|
let servertime = res.ts * 1000;
|
||
|
|
sdkTrace("servertime:", servertime);
|
||
|
|
sdkTrace("curentTime:", curentTime);
|
||
|
|
if (Math.abs(servertime - curentTime) > 1000 * 60 * 30) {
|
||
|
|
callback(curentTime);
|
||
|
|
} else {
|
||
|
|
if (callback) {
|
||
|
|
callback();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}, () => {
|
||
|
|
console.error("获取时间失败");
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**获取服务器时间 */
|
||
|
|
getServerTime() {
|
||
|
|
// console.log("本机时间毫秒数(UTC):", new Date().getTime());
|
||
|
|
// console.log("本机时间格式化(UTC):", new Date().toUTCString());
|
||
|
|
// console.log("本机时间格式化(本地):", new Date().toLocaleString());
|
||
|
|
// console.log("服务器时间毫秒数:", this.serverTime);
|
||
|
|
// console.log("服务器时间格式化(UTC):", new Date(this.serverTime).toUTCString());
|
||
|
|
// console.log("服务器时间格式化(本地):", new Date(this.serverTime).toLocaleString());
|
||
|
|
if (DEV || DEBUG || sys.isBrowser || sdkConfig.serverTimeCheckInterval == 0) {
|
||
|
|
let time = new Date().getTime();
|
||
|
|
//console.log("走了本地时间:", time, "serverTimeCheckInterval:", sdkConfig.serverTimeCheckInterval);
|
||
|
|
return time;
|
||
|
|
}
|
||
|
|
return this.serverTime;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**更新服务器时间 */
|
||
|
|
updateServerTime() {
|
||
|
|
return new Promise((resolve, reject) => {
|
||
|
|
if (!sdkConfig.serverTimeCheckInterval) {
|
||
|
|
this.serverTime = Date.now();
|
||
|
|
resolve(null);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
ZYSDK.ZYSDK.getTimestamp((res) => {
|
||
|
|
if (res && res.ts) {
|
||
|
|
let num = res.ts * 1000;
|
||
|
|
this.serverTime = num;
|
||
|
|
resolve(null);
|
||
|
|
}
|
||
|
|
}, () => {
|
||
|
|
resolve(null);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
initUpdate() {
|
||
|
|
if (typeof this.pf?.getUpdateManager !== 'function') {
|
||
|
|
console.warn('[SDKManager] 宿主无 getUpdateManager');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
UpdatePipeline.bind(
|
||
|
|
this.pf.getUpdateManager(),
|
||
|
|
(opts) => this.pf.showModal(opts),
|
||
|
|
(opts) => this.pf.showToast(opts),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 重启小游戏。有 Sync 用 Sync;支付宝是 my.restartMiniProgram */
|
||
|
|
restartMiniProgramSync() {
|
||
|
|
const pf = this.pf;
|
||
|
|
if (!pf) return;
|
||
|
|
if (typeof pf.restartMiniProgramSync === 'function') {
|
||
|
|
pf.restartMiniProgramSync();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (typeof pf.restartMiniProgram === 'function') {
|
||
|
|
pf.restartMiniProgram({});
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
console.warn('[SDKManager] 宿主无重启接口');
|
||
|
|
}
|
||
|
|
|
||
|
|
getServerData() {
|
||
|
|
if (EDITOR || DEBUG || sys.platform == sys.Platform.DESKTOP_BROWSER || sys.platform == sys.Platform.MOBILE_BROWSER) {
|
||
|
|
return new Promise<string>((resolve, reject) => {
|
||
|
|
resolve("");
|
||
|
|
})
|
||
|
|
}
|
||
|
|
return new Promise<string>((resolve, reject) => {
|
||
|
|
ZYSDK.ZYSDK.getGameData((data) => {
|
||
|
|
resolve(data);
|
||
|
|
}, async () => {
|
||
|
|
resolve(null);
|
||
|
|
})
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 当前平台进入前台
|
||
|
|
* @param res
|
||
|
|
*/
|
||
|
|
onPfShow(res) {
|
||
|
|
sdkTrace("onPfShow", res);
|
||
|
|
this.query = res.query;
|
||
|
|
this._show_time = new Date().getTime();
|
||
|
|
RewardedVideoAd.onAppShow();
|
||
|
|
GEvent.Ins.emit(GEvent.PLATFORM_SHOW, res);
|
||
|
|
if (this._onShare) {
|
||
|
|
let t = new Date().getTime() - this._share_time;
|
||
|
|
this._onShare(t);
|
||
|
|
this._onShare = null;
|
||
|
|
}
|
||
|
|
this._applyLaunchOptions(res);
|
||
|
|
}
|
||
|
|
private _show_time = 0;
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 当前平台进入后台
|
||
|
|
*/
|
||
|
|
onPfHide() {
|
||
|
|
let c = new Date().getTime();
|
||
|
|
let t = c - this._show_time;
|
||
|
|
t = Math.floor(t / 1000);
|
||
|
|
sdkTrace("onPfHide,在线时长:" + t);
|
||
|
|
GEvent.Ins.emit(GEvent.PLATFORM_HIDE);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 显示视频广告
|
||
|
|
* @param callback 回调
|
||
|
|
*/
|
||
|
|
showVideoAd(callback: Function) {
|
||
|
|
sdkTrace('显示视频广告');
|
||
|
|
if (gg.data.getItemNum(ItemNumType.skipAd) > 0) {
|
||
|
|
gg.data.subItemNum(ItemNumType.skipAd, 1);
|
||
|
|
callback(true, "skipAd");
|
||
|
|
}
|
||
|
|
else if (EDITOR || !this.showAd) {
|
||
|
|
gg.data.addDayTaskProgressData(TaskType.videoAd, 1)
|
||
|
|
callback(true, "editor");
|
||
|
|
} else if (sys.isBrowser) {
|
||
|
|
gg.data.addDayTaskProgressData(TaskType.videoAd, 1)
|
||
|
|
callback(true, window.location.href);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
gg.audio.pause();
|
||
|
|
game.pause();
|
||
|
|
RewardedVideoAd.show((res) => {
|
||
|
|
game.resume();
|
||
|
|
gg.audio.resume();
|
||
|
|
if (res) {
|
||
|
|
this.adCount++;
|
||
|
|
callback(true);
|
||
|
|
gg.data.addStatistics(StatisticsType.TodayAdCount, 1);
|
||
|
|
gg.data.addDayTaskProgressData(TaskType.videoAd, 1)
|
||
|
|
ZYSDK.ZYSDK.reportVideo(true);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
callback(false);
|
||
|
|
ZYSDK.ZYSDK.reportVideo(false);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 上次显示插屏广告时间戳
|
||
|
|
*/
|
||
|
|
private _interAdTimeStamp = 0;
|
||
|
|
/**
|
||
|
|
* 显示插屏广告
|
||
|
|
* @param onAdClose
|
||
|
|
* @param onFail
|
||
|
|
*/
|
||
|
|
showInterstitialAd(onAdClose?: Function, onFail?: Function, useAdLevel = false) {
|
||
|
|
if (EDITOR) {
|
||
|
|
onAdClose && onAdClose(true, "editor");
|
||
|
|
} else if (sys.isBrowser) {
|
||
|
|
onAdClose && onAdClose(true, window.location.href);
|
||
|
|
} else if (VivoAd.isVivo()) {
|
||
|
|
this._showVivoNative(onFail);
|
||
|
|
} else {
|
||
|
|
if (!useAdLevel || ZYSDK.ZYSDK.getAdLevel() == 1) {
|
||
|
|
//判断是否间隔x秒
|
||
|
|
let curTime = new Date().getTime();
|
||
|
|
if (curTime - this._interAdTimeStamp < ZYSDK.ZYSDK.getAdInterval() * 1000) {
|
||
|
|
onFail && onFail();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this._interAdTimeStamp = curTime;
|
||
|
|
InterstitialAd.showInterstitialAd(onAdClose, onFail, () => {
|
||
|
|
this.reportDY("inLevel", `插屏-段位${RankDataManager.getPlayerRankId()}`);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* vivo 结算原生模板。与插屏共用冷却,不走 ZYSDK 广告等级。
|
||
|
|
* @param onFail 冷却中或未展示
|
||
|
|
*/
|
||
|
|
private _showVivoNative(onFail?: Function): void {
|
||
|
|
const curTime = new Date().getTime();
|
||
|
|
if (curTime - this._interAdTimeStamp < ZYSDK.ZYSDK.getAdInterval() * 1000) {
|
||
|
|
onFail?.();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (VivoAd.showNative()) this._interAdTimeStamp = curTime;
|
||
|
|
else onFail?.();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* vivo 退出浮层。其他渠道立即回调。
|
||
|
|
* @param onDone 关闭、失败或未展示后继续退出
|
||
|
|
*/
|
||
|
|
showVivoExitAd(onDone: () => void): void {
|
||
|
|
VivoAd.showExit(onDone);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 设置排行榜
|
||
|
|
* @param value 分数
|
||
|
|
* @param dataType 数据类型 0 数字类型 1 字符串类型
|
||
|
|
* @param priority 权重
|
||
|
|
* @param zoneId 排行榜分区
|
||
|
|
*/
|
||
|
|
setImRankData(value: number | string, dataType = 0, priority = 0, zoneId = "default") {
|
||
|
|
if (EDITOR) {
|
||
|
|
sdkTrace('平台无法写入排行榜数据')
|
||
|
|
} else if (sys.isBrowser) {
|
||
|
|
sdkTrace('平台无法写入排行榜数据')
|
||
|
|
} else {
|
||
|
|
TTRank.setImRankData(value, dataType, priority, zoneId)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* 获取排行榜
|
||
|
|
* @param rankTitle 排行榜标题
|
||
|
|
* @param suffix 分数后缀补充文案 为空或不填,一般枚举类型不需要填后缀
|
||
|
|
* @param rankType 排行榜类型 可选值有:day、week、month、month、all
|
||
|
|
* @param zoneId 排行榜分区
|
||
|
|
* @param dataType 数据类型: 0 数字类型 1 字符串类型
|
||
|
|
* @param relationType 排行榜类型 可选值有:default 好友榜、总榜都展示 friend 仅展示好友榜 all 仅展示总榜
|
||
|
|
*/
|
||
|
|
getImRankList(rankTitle: string = "排行榜", suffix = "", rankType = "all", zoneId = "default", dataType = 0, relationType = "default") {
|
||
|
|
if (EDITOR) {
|
||
|
|
sdkTrace('平台无法获取排行榜数据')
|
||
|
|
} else if (sys.isBrowser) {
|
||
|
|
sdkTrace('平台无法获取排行榜数据')
|
||
|
|
} else {
|
||
|
|
TTRank.getImRankList(rankTitle, suffix, rankType, zoneId, dataType, relationType)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* 运营 / 关卡行为打点(进 Gravity userAction)
|
||
|
|
*/
|
||
|
|
reportDY(event, msg) {
|
||
|
|
if (sdkConfig.enableConsolePfLog) {
|
||
|
|
console.log("%c打点==", "color:green", msg);
|
||
|
|
}
|
||
|
|
if (MiniGamePf.canReport()) {
|
||
|
|
ZYSDK.ZYSDK.reportUserAction(msg);
|
||
|
|
void GEMgr.GEReportEvent(msg);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 性能辅助打点(非运营):PF- 前缀,不进 Gravity,避免污染广告/关卡统计
|
||
|
|
*/
|
||
|
|
reportPerf(msg: string): void {
|
||
|
|
if (!msg.startsWith('PF-')) {
|
||
|
|
console.log('[reportPerf] 非法格式,须 PF- 开头', msg);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (/-AD-/.test(msg) || msg.includes('广告')) {
|
||
|
|
console.error('[reportPerf] 拒绝:疑似运营广告口径', msg);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (sdkConfig.enableConsolePfLog) {
|
||
|
|
sdkTrace('%c性能打点==', 'color:#00bcd4', msg);
|
||
|
|
}
|
||
|
|
try {
|
||
|
|
this.pfLog?.(msg);
|
||
|
|
} catch { /* ignore */ }
|
||
|
|
if (MiniGamePf.canReport()) {
|
||
|
|
ZYSDK.ZYSDK.reportUserAction(msg);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 上报30r打点
|
||
|
|
* @param event
|
||
|
|
* @param msg
|
||
|
|
*/
|
||
|
|
report30r(event, msg) {
|
||
|
|
if (this.sdk30r) {
|
||
|
|
this.sdk30r.track(event, msg);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**30r-完成新手引导 */
|
||
|
|
on30rTutorialFinish() {
|
||
|
|
if (this.sdk30r) {
|
||
|
|
this.sdk30r.onTutorialFinish();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**30r-获取关卡模式 */
|
||
|
|
get30rStageType() {
|
||
|
|
return "level";
|
||
|
|
}
|
||
|
|
|
||
|
|
/**30r-获取关卡id(与现有章节打点口径保持一致) */
|
||
|
|
get30rLevelId() {
|
||
|
|
return gg?.game?.CurentBattle?.getReportDYLevelId?.() ?? gg?.game?.CurentSelectLevelId ?? 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**30r-广告次数(当前项目仅维护是否看过广告,按 0/1 上报) */
|
||
|
|
get30rAdCount() {
|
||
|
|
return this.adCount;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 进入侧边栏(快手 / 抖音 / B 站均为 navigateToScene({ scene: 'sidebar' }))
|
||
|
|
* @param callback 跳转结果
|
||
|
|
*/
|
||
|
|
enterSidebar(callback?: Function) {
|
||
|
|
const host = this._pfHost();
|
||
|
|
if (typeof host?.navigateToScene === 'function') {
|
||
|
|
this._enterSidebarCb = callback;
|
||
|
|
host.navigateToScene({
|
||
|
|
scene: "sidebar",
|
||
|
|
success: this._onNavSceneOk,
|
||
|
|
fail: this._onNavSceneFail,
|
||
|
|
});
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
callback?.(false);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 最近一次启动/回前台是否侧边栏 */
|
||
|
|
isFromSidebar(): boolean {
|
||
|
|
return this._fromSidebar;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 最近一次启动/回前台是否 B 站桌面快捷方式 */
|
||
|
|
isFromDesk(): boolean {
|
||
|
|
return this._fromDesk;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 尽早监听宿主 onShow,避免 B 站侧边栏热返回丢场景值。
|
||
|
|
* game.js 模板也会抢先写入 globalThis.__pfLastShow。
|
||
|
|
*/
|
||
|
|
capturePfShow(): void {
|
||
|
|
if (!MiniGamePf.isBl()) return;
|
||
|
|
const host = MiniGamePf.api();
|
||
|
|
if (!host?.onShow) return;
|
||
|
|
const store = globalThis as PfShowStore;
|
||
|
|
if (!store.__pfShowCaptured) {
|
||
|
|
store.__pfShowCaptured = true;
|
||
|
|
try {
|
||
|
|
store.__pfLastShow = host.getEnterOptionsSync?.() ?? host.getLaunchOptionsSync?.() ?? null;
|
||
|
|
} catch {
|
||
|
|
store.__pfLastShow = null;
|
||
|
|
}
|
||
|
|
host.onShow(this._onEarlyPfShow);
|
||
|
|
}
|
||
|
|
this._applyLaunchOptions(this._readLatestLaunch());
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 当前宿主是否支持侧边栏。
|
||
|
|
* 快手:checkSliderBarIsAvailable 在未备案/开发者工具常返回 available=false 或不回调,不能用来藏按钮;入口由 showSidebar 控制,点击再走 navigateToScene。
|
||
|
|
* 抖音/B 站:checkScene → isExist。其余:有 navigateToScene 则显示。
|
||
|
|
* @param callback true 则展示入口
|
||
|
|
*/
|
||
|
|
checkSidebar(callback?: Function) {
|
||
|
|
if (EDITOR || DEBUG || sys.isBrowser) {
|
||
|
|
callback?.(true);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (this._fromSidebar) {
|
||
|
|
callback?.(true);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (MiniGamePf.isKs()) {
|
||
|
|
callback?.(true);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
const host = this._pfHost();
|
||
|
|
if (!host) {
|
||
|
|
callback?.(false);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (typeof host.checkScene === 'function') {
|
||
|
|
this._callSidebarCheck(host.checkScene.bind(host), callback, { scene: 'sidebar' });
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
callback?.(typeof host.navigateToScene === 'function');
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 当前平台宿主;快手兼容微信包优先 window.ks,避免拿到残缺 wx 包装 */
|
||
|
|
private _pfHost(): Record<string, any> | null {
|
||
|
|
if (MiniGamePf.isKs()) {
|
||
|
|
const g = globalThis as unknown as { ks?: Record<string, any>; GameGlobal?: { ks?: Record<string, any> } };
|
||
|
|
if (g.ks && typeof g.ks === 'object') return g.ks;
|
||
|
|
if (g.GameGlobal?.ks && typeof g.GameGlobal.ks === 'object') return g.GameGlobal.ks;
|
||
|
|
}
|
||
|
|
return MiniGamePf.api();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 调用宿主侧边栏检测
|
||
|
|
* @param fn 宿主检测方法
|
||
|
|
* @param callback 业务回调
|
||
|
|
* @param extra 抖音/B 站 checkScene 需带 scene
|
||
|
|
*/
|
||
|
|
private _callSidebarCheck(fn: (opts: object) => void, callback?: Function, extra?: { scene: string }): void {
|
||
|
|
this._sidebarCheckCb = callback;
|
||
|
|
const opts: Record<string, unknown> = {
|
||
|
|
success: this._onSidebarCheckOk,
|
||
|
|
fail: this._onSidebarCheckFail,
|
||
|
|
};
|
||
|
|
if (extra?.scene) opts.scene = extra.scene;
|
||
|
|
try {
|
||
|
|
fn(opts);
|
||
|
|
} catch (err) {
|
||
|
|
this._sidebarCheckCb = undefined;
|
||
|
|
console.warn('[Sidebar] 检测接口异常', String(err));
|
||
|
|
callback?.(typeof this._pfHost()?.navigateToScene === 'function');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 快手 available;抖音 / B 站 isExist */
|
||
|
|
private _parseSidebarCheck(result: { available?: unknown; isAvailable?: unknown; isExist?: unknown } | boolean | null | undefined): boolean {
|
||
|
|
if (result === true) return true;
|
||
|
|
if (!result || typeof result !== 'object') return false;
|
||
|
|
return result.available === true || result.available === 1 || result.isAvailable === true || result.isExist === true;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 验证是否需要显示添加到桌面按钮
|
||
|
|
* @param callback
|
||
|
|
*/
|
||
|
|
checkNeedShowAddShortcut(callback?: Function) {
|
||
|
|
if (EDITOR || DEBUG || sys.isBrowser) {
|
||
|
|
callback?.(true);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (sdkConfig.config.chanId === 'vivo') {
|
||
|
|
this._queryVivoShortcut(callback);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
const pf = MiniGamePf.api();
|
||
|
|
if (!pf?.addShortcut) {
|
||
|
|
callback?.(false);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (MiniGamePf.isKs() && typeof pf.checkShortcut === 'function') {
|
||
|
|
this._addDeskCb = callback;
|
||
|
|
pf.checkShortcut({
|
||
|
|
success: this._onCheckShortcutOk,
|
||
|
|
fail: this._onCheckShortcutFail,
|
||
|
|
});
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
callback?.(true);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 分享游戏
|
||
|
|
* @param timeLimit 分享最小停留时间, 没有回调的平台通过计时判断是否分享成功
|
||
|
|
* @param cb 有回调的平台,通过回调函数判断是否分享成功
|
||
|
|
* @param data 可选参数,分享数据(需要知道参数类型)
|
||
|
|
*/
|
||
|
|
share(timeLimit, cb = null, data = null) {
|
||
|
|
this._share_time = new Date().getTime();
|
||
|
|
this._shareTimeLimit = timeLimit;
|
||
|
|
this._shareResultCb = cb;
|
||
|
|
if (!this.Share) {
|
||
|
|
console.warn('[SDKManager.share] Share 未初始化');
|
||
|
|
cb?.(false);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
let desc = ""
|
||
|
|
let url = ""
|
||
|
|
let query = ""
|
||
|
|
let id = "";
|
||
|
|
if (data && data.desc) desc = data.desc;
|
||
|
|
if (data && data.res) url = data.res;
|
||
|
|
if (data && data.query) query = data.query;
|
||
|
|
if (data && data.shareid) id = data.shareid;
|
||
|
|
if (!id && data && data.ks) id = data.ks;
|
||
|
|
if (!id && data && data.tt) id = data.tt;
|
||
|
|
const pf = MiniGamePf.id();
|
||
|
|
if (pf === 'wx' || pf === 'bl') {
|
||
|
|
this._onShare = this._onShareReturn;
|
||
|
|
this.Share.share(desc, url, cb, query);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (pf === 'tt' || pf === 'ks') {
|
||
|
|
this.Share.share(desc, url, cb, query, id);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
console.warn('[SDKManager.share] 当前平台无分享', pf);
|
||
|
|
cb?.(false);
|
||
|
|
}
|
||
|
|
private _share_time = 0;
|
||
|
|
private _onShare = null;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 短时间震动
|
||
|
|
*/
|
||
|
|
vibrateShort() {
|
||
|
|
this.Vibrate.vibrateShort();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 长时间震动
|
||
|
|
*/
|
||
|
|
vibrateLong() {
|
||
|
|
this.Vibrate.vibrateLong();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 开始震动
|
||
|
|
*/
|
||
|
|
startVibrate() {
|
||
|
|
this.Vibrate.startVibrate();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 停止震动
|
||
|
|
*/
|
||
|
|
stopVibrate() {
|
||
|
|
this.Vibrate.stopVibrate();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 添加到桌面
|
||
|
|
* @param callback 回调
|
||
|
|
*/
|
||
|
|
addShortcut(callback?: Function) {
|
||
|
|
if (sdkConfig.config.chanId === 'vivo') {
|
||
|
|
this._installVivoShortcut(callback);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
const pf = MiniGamePf.api();
|
||
|
|
if (!pf?.addShortcut) {
|
||
|
|
if (callback) callback(false);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this._addShortcutCb = callback;
|
||
|
|
pf.addShortcut({
|
||
|
|
success: this._onAddShortcutOk,
|
||
|
|
fail: this._onAddShortcutFail,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
getVideoPath() {
|
||
|
|
return this.Recording?.getVideoPath();
|
||
|
|
}
|
||
|
|
|
||
|
|
getVideoTime() {
|
||
|
|
return this.Recording?.getVideoTime();
|
||
|
|
}
|
||
|
|
|
||
|
|
getStatus() {
|
||
|
|
return this.Recording?.getStatus();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 开始录屏
|
||
|
|
*/
|
||
|
|
startRecord() {
|
||
|
|
this.Recording && this.Recording.startVideo();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 停止录屏
|
||
|
|
*/
|
||
|
|
stopRecord() {
|
||
|
|
this.Recording && this.Recording.stopVideo();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 分享录屏
|
||
|
|
*/
|
||
|
|
shareRecord(callback = null) {
|
||
|
|
if (this.Recording)
|
||
|
|
this.Recording.shareVideo(callback);
|
||
|
|
else
|
||
|
|
callback(true);
|
||
|
|
}
|
||
|
|
|
||
|
|
pauseVideo() {
|
||
|
|
this.Recording && this.Recording.pauseVideo();
|
||
|
|
}
|
||
|
|
|
||
|
|
resumeVideo() {
|
||
|
|
this.Recording && this.Recording.resumeVideo();
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* 微信转发菜单
|
||
|
|
*/
|
||
|
|
openWXShareMenu() {
|
||
|
|
if (MiniGamePf.id() === 'wx') {
|
||
|
|
window["wx"].showShareMenu({
|
||
|
|
withShareTicket: true,
|
||
|
|
menus: ['shareAppMessage', 'shareTimeline'],
|
||
|
|
success: () => {
|
||
|
|
|
||
|
|
},
|
||
|
|
fail: () => {
|
||
|
|
|
||
|
|
},
|
||
|
|
complete: () => {
|
||
|
|
|
||
|
|
}
|
||
|
|
});
|
||
|
|
window["wx"].onShareAppMessage(function () {
|
||
|
|
let share1 = {
|
||
|
|
title: sdkConfig.config.platformConf.wxOnShareMessage.title,
|
||
|
|
imageUrlId: sdkConfig.config.platformConf.wxOnShareMessage.imageUrlId,
|
||
|
|
imageUrl: sdkConfig.config.platformConf.wxOnShareMessage.imageUrl
|
||
|
|
}
|
||
|
|
// let share2 = {
|
||
|
|
// title: "看不见下雨了嘛,赶紧回笼呀!",
|
||
|
|
// imageUrlId: 'Y2PHkx0bR0Ou2a25kg+Vsg==',
|
||
|
|
// imageUrl: 'https://mmocgame.qpic.cn/wechatgame/WFTmogtfYrIwyhRVuZHbEs709mroiaaDcYkwBSBXLckR7ibQNPfrXKstvCpyV4bmyn/0'
|
||
|
|
// }
|
||
|
|
// let share3 = {
|
||
|
|
// title: "快救救这只猪",
|
||
|
|
// imageUrlId: 'qTQmv6/8SCixA6raayq2HA==',
|
||
|
|
// imageUrl: 'https://mmocgame.qpic.cn/wechatgame/qqRAxsORaczSj5Z33DB4pneEtpOBstVwzhsk8VPh02OlTGHzPHBxicaffB09ILdgl/0'
|
||
|
|
// }
|
||
|
|
// return Math.random() > 0.5 ? share1 : Math.random() > 0.5 ? share2 : share3;
|
||
|
|
return share1
|
||
|
|
});
|
||
|
|
if (gg.data.getStatistics(StatisticsType.yonghuxieyiYS) == 0) {
|
||
|
|
window["wx"].getPrivacySetting({
|
||
|
|
success: (res) => {
|
||
|
|
sdkTrace("是否需要授权:", res.needAuthorization);
|
||
|
|
sdkTrace("隐私协议名称:", res.privacyContractName);
|
||
|
|
if (res.needAuthorization) {
|
||
|
|
window["wx"].requirePrivacyAuthorize({
|
||
|
|
success: () => {
|
||
|
|
// 用户同意授权
|
||
|
|
// runGame() 继续游戏逻辑
|
||
|
|
sdkTrace("用户同意授权");
|
||
|
|
gg.data.setStatistics(StatisticsType.yonghuxieyiYS, 2);
|
||
|
|
},
|
||
|
|
fail: () => {
|
||
|
|
sdkTrace("用户拒绝授权");
|
||
|
|
gg.data.setStatistics(StatisticsType.yonghuxieyiYS, 1);
|
||
|
|
|
||
|
|
}, // 用户拒绝授权
|
||
|
|
complete: () => { }
|
||
|
|
})
|
||
|
|
} else {
|
||
|
|
|
||
|
|
}
|
||
|
|
},
|
||
|
|
fail: () => {
|
||
|
|
// 低版本基础库不支持时的处理
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
getUserInfo() {
|
||
|
|
return new Promise((resolve) => {
|
||
|
|
if (this._userInfo) {
|
||
|
|
resolve(this._userInfo);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (!this.pf || !this.pf["getUserInfo"]) {
|
||
|
|
resolve(null);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this._userInfoResolve = resolve;
|
||
|
|
this.pf["getUserInfo"]({
|
||
|
|
success: this._onGetUserInfoOk,
|
||
|
|
fail: this._onGetUserInfoFail,
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
private _userInfo: any = null;
|
||
|
|
|
||
|
|
private _getSubscribeTmplId(scene: SubscribeTmplScene): string {
|
||
|
|
const t = sdkConfig.config.platformConf?.subscribeTmpl;
|
||
|
|
if (!t) return '';
|
||
|
|
switch (scene) {
|
||
|
|
case 'offlineEarnings': return t.offlineEarnings ?? '';
|
||
|
|
case 'vigourRecovery': return t.vigourRecovery ?? '';
|
||
|
|
case 'versionUpdate': return t.versionUpdate ?? '';
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 离线收益领取提醒 */
|
||
|
|
requestSubscribeOfflineEarnings(force = false): void {
|
||
|
|
this._requestSubscribeScene('offlineEarnings', force);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 体力恢复提醒 */
|
||
|
|
requestSubscribeVigourRecovery(force = false): void {
|
||
|
|
this._requestSubscribeScene('vigourRecovery', force);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 版本更新提醒(须单独调起,不可与其它模板同批) */
|
||
|
|
requestSubscribeVersionUpdate(force = false): void {
|
||
|
|
this._requestSubscribeScene('versionUpdate', force);
|
||
|
|
}
|
||
|
|
|
||
|
|
private _requestSubscribeScene(scene: SubscribeTmplScene, force = false): void {
|
||
|
|
if (DEV || EDITOR || sys.isBrowser) return;
|
||
|
|
|
||
|
|
const tmplId = this._getSubscribeTmplId(scene);
|
||
|
|
if (!tmplId) {
|
||
|
|
sdkTrace('[SubscribeMessage] skip: 未配置', scene);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
const version = sdkConfig.config.vsion ?? '';
|
||
|
|
if (scene === 'versionUpdate') {
|
||
|
|
const prompted = gg.data?.getStringData?.(OtherDataType.SubscribeVersionPrompted) ?? '';
|
||
|
|
if (!force && prompted === version) return;
|
||
|
|
} else if (!force && membershipHas(this._subscribePrompted, scene)) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
const pf = this.pf;
|
||
|
|
if (!pf?.requestSubscribeMessage) {
|
||
|
|
sdkTrace('[SubscribeMessage] skip: 当前平台不支持 requestSubscribeMessage');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (pf.canIUse && !pf.canIUse('requestSubscribeMessage')) {
|
||
|
|
sdkTrace('[SubscribeMessage] skip: canIUse(requestSubscribeMessage)=false');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (scene !== 'versionUpdate') {
|
||
|
|
membershipAdd(this._subscribePrompted, scene);
|
||
|
|
}
|
||
|
|
|
||
|
|
sdkTrace('[SubscribeMessage] request', scene, tmplId);
|
||
|
|
pf.requestSubscribeMessage({
|
||
|
|
tmplIds: [tmplId],
|
||
|
|
fail: (err: { errMsg?: string; errCode?: number }) => {
|
||
|
|
sdkTrace('[SubscribeMessage] fail', scene, err?.errMsg ?? err);
|
||
|
|
},
|
||
|
|
complete: (res: Record<string, string>) => {
|
||
|
|
sdkTrace('[SubscribeMessage] complete', scene, res);
|
||
|
|
this._notifySubscribeAccept([tmplId], res);
|
||
|
|
if (scene === 'versionUpdate' && version) {
|
||
|
|
gg.data.setStringData(OtherDataType.SubscribeVersionPrompted, version);
|
||
|
|
}
|
||
|
|
},
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/** @deprecated 请用 requestSubscribeOfflineEarnings / VigourRecovery / VersionUpdate */
|
||
|
|
requestSubscribeMessage(_force = false): void {
|
||
|
|
this.requestSubscribeOfflineEarnings(_force);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 用户同意订阅后通知 ZYSDK 后台 */
|
||
|
|
private _notifySubscribeAccept(tmplIds: string[], res: Record<string, string>): void {
|
||
|
|
if (!res) return;
|
||
|
|
for (const id of tmplIds) {
|
||
|
|
if (res[id] === 'accept') {
|
||
|
|
try {
|
||
|
|
ZYSDK.ZYSDK.subscribe(id);
|
||
|
|
} catch (e) {
|
||
|
|
sdkTrace('[SubscribeMessage] ZYSDK.subscribe error', id, e);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//推荐流复访订阅(只用复访 Content_ID;本项目方案=体力恢复 scene=2)
|
||
|
|
PlatformFeedSubscribe() {
|
||
|
|
sdkTrace('PlatformFeedSubscribe')
|
||
|
|
if (this._feedSubscribePrompted) {
|
||
|
|
sdkTrace('PlatformFeedSubscribe skip: already prompted this session');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
let self = this
|
||
|
|
if (this.pf && window["tt"]) {
|
||
|
|
sdkTrace('PlatformFeedSubscribe1')
|
||
|
|
// 1离线 / 2体力 / 3重要事件,本项目方案=2 体力恢复
|
||
|
|
let sceneId = this.getRevisitFeedScene();
|
||
|
|
if (this.pf.canIUse("checkFeedSubscribeStatus")) {
|
||
|
|
|
||
|
|
sdkTrace('PlatformFeedSubscribe2')
|
||
|
|
this.pf.checkFeedSubscribeStatus({
|
||
|
|
type: "play",
|
||
|
|
scene: sceneId,
|
||
|
|
success(res) {
|
||
|
|
sdkTrace("checkFeedSubscribeStatus:" + res.status)
|
||
|
|
if (!res.status) {
|
||
|
|
let contentIDs = self.resolveFeedContentIds("revisit");
|
||
|
|
sdkTrace("contentIDs(复访):", contentIDs, "scene:", sceneId)
|
||
|
|
if (!contentIDs.length) {
|
||
|
|
sdkTrace("requestFeedSubscribe skip: missing revisit contentIDs");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
self._feedSubscribePrompted = true;
|
||
|
|
self.pf.requestFeedSubscribe({
|
||
|
|
type: "play",
|
||
|
|
scene: sceneId,
|
||
|
|
contentIDs: contentIDs,
|
||
|
|
success(res) {
|
||
|
|
sdkTrace("requestFeedSubscribe:" + res.success)
|
||
|
|
},
|
||
|
|
fail(res) {
|
||
|
|
sdkTrace(res.errMsg)
|
||
|
|
},
|
||
|
|
})
|
||
|
|
|
||
|
|
|
||
|
|
} else {
|
||
|
|
self._feedSubscribePrompted = true;
|
||
|
|
}
|
||
|
|
},
|
||
|
|
fail(res) {
|
||
|
|
sdkTrace(res.errMsg)
|
||
|
|
},
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 是否推荐流直玩启动 */
|
||
|
|
isFeedDirectPlayLaunch(): boolean {
|
||
|
|
return this._feedDirectPlayLaunch;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 推荐流预启动(直玩启动但尚未 feedEnter) */
|
||
|
|
isFeedPreboot(): boolean {
|
||
|
|
return this._feedDirectPlayLaunch && !this._feedActuallyEntered;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 是否获客直玩 */
|
||
|
|
isFeedAcquireLaunch(): boolean {
|
||
|
|
return this.resolveFeedCapability() === "acquire";
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 是否复访直玩 */
|
||
|
|
isFeedRevisitLaunch(): boolean {
|
||
|
|
return this.resolveFeedCapability() === "revisit";
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 获客应直接进可玩场景 */
|
||
|
|
shouldFeedEnterPlayScene(): boolean {
|
||
|
|
return this._feedDirectPlayLaunch && this.isFeedAcquireLaunch();
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 首屏可交互时上报 reportScene(7001),内部幂等 */
|
||
|
|
notifyFeedGameInteractive() {
|
||
|
|
if (!this._feedDirectPlayLaunch) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
sdkTrace(
|
||
|
|
"SDK 推荐流场景可交互",
|
||
|
|
this.resolveFeedCapability(),
|
||
|
|
this._feedGameContentId || "(none)",
|
||
|
|
"scene",
|
||
|
|
this._feedGameScene,
|
||
|
|
"channel",
|
||
|
|
this._feedGameChannel
|
||
|
|
);
|
||
|
|
this.PlatformReportScene();
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 复访 scene:本项目方案=2(体力恢复);仅当启动 query 显式给出 1|2|3 时用平台值 */
|
||
|
|
private getRevisitFeedScene(): number {
|
||
|
|
return this._feedGameScene === 1 || this._feedGameScene === 2 || this._feedGameScene === 3
|
||
|
|
? this._feedGameScene
|
||
|
|
: 2;
|
||
|
|
}
|
||
|
|
|
||
|
|
private uniqContentIds(list: Array<string | undefined | null>): string[] {
|
||
|
|
const ids: string[] = [];
|
||
|
|
for (const raw of list) {
|
||
|
|
if (typeof raw !== 'string') {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
const v = raw.trim();
|
||
|
|
if (v && !ids.includes(v)) {
|
||
|
|
ids.push(v);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return ids;
|
||
|
|
}
|
||
|
|
|
||
|
|
private getConfiguredRevisitContentIds(): string[] {
|
||
|
|
return this.uniqContentIds(sdkConfig.config.platformConf?.contentIDs || []);
|
||
|
|
}
|
||
|
|
|
||
|
|
private getConfiguredAcquireContentIds(): string[] {
|
||
|
|
return this.uniqContentIds(sdkConfig.config.platformConf?.acquireContentIDs || []);
|
||
|
|
}
|
||
|
|
|
||
|
|
private toFeedFiniteNumber(raw: unknown): number {
|
||
|
|
if (raw === "" || raw === undefined || raw === null) {
|
||
|
|
return NaN;
|
||
|
|
}
|
||
|
|
const n = Number(raw);
|
||
|
|
return Number.isFinite(n) ? n : NaN;
|
||
|
|
}
|
||
|
|
|
||
|
|
private isConfiguredRevisitContentId(contentId: string): boolean {
|
||
|
|
return !!contentId && this.getConfiguredRevisitContentIds().includes(contentId);
|
||
|
|
}
|
||
|
|
|
||
|
|
private isConfiguredAcquireContentId(contentId: string): boolean {
|
||
|
|
return !!contentId && this.getConfiguredAcquireContentIds().includes(contentId);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 获客:channel=2 / scene=0 / 获客 Content_ID;复访:channel=1 / scene=1|2|3 / 复访 Content_ID */
|
||
|
|
private resolveFeedCapability(): "acquire" | "revisit" | "unknown" {
|
||
|
|
if (!this._feedDirectPlayLaunch) {
|
||
|
|
return "unknown";
|
||
|
|
}
|
||
|
|
if (this._feedGameChannel === 2 || this._feedGameScene === 0 || this.isConfiguredAcquireContentId(this._feedGameContentId)) {
|
||
|
|
return "acquire";
|
||
|
|
}
|
||
|
|
if (
|
||
|
|
this._feedGameChannel === 1 ||
|
||
|
|
this._feedGameScene === 1 ||
|
||
|
|
this._feedGameScene === 2 ||
|
||
|
|
this._feedGameScene === 3 ||
|
||
|
|
this.isConfiguredRevisitContentId(this._feedGameContentId)
|
||
|
|
) {
|
||
|
|
return "revisit";
|
||
|
|
}
|
||
|
|
return "unknown";
|
||
|
|
}
|
||
|
|
|
||
|
|
private resolveFeedContentIds(kind: "revisit" | "acquire"): string[] {
|
||
|
|
const configured =
|
||
|
|
kind === "revisit" ? this.getConfiguredRevisitContentIds() : this.getConfiguredAcquireContentIds();
|
||
|
|
const launchId = this._feedGameContentId;
|
||
|
|
const launchMatches =
|
||
|
|
(kind === "revisit" && this.isConfiguredRevisitContentId(launchId)) ||
|
||
|
|
(kind === "acquire" && this.isConfiguredAcquireContentId(launchId));
|
||
|
|
return this.uniqContentIds(launchMatches ? [launchId, ...configured] : configured);
|
||
|
|
}
|
||
|
|
|
||
|
|
private setupFeedDirectPlay() {
|
||
|
|
if (sys.platform !== sys.Platform.BYTEDANCE_MINI_GAME || !this.pf) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
const launch = this.getLaunchOptionsSync_custom();
|
||
|
|
const scene = launch?.scene != null ? String(launch.scene) : "";
|
||
|
|
const query = launch?.query || {};
|
||
|
|
const contentId = query.feed_game_content_id != null ? String(query.feed_game_content_id) : "";
|
||
|
|
// 3041=推荐流直玩,9999=直玩测试入口
|
||
|
|
const isFeedScene =
|
||
|
|
scene.includes("3041") || scene.includes("9999") || !!contentId || query.feed_game_scene != null;
|
||
|
|
if (!isFeedScene) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this._feedDirectPlayLaunch = true;
|
||
|
|
this._feedGameContentId = contentId;
|
||
|
|
const feedScene = this.toFeedFiniteNumber(query.feed_game_scene);
|
||
|
|
this._feedGameScene = Number.isFinite(feedScene) ? feedScene : -1;
|
||
|
|
let channel = this.toFeedFiniteNumber(query.feed_game_channel);
|
||
|
|
if (!Number.isFinite(channel) || channel <= 0) {
|
||
|
|
if (this._feedGameScene === 0 || this.isConfiguredAcquireContentId(contentId)) {
|
||
|
|
channel = 2;
|
||
|
|
} else if (
|
||
|
|
this._feedGameScene === 1 ||
|
||
|
|
this._feedGameScene === 2 ||
|
||
|
|
this._feedGameScene === 3 ||
|
||
|
|
this.isConfiguredRevisitContentId(contentId)
|
||
|
|
) {
|
||
|
|
channel = 1;
|
||
|
|
} else {
|
||
|
|
channel = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
this._feedGameChannel = channel;
|
||
|
|
// scene 缺失时补齐:获客=0,复访默认体力恢复=2
|
||
|
|
if (this._feedGameScene < 0) {
|
||
|
|
if (this.resolveFeedCapability() === "acquire") {
|
||
|
|
this._feedGameScene = 0;
|
||
|
|
} else if (this.resolveFeedCapability() === "revisit") {
|
||
|
|
this._feedGameScene = 2;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const capability = this.resolveFeedCapability();
|
||
|
|
sdkTrace(
|
||
|
|
"SDK 推荐流直玩启动",
|
||
|
|
scene,
|
||
|
|
capability,
|
||
|
|
"channel",
|
||
|
|
this._feedGameChannel,
|
||
|
|
"feed_game_scene",
|
||
|
|
this._feedGameScene,
|
||
|
|
"contentId",
|
||
|
|
this._feedGameContentId || "(none)"
|
||
|
|
);
|
||
|
|
if (this._feedGameContentId) {
|
||
|
|
this.reportDY("inLevel", `推荐流-方案-${capability}-${this._feedGameContentId}`);
|
||
|
|
}
|
||
|
|
this.reportDY("inLevel", this.feedChannelLabel("预启动"));
|
||
|
|
|
||
|
|
this._feedStatusHandler = (res: { type?: string }) => {
|
||
|
|
const type = res?.type;
|
||
|
|
sdkTrace("SDK onFeedStatusChange", type);
|
||
|
|
if (type === "feedEnter") {
|
||
|
|
this.markFeedActuallyEntered("feedEnter");
|
||
|
|
} else if (type === "feedExit") {
|
||
|
|
sdkTrace("SDK 推荐流退出回推荐流");
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
try {
|
||
|
|
if (typeof this.pf.onFeedStatusChange === "function") {
|
||
|
|
this.pf.onFeedStatusChange(this._feedStatusHandler);
|
||
|
|
} else {
|
||
|
|
console.log("SDK onFeedStatusChange 不可用,启用触摸兜底");
|
||
|
|
this.bindFeedTouchFallback();
|
||
|
|
}
|
||
|
|
} catch (e) {
|
||
|
|
console.log("SDK 注册 onFeedStatusChange 失败,启用触摸兜底", String(e));
|
||
|
|
this.bindFeedTouchFallback();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private feedChannelLabel(stage: "预启动" | "活跃"): string {
|
||
|
|
const capability = this.resolveFeedCapability();
|
||
|
|
if (capability === "revisit" || this._feedGameChannel === 1) {
|
||
|
|
return stage === "预启动" ? "推荐流-预启动-复访用户" : "推荐流-复访用户";
|
||
|
|
}
|
||
|
|
if (capability === "acquire" || this._feedGameChannel === 2) {
|
||
|
|
return stage === "预启动" ? "推荐流-预启动-获客用户" : "推荐流-获客用户";
|
||
|
|
}
|
||
|
|
return stage === "预启动" ? "推荐流-预启动" : "推荐流-活跃用户";
|
||
|
|
}
|
||
|
|
|
||
|
|
private markFeedActuallyEntered(source: string) {
|
||
|
|
if (this._feedActuallyEntered) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this._feedActuallyEntered = true;
|
||
|
|
this.unbindFeedTouchFallback();
|
||
|
|
sdkTrace("SDK 推荐流真实进入", source, this.resolveFeedCapability(), this._feedGameChannel);
|
||
|
|
this.reportDY("inLevel", this.feedChannelLabel("活跃"));
|
||
|
|
if (this._feedPendingVigourDeduct) {
|
||
|
|
this._feedPendingVigourDeduct = false;
|
||
|
|
gg.data.subVigour(gg.data.project.vigourCost);
|
||
|
|
}
|
||
|
|
if (this.isFeedRevisitLaunch()) {
|
||
|
|
this.storeFeedData();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 预启动进关未扣体力,等 feedEnter 再扣 */
|
||
|
|
markFeedPendingVigourDeduct() {
|
||
|
|
this._feedPendingVigourDeduct = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
private bindFeedTouchFallback() {
|
||
|
|
if (this._feedTouchFallbackBound || this._feedActuallyEntered) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this._feedTouchFallbackBound = () => {
|
||
|
|
this.markFeedActuallyEntered("touchFallback");
|
||
|
|
};
|
||
|
|
try {
|
||
|
|
if (typeof this.pf?.onTouchEnd === "function") {
|
||
|
|
this.pf.onTouchEnd(this._feedTouchFallbackBound);
|
||
|
|
} else if (typeof document !== "undefined") {
|
||
|
|
document.addEventListener("touchend", this._feedTouchFallbackBound, { once: true, capture: true });
|
||
|
|
document.addEventListener("click", this._feedTouchFallbackBound, { once: true, capture: true });
|
||
|
|
}
|
||
|
|
} catch (e) {
|
||
|
|
console.log("SDK 绑定推荐流触摸兜底失败", String(e));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private unbindFeedTouchFallback() {
|
||
|
|
if (!this._feedTouchFallbackBound) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
try {
|
||
|
|
if (typeof this.pf?.offTouchEnd === "function") {
|
||
|
|
this.pf.offTouchEnd(this._feedTouchFallbackBound);
|
||
|
|
}
|
||
|
|
if (typeof document !== "undefined") {
|
||
|
|
document.removeEventListener("touchend", this._feedTouchFallbackBound, true);
|
||
|
|
document.removeEventListener("click", this._feedTouchFallbackBound, true);
|
||
|
|
}
|
||
|
|
} catch (_) {
|
||
|
|
/* ignore */
|
||
|
|
}
|
||
|
|
this._feedTouchFallbackBound = null;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 推荐流上报场景(sceneId 7001,幂等;失败可重试) */
|
||
|
|
PlatformReportScene() {
|
||
|
|
if (this._feedReportSceneDone || this._feedReportSceneInFlight) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (this.pf && this.pf.reportScene) {
|
||
|
|
this._feedReportSceneInFlight = true;
|
||
|
|
const self = this;
|
||
|
|
this.pf.reportScene({
|
||
|
|
sceneId: 7001,
|
||
|
|
costTime: 2000,
|
||
|
|
success(res) {
|
||
|
|
self._feedReportSceneInFlight = false;
|
||
|
|
self._feedReportSceneDone = true;
|
||
|
|
sdkTrace("ReportScene_success:", res);
|
||
|
|
},
|
||
|
|
fail(res) {
|
||
|
|
self._feedReportSceneInFlight = false;
|
||
|
|
console.log("ReportScene_fail:");
|
||
|
|
},
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 体力恢复场景就绪时刻(毫秒时间戳)。
|
||
|
|
* 官方托管:体力恢复到满值时判定就绪;已满=立刻就绪(rightValue=now),
|
||
|
|
* 不可 skip——否则平台侧无就绪数据,测试模式报「不存在相关就绪数据」。
|
||
|
|
*/
|
||
|
|
private calcVigourFullAtMs(): number {
|
||
|
|
try {
|
||
|
|
const current = gg.data.getVigour();
|
||
|
|
const maxVigour = gg.data.table.getConst(ConstNumType.MaxVigour);
|
||
|
|
const recoverSec = gg.data.table.getConst(ConstNumType.VigourRecoverSec);
|
||
|
|
// 配表异常兜底:仍上报,避免平台永远查不到就绪数据
|
||
|
|
if (!(maxVigour > 0) || !(recoverSec > 0)) {
|
||
|
|
sdkTrace('calcVigourFullAtMs fallback: invalid recover config', maxVigour, recoverSec);
|
||
|
|
return Date.now();
|
||
|
|
}
|
||
|
|
if (current >= maxVigour) {
|
||
|
|
return Date.now();
|
||
|
|
}
|
||
|
|
const need = maxVigour - current;
|
||
|
|
const nextSec = gg.data.project.getAddVigourTime();
|
||
|
|
const remainSec = Math.max(0, nextSec) + Math.max(0, need - 1) * recoverSec;
|
||
|
|
return Date.now() + remainSec * 1000;
|
||
|
|
} catch (e) {
|
||
|
|
sdkTrace('calcVigourFullAtMs fail', String(e));
|
||
|
|
return Date.now();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
storeFeedData() {
|
||
|
|
if (this._feedDirectPlayLaunch && this.isFeedAcquireLaunch()) {
|
||
|
|
sdkTrace("storeFeedData skip: acquire feed");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (this.isFeedPreboot()) {
|
||
|
|
sdkTrace("storeFeedData skip: feed preboot");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (this.pf && this.pf.storeFeedData) {
|
||
|
|
const contentID = this.resolveFeedContentIds("revisit")[0];
|
||
|
|
if (!contentID) {
|
||
|
|
sdkTrace('storeFeedData skip: missing revisit contentIDs');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
const scene = this.getRevisitFeedScene();
|
||
|
|
// 本项目方案=2 体力恢复:就绪=体力回满;已满则 rightValue=now(立刻就绪)
|
||
|
|
const fullAtMs = this.calcVigourFullAtMs();
|
||
|
|
let params = {
|
||
|
|
scene, // 1,离线收益 2,体力恢复 3,重要事件
|
||
|
|
contentID,
|
||
|
|
leftValue: 'timeStampMs',
|
||
|
|
operator: '>=',
|
||
|
|
rightValue: String(fullAtMs),
|
||
|
|
status: 1,
|
||
|
|
success(res) {
|
||
|
|
sdkTrace('storeFeedData success', res)
|
||
|
|
},
|
||
|
|
fail(res) {
|
||
|
|
sdkTrace(res.errMsg || res)
|
||
|
|
},
|
||
|
|
}
|
||
|
|
sdkTrace("使用参数:" + JSON.stringify(params));
|
||
|
|
this.pf.storeFeedData(params);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
getLaunchOptionsSync_custom() {
|
||
|
|
if (this.pf && this.pf.getLaunchOptionsSync) {
|
||
|
|
let obj = this.pf.getLaunchOptionsSync();
|
||
|
|
let str = JSON.stringify(obj);
|
||
|
|
sdkTrace("getLaunchOptionsSync_custom: 场景值", str)
|
||
|
|
///obj.scene
|
||
|
|
return obj
|
||
|
|
} else {
|
||
|
|
return null
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**平台记录日志 */
|
||
|
|
pfLog(msg: string) {
|
||
|
|
if (this.pf && this.pf.getLogManager) {
|
||
|
|
this.pf.getLogManager().log(msg);
|
||
|
|
} else {
|
||
|
|
sdkTrace(msg);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**平台记录调试日志 */
|
||
|
|
pfDebug(msg: string) {
|
||
|
|
if (this.pf && this.pf.getLogManager) {
|
||
|
|
this.pf.getLogManager().debug(msg);
|
||
|
|
} else {
|
||
|
|
console.debug(msg);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
ttWorker(callback) {
|
||
|
|
// if (this.pf && this.pf.createWorker) {
|
||
|
|
// let worker = this.pf.createWorker({
|
||
|
|
// scriptPath: "worker.js",
|
||
|
|
// success: (res) => {
|
||
|
|
// console.log("createWorker success", res);
|
||
|
|
// callback(res);
|
||
|
|
// },
|
||
|
|
// fail: (res) => {
|
||
|
|
// console.log("createWorker fail", res);
|
||
|
|
// },
|
||
|
|
// });
|
||
|
|
// }
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 设置屏幕常亮(抖音 tt / 微信 wx 等小游戏) */
|
||
|
|
setKeepScreenOn(keep: boolean): void {
|
||
|
|
if (EDITOR || DEBUG || sys.isBrowser) return;
|
||
|
|
const api = this.pf?.setKeepScreenOn;
|
||
|
|
if (!api) return;
|
||
|
|
api.call(this.pf, {
|
||
|
|
keepScreenOn: keep,
|
||
|
|
fail: (err: { errMsg?: string }) => {
|
||
|
|
sdkTrace('setKeepScreenOn fail', keep, err?.errMsg ?? err);
|
||
|
|
},
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**平台触发垃圾回收 */
|
||
|
|
pfTriggerGC() {
|
||
|
|
if (this.pf && this.pf.triggerGC) {
|
||
|
|
this.pf.triggerGC();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 平台内存警告(微信 / 抖音 / 快手 / 快应用 / 支付宝 my.onMemoryWarning) */
|
||
|
|
onMemoryWarning(callback: Function = null) {
|
||
|
|
this._memWarnCb = callback;
|
||
|
|
let bound = false;
|
||
|
|
if (this.pf?.onMemoryWarning) {
|
||
|
|
this.pf.onMemoryWarning(this._onMemWarn);
|
||
|
|
bound = true;
|
||
|
|
}
|
||
|
|
const ks = window['ks'];
|
||
|
|
if (!bound && ks?.onMemoryWarning && ks !== this.pf) {
|
||
|
|
ks.onMemoryWarning(this._onMemWarn);
|
||
|
|
bound = true;
|
||
|
|
}
|
||
|
|
const tt = window['tt'];
|
||
|
|
if (!bound && tt?.onMemoryWarning && tt !== this.pf) {
|
||
|
|
tt.onMemoryWarning(this._onMemWarn);
|
||
|
|
bound = true;
|
||
|
|
}
|
||
|
|
const qg = window['qg'];
|
||
|
|
if (!bound && qg?.onMemoryWarning && qg !== this.pf) {
|
||
|
|
qg.onMemoryWarning(this._onMemWarn);
|
||
|
|
bound = true;
|
||
|
|
}
|
||
|
|
const wx = window['wx'];
|
||
|
|
if (!bound && wx?.onMemoryWarning && wx !== this.pf) {
|
||
|
|
wx.onMemoryWarning(this._onMemWarn);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 排行榜授权时缓存的用户信息 */
|
||
|
|
private _rankUserInfo: Record<string, unknown> | null = null;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 排行榜拉头像昵称。
|
||
|
|
* 新基础库 scope.userInfo 已不支持 authorize(必 fail),优先 getUserProfile 直接拉真实资料
|
||
|
|
* (须在点击同步链内调用才有手势权限);无该 API 的平台退回 authorize → getUserInfo 旧链。
|
||
|
|
*/
|
||
|
|
pullRankUserInfo(callback?: (info: { userInfo?: Record<string, unknown> } | null) => void): void {
|
||
|
|
const api = MiniGamePf.api();
|
||
|
|
if (!api) {
|
||
|
|
callback?.(null);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
const done = (info: { userInfo?: Record<string, unknown> } | null) => {
|
||
|
|
if (info?.userInfo) this._rankUserInfo = info.userInfo;
|
||
|
|
callback?.(info ?? null);
|
||
|
|
};
|
||
|
|
|
||
|
|
const readViaGetUserInfo = () => {
|
||
|
|
if (this._rankUserInfo) {
|
||
|
|
done({ userInfo: this._rankUserInfo });
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (typeof api.getUserInfo !== 'function') {
|
||
|
|
done(null);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
api.getUserInfo({
|
||
|
|
success: (res: { userInfo?: Record<string, unknown> }) => done(res ?? null),
|
||
|
|
fail: () => done(null),
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
if (typeof api.getUserProfile === 'function') {
|
||
|
|
if (this._rankUserInfo) {
|
||
|
|
console.warn('[RankDebug] pullRankUserInfo 走 getUserProfile:命中缓存直接返回');
|
||
|
|
done({ userInfo: this._rankUserInfo });
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
console.warn('[RankDebug] pullRankUserInfo 走 getUserProfile 分支');
|
||
|
|
api.getUserProfile({
|
||
|
|
desc: '用于排行榜昵称头像展示',
|
||
|
|
success: (res: { userInfo?: Record<string, unknown> }) => {
|
||
|
|
console.warn('[RankDebug] getUserProfile 成功');
|
||
|
|
done(res ?? null);
|
||
|
|
},
|
||
|
|
fail: (err?: { errMsg?: string }) => {
|
||
|
|
console.log(`[RankDebug] getUserProfile 失败 err=${err?.errMsg ?? String(err ?? '')}`);
|
||
|
|
readViaGetUserInfo();
|
||
|
|
},
|
||
|
|
});
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (typeof api.authorize === 'function') {
|
||
|
|
console.warn('[RankDebug] pullRankUserInfo 走 authorize→getUserInfo 分支');
|
||
|
|
api.authorize({
|
||
|
|
scope: 'scope.userInfo',
|
||
|
|
success: () => {
|
||
|
|
console.warn('[RankDebug] authorize(scope.userInfo) 成功');
|
||
|
|
readViaGetUserInfo();
|
||
|
|
},
|
||
|
|
fail: (err?: { errMsg?: string }) => {
|
||
|
|
console.log(`[RankDebug] authorize(scope.userInfo) 失败 err=${err?.errMsg ?? String(err ?? '')}`);
|
||
|
|
done(null);
|
||
|
|
},
|
||
|
|
});
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
console.warn('[RankDebug] pullRankUserInfo 无 authorize/getUserProfile,直接 getUserInfo');
|
||
|
|
readViaGetUserInfo();
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 授权定位(scope.userLocation) */
|
||
|
|
authorizeUserLocation(callback?: (ok: boolean) => void): void {
|
||
|
|
this._authorizeScope('scope.userLocation', callback);
|
||
|
|
}
|
||
|
|
|
||
|
|
private _authorizeScope(scope: string, callback?: (ok: boolean) => void): void {
|
||
|
|
if (!this.pf?.authorize) {
|
||
|
|
callback?.(false);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this.pf.authorize({
|
||
|
|
scope,
|
||
|
|
success: () => callback?.(true),
|
||
|
|
fail: () => callback?.(false),
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 读取授权设置 authSetting */
|
||
|
|
getSetting(callback?: (setting: { authSetting?: Record<string, unknown> } | null) => void): void {
|
||
|
|
if (!this.pf?.getSetting) {
|
||
|
|
callback?.(null);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this.pf.getSetting({
|
||
|
|
success: (res: { authSetting?: Record<string, unknown> }) => callback?.(res ?? null),
|
||
|
|
fail: () => callback?.(null),
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 打开系统授权设置页 */
|
||
|
|
openSetting(callback?: (ok: boolean) => void): void {
|
||
|
|
if (!this.pf?.openSetting) {
|
||
|
|
callback?.(false);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this.pf.openSetting({
|
||
|
|
success: () => callback?.(true),
|
||
|
|
fail: () => callback?.(false),
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 冷/热启动是否侧边栏入口:快手 from、抖音 launch_from、B 站 scene=021036 */
|
||
|
|
private _isSidebarLaunch(res: PfLaunchRes | null | undefined): boolean {
|
||
|
|
if (!res) return false;
|
||
|
|
const from = String(res.from ?? '');
|
||
|
|
if (from === 'sidebar_new' || from === 'sidebar_miniprogram') return true;
|
||
|
|
if (res.launch_from === 'homepage' && res.location === 'sidebar_card') return true;
|
||
|
|
if (res.launch_from === 'sidebar_miniprogram' || res.launch_from === 'sidebar_new') return true;
|
||
|
|
if (String(res.scene ?? '') === '021036') return true;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** B 站桌面快捷方式 scene=10002 */
|
||
|
|
private _isDeskLaunch(res: PfLaunchRes | null | undefined): boolean {
|
||
|
|
return MiniGamePf.isBl() && String(res?.scene ?? '') === '10002';
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 读取 game.js 抢先缓存或宿主最新启动参数 */
|
||
|
|
private _readLatestLaunch(): PfLaunchRes | null {
|
||
|
|
const store = globalThis as PfShowStore;
|
||
|
|
if (store.__pfLastShow) return store.__pfLastShow;
|
||
|
|
const host = this._pfHost() ?? MiniGamePf.api();
|
||
|
|
try {
|
||
|
|
if (typeof host?.getEnterOptionsSync === 'function') {
|
||
|
|
return host.getEnterOptionsSync() ?? null;
|
||
|
|
}
|
||
|
|
} catch { /* 宿主未就绪 */ }
|
||
|
|
try {
|
||
|
|
if (typeof host?.getLaunchOptionsSync === 'function') {
|
||
|
|
return host.getLaunchOptionsSync() ?? null;
|
||
|
|
}
|
||
|
|
} catch { /* 宿主未就绪 */ }
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 更新侧边栏/桌面资格。B 站跟最新 scene;其它平台侧边栏标记粘滞。 */
|
||
|
|
private _applyLaunchOptions(res: PfLaunchRes | null | undefined): void {
|
||
|
|
const sidebar = this._isSidebarLaunch(res);
|
||
|
|
if (!MiniGamePf.isBl()) {
|
||
|
|
if (!sidebar) return;
|
||
|
|
this._fromSidebar = true;
|
||
|
|
if (sdkConfig.isInitGameData) {
|
||
|
|
gg.data.setStatus(StatusType.DayGiftCanGet, 1);
|
||
|
|
}
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this._fromSidebar = sidebar;
|
||
|
|
this._fromDesk = this._isDeskLaunch(res);
|
||
|
|
if (!sdkConfig.isInitGameData) return;
|
||
|
|
if (this._fromSidebar) {
|
||
|
|
gg.data.setStatus(StatusType.DayGiftCanGet, 1);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (gg.data.getStatus(StatusType.DayGiftGetFinish) === 0) {
|
||
|
|
gg.data.setStatus(StatusType.DayGiftCanGet, 0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/** game.js / 启动阶段 onShow:缓存场景并更新侧边栏/桌面资格 */
|
||
|
|
private _onEarlyPfShow = (res: PfLaunchRes): void => {
|
||
|
|
(globalThis as PfShowStore).__pfLastShow = res;
|
||
|
|
this._applyLaunchOptions(res);
|
||
|
|
};
|
||
|
|
|
||
|
|
/** 跳转侧边栏成功 */
|
||
|
|
private _onNavSceneOk = (): void => {
|
||
|
|
sdkTrace("navigate to scene success");
|
||
|
|
const cb = this._enterSidebarCb;
|
||
|
|
this._enterSidebarCb = undefined;
|
||
|
|
cb?.(true);
|
||
|
|
};
|
||
|
|
|
||
|
|
/** 跳转侧边栏失败 */
|
||
|
|
private _onNavSceneFail = (res: { code?: number; msg?: string }): void => {
|
||
|
|
sdkTrace("navigate to scene fail: ", res);
|
||
|
|
if (res?.code === -20042) console.warn('[Sidebar] 游戏未备案');
|
||
|
|
if (res?.code === -20041) console.warn('[Sidebar] 唤起侧边栏超过每日频控');
|
||
|
|
if (res?.code === -10005) console.warn('[Sidebar] 客户端版本过低');
|
||
|
|
const cb = this._enterSidebarCb;
|
||
|
|
this._enterSidebarCb = undefined;
|
||
|
|
cb?.(false);
|
||
|
|
};
|
||
|
|
|
||
|
|
/** 侧边栏检测成功 */
|
||
|
|
private _onSidebarCheckOk = (result: { available?: unknown; isAvailable?: unknown; isExist?: unknown } | boolean): void => {
|
||
|
|
const ok = this._parseSidebarCheck(result);
|
||
|
|
sdkTrace('sidebar check success', ok, result);
|
||
|
|
const cb = this._sidebarCheckCb;
|
||
|
|
this._sidebarCheckCb = undefined;
|
||
|
|
cb?.(ok);
|
||
|
|
};
|
||
|
|
|
||
|
|
/** 检测 fail 不等于明确不可用;有 navigateToScene 仍展示入口 */
|
||
|
|
private _onSidebarCheckFail = (res: unknown): void => {
|
||
|
|
console.warn('[Sidebar] 检测 fail');
|
||
|
|
const cb = this._sidebarCheckCb;
|
||
|
|
this._sidebarCheckCb = undefined;
|
||
|
|
cb?.(typeof this._pfHost()?.navigateToScene === 'function');
|
||
|
|
};
|
||
|
|
|
||
|
|
/** 未添加桌面则展示入口 */
|
||
|
|
private _onCheckShortcutOk = (res: { installed?: boolean }): void => {
|
||
|
|
const cb = this._addDeskCb;
|
||
|
|
this._addDeskCb = undefined;
|
||
|
|
cb?.(!res?.installed);
|
||
|
|
};
|
||
|
|
|
||
|
|
/** 检测失败仍展示入口(含 -10005 / apk info is invalid) */
|
||
|
|
private _onCheckShortcutFail = (err: { code?: number; msg?: string }): void => {
|
||
|
|
sdkTrace('checkShortcut fail', err?.code, err?.msg);
|
||
|
|
const cb = this._addDeskCb;
|
||
|
|
this._addDeskCb = undefined;
|
||
|
|
cb?.(true);
|
||
|
|
};
|
||
|
|
|
||
|
|
/** 微信分享回前台计时判定 */
|
||
|
|
private _onShareReturn = (time: number): void => {
|
||
|
|
sdkTrace("本次分享时间:" + time);
|
||
|
|
const cb = this._shareResultCb;
|
||
|
|
const limit = this._shareTimeLimit;
|
||
|
|
this._shareResultCb = null;
|
||
|
|
this._onShare = null;
|
||
|
|
cb?.(time >= limit);
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* vivo:未创建过桌面图标才显示按钮。
|
||
|
|
* @param callback 是否显示
|
||
|
|
*/
|
||
|
|
private _queryVivoShortcut(callback?: Function): void {
|
||
|
|
const pf = MiniGamePf.api();
|
||
|
|
if (typeof pf?.hasShortcutInstalled !== 'function') {
|
||
|
|
console.warn('[SDKManager] vivo 无 hasShortcutInstalled');
|
||
|
|
callback?.(false);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this._addDeskCb = callback;
|
||
|
|
pf.hasShortcutInstalled({
|
||
|
|
success: this._onVivoHasShortcut,
|
||
|
|
fail: this._onVivoHasShortcutFail,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/** vivo hasShortcutInstalled 成功。true 表示已创建 */
|
||
|
|
private _onVivoHasShortcut = (status: unknown): void => {
|
||
|
|
const cb = this._addDeskCb;
|
||
|
|
this._addDeskCb = undefined;
|
||
|
|
if (typeof status !== 'boolean') {
|
||
|
|
console.warn('[SDKManager] hasShortcutInstalled 返回值异常', status);
|
||
|
|
cb?.(false);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
cb?.(!status);
|
||
|
|
};
|
||
|
|
|
||
|
|
/** vivo 查询桌面图标失败 */
|
||
|
|
private _onVivoHasShortcutFail = (err: unknown): void => {
|
||
|
|
console.warn('[SDKManager] hasShortcutInstalled 失败', err);
|
||
|
|
const cb = this._addDeskCb;
|
||
|
|
this._addDeskCb = undefined;
|
||
|
|
cb?.(false);
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* vivo 创建桌面图标。两次调用间隔须大于 120 秒。
|
||
|
|
* @param callback 是否创建成功
|
||
|
|
*/
|
||
|
|
private _installVivoShortcut(callback?: Function): void {
|
||
|
|
const pf = MiniGamePf.api();
|
||
|
|
if (typeof pf?.installShortcut !== 'function') {
|
||
|
|
console.warn('[SDKManager] vivo 无 installShortcut');
|
||
|
|
callback?.(false);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this._vivoShortcutOk = false;
|
||
|
|
this._addShortcutCb = callback;
|
||
|
|
pf.installShortcut({
|
||
|
|
success: this._onVivoShortcutOk,
|
||
|
|
fail: this._onAddShortcutFail,
|
||
|
|
complete: this._onVivoShortcutComplete,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/** vivo 创建桌面图标成功 */
|
||
|
|
private _onVivoShortcutOk = (): void => {
|
||
|
|
this._vivoShortcutOk = true;
|
||
|
|
this._onAddShortcutOk();
|
||
|
|
};
|
||
|
|
|
||
|
|
/** vivo complete:成功之后忽略;单独触发视为用户取消 */
|
||
|
|
private _onVivoShortcutComplete = (): void => {
|
||
|
|
if (this._vivoShortcutOk) {
|
||
|
|
this._vivoShortcutOk = false;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this._onAddShortcutFail('cancel');
|
||
|
|
};
|
||
|
|
|
||
|
|
/** 添加桌面成功 */
|
||
|
|
private _onAddShortcutOk = (): void => {
|
||
|
|
sdkTrace("添加成功");
|
||
|
|
const cb = this._addShortcutCb;
|
||
|
|
this._addShortcutCb = undefined;
|
||
|
|
cb?.(true);
|
||
|
|
};
|
||
|
|
|
||
|
|
/** 添加桌面失败 */
|
||
|
|
private _onAddShortcutFail = (res: unknown): void => {
|
||
|
|
sdkTrace("添加失败", res);
|
||
|
|
const cb = this._addShortcutCb;
|
||
|
|
this._addShortcutCb = undefined;
|
||
|
|
cb?.(false);
|
||
|
|
};
|
||
|
|
|
||
|
|
/** getUserInfo 成功 */
|
||
|
|
private _onGetUserInfoOk = (res: { userInfo?: unknown }): void => {
|
||
|
|
sdkTrace(`getUserInfo 调用成功`, res?.userInfo);
|
||
|
|
this._userInfo = res?.userInfo;
|
||
|
|
const resolve = this._userInfoResolve;
|
||
|
|
this._userInfoResolve = null;
|
||
|
|
resolve?.(res?.userInfo ?? null);
|
||
|
|
};
|
||
|
|
|
||
|
|
/** getUserInfo 失败 */
|
||
|
|
private _onGetUserInfoFail = (res: { errMsg?: string }): void => {
|
||
|
|
sdkTrace(`getUserInfo 调用失败`, res?.errMsg);
|
||
|
|
const resolve = this._userInfoResolve;
|
||
|
|
this._userInfoResolve = null;
|
||
|
|
resolve?.(null);
|
||
|
|
};
|
||
|
|
|
||
|
|
/** 内存警告(参数可能是 number 或 {level}) */
|
||
|
|
private _onMemWarn = (res: number | { level?: number }): void => {
|
||
|
|
const level = typeof res === 'number' ? res : Number(res?.level ?? 0);
|
||
|
|
sdkTrace("onMemoryWarning", level);
|
||
|
|
this.pfTriggerGC();
|
||
|
|
if (this._memWarnCb && level >= 5) this._memWarnCb();
|
||
|
|
};
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|