@jolibox/implement 1.1.18 → 1.1.19-beta.6
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 +23 -16
- package/.rush/temp/shrinkwrap-deps.json +1 -1
- package/dist/common/rewards/index.d.ts +1 -10
- package/dist/common/rewards/registers/use-ads.d.ts +3 -2
- package/dist/common/rewards/registers/use-jolicoin-only.d.ts +10 -0
- package/dist/common/rewards/registers/utils/coins/index.d.ts +32 -0
- package/dist/common/rewards/registers/utils/event-listener.d.ts +15 -0
- package/dist/common/rewards/registers/utils/index.d.ts +1 -0
- package/dist/common/rewards/reward-emitter.d.ts +58 -0
- package/dist/common/rewards/reward-helper.d.ts +2 -1
- package/dist/common/utils/index.d.ts +49 -2
- package/dist/h5/api/ads.d.ts +1 -1
- package/dist/h5/http/index.d.ts +1 -1
- package/dist/h5/rewards/index.d.ts +4 -0
- package/dist/index.js +197 -3
- package/dist/index.native.js +402 -21
- package/dist/native/api/ads.d.ts +1 -1
- package/dist/native/api/login.d.ts +4 -1
- package/dist/native/rewards/index.d.ts +4 -0
- package/dist/native/ui/modal-iframe.d.ts +26 -0
- package/implement.build.log +2 -2
- package/package.json +5 -4
- package/src/common/context/index.ts +3 -3
- package/src/common/rewards/fetch-reward.ts +9 -3
- package/src/common/rewards/index.ts +1 -12
- package/src/common/rewards/registers/use-ads.ts +3 -2
- package/src/common/rewards/registers/use-jolicoin-only.ts +57 -0
- package/src/common/rewards/registers/use-jolicoin.ts +27 -77
- package/src/common/rewards/registers/utils/coins/index.ts +186 -0
- package/src/common/rewards/registers/utils/event-listener.ts +66 -0
- package/src/common/rewards/registers/utils/index.ts +8 -0
- package/src/common/rewards/reward-emitter.ts +79 -0
- package/src/common/rewards/reward-helper.ts +3 -2
- package/src/common/utils/index.ts +117 -4
- package/src/h5/api/ads.ts +65 -12
- package/src/h5/http/index.ts +2 -2
- package/src/h5/rewards/index.ts +69 -0
- package/src/native/api/ads.ts +95 -33
- package/src/native/api/login.ts +1 -1
- package/src/native/api/navigate.ts +13 -1
- package/src/native/bootstrap/index.ts +25 -1
- package/src/native/rewards/index.ts +138 -0
- package/src/native/ui/modal-iframe.ts +271 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// rewards-emitter-wrapper.ts
|
|
2
|
+
|
|
3
|
+
import { EventEmitter } from '@jolibox/common';
|
|
4
|
+
import { IUnlockOption } from './type';
|
|
5
|
+
import { IJoliCoin } from './type';
|
|
6
|
+
|
|
7
|
+
export interface IUnlockOptionsEvent {
|
|
8
|
+
options: IUnlockOption[];
|
|
9
|
+
userJoliCoin: IJoliCoin;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const UnlockOptionsEventName = 'UNLOCK_OPTIONS_CHANGED' as const;
|
|
13
|
+
export const InvokePaymentEventName = 'INVOKE_PAYMENT' as const;
|
|
14
|
+
export const PaymentResultEventName = 'ON_PAYMENT_RESULT' as const;
|
|
15
|
+
export const UseModalEventName = 'ON_USE_MODAL_EVENT' as const;
|
|
16
|
+
export const UseModalResultEventName = 'ON_USE_MODAL_RESULT' as const;
|
|
17
|
+
|
|
18
|
+
type IPaymentResult = 'SUCCESS' | 'FAILED' | 'CANCEL';
|
|
19
|
+
export interface IPaymentEvent {
|
|
20
|
+
userJoliCoin?: IJoliCoin;
|
|
21
|
+
paymentResult: IPaymentResult;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface IPaymentChoice {
|
|
25
|
+
productId: string;
|
|
26
|
+
totalAmountStr: string;
|
|
27
|
+
quantity: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface IInvokePaymentEvent {
|
|
31
|
+
userJoliCoin: IJoliCoin;
|
|
32
|
+
joliCoinQuantity: number;
|
|
33
|
+
enableAutoDeduct: boolean;
|
|
34
|
+
confirmButtonText: string;
|
|
35
|
+
cancelButtonText: string;
|
|
36
|
+
sequenceId?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface IUseModalEvent {
|
|
40
|
+
enableAutoDeduct: boolean;
|
|
41
|
+
userJoliCoin: IJoliCoin;
|
|
42
|
+
joliCoinQuantity: number;
|
|
43
|
+
confirmButtonText: string;
|
|
44
|
+
cancelButtonText: string;
|
|
45
|
+
sequenceId?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface IUseModalResultEvent {
|
|
49
|
+
useModalResult: 'CONFIRM' | 'CANCEL' | 'FAILED';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface RewardsEventMap extends Record<string, unknown[]> {
|
|
53
|
+
[UnlockOptionsEventName]: [IUnlockOptionsEvent];
|
|
54
|
+
[InvokePaymentEventName]: ['JOLI_COIN' | 'ADS-JOLI_COIN', IInvokePaymentEvent];
|
|
55
|
+
[PaymentResultEventName]: [IPaymentEvent];
|
|
56
|
+
[UseModalResultEventName]: [IUseModalResultEvent];
|
|
57
|
+
[UseModalEventName]: ['JOLI_COIN' | 'ADS-JOLI_COIN', IUseModalEvent];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export const originalRewardsEmitter = new EventEmitter<RewardsEventMap>();
|
|
61
|
+
|
|
62
|
+
export type RewardsEventType = keyof RewardsEventMap;
|
|
63
|
+
|
|
64
|
+
export interface RewardsEmitter {
|
|
65
|
+
on<T extends RewardsEventType>(event: T, callback: (...args: RewardsEventMap[T]) => void): void;
|
|
66
|
+
off<T extends RewardsEventType>(event: T, callback: (...args: RewardsEventMap[T]) => void): void;
|
|
67
|
+
emit<T extends RewardsEventType>(event: T, ...args: RewardsEventMap[T]): void;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// 创建包装器
|
|
71
|
+
export const createRewardsEmitterWrapper = (): RewardsEmitter => {
|
|
72
|
+
return {
|
|
73
|
+
on: originalRewardsEmitter.on.bind(originalRewardsEmitter),
|
|
74
|
+
off: originalRewardsEmitter.off.bind(originalRewardsEmitter),
|
|
75
|
+
emit: originalRewardsEmitter.emit.bind(originalRewardsEmitter)
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export const rewardsEmitter = createRewardsEmitterWrapper();
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
export type RewardType = 'ADS' | 'JOLI_COIN';
|
|
1
|
+
export type RewardType = 'ADS' | 'JOLI_COIN' | 'JOLI_COIN_ONLY';
|
|
2
2
|
|
|
3
3
|
import { context } from '../context';
|
|
4
4
|
import type { AdsRewardsHandler } from './registers/use-ads';
|
|
5
5
|
|
|
6
6
|
export interface RewardHandlerMap {
|
|
7
7
|
ADS: AdsRewardsHandler;
|
|
8
|
-
JOLI_COIN: (params?: unknown) => Promise<boolean>;
|
|
8
|
+
JOLI_COIN: (params?: unknown) => Promise<boolean>; // coins + ads
|
|
9
|
+
JOLI_COIN_ONLY: (params?: unknown) => Promise<boolean>; // coins only
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
export type RewardHandler<T extends RewardType> = RewardHandlerMap[T];
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* event send to parent window
|
|
3
|
+
*/
|
|
1
4
|
const JOLIBOX_CUSTOM_ADS_EVENT_TYPE = 'JOLIBOX_ADS_EVENT';
|
|
2
5
|
const JOLIBOX_CUSTOM_REWARDS_EVENT_TYPE = 'JOLIBOX_CUSTOM_REWARDS_EVENT';
|
|
6
|
+
const JOLIBOX_TOPUP_EVENT = 'JOLIBOX_TOPUP_EVENT';
|
|
7
|
+
const JOLIBOX_JOLI_COIN_USE_EVENT = 'JOLIBOX_JOLI_COIN_USE_EVENT';
|
|
3
8
|
|
|
4
9
|
interface JoliboxCustomEvent {
|
|
5
10
|
[JOLIBOX_CUSTOM_ADS_EVENT_TYPE]: {
|
|
@@ -11,12 +16,28 @@ interface JoliboxCustomEvent {
|
|
|
11
16
|
balance: number;
|
|
12
17
|
};
|
|
13
18
|
};
|
|
19
|
+
[JOLIBOX_TOPUP_EVENT]: {
|
|
20
|
+
['JOLI_COIN']?: {
|
|
21
|
+
quantity: number;
|
|
22
|
+
balance: number;
|
|
23
|
+
enableAutoDeduct?: boolean;
|
|
24
|
+
};
|
|
25
|
+
type: 'ADS-JOLI_COIN' | 'JOLI_COIN';
|
|
26
|
+
sequenceId: string;
|
|
27
|
+
};
|
|
28
|
+
//
|
|
29
|
+
[JOLIBOX_JOLI_COIN_USE_EVENT]: {
|
|
30
|
+
['JOLI_COIN']?: {
|
|
31
|
+
quantity: number;
|
|
32
|
+
balance: number;
|
|
33
|
+
enableAutoDeduct?: boolean;
|
|
34
|
+
};
|
|
35
|
+
type: 'ADS-JOLI_COIN' | 'JOLI_COIN';
|
|
36
|
+
sequenceId: string;
|
|
37
|
+
};
|
|
14
38
|
}
|
|
15
39
|
|
|
16
|
-
|
|
17
|
-
eventName: T,
|
|
18
|
-
data: JoliboxCustomEvent[T]
|
|
19
|
-
) => {
|
|
40
|
+
const notifyCustomEvent = <T extends keyof JoliboxCustomEvent>(eventName: T, data: JoliboxCustomEvent[T]) => {
|
|
20
41
|
window.dispatchEvent(new CustomEvent(eventName, { detail: data }));
|
|
21
42
|
window.parent?.postMessage(
|
|
22
43
|
{
|
|
@@ -28,3 +49,95 @@ export const notifyCustomEvent = <T extends keyof JoliboxCustomEvent>(
|
|
|
28
49
|
'*'
|
|
29
50
|
);
|
|
30
51
|
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* received event to parent window
|
|
55
|
+
* @param eventName
|
|
56
|
+
* @param data
|
|
57
|
+
*/
|
|
58
|
+
|
|
59
|
+
const ON_JOLIBOX_TOPUP_JOLI_COIN_RESULT = 'ON_JOLIBOX_TOPUP_JOLI_COIN_RESULT';
|
|
60
|
+
const ON_JOLIBOX_JOLI_COIN_USE_RESULT = 'ON_JOLIBOX_JOLI_COIN_USE_RESULT';
|
|
61
|
+
|
|
62
|
+
interface ReceivedJoliboxCustomEvent {
|
|
63
|
+
[ON_JOLIBOX_TOPUP_JOLI_COIN_RESULT]: {
|
|
64
|
+
sequenceId: string;
|
|
65
|
+
result: 'SUCCESS' | 'CANCEL' | 'ADS';
|
|
66
|
+
type: 'ADS-JOLI_COIN' | 'JOLI_COIN';
|
|
67
|
+
joliCoin: {
|
|
68
|
+
enableAutoDeduct: boolean;
|
|
69
|
+
balance: number;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
[ON_JOLIBOX_JOLI_COIN_USE_RESULT]: {
|
|
73
|
+
sequenceId: string;
|
|
74
|
+
result: 'USE_COIN' | 'ADS' | 'CANCEL';
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
type ReceivedJoliboxCustomEventResult = keyof ReceivedJoliboxCustomEvent;
|
|
79
|
+
|
|
80
|
+
interface MessageData<T extends ReceivedJoliboxCustomEventResult> {
|
|
81
|
+
type: T;
|
|
82
|
+
data: ReceivedJoliboxCustomEvent[T];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const eventCallbacks = new Map<string, Set<(data: any) => void>>();
|
|
86
|
+
|
|
87
|
+
const globalMessageHandler = (event: MessageEvent) => {
|
|
88
|
+
if (event.source !== window.parent) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
const message = event.data as MessageData<any>;
|
|
94
|
+
if (message && message.type) {
|
|
95
|
+
const callbacks = eventCallbacks.get(message.type);
|
|
96
|
+
if (callbacks) {
|
|
97
|
+
callbacks.forEach((callback) => {
|
|
98
|
+
try {
|
|
99
|
+
callback(message.data);
|
|
100
|
+
} catch (error) {
|
|
101
|
+
console.warn('Callback execution failed:', error);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
} catch (error) {
|
|
107
|
+
console.warn('Failed to parse message:', error);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
let isInitialized = false;
|
|
112
|
+
const initializeGlobalListener = () => {
|
|
113
|
+
if (!isInitialized) {
|
|
114
|
+
window.addEventListener('message', globalMessageHandler);
|
|
115
|
+
isInitialized = true;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const onCustomEvent = <T extends ReceivedJoliboxCustomEventResult>(
|
|
120
|
+
eventName: T,
|
|
121
|
+
callback: (data: ReceivedJoliboxCustomEvent[T]) => void
|
|
122
|
+
) => {
|
|
123
|
+
initializeGlobalListener();
|
|
124
|
+
|
|
125
|
+
if (!eventCallbacks.has(eventName)) {
|
|
126
|
+
eventCallbacks.set(eventName, new Set());
|
|
127
|
+
}
|
|
128
|
+
const callbacks = eventCallbacks.get(eventName)!;
|
|
129
|
+
|
|
130
|
+
callbacks.add(callback);
|
|
131
|
+
return () => {
|
|
132
|
+
callbacks.delete(callback);
|
|
133
|
+
if (callbacks.size === 0) {
|
|
134
|
+
eventCallbacks.delete(eventName);
|
|
135
|
+
}
|
|
136
|
+
if (eventCallbacks.size === 0) {
|
|
137
|
+
window.removeEventListener('message', globalMessageHandler);
|
|
138
|
+
isInitialized = false;
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
export { onCustomEvent, notifyCustomEvent };
|
package/src/h5/api/ads.ts
CHANGED
|
@@ -1,23 +1,68 @@
|
|
|
1
|
-
import { JoliboxAdsImpl, adEventEmitter } from '@/common/ads';
|
|
2
1
|
import { track } from '../report';
|
|
3
|
-
import { createCommands } from '@jolibox/common';
|
|
2
|
+
import { createCommands, EventEmitter, platform } from '@jolibox/common';
|
|
4
3
|
import { httpClientManager } from '../http';
|
|
5
4
|
import { notifyCustomEvent } from '@/common/utils';
|
|
6
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
createAdsRewardHandler,
|
|
7
|
+
rewardsHelper,
|
|
8
|
+
createJolicoinRewardHandler,
|
|
9
|
+
createJolicoinOnlyRewardHandler
|
|
10
|
+
} from '@/common/rewards';
|
|
11
|
+
import { JoliboxAdsForGame, type IAdsContext } from '@jolibox/ads';
|
|
12
|
+
import { context } from '@/common/context';
|
|
13
|
+
import '../rewards';
|
|
7
14
|
|
|
8
15
|
const commands = createCommands();
|
|
9
16
|
|
|
17
|
+
const adEventEmitter = new EventEmitter<{
|
|
18
|
+
isAdShowing: [boolean];
|
|
19
|
+
}>();
|
|
20
|
+
|
|
10
21
|
const httpClient = httpClientManager.create();
|
|
11
|
-
|
|
22
|
+
|
|
23
|
+
const adsContext: IAdsContext<'GAME'> = {
|
|
24
|
+
httpClient,
|
|
25
|
+
checkNetwork: () => httpClientManager.getNetworkStatus(),
|
|
26
|
+
track,
|
|
27
|
+
eventEmitter: adEventEmitter,
|
|
28
|
+
getContextInfo: () => {
|
|
29
|
+
return {
|
|
30
|
+
hostAppId: context.hostInfo?.aid ?? '1',
|
|
31
|
+
deviceId: context.deviceInfo.did ?? '',
|
|
32
|
+
adId: context.deviceInfo.did ?? '', //TODO: @Deng Xue
|
|
33
|
+
sessionId: context.sessionId ?? '',
|
|
34
|
+
userId: context.hostUserInfo?.uid ?? '',
|
|
35
|
+
objectType: 'GAME',
|
|
36
|
+
objectId: context.mpId,
|
|
37
|
+
testAdsMode: context.testAdsMode,
|
|
38
|
+
channel: context.joliSource ?? '',
|
|
39
|
+
deviceBrand: context.deviceInfo.brand,
|
|
40
|
+
deviceModel: context.deviceInfo.model,
|
|
41
|
+
osType: platform.isAndroid ? 'ANDROID' : platform.isiOS ? 'IOS' : 'PC',
|
|
42
|
+
runtimeType: 'WEB',
|
|
43
|
+
platform: 1000 // WebSDK
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const handleUnlockSuccess = (params: { quantity: number; balance: number }) => {
|
|
49
|
+
notifyCustomEvent('JOLIBOX_CUSTOM_REWARDS_EVENT', {
|
|
50
|
+
JOLI_COIN: params
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const ads = new JoliboxAdsForGame(adsContext);
|
|
12
55
|
rewardsHelper.registerRewardHandler('ADS', createAdsRewardHandler(ads));
|
|
13
56
|
rewardsHelper.registerRewardHandler(
|
|
14
57
|
'JOLI_COIN',
|
|
15
|
-
createJolicoinRewardHandler(
|
|
16
|
-
onUnlockSuccess: (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
58
|
+
createJolicoinRewardHandler(httpClient, {
|
|
59
|
+
onUnlockSuccess: handleUnlockSuccess.bind(this)
|
|
60
|
+
}) as unknown as (params?: unknown) => Promise<boolean>
|
|
61
|
+
);
|
|
62
|
+
rewardsHelper.registerRewardHandler(
|
|
63
|
+
'JOLI_COIN_ONLY',
|
|
64
|
+
createJolicoinOnlyRewardHandler(httpClient, {
|
|
65
|
+
onUnlockSuccess: handleUnlockSuccess.bind(this)
|
|
21
66
|
}) as unknown as (params?: unknown) => Promise<boolean>
|
|
22
67
|
);
|
|
23
68
|
|
|
@@ -35,8 +80,16 @@ commands.registerCommand('AdsSDK.adConfig', (params) => {
|
|
|
35
80
|
|
|
36
81
|
commands.registerCommand('AdsSDK.adBreak', (params) => {
|
|
37
82
|
if (params.type === 'reward') {
|
|
38
|
-
rewardsHelper.getRewardsTypes(
|
|
39
|
-
rewardsHelper.handleReward(rewardsTypes, params)
|
|
83
|
+
rewardsHelper.getRewardsTypes(httpClient).then((rewardsTypes) => {
|
|
84
|
+
rewardsHelper.handleReward(rewardsTypes, params).catch((e) => {
|
|
85
|
+
// error should terminate the reward handler, invoke unlock failed
|
|
86
|
+
console.info('handleReward failed', e);
|
|
87
|
+
params.adBreakDone?.({
|
|
88
|
+
breakType: params.type,
|
|
89
|
+
breakFormat: params.type === 'reward' ? 'reward' : 'interstitial',
|
|
90
|
+
breakStatus: 'noAdPreloaded'
|
|
91
|
+
});
|
|
92
|
+
});
|
|
40
93
|
});
|
|
41
94
|
} else {
|
|
42
95
|
ads.adBreak(params);
|
package/src/h5/http/index.ts
CHANGED
|
@@ -46,7 +46,7 @@ export class HttpClientManager {
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
getNetworkStatus(): boolean {
|
|
49
|
+
getNetworkStatus = (): boolean => {
|
|
50
50
|
if (this.networkRequests.length === 0) {
|
|
51
51
|
return true;
|
|
52
52
|
}
|
|
@@ -55,7 +55,7 @@ export class HttpClientManager {
|
|
|
55
55
|
const successRate = successCount / this.networkRequests.length;
|
|
56
56
|
|
|
57
57
|
return successRate >= 0.6;
|
|
58
|
-
}
|
|
58
|
+
};
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
class JoliboxHttpClient implements IHttpClient {
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rewards event handlers
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
rewardsEmitter,
|
|
7
|
+
UseModalEventName,
|
|
8
|
+
IUseModalEvent,
|
|
9
|
+
PaymentResultEventName,
|
|
10
|
+
UseModalResultEventName,
|
|
11
|
+
InvokePaymentEventName,
|
|
12
|
+
IInvokePaymentEvent,
|
|
13
|
+
IUseModalResultEvent
|
|
14
|
+
} from '@/common/rewards/reward-emitter';
|
|
15
|
+
import { notifyCustomEvent, onCustomEvent } from '@/common/utils';
|
|
16
|
+
import { uuidv4 as v4 } from '@jolibox/common';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* confirm jolicoin modal
|
|
20
|
+
*/
|
|
21
|
+
const UseCoinEventMap: Record<string, IUseModalResultEvent['useModalResult']> = {
|
|
22
|
+
USE_COIN: 'CONFIRM',
|
|
23
|
+
ADS: 'FAILED',
|
|
24
|
+
CANCEL: 'CANCEL'
|
|
25
|
+
};
|
|
26
|
+
onCustomEvent('ON_JOLIBOX_JOLI_COIN_USE_RESULT', (data) => {
|
|
27
|
+
console.log('onCustomEvent ON_JOLIBOX_JOLI_COIN_USE_RESULT', UseCoinEventMap[data.result]);
|
|
28
|
+
|
|
29
|
+
rewardsEmitter.emit(UseModalResultEventName, {
|
|
30
|
+
useModalResult: UseCoinEventMap[data.result]
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
rewardsEmitter.on(UseModalEventName, (type: 'JOLI_COIN' | 'ADS-JOLI_COIN', params: IUseModalEvent) => {
|
|
34
|
+
notifyCustomEvent('JOLIBOX_JOLI_COIN_USE_EVENT', {
|
|
35
|
+
JOLI_COIN: {
|
|
36
|
+
quantity: params.joliCoinQuantity,
|
|
37
|
+
balance: params.userJoliCoin.balance,
|
|
38
|
+
enableAutoDeduct: params.enableAutoDeduct
|
|
39
|
+
},
|
|
40
|
+
type,
|
|
41
|
+
sequenceId: params.sequenceId ?? v4()
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* payment jolicoin modal
|
|
47
|
+
*/
|
|
48
|
+
onCustomEvent('ON_JOLIBOX_TOPUP_JOLI_COIN_RESULT', (data) => {
|
|
49
|
+
rewardsEmitter.emit(PaymentResultEventName, {
|
|
50
|
+
paymentResult: data.result == 'ADS' ? 'FAILED' : data.result,
|
|
51
|
+
userJoliCoin: data.joliCoin
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
rewardsEmitter.on(
|
|
56
|
+
InvokePaymentEventName,
|
|
57
|
+
async (type: 'JOLI_COIN' | 'ADS-JOLI_COIN', params: IInvokePaymentEvent) => {
|
|
58
|
+
// 充值面板
|
|
59
|
+
notifyCustomEvent('JOLIBOX_TOPUP_EVENT', {
|
|
60
|
+
JOLI_COIN: {
|
|
61
|
+
quantity: params.joliCoinQuantity,
|
|
62
|
+
balance: params.userJoliCoin.balance,
|
|
63
|
+
enableAutoDeduct: params.enableAutoDeduct
|
|
64
|
+
},
|
|
65
|
+
type,
|
|
66
|
+
sequenceId: params.sequenceId ?? v4()
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
);
|
package/src/native/api/ads.ts
CHANGED
|
@@ -1,61 +1,116 @@
|
|
|
1
1
|
import { createCommands } from '@jolibox/common';
|
|
2
2
|
import { createSyncAPI, registerCanIUse } from './base';
|
|
3
3
|
import { createToast } from '@jolibox/ui';
|
|
4
|
+
import '../rewards';
|
|
4
5
|
|
|
5
6
|
const commands = createCommands();
|
|
6
7
|
|
|
7
|
-
import { IAdsInitParams, JoliboxAdsImpl, IAdConfigParams, IAdBreakParams, IAdUnitParams } from '@/common/ads';
|
|
8
|
+
// import { IAdsInitParams, JoliboxAdsImpl, IAdConfigParams, IAdBreakParams, IAdUnitParams } from '@/common/ads';
|
|
9
|
+
import {
|
|
10
|
+
JoliboxAdsForGame,
|
|
11
|
+
type IAdsInitParams,
|
|
12
|
+
type IAdsContext,
|
|
13
|
+
type IAdConfigParams,
|
|
14
|
+
type IAdBreakParams,
|
|
15
|
+
type IAdUnitParams
|
|
16
|
+
} from '@jolibox/ads';
|
|
8
17
|
import { track } from '../report';
|
|
18
|
+
import { context } from '@/common/context';
|
|
9
19
|
|
|
10
20
|
import { innerFetch as fetch } from '../network';
|
|
11
21
|
import { invokeNative } from '@jolibox/native-bridge';
|
|
12
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
rewardsHelper,
|
|
24
|
+
createAdsRewardHandler,
|
|
25
|
+
createJolicoinRewardHandler,
|
|
26
|
+
createJolicoinOnlyRewardHandler
|
|
27
|
+
} from '@/common/rewards';
|
|
13
28
|
|
|
14
29
|
const checkNetworkStatus = () => {
|
|
15
30
|
const { data } = invokeNative('getNetworkStatusSync');
|
|
16
31
|
return !!data?.isConnected;
|
|
17
32
|
};
|
|
18
|
-
|
|
33
|
+
|
|
34
|
+
const httpClient = {
|
|
35
|
+
get: <T>(url: string, options?: any) =>
|
|
36
|
+
fetch<T>(url, {
|
|
37
|
+
method: 'GET',
|
|
38
|
+
responseType: 'json',
|
|
39
|
+
appendHostCookie: true,
|
|
40
|
+
...options
|
|
41
|
+
}).then((res) => res.response.data as T),
|
|
42
|
+
post: <T>(url: string, options?: any) =>
|
|
43
|
+
fetch<T>(url, {
|
|
44
|
+
method: 'POST',
|
|
45
|
+
responseType: 'json',
|
|
46
|
+
appendHostCookie: true,
|
|
47
|
+
...options
|
|
48
|
+
}).then((res) => res.response.data as T)
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const adsContext: IAdsContext<'GAME'> = {
|
|
52
|
+
httpClient,
|
|
53
|
+
checkNetwork: checkNetworkStatus,
|
|
19
54
|
track,
|
|
20
|
-
{
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
55
|
+
getContextInfo: () => {
|
|
56
|
+
return {
|
|
57
|
+
hostAppId: context.hostInfo?.aid ?? '1',
|
|
58
|
+
deviceId: context.deviceInfo.did ?? '',
|
|
59
|
+
adId: context.deviceInfo.did ?? '', //TODO: @Deng Xue
|
|
60
|
+
sessionId: context.sessionId ?? '',
|
|
61
|
+
userId: context.hostUserInfo?.uid ?? '',
|
|
62
|
+
objectType: 'GAME',
|
|
63
|
+
objectId: context.mpId,
|
|
64
|
+
testAdsMode: context.testAdsMode,
|
|
65
|
+
channel: context.joliSource ?? '',
|
|
66
|
+
deviceBrand: context.deviceInfo.brand,
|
|
67
|
+
deviceModel: context.deviceInfo.model,
|
|
68
|
+
osType: context.platform === 'android' ? 'ANDROID' : context.platform === 'ios' ? 'IOS' : 'PC',
|
|
69
|
+
runtimeType: 'APP',
|
|
70
|
+
platform: 1000 // WebSDK
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const ads = new JoliboxAdsForGame(adsContext);
|
|
38
76
|
|
|
39
77
|
rewardsHelper.registerRewardHandler('ADS', createAdsRewardHandler(ads));
|
|
40
78
|
rewardsHelper.registerRewardHandler(
|
|
41
79
|
'JOLI_COIN',
|
|
42
|
-
createJolicoinRewardHandler(
|
|
80
|
+
createJolicoinRewardHandler(httpClient, {
|
|
43
81
|
onUnlockSuccess: (params) => {
|
|
44
|
-
|
|
45
|
-
const balanceStr = balance >= 1000 ? '999+' : balance;
|
|
46
|
-
createToast(`{slot-checkmark} −${quantity} {slot-coin} | Balance: ${balanceStr} {slot-coin}`, {
|
|
47
|
-
customStyle: {
|
|
48
|
-
mark: {
|
|
49
|
-
marginRight: '8px'
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
});
|
|
82
|
+
showUnlockSuccessToast(params);
|
|
53
83
|
},
|
|
54
84
|
onUnlockFailed: () => {
|
|
55
85
|
console.log('onUnlockFailed');
|
|
56
86
|
}
|
|
57
87
|
}) as unknown as (params?: unknown) => Promise<boolean>
|
|
58
88
|
);
|
|
89
|
+
|
|
90
|
+
rewardsHelper.registerRewardHandler(
|
|
91
|
+
'JOLI_COIN_ONLY',
|
|
92
|
+
createJolicoinOnlyRewardHandler(httpClient, {
|
|
93
|
+
onUnlockSuccess: (params) => {
|
|
94
|
+
showUnlockSuccessToast(params);
|
|
95
|
+
},
|
|
96
|
+
onUnlockFailed: () => {
|
|
97
|
+
console.log('onUnlockFailed');
|
|
98
|
+
}
|
|
99
|
+
}) as unknown as (params?: unknown) => Promise<boolean>
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
const showUnlockSuccessToast = (params: { quantity: number; balance: number }) => {
|
|
103
|
+
const { quantity } = params;
|
|
104
|
+
const toastTemplate = `{slot-coin} ${quantity} JoliCoins used`;
|
|
105
|
+
createToast(toastTemplate, {
|
|
106
|
+
customStyle: {
|
|
107
|
+
mark: {
|
|
108
|
+
marginRight: '8px'
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
};
|
|
113
|
+
|
|
59
114
|
const adInit = createSyncAPI('adInit', {
|
|
60
115
|
implement: (config?: IAdsInitParams) => {
|
|
61
116
|
ads.init(config);
|
|
@@ -71,8 +126,15 @@ const adConfig = createSyncAPI('adConfig', {
|
|
|
71
126
|
const adBreak = createSyncAPI('adBreak', {
|
|
72
127
|
implement: (params: IAdBreakParams) => {
|
|
73
128
|
if (params.type === 'reward') {
|
|
74
|
-
rewardsHelper.getRewardsTypes(
|
|
75
|
-
rewardsHelper.handleReward(rewardsTypes, params)
|
|
129
|
+
rewardsHelper.getRewardsTypes(httpClient).then((rewardsTypes) => {
|
|
130
|
+
rewardsHelper.handleReward(rewardsTypes, params).catch((e) => {
|
|
131
|
+
console.info('handleReward failed in native', e);
|
|
132
|
+
params.adBreakDone?.({
|
|
133
|
+
breakType: params.type,
|
|
134
|
+
breakFormat: params.type === 'reward' ? 'reward' : 'interstitial',
|
|
135
|
+
breakStatus: 'noAdPreloaded'
|
|
136
|
+
});
|
|
137
|
+
});
|
|
76
138
|
});
|
|
77
139
|
} else {
|
|
78
140
|
ads.adBreak(params);
|
package/src/native/api/login.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createCommands, UserCustomError } from '@jolibox/common';
|
|
1
|
+
import { createCommands, hostEmitter, UserCustomError } from '@jolibox/common';
|
|
2
2
|
import { invokeNative } from '@jolibox/native-bridge';
|
|
3
3
|
import { createSyncAPI, t, registerCanIUse } from './base';
|
|
4
4
|
import { context } from '@/common/context';
|
|
@@ -44,9 +44,17 @@ const closePageSync = createSyncAPI('closePageSync', {
|
|
|
44
44
|
}
|
|
45
45
|
});
|
|
46
46
|
|
|
47
|
+
const interceptSystemExitSync = createSyncAPI('interceptSystemExitSync', {
|
|
48
|
+
paramsSchema: t.tuple(t.boolean()),
|
|
49
|
+
implement: (intercept) => {
|
|
50
|
+
hostEmitter.emit('onInterceptSystemExit', { intercept });
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
47
54
|
commands.registerCommand('RouterSDK.openSchema', openSchemaSync);
|
|
48
55
|
commands.registerCommand('RouterSDK.openPage', openPageSync);
|
|
49
56
|
commands.registerCommand('RouterSDK.closePage', closePageSync);
|
|
57
|
+
commands.registerCommand('RouterSDK.interceptSystemExit', interceptSystemExitSync);
|
|
50
58
|
|
|
51
59
|
registerCanIUse('router.openSchema', {
|
|
52
60
|
version: '1.1.10'
|
|
@@ -59,3 +67,7 @@ registerCanIUse('router.openPage', {
|
|
|
59
67
|
registerCanIUse('router.closePage', {
|
|
60
68
|
version: '1.1.10'
|
|
61
69
|
});
|
|
70
|
+
|
|
71
|
+
registerCanIUse('router.interceptSystemExit', {
|
|
72
|
+
version: '1.1.18'
|
|
73
|
+
});
|