@jolibox/implement 1.1.55 → 1.2.0-beta.9

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 (60) hide show
  1. package/.rush/temp/package-deps_build.json +34 -27
  2. package/dist/common/rewards/index.d.ts +2 -0
  3. package/dist/common/rewards/registers/use-gem-only.d.ts +10 -0
  4. package/dist/common/rewards/registers/use-gem.d.ts +10 -0
  5. package/dist/common/rewards/registers/utils/coins/commands/currency-handlers.d.ts +15 -0
  6. package/dist/common/rewards/registers/utils/coins/commands/index.d.ts +1 -1
  7. package/dist/common/rewards/registers/utils/coins/commands/use-jolicoin.d.ts +10 -8
  8. package/dist/common/rewards/registers/utils/coins/commands/use-payment.d.ts +10 -8
  9. package/dist/common/rewards/registers/utils/coins/commands/use-unlogin.d.ts +6 -8
  10. package/dist/common/rewards/registers/utils/coins/currency-config.d.ts +8 -0
  11. package/dist/common/rewards/registers/utils/coins/index.d.ts +2 -18
  12. package/dist/common/rewards/registers/utils/coins/jolicoin/jolicoin-handler.d.ts +18 -0
  13. package/dist/common/rewards/registers/utils/coins/joligem/fetch-gem-balance.d.ts +4 -0
  14. package/dist/common/rewards/registers/utils/coins/joligem/gem-handler.d.ts +19 -0
  15. package/dist/common/rewards/registers/utils/index.d.ts +3 -1
  16. package/dist/common/rewards/reward-emitter.d.ts +23 -13
  17. package/dist/common/rewards/reward-helper.d.ts +3 -1
  18. package/dist/common/rewards/type.d.ts +10 -1
  19. package/dist/index.js +25 -25
  20. package/dist/index.native.js +68 -53
  21. package/dist/native/api/ads.d.ts +4 -0
  22. package/dist/native/payment/payment-helper.d.ts +5 -1
  23. package/dist/native/rewards/check-frequency.d.ts +24 -0
  24. package/dist/native/rewards/ui/utils.d.ts +1 -1
  25. package/implement.build.log +2 -2
  26. package/package.json +5 -5
  27. package/src/common/rewards/__tests__/can-use-jolicoin.test.ts +265 -9
  28. package/src/common/rewards/fetch-reward.ts +18 -3
  29. package/src/common/rewards/index.ts +2 -0
  30. package/src/common/rewards/registers/use-gem-only.ts +58 -0
  31. package/src/common/rewards/registers/use-gem.ts +53 -0
  32. package/src/common/rewards/registers/use-jolicoin-only.ts +4 -4
  33. package/src/common/rewards/registers/use-jolicoin.ts +4 -4
  34. package/src/common/rewards/registers/utils/coins/commands/currency-handlers.ts +50 -0
  35. package/src/common/rewards/registers/utils/coins/commands/index.ts +1 -1
  36. package/src/common/rewards/registers/utils/coins/commands/use-jolicoin.ts +31 -19
  37. package/src/common/rewards/registers/utils/coins/commands/use-payment.ts +32 -25
  38. package/src/common/rewards/registers/utils/coins/commands/use-unlogin.ts +22 -24
  39. package/src/common/rewards/registers/utils/coins/currency-config.ts +23 -0
  40. package/src/common/rewards/registers/utils/coins/index.ts +2 -139
  41. package/src/common/rewards/registers/utils/coins/jolicoin/jolicoin-handler.ts +152 -0
  42. package/src/common/rewards/registers/utils/coins/joligem/fetch-gem-balance.ts +15 -0
  43. package/src/common/rewards/registers/utils/coins/joligem/gem-handler.ts +134 -0
  44. package/src/common/rewards/registers/utils/index.ts +20 -1
  45. package/src/common/rewards/reward-emitter.ts +23 -13
  46. package/src/common/rewards/reward-helper.ts +3 -1
  47. package/src/common/rewards/type.ts +13 -1
  48. package/src/h5/rewards/index.ts +33 -20
  49. package/src/native/api/ads.ts +55 -1
  50. package/src/native/api/call-host-method.ts +36 -1
  51. package/src/native/bootstrap/index.ts +11 -7
  52. package/src/native/payment/index.ts +2 -0
  53. package/src/native/payment/payment-helper.ts +2 -1
  54. package/src/native/rewards/check-frequency.ts +10 -0
  55. package/src/native/rewards/ui/payment-modal.ts +115 -34
  56. package/src/native/rewards/ui/unlogin-modal.ts +182 -87
  57. package/src/native/rewards/ui/use-modal.ts +129 -68
  58. package/src/native/rewards/ui/utils.ts +2 -2
  59. /package/dist/common/rewards/registers/utils/coins/{fetch-balance.d.ts → jolicoin/fetch-balance.d.ts} +0 -0
  60. /package/src/common/rewards/registers/utils/coins/{fetch-balance.ts → jolicoin/fetch-balance.ts} +0 -0
