@jolibox/implement 1.1.38 → 1.1.40

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.
Files changed (48) hide show
  1. package/.rush/temp/package-deps_build.json +26 -15
  2. package/dist/common/rewards/registers/utils/coins/commands/index.d.ts +3 -0
  3. package/dist/common/rewards/registers/utils/coins/commands/use-jolicoin.d.ts +16 -0
  4. package/dist/common/rewards/registers/utils/coins/commands/use-payment.d.ts +16 -0
  5. package/dist/common/rewards/registers/utils/coins/commands/use-unlogin.d.ts +18 -0
  6. package/dist/common/rewards/registers/utils/coins/fetch-balance.d.ts +4 -0
  7. package/dist/common/rewards/registers/utils/coins/index.d.ts +3 -17
  8. package/dist/common/rewards/registers/utils/coins/rewards-command.d.ts +1 -0
  9. package/dist/common/rewards/registers/utils/common.d.ts +8 -0
  10. package/dist/common/rewards/registers/utils/event-listener.d.ts +1 -0
  11. package/dist/common/rewards/reward-emitter.d.ts +30 -4
  12. package/dist/common/utils/index.d.ts +19 -0
  13. package/dist/index.js +25 -25
  14. package/dist/index.native.js +132 -46
  15. package/dist/native/api/login.d.ts +20 -0
  16. package/dist/native/rewards/check-frequency.d.ts +13 -16
  17. package/dist/native/rewards/index.d.ts +3 -1
  18. package/dist/native/rewards/ui/payment-modal.d.ts +1 -0
  19. package/dist/native/rewards/ui/unlogin-modal.d.ts +1 -0
  20. package/dist/native/rewards/ui/use-modal.d.ts +1 -0
  21. package/dist/native/rewards/ui/utils.d.ts +6 -0
  22. package/implement.build.log +2 -2
  23. package/package.json +5 -5
  24. package/src/common/rewards/fetch-reward.ts +6 -3
  25. package/src/common/rewards/registers/use-jolicoin-only.ts +13 -13
  26. package/src/common/rewards/registers/use-jolicoin.ts +15 -11
  27. package/src/common/rewards/registers/utils/coins/commands/index.ts +3 -0
  28. package/src/common/rewards/registers/utils/coins/commands/use-jolicoin.ts +67 -0
  29. package/src/common/rewards/registers/utils/coins/commands/use-payment.ts +85 -0
  30. package/src/common/rewards/registers/utils/coins/commands/use-unlogin.ts +96 -0
  31. package/src/common/rewards/registers/utils/coins/fetch-balance.ts +15 -0
  32. package/src/common/rewards/registers/utils/coins/index.ts +45 -99
  33. package/src/common/rewards/registers/utils/coins/rewards-command.ts +3 -0
  34. package/src/common/rewards/registers/utils/common.ts +8 -0
  35. package/src/common/rewards/registers/utils/event-listener.ts +13 -0
  36. package/src/common/rewards/reward-emitter.ts +33 -4
  37. package/src/common/rewards/reward-helper.ts +3 -3
  38. package/src/common/utils/index.ts +20 -0
  39. package/src/h5/bootstrap/index.ts +20 -2
  40. package/src/h5/rewards/index.ts +29 -1
  41. package/src/native/api/ads.ts +17 -7
  42. package/src/native/api/login.ts +62 -32
  43. package/src/native/rewards/check-frequency.ts +46 -84
  44. package/src/native/rewards/index.ts +3 -370
  45. package/src/native/rewards/ui/payment-modal.ts +254 -0
  46. package/src/native/rewards/ui/unlogin-modal.ts +121 -0
  47. package/src/native/rewards/ui/use-modal.ts +104 -0
  48. package/src/native/rewards/ui/utils.ts +25 -0
@@ -12,97 +12,59 @@ const parseFrequency = (data: string) => {
12
12
  return fequeycies;
13
13
  };
14
14
 
