@jolibox/implement 1.1.12 → 1.1.13-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.rush/temp/package-deps_build.json +20 -34
- package/.rush/temp/shrinkwrap-deps.json +1 -1
- package/dist/common/context/index.d.ts +5 -0
- package/dist/common/context/url-parse.d.ts +8 -1
- package/dist/index.js +3 -3
- package/dist/index.native.js +110 -4
- package/dist/native/api/index.d.ts +1 -0
- package/dist/native/api/keyboard.d.ts +1 -1
- package/dist/native/api/navigate.d.ts +1 -0
- package/dist/native/network/create-fetch.d.ts +1 -0
- package/dist/native/ui/retention.d.ts +1 -0
- package/implement.build.log +2 -2
- package/package.json +5 -3
- package/src/common/context/index.ts +22 -3
- package/src/common/context/url-parse.ts +24 -1
- package/src/native/api/ads.ts +1 -1
- package/src/native/api/get-system-info.ts +1 -1
- package/src/native/api/index.ts +1 -0
- package/src/native/api/keyboard.ts +1 -1
- package/src/native/api/lifecycle.ts +16 -4
- package/src/native/api/login.ts +1 -1
- package/src/native/api/navigate.ts +61 -0
- package/src/native/api/request.ts +19 -10
- package/src/native/api/storage.ts +1 -1
- package/src/native/bootstrap/index.ts +111 -27
- package/src/native/network/create-fetch.ts +2 -1
- package/src/native/network/utils.ts +13 -6
- package/src/native/report/errors/index.ts +1 -1
- package/src/native/report/index.ts +1 -1
- package/src/native/report/task-tracker.ts +1 -1
- package/src/native/ui/retention.ts +152 -0
- package/dist/native/bootstrap/bridge.d.ts +0 -4
- package/dist/native/js-bridge/const.d.ts +0 -5
- package/dist/native/js-bridge/index.d.ts +0 -2
- package/dist/native/js-bridge/invoke.d.ts +0 -21
- package/dist/native/js-bridge/js-bridge.d.ts +0 -6
- package/dist/native/js-bridge/report.d.ts +0 -63
- package/dist/native/js-bridge/subscribe.d.ts +0 -8
- package/dist/native/js-bridge/types.d.ts +0 -14
- package/dist/native/js-bridge/utils.d.ts +0 -17
- package/dist/native/js-core/index.d.ts +0 -3
- package/dist/native/js-core/jolibox-js-core.d.ts +0 -45
- package/dist/native/js-core/message-port.d.ts +0 -12
- package/dist/native/js-core/utils.d.ts +0 -7
- package/src/native/bootstrap/bridge.ts +0 -59
- package/src/native/js-bridge/const.ts +0 -11
- package/src/native/js-bridge/index.ts +0 -2
- package/src/native/js-bridge/invoke.ts +0 -208
- package/src/native/js-bridge/js-bridge.ts +0 -23
- package/src/native/js-bridge/report.ts +0 -311
- package/src/native/js-bridge/subscribe.ts +0 -50
- package/src/native/js-bridge/types.ts +0 -26
- package/src/native/js-bridge/utils.ts +0 -116
- package/src/native/js-core/index.ts +0 -4
- package/src/native/js-core/jolibox-js-core.ts +0 -188
- package/src/native/js-core/message-port.ts +0 -52
- package/src/native/js-core/utils.ts +0 -9
- package/src/native/types/global.d.ts +0 -26
- package/src/native/types/native-method-map.d.ts +0 -300
- package/src/native/types/native-method.d.ts +0 -30
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export declare const showKeyboard: (params: {
|
|
2
2
|
defaultValue?: string | undefined;
|
|
3
|
-
maxLength?: unknown;
|
|
4
3
|
multiple?: boolean | undefined;
|
|
4
|
+
maxLength?: unknown;
|
|
5
5
|
}) => import("@jolibox/types").StandardResponse<void>;
|
|
6
6
|
export declare const updateKeyboard: (params: {
|
|
7
7
|
value: string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -15,6 +15,7 @@ type PublicFetch = <T>(url: string, options?: FetchOptions) => Promise<{
|
|
|
15
15
|
}>;
|
|
16
16
|
export declare function createFetch(createMethod: 'createRequestTaskSync', operateMethod: 'operateRequestTaskSync', options?: {
|
|
17
17
|
baseUrl?: string;
|
|
18
|
+
defaultHeaders?: Record<string, string>;
|
|
18
19
|
type: 'public';
|
|
19
20
|
}): PublicFetch;
|
|
20
21
|
export declare function createFetch(createMethod: 'createRequestTaskSync', operateMethod: 'operateRequestTaskSync', options?: {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function openRetentionSchema(): Promise<boolean>;
|
package/implement.build.log
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Invoking: npm run clean && npm run build:esm && tsc
|
|
2
2
|
|
|
3
|
-
> @jolibox/implement@1.1.
|
|
3
|
+
> @jolibox/implement@1.1.13-beta.2 clean
|
|
4
4
|
> rimraf ./dist
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
> @jolibox/implement@1.1.
|
|
7
|
+
> @jolibox/implement@1.1.13-beta.2 build:esm
|
|
8
8
|
> BUILD_VERSION=$(node -p "require('./package.json').version") node esbuild.config.js --format=esm
|
|
9
9
|
|
package/package.json
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jolibox/implement",
|
|
3
3
|
"description": "This project is Jolibox JS-SDk implement for Native && H5",
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.13-beta.2",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@jolibox/common": "1.1.
|
|
10
|
-
"@jolibox/types": "1.1.
|
|
9
|
+
"@jolibox/common": "1.1.13-beta.2",
|
|
10
|
+
"@jolibox/types": "1.1.13-beta.2",
|
|
11
|
+
"@jolibox/native-bridge": "1.0.0",
|
|
11
12
|
"localforage": "1.10.0",
|
|
13
|
+
"@jolibox/ui": "1.0.0",
|
|
12
14
|
"web-vitals": "4.2.4"
|
|
13
15
|
},
|
|
14
16
|
"devDependencies": {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { mergeArray, mergeWith } from '@jolibox/common';
|
|
2
2
|
import { DeviceInfo, HostInfo, HostUserInfo, SdkInfo } from './types';
|
|
3
3
|
import { Env } from '@jolibox/types';
|
|
4
|
-
import { parseUrlQuery } from './url-parse';
|
|
4
|
+
import { parseUrlQuery, encodeJoliSourceQuery, QueryParams } from './url-parse';
|
|
5
5
|
import { getAppVersion } from '../http/xua';
|
|
6
6
|
import { getDeviceId } from '@jolibox/common';
|
|
7
7
|
|
|
@@ -36,12 +36,13 @@ const env = Object.assign({}, nativeEnv?.() ?? defaultEnv);
|
|
|
36
36
|
type MPType = 'game' | 'miniApp';
|
|
37
37
|
|
|
38
38
|
const wrapContext = () => {
|
|
39
|
-
const { payloadJson, headerJson } = env.schema.length ? parseUrlQuery(env.schema) : {};
|
|
39
|
+
const { payloadJson, headerJson, signature } = env.schema.length ? parseUrlQuery(env.schema) : {};
|
|
40
40
|
const defaultSessionId = `${env.deviceInfo.did}-${new Date().getTime()}`;
|
|
41
41
|
const url = new URL(env.schema.length ? env.schema : window.location.href);
|
|
42
42
|
const urlParams = url.searchParams;
|
|
43
43
|
const defaultGameID = urlParams.get('mpId') ?? urlParams.get('appId') ?? urlParams.get('gameId') ?? '';
|
|
44
|
-
const sessionId =
|
|
44
|
+
const sessionId =
|
|
45
|
+
env.clientSessionId ?? payloadJson?.sessionId ?? urlParams.get('sessionId') ?? defaultSessionId;
|
|
45
46
|
const testAdsMode = !!(payloadJson?.testAdsMode ?? urlParams.get('testAdsMode') === 'true');
|
|
46
47
|
const joliboxEnv = payloadJson?.joliboxEnv ?? urlParams.get('joliboxEnv') ?? 'production';
|
|
47
48
|
const testMode = joliboxEnv === 'staging';
|
|
@@ -93,8 +94,26 @@ const wrapContext = () => {
|
|
|
93
94
|
get webviewId(): number {
|
|
94
95
|
return env.webviewId ?? -1;
|
|
95
96
|
},
|
|
97
|
+
get shouldInterupt(): boolean | undefined {
|
|
98
|
+
return payloadJson?.__shouldInterupt;
|
|
99
|
+
},
|
|
100
|
+
get from(): number | undefined {
|
|
101
|
+
return payloadJson?.__from;
|
|
102
|
+
},
|
|
103
|
+
get baseApiHost(): string {
|
|
104
|
+
return testMode ? 'https://stg-api.jolibox.com' : 'https://api.jolibox.com';
|
|
105
|
+
},
|
|
96
106
|
onEnvConfigChanged: (newConfig: Partial<Env>) => {
|
|
97
107
|
mergeWith(env, newConfig, mergeArray);
|
|
108
|
+
},
|
|
109
|
+
encodeJoliSourceQuery: (newPayloadJson: QueryParams['payloadJson']) => {
|
|
110
|
+
if (headerJson && signature) {
|
|
111
|
+
return encodeJoliSourceQuery(
|
|
112
|
+
{ ...payloadJson, ...newPayloadJson },
|
|
113
|
+
urlParams.get('joliSource') ?? ''
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
return urlParams.get('joliSource') ?? '';
|
|
98
117
|
}
|
|
99
118
|
};
|
|
100
119
|
};
|
|
@@ -14,6 +14,12 @@ interface PayloadJson {
|
|
|
14
14
|
joliboxEnv?: 'staging' | 'production';
|
|
15
15
|
sessionId?: string;
|
|
16
16
|
__mpType?: 'game' | 'miniApp';
|
|
17
|
+
__orientation?: 'HORIZONTAL' | 'VERTICAL';
|
|
18
|
+
__transparent?: boolean;
|
|
19
|
+
__entryPath?: string;
|
|
20
|
+
__showStatusBar?: boolean;
|
|
21
|
+
__shouldInterupt?: boolean;
|
|
22
|
+
__from?: number; // 从哪个小程序打开的
|
|
17
23
|
}
|
|
18
24
|
|
|
19
25
|
interface Signature {
|
|
@@ -21,7 +27,7 @@ interface Signature {
|
|
|
21
27
|
payloadSig?: string;
|
|
22
28
|
}
|
|
23
29
|
|
|
24
|
-
interface QueryParams {
|
|
30
|
+
export interface QueryParams {
|
|
25
31
|
headerJson: HeaderJson;
|
|
26
32
|
payloadJson: PayloadJson;
|
|
27
33
|
signature: Signature;
|
|
@@ -38,6 +44,12 @@ const base64UrlDecode = <T>(input: string): T => {
|
|
|
38
44
|
}
|
|
39
45
|
};
|
|
40
46
|
|
|
47
|
+
const base64UrlEncode = <T>(input: T): string => {
|
|
48
|
+
const jsonStr = JSON.stringify(input);
|
|
49
|
+
const base64 = btoa(jsonStr);
|
|
50
|
+
return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
|
|
51
|
+
};
|
|
52
|
+
|
|
41
53
|
export const parseUrlQuery = (url: string): QueryParams => {
|
|
42
54
|
try {
|
|
43
55
|
const urlObj = new URL(url);
|
|
@@ -63,3 +75,14 @@ export const parseUrlQuery = (url: string): QueryParams => {
|
|
|
63
75
|
};
|
|
64
76
|
}
|
|
65
77
|
};
|
|
78
|
+
|
|
79
|
+
export const encodeJoliSourceQuery = (payloadJson: PayloadJson, originJoliSource: string): string => {
|
|
80
|
+
const joli_source = originJoliSource.split('.');
|
|
81
|
+
if (joli_source && joli_source.length === 3) {
|
|
82
|
+
const headerJsonStr = joli_source[0];
|
|
83
|
+
const payloadJsonStr = base64UrlEncode(payloadJson);
|
|
84
|
+
const signatureJsonStr = joli_source[2];
|
|
85
|
+
return `${headerJsonStr}.${payloadJsonStr}.${signatureJsonStr}`;
|
|
86
|
+
}
|
|
87
|
+
return originJoliSource;
|
|
88
|
+
};
|
package/src/native/api/ads.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { IAdsInitParams, JoliboxAdsImpl, IAdConfigParams, IAdBreakParams, IAdUni
|
|
|
7
7
|
import { track } from '../report';
|
|
8
8
|
|
|
9
9
|
import { innerFetch as fetch } from '../network';
|
|
10
|
-
import { invokeNative } from '
|
|
10
|
+
import { invokeNative } from '@jolibox/native-bridge';
|
|
11
11
|
|
|
12
12
|
const checkNetworkStatus = () => {
|
|
13
13
|
const { data } = invokeNative('getNetworkStatusSync');
|
package/src/native/api/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createCommands } from '@jolibox/common';
|
|
2
|
-
import { invokeNative } from '
|
|
2
|
+
import { invokeNative } from '@jolibox/native-bridge';
|
|
3
3
|
import { createSyncAPI, registerCanIUse, t } from './base';
|
|
4
4
|
|
|
5
5
|
export const showKeyboard = createSyncAPI('showKeyboard', {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { BaseError, createCommands, wrapUserFunction, hostEmitter } from '@jolibox/common';
|
|
1
|
+
import { BaseError, createCommands, wrapUserFunction, hostEmitter, isBoolean } from '@jolibox/common';
|
|
2
2
|
import { createAPI, createSyncAPI, registerCanIUse, t } from './base';
|
|
3
3
|
import { reportError } from '@/common/report/errors/report';
|
|
4
|
-
import { applyNative, onNative } from '
|
|
4
|
+
import { applyNative, onNative, publish } from '@jolibox/native-bridge';
|
|
5
5
|
import { nativeTaskEmitter } from '../report';
|
|
6
|
+
import { context } from '@/common/context';
|
|
6
7
|
|
|
7
8
|
const EXIT_GAME = 'exitGame';
|
|
8
9
|
const ON_READY = 'onReady';
|
|
@@ -13,11 +14,22 @@ const commands = createCommands();
|
|
|
13
14
|
|
|
14
15
|
const safeCallbackWrapper = wrapUserFunction(reportError as (err: Error | BaseError) => void);
|
|
15
16
|
const exitGame = createAPI(EXIT_GAME, {
|
|
16
|
-
paramsSchema: t.tuple(t.function()),
|
|
17
|
-
implement: async (onBeforeExit: () => void) => {
|
|
17
|
+
paramsSchema: t.tuple(t.function(), t.boolean().optional().default(false)),
|
|
18
|
+
implement: async (onBeforeExit: () => void, shouldStay = false) => {
|
|
18
19
|
const safeCallback = safeCallbackWrapper(onBeforeExit);
|
|
19
20
|
// 集中上报
|
|
20
21
|
safeCallback.call(this);
|
|
22
|
+
// 透传context.shouldInterupt 且值为false时,为内部小程序。广播onRetentionResult
|
|
23
|
+
if (isBoolean(context.shouldInterupt) && !context.shouldInterupt && context.from) {
|
|
24
|
+
publish(
|
|
25
|
+
'onRetentionResult',
|
|
26
|
+
{
|
|
27
|
+
shouldStay
|
|
28
|
+
},
|
|
29
|
+
context.from,
|
|
30
|
+
true
|
|
31
|
+
);
|
|
32
|
+
}
|
|
21
33
|
await applyNative('exitAppAsync');
|
|
22
34
|
}
|
|
23
35
|
});
|
package/src/native/api/login.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { context } from '@/common/context';
|
|
2
|
-
import { applyNative, invokeNative, onNative } from '
|
|
2
|
+
import { applyNative, invokeNative, onNative } from '@jolibox/native-bridge';
|
|
3
3
|
import { createAPI, t, registerCanIUse } from './base';
|
|
4
4
|
import { createCommands, Deferred, hostEmitter } from '@jolibox/common';
|
|
5
5
|
import { createAPIError } from '@/common/report/errors';
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { createCommands, UserCustomError } from '@jolibox/common';
|
|
2
|
+
import { invokeNative } from '@jolibox/native-bridge';
|
|
3
|
+
import { createSyncAPI, t, registerCanIUse } from './base';
|
|
4
|
+
import { context } from '@/common/context';
|
|
5
|
+
|
|
6
|
+
const commands = createCommands();
|
|
7
|
+
|
|
8
|
+
const openSchemaSync = createSyncAPI('openSchemaSync', {
|
|
9
|
+
paramsSchema: t.tuple(t.string()),
|
|
10
|
+
implement: (schema) => {
|
|
11
|
+
// Add compatibility logic for incomplete URLs
|
|
12
|
+
let finalSchema = schema;
|
|
13
|
+
if (!schema.match(/^https?:\/\//)) {
|
|
14
|
+
finalSchema = `https://${context.mpId}.app.jolibox.com${schema.startsWith('/') ? '' : '/'}${schema}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const res = invokeNative('openSchemaSync', {
|
|
18
|
+
schema: finalSchema
|
|
19
|
+
});
|
|
20
|
+
if (res.errNo !== 0) {
|
|
21
|
+
throw new UserCustomError(res.errMsg, res.errNo);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const openPageSync = createSyncAPI('openPageSync', {
|
|
27
|
+
paramsSchema: t.tuple(t.string()),
|
|
28
|
+
implement: (page) => {
|
|
29
|
+
const { errNo, errMsg, data } = invokeNative('openPageSync', { url: page });
|
|
30
|
+
if (errNo !== 0 || !data) {
|
|
31
|
+
throw new UserCustomError(errMsg, errNo);
|
|
32
|
+
}
|
|
33
|
+
return { webviewId: data.webviewId };
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const closePageSync = createSyncAPI('closePageSync', {
|
|
38
|
+
paramsSchema: t.tuple(t.number()),
|
|
39
|
+
implement: (webviewId) => {
|
|
40
|
+
const { errNo, errMsg } = invokeNative('closePageSync', { webviewId });
|
|
41
|
+
if (errNo !== 0) {
|
|
42
|
+
throw new UserCustomError(errMsg, errNo);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
commands.registerCommand('RouterSDK.openSchema', openSchemaSync);
|
|
48
|
+
commands.registerCommand('RouterSDK.openPage', openPageSync);
|
|
49
|
+
commands.registerCommand('RouterSDK.closePage', closePageSync);
|
|
50
|
+
|
|
51
|
+
registerCanIUse('router.openSchema', {
|
|
52
|
+
version: '1.1.10'
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
registerCanIUse('router.openPage', {
|
|
56
|
+
version: '1.1.10'
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
registerCanIUse('router.closePage', {
|
|
60
|
+
version: '1.1.10'
|
|
61
|
+
});
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { createAPIError } from '@/common/report/errors';
|
|
2
2
|
import { createFetch } from '../network/create-fetch';
|
|
3
|
-
import {
|
|
3
|
+
import { createSyncAPI, registerCanIUse, t } from './base';
|
|
4
4
|
import { dirtyURL, normalizeHeader, normalizeMethod, normalizeTimeout } from '../network/utils';
|
|
5
5
|
import { BaseError, createCommands, Deferred, wrapUserFunction } from '@jolibox/common';
|
|
6
6
|
import { AnyFunction, ResponseType } from '@jolibox/types';
|
|
7
7
|
import { reportError } from '@/common/report/errors/report';
|
|
8
8
|
import { FetchOptions } from '../network/types';
|
|
9
|
+
import { context } from '@/common/context';
|
|
9
10
|
|
|
10
11
|
const LIMIT = 15;
|
|
11
12
|
|
|
12
13
|
const publicFetch = createFetch('createRequestTaskSync', 'operateRequestTaskSync', {
|
|
13
|
-
type: 'public'
|
|
14
|
+
type: 'public',
|
|
15
|
+
baseUrl: context.baseApiHost
|
|
14
16
|
});
|
|
15
17
|
|
|
16
18
|
/** current active count */
|
|
@@ -41,12 +43,12 @@ const request = (_params: unknown) => {
|
|
|
41
43
|
// noop
|
|
42
44
|
};
|
|
43
45
|
|
|
44
|
-
const _request =
|
|
46
|
+
const _request = createSyncAPI('request', {
|
|
45
47
|
paramsSchema: t.tuple(
|
|
46
48
|
t.object({
|
|
47
49
|
url: t.string(),
|
|
48
50
|
method: t.string(),
|
|
49
|
-
|
|
51
|
+
headers: t.object(),
|
|
50
52
|
data: t.object().optional(),
|
|
51
53
|
query: t.object().optional(),
|
|
52
54
|
dataType: t.string().default('json'),
|
|
@@ -68,9 +70,10 @@ const request = (_params: unknown) => {
|
|
|
68
70
|
if (deferred.state !== 'pending') {
|
|
69
71
|
return;
|
|
70
72
|
}
|
|
73
|
+
|
|
71
74
|
const { data, dataType, responseType, enableCache, appendHostCookie } = params;
|
|
72
75
|
|
|
73
|
-
const header = normalizeHeader(params.
|
|
76
|
+
const header = normalizeHeader(params.headers);
|
|
74
77
|
const method = normalizeMethod(params.method);
|
|
75
78
|
const timeout = normalizeTimeout(params.timeout);
|
|
76
79
|
const url = dirtyURL(params.url, method, data);
|
|
@@ -89,15 +92,21 @@ const request = (_params: unknown) => {
|
|
|
89
92
|
|
|
90
93
|
if (timeout) _params['timeout'] = timeout;
|
|
91
94
|
|
|
92
|
-
const task = publicFetch<
|
|
93
|
-
|
|
95
|
+
const task = publicFetch<
|
|
96
|
+
string | ArrayBuffer | JSON | { status: number; data: string | ArrayBuffer | JSON }
|
|
97
|
+
>(url, _params);
|
|
94
98
|
{
|
|
95
99
|
const { response } = await task;
|
|
96
100
|
const { code, data, message } = response;
|
|
97
|
-
|
|
101
|
+
if (data && typeof data === 'object' && 'status' in data && data.status !== 200) {
|
|
102
|
+
throw createAPIError({
|
|
103
|
+
code: data.status || -1,
|
|
104
|
+
msg: `request:fail status ${data.status}`
|
|
105
|
+
});
|
|
106
|
+
}
|
|
98
107
|
deferred.resolve({
|
|
99
108
|
code: (code ?? 'SUCCESS') as ResponseType,
|
|
100
|
-
data,
|
|
109
|
+
data: data as string | ArrayBuffer | JSON,
|
|
101
110
|
message: message ?? 'request:ok'
|
|
102
111
|
});
|
|
103
112
|
|
|
@@ -132,7 +141,7 @@ const request = (_params: unknown) => {
|
|
|
132
141
|
}
|
|
133
142
|
});
|
|
134
143
|
|
|
135
|
-
_request(_params);
|
|
144
|
+
_request(_params as Parameters<typeof _request>[0]);
|
|
136
145
|
|
|
137
146
|
return {
|
|
138
147
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createAPI, createSyncAPI, registerCanIUse, t } from './base';
|
|
2
|
-
import { applyNative, invokeNative } from '
|
|
2
|
+
import { applyNative, invokeNative } from '@jolibox/native-bridge';
|
|
3
3
|
import { createCommands } from '@jolibox/common';
|
|
4
4
|
import { innerFetch as fetch } from '../network';
|
|
5
5
|
import { context } from '@/common/context';
|
|
@@ -1,39 +1,63 @@
|
|
|
1
|
-
import { invokeNative, onNative, RuntimeLoader } from '
|
|
2
|
-
import { joliboxJSCore } from '../js-core';
|
|
1
|
+
import { invokeNative, onNative, RuntimeLoader } from '@jolibox/native-bridge';
|
|
3
2
|
import { context } from '@/common/context';
|
|
4
3
|
import { hostEmitter, isBoolean } from '@jolibox/common';
|
|
5
4
|
import { taskTracker, track } from '../report';
|
|
6
5
|
import { initializeNativeEnv } from './init-env';
|
|
7
6
|
import { adEventEmitter } from '@/common/ads';
|
|
7
|
+
import { openRetentionSchema } from '../ui/retention';
|
|
8
|
+
import { innerFetch } from '../network';
|
|
9
|
+
import { Env } from '@jolibox/types';
|
|
10
|
+
interface IBasicMetaConfig {
|
|
11
|
+
canShowRecommended: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
declare const globalThis: {
|
|
15
|
+
joliboxJSCore: {
|
|
16
|
+
doExit: (uuid: string) => void;
|
|
17
|
+
onDocumentReady: (path: string) => void;
|
|
18
|
+
env: (params: { onError: (error: Error) => void }) => Env | undefined;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 全局变量
|
|
24
|
+
*/
|
|
8
25
|
|
|
26
|
+
/**
|
|
27
|
+
* 清除safari jolibox样式
|
|
28
|
+
*/
|
|
9
29
|
let cleanStyles: () => void;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 启动时间戳
|
|
33
|
+
*/
|
|
34
|
+
let start_timestamp: number;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 是否展示广告
|
|
38
|
+
*/
|
|
39
|
+
let isAdShowing = false;
|
|
40
|
+
|
|
41
|
+
let baskcMeta: IBasicMetaConfig | null = null;
|
|
42
|
+
|
|
10
43
|
RuntimeLoader.onReady(() => {
|
|
11
44
|
// TODO: merge some env config
|
|
12
45
|
});
|
|
13
46
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
47
|
+
/**
|
|
48
|
+
* 添加广告展示监听
|
|
49
|
+
*/
|
|
50
|
+
function addShowAdListener() {
|
|
51
|
+
adEventEmitter.on('isAdShowing', (isShowing) => {
|
|
52
|
+
isAdShowing = isShowing;
|
|
53
|
+
if (isBoolean(isAdShowing)) {
|
|
54
|
+
invokeNative('updateContainerConfigSync', {
|
|
55
|
+
displayCapsuleButton: !isAdShowing,
|
|
56
|
+
webviewId: context.webviewId
|
|
57
|
+
});
|
|
58
|
+
}
|
|
18
59
|
});
|
|
19
|
-
|
|
20
|
-
taskTracker.close(Date.now() - start_timestamp);
|
|
21
|
-
if (isAdShowing) {
|
|
22
|
-
return true; // Forbid exit on watching ads
|
|
23
|
-
}
|
|
24
|
-
return false;
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
let isAdShowing = false;
|
|
28
|
-
adEventEmitter.on('isAdShowing', (isShowing) => {
|
|
29
|
-
isAdShowing = isShowing;
|
|
30
|
-
if (isBoolean(isAdShowing)) {
|
|
31
|
-
invokeNative('updateContainerConfigSync', {
|
|
32
|
-
displayCapsuleButton: !isAdShowing,
|
|
33
|
-
webviewId: context.webviewId
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
});
|
|
60
|
+
}
|
|
37
61
|
|
|
38
62
|
/**
|
|
39
63
|
* The DOMContentLoaded event might be triggered very early,
|
|
@@ -41,7 +65,7 @@ adEventEmitter.on('isAdShowing', (isShowing) => {
|
|
|
41
65
|
*/
|
|
42
66
|
function addWebviewReadyListener() {
|
|
43
67
|
hostEmitter.on('onDocumentReady', () => {
|
|
44
|
-
joliboxJSCore?.onDocumentReady(window.location.href);
|
|
68
|
+
globalThis.joliboxJSCore?.onDocumentReady(window.location.href);
|
|
45
69
|
track('onDocumentReady', {
|
|
46
70
|
start_timestamp,
|
|
47
71
|
timestamp: Date.now()
|
|
@@ -72,14 +96,74 @@ function addGameServiceReadyListener() {
|
|
|
72
96
|
});
|
|
73
97
|
|
|
74
98
|
onNative('onBeforeExit', ({ uuid }) => {
|
|
75
|
-
joliboxJSCore?.doExit(uuid);
|
|
99
|
+
globalThis.joliboxJSCore?.doExit(uuid);
|
|
76
100
|
});
|
|
77
101
|
}
|
|
78
|
-
|
|
102
|
+
|
|
103
|
+
function addDoExitLoader() {
|
|
104
|
+
/**
|
|
105
|
+
* 退出逻辑
|
|
106
|
+
* 1. 如果正在展示广告,则禁止退出
|
|
107
|
+
* 2. 如果指定退出挽留逻辑,则按照指定逻辑运行
|
|
108
|
+
* 3. 如果退出挽留逻辑返回 true,则按照指定逻辑运行
|
|
109
|
+
* 4. 否则,按照默认逻辑运行
|
|
110
|
+
*/
|
|
111
|
+
|
|
112
|
+
const doActualExit = () => {
|
|
113
|
+
//埋点上报
|
|
114
|
+
track('onBeforeExit', {
|
|
115
|
+
timestamp: Date.now()
|
|
116
|
+
});
|
|
117
|
+
cleanStyles?.();
|
|
118
|
+
taskTracker.close(Date.now() - start_timestamp);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
RuntimeLoader.onDoExit(async () => {
|
|
122
|
+
if (isAdShowing) {
|
|
123
|
+
return true; // Forbid exit on watching ads
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// 指定退出挽留逻辑,则按照指定逻辑运行
|
|
127
|
+
if (isBoolean(context.shouldInterupt)) {
|
|
128
|
+
// 不需要打断退出,上报埋点
|
|
129
|
+
if (!context.shouldInterupt) {
|
|
130
|
+
doActualExit();
|
|
131
|
+
}
|
|
132
|
+
return context.shouldInterupt;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (baskcMeta?.canShowRecommended) {
|
|
136
|
+
const stay = await openRetentionSchema();
|
|
137
|
+
if (stay) {
|
|
138
|
+
// 挽留成功,打断退出
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// 退出,对应上报
|
|
144
|
+
//埋点上报
|
|
145
|
+
doActualExit();
|
|
146
|
+
return false;
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function fetchMetaConfig() {
|
|
151
|
+
const url = `${context.baseApiHost}/api/fe-configs/js-sdk/basic-meta`;
|
|
152
|
+
const {
|
|
153
|
+
response: { data }
|
|
154
|
+
} = await innerFetch<IBasicMetaConfig>(url);
|
|
155
|
+
|
|
156
|
+
if (data) {
|
|
157
|
+
baskcMeta = data;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
79
160
|
|
|
80
161
|
export function config(): void {
|
|
81
162
|
start_timestamp = Date.now();
|
|
82
163
|
addGameServiceReadyListener();
|
|
164
|
+
addShowAdListener();
|
|
165
|
+
addDoExitLoader();
|
|
83
166
|
addWebviewReadyListener();
|
|
167
|
+
fetchMetaConfig();
|
|
84
168
|
cleanStyles = initializeNativeEnv();
|
|
85
169
|
}
|
|
@@ -2,7 +2,7 @@ import { isString, logger, Deferred, isObject, hostEmitter } from '@jolibox/comm
|
|
|
2
2
|
import { reportNetworkAPI } from './report';
|
|
3
3
|
import { RequestFrom } from './types';
|
|
4
4
|
import { FetchResponse, FetchOptions } from './types';
|
|
5
|
-
import { invokeNative, onNative } from '
|
|
5
|
+
import { invokeNative, onNative } from '@jolibox/native-bridge';
|
|
6
6
|
import { AnyFunction } from '@jolibox/types';
|
|
7
7
|
import { reportError } from '@/common/report/errors/report';
|
|
8
8
|
import { createAPIError } from '@/common/report/errors';
|
|
@@ -46,6 +46,7 @@ export function createFetch(
|
|
|
46
46
|
operateMethod: 'operateRequestTaskSync',
|
|
47
47
|
options?: {
|
|
48
48
|
baseUrl?: string;
|
|
49
|
+
defaultHeaders?: Record<string, string>;
|
|
49
50
|
type: 'public';
|
|
50
51
|
}
|
|
51
52
|
): PublicFetch;
|
|
@@ -79,12 +79,19 @@ export function dirtyURL(url: string, method: HTTPMethod, data?: unknown) {
|
|
|
79
79
|
|
|
80
80
|
if (!isObject(data)) return url;
|
|
81
81
|
|
|
82
|
-
const [
|
|
82
|
+
const [baseUrl, search = ''] = url.split('?');
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
...data
|
|
87
|
-
});
|
|
84
|
+
// Parse existing query parameters
|
|
85
|
+
const dataParams = new URLSearchParams(search);
|
|
88
86
|
|
|
89
|
-
|
|
87
|
+
// Add new parameters from data object
|
|
88
|
+
for (const [key, value] of Object.entries(data)) {
|
|
89
|
+
if (value !== undefined && value !== null) {
|
|
90
|
+
dataParams.append(key, String(value));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const queryString = dataParams.toString();
|
|
95
|
+
|
|
96
|
+
return queryString ? `${baseUrl}?${queryString}` : baseUrl;
|
|
90
97
|
}
|
|
@@ -5,7 +5,7 @@ import '@/common/report/errors/report/listeners';
|
|
|
5
5
|
import { errorReportEmitter } from '@/common/report/errors';
|
|
6
6
|
import { ErrorData } from '@/common/report/errors/report';
|
|
7
7
|
import { logger } from '@jolibox/common';
|
|
8
|
-
import {
|
|
8
|
+
import { invokeNative } from '@jolibox/native-bridge';
|
|
9
9
|
|
|
10
10
|
errorReportEmitter.on('GLOBAL_ERROR', (error, errorData: ErrorData) => {
|
|
11
11
|
const extra = {
|
|
@@ -4,7 +4,7 @@ export * from '../../common/report/types';
|
|
|
4
4
|
import { createTracks, ReportHandler } from '@/common/report';
|
|
5
5
|
import { context } from '@/common/context';
|
|
6
6
|
import { NativeTaskTracker } from './task-tracker';
|
|
7
|
-
import { invokeNative } from '
|
|
7
|
+
import { invokeNative } from '@jolibox/native-bridge';
|
|
8
8
|
|
|
9
9
|
const reportNative: ReportHandler = (event, data, webviewId) => {
|
|
10
10
|
const _data = data as Record<string, unknown>;
|
|
@@ -6,7 +6,7 @@ import { context } from '@/common/context';
|
|
|
6
6
|
import { TaskTracker, TaskPoint } from '@/common/report/task-track';
|
|
7
7
|
import { EventEmitter } from '@jolibox/common';
|
|
8
8
|
import { innerFetch as fetch } from '../network';
|
|
9
|
-
import { applyNative } from '
|
|
9
|
+
import { applyNative } from '@jolibox/native-bridge';
|
|
10
10
|
import type { Track } from '.';
|
|
11
11
|
import type { TrackEvent } from '@jolibox/types';
|
|
12
12
|
|