@jolibox/implement 1.1.56 → 1.2.1

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 (61) hide show
  1. package/.rush/temp/package-deps_build.json +35 -28
  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 +9 -9
  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 +148 -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 +130 -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/api/ads.ts +3 -0
  49. package/src/h5/rewards/index.ts +33 -20
  50. package/src/native/api/ads.ts +69 -1
  51. package/src/native/api/call-host-method.ts +36 -1
  52. package/src/native/bootstrap/index.ts +11 -7
  53. package/src/native/payment/index.ts +2 -0
  54. package/src/native/payment/payment-helper.ts +2 -1
  55. package/src/native/rewards/check-frequency.ts +10 -0
  56. package/src/native/rewards/ui/payment-modal.ts +115 -34
  57. package/src/native/rewards/ui/unlogin-modal.ts +182 -87
  58. package/src/native/rewards/ui/use-modal.ts +129 -68
  59. package/src/native/rewards/ui/utils.ts +2 -2
  60. /package/dist/common/rewards/registers/utils/coins/{fetch-balance.d.ts → jolicoin/fetch-balance.d.ts} +0 -0
  61. /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,130 @@
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
+
19
+ interface IGemUnlockRes {
20
+ code: 'SUCCESS' | 'BALANCE_NOT_ENOUGH' | 'EPISODE_LOCK_JUMP' | 'EPISODE_UNLOCK_ALREADY';
21
+ message: string;
22
+ data: {
23
+ transactionId: string;
24
+ quantity: number;
25
+ balance: number;
26
+ };
27
+ }
28
+
29
+ export const createCommonGemRewardHandler = (
30
+ type: 'JOLI_GEM' | 'ADS-JOLI_GEM',
31
+ httpClient: IHttpClient,
32
+ {
33
+ handlers: {
34
+ handleUnlockSuccess,
35
+ handleUnlockFailed,
36
+ unlockOptionsHandler,
37
+ initiateAndAwaitPayment,
38
+ showUnlockWithCurrencyModal,
39
+ showUnloginModal
40
+ }
41
+ }: {
42
+ handlers: {
43
+ handleUnlockSuccess?: (data: { quantity: number; balance: number }) => void;
44
+ handleUnlockFailed?: (params: IAdBreakParams) => void;
45
+ unlockOptionsHandler: EventPromiseHandler<IUnlockOptionsEvent, typeof UnlockOptionsEventName>;
46
+ initiateAndAwaitPayment: ReturnType<typeof createInitiateAndAwaitPayment>;
47
+ showUnlockWithCurrencyModal: ReturnType<typeof createShowUnlockWithCurrencyModal>;
48
+ showUnloginModal: ReturnType<typeof createShowUnloginModal>;
49
+ };
50
+ }
51
+ ) => {
52
+ // register commands
53
+ registerUseUnloginCommand(type, 'JOLI_GEM', {
54
+ httpClient: httpClient,
55
+ showUnloginModal: showUnloginModal
56
+ });
57
+ registerUsePaymentCommand(type, 'JOLI_GEM', {
58
+ httpClient: httpClient,
59
+ initiateAndAwaitPayment: initiateAndAwaitPayment
60
+ });
61
+ registerUseJolicoinCommand(type, 'JOLI_GEM', {
62
+ showUnlockWithCurrencyModal: showUnlockWithCurrencyModal
63
+ });
64
+
65
+ const commands = [`Rewards.${type}.usePayment`, `Rewards.${type}.useJolicoin`];
66
+
67
+ return async (params: IAdBreakParams) => {
68
+ try {
69
+ let result = true;
70
+ for (const command of commands) {
71
+ const commandResult = await rewardsCommands.executeCommand(command as RewardsCommandType);
72
+ result = result && commandResult.result !== 'FAILED';
73
+ if (commandResult.result !== 'CONTINUE') {
74
+ break;
75
+ }
76
+ }
77
+
78
+ if (!result) {
79
+ handleUnlockFailed?.(params);
80
+ return false;
81
+ }
82
+
83
+ const config = CURRENCY_CONFIG['GEM'];
84
+ const unlockWithGem = await httpClient.post<IGemUnlockRes>(config.unlockEndpoint, {
85
+ data: {
86
+ type: 'GAME_REWARD',
87
+ reqId: `${uuidv4()}-${context.mpType}-${Date.now()}`,
88
+ gameInfo: {
89
+ gameId: context.mpId
90
+ }
91
+ }
92
+ });
93
+
94
+ console.log('-----unlockWithGem request result-----', unlockWithGem);
95
+ if (unlockWithGem.code == 'SUCCESS') {
96
+ try {
97
+ params.adBreakDone?.({
98
+ breakType: params.type,
99
+ breakName: 'name' in params ? params.name ?? '' : '',
100
+ breakFormat: 'reward',
101
+ breakStatus: 'viewed'
102
+ });
103
+ if ('adViewed' in params) {
104
+ params.adViewed?.();
105
+ }
106
+ } catch (e) {
107
+ console.error('-----unlockWithGem adBreakDone error-----', e);
108
+ }
109
+
110
+ handleUnlockSuccess?.({
111
+ quantity: unlockWithGem.data.quantity,
112
+ balance: unlockWithGem.data.balance
113
+ });
114
+ return true;
115
+ }
116
+ handleUnlockFailed?.(params);
117
+ return false;
118
+ } catch (e) {
119
+ console.info(`GemRewardHandler error:`, e);
120
+ if (e instanceof Error && e.message == 'CANCEL') {
121
+ // Cancel should terminate the reward handler, invoke unlock failed
122
+ throw e;
123
+ }
124
+ handleUnlockFailed?.(params);
125
+ return false;
126
+ } finally {
127
+ unlockOptionsHandler.clearCache();
128
+ }
129
+ };
130
+ };
@@ -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
  }