@@ -0,0 +1,15 @@
1
+ import { IHttpClient } from '@/common/http';
2
+ import { StandardResponse } from '@jolibox/types';
3
+
4
+ export const fetchGemBalance = async (httpClient: IHttpClient) => {
5
+ const res = await httpClient.get<
6
+ StandardResponse<{
7
+ balance: number;
8
+ }>
9
+ >('/api/joli-gem/balance', {
10
+ query: {
11
+ type: 'GEM'
12
+ }
13
+ });
14
+ return res.data;
15
+ };
@@ -0,0 +1,134 @@
1
+ import { IHttpClient } from '@/common/http';
2
+ import { context } from '@/common/context';
3
+ import { uuidv4 } from '@jolibox/common';
4
+ import { UnlockOptionsEventName, IUnlockOptionsEvent } from '@/common/rewards/reward-emitter';
5
+ import { IAdBreakParams } from '@/common/ads';
6
+ import { EventPromiseHandler } from '../../event-listener';
7
+ import { CURRENCY_CONFIG } from '../currency-config';
8
+
9
+ import {
10
+ createInitiateAndAwaitPayment,
11
+ registerUsePaymentCommand,
12
+ registerUseUnloginCommand,
13
+ createShowUnloginModal
14
+ } from '../commands';
15
+ import { registerUseJolicoinCommand, createShowUnlockWithCurrencyModal } from '../commands/use-jolicoin';
16
+ import { rewardsCommands } from '../rewards-command';
17
+ import { RewardsCommandType } from '@jolibox/types';
18
+ import { track } from '@/native/report';
19
+
20
+ interface IGemUnlockRes {
21
+ code: 'SUCCESS' | 'BALANCE_NOT_ENOUGH' | 'EPISODE_LOCK_JUMP' | 'EPISODE_UNLOCK_ALREADY';
22
+ message: string;
23
+ data: {
24
+ transactionId: string;
25
+ quantity: number;
26
+ balance: number;
27
+ };
28
+ }
29
+
30
+ export const createCommonGemRewardHandler = (
31
+ type: 'JOLI_GEM' | 'ADS-JOLI_GEM',
32
+ httpClient: IHttpClient,
33
+ {
34
+ handlers: {
35
+ handleUnlockSuccess,
36
+ handleUnlockFailed,
37
+ unlockOptionsHandler,
38
+ initiateAndAwaitPayment,
39
+ showUnlockWithCurrencyModal,
40
+ showUnloginModal
41
+ }
42
+ }: {
43
+ handlers: {
44
+ handleUnlockSuccess?: (data: { quantity: number; balance: number }) => void;
45
+ handleUnlockFailed?: (params: IAdBreakParams) => void;
46
+ unlockOptionsHandler: EventPromiseHandler<IUnlockOptionsEvent, typeof UnlockOptionsEventName>;
47
+ initiateAndAwaitPayment: ReturnType<typeof createInitiateAndAwaitPayment>;
48
+ showUnlockWithCurrencyModal: ReturnType<typeof createShowUnlockWithCurrencyModal>;
49
+ showUnloginModal: ReturnType<typeof createShowUnloginModal>;
50
+ };
51
+ }
52
+ ) => {
53
+ // register commands
54
+ registerUseUnloginCommand(type, 'JOLI_GEM', {
55
+ httpClient: httpClient,
56
+ showUnloginModal: showUnloginModal
57
+ });
58
+ registerUsePaymentCommand(type, 'JOLI_GEM', {
59
+ httpClient: httpClient,
60
+ initiateAndAwaitPayment: initiateAndAwaitPayment
61
+ });
62
+ registerUseJolicoinCommand(type, 'JOLI_GEM', {
63
+ showUnlockWithCurrencyModal: showUnlockWithCurrencyModal
64
+ });
65
+
66
+ const commands = [`Rewards.${type}.usePayment`, `Rewards.${type}.useJolicoin`];
67
+
68
+ return async (params: IAdBreakParams) => {
69
+ try {
70
+ let result = true;
71
+ for (const command of commands) {
72
+ const commandResult = await rewardsCommands.executeCommand(command as RewardsCommandType);
73
+ result = result && commandResult.result !== 'FAILED';
74
+ if (commandResult.result !== 'CONTINUE') {
75
+ break;
76
+ }
77
+ }
78
+
79
+ if (!result) {
80
+ handleUnlockFailed?.(params);
81
+ return false;
82
+ }
83
+
84
+ const config = CURRENCY_CONFIG['GEM'];
85
+ const unlockWithGem = await httpClient.post<IGemUnlockRes>(config.unlockEndpoint, {
86
+ data: {
87
+ type: 'GAME_REWARD',
88
+ reqId: `${uuidv4()}-${context.mpType}-${Date.now()}`,
89
+ gameInfo: {
90
+ gameId: context.mpId
91
+ }
92
+ }
93
+ });
94
+
95
+ console.log('-----unlockWithGem request result-----', unlockWithGem);
96
+ if (unlockWithGem.code == 'SUCCESS') {
97
+ try {
98
+ params.adBreakDone?.({
99
+ breakType: params.type,
100
+ breakName: 'name' in params ? params.name ?? '' : '',
101
+ breakFormat: 'reward',
102
+ breakStatus: 'viewed'
103
+ });
104
+ if ('adViewed' in params) {
105
+ params.adViewed?.();
106
+ }
107
+ track('gem_unlock_success', {
108
+ quantity: unlockWithGem.data.quantity
109
+ });
110
+ } catch (e) {
111
+ console.error('-----unlockWithGem adBreakDone error-----', e);
112
+ }
113
+
114
+ handleUnlockSuccess?.({
115
+ quantity: unlockWithGem.data.quantity,
116
+ balance: unlockWithGem.data.balance
117
+ });
118
+ return true;
119
+ }
120
+ handleUnlockFailed?.(params);
121
+ return false;
122
+ } catch (e) {
123
+ console.info(`GemRewardHandler error:`, e);
124
+ if (e instanceof Error && e.message == 'CANCEL') {
125
+ // Cancel should terminate the reward handler, invoke unlock failed
126
+ throw e;
127
+ }
128
+ handleUnlockFailed?.(params);
129
+ return false;
130
+ } finally {
131
+ unlockOptionsHandler.clearCache();
132
+ }
133
+ };
134
+ };
@@ -1,4 +1,5 @@
1
- import { IJoliCoin, IUnlockOption } from '@/common/rewards/type';
1
+ import { IJoliCoin, IGem, IUnlockOption } from '@/common/rewards/type';
2
+ import { isNumber } from '@jolibox/common';
2
3
 