15
- /**
16
- * check can show useModal
17
- * @param config
18
- * @returns
19
- */
20
- export const checkUseModalFrequency = async (config: { dailyMaxPopUps: number; minInterval: number }) => {
21
- const { dailyMaxPopUps, minInterval } = config;
22
- const res = (await getGlobalStorage('joli_coin_use_modal_frequency')) as StandardResponse<string>;
23
- console.log('checkUseModalFrequency', res.data);
24
- if (!res.data) {
25
- return {
26
- canShow: true,
27
- isFirst: true
28
- };
29
- }
30
-
31
- const fequeycies = parseFrequency(res.data);
32
- const todayFequencies = filterTodayTimestamps(fequeycies);
33
- if (todayFequencies.length >= dailyMaxPopUps) {
34
- return {
35
- canShow: false,
36
- isFirst: false
37
- };
38
- }
39
- const now = Date.now();
40
- if (now - todayFequencies[todayFequencies.length - 1] < minInterval) {
41
- return {
42
- canShow: false,
43
- isFirst: false
44
- };
45
- }
46
- return {
47
- canShow: true,
48
- isFirst: false
49
- };
50
- };
15
+ // common get frequency
16
+ function createFrequencyChecker(storageKey: string) {
17
+ return async (config: { dailyMaxPopUps?: number; minInterval?: number }) => {
18
+ const { dailyMaxPopUps, minInterval } = config;
19
+ const res = (await getGlobalStorage(storageKey)) as StandardResponse<string>;
51
20
 
52
- export const updateUseModalFrequency = async () => {
53
- const now = Date.now();
54
- const res = (await getGlobalStorage('joli_coin_use_modal_frequency')) as StandardResponse<string>;
21
+ if (!res.data) {
22
+ return {
23
+ canShow: true,
24
+ isFirst: true
25
+ };
26
+ }
27
+ const frequencies = parseFrequency(res.data);
28
+ const todayFrequencies = filterTodayTimestamps(frequencies);
29
+ if (dailyMaxPopUps && todayFrequencies.length >= dailyMaxPopUps) {
30
+ return {
31
+ canShow: false,
32
+ isFirst: false
33
+ };
34
+ }
55
35
 
56
- const frequencies = parseFrequency(res.data ?? '[]') as number[];
57
- frequencies.push(now);
58
- frequencies.sort((a, b) => b - a).splice(8);
36
+ const now = Date.now();
37
+ console.log('todayFrequencies', todayFrequencies, minInterval, now - todayFrequencies[0]);
59
38
 
60
- await setGlobalStorage('joli_coin_use_modal_frequency', JSON.stringify(frequencies));
61
- };
62
-
63
- /**
64
- * check can show paymentModal
65
- */
66
- export const checkPaymentFrequency = async (config: { dailyMaxPopUps: number; minInterval: number }) => {
67
- const { dailyMaxPopUps, minInterval } = config;
68
- const res = (await getGlobalStorage('joli_coin_payment_frequency')) as StandardResponse<string>;
69
- console.log('checkPaymentFrequency', res.data);
70
- if (!res.data) {
39
+ if (minInterval && now - (todayFrequencies?.[0] ?? 0) < minInterval) {
40
+ return {
41
+ canShow: false,
42
+ isFirst: false
43
+ };
44
+ }
71
45
  return {
72
46
  canShow: true,
73
- isFirst: true
74
- };
75
- }
76
- const frequencies = parseFrequency(res.data);
77
- const todayFequencies = filterTodayTimestamps(frequencies);
78
- if (todayFequencies.length >= dailyMaxPopUps) {
79
- return {
80
- canShow: false,
81
- isFirst: false
82
- };
83
- }
84
- const now = Date.now();
85
- if (now - todayFequencies[todayFequencies.length - 1] < minInterval) {
86
- return {
87
- canShow: false,
88
47
  isFirst: false
89
48
  };
90
- }
91
- return {
92
- canShow: true,
93
- isFirst: false
94
49
  };
95
- };
50
+ }
96
51
 
97
- /**
98
- * update paymentFrequency
99
- */
100
- export const updatePaymentFrequency = async () => {
101
- const now = Date.now();
102
- const res = (await getGlobalStorage('joli_coin_payment_frequency')) as StandardResponse<string>;
103
- const fequeycies: number[] = parseFrequency(res.data ?? '[]');
52
+ export const checkUseModalFrequency = createFrequencyChecker('joli_coin_use_modal_frequency');
53
+ export const checkPaymentFrequency = createFrequencyChecker('joli_coin_payment_frequency');
54
+ export const checkUnloginModalFrequency = createFrequencyChecker('joli_coin_unlogin_modal_frequency');
104
55
 
105
- fequeycies.push(now);
106
- fequeycies.sort((a, b) => b - a).splice(8);
107
- await setGlobalStorage('joli_coin_payment_frequency', JSON.stringify(fequeycies));
108
- };
56
+ // common update frequency
57
+ function createFrequencyUpdater(storageKey: string) {
58
+ return async () => {
59
+ const now = Date.now();
60
+ const res = (await getGlobalStorage(storageKey)) as StandardResponse<string>;
61
+ const frequencies: number[] = parseFrequency(res.data ?? '[]');
62
+ frequencies.push(now);
63
+ frequencies.sort((a, b) => b - a).splice(8);
64
+ await setGlobalStorage(storageKey, JSON.stringify(frequencies));
65
+ };
66
+ }
67
+
68
+ export const updateUseModalFrequency = createFrequencyUpdater('joli_coin_use_modal_frequency');
69
+ export const updatePaymentFrequency = createFrequencyUpdater('joli_coin_payment_frequency');
70
+ export const updateUnloginModalFrequency = createFrequencyUpdater('joli_coin_unlogin_modal_frequency');
@@ -2,373 +2,6 @@
2
2
  * rewards event handlers
3
3
  */
4
4
 
5
- import {
6
- rewardsEmitter,
7
- UseModalEventName,
8
- IUseModalEvent,
9
- PaymentResultEventName,
10
- UseModalResultEventName,
11
- InvokePaymentEventName,
12
- IInvokePaymentEvent,
13
- IPaymentChoice,
14
- UseModalFrequencyEventName,
15
- IUseModalFrequencyConfig
16
- } from '@/common/rewards/reward-emitter';
17
- import { createConfirmJolicoinModal, createPaymentJolicoinModal, createToast } from '@jolibox/ui';
18
- import { innerFetch as fetch } from '../network';
19
- import { StandardResponse } from '@jolibox/types';
20
- import { context } from '@/common/context';
21
- import { login } from '../api/login';
22
- import { EventType } from '@jolibox/common';
23
-
24
- import { createEventPromiseHandler } from '@/common/rewards/registers/utils/event-listener';
25
- import {
26
- checkUseModalFrequency,
27
- updateUseModalFrequency,
28
- checkPaymentFrequency,
29
- updatePaymentFrequency
30
- } from './check-frequency';
31
- import { paymentHelper } from '../payment';
32
- import { createLoading } from '@jolibox/ui';
33
- import { canIUseNative } from '../api/base';
34
- import { applyNative } from '@jolibox/native-bridge';
35
- import { isUndefinedOrNull } from '@jolibox/common';
36
- import { track } from '../report';
37
-
38
- const modalUseFrequencyConfig = createEventPromiseHandler<
39
- IUseModalFrequencyConfig,
40
- typeof UseModalFrequencyEventName
41
- >(rewardsEmitter, UseModalFrequencyEventName);
42
-
43
- modalUseFrequencyConfig.getData();
44
-
45
- const loading = createLoading();
46
-
47
- /**
48
- * update config
49
- */
50
-
51
- let updateEnableConfigPromise = Promise.resolve();
52
-
53
- /**
54
- * 更新自动扣费配置的函数
55
- * @param enabled 是否启用自动扣费
56
- * @returns Promise 更新操作的Promise
57
- */
58
- const updateAutoDeductConfig = async (enabled: boolean): Promise<void> => {
59
- updateEnableConfigPromise = updateEnableConfigPromise.then(async () => {
60
- await fetch('/api/joli-coin/user-config', {
61
- method: 'POST',
62
- appendHostCookie: true,
63
- data: {
64
- enableAutoDeduct: enabled
65
- }
66
- });
67
- });
68
-
69
- await updateEnableConfigPromise;
70
- };
71
-
72
- /**
73
- * confirm jolicoin modal
74
- */
75
- rewardsEmitter.on(UseModalEventName, async (type: 'JOLI_COIN' | 'ADS-JOLI_COIN', params: IUseModalEvent) => {
76
- if (type === 'ADS-JOLI_COIN') {
77
- //TODO
78
- await loading.show({
79
- duration: 3000
80
- });
81
- const config = await modalUseFrequencyConfig.getData();
82
- const { canShow: canShowUseModal, isFirst: isFirstUseModal } = await checkUseModalFrequency(
83
- config.joliCoinUseAndCharge.useJolicoin
84
- );
85
- console.log('use modal show by frequency', canShowUseModal, isFirstUseModal);
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.
97
- if (!canShowUseModal) {
98
- // confirm by frequency control
99
- rewardsEmitter.emit(UseModalResultEventName, { useModalResult: 'CONFIRM' });
100
- return;
101
- }
102
- }
103
-
104
- track('unlock_popup_show', {
105
- eventType: EventType.View,
106
- targetType: 'game'
107
- });
108
-
109
- const modal = createConfirmJolicoinModal({
110
- data: {
111
- enableAutoDeduct: params.enableAutoDeduct,
112
- userJolicoin: params.userJoliCoin,
113
- joliCoinQuantity: params.joliCoinQuantity
114
- },
115
- buttons: {
116
- confirm: {
117
- text: params.confirmButtonText,
118
- onPress: () => {
119
- track('coin_unlock_click', {
120
- targetType: 'game',
121
- eventType: EventType.Click,
122
- coinConsume: params.joliCoinQuantity,
123
- ifAutoUnlock: params.enableAutoDeduct
124
- });
125
- rewardsEmitter.emit(UseModalResultEventName, { useModalResult: 'CONFIRM' });
126
- modal.destroy();
127
- }
128
- },
129
- cancel: {
130
- text: params.cancelButtonText,
131
- onPress: ({ type }) => {
132
- if (type === 'FAILED') {
133
- track('ad_unlock_click', {
134
- targetType: 'game',
135
- eventType: EventType.Click
136
- });
137
- }
138
- rewardsEmitter.emit(UseModalResultEventName, {
139
- useModalResult: (type ?? '') === 'CANCEL' ? 'CANCEL' : 'FAILED'
140
- });
141
- modal.destroy();
142
- }
143
- },
144
- onEnableDeductChanged: async (enabled: boolean) => {
145
- await updateAutoDeductConfig(enabled);
146
- }
147
- }
148
- });
149
-
150
- await updateUseModalFrequency();
151
- });
152
-
153
- /**
154
- * payment jolicoin modal
155
- */
156
- rewardsEmitter.on(
157
- InvokePaymentEventName,
158
- async (type: 'JOLI_COIN' | 'ADS-JOLI_COIN', params: IInvokePaymentEvent) => {
159
- try {
160
- // TODO: temp remove it for dev
161
- if (!canIUseNative('requestPaymentSync:paymentBody:appStoreProductId')) {
162
- //TODO: show Toast
163
- console.info('requestPaymentSync:paymentBody:appStoreProductId not supported');
164
- setTimeout(() => {
165
- rewardsEmitter.emit(PaymentResultEventName, { paymentResult: 'FAILED' });
166
- }, 0);
167
- return;
168
- }
169
- // handle showup frequecy
170
- if (type === 'ADS-JOLI_COIN') {
171
- await loading.show({
172
- duration: 3000
173
- });
174
- const config = await modalUseFrequencyConfig.getData();
175
- const { canShow: canShowPaymentModal } = await checkPaymentFrequency(
176
- config.joliCoinUseAndCharge.charge
177
- );
178
- console.log('use payment show by frequency', canShowPaymentModal);
179
- loading.hide();
180
- if (!canShowPaymentModal) {
181
- // return by frequency control
182
- rewardsEmitter.emit(PaymentResultEventName, { paymentResult: 'SUCCESS' });
183
- return;
184
- }
185
- console.log('show by frequency');
186
- }
187
-
188
- /**
189
- * TODO: need merge totalAmountStr from native
190
- */
191
- await loading.show({
192
- duration: 3000
193
- });
194
- const balenceDetails = await getBalenceDetails();
195
- loading.hide();
196
-
197
- if (!balenceDetails) {
198
- rewardsEmitter.emit(PaymentResultEventName, { paymentResult: 'FAILED' });
199
- return;
200
- }
201
-
202
- track('coinorder_show', {
203
- targetType: 'game',
204
- eventType: EventType.View
205
- });
206
-
207
- const modal = createPaymentJolicoinModal({
208
- data: {
209
- userJolicoin: params.userJoliCoin,
210
- joliCoinQuantity: params.joliCoinQuantity,
211
- paymentChoices:
212
- balenceDetails.paymentChoices?.map((choice) => ({
213
- ...choice,
214
- totalAmountStr: choice.totalAmountStr ?? ''
215
- })) ?? [],
216
- enableAutoDeduct: balenceDetails.enableAutoDeduct
217
- },
218
- buttons: {
219
- confirm: {
220
- text: params.confirmButtonText,
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
- });
231
- if (!context.hostUserInfo?.isLogin) {
232
- const { data } = await login({
233
- skipLogin: true
234
- });
235
- if (!data?.isLogin) {
236
- console.log('login failed');
237
- return;
238
- }
239
-
240
- const balenceDetails = await getBalenceDetails();
241
- if ((balenceDetails?.balance ?? 0) >= params.joliCoinQuantity) {
242
- rewardsEmitter.emit(PaymentResultEventName, { paymentResult: 'SUCCESS' });
243
- modal.destroy();
244
- return;
245
- }
246
- }
247
- console.log('invokeNativePayment', productId);
248
- const appStoreProductId = balenceDetails?.paymentChoices?.find(
249
- (choice) => choice.productId === productId
250
- )?.appStoreProductId;
251
-
252
- if (!appStoreProductId) {
253
- rewardsEmitter.emit(PaymentResultEventName, { paymentResult: 'FAILED' });
254
- modal.destroy();
255
- return;
256
- }
257
- await loading.show({
258
- duration: 3000
259
- });
260
- const { code } = await paymentHelper.invokePayment('JOLI_COIN_IAP', {
261
- productId,
262
- appStoreProductId
263
- });
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
- });
275
- if (code !== 'SUCCESS') {
276
- /** add timeout for google panel closed */
277
- console.info('[JoliboxSDK] payment failed in payment.invokePaymet');
278
- return;
279
- }
280
- rewardsEmitter.emit(PaymentResultEventName, { paymentResult: 'SUCCESS' });
281
- modal.destroy();
282
- }
283
- },
284
- cancel: {
285
- text: params.cancelButtonText,
286
- onPress: ({ type }) => {
287
- rewardsEmitter.emit(PaymentResultEventName, {
288
- paymentResult: (type ?? '') === 'CANCEL' ? 'CANCEL' : 'FAILED'
289
- });
290
- track('ad_unlock_click', {
291
- targetType: 'game',
292
- eventType: EventType.Click
293
- });
294
- modal.destroy();
295
- }
296
- },
297
- onEnableDeductChanged: async (enabled: boolean) => {
298
- await updateAutoDeductConfig(enabled);
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
- });
310
- }
311
- });
312
-
313
- await updatePaymentFrequency();
314
- } catch (error) {
315
- console.info('payment failed', error);
316
- rewardsEmitter.emit(PaymentResultEventName, { paymentResult: 'FAILED' });
317
- }
318
- }
319
- );
320
-
321
- const mergeResponseData = (
322
- responseData: { paymentChoices: IPaymentChoice[] },
323
- data: { [appStoreProductId: string]: { price: string } }
324
- ) => {
325
- Object.keys(data).forEach((key) => {
326
- const choice = responseData.paymentChoices.find((choice) => choice.appStoreProductId === key);
327
- if (choice) {
328
- choice.totalAmountStr = data[key].price;
329
- }
330
- });
331
-
332
- responseData.paymentChoices = responseData.paymentChoices.filter(
333
- (choice) => !isUndefinedOrNull(choice.totalAmountStr)
334
- ) as IPaymentChoice[];
335
- console.info('----mergeResponseData-----', responseData.paymentChoices);
336
- };
337
-
338
- const getBalenceDetails = async (): Promise<
339
- | {
340
- balance: number;
341
- enableAutoDeduct: boolean;
342
- paymentChoices: IPaymentChoice[];
343
- }
344
- | undefined
345
- > => {
346
- const { response } = await fetch<
347
- StandardResponse<{
348
- balance: number;
349
- enableAutoDeduct: boolean;
350
- paymentChoices: IPaymentChoice[];
351
- }>
352
- >('/api/joli-coin/balance-detail', {
353
- method: 'GET',
354
- appendHostCookie: true,
355
- responseType: 'json'
356
- });
357
-
358
- console.info('getBalenceDetails', response);
359
- const { data } = await applyNative('requestProductDetailsAsync', {
360
- appStoreProductIds:
361
- response.data?.data?.paymentChoices
362
- ?.filter((choice) => typeof choice.appStoreProductId === 'string')
363
- .map((choice) => choice.appStoreProductId as string) ?? []
364
- });
365
-
366
- if (response.data?.data && data) {
367
- mergeResponseData(response.data?.data, data);
368
- }
369
- console.info('productDetails', response.data?.data);
370
- if (response.data?.data?.paymentChoices.length === 0) {
371
- throw new Error('paymentChoices is empty');
372
- }
373
- return response.data?.data;
374
- };
5
+ import './ui/use-modal';
6
+ import './ui/payment-modal';
7
+ import './ui/unlogin-modal';