@1selfworld/adchain-sdk-react-native 1.0.1 → 1.0.3
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/android/build.gradle +2 -1
- package/lib/module/AdchainOfferwallView.js +141 -0
- package/lib/module/AdchainOfferwallView.js.map +1 -0
- package/lib/module/index.js +23 -5
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/AdchainOfferwallView.d.ts +54 -0
- package/lib/typescript/src/AdchainOfferwallView.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +2 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +9 -3
- package/plugin/src/withAdchainConfig.js +1 -1
- package/src/AdchainOfferwallView.tsx +245 -0
- package/src/index.tsx +86 -48
package/android/build.gradle
CHANGED
|
@@ -34,5 +34,6 @@ android {
|
|
|
34
34
|
dependencies {
|
|
35
35
|
implementation 'com.facebook.react:react-native:+'
|
|
36
36
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.9.21"
|
|
37
|
-
|
|
37
|
+
// 로컬 Android SDK 사용 (JitPack 빌드 문제로 인해 임시)
|
|
38
|
+
implementation project(':adchain-sdk')
|
|
38
39
|
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import React, { useEffect, useRef } from 'react';
|
|
4
|
+
import { requireNativeComponent, UIManager, findNodeHandle, Platform } from 'react-native';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Event types for Offerwall callbacks
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Custom event from WebView
|
|
12
|
+
* @since 1.0.41
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Data request from WebView
|
|
17
|
+
* @since 1.0.41
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Props for AdchainOfferwallView component
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Native component interface
|
|
26
|
+
*/
|
|
27
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
28
|
+
// Require native component
|
|
29
|
+
const NativeOfferwallView = requireNativeComponent('AdchainOfferwallView');
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* AdChain Offerwall View Component
|
|
33
|
+
*
|
|
34
|
+
* This component embeds the AdChain Offerwall WebView in a React Native container.
|
|
35
|
+
* It can be used in tabs, modals, or any other container.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```tsx
|
|
39
|
+
* <AdchainOfferwallView
|
|
40
|
+
* placementId="main_tab_offerwall"
|
|
41
|
+
* style={{ flex: 1 }}
|
|
42
|
+
* onOfferwallOpened={() => console.log('Offerwall opened')}
|
|
43
|
+
* onOfferwallError={(error) => console.error('Error:', error)}
|
|
44
|
+
* onRewardEarned={(amount) => console.log('Earned:', amount)}
|
|
45
|
+
* />
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export const AdchainOfferwallView = /*#__PURE__*/React.forwardRef(({
|
|
49
|
+
placementId,
|
|
50
|
+
style,
|
|
51
|
+
onOfferwallOpened,
|
|
52
|
+
onOfferwallClosed,
|
|
53
|
+
onOfferwallError,
|
|
54
|
+
onRewardEarned,
|
|
55
|
+
onCustomEvent,
|
|
56
|
+
onDataRequest
|
|
57
|
+
}, ref) => {
|
|
58
|
+
const viewRef = useRef(null);
|
|
59
|
+
|
|
60
|
+
// Merge external ref with internal ref
|
|
61
|
+
React.useImperativeHandle(ref, () => viewRef.current);
|
|
62
|
+
|
|
63
|
+
// Load offerwall using UIManager command when placementId changes
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
if (placementId && viewRef.current) {
|
|
66
|
+
const viewId = findNodeHandle(viewRef.current);
|
|
67
|
+
if (viewId) {
|
|
68
|
+
if (Platform.OS === 'android') {
|
|
69
|
+
try {
|
|
70
|
+
// Use command name directly (React Native 0.74+ style)
|
|
71
|
+
UIManager.dispatchViewManagerCommand(viewId, 'loadOfferwall', [placementId]);
|
|
72
|
+
} catch (error) {
|
|
73
|
+
console.error('[OfferwallView] Failed to dispatch command:', error);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}, [placementId]);
|
|
79
|
+
|
|
80
|
+
// Handle native error events
|
|
81
|
+
const handleOfferwallError = event => {
|
|
82
|
+
if (onOfferwallError) {
|
|
83
|
+
onOfferwallError(event.nativeEvent.error);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Handle native reward events
|
|
88
|
+
const handleRewardEarned = event => {
|
|
89
|
+
if (onRewardEarned) {
|
|
90
|
+
onRewardEarned(event.nativeEvent.amount);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// ===== NEW: Handle custom events from WebView =====
|
|
95
|
+
const handleCustomEvent = event => {
|
|
96
|
+
if (onCustomEvent) {
|
|
97
|
+
onCustomEvent(event.nativeEvent.eventType, event.nativeEvent.payload);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// ===== NEW: Handle data requests from WebView =====
|
|
102
|
+
const handleDataRequest = event => {
|
|
103
|
+
if (onDataRequest) {
|
|
104
|
+
const {
|
|
105
|
+
requestId,
|
|
106
|
+
requestType,
|
|
107
|
+
params
|
|
108
|
+
} = event.nativeEvent;
|
|
109
|
+
|
|
110
|
+
// Get data from parent app
|
|
111
|
+
const responseData = onDataRequest(requestType, params);
|
|
112
|
+
|
|
113
|
+
// Send response back to native (which will forward to WebView)
|
|
114
|
+
if (responseData !== null && responseData !== undefined && viewRef.current) {
|
|
115
|
+
const viewId = findNodeHandle(viewRef.current);
|
|
116
|
+
if (viewId) {
|
|
117
|
+
try {
|
|
118
|
+
UIManager.dispatchViewManagerCommand(viewId, 'sendDataResponse', [requestId, responseData]);
|
|
119
|
+
} catch (error) {
|
|
120
|
+
console.error('[OfferwallView] Failed to send data response:', error);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
return /*#__PURE__*/_jsx(NativeOfferwallView, {
|
|
127
|
+
ref: viewRef,
|
|
128
|
+
style: style,
|
|
129
|
+
placementId: Platform.OS === 'ios' ? placementId : undefined // iOS uses property
|
|
130
|
+
,
|
|
131
|
+
onOfferwallOpened: onOfferwallOpened,
|
|
132
|
+
onOfferwallClosed: onOfferwallClosed,
|
|
133
|
+
onOfferwallError: handleOfferwallError,
|
|
134
|
+
onRewardEarned: handleRewardEarned,
|
|
135
|
+
onCustomEvent: handleCustomEvent // NEW
|
|
136
|
+
,
|
|
137
|
+
onDataRequest: handleDataRequest // NEW
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
export default AdchainOfferwallView;
|
|
141
|
+
//# sourceMappingURL=AdchainOfferwallView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","useEffect","useRef","requireNativeComponent","UIManager","findNodeHandle","Platform","jsx","_jsx","NativeOfferwallView","AdchainOfferwallView","forwardRef","placementId","style","onOfferwallOpened","onOfferwallClosed","onOfferwallError","onRewardEarned","onCustomEvent","onDataRequest","ref","viewRef","useImperativeHandle","current","viewId","OS","dispatchViewManagerCommand","error","console","handleOfferwallError","event","nativeEvent","handleRewardEarned","amount","handleCustomEvent","eventType","payload","handleDataRequest","requestId","requestType","params","responseData","undefined"],"sourceRoot":"../../src","sources":["AdchainOfferwallView.tsx"],"mappings":"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","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import { NativeModules, Platform, NativeEventEmitter } from 'react-native';
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
// Expo Constants는 autoInitialize() 함수에서만 사용됨 (Expo 프로젝트 전용)
|
|
6
|
+
// 순수 React Native 프로젝트에서는 경고 없이 건너뜀
|
|
7
|
+
let Constants = null;
|
|
8
|
+
try {
|
|
9
|
+
// require.resolve() 대신 직접 require를 시도
|
|
10
|
+
// Metro 번들러가 require.resolve()를 정적으로 분석하여 모듈을 찾으려 하므로,
|
|
11
|
+
// Pure RN 프로젝트에서 오류가 발생할 수 있음
|
|
12
|
+
Constants = require('expo-constants').default;
|
|
13
|
+
} catch (e) {
|
|
14
|
+
// expo-constants가 없는 경우 (순수 React Native) - autoInitialize()는 사용 불가
|
|
15
|
+
// 이는 정상적인 동작이며 경고를 발생시키지 않음
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Export Offerwall View Component
|
|
19
|
+
export { AdchainOfferwallView } from "./AdchainOfferwallView.js";
|
|
5
20
|
const LINKING_ERROR = `The package 'adchain-sdk' doesn't seem to be linked. Make sure: \n\n` + Platform.select({
|
|
6
21
|
ios: "- You have run 'pod install'\n",
|
|
7
22
|
default: ''
|
|
@@ -33,6 +48,9 @@ class AdchainSDK {
|
|
|
33
48
|
// Expo용 자동 초기화 (app.json 설정 사용) - 플랫폼별 credentials 지원
|
|
34
49
|
async autoInitialize() {
|
|
35
50
|
try {
|
|
51
|
+
if (!Constants) {
|
|
52
|
+
throw new Error('AdChain: autoInitialize() is only available in Expo projects. ' + 'For pure React Native projects, please use initialize() method with your credentials.');
|
|
53
|
+
}
|
|
36
54
|
const expoConfig = Constants.expoConfig;
|
|
37
55
|
if (!expoConfig) {
|
|
38
56
|
throw new Error('AdChain: Expo config not found. ' + 'Are you running in Expo Go? This SDK requires a development build. ' + 'Please use: npx expo run:android or npx expo run:ios');
|
|
@@ -108,19 +126,19 @@ class AdchainSDK {
|
|
|
108
126
|
// 5. Offerwall (3개)
|
|
109
127
|
async openOfferwall(placementId) {
|
|
110
128
|
// SDK requires placementId, use empty string if not provided
|
|
111
|
-
return AdchainSdk.openOfferwall(placementId ||
|
|
129
|
+
return AdchainSdk.openOfferwall(placementId || '');
|
|
112
130
|
}
|
|
113
131
|
async openOfferwallWithUrl(url, placementId) {
|
|
114
132
|
// SDK requires placementId, use empty string if not provided
|
|
115
|
-
return AdchainSdk.openOfferwallWithUrl(url, placementId ||
|
|
133
|
+
return AdchainSdk.openOfferwallWithUrl(url, placementId || '');
|
|
116
134
|
}
|
|
117
135
|
async openExternalBrowser(url, placementId) {
|
|
118
136
|
// SDK requires placementId, use empty string if not provided
|
|
119
|
-
return AdchainSdk.openExternalBrowser(url, placementId ||
|
|
137
|
+
return AdchainSdk.openExternalBrowser(url, placementId || '');
|
|
120
138
|
}
|
|
121
139
|
async openAdjoeOfferwall(placementId) {
|
|
122
140
|
// SDK requires placementId, use empty string if not provided
|
|
123
|
-
return AdchainSdk.openAdjoeOfferwall(placementId ||
|
|
141
|
+
return AdchainSdk.openAdjoeOfferwall(placementId || '');
|
|
124
142
|
}
|
|
125
143
|
|
|
126
144
|
// 6. Debug/Utility Methods (3개)
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeModules","Platform","NativeEventEmitter","Constants","LINKING_ERROR","select","ios","
|
|
1
|
+
{"version":3,"names":["NativeModules","Platform","NativeEventEmitter","Constants","require","default","e","AdchainOfferwallView","LINKING_ERROR","select","ios","AdchainSdk","Proxy","get","Error","adchainEventEmitter","AdchainSDK","initialize","config","options","environment","timeout","appKey","appSecret","autoInitialize","expoConfig","adchainAndroidAppKey","adchainAndroidAppSecret","adchainIosAppKey","adchainIosAppSecret","adchainEnvironment","adchainTimeout","extra","isIOS","OS","console","log","error","login","user","userInfo","gender","birthYear","customProperties","userId","logout","isLoggedIn","getCurrentUser","loadQuizList","unitId","clickQuiz","quizId","loadMissionList","clickMission","missionId","claimReward","openOfferwall","placementId","openOfferwallWithUrl","url","openExternalBrowser","openAdjoeOfferwall","isInitialized","getUserId","getIFA","getBannerInfo","addQuizCompletedListener","callback","addListener","addMissionCompletedListener","addMissionProgressedListener","addMissionRefreshedListener","sdk"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ViewStyle } from 'react-native';
|
|
3
|
+
/**
|
|
4
|
+
* Props for AdchainOfferwallView component
|
|
5
|
+
*/
|
|
6
|
+
export interface AdchainOfferwallViewProps {
|
|
7
|
+
/** Placement ID for tracking and analytics */
|
|
8
|
+
placementId: string;
|
|
9
|
+
/** View style */
|
|
10
|
+
style?: ViewStyle;
|
|
11
|
+
/** Callback when offerwall is opened */
|
|
12
|
+
onOfferwallOpened?: () => void;
|
|
13
|
+
/** Callback when offerwall is closed */
|
|
14
|
+
onOfferwallClosed?: () => void;
|
|
15
|
+
/** Callback when an error occurs */
|
|
16
|
+
onOfferwallError?: (error: string) => void;
|
|
17
|
+
/** Callback when user earns a reward */
|
|
18
|
+
onRewardEarned?: (amount: number) => void;
|
|
19
|
+
/**
|
|
20
|
+
* Callback when WebView sends a custom event
|
|
21
|
+
* @param eventType - Type of event (e.g., "navigate", "show_toast")
|
|
22
|
+
* @param payload - Event data
|
|
23
|
+
* @since 1.0.41
|
|
24
|
+
*/
|
|
25
|
+
onCustomEvent?: (eventType: string, payload: any) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Callback when WebView requests data from the app
|
|
28
|
+
* @param requestType - Type of data requested (e.g., "user_points", "user_profile")
|
|
29
|
+
* @param params - Request parameters
|
|
30
|
+
* @returns Data to send back to WebView, or null/undefined if unavailable
|
|
31
|
+
* @since 1.0.41
|
|
32
|
+
*/
|
|
33
|
+
onDataRequest?: (requestType: string, params: any) => any;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* AdChain Offerwall View Component
|
|
37
|
+
*
|
|
38
|
+
* This component embeds the AdChain Offerwall WebView in a React Native container.
|
|
39
|
+
* It can be used in tabs, modals, or any other container.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```tsx
|
|
43
|
+
* <AdchainOfferwallView
|
|
44
|
+
* placementId="main_tab_offerwall"
|
|
45
|
+
* style={{ flex: 1 }}
|
|
46
|
+
* onOfferwallOpened={() => console.log('Offerwall opened')}
|
|
47
|
+
* onOfferwallError={(error) => console.error('Error:', error)}
|
|
48
|
+
* onRewardEarned={(amount) => console.log('Earned:', amount)}
|
|
49
|
+
* />
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare const AdchainOfferwallView: React.ForwardRefExoticComponent<AdchainOfferwallViewProps & React.RefAttributes<any>>;
|
|
53
|
+
export default AdchainOfferwallView;
|
|
54
|
+
//# sourceMappingURL=AdchainOfferwallView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AdchainOfferwallView.d.ts","sourceRoot":"","sources":["../../../src/AdchainOfferwallView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAOjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AA8C9C;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,wCAAwC;IACxC,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B,wCAAwC;IACxC,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B,oCAAoC;IACpC,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,wCAAwC;IACxC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAI1C;;;;;OAKG;IACH,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC;IAE1D;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC;CAC3D;AAsBD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,oBAAoB,uFAmHhC,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@1selfworld/adchain-sdk-react-native",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "AdChain SDK for React Native with Expo support",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
@@ -83,11 +83,17 @@
|
|
|
83
83
|
"typescript": "^5.9.2"
|
|
84
84
|
},
|
|
85
85
|
"peerDependencies": {
|
|
86
|
-
"expo": ">=53.0.0",
|
|
87
|
-
"expo-constants": ">=17.0.0",
|
|
88
86
|
"react": ">=18.0.0",
|
|
89
87
|
"react-native": ">=0.79.0"
|
|
90
88
|
},
|
|
89
|
+
"peerDependenciesMeta": {
|
|
90
|
+
"expo": {
|
|
91
|
+
"optional": true
|
|
92
|
+
},
|
|
93
|
+
"expo-constants": {
|
|
94
|
+
"optional": true
|
|
95
|
+
}
|
|
96
|
+
},
|
|
91
97
|
"packageManager": "yarn@3.6.1",
|
|
92
98
|
"jest": {
|
|
93
99
|
"preset": "react-native",
|
|
@@ -13,7 +13,7 @@ function withAdchainConfig(config, props = {}) {
|
|
|
13
13
|
adchainIosAppSecret: iosConfig.appSecret || props.appSecret,
|
|
14
14
|
// 공통 설정
|
|
15
15
|
adchainEnvironment: props.environment || 'PRODUCTION',
|
|
16
|
-
adchainTimeout: props.timeout || 30000
|
|
16
|
+
adchainTimeout: props.timeout || 30000,
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
return config;
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
requireNativeComponent,
|
|
4
|
+
UIManager,
|
|
5
|
+
findNodeHandle,
|
|
6
|
+
Platform,
|
|
7
|
+
} from 'react-native';
|
|
8
|
+
import type { ViewStyle } from 'react-native';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Event types for Offerwall callbacks
|
|
12
|
+
*/
|
|
13
|
+
interface OfferwallErrorEvent {
|
|
14
|
+
nativeEvent: {
|
|
15
|
+
error: string;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface OfferwallRewardEvent {
|
|
20
|
+
nativeEvent: {
|
|
21
|
+
amount: number;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface OfferwallHeightChangeEvent {
|
|
26
|
+
nativeEvent: {
|
|
27
|
+
height: number;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Custom event from WebView
|
|
33
|
+
* @since 1.0.41
|
|
34
|
+
*/
|
|
35
|
+
interface OfferwallCustomEvent {
|
|
36
|
+
nativeEvent: {
|
|
37
|
+
eventType: string;
|
|
38
|
+
payload: any;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Data request from WebView
|
|
44
|
+
* @since 1.0.41
|
|
45
|
+
*/
|
|
46
|
+
interface OfferwallDataRequestEvent {
|
|
47
|
+
nativeEvent: {
|
|
48
|
+
requestId: string;
|
|
49
|
+
requestType: string;
|
|
50
|
+
params: any;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Props for AdchainOfferwallView component
|
|
56
|
+
*/
|
|
57
|
+
export interface AdchainOfferwallViewProps {
|
|
58
|
+
/** Placement ID for tracking and analytics */
|
|
59
|
+
placementId: string;
|
|
60
|
+
/** View style */
|
|
61
|
+
style?: ViewStyle;
|
|
62
|
+
/** Callback when offerwall is opened */
|
|
63
|
+
onOfferwallOpened?: () => void;
|
|
64
|
+
/** Callback when offerwall is closed */
|
|
65
|
+
onOfferwallClosed?: () => void;
|
|
66
|
+
/** Callback when an error occurs */
|
|
67
|
+
onOfferwallError?: (error: string) => void;
|
|
68
|
+
/** Callback when user earns a reward */
|
|
69
|
+
onRewardEarned?: (amount: number) => void;
|
|
70
|
+
|
|
71
|
+
// ===== NEW: Event Bridge Callbacks (v1.0.41+) =====
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Callback when WebView sends a custom event
|
|
75
|
+
* @param eventType - Type of event (e.g., "navigate", "show_toast")
|
|
76
|
+
* @param payload - Event data
|
|
77
|
+
* @since 1.0.41
|
|
78
|
+
*/
|
|
79
|
+
onCustomEvent?: (eventType: string, payload: any) => void;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Callback when WebView requests data from the app
|
|
83
|
+
* @param requestType - Type of data requested (e.g., "user_points", "user_profile")
|
|
84
|
+
* @param params - Request parameters
|
|
85
|
+
* @returns Data to send back to WebView, or null/undefined if unavailable
|
|
86
|
+
* @since 1.0.41
|
|
87
|
+
*/
|
|
88
|
+
onDataRequest?: (requestType: string, params: any) => any;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Native component interface
|
|
93
|
+
*/
|
|
94
|
+
interface NativeOfferwallViewProps {
|
|
95
|
+
style?: ViewStyle;
|
|
96
|
+
placementId?: string; // iOS uses property, Android uses command
|
|
97
|
+
onOfferwallOpened?: () => void;
|
|
98
|
+
onOfferwallClosed?: () => void;
|
|
99
|
+
onOfferwallError?: (event: OfferwallErrorEvent) => void;
|
|
100
|
+
onRewardEarned?: (event: OfferwallRewardEvent) => void;
|
|
101
|
+
onHeightChange?: (event: OfferwallHeightChangeEvent) => void;
|
|
102
|
+
onCustomEvent?: (event: OfferwallCustomEvent) => void; // NEW
|
|
103
|
+
onDataRequest?: (event: OfferwallDataRequestEvent) => void; // NEW
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Require native component
|
|
107
|
+
const NativeOfferwallView = requireNativeComponent<NativeOfferwallViewProps>(
|
|
108
|
+
'AdchainOfferwallView'
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* AdChain Offerwall View Component
|
|
113
|
+
*
|
|
114
|
+
* This component embeds the AdChain Offerwall WebView in a React Native container.
|
|
115
|
+
* It can be used in tabs, modals, or any other container.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```tsx
|
|
119
|
+
* <AdchainOfferwallView
|
|
120
|
+
* placementId="main_tab_offerwall"
|
|
121
|
+
* style={{ flex: 1 }}
|
|
122
|
+
* onOfferwallOpened={() => console.log('Offerwall opened')}
|
|
123
|
+
* onOfferwallError={(error) => console.error('Error:', error)}
|
|
124
|
+
* onRewardEarned={(amount) => console.log('Earned:', amount)}
|
|
125
|
+
* />
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
export const AdchainOfferwallView = React.forwardRef<
|
|
129
|
+
any,
|
|
130
|
+
AdchainOfferwallViewProps
|
|
131
|
+
>(
|
|
132
|
+
(
|
|
133
|
+
{
|
|
134
|
+
placementId,
|
|
135
|
+
style,
|
|
136
|
+
onOfferwallOpened,
|
|
137
|
+
onOfferwallClosed,
|
|
138
|
+
onOfferwallError,
|
|
139
|
+
onRewardEarned,
|
|
140
|
+
onCustomEvent,
|
|
141
|
+
onDataRequest,
|
|
142
|
+
},
|
|
143
|
+
ref
|
|
144
|
+
) => {
|
|
145
|
+
const viewRef = useRef(null);
|
|
146
|
+
|
|
147
|
+
// Merge external ref with internal ref
|
|
148
|
+
React.useImperativeHandle(ref, () => viewRef.current);
|
|
149
|
+
|
|
150
|
+
// Load offerwall using UIManager command when placementId changes
|
|
151
|
+
useEffect(() => {
|
|
152
|
+
if (placementId && viewRef.current) {
|
|
153
|
+
const viewId = findNodeHandle(viewRef.current);
|
|
154
|
+
|
|
155
|
+
if (viewId) {
|
|
156
|
+
if (Platform.OS === 'android') {
|
|
157
|
+
try {
|
|
158
|
+
// Use command name directly (React Native 0.74+ style)
|
|
159
|
+
UIManager.dispatchViewManagerCommand(
|
|
160
|
+
viewId,
|
|
161
|
+
'loadOfferwall' as any,
|
|
162
|
+
[placementId]
|
|
163
|
+
);
|
|
164
|
+
} catch (error) {
|
|
165
|
+
console.error(
|
|
166
|
+
'[OfferwallView] Failed to dispatch command:',
|
|
167
|
+
error
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}, [placementId]);
|
|
174
|
+
|
|
175
|
+
// Handle native error events
|
|
176
|
+
const handleOfferwallError = (event: OfferwallErrorEvent) => {
|
|
177
|
+
if (onOfferwallError) {
|
|
178
|
+
onOfferwallError(event.nativeEvent.error);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
// Handle native reward events
|
|
183
|
+
const handleRewardEarned = (event: OfferwallRewardEvent) => {
|
|
184
|
+
if (onRewardEarned) {
|
|
185
|
+
onRewardEarned(event.nativeEvent.amount);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// ===== NEW: Handle custom events from WebView =====
|
|
190
|
+
const handleCustomEvent = (event: OfferwallCustomEvent) => {
|
|
191
|
+
if (onCustomEvent) {
|
|
192
|
+
onCustomEvent(event.nativeEvent.eventType, event.nativeEvent.payload);
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// ===== NEW: Handle data requests from WebView =====
|
|
197
|
+
const handleDataRequest = (event: OfferwallDataRequestEvent) => {
|
|
198
|
+
if (onDataRequest) {
|
|
199
|
+
const { requestId, requestType, params } = event.nativeEvent;
|
|
200
|
+
|
|
201
|
+
// Get data from parent app
|
|
202
|
+
const responseData = onDataRequest(requestType, params);
|
|
203
|
+
|
|
204
|
+
// Send response back to native (which will forward to WebView)
|
|
205
|
+
if (
|
|
206
|
+
responseData !== null &&
|
|
207
|
+
responseData !== undefined &&
|
|
208
|
+
viewRef.current
|
|
209
|
+
) {
|
|
210
|
+
const viewId = findNodeHandle(viewRef.current);
|
|
211
|
+
if (viewId) {
|
|
212
|
+
try {
|
|
213
|
+
UIManager.dispatchViewManagerCommand(
|
|
214
|
+
viewId,
|
|
215
|
+
'sendDataResponse' as any,
|
|
216
|
+
[requestId, responseData]
|
|
217
|
+
);
|
|
218
|
+
} catch (error) {
|
|
219
|
+
console.error(
|
|
220
|
+
'[OfferwallView] Failed to send data response:',
|
|
221
|
+
error
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
return (
|
|
230
|
+
<NativeOfferwallView
|
|
231
|
+
ref={viewRef}
|
|
232
|
+
style={style}
|
|
233
|
+
placementId={Platform.OS === 'ios' ? placementId : undefined} // iOS uses property
|
|
234
|
+
onOfferwallOpened={onOfferwallOpened}
|
|
235
|
+
onOfferwallClosed={onOfferwallClosed}
|
|
236
|
+
onOfferwallError={handleOfferwallError}
|
|
237
|
+
onRewardEarned={handleRewardEarned}
|
|
238
|
+
onCustomEvent={handleCustomEvent} // NEW
|
|
239
|
+
onDataRequest={handleDataRequest} // NEW
|
|
240
|
+
/>
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
export default AdchainOfferwallView;
|
package/src/index.tsx
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
import { NativeModules, Platform, NativeEventEmitter } from 'react-native';
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
// Expo Constants는 autoInitialize() 함수에서만 사용됨 (Expo 프로젝트 전용)
|
|
4
|
+
// 순수 React Native 프로젝트에서는 경고 없이 건너뜀
|
|
5
|
+
let Constants: any = null;
|
|
6
|
+
try {
|
|
7
|
+
// require.resolve() 대신 직접 require를 시도
|
|
8
|
+
// Metro 번들러가 require.resolve()를 정적으로 분석하여 모듈을 찾으려 하므로,
|
|
9
|
+
// Pure RN 프로젝트에서 오류가 발생할 수 있음
|
|
10
|
+
Constants = require('expo-constants').default;
|
|
11
|
+
} catch (e) {
|
|
12
|
+
// expo-constants가 없는 경우 (순수 React Native) - autoInitialize()는 사용 불가
|
|
13
|
+
// 이는 정상적인 동작이며 경고를 발생시키지 않음
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Export Offerwall View Component
|
|
17
|
+
export { AdchainOfferwallView } from './AdchainOfferwallView';
|
|
18
|
+
export type { AdchainOfferwallViewProps } from './AdchainOfferwallView';
|
|
3
19
|
|
|
4
20
|
const LINKING_ERROR =
|
|
5
21
|
`The package 'adchain-sdk' doesn't seem to be linked. Make sure: \n\n` +
|
|
@@ -87,26 +103,29 @@ class AdchainSDK {
|
|
|
87
103
|
// options 객체로 environment와 timeout 전달
|
|
88
104
|
const options = {
|
|
89
105
|
environment: config.environment,
|
|
90
|
-
timeout: config.timeout
|
|
106
|
+
timeout: config.timeout,
|
|
91
107
|
};
|
|
92
108
|
|
|
93
|
-
return AdchainSdk.initialize(
|
|
94
|
-
config.appKey,
|
|
95
|
-
config.appSecret,
|
|
96
|
-
options
|
|
97
|
-
);
|
|
109
|
+
return AdchainSdk.initialize(config.appKey, config.appSecret, options);
|
|
98
110
|
}
|
|
99
111
|
|
|
100
112
|
// Expo용 자동 초기화 (app.json 설정 사용) - 플랫폼별 credentials 지원
|
|
101
113
|
async autoInitialize(): Promise<SuccessResponse> {
|
|
102
114
|
try {
|
|
115
|
+
if (!Constants) {
|
|
116
|
+
throw new Error(
|
|
117
|
+
'AdChain: autoInitialize() is only available in Expo projects. ' +
|
|
118
|
+
'For pure React Native projects, please use initialize() method with your credentials.'
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
103
122
|
const expoConfig = Constants.expoConfig;
|
|
104
123
|
|
|
105
124
|
if (!expoConfig) {
|
|
106
125
|
throw new Error(
|
|
107
126
|
'AdChain: Expo config not found. ' +
|
|
108
|
-
|
|
109
|
-
|
|
127
|
+
'Are you running in Expo Go? This SDK requires a development build. ' +
|
|
128
|
+
'Please use: npx expo run:android or npx expo run:ios'
|
|
110
129
|
);
|
|
111
130
|
}
|
|
112
131
|
|
|
@@ -116,7 +135,7 @@ class AdchainSDK {
|
|
|
116
135
|
adchainIosAppKey,
|
|
117
136
|
adchainIosAppSecret,
|
|
118
137
|
adchainEnvironment,
|
|
119
|
-
adchainTimeout
|
|
138
|
+
adchainTimeout,
|
|
120
139
|
} = expoConfig.extra || {};
|
|
121
140
|
|
|
122
141
|
// 플랫폼별 credentials 선택
|
|
@@ -127,33 +146,35 @@ class AdchainSDK {
|
|
|
127
146
|
if (!appKey || !appSecret) {
|
|
128
147
|
throw new Error(
|
|
129
148
|
`AdChain: Missing ${Platform.OS} configuration in app.json. ` +
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
149
|
+
'Please add AdChain SDK to plugins section:\n\n' +
|
|
150
|
+
'{\n' +
|
|
151
|
+
' "expo": {\n' +
|
|
152
|
+
' "plugins": [\n' +
|
|
153
|
+
' ["@adchain/expo-sdk", {\n' +
|
|
154
|
+
' "android": {\n' +
|
|
155
|
+
' "appKey": "YOUR_ANDROID_APP_KEY",\n' +
|
|
156
|
+
' "appSecret": "YOUR_APP_SECRET"\n' +
|
|
157
|
+
' },\n' +
|
|
158
|
+
' "ios": {\n' +
|
|
159
|
+
' "appKey": "YOUR_IOS_APP_KEY",\n' +
|
|
160
|
+
' "appSecret": "YOUR_APP_SECRET"\n' +
|
|
161
|
+
' }\n' +
|
|
162
|
+
' }]\n' +
|
|
163
|
+
' ]\n' +
|
|
164
|
+
' }\n' +
|
|
165
|
+
'}'
|
|
147
166
|
);
|
|
148
167
|
}
|
|
149
168
|
|
|
150
|
-
console.log(
|
|
169
|
+
console.log(
|
|
170
|
+
`[AdChain] Auto-initializing with ${Platform.OS} credentials...`
|
|
171
|
+
);
|
|
151
172
|
|
|
152
173
|
return await this.initialize({
|
|
153
174
|
appKey,
|
|
154
175
|
appSecret,
|
|
155
176
|
environment: adchainEnvironment || 'PRODUCTION',
|
|
156
|
-
timeout: adchainTimeout
|
|
177
|
+
timeout: adchainTimeout,
|
|
157
178
|
});
|
|
158
179
|
} catch (error) {
|
|
159
180
|
console.error('[AdChain autoInitialize] Failed:', error);
|
|
@@ -167,13 +188,10 @@ class AdchainSDK {
|
|
|
167
188
|
const userInfo = {
|
|
168
189
|
gender: user.gender,
|
|
169
190
|
birthYear: user.birthYear,
|
|
170
|
-
customProperties: user.customProperties
|
|
191
|
+
customProperties: user.customProperties,
|
|
171
192
|
};
|
|
172
|
-
|
|
173
|
-
return AdchainSdk.login(
|
|
174
|
-
user.userId,
|
|
175
|
-
userInfo
|
|
176
|
-
);
|
|
193
|
+
|
|
194
|
+
return AdchainSdk.login(user.userId, userInfo);
|
|
177
195
|
}
|
|
178
196
|
|
|
179
197
|
async logout(): Promise<SuccessResponse> {
|
|
@@ -202,7 +220,10 @@ class AdchainSDK {
|
|
|
202
220
|
return AdchainSdk.loadMissionList(unitId);
|
|
203
221
|
}
|
|
204
222
|
|
|
205
|
-
async clickMission(
|
|
223
|
+
async clickMission(
|
|
224
|
+
unitId: string,
|
|
225
|
+
missionId: string
|
|
226
|
+
): Promise<SuccessResponse> {
|
|
206
227
|
return AdchainSdk.clickMission(unitId, missionId);
|
|
207
228
|
}
|
|
208
229
|
|
|
@@ -213,22 +234,28 @@ class AdchainSDK {
|
|
|
213
234
|
// 5. Offerwall (3개)
|
|
214
235
|
async openOfferwall(placementId?: string): Promise<SuccessResponse> {
|
|
215
236
|
// SDK requires placementId, use empty string if not provided
|
|
216
|
-
return AdchainSdk.openOfferwall(placementId ||
|
|
237
|
+
return AdchainSdk.openOfferwall(placementId || '');
|
|
217
238
|
}
|
|
218
239
|
|
|
219
|
-
async openOfferwallWithUrl(
|
|
240
|
+
async openOfferwallWithUrl(
|
|
241
|
+
url: string,
|
|
242
|
+
placementId?: string
|
|
243
|
+
): Promise<SuccessResponse> {
|
|
220
244
|
// SDK requires placementId, use empty string if not provided
|
|
221
|
-
return AdchainSdk.openOfferwallWithUrl(url, placementId ||
|
|
245
|
+
return AdchainSdk.openOfferwallWithUrl(url, placementId || '');
|
|
222
246
|
}
|
|
223
247
|
|
|
224
|
-
async openExternalBrowser(
|
|
248
|
+
async openExternalBrowser(
|
|
249
|
+
url: string,
|
|
250
|
+
placementId?: string
|
|
251
|
+
): Promise<SuccessResponse> {
|
|
225
252
|
// SDK requires placementId, use empty string if not provided
|
|
226
|
-
return AdchainSdk.openExternalBrowser(url, placementId ||
|
|
253
|
+
return AdchainSdk.openExternalBrowser(url, placementId || '');
|
|
227
254
|
}
|
|
228
255
|
|
|
229
256
|
async openAdjoeOfferwall(placementId?: string): Promise<SuccessResponse> {
|
|
230
257
|
// SDK requires placementId, use empty string if not provided
|
|
231
|
-
return AdchainSdk.openAdjoeOfferwall(placementId ||
|
|
258
|
+
return AdchainSdk.openAdjoeOfferwall(placementId || '');
|
|
232
259
|
}
|
|
233
260
|
|
|
234
261
|
// 6. Debug/Utility Methods (3개)
|
|
@@ -252,23 +279,34 @@ class AdchainSDK {
|
|
|
252
279
|
|
|
253
280
|
// ===== Event Helper Functions =====
|
|
254
281
|
|
|
255
|
-
export function addQuizCompletedListener(
|
|
282
|
+
export function addQuizCompletedListener(
|
|
283
|
+
callback: (event: { quizId: string; unitId: string }) => void
|
|
284
|
+
) {
|
|
256
285
|
return adchainEventEmitter.addListener('onQuizCompleted', callback as any);
|
|
257
286
|
}
|
|
258
287
|
|
|
259
|
-
export function addMissionCompletedListener(
|
|
288
|
+
export function addMissionCompletedListener(
|
|
289
|
+
callback: (event: { missionId: string; unitId: string }) => void
|
|
290
|
+
) {
|
|
260
291
|
return adchainEventEmitter.addListener('onMissionCompleted', callback as any);
|
|
261
292
|
}
|
|
262
293
|
|
|
263
|
-
export function addMissionProgressedListener(
|
|
264
|
-
|
|
294
|
+
export function addMissionProgressedListener(
|
|
295
|
+
callback: (event: { missionId: string; unitId: string }) => void
|
|
296
|
+
) {
|
|
297
|
+
return adchainEventEmitter.addListener(
|
|
298
|
+
'onMissionProgressed',
|
|
299
|
+
callback as any
|
|
300
|
+
);
|
|
265
301
|
}
|
|
266
302
|
|
|
267
|
-
export function addMissionRefreshedListener(
|
|
303
|
+
export function addMissionRefreshedListener(
|
|
304
|
+
callback: (event: { unitId: string }) => void
|
|
305
|
+
) {
|
|
268
306
|
return adchainEventEmitter.addListener('onMissionRefreshed', callback as any);
|
|
269
307
|
}
|
|
270
308
|
|
|
271
309
|
// ===== Export =====
|
|
272
310
|
|
|
273
311
|
const sdk = new AdchainSDK();
|
|
274
|
-
export default sdk;
|
|
312
|
+
export default sdk;
|