@apps-in-toss/framework 1.9.3 → 1.10.0
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/dist/index.cjs +1261 -61
- package/dist/index.d.cts +50 -55
- package/dist/index.d.ts +50 -55
- package/dist/index.js +1269 -62
- package/package.json +7 -6
package/dist/index.cjs
CHANGED
|
@@ -34,6 +34,7 @@ __export(src_exports, {
|
|
|
34
34
|
Analytics: () => Analytics2,
|
|
35
35
|
AppsInToss: () => AppsInToss,
|
|
36
36
|
INTERNAL__onVisibilityChangedByTransparentServiceWeb: () => INTERNAL__onVisibilityChangedByTransparentServiceWeb,
|
|
37
|
+
InlineAd: () => InlineAd,
|
|
37
38
|
OverlayProvider: () => import_private10.OverlayProvider,
|
|
38
39
|
WebView: () => WebView,
|
|
39
40
|
env: () => env,
|
|
@@ -62,7 +63,9 @@ var import_react3 = require("react");
|
|
|
62
63
|
|
|
63
64
|
// src/env.ts
|
|
64
65
|
var env = {
|
|
65
|
-
getDeploymentId: () => __DEV__ ? "local" : global.__appsInToss?.deploymentId
|
|
66
|
+
getDeploymentId: () => __DEV__ ? "local" : global.__appsInToss?.deploymentId,
|
|
67
|
+
getWebViewType: () => global.__appsInToss.webViewType,
|
|
68
|
+
getAppName: () => global.__granite.app.name
|
|
66
69
|
};
|
|
67
70
|
|
|
68
71
|
// src/hooks/useCaptureExitLog.ts
|
|
@@ -1439,6 +1442,7 @@ var import_native_modules24 = require("@apps-in-toss/native-modules");
|
|
|
1439
1442
|
var appsInTossAsyncBridges = __toESM(require("@apps-in-toss/native-modules/async-bridges"), 1);
|
|
1440
1443
|
var appsInTossConstantBridges = __toESM(require("@apps-in-toss/native-modules/constant-bridges"), 1);
|
|
1441
1444
|
var appsInTossEventBridges = __toESM(require("@apps-in-toss/native-modules/event-bridges"), 1);
|
|
1445
|
+
var import_user_scripts = require("@apps-in-toss/user-scripts");
|
|
1442
1446
|
var import_react_native_safe_area_context4 = require("@granite-js/native/react-native-safe-area-context");
|
|
1443
1447
|
var import_react_native39 = require("@granite-js/react-native");
|
|
1444
1448
|
var import_tds_react_native15 = require("@toss/tds-react-native");
|
|
@@ -2683,7 +2687,9 @@ function WebView({ type, local, onMessage, ...props }) {
|
|
|
2683
2687
|
/** TossAd */
|
|
2684
2688
|
fetchTossAd_isSupported: fetchTossAd.isSupported,
|
|
2685
2689
|
/** env */
|
|
2686
|
-
getDeploymentId: env.getDeploymentId
|
|
2690
|
+
getDeploymentId: env.getDeploymentId,
|
|
2691
|
+
getWebViewType: env.getWebViewType,
|
|
2692
|
+
getAppName: env.getAppName
|
|
2687
2693
|
},
|
|
2688
2694
|
asyncHandlerMap: {
|
|
2689
2695
|
...appsInTossAsyncBridges,
|
|
@@ -2721,7 +2727,11 @@ function WebView({ type, local, onMessage, ...props }) {
|
|
|
2721
2727
|
/** Toss Ads */
|
|
2722
2728
|
tossAdEventLog,
|
|
2723
2729
|
/** Private */
|
|
2724
|
-
memoryDebugLog: webViewMemoryDebugLog
|
|
2730
|
+
memoryDebugLog: webViewMemoryDebugLog,
|
|
2731
|
+
debugLog: async (event) => {
|
|
2732
|
+
import_react_native40.NativeModules.AppsInTossModule?.eventLog(event);
|
|
2733
|
+
import_react_native40.NativeModules.TossCoreModule?.eventLog({ params: event });
|
|
2734
|
+
}
|
|
2725
2735
|
}
|
|
2726
2736
|
});
|
|
2727
2737
|
const headerPropForExternalWebView = (0, import_react28.useMemo)(() => {
|
|
@@ -2753,7 +2763,6 @@ function WebView({ type, local, onMessage, ...props }) {
|
|
|
2753
2763
|
import_react_native40.BackHandler.addEventListener("hardwareBackPress", callback);
|
|
2754
2764
|
return () => import_react_native40.BackHandler.removeEventListener("hardwareBackPress", callback);
|
|
2755
2765
|
}, [webBackHandler]);
|
|
2756
|
-
const globalScripts = useGlobalScripts();
|
|
2757
2766
|
const handleWebViewProcessDidTerminate = useHandleWebViewProcessDidTerminate(webViewRef);
|
|
2758
2767
|
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2759
2768
|
BaseWebView,
|
|
@@ -2782,8 +2791,8 @@ function WebView({ type, local, onMessage, ...props }) {
|
|
|
2782
2791
|
webviewDebuggingEnabled: webViewDebuggingEnabled,
|
|
2783
2792
|
thirdPartyCookiesEnabled: true,
|
|
2784
2793
|
onMessage: handler.onMessage,
|
|
2785
|
-
injectedJavaScript:
|
|
2786
|
-
injectedJavaScriptBeforeContentLoaded:
|
|
2794
|
+
injectedJavaScript: import_user_scripts.afterDocumentLoad,
|
|
2795
|
+
injectedJavaScriptBeforeContentLoaded: [handler.injectedJavaScript, import_user_scripts.beforeDocumentLoad].join("\n"),
|
|
2787
2796
|
decelerationRate: import_react_native40.Platform.OS === "ios" ? 1 : void 0,
|
|
2788
2797
|
allowsBackForwardNavigationGestures,
|
|
2789
2798
|
onShouldStartLoadWithRequest: (event) => {
|
|
@@ -2814,73 +2823,1263 @@ function WebView({ type, local, onMessage, ...props }) {
|
|
|
2814
2823
|
}
|
|
2815
2824
|
);
|
|
2816
2825
|
}
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2826
|
+
|
|
2827
|
+
// src/index.ts
|
|
2828
|
+
__reExport(src_exports, require("@apps-in-toss/analytics"), module.exports);
|
|
2829
|
+
var import_private10 = require("@toss/tds-react-native/private");
|
|
2830
|
+
__reExport(src_exports, require("@apps-in-toss/native-modules"), module.exports);
|
|
2831
|
+
__reExport(src_exports, require("@apps-in-toss/types"), module.exports);
|
|
2832
|
+
|
|
2833
|
+
// src/ads/inlineAd/InlineAd.tsx
|
|
2834
|
+
var import_react_native44 = require("@granite-js/react-native");
|
|
2835
|
+
var import_react31 = require("react");
|
|
2836
|
+
var import_react_native45 = require("react-native");
|
|
2837
|
+
|
|
2838
|
+
// src/ads/inlineAd/constants.ts
|
|
2839
|
+
var SDK_ID = "106";
|
|
2840
|
+
var LIST_BANNER_STYLE_ID = "1";
|
|
2841
|
+
var NATIVE_IMAGE_STYLE_ID = "2";
|
|
2842
|
+
var FEED_BANNER_STYLE_ID = NATIVE_IMAGE_STYLE_ID;
|
|
2843
|
+
var AVAILABLE_STYLE_IDS = [LIST_BANNER_STYLE_ID, NATIVE_IMAGE_STYLE_ID];
|
|
2844
|
+
var DEFAULT_INLINE_AD_THEME = "auto";
|
|
2845
|
+
var DEFAULT_INLINE_AD_TONE = "blackAndWhite";
|
|
2846
|
+
var DEFAULT_INLINE_AD_VARIANT = "expanded";
|
|
2847
|
+
var DEFAULT_INLINE_AD_PADDING_BANNER = "16px 20px";
|
|
2848
|
+
var DEFAULT_INLINE_AD_PADDING_NATIVE_IMAGE = "20px";
|
|
2849
|
+
var ERROR_CODES = {
|
|
2850
|
+
NETWORK_ERROR: 1001,
|
|
2851
|
+
INVALID_REQUEST: 1002,
|
|
2852
|
+
NO_AD: 1003,
|
|
2853
|
+
ERROR: 1004,
|
|
2854
|
+
INVALID_SPACE: 1005,
|
|
2855
|
+
SDK_NOT_INITIALIZED: 1007,
|
|
2856
|
+
HTTP_TIMEOUT: 1008,
|
|
2857
|
+
EXECUTION_FAIL: 1009,
|
|
2858
|
+
INTERRUPTED: 1010,
|
|
2859
|
+
FAIL: 1011,
|
|
2860
|
+
BLOCKED: 1012,
|
|
2861
|
+
TIMEOUT: 1013,
|
|
2862
|
+
LIMITED_AD: 1014,
|
|
2863
|
+
CONSENT_REQUIRED: 1015,
|
|
2864
|
+
TEST_MODE: 1016,
|
|
2865
|
+
INTERNAL_ERROR: 1017
|
|
2866
|
+
};
|
|
2867
|
+
var ERROR_MESSAGES = {
|
|
2868
|
+
[ERROR_CODES.NETWORK_ERROR]: "Network error occurred",
|
|
2869
|
+
[ERROR_CODES.INVALID_REQUEST]: "Invalid request parameters",
|
|
2870
|
+
[ERROR_CODES.NO_AD]: "No ads available",
|
|
2871
|
+
[ERROR_CODES.ERROR]: "Server error occurred",
|
|
2872
|
+
[ERROR_CODES.INVALID_SPACE]: "Invalid or disabled inventory",
|
|
2873
|
+
[ERROR_CODES.SDK_NOT_INITIALIZED]: "SDK is not initialized",
|
|
2874
|
+
[ERROR_CODES.HTTP_TIMEOUT]: "Request timed out",
|
|
2875
|
+
[ERROR_CODES.EXECUTION_FAIL]: "Request execution failed",
|
|
2876
|
+
[ERROR_CODES.INTERRUPTED]: "Request interrupted",
|
|
2877
|
+
[ERROR_CODES.FAIL]: "Request failed",
|
|
2878
|
+
[ERROR_CODES.BLOCKED]: "Ad blocked by policy",
|
|
2879
|
+
[ERROR_CODES.TIMEOUT]: "SSP processing timed out",
|
|
2880
|
+
[ERROR_CODES.LIMITED_AD]: "Ad limited by privacy",
|
|
2881
|
+
[ERROR_CODES.CONSENT_REQUIRED]: "Consent required to show ads",
|
|
2882
|
+
[ERROR_CODES.TEST_MODE]: "Test mode only",
|
|
2883
|
+
[ERROR_CODES.INTERNAL_ERROR]: "Unknown error occurred"
|
|
2884
|
+
};
|
|
2885
|
+
var API_RESULT_ERROR_MAP = {
|
|
2886
|
+
HTTP_TIMEOUT: {
|
|
2887
|
+
code: ERROR_CODES.HTTP_TIMEOUT,
|
|
2888
|
+
message: ERROR_MESSAGES[ERROR_CODES.HTTP_TIMEOUT]
|
|
2889
|
+
},
|
|
2890
|
+
NETWORK_ERROR: {
|
|
2891
|
+
code: ERROR_CODES.NETWORK_ERROR,
|
|
2892
|
+
message: ERROR_MESSAGES[ERROR_CODES.NETWORK_ERROR]
|
|
2893
|
+
},
|
|
2894
|
+
EXECUTION_FAIL: {
|
|
2895
|
+
code: ERROR_CODES.EXECUTION_FAIL,
|
|
2896
|
+
message: ERROR_MESSAGES[ERROR_CODES.EXECUTION_FAIL]
|
|
2897
|
+
},
|
|
2898
|
+
INTERRUPTED: {
|
|
2899
|
+
code: ERROR_CODES.INTERRUPTED,
|
|
2900
|
+
message: ERROR_MESSAGES[ERROR_CODES.INTERRUPTED]
|
|
2901
|
+
},
|
|
2902
|
+
INTERNAL_ERROR: {
|
|
2903
|
+
code: ERROR_CODES.ERROR,
|
|
2904
|
+
message: ERROR_MESSAGES[ERROR_CODES.ERROR]
|
|
2905
|
+
},
|
|
2906
|
+
FAIL: {
|
|
2907
|
+
code: ERROR_CODES.FAIL,
|
|
2908
|
+
message: ERROR_MESSAGES[ERROR_CODES.FAIL]
|
|
2909
|
+
}
|
|
2910
|
+
};
|
|
2911
|
+
var AD_STATUS_ERROR_MAP = {
|
|
2912
|
+
NO_AD: {
|
|
2913
|
+
code: ERROR_CODES.NO_AD,
|
|
2914
|
+
message: ERROR_MESSAGES[ERROR_CODES.NO_AD]
|
|
2915
|
+
},
|
|
2916
|
+
BLOCKED: {
|
|
2917
|
+
code: ERROR_CODES.BLOCKED,
|
|
2918
|
+
message: ERROR_MESSAGES[ERROR_CODES.BLOCKED]
|
|
2919
|
+
},
|
|
2920
|
+
ERROR: {
|
|
2921
|
+
code: ERROR_CODES.ERROR,
|
|
2922
|
+
message: ERROR_MESSAGES[ERROR_CODES.ERROR]
|
|
2923
|
+
},
|
|
2924
|
+
TIMEOUT: {
|
|
2925
|
+
code: ERROR_CODES.TIMEOUT,
|
|
2926
|
+
message: ERROR_MESSAGES[ERROR_CODES.TIMEOUT]
|
|
2927
|
+
},
|
|
2928
|
+
INVALID_SPACE: {
|
|
2929
|
+
code: ERROR_CODES.INVALID_SPACE,
|
|
2930
|
+
message: ERROR_MESSAGES[ERROR_CODES.INVALID_SPACE]
|
|
2931
|
+
},
|
|
2932
|
+
INVALID_REQUEST: {
|
|
2933
|
+
code: ERROR_CODES.INVALID_REQUEST,
|
|
2934
|
+
message: ERROR_MESSAGES[ERROR_CODES.INVALID_REQUEST]
|
|
2935
|
+
},
|
|
2936
|
+
LIMITED_AD: {
|
|
2937
|
+
code: ERROR_CODES.LIMITED_AD,
|
|
2938
|
+
message: ERROR_MESSAGES[ERROR_CODES.LIMITED_AD]
|
|
2939
|
+
},
|
|
2940
|
+
CONSENT_REQUIRED: {
|
|
2941
|
+
code: ERROR_CODES.CONSENT_REQUIRED,
|
|
2942
|
+
message: ERROR_MESSAGES[ERROR_CODES.CONSENT_REQUIRED]
|
|
2943
|
+
},
|
|
2944
|
+
TEST_MODE: {
|
|
2945
|
+
code: ERROR_CODES.TEST_MODE,
|
|
2946
|
+
message: ERROR_MESSAGES[ERROR_CODES.TEST_MODE]
|
|
2947
|
+
}
|
|
2948
|
+
};
|
|
2949
|
+
|
|
2950
|
+
// src/ads/inlineAd/loadAd.ts
|
|
2951
|
+
function createError(code, message) {
|
|
2952
|
+
return {
|
|
2953
|
+
code,
|
|
2954
|
+
message: message || ERROR_MESSAGES[code] || "Unknown error",
|
|
2955
|
+
domain: "@apps-in-toss/framework"
|
|
2956
|
+
};
|
|
2957
|
+
}
|
|
2958
|
+
function isAdError(error) {
|
|
2959
|
+
return Boolean(
|
|
2960
|
+
error && typeof error === "object" && "code" in error && typeof error.code === "number" && "message" in error && typeof error.message === "string"
|
|
2961
|
+
);
|
|
2962
|
+
}
|
|
2963
|
+
function fetchTossAdPromise(options) {
|
|
2964
|
+
return new Promise((resolve, reject) => {
|
|
2965
|
+
if (!fetchTossAd.isSupported()) {
|
|
2966
|
+
reject(new Error("fetchTossAd is not supported in this environment."));
|
|
2967
|
+
return;
|
|
2968
|
+
}
|
|
2969
|
+
fetchTossAd({
|
|
2970
|
+
options,
|
|
2971
|
+
onEvent: resolve,
|
|
2972
|
+
onError: reject
|
|
2973
|
+
});
|
|
2974
|
+
});
|
|
2975
|
+
}
|
|
2976
|
+
function isApiResponse(payload) {
|
|
2977
|
+
return Boolean(payload && typeof payload === "object" && "resultType" in payload);
|
|
2978
|
+
}
|
|
2979
|
+
function isAdResponse(payload) {
|
|
2980
|
+
return Boolean(payload && typeof payload === "object" && "ads" in payload);
|
|
2981
|
+
}
|
|
2982
|
+
function normalizeAdResponse(adResponse) {
|
|
2983
|
+
const ads = Array.isArray(adResponse.ads) ? adResponse.ads.map((ad) => ({
|
|
2984
|
+
...ad,
|
|
2985
|
+
requestId: ad.requestId ?? adResponse.requestId
|
|
2986
|
+
})).filter((ad) => AVAILABLE_STYLE_IDS.includes(String(ad.styleId))) : [];
|
|
2987
|
+
return {
|
|
2988
|
+
requestId: adResponse.requestId ?? "",
|
|
2989
|
+
status: adResponse.status ?? "OK",
|
|
2990
|
+
ads,
|
|
2991
|
+
ext: adResponse.ext
|
|
2992
|
+
};
|
|
2993
|
+
}
|
|
2994
|
+
function normalizeApiResponse(raw) {
|
|
2995
|
+
if (isApiResponse(raw)) {
|
|
2996
|
+
if (raw.resultType !== "SUCCESS") {
|
|
2997
|
+
return raw;
|
|
2998
|
+
}
|
|
2999
|
+
if (!raw.success) {
|
|
3000
|
+
return {
|
|
3001
|
+
resultType: "FAIL",
|
|
3002
|
+
error: { reason: "fetchTossAd returned SUCCESS without payload" }
|
|
3003
|
+
};
|
|
3004
|
+
}
|
|
3005
|
+
return { ...raw, success: normalizeAdResponse(raw.success) };
|
|
3006
|
+
}
|
|
3007
|
+
if (isAdResponse(raw)) {
|
|
3008
|
+
return {
|
|
3009
|
+
resultType: "SUCCESS",
|
|
3010
|
+
success: normalizeAdResponse(raw)
|
|
3011
|
+
};
|
|
3012
|
+
}
|
|
3013
|
+
return {
|
|
3014
|
+
resultType: "FAIL",
|
|
3015
|
+
error: { reason: "Invalid response from fetchTossAd" }
|
|
3016
|
+
};
|
|
3017
|
+
}
|
|
3018
|
+
function isStructurallyValidAd(ad) {
|
|
3019
|
+
return Boolean(ad && ad.creative && typeof ad.creative === "object");
|
|
3020
|
+
}
|
|
3021
|
+
async function loadAd(adGroupId) {
|
|
3022
|
+
if (!adGroupId) {
|
|
3023
|
+
return {
|
|
3024
|
+
type: "error",
|
|
3025
|
+
error: createError(ERROR_CODES.INVALID_SPACE, "Invalid adGroupId - adGroupId must be provided")
|
|
3026
|
+
};
|
|
3027
|
+
}
|
|
3028
|
+
if (!fetchTossAd.isSupported()) {
|
|
3029
|
+
return {
|
|
3030
|
+
type: "error",
|
|
3031
|
+
error: createError(ERROR_CODES.SDK_NOT_INITIALIZED, "This feature is not supported in the current environment")
|
|
3032
|
+
};
|
|
3033
|
+
}
|
|
3034
|
+
let response;
|
|
3035
|
+
try {
|
|
3036
|
+
const raw = await fetchTossAdPromise({
|
|
3037
|
+
adGroupId,
|
|
3038
|
+
sdkId: SDK_ID,
|
|
3039
|
+
availableStyleIds: AVAILABLE_STYLE_IDS
|
|
3040
|
+
});
|
|
3041
|
+
response = normalizeApiResponse(raw);
|
|
3042
|
+
} catch (error) {
|
|
3043
|
+
if (isAdError(error)) {
|
|
3044
|
+
return { type: "error", error };
|
|
3045
|
+
}
|
|
3046
|
+
const message = error instanceof Error ? error.message : "Network error";
|
|
3047
|
+
return {
|
|
3048
|
+
type: "error",
|
|
3049
|
+
error: createError(ERROR_CODES.NETWORK_ERROR, message)
|
|
3050
|
+
};
|
|
3051
|
+
}
|
|
3052
|
+
if (response.resultType !== "SUCCESS") {
|
|
3053
|
+
const mappedError = API_RESULT_ERROR_MAP[response.resultType];
|
|
3054
|
+
const errorMessage = response.error?.reason ?? mappedError?.message ?? ERROR_MESSAGES[ERROR_CODES.INTERNAL_ERROR];
|
|
3055
|
+
const errorCode = mappedError?.code ?? ERROR_CODES.INTERNAL_ERROR;
|
|
3056
|
+
return {
|
|
3057
|
+
type: "error",
|
|
3058
|
+
error: createError(errorCode, errorMessage)
|
|
3059
|
+
};
|
|
3060
|
+
}
|
|
3061
|
+
if (!response.success) {
|
|
3062
|
+
return {
|
|
3063
|
+
type: "error",
|
|
3064
|
+
error: createError(ERROR_CODES.INTERNAL_ERROR, "Missing ad response payload")
|
|
3065
|
+
};
|
|
3066
|
+
}
|
|
3067
|
+
const adResponse = response.success;
|
|
3068
|
+
if (adResponse.status !== "OK" && adResponse.status !== "TEST_MODE") {
|
|
3069
|
+
const statusError = AD_STATUS_ERROR_MAP[adResponse.status];
|
|
3070
|
+
const errorMessage = statusError?.message ?? `Ad response status: ${adResponse.status}`;
|
|
3071
|
+
const errorCode = statusError?.code ?? ERROR_CODES.INTERNAL_ERROR;
|
|
3072
|
+
const error = createError(errorCode, errorMessage);
|
|
3073
|
+
if (error.code === ERROR_CODES.NO_AD) {
|
|
3074
|
+
return { type: "noFill", error, response: adResponse };
|
|
3075
|
+
}
|
|
3076
|
+
return { type: "error", error, response: adResponse };
|
|
3077
|
+
}
|
|
3078
|
+
const topPriorityAd = adResponse.ads[0];
|
|
3079
|
+
const selectedAd = isStructurallyValidAd(topPriorityAd) ? topPriorityAd : adResponse.ads.find(isStructurallyValidAd) ?? null;
|
|
3080
|
+
if (!selectedAd) {
|
|
3081
|
+
return {
|
|
3082
|
+
type: "error",
|
|
3083
|
+
error: createError(ERROR_CODES.INTERNAL_ERROR, "Unsupported styleId in response"),
|
|
3084
|
+
response: adResponse
|
|
3085
|
+
};
|
|
3086
|
+
}
|
|
3087
|
+
return {
|
|
3088
|
+
type: "success",
|
|
3089
|
+
ad: selectedAd,
|
|
3090
|
+
responseExt: adResponse.ext ?? null,
|
|
3091
|
+
requestId: adResponse.requestId,
|
|
3092
|
+
response: adResponse
|
|
3093
|
+
};
|
|
3094
|
+
}
|
|
3095
|
+
|
|
3096
|
+
// src/ads/inlineAd/opener.ts
|
|
3097
|
+
var import_react_native41 = require("@granite-js/react-native");
|
|
3098
|
+
function isSafeUrl(url) {
|
|
3099
|
+
try {
|
|
3100
|
+
const parsed = new URL(url);
|
|
3101
|
+
const dangerous = [
|
|
3102
|
+
"javascript:",
|
|
3103
|
+
"data:",
|
|
3104
|
+
"vbscript:",
|
|
3105
|
+
"file:",
|
|
3106
|
+
"about:",
|
|
3107
|
+
"blob:",
|
|
3108
|
+
"filesystem:",
|
|
3109
|
+
"chrome:",
|
|
3110
|
+
"chrome-extension:",
|
|
3111
|
+
"ftp:",
|
|
3112
|
+
"ftps:",
|
|
3113
|
+
"sftp:",
|
|
3114
|
+
"telnet:",
|
|
3115
|
+
"ssh:",
|
|
3116
|
+
"intent:"
|
|
3117
|
+
];
|
|
3118
|
+
return !dangerous.includes(parsed.protocol.toLowerCase());
|
|
3119
|
+
} catch {
|
|
3120
|
+
return false;
|
|
3121
|
+
}
|
|
3122
|
+
}
|
|
3123
|
+
function openLandingUrl(url) {
|
|
3124
|
+
if (!isSafeUrl(url)) {
|
|
3125
|
+
console.warn("[InlineAd] Blocked unsafe landing URL:", url);
|
|
3126
|
+
return;
|
|
3127
|
+
}
|
|
3128
|
+
try {
|
|
3129
|
+
(0, import_react_native41.openURL)(getWebSchemeOrUri(url));
|
|
3130
|
+
} catch (error) {
|
|
3131
|
+
console.error("[InlineAd] Failed to open landing URL:", error);
|
|
3132
|
+
}
|
|
3133
|
+
}
|
|
3134
|
+
function getWebSchemeOrUri(uri) {
|
|
3135
|
+
const isHttp = ["http://", "https://"].some((protocol) => uri.startsWith(protocol));
|
|
3136
|
+
return isHttp ? supertossWeb(uri) : uri;
|
|
3137
|
+
}
|
|
3138
|
+
function supertossWeb(uri) {
|
|
3139
|
+
return `supertoss://web?url=${encodeURIComponent(uri)}&external=true`;
|
|
3140
|
+
}
|
|
3141
|
+
|
|
3142
|
+
// src/ads/inlineAd/tracking.ts
|
|
3143
|
+
var GlobalEventDeduplicator = class _GlobalEventDeduplicator {
|
|
3144
|
+
static MAX_EVENTS = 1e4;
|
|
3145
|
+
trackedEvents = /* @__PURE__ */ new Set();
|
|
3146
|
+
hasTracked(requestId, creativeId, eventType) {
|
|
3147
|
+
return this.trackedEvents.has(this.buildKey(requestId, creativeId, eventType));
|
|
3148
|
+
}
|
|
3149
|
+
markTracked(requestId, creativeId, eventType) {
|
|
3150
|
+
if (this.trackedEvents.size >= _GlobalEventDeduplicator.MAX_EVENTS) {
|
|
3151
|
+
const firstKey = this.trackedEvents.keys().next().value;
|
|
3152
|
+
if (firstKey) {
|
|
3153
|
+
this.trackedEvents.delete(firstKey);
|
|
2828
3154
|
}
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
3155
|
+
}
|
|
3156
|
+
this.trackedEvents.add(this.buildKey(requestId, creativeId, eventType));
|
|
3157
|
+
}
|
|
3158
|
+
buildKey(requestId, creativeId, eventType) {
|
|
3159
|
+
return `${requestId}:${creativeId}:${eventType}`;
|
|
3160
|
+
}
|
|
3161
|
+
};
|
|
3162
|
+
var globalEventDeduplicator = new GlobalEventDeduplicator();
|
|
3163
|
+
var EventTracker = class {
|
|
3164
|
+
constructor(eventTrackingUrls = [], eventTypes = [], eventPayload = "", requestId, creativeId, requestHeaders) {
|
|
3165
|
+
this.eventTrackingUrls = eventTrackingUrls;
|
|
3166
|
+
this.eventPayload = eventPayload;
|
|
3167
|
+
this.requestId = requestId;
|
|
3168
|
+
this.creativeId = creativeId;
|
|
3169
|
+
this.requestHeaders = requestHeaders;
|
|
3170
|
+
this.eventTypes = new Set(eventTypes);
|
|
3171
|
+
this.repeatableEvents = /* @__PURE__ */ new Set(["VIEW_MUTE", "VIEW_UNMUTE"]);
|
|
3172
|
+
}
|
|
3173
|
+
eventTypes;
|
|
3174
|
+
repeatableEvents;
|
|
3175
|
+
async track(eventType) {
|
|
3176
|
+
if (!this.eventTypes.has(eventType)) {
|
|
3177
|
+
return;
|
|
3178
|
+
}
|
|
3179
|
+
if (!this.repeatableEvents.has(eventType)) {
|
|
3180
|
+
if (this.requestId && this.creativeId) {
|
|
3181
|
+
if (globalEventDeduplicator.hasTracked(this.requestId, this.creativeId, eventType)) {
|
|
3182
|
+
return;
|
|
2837
3183
|
}
|
|
2838
|
-
}
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
3184
|
+
}
|
|
3185
|
+
}
|
|
3186
|
+
if (this.eventTrackingUrls.length === 0) {
|
|
3187
|
+
return;
|
|
3188
|
+
}
|
|
3189
|
+
const payload = {
|
|
3190
|
+
type: eventType,
|
|
3191
|
+
data: this.eventPayload
|
|
3192
|
+
};
|
|
3193
|
+
await Promise.allSettled(this.eventTrackingUrls.map((url) => this.sendTrackingRequest(url, payload)));
|
|
3194
|
+
if (!this.repeatableEvents.has(eventType) && this.requestId && this.creativeId) {
|
|
3195
|
+
globalEventDeduplicator.markTracked(this.requestId, this.creativeId, eventType);
|
|
3196
|
+
}
|
|
3197
|
+
}
|
|
3198
|
+
async sendTrackingRequest(url, payload) {
|
|
3199
|
+
const headers = {
|
|
3200
|
+
"Content-Type": "application/json",
|
|
3201
|
+
...this.requestHeaders ?? {}
|
|
3202
|
+
};
|
|
3203
|
+
if (this.requestId) {
|
|
3204
|
+
headers["X-Toss-RequestId"] = this.requestId;
|
|
3205
|
+
}
|
|
3206
|
+
await fetch(url, {
|
|
3207
|
+
method: "POST",
|
|
3208
|
+
headers,
|
|
3209
|
+
body: JSON.stringify(payload)
|
|
3210
|
+
});
|
|
3211
|
+
}
|
|
3212
|
+
};
|
|
3213
|
+
|
|
3214
|
+
// src/ads/inlineAd/ui/FeedBannerAdView.tsx
|
|
3215
|
+
var import_react_native_svg = require("@granite-js/native/react-native-svg");
|
|
3216
|
+
var import_react29 = require("react");
|
|
3217
|
+
var import_react_native42 = require("react-native");
|
|
3218
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
3219
|
+
var ARROW_PATH = "m7.5 20.4c-.5-.5-.5-1.2 0-1.7l6.7-6.7-6.8-6.7c-.5-.5-.5-1.2 0-1.7s1.2-.5 1.7 0l7.5 7.5c.5.5.5 1.2 0 1.7l-7.5 7.5c-.2.3-.5.4-.8.4s-.6-.1-.8-.3z";
|
|
3220
|
+
function FeedBannerAdView({
|
|
3221
|
+
brandName,
|
|
3222
|
+
brandLogoUri,
|
|
3223
|
+
title,
|
|
3224
|
+
subtitle,
|
|
3225
|
+
mainImageUri,
|
|
3226
|
+
ctaText,
|
|
3227
|
+
ctaTextColor,
|
|
3228
|
+
ctaBackgroundColor,
|
|
3229
|
+
adClearanceText,
|
|
3230
|
+
colors,
|
|
3231
|
+
isAdBadgeEnabled,
|
|
3232
|
+
paddingStyle,
|
|
3233
|
+
onPress
|
|
3234
|
+
}) {
|
|
3235
|
+
const scale = (0, import_react29.useRef)(new import_react_native42.Animated.Value(1)).current;
|
|
3236
|
+
const animateScale = (toValue) => {
|
|
3237
|
+
import_react_native42.Animated.timing(scale, {
|
|
3238
|
+
toValue,
|
|
3239
|
+
duration: 100,
|
|
3240
|
+
easing: import_react_native42.Easing.inOut(import_react_native42.Easing.ease),
|
|
3241
|
+
useNativeDriver: true
|
|
3242
|
+
}).start();
|
|
3243
|
+
};
|
|
3244
|
+
const handlePressIn = () => {
|
|
3245
|
+
animateScale(0.98);
|
|
3246
|
+
};
|
|
3247
|
+
const handlePressOut = () => {
|
|
3248
|
+
animateScale(1);
|
|
3249
|
+
};
|
|
3250
|
+
const resolvedCtaBackground = ctaBackgroundColor ?? "#3081F9";
|
|
3251
|
+
const resolvedCtaTextColor = ctaTextColor ?? "#ffffff";
|
|
3252
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3253
|
+
import_react_native42.Pressable,
|
|
3254
|
+
{
|
|
3255
|
+
accessibilityRole: "button",
|
|
3256
|
+
onPress: () => onPress(null),
|
|
3257
|
+
onPressIn: handlePressIn,
|
|
3258
|
+
onPressOut: handlePressOut,
|
|
3259
|
+
style: styles.pressable,
|
|
3260
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react_native42.Animated.View, { style: [styles.container, paddingStyle, { transform: [{ scale }] }], children: [
|
|
3261
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react_native42.View, { style: styles.profileContainer, children: [
|
|
3262
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react_native42.View, { style: styles.brandArea, children: [
|
|
3263
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3264
|
+
import_react_native42.Pressable,
|
|
3265
|
+
{
|
|
3266
|
+
accessibilityRole: "button",
|
|
3267
|
+
onPress: () => onPress("202"),
|
|
3268
|
+
onPressIn: handlePressIn,
|
|
3269
|
+
onPressOut: handlePressOut,
|
|
3270
|
+
style: styles.logoContainer,
|
|
3271
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react_native42.View, { style: [styles.logoWrapper, { backgroundColor: colors.brandLogoBg }], children: [
|
|
3272
|
+
brandLogoUri ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native42.Image, { source: { uri: brandLogoUri }, style: styles.logoImage, resizeMode: "cover" }) : null,
|
|
3273
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native42.View, { style: [styles.logoOverlay, { borderColor: colors.brandLogoBorder }] })
|
|
3274
|
+
] })
|
|
3275
|
+
}
|
|
3276
|
+
),
|
|
3277
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react_native42.View, { style: styles.brandTextContainer, children: [
|
|
3278
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3279
|
+
import_react_native42.Pressable,
|
|
3280
|
+
{
|
|
3281
|
+
accessibilityRole: "button",
|
|
3282
|
+
onPress: () => onPress("103"),
|
|
3283
|
+
onPressIn: handlePressIn,
|
|
3284
|
+
onPressOut: handlePressOut,
|
|
3285
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native42.Text, { numberOfLines: 1, style: [styles.brandName, { color: colors.brandName }], children: brandName })
|
|
3286
|
+
}
|
|
3287
|
+
),
|
|
3288
|
+
isAdBadgeEnabled ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native42.Text, { numberOfLines: 1, style: [styles.adBadge, { color: colors.adBadge }], children: "\uAD11\uACE0" }) : null
|
|
3289
|
+
] })
|
|
3290
|
+
] }),
|
|
3291
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react_native42.View, { style: styles.textArea, children: [
|
|
3292
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3293
|
+
import_react_native42.Pressable,
|
|
3294
|
+
{
|
|
3295
|
+
accessibilityRole: "button",
|
|
3296
|
+
onPress: () => onPress("101"),
|
|
3297
|
+
onPressIn: handlePressIn,
|
|
3298
|
+
onPressOut: handlePressOut,
|
|
3299
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native42.Text, { style: [styles.title, { color: colors.title }], children: title })
|
|
3300
|
+
}
|
|
3301
|
+
),
|
|
3302
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3303
|
+
import_react_native42.Pressable,
|
|
3304
|
+
{
|
|
3305
|
+
accessibilityRole: "button",
|
|
3306
|
+
onPress: () => onPress("102"),
|
|
3307
|
+
onPressIn: handlePressIn,
|
|
3308
|
+
onPressOut: handlePressOut,
|
|
3309
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native42.Text, { style: [styles.subtitle, { color: colors.subtitle }], children: subtitle })
|
|
3310
|
+
}
|
|
3311
|
+
)
|
|
3312
|
+
] })
|
|
3313
|
+
] }),
|
|
3314
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react_native42.View, { style: styles.card, children: [
|
|
3315
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3316
|
+
import_react_native42.Pressable,
|
|
3317
|
+
{
|
|
3318
|
+
accessibilityRole: "button",
|
|
3319
|
+
onPress: () => onPress("201"),
|
|
3320
|
+
onPressIn: handlePressIn,
|
|
3321
|
+
onPressOut: handlePressOut,
|
|
3322
|
+
style: styles.imageButton,
|
|
3323
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native42.View, { style: styles.imageContainer, children: mainImageUri ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native42.Image, { source: { uri: mainImageUri }, style: styles.mainImage, resizeMode: "cover" }) : null })
|
|
2852
3324
|
}
|
|
2853
|
-
|
|
2854
|
-
|
|
3325
|
+
),
|
|
3326
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
3327
|
+
import_react_native42.Pressable,
|
|
3328
|
+
{
|
|
3329
|
+
accessibilityRole: "button",
|
|
3330
|
+
onPress: () => onPress("0"),
|
|
3331
|
+
onPressIn: handlePressIn,
|
|
3332
|
+
onPressOut: handlePressOut,
|
|
3333
|
+
style: [styles.cta, { backgroundColor: resolvedCtaBackground }],
|
|
3334
|
+
children: [
|
|
3335
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native42.Text, { style: [styles.ctaText, { color: resolvedCtaTextColor }], children: ctaText }),
|
|
3336
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native_svg.Svg, { width: 20, height: 20, viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native_svg.Path, { d: ARROW_PATH, fill: resolvedCtaTextColor }) })
|
|
3337
|
+
]
|
|
2855
3338
|
}
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
3339
|
+
),
|
|
3340
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native42.View, { style: [styles.cardOverlay, { borderColor: colors.imageOverlayBorder }] })
|
|
3341
|
+
] }),
|
|
3342
|
+
adClearanceText ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native42.Text, { style: [styles.adClearance, { color: colors.adClearance }], children: adClearanceText }) : null
|
|
3343
|
+
] })
|
|
3344
|
+
}
|
|
3345
|
+
);
|
|
3346
|
+
}
|
|
3347
|
+
var styles = import_react_native42.StyleSheet.create({
|
|
3348
|
+
pressable: {
|
|
3349
|
+
width: "100%"
|
|
3350
|
+
},
|
|
3351
|
+
container: {
|
|
3352
|
+
flexDirection: "column",
|
|
3353
|
+
padding: 0,
|
|
3354
|
+
width: "100%"
|
|
3355
|
+
},
|
|
3356
|
+
profileContainer: {
|
|
3357
|
+
flexDirection: "column",
|
|
3358
|
+
paddingBottom: 8,
|
|
3359
|
+
gap: 12
|
|
3360
|
+
},
|
|
3361
|
+
brandArea: {
|
|
3362
|
+
flexDirection: "row",
|
|
3363
|
+
alignItems: "center",
|
|
3364
|
+
gap: 8
|
|
3365
|
+
},
|
|
3366
|
+
logoContainer: {
|
|
3367
|
+
width: 40,
|
|
3368
|
+
height: 40,
|
|
3369
|
+
alignItems: "center",
|
|
3370
|
+
justifyContent: "center"
|
|
3371
|
+
},
|
|
3372
|
+
logoWrapper: {
|
|
3373
|
+
width: 36,
|
|
3374
|
+
height: 36,
|
|
3375
|
+
borderRadius: 18,
|
|
3376
|
+
overflow: "hidden",
|
|
3377
|
+
alignItems: "center",
|
|
3378
|
+
justifyContent: "center"
|
|
3379
|
+
},
|
|
3380
|
+
logoImage: {
|
|
3381
|
+
width: 36,
|
|
3382
|
+
height: 36,
|
|
3383
|
+
borderRadius: 18
|
|
3384
|
+
},
|
|
3385
|
+
logoOverlay: {
|
|
3386
|
+
...import_react_native42.StyleSheet.absoluteFillObject,
|
|
3387
|
+
borderWidth: 1,
|
|
3388
|
+
borderRadius: 18
|
|
3389
|
+
},
|
|
3390
|
+
brandTextContainer: {
|
|
3391
|
+
flexDirection: "column"
|
|
3392
|
+
},
|
|
3393
|
+
brandName: {
|
|
3394
|
+
fontSize: 15,
|
|
3395
|
+
fontWeight: "600",
|
|
3396
|
+
lineHeight: 22.5
|
|
3397
|
+
},
|
|
3398
|
+
adBadge: {
|
|
3399
|
+
fontSize: 13,
|
|
3400
|
+
fontWeight: "400",
|
|
3401
|
+
lineHeight: 19.5
|
|
3402
|
+
},
|
|
3403
|
+
textArea: {
|
|
3404
|
+
flexDirection: "column",
|
|
3405
|
+
alignItems: "flex-start"
|
|
3406
|
+
},
|
|
3407
|
+
title: {
|
|
3408
|
+
fontSize: 15,
|
|
3409
|
+
fontWeight: "600",
|
|
3410
|
+
lineHeight: 22.5
|
|
3411
|
+
},
|
|
3412
|
+
subtitle: {
|
|
3413
|
+
fontSize: 15,
|
|
3414
|
+
fontWeight: "400",
|
|
3415
|
+
lineHeight: 22.5
|
|
3416
|
+
},
|
|
3417
|
+
card: {
|
|
3418
|
+
borderRadius: 12,
|
|
3419
|
+
overflow: "hidden",
|
|
3420
|
+
position: "relative",
|
|
3421
|
+
width: "100%"
|
|
3422
|
+
},
|
|
3423
|
+
imageButton: {
|
|
3424
|
+
width: "100%"
|
|
3425
|
+
},
|
|
3426
|
+
imageContainer: {
|
|
3427
|
+
width: "100%",
|
|
3428
|
+
aspectRatio: 16 / 9,
|
|
3429
|
+
overflow: "hidden"
|
|
3430
|
+
},
|
|
3431
|
+
mainImage: {
|
|
3432
|
+
width: "100%",
|
|
3433
|
+
height: "100%"
|
|
3434
|
+
},
|
|
3435
|
+
cta: {
|
|
3436
|
+
height: 50,
|
|
3437
|
+
paddingLeft: 20,
|
|
3438
|
+
paddingRight: 16,
|
|
3439
|
+
alignItems: "center",
|
|
3440
|
+
justifyContent: "space-between",
|
|
3441
|
+
flexDirection: "row"
|
|
3442
|
+
},
|
|
3443
|
+
ctaText: {
|
|
3444
|
+
fontSize: 15,
|
|
3445
|
+
fontWeight: "600",
|
|
3446
|
+
lineHeight: 22.5
|
|
3447
|
+
},
|
|
3448
|
+
cardOverlay: {
|
|
3449
|
+
...import_react_native42.StyleSheet.absoluteFillObject,
|
|
3450
|
+
borderWidth: 2,
|
|
3451
|
+
borderRadius: 12,
|
|
3452
|
+
pointerEvents: "none"
|
|
3453
|
+
},
|
|
3454
|
+
adClearance: {
|
|
3455
|
+
marginTop: 10,
|
|
3456
|
+
fontSize: 8,
|
|
3457
|
+
fontWeight: "400"
|
|
3458
|
+
}
|
|
3459
|
+
});
|
|
3460
|
+
|
|
3461
|
+
// src/ads/inlineAd/ui/ListBannerAdView.tsx
|
|
3462
|
+
var import_react_native_svg2 = require("@granite-js/native/react-native-svg");
|
|
3463
|
+
var import_react30 = require("react");
|
|
3464
|
+
var import_react_native43 = require("react-native");
|
|
3465
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
3466
|
+
var SQUIRCLE_PATH = "M0 17.352C0 3.564 3.564 0 17.352 0H18.648C32.436 0 36 3.564 36 17.352V18.648C36 32.436 32.436 36 18.648 36H17.352C3.564 36 0 32.436 0 18.648V17.352Z";
|
|
3467
|
+
function ListBannerAdView({
|
|
3468
|
+
title,
|
|
3469
|
+
subtitle,
|
|
3470
|
+
adClearanceText,
|
|
3471
|
+
adClearanceFontSize,
|
|
3472
|
+
imageUri,
|
|
3473
|
+
paddingStyle,
|
|
3474
|
+
colors,
|
|
3475
|
+
onPress
|
|
3476
|
+
}) {
|
|
3477
|
+
const scale = (0, import_react30.useRef)(new import_react_native43.Animated.Value(1)).current;
|
|
3478
|
+
const clipIdRef = (0, import_react30.useRef)(`clip-${Math.random().toString(36).slice(2)}`);
|
|
3479
|
+
const animateScale = (toValue) => {
|
|
3480
|
+
import_react_native43.Animated.timing(scale, {
|
|
3481
|
+
toValue,
|
|
3482
|
+
duration: 100,
|
|
3483
|
+
easing: import_react_native43.Easing.inOut(import_react_native43.Easing.ease),
|
|
3484
|
+
useNativeDriver: true
|
|
3485
|
+
}).start();
|
|
3486
|
+
};
|
|
3487
|
+
const handlePressIn = () => {
|
|
3488
|
+
animateScale(0.96);
|
|
3489
|
+
};
|
|
3490
|
+
const handlePressOut = () => {
|
|
3491
|
+
animateScale(1);
|
|
3492
|
+
};
|
|
3493
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3494
|
+
import_react_native43.Pressable,
|
|
3495
|
+
{
|
|
3496
|
+
accessibilityRole: "button",
|
|
3497
|
+
onPress: () => onPress(null),
|
|
3498
|
+
onPressIn: handlePressIn,
|
|
3499
|
+
onPressOut: handlePressOut,
|
|
3500
|
+
style: styles2.pressable,
|
|
3501
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react_native43.Animated.View, { style: [styles2.container, paddingStyle, { transform: [{ scale }] }], children: [
|
|
3502
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react_native43.View, { style: styles2.titleRow, children: [
|
|
3503
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3504
|
+
import_react_native43.Pressable,
|
|
3505
|
+
{
|
|
3506
|
+
accessibilityRole: "button",
|
|
3507
|
+
onPress: () => onPress("202"),
|
|
3508
|
+
onPressIn: handlePressIn,
|
|
3509
|
+
onPressOut: handlePressOut,
|
|
3510
|
+
style: styles2.iconWrapper,
|
|
3511
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react_native_svg2.Svg, { width: 36, height: 36, viewBox: "0 0 36 36", children: [
|
|
3512
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_native_svg2.Defs, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_native_svg2.ClipPath, { id: clipIdRef.current, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_native_svg2.Path, { d: SQUIRCLE_PATH }) }) }),
|
|
3513
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_native_svg2.Path, { d: SQUIRCLE_PATH, fill: colors.iconBg }),
|
|
3514
|
+
imageUri ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3515
|
+
import_react_native_svg2.Image,
|
|
3516
|
+
{
|
|
3517
|
+
href: { uri: imageUri },
|
|
3518
|
+
width: 36,
|
|
3519
|
+
height: 36,
|
|
3520
|
+
preserveAspectRatio: "xMidYMid slice",
|
|
3521
|
+
clipPath: `url(#${clipIdRef.current})`
|
|
3522
|
+
}
|
|
3523
|
+
) : null,
|
|
3524
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3525
|
+
import_react_native_svg2.Path,
|
|
3526
|
+
{
|
|
3527
|
+
d: SQUIRCLE_PATH,
|
|
3528
|
+
fill: "none",
|
|
3529
|
+
stroke: colors.iconBorder,
|
|
3530
|
+
strokeWidth: 2,
|
|
3531
|
+
clipPath: `url(#${clipIdRef.current})`
|
|
3532
|
+
}
|
|
3533
|
+
)
|
|
3534
|
+
] })
|
|
2859
3535
|
}
|
|
2860
|
-
|
|
2861
|
-
|
|
3536
|
+
),
|
|
3537
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react_native43.View, { style: styles2.textWrapper, children: [
|
|
3538
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3539
|
+
import_react_native43.Pressable,
|
|
3540
|
+
{
|
|
3541
|
+
accessibilityRole: "button",
|
|
3542
|
+
onPress: () => onPress("101"),
|
|
3543
|
+
onPressIn: handlePressIn,
|
|
3544
|
+
onPressOut: handlePressOut,
|
|
3545
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_native43.Text, { style: [styles2.title, { color: colors.title }], children: title })
|
|
3546
|
+
}
|
|
3547
|
+
),
|
|
3548
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3549
|
+
import_react_native43.Pressable,
|
|
3550
|
+
{
|
|
3551
|
+
accessibilityRole: "button",
|
|
3552
|
+
onPress: () => onPress("102"),
|
|
3553
|
+
onPressIn: handlePressIn,
|
|
3554
|
+
onPressOut: handlePressOut,
|
|
3555
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_native43.Text, { style: [styles2.subtitle, { color: colors.subtitle }], children: subtitle })
|
|
3556
|
+
}
|
|
3557
|
+
)
|
|
3558
|
+
] })
|
|
3559
|
+
] }),
|
|
3560
|
+
adClearanceText ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3561
|
+
import_react_native43.Text,
|
|
3562
|
+
{
|
|
3563
|
+
style: [
|
|
3564
|
+
styles2.adClearance,
|
|
3565
|
+
{
|
|
3566
|
+
color: colors.adClearance,
|
|
3567
|
+
fontSize: adClearanceFontSize,
|
|
3568
|
+
lineHeight: adClearanceFontSize * 1.2
|
|
3569
|
+
}
|
|
3570
|
+
],
|
|
3571
|
+
children: adClearanceText
|
|
2862
3572
|
}
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
3573
|
+
) : null
|
|
3574
|
+
] })
|
|
3575
|
+
}
|
|
3576
|
+
);
|
|
3577
|
+
}
|
|
3578
|
+
var styles2 = import_react_native43.StyleSheet.create({
|
|
3579
|
+
pressable: {
|
|
3580
|
+
width: "100%"
|
|
3581
|
+
},
|
|
3582
|
+
container: {
|
|
3583
|
+
flexDirection: "column",
|
|
3584
|
+
padding: 0,
|
|
3585
|
+
width: "100%"
|
|
3586
|
+
},
|
|
3587
|
+
titleRow: {
|
|
3588
|
+
flexDirection: "row",
|
|
3589
|
+
alignItems: "center"
|
|
3590
|
+
},
|
|
3591
|
+
iconWrapper: {
|
|
3592
|
+
width: 36,
|
|
3593
|
+
height: 36,
|
|
3594
|
+
overflow: "hidden",
|
|
3595
|
+
alignItems: "center",
|
|
3596
|
+
justifyContent: "center",
|
|
3597
|
+
marginRight: 12
|
|
3598
|
+
},
|
|
3599
|
+
textWrapper: {
|
|
3600
|
+
flex: 1,
|
|
3601
|
+
flexDirection: "column",
|
|
3602
|
+
alignItems: "flex-start",
|
|
3603
|
+
justifyContent: "center",
|
|
3604
|
+
width: "100%"
|
|
3605
|
+
},
|
|
3606
|
+
title: {
|
|
3607
|
+
fontSize: 17,
|
|
3608
|
+
fontWeight: "700",
|
|
3609
|
+
lineHeight: 25.5
|
|
3610
|
+
},
|
|
3611
|
+
subtitle: {
|
|
3612
|
+
fontSize: 13,
|
|
3613
|
+
fontWeight: "500",
|
|
3614
|
+
flexShrink: 1,
|
|
3615
|
+
lineHeight: 15.6
|
|
3616
|
+
},
|
|
3617
|
+
adClearance: {
|
|
3618
|
+
marginTop: 8,
|
|
3619
|
+
paddingLeft: 48,
|
|
3620
|
+
width: "100%"
|
|
3621
|
+
}
|
|
3622
|
+
});
|
|
3623
|
+
|
|
3624
|
+
// src/ads/inlineAd/utils/ids.ts
|
|
3625
|
+
var slotCounter = 0;
|
|
3626
|
+
function createSlotId() {
|
|
3627
|
+
slotCounter += 1;
|
|
3628
|
+
return `banner-slot-${Date.now()}-${slotCounter}`;
|
|
3629
|
+
}
|
|
3630
|
+
|
|
3631
|
+
// src/ads/inlineAd/utils/padding.ts
|
|
3632
|
+
function resolvePaddingStyle(padding) {
|
|
3633
|
+
if (padding === void 0) {
|
|
3634
|
+
return void 0;
|
|
3635
|
+
}
|
|
3636
|
+
if (typeof padding === "number") {
|
|
3637
|
+
return { padding };
|
|
3638
|
+
}
|
|
3639
|
+
const trimmed = padding.trim();
|
|
3640
|
+
if (!trimmed) {
|
|
3641
|
+
return void 0;
|
|
3642
|
+
}
|
|
3643
|
+
const parts = trimmed.split(/\s+/);
|
|
3644
|
+
if (parts.length < 1 || parts.length > 4) {
|
|
3645
|
+
return void 0;
|
|
3646
|
+
}
|
|
3647
|
+
const values = parts.map((part) => {
|
|
3648
|
+
const normalized = part.endsWith("px") ? part.slice(0, -2).trim() : part;
|
|
3649
|
+
const numeric = Number(normalized);
|
|
3650
|
+
return Number.isFinite(numeric) ? numeric : null;
|
|
3651
|
+
});
|
|
3652
|
+
if (values.some((value) => value === null)) {
|
|
3653
|
+
return void 0;
|
|
3654
|
+
}
|
|
3655
|
+
const [top, right, bottom, left] = normalizePaddingValues(values);
|
|
3656
|
+
return {
|
|
3657
|
+
paddingTop: top,
|
|
3658
|
+
paddingRight: right,
|
|
3659
|
+
paddingBottom: bottom,
|
|
3660
|
+
paddingLeft: left
|
|
3661
|
+
};
|
|
3662
|
+
}
|
|
3663
|
+
function normalizePaddingValues(values) {
|
|
3664
|
+
const [top = 0, right = top, bottom = top, left = right] = values;
|
|
3665
|
+
return [top, right, bottom, left];
|
|
3666
|
+
}
|
|
3667
|
+
|
|
3668
|
+
// src/ads/inlineAd/utils/payload.ts
|
|
3669
|
+
function buildBannerEventPayload(slotId, adGroupId, ad) {
|
|
2870
3670
|
return {
|
|
2871
|
-
|
|
2872
|
-
|
|
3671
|
+
slotId,
|
|
3672
|
+
adGroupId,
|
|
3673
|
+
adMetadata: {
|
|
3674
|
+
creativeId: ad.creative?.id ?? "",
|
|
3675
|
+
requestId: ad.requestId ?? "",
|
|
3676
|
+
styleId: ad.styleId ?? LIST_BANNER_STYLE_ID
|
|
3677
|
+
}
|
|
2873
3678
|
};
|
|
2874
3679
|
}
|
|
2875
|
-
function
|
|
2876
|
-
return
|
|
3680
|
+
function buildBannerErrorPayload(slotId, adGroupId, error) {
|
|
3681
|
+
return {
|
|
3682
|
+
slotId,
|
|
3683
|
+
adGroupId,
|
|
3684
|
+
adMetadata: {},
|
|
3685
|
+
error
|
|
3686
|
+
};
|
|
3687
|
+
}
|
|
3688
|
+
function buildNoFillPayload(slotId, adGroupId) {
|
|
3689
|
+
return {
|
|
3690
|
+
slotId,
|
|
3691
|
+
adGroupId,
|
|
3692
|
+
adMetadata: {}
|
|
3693
|
+
};
|
|
3694
|
+
}
|
|
3695
|
+
|
|
3696
|
+
// src/ads/inlineAd/InlineAd.tsx
|
|
3697
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
3698
|
+
var themePalette = {
|
|
3699
|
+
light: {
|
|
3700
|
+
title: "#4e5968",
|
|
3701
|
+
subtitle: "#6b7684",
|
|
3702
|
+
adClearance: "#b0b8c1",
|
|
3703
|
+
iconBg: "rgba(2,32,71,0.05)",
|
|
3704
|
+
iconBorder: "rgba(2,32,71,0.05)"
|
|
3705
|
+
},
|
|
3706
|
+
dark: {
|
|
3707
|
+
title: "rgba(253,253,255,0.75)",
|
|
3708
|
+
subtitle: "rgba(248,248,255,0.6)",
|
|
3709
|
+
adClearance: "rgba(242,242,255,0.47)",
|
|
3710
|
+
iconBg: "#ffffff",
|
|
3711
|
+
iconBorder: "rgba(217,217,255,0.11)"
|
|
3712
|
+
}
|
|
3713
|
+
};
|
|
3714
|
+
var feedThemePalette = {
|
|
3715
|
+
light: {
|
|
3716
|
+
brandLogoBg: "rgba(2,32,71,0.05)",
|
|
3717
|
+
brandLogoBorder: "rgba(2,32,71,0.05)",
|
|
3718
|
+
brandName: "#6b7684",
|
|
3719
|
+
adBadge: "#8b95a1",
|
|
3720
|
+
title: "#333d4b",
|
|
3721
|
+
subtitle: "#4e5968",
|
|
3722
|
+
adClearance: "#8b95a1",
|
|
3723
|
+
imageOverlayBorder: "rgba(2,32,71,0.05)"
|
|
3724
|
+
},
|
|
3725
|
+
dark: {
|
|
3726
|
+
brandLogoBg: "#ffffff",
|
|
3727
|
+
brandLogoBorder: "rgba(217,217,255,0.11)",
|
|
3728
|
+
brandName: "#9e9ea4",
|
|
3729
|
+
adBadge: "#7e7e87",
|
|
3730
|
+
title: "#e4e4e5",
|
|
3731
|
+
subtitle: "#c3c3c6",
|
|
3732
|
+
adClearance: "#7e7e87",
|
|
3733
|
+
imageOverlayBorder: "rgba(217,217,255,0.11)"
|
|
3734
|
+
}
|
|
3735
|
+
};
|
|
3736
|
+
function createError2(code, message) {
|
|
3737
|
+
return {
|
|
3738
|
+
code,
|
|
3739
|
+
message: message || ERROR_MESSAGES[code] || "Unknown error",
|
|
3740
|
+
domain: "@apps-in-toss/framework"
|
|
3741
|
+
};
|
|
3742
|
+
}
|
|
3743
|
+
function isListBannerCreative(creative) {
|
|
3744
|
+
return Boolean(
|
|
3745
|
+
creative && typeof creative.title === "string" && typeof creative.subTitle === "string" && typeof creative.landingUrl === "string" && typeof creative.imageUrl === "string"
|
|
3746
|
+
);
|
|
3747
|
+
}
|
|
3748
|
+
function isFeedBannerCreative(creative) {
|
|
3749
|
+
if (!creative || typeof creative !== "object") {
|
|
3750
|
+
return false;
|
|
3751
|
+
}
|
|
3752
|
+
if (!("brandName" in creative)) {
|
|
3753
|
+
return false;
|
|
3754
|
+
}
|
|
3755
|
+
const candidate = creative;
|
|
3756
|
+
return Boolean(
|
|
3757
|
+
typeof candidate.brandName === "string" && typeof candidate.brandLogoUrl === "string" && typeof candidate.title === "string" && typeof candidate.subTitle === "string" && typeof candidate.mainImageUrl === "string" && typeof candidate.ctaText === "string" && typeof candidate.landingUrl === "string"
|
|
3758
|
+
);
|
|
3759
|
+
}
|
|
3760
|
+
function isValidCreative(ad) {
|
|
3761
|
+
const creative = ad.creative;
|
|
3762
|
+
const styleId = String(ad.styleId);
|
|
3763
|
+
if (styleId === LIST_BANNER_STYLE_ID) {
|
|
3764
|
+
return isListBannerCreative(creative);
|
|
3765
|
+
}
|
|
3766
|
+
if (styleId === FEED_BANNER_STYLE_ID) {
|
|
3767
|
+
return isFeedBannerCreative(creative);
|
|
3768
|
+
}
|
|
3769
|
+
return false;
|
|
3770
|
+
}
|
|
3771
|
+
function InlineAd(props) {
|
|
3772
|
+
const {
|
|
3773
|
+
adGroupId,
|
|
3774
|
+
theme,
|
|
3775
|
+
tone,
|
|
3776
|
+
variant,
|
|
3777
|
+
impressFallbackOnMount,
|
|
3778
|
+
onAdRendered,
|
|
3779
|
+
onAdViewable,
|
|
3780
|
+
onAdClicked,
|
|
3781
|
+
onAdImpression,
|
|
3782
|
+
onAdFailedToRender,
|
|
3783
|
+
onNoFill
|
|
3784
|
+
} = props;
|
|
3785
|
+
const slotIdRef = (0, import_react31.useRef)(createSlotId());
|
|
3786
|
+
const [ad, setAd] = (0, import_react31.useState)(null);
|
|
3787
|
+
const [isAdBadgeEnabled, setIsAdBadgeEnabled] = (0, import_react31.useState)(true);
|
|
3788
|
+
const eventTrackerRef = (0, import_react31.useRef)(null);
|
|
3789
|
+
const eventPayloadRef = (0, import_react31.useRef)(null);
|
|
3790
|
+
const hasRenderedRef = (0, import_react31.useRef)(false);
|
|
3791
|
+
const hasLoggedImp1pxRef = (0, import_react31.useRef)(false);
|
|
3792
|
+
const hasLoggedImp100pRef = (0, import_react31.useRef)(false);
|
|
3793
|
+
const hasNotifiedViewableRef = (0, import_react31.useRef)(false);
|
|
3794
|
+
const viewableTimerRef = (0, import_react31.useRef)(null);
|
|
3795
|
+
const refetchIntervalMsRef = (0, import_react31.useRef)(null);
|
|
3796
|
+
const lastImp1pxAtRef = (0, import_react31.useRef)(null);
|
|
3797
|
+
const loadingRef = (0, import_react31.useRef)(false);
|
|
3798
|
+
const loadRef = (0, import_react31.useRef)(null);
|
|
3799
|
+
const callbacksRef = (0, import_react31.useRef)({
|
|
3800
|
+
onAdRendered,
|
|
3801
|
+
onAdViewable,
|
|
3802
|
+
onAdClicked,
|
|
3803
|
+
onAdImpression,
|
|
3804
|
+
onAdFailedToRender,
|
|
3805
|
+
onNoFill
|
|
3806
|
+
});
|
|
3807
|
+
const isMountedRef = (0, import_react31.useRef)(false);
|
|
3808
|
+
const colorScheme = (0, import_react_native45.useColorScheme)();
|
|
3809
|
+
const selectedTheme = theme ?? DEFAULT_INLINE_AD_THEME;
|
|
3810
|
+
const resolvedTheme = selectedTheme === "auto" ? colorScheme === "dark" ? "dark" : "light" : selectedTheme;
|
|
3811
|
+
const resolvedTone = tone ?? DEFAULT_INLINE_AD_TONE;
|
|
3812
|
+
const resolvedVariant = variant ?? DEFAULT_INLINE_AD_VARIANT;
|
|
3813
|
+
const colors = themePalette[resolvedTheme];
|
|
3814
|
+
const feedColors = feedThemePalette[resolvedTheme];
|
|
3815
|
+
const backgroundColor = resolvedTone === "grey" ? resolvedTheme === "dark" ? "#101013" : "#f2f4f7" : resolvedTheme === "dark" ? "#17171c" : "#ffffff";
|
|
3816
|
+
callbacksRef.current = {
|
|
3817
|
+
onAdRendered,
|
|
3818
|
+
onAdViewable,
|
|
3819
|
+
onAdClicked,
|
|
3820
|
+
onAdImpression,
|
|
3821
|
+
onAdFailedToRender,
|
|
3822
|
+
onNoFill
|
|
3823
|
+
};
|
|
3824
|
+
(0, import_react31.useEffect)(() => {
|
|
3825
|
+
isMountedRef.current = true;
|
|
3826
|
+
return () => {
|
|
3827
|
+
isMountedRef.current = false;
|
|
3828
|
+
if (viewableTimerRef.current) {
|
|
3829
|
+
clearTimeout(viewableTimerRef.current);
|
|
3830
|
+
viewableTimerRef.current = null;
|
|
3831
|
+
}
|
|
3832
|
+
};
|
|
3833
|
+
}, []);
|
|
3834
|
+
(0, import_react31.useEffect)(() => {
|
|
3835
|
+
const loadAdRequest = () => {
|
|
3836
|
+
if (loadingRef.current) {
|
|
3837
|
+
return;
|
|
3838
|
+
}
|
|
3839
|
+
if (!adGroupId) {
|
|
3840
|
+
const error = createError2(
|
|
3841
|
+
ERROR_CODES.INVALID_SPACE,
|
|
3842
|
+
`${ERROR_MESSAGES[ERROR_CODES.INVALID_SPACE]} - adGroupId must be provided`
|
|
3843
|
+
);
|
|
3844
|
+
callbacksRef.current.onAdFailedToRender?.(buildBannerErrorPayload(slotIdRef.current, adGroupId, error));
|
|
3845
|
+
return;
|
|
3846
|
+
}
|
|
3847
|
+
loadingRef.current = true;
|
|
3848
|
+
loadAd(adGroupId).then((result) => {
|
|
3849
|
+
if (!isMountedRef.current) return;
|
|
3850
|
+
if (result.type === "noFill") {
|
|
3851
|
+
callbacksRef.current.onNoFill?.(buildNoFillPayload(slotIdRef.current, adGroupId));
|
|
3852
|
+
return;
|
|
3853
|
+
}
|
|
3854
|
+
if (result.type === "error") {
|
|
3855
|
+
callbacksRef.current.onAdFailedToRender?.(
|
|
3856
|
+
buildBannerErrorPayload(slotIdRef.current, adGroupId, result.error)
|
|
3857
|
+
);
|
|
3858
|
+
return;
|
|
3859
|
+
}
|
|
3860
|
+
if (!isValidCreative(result.ad)) {
|
|
3861
|
+
const invalidError = createError2(ERROR_CODES.INTERNAL_ERROR, "Invalid creative payload");
|
|
3862
|
+
callbacksRef.current.onAdFailedToRender?.(
|
|
3863
|
+
buildBannerErrorPayload(slotIdRef.current, adGroupId, invalidError)
|
|
3864
|
+
);
|
|
3865
|
+
return;
|
|
3866
|
+
}
|
|
3867
|
+
if (result.responseExt?.refetchSeconds !== void 0) {
|
|
3868
|
+
refetchIntervalMsRef.current = typeof result.responseExt.refetchSeconds === "number" && result.responseExt.refetchSeconds > 0 ? result.responseExt.refetchSeconds * 1e3 : null;
|
|
3869
|
+
}
|
|
3870
|
+
hasRenderedRef.current = false;
|
|
3871
|
+
hasLoggedImp1pxRef.current = false;
|
|
3872
|
+
hasLoggedImp100pRef.current = false;
|
|
3873
|
+
hasNotifiedViewableRef.current = false;
|
|
3874
|
+
lastImp1pxAtRef.current = null;
|
|
3875
|
+
if (viewableTimerRef.current) {
|
|
3876
|
+
clearTimeout(viewableTimerRef.current);
|
|
3877
|
+
viewableTimerRef.current = null;
|
|
3878
|
+
}
|
|
3879
|
+
const payload = buildBannerEventPayload(slotIdRef.current, adGroupId, result.ad);
|
|
3880
|
+
eventPayloadRef.current = payload;
|
|
3881
|
+
eventTrackerRef.current = new EventTracker(
|
|
3882
|
+
result.ad.eventTrackingUrls ?? [],
|
|
3883
|
+
result.ad.eventTypes ?? [],
|
|
3884
|
+
result.ad.eventPayload ?? "",
|
|
3885
|
+
result.requestId,
|
|
3886
|
+
result.ad.creative?.id
|
|
3887
|
+
);
|
|
3888
|
+
setIsAdBadgeEnabled(result.responseExt?.isAdBadgeEnabled !== false);
|
|
3889
|
+
setAd(result.ad);
|
|
3890
|
+
}).catch((error) => {
|
|
3891
|
+
if (!isMountedRef.current) return;
|
|
3892
|
+
const adError = error instanceof Error ? createError2(ERROR_CODES.INTERNAL_ERROR, error.message) : createError2(ERROR_CODES.INTERNAL_ERROR, "Unknown error");
|
|
3893
|
+
callbacksRef.current.onAdFailedToRender?.(buildBannerErrorPayload(slotIdRef.current, adGroupId, adError));
|
|
3894
|
+
}).finally(() => {
|
|
3895
|
+
loadingRef.current = false;
|
|
3896
|
+
});
|
|
3897
|
+
};
|
|
3898
|
+
loadRef.current = loadAdRequest;
|
|
3899
|
+
loadAdRequest();
|
|
3900
|
+
return () => {
|
|
3901
|
+
loadRef.current = null;
|
|
3902
|
+
};
|
|
3903
|
+
}, [adGroupId]);
|
|
3904
|
+
(0, import_react_native44.useVisibilityChange)((documentVisibility) => {
|
|
3905
|
+
if (documentVisibility !== "visible") {
|
|
3906
|
+
return;
|
|
3907
|
+
}
|
|
3908
|
+
const interval = refetchIntervalMsRef.current;
|
|
3909
|
+
const lastImp1pxAt = lastImp1pxAtRef.current;
|
|
3910
|
+
if (!interval || !lastImp1pxAt || loadingRef.current) {
|
|
3911
|
+
return;
|
|
3912
|
+
}
|
|
3913
|
+
if (Date.now() - lastImp1pxAt >= interval) {
|
|
3914
|
+
loadRef.current?.();
|
|
3915
|
+
}
|
|
3916
|
+
});
|
|
3917
|
+
(0, import_react31.useEffect)(() => {
|
|
3918
|
+
if (!ad || hasRenderedRef.current) {
|
|
3919
|
+
return;
|
|
3920
|
+
}
|
|
3921
|
+
hasRenderedRef.current = true;
|
|
3922
|
+
const payload = eventPayloadRef.current;
|
|
3923
|
+
if (payload) {
|
|
3924
|
+
callbacksRef.current.onAdRendered?.(payload);
|
|
3925
|
+
}
|
|
3926
|
+
}, [ad]);
|
|
3927
|
+
if (!ad) {
|
|
3928
|
+
return null;
|
|
3929
|
+
}
|
|
3930
|
+
const impressionKey = `${ad.requestId ?? "request"}:${ad.creative?.id ?? "creative"}`;
|
|
3931
|
+
const resolvedStyleId = ad.styleId || LIST_BANNER_STYLE_ID;
|
|
3932
|
+
const defaultPaddingValue = resolvedStyleId === LIST_BANNER_STYLE_ID ? DEFAULT_INLINE_AD_PADDING_BANNER : DEFAULT_INLINE_AD_PADDING_NATIVE_IMAGE;
|
|
3933
|
+
const paddingStyle = resolvePaddingStyle(defaultPaddingValue);
|
|
3934
|
+
const isListBanner = String(resolvedStyleId) === LIST_BANNER_STYLE_ID;
|
|
3935
|
+
const isFeedBanner = String(resolvedStyleId) === FEED_BANNER_STYLE_ID;
|
|
3936
|
+
const listCreative = isListBanner ? ad.creative : null;
|
|
3937
|
+
const feedCreative = isFeedBanner ? ad.creative : null;
|
|
3938
|
+
const subtitleText = listCreative && isAdBadgeEnabled ? `${listCreative.subTitle} \u2022 AD` : listCreative?.subTitle ?? "";
|
|
3939
|
+
const adClearanceText = listCreative?.adClearanceText ?? feedCreative?.adClearanceText ?? void 0;
|
|
3940
|
+
const adClearanceFontSize = adClearanceText && adClearanceText.length >= 60 ? 6 : 8;
|
|
3941
|
+
const imageUri = listCreative?.imageUrl && isSafeUrl(listCreative.imageUrl) ? listCreative.imageUrl : null;
|
|
3942
|
+
const brandLogoUri = feedCreative?.brandLogoUrl && isSafeUrl(feedCreative.brandLogoUrl) ? feedCreative.brandLogoUrl : null;
|
|
3943
|
+
const mainImageUri = feedCreative?.mainImageUrl && isSafeUrl(feedCreative.mainImageUrl) ? feedCreative.mainImageUrl : null;
|
|
3944
|
+
const basePayload = eventPayloadRef.current;
|
|
3945
|
+
const trackEvent = (eventType) => {
|
|
3946
|
+
eventTrackerRef.current?.track(eventType).catch((error) => {
|
|
3947
|
+
console.error("[InlineAd] Failed to track event:", error);
|
|
3948
|
+
});
|
|
3949
|
+
};
|
|
3950
|
+
const handleImpression1px = () => {
|
|
3951
|
+
if (hasLoggedImp1pxRef.current) return;
|
|
3952
|
+
hasLoggedImp1pxRef.current = true;
|
|
3953
|
+
lastImp1pxAtRef.current = Date.now();
|
|
3954
|
+
trackEvent("IMP_1PX");
|
|
3955
|
+
if (basePayload) {
|
|
3956
|
+
void tossAdEventLog({
|
|
3957
|
+
log_name: "display_ads_all::impression__1px_banner",
|
|
3958
|
+
log_type: "event",
|
|
3959
|
+
params: {
|
|
3960
|
+
event_type: "impression",
|
|
3961
|
+
schema_id: 1812034,
|
|
3962
|
+
request_id: basePayload.adMetadata.requestId ?? ""
|
|
3963
|
+
}
|
|
3964
|
+
});
|
|
3965
|
+
callbacksRef.current.onAdImpression?.(basePayload);
|
|
3966
|
+
}
|
|
3967
|
+
};
|
|
3968
|
+
const handleImpression100p = () => {
|
|
3969
|
+
if (hasLoggedImp100pRef.current) return;
|
|
3970
|
+
hasLoggedImp100pRef.current = true;
|
|
3971
|
+
trackEvent("IMP_100P");
|
|
3972
|
+
};
|
|
3973
|
+
const handleViewableStart = () => {
|
|
3974
|
+
if (hasNotifiedViewableRef.current || viewableTimerRef.current) return;
|
|
3975
|
+
viewableTimerRef.current = setTimeout(() => {
|
|
3976
|
+
hasNotifiedViewableRef.current = true;
|
|
3977
|
+
viewableTimerRef.current = null;
|
|
3978
|
+
trackEvent("VIMP");
|
|
3979
|
+
if (basePayload) {
|
|
3980
|
+
callbacksRef.current.onAdViewable?.(basePayload);
|
|
3981
|
+
}
|
|
3982
|
+
}, 1e3);
|
|
3983
|
+
};
|
|
3984
|
+
const handleViewableEnd = () => {
|
|
3985
|
+
if (viewableTimerRef.current) {
|
|
3986
|
+
clearTimeout(viewableTimerRef.current);
|
|
3987
|
+
viewableTimerRef.current = null;
|
|
3988
|
+
}
|
|
3989
|
+
};
|
|
3990
|
+
const handleClick = (slotKey) => {
|
|
3991
|
+
trackEvent("CLICK");
|
|
3992
|
+
if (slotKey != null) {
|
|
3993
|
+
trackEvent(`CLICK_${slotKey}`);
|
|
3994
|
+
}
|
|
3995
|
+
if (isSafeUrl(ad.creative.landingUrl)) {
|
|
3996
|
+
openLandingUrl(ad.creative.landingUrl);
|
|
3997
|
+
}
|
|
3998
|
+
if (basePayload) {
|
|
3999
|
+
callbacksRef.current.onAdClicked?.(basePayload);
|
|
4000
|
+
}
|
|
4001
|
+
};
|
|
4002
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4003
|
+
import_react_native44.ImpressionArea,
|
|
4004
|
+
{
|
|
4005
|
+
style: styles3.impressionArea,
|
|
4006
|
+
onImpressionStart: handleImpression1px,
|
|
4007
|
+
areaThreshold: 0,
|
|
4008
|
+
UNSAFE__impressFallbackOnMount: Boolean(impressFallbackOnMount),
|
|
4009
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4010
|
+
import_react_native44.ImpressionArea,
|
|
4011
|
+
{
|
|
4012
|
+
onImpressionStart: handleImpression100p,
|
|
4013
|
+
areaThreshold: 1,
|
|
4014
|
+
UNSAFE__impressFallbackOnMount: Boolean(impressFallbackOnMount),
|
|
4015
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4016
|
+
import_react_native44.ImpressionArea,
|
|
4017
|
+
{
|
|
4018
|
+
onImpressionStart: handleViewableStart,
|
|
4019
|
+
onImpressionEnd: handleViewableEnd,
|
|
4020
|
+
areaThreshold: 0.5,
|
|
4021
|
+
UNSAFE__impressFallbackOnMount: Boolean(impressFallbackOnMount),
|
|
4022
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native45.View, { style: [styles3.wrapper, resolvedVariant === "card" && styles3.cardWrapper], children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native45.View, { style: [styles3.surface, { backgroundColor }, resolvedVariant === "card" && styles3.cardSurface], children: [
|
|
4023
|
+
isListBanner && listCreative ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4024
|
+
ListBannerAdView,
|
|
4025
|
+
{
|
|
4026
|
+
title: listCreative.title,
|
|
4027
|
+
subtitle: subtitleText,
|
|
4028
|
+
adClearanceText,
|
|
4029
|
+
adClearanceFontSize,
|
|
4030
|
+
imageUri,
|
|
4031
|
+
paddingStyle,
|
|
4032
|
+
colors,
|
|
4033
|
+
onPress: handleClick
|
|
4034
|
+
}
|
|
4035
|
+
) : null,
|
|
4036
|
+
isFeedBanner && feedCreative ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4037
|
+
FeedBannerAdView,
|
|
4038
|
+
{
|
|
4039
|
+
brandName: feedCreative.brandName,
|
|
4040
|
+
brandLogoUri,
|
|
4041
|
+
title: feedCreative.title,
|
|
4042
|
+
subtitle: feedCreative.subTitle,
|
|
4043
|
+
mainImageUri,
|
|
4044
|
+
ctaText: feedCreative.ctaText,
|
|
4045
|
+
ctaTextColor: feedCreative.ctaTextColor,
|
|
4046
|
+
ctaBackgroundColor: feedCreative.ctaBackgroundColor,
|
|
4047
|
+
adClearanceText,
|
|
4048
|
+
colors: feedColors,
|
|
4049
|
+
isAdBadgeEnabled,
|
|
4050
|
+
paddingStyle,
|
|
4051
|
+
onPress: handleClick
|
|
4052
|
+
}
|
|
4053
|
+
) : null
|
|
4054
|
+
] }) })
|
|
4055
|
+
}
|
|
4056
|
+
)
|
|
4057
|
+
}
|
|
4058
|
+
)
|
|
4059
|
+
},
|
|
4060
|
+
impressionKey
|
|
4061
|
+
);
|
|
2877
4062
|
}
|
|
4063
|
+
var styles3 = import_react_native45.StyleSheet.create({
|
|
4064
|
+
impressionArea: {
|
|
4065
|
+
width: "100%"
|
|
4066
|
+
},
|
|
4067
|
+
wrapper: {
|
|
4068
|
+
width: "100%"
|
|
4069
|
+
},
|
|
4070
|
+
cardWrapper: {
|
|
4071
|
+
paddingHorizontal: 10
|
|
4072
|
+
},
|
|
4073
|
+
surface: {
|
|
4074
|
+
width: "100%",
|
|
4075
|
+
overflow: "hidden"
|
|
4076
|
+
},
|
|
4077
|
+
cardSurface: {
|
|
4078
|
+
borderRadius: 16
|
|
4079
|
+
}
|
|
4080
|
+
});
|
|
2878
4081
|
|
|
2879
4082
|
// src/index.ts
|
|
2880
|
-
__reExport(src_exports, require("@apps-in-toss/analytics"), module.exports);
|
|
2881
|
-
var import_private10 = require("@toss/tds-react-native/private");
|
|
2882
|
-
__reExport(src_exports, require("@apps-in-toss/native-modules"), module.exports);
|
|
2883
|
-
__reExport(src_exports, require("@apps-in-toss/types"), module.exports);
|
|
2884
4083
|
var Analytics2 = {
|
|
2885
4084
|
init: import_analytics2.Analytics.init,
|
|
2886
4085
|
Impression: import_analytics2.Analytics.Impression,
|
|
@@ -2892,6 +4091,7 @@ var Analytics2 = {
|
|
|
2892
4091
|
Analytics,
|
|
2893
4092
|
AppsInToss,
|
|
2894
4093
|
INTERNAL__onVisibilityChangedByTransparentServiceWeb,
|
|
4094
|
+
InlineAd,
|
|
2895
4095
|
OverlayProvider,
|
|
2896
4096
|
WebView,
|
|
2897
4097
|
env,
|