import { context } from '@/common/context'; import { applyNative, invokeNative, onNative } from '@jolibox/native-bridge'; import { createAPI, t, registerCanIUse } from './base'; import { createCommands, Deferred, hostEmitter } from '@jolibox/common'; import { createAPIError } from '@/common/report/errors'; registerCanIUse('login', { version: '1.0.0', properties: { force: '1.0.0' }, success: { errMsg: '1.0.0', code: '1.0.0', token: '1.0.0', isLogin: '1.0.0' } }); registerCanIUse('checkSession', { version: '1.0.0', success: { errMsg: '1.0.0', isLogin: '1.0.0', isSubUser: '1.2.9' } }); const loginDeferredMap = new Map< string, Deferred<{ isLogin: boolean; token?: string; isFirstLogin?: boolean; extra?: LoginExtra; appAccountToken?: string; }> >(); onNative('onLoginStateChange', ({ isLogin, token, uuid, isFirstLogin, extra, appAccountToken }) => { const deferred = loginDeferredMap.get(uuid); if (deferred) { deferred.resolve({ isLogin, token, isFirstLogin, extra, appAccountToken }); loginDeferredMap.delete(uuid); } }); type LoginExtra = { firstLogin?: { reward: { rewardType: 'JOLI_COIN'; rewardValue: number; }; }; }; export const loginImplement = async ( params: { skipLogin?: boolean; triggerFrom?: string }, needExtra = false ): Promise<{ isLogin: boolean; token?: string; isFirstLogin?: boolean; extra?: LoginExtra; }> => { const { data: { isLogin } } = await applyNative('checkLoginAsync'); if (isLogin) { return { isLogin: true, token: context.hostUserInfo?.token }; } const { skipLogin, triggerFrom } = params ?? {}; const res = invokeNative('loginSync', { skipLogin, triggerFrom }); const { data: { uuid: loginUUID } } = res; if (!loginUUID) { throw createAPIError({ code: -1, msg: 'login failed' }); } const deferred = new Deferred<{ isLogin: boolean; token?: string; isFirstLogin?: boolean; appAccountToken?: string; extra?: LoginExtra; }>(); loginDeferredMap.set(loginUUID, deferred); const loginRes = await deferred.promise; // update sub user status const env = invokeNative('envSync'); const isSubUser = env?.data?.hostUserInfo?.isSubUser; context.onEnvConfigChanged({ hostUserInfo: { ...loginRes, isSubUser } }); const { extra, appAccountToken, ...rest } = loginRes; hostEmitter.emit('onLoginComplete', rest); return needExtra ? loginRes : rest; }; export const login = createAPI('login', { paramsSchema: t.tuple( t .object({ skipLogin: t.boolean().optional(), triggerFrom: t.string().optional() }) .optional() ), async implement(params) { return await loginImplement(params ?? {}); } }); const checkSession = createAPI('checkSession', { async implement() { const { data: { isLogin } } = await applyNative('checkLoginAsync'); const isSubUser = context.hostUserInfo?.isSubUser; return { isLogin, isSubUser }; } }); const commands = createCommands(); commands.registerCommand('API.login', login); commands.registerCommand('API.checkSession', checkSession);