import { getAdvertisingId, mergeArray, mergeWith, getApiDomain } from '@jolibox/common'; import { DeviceInfo, HostInfo, HostUserInfo, SdkInfo } from './types'; import { Env } from '@jolibox/types'; import { parseUrlQuery, encodeJoliSourceQuery, QueryParams } from './url-parse'; import { getAppVersion } from '../http/xua'; import { getDeviceId, platform } from '@jolibox/common'; declare const globalThis: { joliboxJSCore?: { env: () => Env | undefined; }; }; const defaultEnv: Env = { deviceInfo: { brand: 'UnknownBrand', model: 'UnknownModel', did: getDeviceId(), adId: getAdvertisingId(), pixelRatio: window.devicePixelRatio || 1, platform: platform.isAndroid ? 'android' : platform.isiOS ? 'ios' : 'h5', system: 'UnknownSystemVersion', lang: 'zh' }, sdkInfo: { nativeSDKVersion: '', jssdkVersion: getAppVersion() }, schema: window.location.href, platform: platform.isAndroid ? 'android' : platform.isiOS ? 'ios' : 'h5' }; const nativeEnv = globalThis.joliboxJSCore?.env; const env = Object.assign({}, nativeEnv?.() ?? defaultEnv); type MPType = 'game' | 'miniApp'; export enum SDKEnvironment { jolibox = 'jolibox', // 默认 dlightek = 'dlightek', // 传音 funmax = 'funmax', // 小米 huaweiQuick = 'huaweiQuick', // 华为快应用 gamedistribution = 'gamedistribution' } type Viewport = { statusBarHeight: number; navigationBarHeight: number; }; type MPInfo = { mpName: string; mpVersion?: string; }; function hasMetaTag(name: string, content: string): boolean { return document?.head.querySelector(`meta[name="${name}"][content="${content}"]`) !== null; } const wrapContext = () => { const { payloadJson, headerJson, signature } = env.schema.length ? parseUrlQuery(env.schema) : {}; const defaultSessionId = `${env.deviceInfo.did}-${new Date().getTime()}`; const url = new URL(env.schema.length ? env.schema : window.location.href); const urlParams = url.searchParams; const defaultGameID = urlParams.get('mpId') ?? urlParams.get('appId') ?? urlParams.get('gameId') ?? ''; const sessionId = env.clientSessionId ?? payloadJson?.sessionId ?? urlParams.get('sessionId') ?? defaultSessionId; const testAdsMode = !!( payloadJson?.testAdsMode ?? payloadJson?.__testAdsMode ?? urlParams.get('testAdsMode') === 'true' ); const joliboxEnv = payloadJson?.joliboxEnv ?? payloadJson?.__joliboxEnv ?? urlParams.get('joliboxEnv') ?? 'production'; const testMode = joliboxEnv === 'staging'; const channel = headerJson?.channel; const originUrl = new URL(window.location.href); const originUrlParams = originUrl.searchParams; // default should show stay recommend panel let shouldInterupt = payloadJson?.__shouldInterupt; return { get startTime(): number { return performance.timeOrigin ?? performance.timing.navigationStart; }, get testMode(): boolean { return testMode; // TODO: true test mode }, get testAdsMode(): boolean { return testAdsMode; }, get joliboxEnv() { return joliboxEnv; }, get joliSource(): string | null { return originUrlParams.get('joliSource') ?? urlParams.get('joliSource') ?? null; }, get mpId(): string { return defaultGameID ?? payloadJson?.id ?? ''; }, get mpVersion(): string { return headerJson?.ver ?? getAppVersion(); }, get mpType(): MPType { return headerJson?.__mpType ?? payloadJson?.__mpType ?? 'game'; }, get platform(): Env['platform'] { return (env.platform ?? env.deviceInfo.platform).toLowerCase() as 'h5' | 'android' | 'ios'; }, get deviceInfo(): DeviceInfo { return env.deviceInfo; }, get sdkInfo(): SdkInfo { return env.sdkInfo; }, get hostInfo(): HostInfo { return env.hostInfo; }, get hostUserInfo(): HostUserInfo { return env.hostUserInfo; }, get sessionId(): string { return env.clientSessionId ?? sessionId ?? defaultSessionId; }, get channel(): string | undefined { return channel; }, get webviewId(): number { return env.webviewId ?? -1; }, get shouldInterupt(): boolean | undefined { return shouldInterupt; }, get from(): number | undefined { return payloadJson?.__from; }, get baseApiHost(): string { return getApiDomain(testMode); }, get adId(): string { return env.deviceInfo.adId ?? env.deviceInfo.did; }, get language(): string { return env.deviceInfo.lang; }, get sdkEnvironment(): SDKEnvironment { if (hasMetaTag('dlightek', 'jolibox')) { return SDKEnvironment.dlightek; } if (urlParams.get('huaweiQuick') === 'true') { return SDKEnvironment.huaweiQuick; } if (hasMetaTag('gamedistribution', 'jolibox')) { return SDKEnvironment.gamedistribution; } if (hasMetaTag('funmax', 'jolibox')) { return SDKEnvironment.funmax; } return SDKEnvironment.jolibox; }, get viewport(): Viewport { const pixelRatio = env.deviceInfo.pixelRatio ?? 1; const rawStatusHeight = env.deviceInfo.statusBarHeight ?? payloadJson?.__androidStatusBarHeight; const rawNavHeight = env.deviceInfo.navigationBarHeight ?? payloadJson?.__androidNavigationBarHeight; return { statusBarHeight: rawStatusHeight !== undefined ? rawStatusHeight / pixelRatio : 20, navigationBarHeight: rawNavHeight !== undefined ? rawNavHeight / pixelRatio : 10 }; }, get abTests(): string[] { return env.abValues?.split(',') ?? []; }, get mpInfo(): MPInfo { return ( env.mpInfo ?? { mpName: 'unknown' } ); }, onEnvConfigChanged: (newConfig: Partial) => { mergeWith(env, newConfig, mergeArray); }, encodeJoliSourceQuery: (newPayloadJson: QueryParams['payloadJson']) => { if (headerJson && signature) { return encodeJoliSourceQuery( { ...payloadJson, ...newPayloadJson }, urlParams.get('joliSource') ?? '' ); } return urlParams.get('joliSource') ?? ''; }, setDoExitDirectly: () => { shouldInterupt = false; } }; }; export const context = wrapContext();