package/src/h5/api/ads.ts CHANGED
@@ -131,6 +131,9 @@ const handleUnlockSuccess = (params: { quantity: number; balance: number }) => {
131
131
  notifyCustomEvent('JOLIBOX_CUSTOM_REWARDS_EVENT', {
132
132
  JOLI_COIN: params
133
133
  });
134
+ track('jolicoin_unlock_success', {
135
+ quantity: params.quantity
136
+ });
134
137
  };
135
138
 
136
139
  const adsManager = new H5AdsManager(adsContext);
@@ -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
 
@@ -96,6 +98,9 @@ rewardsHelper.registerRewardHandler(
96
98
  createJolicoinRewardHandler(httpClient, {
97
99
  onUnlockSuccess: (params) => {
98
100
  showUnlockSuccessToast(params);
101
+ track('jolicoin_unlock_success', {
102
+ quantity: params.quantity
103
+ });
99
104
  },
100
105
  onUnlockFailed: () => {
101
106
  console.log('onUnlockFailed');
@@ -108,6 +113,10 @@ rewardsHelper.registerRewardHandler(
108
113
  createJolicoinOnlyRewardHandler(httpClient, {
109
114
  onUnlockSuccess: (params) => {
110
115
  showUnlockSuccessToast(params);
116
+ track('jolicoin_unlock_success', {
117
+ quantity: params.quantity,
118
+ isOnly: true
119
+ });
111
120
  },
112
121
  onUnlockFailed: () => {
113
122
  console.log('onUnlockFailed');
@@ -115,6 +124,32 @@ rewardsHelper.registerRewardHandler(
115
124
  }) as unknown as (params?: unknown) => Promise<boolean>
116
125
  );
117
126
 
127
+ // gem
128
+ rewardsHelper.registerRewardHandler(
129
+ 'JOLI_GEM',
130
+ createGemRewardHandler(httpClient, {
131
+ onUnlockSuccess: (params) => {
132
+ showGemSuccessToast(params);
133
+ track('gem_unlock_success', {
134
+ quantity: params.quantity
135
+ });
136
+ }
137
+ }) as unknown as (params?: unknown) => Promise<boolean>
138
+ );
139
+
140
+ rewardsHelper.registerRewardHandler(
141
+ 'JOLI_GEM_ONLY',
142
+ createGemOnlyRewardHandler(httpClient, {
143
+ onUnlockSuccess: (params) => {
144
+ showGemSuccessToast(params);
145
+ track('gem_unlock_success', {
146
+ quantity: params.quantity,
147
+ isOnly: true
148
+ });
149
+ }
150
+ }) as unknown as (params?: unknown) => Promise<boolean>
151
+ );
152
+
118
153
  const showUnlockSuccessToast = (params: { quantity: number; balance: number }) => {
119
154
  const { quantity } = params;
120
155
  const toastTemplate = `{slot-coin} ${quantity} {slot-i18n-jolicoin.coinUsed}`;
@@ -122,6 +157,9 @@ const showUnlockSuccessToast = (params: { quantity: number; balance: number }) =
122
157
  customStyle: {
123
158
  mark: {
124
159
  marginRight: '8px'
160
+ },
161
+ base: {
162
+ with: 'auto'
125
163
  }
126
164
  },
127
165
  i18nParams: {
@@ -130,6 +168,36 @@ const showUnlockSuccessToast = (params: { quantity: number; balance: number }) =
130
168
  });
131
169
  };
132
170
 
171
+ export const showGemSuccessToast = (params: { quantity: number; balance: number }) => {
172
+ const { quantity } = params;
173
+ const toastTemplate = `{slot-correct} ${quantity * -1} {slot-gem}`;
174
+ createToast(toastTemplate, {
175
+ customStyle: {
176
+ mark: {
177
+ marginRight: '8px'
178
+ },
179
+ base: {
180
+ 'font-size': '25px',
181
+ 'font-weight': '700',
182
+ 'line-height': '18px'
183
+ },
184
+ span: {
185
+ width: 'auto',
186
+ minWidth: 'fit-content',
187
+ maxWidth: '60px',
188
+ textAlign: 'center',
189
+ padding: '0 2px',
190
+ lineHeight: '25px'
191
+ },
192
+ gem: {
193
+ transform: 'translateY(-2px)',
194
+ width: '28px',
195
+ height: '28px'
196
+ }
197
+ }
198
+ });
199
+ };
200
+
133
201
  const adInit = createSyncAPI('adInit', {
134
202
  implement: (config?: IAdsInitParams) => {
135
203
  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');