3
4
  export const canUseJolicoin = (unlockOptions: IUnlockOption[], joliCoin?: IJoliCoin) => {
4
5
  return unlockOptions.some(
@@ -17,3 +18,21 @@ export const joliCoinIsEnough = (unlockOptions: IUnlockOption[], joliCoin?: IJol
17
18
  option.joliCoinChoices.some((choice) => choice.joliCoinQuantity <= (joliCoin?.balance ?? 0))
18
19
  );
19
20
  };
21
+
22
+ // Gem utility functions
23
+ export const canUseGem = (unlockOptions: IUnlockOption[], gem?: IGem) => {
24
+ return unlockOptions.some((option) => {
25
+ if (option.type === 'JOLI_GEM' && isNumber(option.joliGemChoice?.joliGemQuantity)) {
26
+ return option.joliGemChoice.joliGemQuantity <= (gem?.balance ?? 0) && !!gem?.enableAutoDeduct;
27
+ }
28
+ return false;
29
+ });
30
+ };
31
+
32
+ export const gemIsEnough = (unlockOptions: IUnlockOption[], gem?: IGem) => {
33
+ const gemOptions = unlockOptions.find((option) => option.type === 'JOLI_GEM');
34
+ if (gemOptions) {
35
+ return (gemOptions.joliGemChoice?.joliGemQuantity ?? 0) <= (gem?.balance ?? 0);
36
+ }
37
+ return false;
38
+ };
@@ -1,12 +1,12 @@
1
1
  // rewards-emitter-wrapper.ts
2
2
 
3
3
  import { EventEmitter } from '@jolibox/common';
4
- import { IUnlockOption } from './type';
5
- import { IJoliCoin } from './type';
4
+ import { IUnlockOption, IJoliCoin, IGem } from './type';
6
5
 
7
6
  export interface IUnlockOptionsEvent {
8
7
  options: IUnlockOption[];
9
8
  userJoliCoin: IJoliCoin;
9
+ userGem?: IGem;
10
10
  }
11
11
 
12
12
  export const UnlockOptionsEventName = 'UNLOCK_OPTIONS_CHANGED' as const;
@@ -21,6 +21,8 @@ export const InvokeUnloginModalEventName = 'INVOKE_UNLOGIN_MODAL_EVENT' as const
21
21
  type IPaymentResult = 'SUCCESS' | 'FAILED' | 'CANCEL';
22
22
  export interface IPaymentEvent {
23
23
  userJoliCoin?: IJoliCoin;
24
+ userGem?: IGem;
25
+ currency: 'JOLI_COIN' | 'JOLI_GEM';
24
26
  paymentResult: IPaymentResult;
25
27
  }
26
28
 
@@ -32,8 +34,9 @@ export interface IPaymentChoice {
32
34
  }
33
35
 
34
36
  export interface IInvokePaymentEvent {
35
- userJoliCoin: IJoliCoin;
36
- joliCoinQuantity: number;
37
+ userCurrency: IJoliCoin | IGem;
38
+ quantity: number;
39
+ currency: 'JOLI_COIN' | 'JOLI_GEM';
37
40
  enableAutoDeduct: boolean;
38
41
  confirmButtonText: string;
39
42
  cancelButtonText: string;
@@ -42,8 +45,9 @@ export interface IInvokePaymentEvent {
42
45
 
43
46
  export interface IUseModalEvent {
44
47
  enableAutoDeduct: boolean;
45
- userJoliCoin: IJoliCoin;
46
- joliCoinQuantity: number;
48
+ userCurrency: IJoliCoin | IGem;
49
+ quantity: number;
50
+ currency: 'JOLI_COIN' | 'JOLI_GEM';
47
51
  confirmButtonText: string;
48
52
  cancelButtonText: string;
49
53
  sequenceId?: string;
@@ -52,6 +56,7 @@ export interface IUseModalEvent {
52
56
  export interface IUseUnloginModalEvent {
53
57
  confirmButtonText: string;
54
58
  cancelButtonText: string;
59
+ currency: 'JOLI_COIN' | 'JOLI_GEM';
55
60
  }
56
61
 
57
62
  export interface IUseModalResultEvent {
@@ -61,10 +66,9 @@ export interface IUseModalResultEvent {
61
66
  export interface IUseUnloginModalResultEvent {
62
67
  result: 'SUCCESS' | 'CANCEL' | 'ADS' | 'FAILED' | 'NOT_SUPPORT';
63
68
  rewards?: {
64
- jolicoin?: {
65
- claimedRewardValue: number;
66
- isFirstLogin: boolean;
67
- };
69
+ claimedRewardValue: number;
70
+ isFirstLogin: boolean;
71
+ currency?: 'JOLI_COIN' | 'JOLI_GEM';
68
72
  };
69
73
  }
70
74
 
@@ -88,12 +92,18 @@ export interface IUseModalFrequencyConfig {
88
92
 
89
93
  export interface RewardsEventMap extends Record<string, unknown[]> {
90
94
  [UnlockOptionsEventName]: [IUnlockOptionsEvent];
91
- [InvokePaymentEventName]: ['JOLI_COIN' | 'ADS-JOLI_COIN', IInvokePaymentEvent];
95
+ [InvokePaymentEventName]: [
96
+ 'JOLI_COIN' | 'ADS-JOLI_COIN' | 'JOLI_GEM' | 'ADS-JOLI_GEM',
97
+ IInvokePaymentEvent
98
+ ];
92
99
  [PaymentResultEventName]: [IPaymentEvent];
93
100
  [UseModalResultEventName]: [IUseModalResultEvent];
94
- [UseModalEventName]: ['JOLI_COIN' | 'ADS-JOLI_COIN', IUseModalEvent];
101
+ [UseModalEventName]: ['JOLI_COIN' | 'ADS-JOLI_COIN' | 'JOLI_GEM' | 'ADS-JOLI_GEM', IUseModalEvent];
95
102
  [UseModalFrequencyEventName]: [IUseModalFrequencyConfig];
96
- [InvokeUnloginModalEventName]: ['JOLI_COIN' | 'ADS-JOLI_COIN', IUseUnloginModalEvent];
103
+ [InvokeUnloginModalEventName]: [
104
+ 'JOLI_COIN' | 'ADS-JOLI_COIN' | 'JOLI_GEM' | 'ADS-JOLI_GEM',
105
+ IUseUnloginModalEvent
106
+ ];
97
107
  [UseUnloginModalResultEventName]: [IUseUnloginModalResultEvent];
98
108
  }
99
109
 
@@ -1,4 +1,4 @@
1
- export type RewardType = 'ADS' | 'JOLI_COIN' | 'JOLI_COIN_ONLY';
1
+ export type RewardType = 'ADS' | 'JOLI_COIN' | 'JOLI_COIN_ONLY' | 'JOLI_GEM' | 'JOLI_GEM_ONLY';
2
2
 
3
3
  import { context } from '../context';
4
4
  import type { AdsRewardsHandler } from './registers/use-ads';
@@ -8,6 +8,8 @@ export interface RewardHandlerMap {
8
8
  ADS: AdsRewardsHandler;
9
9
  JOLI_COIN: (params?: unknown) => Promise<boolean>; // coins + ads
10
10
  JOLI_COIN_ONLY: (params?: unknown) => Promise<boolean>; // coins only
11
+ JOLI_GEM: (params?: unknown) => Promise<boolean>; // gem + ads
12
+ JOLI_GEM_ONLY: (params?: unknown) => Promise<boolean>; // gem only
11
13
  }
12
14
 
13
15
  export type RewardHandler<T extends RewardType> = RewardHandlerMap[T];
@@ -3,14 +3,25 @@ export interface IJoliCoin {
3
3
  enableAutoDeduct: boolean;
4
4
  }
5
5
 
6
- export type IUnlockOptionType = 'JOLI_COIN' | 'ADS';
6
+ export interface IGem {
7
+ balance: number;
8
+ enableAutoDeduct: boolean;
9
+ }
10
+
11
+ export type IUnlockOptionType = 'JOLI_COIN' | 'ADS' | 'JOLI_GEM';
7
12
 
8
13
  interface IJoliCoinChoice {
9
14
  joliCoinQuantity: number;
10
15
  }
16
+
17
+ interface IGemChoice {
18
+ joliGemQuantity: number;
19
+ }
20
+
11
21
  export interface IUnlockOption {
12
22
  type: IUnlockOptionType;
13
23
  joliCoinChoices: IJoliCoinChoice[];
24
+ joliGemChoice: IGemChoice | null;
14
25
  }
15
26
 
16
27
  export interface IJolicoinRewardOption {
@@ -21,5 +32,6 @@ export interface IJolicoinRewardOption {
21
32
  };
22
33
  extra: {
23
34
  joliCoin: IJoliCoin;
35
+ joliGem?: IGem;
24
36
  };
25
37
  }
@@ -33,17 +33,24 @@ onCustomEvent('ON_JOLIBOX_JOLI_COIN_USE_RESULT', (data) => {
33
33
  useModalResult: UseCoinEventMap[data.result]
34
34
  });
35
35
  });
36
- rewardsEmitter.on(UseModalEventName, (type: 'JOLI_COIN' | 'ADS-JOLI_COIN', params: IUseModalEvent) => {
37
- notifyCustomEvent('JOLIBOX_JOLI_COIN_USE_EVENT', {
38
- JOLI_COIN: {
39
- quantity: params.joliCoinQuantity,
40
- balance: params.userJoliCoin.balance,
41
- enableAutoDeduct: params.enableAutoDeduct
42
- },
43
- type,
44
- sequenceId: params.sequenceId ?? v4()
45
- });
46
- });
36
+ rewardsEmitter.on(
37
+ UseModalEventName,
38
+ (type: 'JOLI_COIN' | 'ADS-JOLI_COIN' | 'JOLI_GEM' | 'ADS-JOLI_GEM', params: IUseModalEvent) => {
39
+ // not support gem in h5
40
+ if (type == 'ADS-JOLI_GEM' || type == 'JOLI_GEM') {
41
+ return;
42
+ }
43
+ notifyCustomEvent('JOLIBOX_JOLI_COIN_USE_EVENT', {
44
+ JOLI_COIN: {
45
+ quantity: params.quantity,
46
+ balance: params.userCurrency.balance,
47
+ enableAutoDeduct: params.enableAutoDeduct
48
+ },
49
+ type: type as 'JOLI_COIN' | 'ADS-JOLI_COIN',
50
+ sequenceId: params.sequenceId ?? v4()
51
+ });
52
+ }
53
+ );
47
54
 
48
55
  /**
49
56
  * payment jolicoin modal
@@ -51,21 +58,26 @@ rewardsEmitter.on(UseModalEventName, (type: 'JOLI_COIN' | 'ADS-JOLI_COIN', param
51
58
  onCustomEvent('ON_JOLIBOX_TOPUP_JOLI_COIN_RESULT', (data) => {
52
59
  rewardsEmitter.emit(PaymentResultEventName, {
53
60
  paymentResult: data.result == 'ADS' ? 'FAILED' : data.result,
54
- userJoliCoin: data.joliCoin
61
+ userJoliCoin: data.joliCoin,
62
+ currency: 'JOLI_COIN' // h5 only support jolicoin, should get currency from data later
55
63
  });
56
64
  });
57
65
 
58
66
  rewardsEmitter.on(
59
67
  InvokePaymentEventName,
60
- async (type: 'JOLI_COIN' | 'ADS-JOLI_COIN', params: IInvokePaymentEvent) => {
68
+ async (type: 'JOLI_COIN' | 'ADS-JOLI_COIN' | 'JOLI_GEM' | 'ADS-JOLI_GEM', params: IInvokePaymentEvent) => {
61
69
  // 充值面板
70
+ if (type == 'ADS-JOLI_GEM' || type == 'JOLI_GEM') {
71
+ return;
72
+ }
73
+
62
74
  notifyCustomEvent('JOLIBOX_TOPUP_EVENT', {
63
75
  JOLI_COIN: {
64
- quantity: params.joliCoinQuantity,
65
- balance: params.userJoliCoin.balance,
76
+ quantity: params.quantity,
77
+ balance: params.userCurrency.balance,
66
78
  enableAutoDeduct: params.enableAutoDeduct
67
79
  },
68
- type,
80
+ type: type as 'JOLI_COIN' | 'ADS-JOLI_COIN',
69
81
  sequenceId: params.sequenceId ?? v4()
70
82
  });
71
83
  }
@@ -76,10 +88,8 @@ onCustomEvent('ON_JOLIBOX_JOLI_UNLOGIN_MODAL_RESULT_EVENT', (data) => {
76
88
  rewardsEmitter.emit(UseUnloginModalResultEventName, {
77
89
  result: data.result == 'ADS' ? 'FAILED' : data.result,
78
90
  rewards: {
79
- jolicoin: {
80
- claimedRewardValue: data.extra?.firstLogin?.reward?.rewardValue ?? 0,
81
- isFirstLogin: data.isFirstLogin ?? false
82
- }
91
+ claimedRewardValue: data.extra?.firstLogin?.reward?.rewardValue ?? 0,
92
+ isFirstLogin: data.isFirstLogin ?? false
83
93
  }
84
94
  });
85
95
 
@@ -90,6 +100,9 @@ onCustomEvent('ON_JOLIBOX_JOLI_UNLOGIN_MODAL_RESULT_EVENT', (data) => {
90
100
 
91
101
  rewardsEmitter.on(InvokeUnloginModalEventName, async (type) => {
92
102
  // 未登录面板
103
+ if (type == 'ADS-JOLI_GEM' || type == 'JOLI_GEM') {
104
+ return;
105
+ }
93
106
  notifyCustomEvent('JOLIBOX_JOLI_UNLOGIN_MODAL_EVENT', {
94
107
  sequenceId: v4(),
95
108
  type: type
@@ -23,7 +23,9 @@ import {
23
23
  rewardsHelper,
24
24
  createAdsRewardHandler,
25
25
  createJolicoinRewardHandler,
26
- createJolicoinOnlyRewardHandler
26
+ createJolicoinOnlyRewardHandler,
27
+ createGemRewardHandler,
28
+ createGemOnlyRewardHandler
27
29
  } from '@/common/rewards';
28
30
  import { adEventEmitter } from '@/common/ads';
29
31
 
@@ -115,6 +117,25 @@ rewardsHelper.registerRewardHandler(
115
117
  }) as unknown as (params?: unknown) => Promise<boolean>
116
118
  );
117
119
 
120
+ // gem
121
+ rewardsHelper.registerRewardHandler(
122
+ 'JOLI_GEM',
123
+ createGemRewardHandler(httpClient, {
124
+ onUnlockSuccess: (params) => {
125
+ showGemSuccessToast(params);
126
+ }
127
+ }) as unknown as (params?: unknown) => Promise<boolean>
128
+ );
129
+
130
+ rewardsHelper.registerRewardHandler(
131
+ 'JOLI_GEM_ONLY',
132
+ createGemOnlyRewardHandler(httpClient, {
133
+ onUnlockSuccess: (params) => {
134
+ showGemSuccessToast(params);
135
+ }
136
+ }) as unknown as (params?: unknown) => Promise<boolean>
137
+ );
138
+
118
139
  const showUnlockSuccessToast = (params: { quantity: number; balance: number }) => {
119
140
  const { quantity } = params;
120
141
  const toastTemplate = `{slot-coin} ${quantity} {slot-i18n-jolicoin.coinUsed}`;
@@ -122,6 +143,9 @@ const showUnlockSuccessToast = (params: { quantity: number; balance: number }) =
122
143
  customStyle: {
123
144
  mark: {
124
145
  marginRight: '8px'
146
+ },
147
+ base: {
148
+ with: 'auto'
125
149
  }
126
150
  },
127
151
  i18nParams: {
@@ -130,6 +154,36 @@ const showUnlockSuccessToast = (params: { quantity: number; balance: number }) =
130
154
  });
131
155
  };
132
156
 
157
+ export const showGemSuccessToast = (params: { quantity: number; balance: number }) => {
158
+ const { quantity } = params;
159
+ const toastTemplate = `{slot-correct} ${quantity * -1} {slot-gem}`;
160
+ createToast(toastTemplate, {
161
+ customStyle: {
162
+ mark: {
163
+ marginRight: '8px'
164
+ },
165
+ base: {
166
+ 'font-size': '25px',
167
+ 'font-weight': '700',
168
+ 'line-height': '18px'
169
+ },
170
+ span: {
171
+ width: 'auto',
172
+ minWidth: 'fit-content',
173
+ maxWidth: '60px',
174
+ textAlign: 'center',
175
+ padding: '0 2px',
176
+ lineHeight: '25px'
177
+ },
178
+ gem: {
179
+ transform: 'translateY(-2px)',
180
+ width: '28px',
181
+ height: '28px'
182
+ }
183
+ }
184
+ });
185
+ };
186
+
133
187
  const adInit = createSyncAPI('adInit', {
134
188
  implement: (config?: IAdsInitParams) => {
135
189
  ads.init(config);
@@ -1,4 +1,4 @@
1
- import { canIUseNative, createAPI, registerCanIUse, t } from './base';
1
+ import { canIUseNative, createAPI, registerCanIUse, t, createSyncAPI } from './base';
2
2
  import { invokeNative } from '@jolibox/native-bridge';
3
3
  import { hostEmitter, UserCustomError } from '@jolibox/common';
4
4
  import { createCommands } from '@jolibox/common';
@@ -95,3 +95,38 @@ commands.registerCommand('API.callHostMethod', callHostMethodAsync);
95
95
  registerCanIUse('callHostMethod', {
96
96
  version: '1.1.49'
97
97
  });
98
+
99
+ //user track
100
+ const userTrackAsync = createAPI('userTrackAsync', {
101
+ paramsSchema: t.tuple(
102
+ t.object({
103
+ event: t.string(),
104
+ eventType: t.number(),
105
+ params: t.object().optional().default({})
106
+ })
107
+ ),
108
+ implement: async ({ event, eventType, params }) => {
109
+ const supportedMethods = await getSupportedMethods();
110
+ if (!supportedMethods.includes('userTrackAsync')) {
111
+ throw new UserCustomError('Method not supported', 10001);
112
+ }
113
+ const { errNo, errMsg } = await invokeNative('trackAsync', {
114
+ event,
115
+ eventType,
116
+ data: {
117
+ ...params
118
+ },
119
+ webviewId: context.webviewId
120
+ });
121
+ if (errNo !== 0) {
122
+ throw new UserCustomError(errMsg, errNo);
123
+ }
124
+ return;
125
+ }
126
+ });
127
+
128
+ commands.registerCommand('API.track', userTrackAsync);
129
+
130
+ registerCanIUse('track', {
131
+ version: '1.1.53'
132
+ });
@@ -218,13 +218,17 @@ function addDoExitLoader() {
218
218
  }
219
219
 
220
220
  async function fetchMetaConfig() {
221
- const url = `${context.baseApiHost}/api/fe-configs/js-sdk/basic-meta`;
222
- const {
223
- response: { data }
224
- } = await innerFetch<IBasicMetaConfig>(url);
225
-
226
- if (data) {
227
- baskcMeta = data;
221
+ try {
222
+ const url = `/api/fe-configs/js-sdk/basic-meta`;
223
+ const {
224
+ response: { data }
225
+ } = await innerFetch<IBasicMetaConfig>(url);
226
+
227
+ if (data) {
228
+ baskcMeta = data;
229
+ }
230
+ } catch (error) {
231
+ console.error('fetchMetaConfig error:', error);
228
232
  }
229
233
  }
230
234
 
@@ -5,3 +5,5 @@ import { createJolicoinIAPPaymentHandler } from './registers/jolicoin-iap';
5
5
  export const paymentHelper = createPaymentHelper();
6
6
  paymentHelper.registerPaymentHandler('JOLI_COIN', createJolicoinPaymentHandler());
7
7
  paymentHelper.registerPaymentHandler('JOLI_COIN_IAP', createJolicoinIAPPaymentHandler());
8
+ // Temporarily reuse the same IAP handler for gem, can be extended later with gem-specific logic
9
+ paymentHelper.registerPaymentHandler('JOLI_GEM_IAP', createJolicoinIAPPaymentHandler());
@@ -1,4 +1,4 @@
1
- export type PaymentType = 'JOLI_COIN' | 'JOLI_COIN_IAP'; // current only jolicoin
1
+ export type PaymentType = 'JOLI_COIN' | 'JOLI_COIN_IAP' | 'JOLI_GEM_IAP'; // support both jolicoin and gem
2
2
 
3
3
  import { StandardResponse } from '@jolibox/types';
4
4
  import { reportError } from '@/common/report/errors/report';
@@ -9,6 +9,7 @@ type PaymentResult = StandardResponse<void>;
9
9
  export interface PaymentHandlerMap {
10
10
  JOLI_COIN: (productId: string) => Promise<PaymentResult>; // jolicoin
11
11
  JOLI_COIN_IAP: (params: { productId: string; appStoreProductId: string }) => Promise<PaymentResult>; // jolicoin iap
12
+ JOLI_GEM_IAP: (params: { productId: string; appStoreProductId: string }) => Promise<PaymentResult>; // gem iap
12
13
  }
13
14
 
14
15
  export type PaymentHandler<T extends PaymentType> = PaymentHandlerMap[T];
@@ -53,6 +53,11 @@ export const checkUseModalFrequency = createFrequencyChecker('joli_coin_use_moda
53
53
  export const checkPaymentFrequency = createFrequencyChecker('joli_coin_payment_frequency');
54
54
  export const checkUnloginModalFrequency = createFrequencyChecker('joli_coin_unlogin_modal_frequency');
55
55
 
56
+ // gem frequency
57
+ export const checkUseModalFrequencyGem = createFrequencyChecker('joli_gem_use_modal_frequency');
58
+ export const checkPaymentFrequencyGem = createFrequencyChecker('joli_gem_payment_frequency');
59
+ export const checkUnloginModalFrequencyGem = createFrequencyChecker('joli_gem_unlogin_modal_frequency');
60
+
56
61
  // common update frequency
57
62
  function createFrequencyUpdater(storageKey: string) {
58
63
  return async () => {
@@ -68,3 +73,8 @@ function createFrequencyUpdater(storageKey: string) {
68
73
  export const updateUseModalFrequency = createFrequencyUpdater('joli_coin_use_modal_frequency');
69
74
  export const updatePaymentFrequency = createFrequencyUpdater('joli_coin_payment_frequency');
70
75
  export const updateUnloginModalFrequency = createFrequencyUpdater('joli_coin_unlogin_modal_frequency');
76
+
77
+ // gem frequency
78
+ export const updateUseModalFrequencyGem = createFrequencyUpdater('joli_gem_use_modal_frequency');
79
+ export const updatePaymentFrequencyGem = createFrequencyUpdater('joli_gem_payment_frequency');
80
+ export const updateUnloginModalFrequencyGem = createFrequencyUpdater('joli_gem_unlogin_modal_frequency');