@jolibox/implement 1.1.32 → 1.1.34
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 +15 -13
- package/dist/common/context/index.d.ts +2 -1
- package/dist/common/report/types.d.ts +2 -1
- package/dist/h5/api/ads.d.ts +12 -1
- package/dist/h5/api/platformAdsHandle/DlightekAdsHandler.d.ts +11 -0
- package/dist/h5/api/platformAdsHandle/HuaweiQuickAdsHandler.d.ts +16 -0
- package/dist/index.js +9 -9
- package/dist/index.native.js +79 -62
- package/dist/native/rewards/check-frequency.d.ts +8 -2
- package/implement.build.log +2 -2
- package/package.json +5 -5
- package/src/common/context/index.ts +6 -1
- package/src/common/report/track.ts +4 -2
- package/src/common/report/types.ts +3 -3
- package/src/common/rewards/registers/utils/coins/index.ts +1 -5
- package/src/h5/api/ads.ts +14 -31
- package/src/h5/api/platformAdsHandle/DlightekAdsHandler.ts +26 -0
- package/src/h5/api/platformAdsHandle/HuaweiQuickAdsHandler.ts +268 -0
- package/src/native/api/get-system-info.ts +10 -2
- package/src/native/api/login.ts +28 -10
- package/src/native/payment/registers/jolicoin-iap.ts +7 -5
- package/src/native/report/index.ts +5 -2
- package/src/native/rewards/check-frequency.ts +32 -8
- package/src/native/rewards/index.ts +83 -5
- package/src/native/ui/retention.ts +39 -1
|
@@ -22,19 +22,31 @@ export const checkUseModalFrequency = async (config: { dailyMaxPopUps: number; m
|
|
|
22
22
|
const res = (await getGlobalStorage('joli_coin_use_modal_frequency')) as StandardResponse<string>;
|
|
23
23
|
console.log('checkUseModalFrequency', res.data);
|
|
24
24
|
if (!res.data) {
|
|
25
|
-
return
|
|
25
|
+
return {
|
|
26
|
+
canShow: true,
|
|
27
|
+
isFirst: true
|
|
28
|
+
};
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
const fequeycies = parseFrequency(res.data);
|
|
29
32
|
const todayFequencies = filterTodayTimestamps(fequeycies);
|
|
30
33
|
if (todayFequencies.length >= dailyMaxPopUps) {
|
|
31
|
-
return
|
|
34
|
+
return {
|
|
35
|
+
canShow: false,
|
|
36
|
+
isFirst: false
|
|
37
|
+
};
|
|
32
38
|
}
|
|
33
39
|
const now = Date.now();
|
|
34
40
|
if (now - todayFequencies[todayFequencies.length - 1] < minInterval) {
|
|
35
|
-
return
|
|
41
|
+
return {
|
|
42
|
+
canShow: false,
|
|
43
|
+
isFirst: false
|
|
44
|
+
};
|
|
36
45
|
}
|
|
37
|
-
return
|
|
46
|
+
return {
|
|
47
|
+
canShow: true,
|
|
48
|
+
isFirst: false
|
|
49
|
+
};
|
|
38
50
|
};
|
|
39
51
|
|
|
40
52
|
export const updateUseModalFrequency = async () => {
|
|
@@ -56,18 +68,30 @@ export const checkPaymentFrequency = async (config: { dailyMaxPopUps: number; mi
|
|
|
56
68
|
const res = (await getGlobalStorage('joli_coin_payment_frequency')) as StandardResponse<string>;
|
|
57
69
|
console.log('checkPaymentFrequency', res.data);
|
|
58
70
|
if (!res.data) {
|
|
59
|
-
return
|
|
71
|
+
return {
|
|
72
|
+
canShow: true,
|
|
73
|
+
isFirst: true
|
|
74
|
+
};
|
|
60
75
|
}
|
|
61
76
|
const frequencies = parseFrequency(res.data);
|
|
62
77
|
const todayFequencies = filterTodayTimestamps(frequencies);
|
|
63
78
|
if (todayFequencies.length >= dailyMaxPopUps) {
|
|
64
|
-
return
|
|
79
|
+
return {
|
|
80
|
+
canShow: false,
|
|
81
|
+
isFirst: false
|
|
82
|
+
};
|
|
65
83
|
}
|
|
66
84
|
const now = Date.now();
|
|
67
85
|
if (now - todayFequencies[todayFequencies.length - 1] < minInterval) {
|
|
68
|
-
return
|
|
86
|
+
return {
|
|
87
|
+
canShow: false,
|
|
88
|
+
isFirst: false
|
|
89
|
+
};
|
|
69
90
|
}
|
|
70
|
-
return
|
|
91
|
+
return {
|
|
92
|
+
canShow: true,
|
|
93
|
+
isFirst: false
|
|
94
|
+
};
|
|
71
95
|
};
|
|
72
96
|
|
|
73
97
|
/**
|
|
@@ -19,6 +19,7 @@ import { innerFetch as fetch } from '../network';
|
|
|
19
19
|
import { StandardResponse } from '@jolibox/types';
|
|
20
20
|
import { context } from '@/common/context';
|
|
21
21
|
import { login } from '../api/login';
|
|
22
|
+
import { EventType } from '@jolibox/common';
|
|
22
23
|
|
|
23
24
|
import { createEventPromiseHandler } from '@/common/rewards/registers/utils/event-listener';
|
|
24
25
|
import {
|
|
@@ -32,6 +33,7 @@ import { createLoading } from '@jolibox/ui';
|
|
|
32
33
|
import { canIUseNative } from '../api/base';
|
|
33
34
|
import { applyNative } from '@jolibox/native-bridge';
|
|
34
35
|
import { isUndefinedOrNull } from '@jolibox/common';
|
|
36
|
+
import { track } from '../report';
|
|
35
37
|
|
|
36
38
|
const modalUseFrequencyConfig = createEventPromiseHandler<
|
|
37
39
|
IUseModalFrequencyConfig,
|
|
@@ -77,15 +79,33 @@ rewardsEmitter.on(UseModalEventName, async (type: 'JOLI_COIN' | 'ADS-JOLI_COIN',
|
|
|
77
79
|
duration: 3000
|
|
78
80
|
});
|
|
79
81
|
const config = await modalUseFrequencyConfig.getData();
|
|
80
|
-
const canShowUseModal = await checkUseModalFrequency(
|
|
81
|
-
|
|
82
|
+
const { canShow: canShowUseModal, isFirst: isFirstUseModal } = await checkUseModalFrequency(
|
|
83
|
+
config.joliCoinUseAndCharge.useJolicoin
|
|
84
|
+
);
|
|
85
|
+
console.log('use modal show by frequency', canShowUseModal, isFirstUseModal);
|
|
82
86
|
loading.hide();
|
|
87
|
+
|
|
88
|
+
// First, check for direct use: sufficient balance, auto-deduct enabled, and not the first modal.
|
|
89
|
+
const { balance } = params.userJoliCoin;
|
|
90
|
+
const useDirectly = balance >= params.joliCoinQuantity && params.enableAutoDeduct;
|
|
91
|
+
if (useDirectly && !isFirstUseModal) {
|
|
92
|
+
rewardsEmitter.emit(UseModalResultEventName, { useModalResult: 'CONFIRM' });
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// If not used directly, then check frequency control.
|
|
83
97
|
if (!canShowUseModal) {
|
|
84
|
-
//
|
|
98
|
+
// confirm by frequency control
|
|
85
99
|
rewardsEmitter.emit(UseModalResultEventName, { useModalResult: 'CONFIRM' });
|
|
86
100
|
return;
|
|
87
101
|
}
|
|
88
102
|
}
|
|
103
|
+
|
|
104
|
+
track('unlock_popup_show', {
|
|
105
|
+
eventType: EventType.View,
|
|
106
|
+
targetType: 'game'
|
|
107
|
+
});
|
|
108
|
+
|
|
89
109
|
const modal = createConfirmJolicoinModal({
|
|
90
110
|
data: {
|
|
91
111
|
enableAutoDeduct: params.enableAutoDeduct,
|
|
@@ -96,6 +116,12 @@ rewardsEmitter.on(UseModalEventName, async (type: 'JOLI_COIN' | 'ADS-JOLI_COIN',
|
|
|
96
116
|
confirm: {
|
|
97
117
|
text: params.confirmButtonText,
|
|
98
118
|
onPress: () => {
|
|
119
|
+
track('coin_unlock_click', {
|
|
120
|
+
targetType: 'game',
|
|
121
|
+
eventType: EventType.Click,
|
|
122
|
+
coinConsume: params.joliCoinQuantity,
|
|
123
|
+
ifAutoUnlock: params.enableAutoDeduct
|
|
124
|
+
});
|
|
99
125
|
rewardsEmitter.emit(UseModalResultEventName, { useModalResult: 'CONFIRM' });
|
|
100
126
|
modal.destroy();
|
|
101
127
|
}
|
|
@@ -103,6 +129,12 @@ rewardsEmitter.on(UseModalEventName, async (type: 'JOLI_COIN' | 'ADS-JOLI_COIN',
|
|
|
103
129
|
cancel: {
|
|
104
130
|
text: params.cancelButtonText,
|
|
105
131
|
onPress: ({ type }) => {
|
|
132
|
+
if (type === 'FAILED') {
|
|
133
|
+
track('ad_unlock_click', {
|
|
134
|
+
targetType: 'game',
|
|
135
|
+
eventType: EventType.Click
|
|
136
|
+
});
|
|
137
|
+
}
|
|
106
138
|
rewardsEmitter.emit(UseModalResultEventName, {
|
|
107
139
|
useModalResult: (type ?? '') === 'CANCEL' ? 'CANCEL' : 'FAILED'
|
|
108
140
|
});
|
|
@@ -140,7 +172,9 @@ rewardsEmitter.on(
|
|
|
140
172
|
duration: 3000
|
|
141
173
|
});
|
|
142
174
|
const config = await modalUseFrequencyConfig.getData();
|
|
143
|
-
const canShowPaymentModal = await checkPaymentFrequency(
|
|
175
|
+
const { canShow: canShowPaymentModal } = await checkPaymentFrequency(
|
|
176
|
+
config.joliCoinUseAndCharge.charge
|
|
177
|
+
);
|
|
144
178
|
console.log('use payment show by frequency', canShowPaymentModal);
|
|
145
179
|
loading.hide();
|
|
146
180
|
if (!canShowPaymentModal) {
|
|
@@ -164,6 +198,12 @@ rewardsEmitter.on(
|
|
|
164
198
|
rewardsEmitter.emit(PaymentResultEventName, { paymentResult: 'FAILED' });
|
|
165
199
|
return;
|
|
166
200
|
}
|
|
201
|
+
|
|
202
|
+
track('coinorder_show', {
|
|
203
|
+
targetType: 'game',
|
|
204
|
+
eventType: EventType.View
|
|
205
|
+
});
|
|
206
|
+
|
|
167
207
|
const modal = createPaymentJolicoinModal({
|
|
168
208
|
data: {
|
|
169
209
|
userJolicoin: params.userJoliCoin,
|
|
@@ -179,8 +219,19 @@ rewardsEmitter.on(
|
|
|
179
219
|
confirm: {
|
|
180
220
|
text: params.confirmButtonText,
|
|
181
221
|
onPress: async (productId: string) => {
|
|
222
|
+
track('order_pay_ensure', {
|
|
223
|
+
targetType: 'game',
|
|
224
|
+
eventType: EventType.Click,
|
|
225
|
+
payWay: 'app_iap',
|
|
226
|
+
coinAmount: params.joliCoinQuantity,
|
|
227
|
+
orderPrice:
|
|
228
|
+
balenceDetails.paymentChoices.find((choice) => choice.productId === productId)
|
|
229
|
+
?.totalAmountStr ?? ''
|
|
230
|
+
});
|
|
182
231
|
if (!context.hostUserInfo?.isLogin) {
|
|
183
|
-
const { data } = await login(
|
|
232
|
+
const { data } = await login({
|
|
233
|
+
skipLogin: true
|
|
234
|
+
});
|
|
184
235
|
if (!data?.isLogin) {
|
|
185
236
|
console.log('login failed');
|
|
186
237
|
return;
|
|
@@ -211,6 +262,16 @@ rewardsEmitter.on(
|
|
|
211
262
|
appStoreProductId
|
|
212
263
|
});
|
|
213
264
|
loading.hide();
|
|
265
|
+
track('order_pay_result', {
|
|
266
|
+
eventType: EventType.Other,
|
|
267
|
+
targetType: 'game',
|
|
268
|
+
payWay: 'app_iap',
|
|
269
|
+
coinAmount: params.joliCoinQuantity,
|
|
270
|
+
orderPrice:
|
|
271
|
+
balenceDetails.paymentChoices.find((choice) => choice.productId === productId)
|
|
272
|
+
?.totalAmountStr ?? '',
|
|
273
|
+
payResult: code
|
|
274
|
+
});
|
|
214
275
|
if (code !== 'SUCCESS') {
|
|
215
276
|
/** add timeout for google panel closed */
|
|
216
277
|
console.info('[JoliboxSDK] payment failed in payment.invokePaymet');
|
|
@@ -226,12 +287,26 @@ rewardsEmitter.on(
|
|
|
226
287
|
rewardsEmitter.emit(PaymentResultEventName, {
|
|
227
288
|
paymentResult: (type ?? '') === 'CANCEL' ? 'CANCEL' : 'FAILED'
|
|
228
289
|
});
|
|
290
|
+
track('ad_unlock_click', {
|
|
291
|
+
targetType: 'game',
|
|
292
|
+
eventType: EventType.Click
|
|
293
|
+
});
|
|
229
294
|
modal.destroy();
|
|
230
295
|
}
|
|
231
296
|
},
|
|
232
297
|
onEnableDeductChanged: async (enabled: boolean) => {
|
|
233
298
|
await updateAutoDeductConfig(enabled);
|
|
234
299
|
}
|
|
300
|
+
},
|
|
301
|
+
onSelect: (productId: string) => {
|
|
302
|
+
track('coinorder_click', {
|
|
303
|
+
targetType: 'game',
|
|
304
|
+
eventType: EventType.Click,
|
|
305
|
+
coinAmount: params.joliCoinQuantity,
|
|
306
|
+
orderPrice:
|
|
307
|
+
balenceDetails.paymentChoices.find((choice) => choice.productId === productId)
|
|
308
|
+
?.totalAmountStr ?? ''
|
|
309
|
+
});
|
|
235
310
|
}
|
|
236
311
|
});
|
|
237
312
|
|
|
@@ -292,5 +367,8 @@ const getBalenceDetails = async (): Promise<
|
|
|
292
367
|
mergeResponseData(response.data?.data, data);
|
|
293
368
|
}
|
|
294
369
|
console.info('productDetails', response.data?.data);
|
|
370
|
+
if (response.data?.data?.paymentChoices.length === 0) {
|
|
371
|
+
throw new Error('paymentChoices is empty');
|
|
372
|
+
}
|
|
295
373
|
return response.data?.data;
|
|
296
374
|
};
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { context } from '@/common/context';
|
|
2
2
|
import { invokeNative, subscribe } from '@jolibox/native-bridge';
|
|
3
|
-
import { Deferred } from '@jolibox/common';
|
|
3
|
+
import { Deferred, EventType } from '@jolibox/common';
|
|
4
4
|
import { createRecommendModal, IGame, IRecommendationButton, RecommendModalOnCloseParams } from '@jolibox/ui';
|
|
5
5
|
import { innerFetch as fetch } from '../network';
|
|
6
|
+
import { track } from '../report';
|
|
7
|
+
|
|
8
|
+
enum RecommendGuideType {
|
|
9
|
+
Hide = 'Hide',
|
|
10
|
+
View = 'View',
|
|
11
|
+
Click = 'Click'
|
|
12
|
+
}
|
|
6
13
|
|
|
7
14
|
let exitRecommendationsCache: {
|
|
8
15
|
code: string;
|
|
@@ -96,6 +103,17 @@ export async function openRetentionSchema() {
|
|
|
96
103
|
const { gameListInfo, title, buttons } = data.data;
|
|
97
104
|
|
|
98
105
|
isOpenRetentionSchema = true;
|
|
106
|
+
|
|
107
|
+
const modalContentForReport = {
|
|
108
|
+
domain: 'GAME',
|
|
109
|
+
buttons: data.data.buttons.map((btn) => `${btn.type}-${btn.text}`).join(','),
|
|
110
|
+
list: gameListInfo.games.map((game) => game.gameId).join(',')
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
track('RecommendedGuide', {
|
|
114
|
+
eventType: EventType.View,
|
|
115
|
+
...modalContentForReport
|
|
116
|
+
});
|
|
99
117
|
const modal = createRecommendModal({
|
|
100
118
|
games: gameListInfo.games,
|
|
101
119
|
title,
|
|
@@ -104,17 +122,33 @@ export async function openRetentionSchema() {
|
|
|
104
122
|
isOpenRetentionSchema = false;
|
|
105
123
|
switch (params.type) {
|
|
106
124
|
case 'quit':
|
|
125
|
+
track('RecommendedGuide', {
|
|
126
|
+
eventType: EventType.Click,
|
|
127
|
+
type: 'QUIT',
|
|
128
|
+
domain: 'GAME'
|
|
129
|
+
});
|
|
107
130
|
quitResultDeffer.resolve(false);
|
|
108
131
|
break;
|
|
109
132
|
case 'dismiss':
|
|
133
|
+
track('RecommendedGuide', {
|
|
134
|
+
eventType: EventType.Hide,
|
|
135
|
+
...modalContentForReport
|
|
136
|
+
});
|
|
110
137
|
quitResultDeffer.resolve(true);
|
|
111
138
|
modal.destroy();
|
|
139
|
+
|
|
112
140
|
break;
|
|
113
141
|
case 'navigate':
|
|
114
142
|
// TODO: 跳转游戏
|
|
115
143
|
if (params.data?.game) {
|
|
116
144
|
const game = params.data.game;
|
|
117
145
|
openGameSchema(game);
|
|
146
|
+
track('GameItem', {
|
|
147
|
+
eventType: EventType.Click,
|
|
148
|
+
gameId: game.gameId,
|
|
149
|
+
layerName: 'RecommendedGuide',
|
|
150
|
+
domain: 'GAME'
|
|
151
|
+
});
|
|
118
152
|
setTimeout(() => {
|
|
119
153
|
quitResultDeffer.resolve(false);
|
|
120
154
|
}, 0);
|
|
@@ -125,6 +159,10 @@ export async function openRetentionSchema() {
|
|
|
125
159
|
break;
|
|
126
160
|
default:
|
|
127
161
|
// 关闭弹框,留在当前游戏
|
|
162
|
+
track('RecommendedGuide', {
|
|
163
|
+
eventType: EventType.Hide,
|
|
164
|
+
...modalContentForReport
|
|
165
|
+
});
|
|
128
166
|
quitResultDeffer.resolve(true);
|
|
129
167
|
break;
|
|
130
168
|
}
|