import { createCommands } from '@jolibox/common'; import { t, createSyncAPI } from './base'; import { emitNative } from '@jolibox/native-bridge'; import { context } from '@/common/context'; import { track } from '../report'; import { notifyCustomEvent } from '@/common/utils'; const commands = createCommands(); const onLoadFinished = createSyncAPI('onLoadFinished', { implement: () => { emitNative('cpLoadFinishEvent', {}, context.webviewId, true); notifyCustomEvent('CP_LOAD_FINISH', { duration: performance.now() }); track('loadFinished', { duration: performance.now() }); } }); let lastProgress: number | null = null; let scheduled = false; let lastEmitTime = 0; const THROTTLE_INTERVAL = 200; function notifyProgress(progress: number) { emitNative('cpLoadProgressEvent', { progress }, context.webviewId, true); notifyCustomEvent('CP_LOAD_PROGRESS', { progress }); } const onLoadProgress = createSyncAPI('onLoadProgress', { paramsSchema: t.tuple(t.number()), implement: (progress) => { lastProgress = progress; if (!scheduled) { scheduled = true; requestAnimationFrame(function frame() { const now = Date.now(); if (now - lastEmitTime >= THROTTLE_INTERVAL) { if (lastProgress !== null) { notifyProgress(lastProgress); lastEmitTime = now; lastProgress = null; } scheduled = false; } else { requestAnimationFrame(frame); } }); } } }); const onGameTTI = createSyncAPI('onGameTTI', { paramsSchema: t.tuple(t.number().optional()), implement: () => { emitNative( 'cpGameTTIEvent', { duration: performance.now() }, context.webviewId, true ); notifyCustomEvent('CP_GAME_TTI', { duration: performance.now() }); track('gameTTI', { duration: performance.now() }); } }); commands.registerCommand('RuntimeSDK.loadFinishedEvent', onLoadFinished); commands.registerCommand('RuntimeSDK.loadProgressEvent', onLoadProgress); commands.registerCommand('RuntimeSDK.gameTTIEvent', onGameTTI);