@apps-in-toss/framework 0.0.0-dev.1758103372343 → 0.0.0-dev.1758275837494

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 CHANGED
@@ -337,7 +337,7 @@ function NavigationBarImpressionArea({
337
337
  logging.navBarImpression({ home_icon_yn: withHomeButton ? "Y" : "N" });
338
338
  hasLogged.current = true;
339
339
  }
340
- }, []);
340
+ }, [logging, withHomeButton]);
341
341
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children });
342
342
  }
343
343
 
@@ -681,16 +681,16 @@ function RNNavigationBar() {
681
681
  }
682
682
  handleBackOrClose();
683
683
  }, [backEventContext, handleBackOrClose]);
684
- const handleAndroidBackEvent = (0, import_react9.useCallback)(() => {
685
- handleBack();
686
- return true;
687
- }, [handleBack]);
688
684
  (0, import_react9.useEffect)(() => {
685
+ const handleAndroidBackEvent = () => {
686
+ handleBack();
687
+ return true;
688
+ };
689
689
  import_react_native16.BackHandler.addEventListener("hardwareBackPress", handleAndroidBackEvent);
690
690
  return () => {
691
691
  import_react_native16.BackHandler.removeEventListener("hardwareBackPress", handleAndroidBackEvent);
692
692
  };
693
- }, [handleAndroidBackEvent]);
693
+ }, [handleBack]);
694
694
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(NavigationBarImpressionArea, { withHomeButton, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
695
695
  import_private2.TopNavigation,
696
696
  {
@@ -771,9 +771,9 @@ function registerApp(container, { context, analytics }) {
771
771
  return global.Page;
772
772
  }
773
773
  function AppsInTossScreenContainer({ children }) {
774
- const isRN = getAppsInTossGlobals().webViewType == null;
774
+ const isReactNativeService = getAppsInTossGlobals().webViewType == null;
775
775
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_analytics.Analytics.Screen, { children: [
776
- isRN && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RNNavigationBar, {}),
776
+ isReactNativeService && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RNNavigationBar, {}),
777
777
  children
778
778
  ] });
779
779
  }
@@ -817,7 +817,7 @@ var import_react11 = require("react");
817
817
  var import_react_native25 = require("react-native");
818
818
 
819
819
  // src/constant/game-center.ts
820
- var GAME_PROFILE_WEBVIEW_URL = "https://service.toss.im/game-center/profile";
820
+ var GAME_PROFILE_WEBVIEW_URL = "servicetoss://game-center/profile";
821
821
  var GAME_CENTER_MIN_VERSION = {
822
822
  android: "5.221.0",
823
823
  ios: "5.221.0"
@@ -1155,14 +1155,14 @@ function GameWebviewNavigationBar() {
1155
1155
  (0, import_react_native26.closeView)();
1156
1156
  }
1157
1157
  }, [captureExitLog, global2.brandDisplayName, logging, openConfirm]);
1158
- const handleAndroidBackEvent = (0, import_react12.useCallback)(() => {
1159
- handleGameWebviewClose();
1160
- return true;
1161
- }, [handleGameWebviewClose]);
1162
1158
  (0, import_react12.useEffect)(() => {
1159
+ const handleAndroidBackEvent = () => {
1160
+ handleGameWebviewClose();
1161
+ return true;
1162
+ };
1163
1163
  import_react_native28.BackHandler.addEventListener("hardwareBackPress", handleAndroidBackEvent);
1164
1164
  return () => import_react_native28.BackHandler.removeEventListener("hardwareBackPress", handleAndroidBackEvent);
1165
- }, [handleAndroidBackEvent]);
1165
+ }, [handleGameWebviewClose]);
1166
1166
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
1167
1167
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native27.PageNavbar, { preference: { type: "none" } }),
1168
1168
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
@@ -1170,6 +1170,7 @@ function GameWebviewNavigationBar() {
1170
1170
  {
1171
1171
  style: {
1172
1172
  width: "100%",
1173
+ // TODO: UI관련 스타일 설정은 TDS로 이관
1173
1174
  height: import_react_native28.Platform.OS === "ios" ? 44 : 54,
1174
1175
  flexDirection: "row",
1175
1176
  alignItems: "center",
@@ -1185,7 +1186,10 @@ function GameWebviewNavigationBar() {
1185
1186
  {
1186
1187
  fixedRightButton: initialAccessoryButton,
1187
1188
  onPressDots: openMoreButtonBottomSheet,
1188
- onPressClose: handleGameWebviewClose,
1189
+ onPressClose: () => {
1190
+ logging.closeButtonClick();
1191
+ handleGameWebviewClose();
1192
+ },
1189
1193
  theme: "dark"
1190
1194
  }
1191
1195
  )
@@ -1293,51 +1297,46 @@ function mergeRefs(...refs) {
1293
1297
 
1294
1298
  // src/hooks/useWebviewHistoryStack.tsx
1295
1299
  var import_react15 = require("react");
1296
- function useWebViewHistory() {
1297
- const [stack, setStack] = (0, import_react15.useState)([]);
1298
- const [index, setIndex] = (0, import_react15.useState)(-1);
1299
- const canGoBack = index > 0;
1300
- const canGoForward = index >= 0 && index < stack.length - 1;
1301
- const push = (0, import_react15.useCallback)(
1302
- (url) => {
1303
- setStack((prev) => {
1304
- const base = prev.slice(0, index + 1);
1305
- return [...base, url];
1306
- });
1307
- setIndex((i) => i + 1);
1308
- },
1309
- [index]
1310
- );
1311
- const onNavigationStateChange = (0, import_react15.useCallback)(
1312
- ({ url }) => {
1313
- if (stack.length === 0) {
1314
- setStack([url]);
1315
- setIndex(0);
1316
- return;
1300
+ var INITIAL_STATE = { stack: [], index: -1 };
1301
+ function reducer(state, action) {
1302
+ switch (action.type) {
1303
+ case "NAVIGATION_CHANGE": {
1304
+ const { url, canGoForward } = action;
1305
+ if (state.stack.length === 0) {
1306
+ return { stack: [url], index: 0 };
1317
1307
  }
1308
+ const { stack, index } = state;
1318
1309
  const cur = stack[index];
1319
1310
  if (url === cur) {
1320
- return;
1311
+ return state;
1321
1312
  }
1322
1313
  const prev = index > 0 ? stack[index - 1] : void 0;
1323
1314
  const next = index < stack.length - 1 ? stack[index + 1] : void 0;
1324
- if (prev && url === prev) {
1325
- setIndex((i) => i - 1);
1326
- return;
1315
+ if (prev && url === prev && canGoForward) {
1316
+ return { ...state, index: index - 1 };
1327
1317
  }
1328
1318
  if (next && url === next) {
1329
- setIndex((i) => i + 1);
1330
- return;
1319
+ return { ...state, index: index + 1 };
1331
1320
  }
1332
- push(url);
1333
- },
1334
- [stack, index, push]
1335
- );
1336
- return {
1337
- onNavigationStateChange,
1338
- canGoBack,
1339
- canGoForward
1340
- };
1321
+ const base = stack.slice(0, index + 1);
1322
+ const nextStack = [...base, url];
1323
+ return { stack: nextStack, index: nextStack.length - 1 };
1324
+ }
1325
+ default:
1326
+ return state;
1327
+ }
1328
+ }
1329
+ function useWebViewHistory() {
1330
+ const [state, dispatch] = (0, import_react15.useReducer)(reducer, INITIAL_STATE);
1331
+ const onNavigationStateChange = (0, import_react15.useCallback)(({ url, canGoForward: canGoForward2 }) => {
1332
+ dispatch({ type: "NAVIGATION_CHANGE", url, canGoForward: canGoForward2 });
1333
+ }, []);
1334
+ const { canGoBack, canGoForward } = (0, import_react15.useMemo)(() => {
1335
+ const canBack = state.index > 0;
1336
+ const canFwd = state.index >= 0 && state.index < state.stack.length - 1;
1337
+ return { canGoBack: canBack, canGoForward: canFwd };
1338
+ }, [state.index, state.stack.length]);
1339
+ return { onNavigationStateChange, canGoBack, canGoForward };
1341
1340
  }
1342
1341
 
1343
1342
  // src/utils/log.ts
@@ -1399,13 +1398,13 @@ var PartnerWebView = (0, import_react16.forwardRef)(
1399
1398
  const { canGoBack, onNavigationStateChange } = useWebViewHistory();
1400
1399
  const historyBackScript = `
1401
1400
  (function() {
1402
- history.back();
1401
+ window.history.back();
1403
1402
  true;
1404
1403
  })();
1405
1404
  `;
1406
1405
  const historyHomeScript = `
1407
1406
  (function() {
1408
- history.replaceState(null, '', '/');
1407
+ window.location.href = '/';
1409
1408
  true;
1410
1409
  })();
1411
1410
  `;
@@ -1417,18 +1416,19 @@ var PartnerWebView = (0, import_react16.forwardRef)(
1417
1416
  (0, import_native_modules14.closeView)();
1418
1417
  }
1419
1418
  }, [canGoBack, captureExitLog, historyBackScript]);
1420
- const handleAndroidBackEvent = (0, import_react16.useCallback)(() => {
1421
- if (canGoBack) {
1422
- webViewRef.current?.injectJavaScript(historyBackScript);
1423
- return true;
1424
- } else {
1425
- return false;
1426
- }
1427
- }, [canGoBack, historyBackScript]);
1428
1419
  (0, import_react16.useEffect)(() => {
1420
+ const handleAndroidBackEvent = () => {
1421
+ if (canGoBack) {
1422
+ webViewRef.current?.injectJavaScript(historyBackScript);
1423
+ return true;
1424
+ } else {
1425
+ captureExitLog(Date.now());
1426
+ return false;
1427
+ }
1428
+ };
1429
1429
  import_react_native33.BackHandler.addEventListener("hardwareBackPress", handleAndroidBackEvent);
1430
1430
  return () => import_react_native33.BackHandler.removeEventListener("hardwareBackPress", handleAndroidBackEvent);
1431
- }, [handleAndroidBackEvent]);
1431
+ }, [canGoBack, captureExitLog, historyBackScript]);
1432
1432
  const handleHomeIconButtonClick = (0, import_react16.useCallback)(() => {
1433
1433
  webViewRef.current?.injectJavaScript(historyHomeScript);
1434
1434
  }, [historyHomeScript]);
@@ -1471,6 +1471,10 @@ function serializeError(error) {
1471
1471
  return JSON.stringify(error, (_, value) => {
1472
1472
  if (value instanceof Error) {
1473
1473
  return {
1474
+ ...Object.entries(value).reduce((acc, [key, value2]) => {
1475
+ acc[key] = value2;
1476
+ return acc;
1477
+ }, {}),
1474
1478
  name: value.name,
1475
1479
  message: value.message,
1476
1480
  stack: value.stack,
@@ -1843,7 +1847,10 @@ function WebView({ type, local, onMessage, ...props }) {
1843
1847
  showAdMobRewardedAd: import_native_modules17.GoogleAdMob.showAdMobRewardedAd,
1844
1848
  /** AdMobV2 */
1845
1849
  loadAppsInTossAdMob: import_native_modules17.GoogleAdMob.loadAppsInTossAdMob,
1846
- showAppsInTossAdMob: import_native_modules17.GoogleAdMob.showAppsInTossAdMob
1850
+ showAppsInTossAdMob: import_native_modules17.GoogleAdMob.showAppsInTossAdMob,
1851
+ /** IAP */
1852
+ iapCreateOneTimePurchaseOrder: import_native_modules17.IAP.createOneTimePurchaseOrder,
1853
+ requestOneTimePurchase: import_native_modules17.requestOneTimePurchase
1847
1854
  },
1848
1855
  constantHandlerMap: {
1849
1856
  ...graniteConstantBridges,
@@ -1887,8 +1894,9 @@ function WebView({ type, local, onMessage, ...props }) {
1887
1894
  removeStorageItem: import_native_modules17.Storage.removeItem,
1888
1895
  clearItems: import_native_modules17.Storage.clearItems,
1889
1896
  /** IAP */
1890
- iapCreateOneTimePurchaseOrder: import_native_modules17.IAP.createOneTimePurchaseOrder,
1891
- iapGetProductItemList: import_native_modules17.IAP.getProductItemList
1897
+ iapGetProductItemList: import_native_modules17.IAP.getProductItemList,
1898
+ iapCreateOneTimePurchaseOrder: import_native_modules17.iapCreateOneTimePurchaseOrder,
1899
+ processProductGrant: import_native_modules17.processProductGrant
1892
1900
  }
1893
1901
  });
1894
1902
  const headerPropForExternalWebView = (0, import_react19.useMemo)(() => {
package/dist/index.js CHANGED
@@ -295,7 +295,7 @@ function NavigationBarImpressionArea({
295
295
  logging.navBarImpression({ home_icon_yn: withHomeButton ? "Y" : "N" });
296
296
  hasLogged.current = true;
297
297
  }
298
- }, []);
298
+ }, [logging, withHomeButton]);
299
299
  return /* @__PURE__ */ jsx2(Fragment2, { children });
300
300
  }
301
301
 
@@ -639,16 +639,16 @@ function RNNavigationBar() {
639
639
  }
640
640
  handleBackOrClose();
641
641
  }, [backEventContext, handleBackOrClose]);
642
- const handleAndroidBackEvent = useCallback3(() => {
643
- handleBack();
644
- return true;
645
- }, [handleBack]);
646
642
  useEffect7(() => {
643
+ const handleAndroidBackEvent = () => {
644
+ handleBack();
645
+ return true;
646
+ };
647
647
  BackHandler.addEventListener("hardwareBackPress", handleAndroidBackEvent);
648
648
  return () => {
649
649
  BackHandler.removeEventListener("hardwareBackPress", handleAndroidBackEvent);
650
650
  };
651
- }, [handleAndroidBackEvent]);
651
+ }, [handleBack]);
652
652
  return /* @__PURE__ */ jsx4(NavigationBarImpressionArea, { withHomeButton, children: /* @__PURE__ */ jsx4(
653
653
  TopNavigation,
654
654
  {
@@ -729,9 +729,9 @@ function registerApp(container, { context, analytics }) {
729
729
  return global.Page;
730
730
  }
731
731
  function AppsInTossScreenContainer({ children }) {
732
- const isRN = getAppsInTossGlobals().webViewType == null;
732
+ const isReactNativeService = getAppsInTossGlobals().webViewType == null;
733
733
  return /* @__PURE__ */ jsxs(Analytics.Screen, { children: [
734
- isRN && /* @__PURE__ */ jsx5(RNNavigationBar, {}),
734
+ isReactNativeService && /* @__PURE__ */ jsx5(RNNavigationBar, {}),
735
735
  children
736
736
  ] });
737
737
  }
@@ -750,7 +750,16 @@ var AppsInToss = {
750
750
  };
751
751
 
752
752
  // src/components/WebView.tsx
753
- import { GoogleAdMob, IAP, Storage, AppsInTossModule, appsInTossEvent as appsInTossEvent3 } from "@apps-in-toss/native-modules";
753
+ import {
754
+ GoogleAdMob,
755
+ IAP,
756
+ Storage,
757
+ AppsInTossModule,
758
+ appsInTossEvent as appsInTossEvent3,
759
+ iapCreateOneTimePurchaseOrder,
760
+ processProductGrant,
761
+ requestOneTimePurchase
762
+ } from "@apps-in-toss/native-modules";
754
763
  import * as appsInTossAsyncBridges from "@apps-in-toss/native-modules/async-bridges";
755
764
  import * as appsInTossConstantBridges from "@apps-in-toss/native-modules/constant-bridges";
756
765
  import * as appsInTossEventBridges from "@apps-in-toss/native-modules/event-bridges";
@@ -759,7 +768,7 @@ import * as graniteAsyncBridges from "@granite-js/react-native/async-bridges";
759
768
  import * as graniteConstantBridges from "@granite-js/react-native/constant-bridges";
760
769
  import { ExternalWebViewScreen, tdsEvent } from "@toss-design-system/react-native";
761
770
  import { useSafeAreaBottom, useSafeAreaTop as useSafeAreaTop2, useTopNavigation } from "@toss-design-system/react-native/private";
762
- import { useMemo as useMemo3, useState as useState6 } from "react";
771
+ import { useMemo as useMemo4, useState as useState5 } from "react";
763
772
  import { Platform as Platform4 } from "react-native";
764
773
 
765
774
  // src/components/GameWebView.tsx
@@ -777,7 +786,7 @@ import { useEffect as useEffect8 } from "react";
777
786
  import { Pressable, View } from "react-native";
778
787
 
779
788
  // src/constant/game-center.ts
780
- var GAME_PROFILE_WEBVIEW_URL = "https://service.toss.im/game-center/profile";
789
+ var GAME_PROFILE_WEBVIEW_URL = "servicetoss://game-center/profile";
781
790
  var GAME_CENTER_MIN_VERSION = {
782
791
  android: "5.221.0",
783
792
  ios: "5.221.0"
@@ -1115,14 +1124,14 @@ function GameWebviewNavigationBar() {
1115
1124
  closeView3();
1116
1125
  }
1117
1126
  }, [captureExitLog, global2.brandDisplayName, logging, openConfirm]);
1118
- const handleAndroidBackEvent = useCallback5(() => {
1119
- handleGameWebviewClose();
1120
- return true;
1121
- }, [handleGameWebviewClose]);
1122
1127
  useEffect9(() => {
1128
+ const handleAndroidBackEvent = () => {
1129
+ handleGameWebviewClose();
1130
+ return true;
1131
+ };
1123
1132
  BackHandler2.addEventListener("hardwareBackPress", handleAndroidBackEvent);
1124
1133
  return () => BackHandler2.removeEventListener("hardwareBackPress", handleAndroidBackEvent);
1125
- }, [handleAndroidBackEvent]);
1134
+ }, [handleGameWebviewClose]);
1126
1135
  return /* @__PURE__ */ jsxs3(Fragment6, { children: [
1127
1136
  /* @__PURE__ */ jsx8(PageNavbar, { preference: { type: "none" } }),
1128
1137
  /* @__PURE__ */ jsx8(
@@ -1130,6 +1139,7 @@ function GameWebviewNavigationBar() {
1130
1139
  {
1131
1140
  style: {
1132
1141
  width: "100%",
1142
+ // TODO: UI관련 스타일 설정은 TDS로 이관
1133
1143
  height: Platform2.OS === "ios" ? 44 : 54,
1134
1144
  flexDirection: "row",
1135
1145
  alignItems: "center",
@@ -1145,7 +1155,10 @@ function GameWebviewNavigationBar() {
1145
1155
  {
1146
1156
  fixedRightButton: initialAccessoryButton,
1147
1157
  onPressDots: openMoreButtonBottomSheet,
1148
- onPressClose: handleGameWebviewClose,
1158
+ onPressClose: () => {
1159
+ logging.closeButtonClick();
1160
+ handleGameWebviewClose();
1161
+ },
1149
1162
  theme: "dark"
1150
1163
  }
1151
1164
  )
@@ -1254,52 +1267,47 @@ function mergeRefs(...refs) {
1254
1267
  }
1255
1268
 
1256
1269
  // src/hooks/useWebviewHistoryStack.tsx
1257
- import { useCallback as useCallback7, useState as useState4 } from "react";
1258
- function useWebViewHistory() {
1259
- const [stack, setStack] = useState4([]);
1260
- const [index, setIndex] = useState4(-1);
1261
- const canGoBack = index > 0;
1262
- const canGoForward = index >= 0 && index < stack.length - 1;
1263
- const push = useCallback7(
1264
- (url) => {
1265
- setStack((prev) => {
1266
- const base = prev.slice(0, index + 1);
1267
- return [...base, url];
1268
- });
1269
- setIndex((i) => i + 1);
1270
- },
1271
- [index]
1272
- );
1273
- const onNavigationStateChange = useCallback7(
1274
- ({ url }) => {
1275
- if (stack.length === 0) {
1276
- setStack([url]);
1277
- setIndex(0);
1278
- return;
1270
+ import { useCallback as useCallback7, useMemo as useMemo2, useReducer } from "react";
1271
+ var INITIAL_STATE = { stack: [], index: -1 };
1272
+ function reducer(state, action) {
1273
+ switch (action.type) {
1274
+ case "NAVIGATION_CHANGE": {
1275
+ const { url, canGoForward } = action;
1276
+ if (state.stack.length === 0) {
1277
+ return { stack: [url], index: 0 };
1279
1278
  }
1279
+ const { stack, index } = state;
1280
1280
  const cur = stack[index];
1281
1281
  if (url === cur) {
1282
- return;
1282
+ return state;
1283
1283
  }
1284
1284
  const prev = index > 0 ? stack[index - 1] : void 0;
1285
1285
  const next = index < stack.length - 1 ? stack[index + 1] : void 0;
1286
- if (prev && url === prev) {
1287
- setIndex((i) => i - 1);
1288
- return;
1286
+ if (prev && url === prev && canGoForward) {
1287
+ return { ...state, index: index - 1 };
1289
1288
  }
1290
1289
  if (next && url === next) {
1291
- setIndex((i) => i + 1);
1292
- return;
1290
+ return { ...state, index: index + 1 };
1293
1291
  }
1294
- push(url);
1295
- },
1296
- [stack, index, push]
1297
- );
1298
- return {
1299
- onNavigationStateChange,
1300
- canGoBack,
1301
- canGoForward
1302
- };
1292
+ const base = stack.slice(0, index + 1);
1293
+ const nextStack = [...base, url];
1294
+ return { stack: nextStack, index: nextStack.length - 1 };
1295
+ }
1296
+ default:
1297
+ return state;
1298
+ }
1299
+ }
1300
+ function useWebViewHistory() {
1301
+ const [state, dispatch] = useReducer(reducer, INITIAL_STATE);
1302
+ const onNavigationStateChange = useCallback7(({ url, canGoForward: canGoForward2 }) => {
1303
+ dispatch({ type: "NAVIGATION_CHANGE", url, canGoForward: canGoForward2 });
1304
+ }, []);
1305
+ const { canGoBack, canGoForward } = useMemo2(() => {
1306
+ const canBack = state.index > 0;
1307
+ const canFwd = state.index >= 0 && state.index < state.stack.length - 1;
1308
+ return { canGoBack: canBack, canGoForward: canFwd };
1309
+ }, [state.index, state.stack.length]);
1310
+ return { onNavigationStateChange, canGoBack, canGoForward };
1303
1311
  }
1304
1312
 
1305
1313
  // src/utils/log.ts
@@ -1361,13 +1369,13 @@ var PartnerWebView = forwardRef2(
1361
1369
  const { canGoBack, onNavigationStateChange } = useWebViewHistory();
1362
1370
  const historyBackScript = `
1363
1371
  (function() {
1364
- history.back();
1372
+ window.history.back();
1365
1373
  true;
1366
1374
  })();
1367
1375
  `;
1368
1376
  const historyHomeScript = `
1369
1377
  (function() {
1370
- history.replaceState(null, '', '/');
1378
+ window.location.href = '/';
1371
1379
  true;
1372
1380
  })();
1373
1381
  `;
@@ -1379,18 +1387,19 @@ var PartnerWebView = forwardRef2(
1379
1387
  closeView5();
1380
1388
  }
1381
1389
  }, [canGoBack, captureExitLog, historyBackScript]);
1382
- const handleAndroidBackEvent = useCallback8(() => {
1383
- if (canGoBack) {
1384
- webViewRef.current?.injectJavaScript(historyBackScript);
1385
- return true;
1386
- } else {
1387
- return false;
1388
- }
1389
- }, [canGoBack, historyBackScript]);
1390
1390
  useEffect11(() => {
1391
+ const handleAndroidBackEvent = () => {
1392
+ if (canGoBack) {
1393
+ webViewRef.current?.injectJavaScript(historyBackScript);
1394
+ return true;
1395
+ } else {
1396
+ captureExitLog(Date.now());
1397
+ return false;
1398
+ }
1399
+ };
1391
1400
  BackHandler3.addEventListener("hardwareBackPress", handleAndroidBackEvent);
1392
1401
  return () => BackHandler3.removeEventListener("hardwareBackPress", handleAndroidBackEvent);
1393
- }, [handleAndroidBackEvent]);
1402
+ }, [canGoBack, captureExitLog, historyBackScript]);
1394
1403
  const handleHomeIconButtonClick = useCallback8(() => {
1395
1404
  webViewRef.current?.injectJavaScript(historyHomeScript);
1396
1405
  }, [historyHomeScript]);
@@ -1428,11 +1437,15 @@ var PartnerWebView = forwardRef2(
1428
1437
  );
1429
1438
 
1430
1439
  // src/bridge-handler/useBridgeHandler.tsx
1431
- import { useCallback as useCallback9, useMemo as useMemo2, useRef as useRef5 } from "react";
1440
+ import { useCallback as useCallback9, useMemo as useMemo3, useRef as useRef5 } from "react";
1432
1441
  function serializeError(error) {
1433
1442
  return JSON.stringify(error, (_, value) => {
1434
1443
  if (value instanceof Error) {
1435
1444
  return {
1445
+ ...Object.entries(value).reduce((acc, [key, value2]) => {
1446
+ acc[key] = value2;
1447
+ return acc;
1448
+ }, {}),
1436
1449
  name: value.name,
1437
1450
  message: value.message,
1438
1451
  stack: value.stack,
@@ -1478,7 +1491,7 @@ function useBridgeHandler({
1478
1491
  injectedJavaScript: originalInjectedJavaScript
1479
1492
  }) {
1480
1493
  const ref = useRef5(null);
1481
- const injectedJavaScript = useMemo2(
1494
+ const injectedJavaScript = useMemo3(
1482
1495
  () => [
1483
1496
  `window.__CONSTANT_HANDLER_MAP = ${JSON.stringify(
1484
1497
  Object.entries(constantHandlerMap).reduce(
@@ -1714,10 +1727,10 @@ function useCreateUserAgent({
1714
1727
  // src/hooks/useGeolocation.ts
1715
1728
  import { startUpdateLocation } from "@apps-in-toss/native-modules";
1716
1729
  import { useVisibility as useVisibility3 } from "@granite-js/react-native";
1717
- import { useEffect as useEffect12, useState as useState5 } from "react";
1730
+ import { useEffect as useEffect12, useState as useState4 } from "react";
1718
1731
  function useGeolocation({ accuracy, distanceInterval, timeInterval }) {
1719
1732
  const isVisible = useVisibility3();
1720
- const [location, setLocation] = useState5(null);
1733
+ const [location, setLocation] = useState4(null);
1721
1734
  useEffect12(() => {
1722
1735
  if (!isVisible) {
1723
1736
  return;
@@ -1771,7 +1784,7 @@ function WebView({ type, local, onMessage, ...props }) {
1771
1784
  throw new Error(`Invalid WebView type: '${type}'`);
1772
1785
  }
1773
1786
  const graniteEvent = useGraniteEvent();
1774
- const uri = useMemo3(() => getWebViewUri(local), [local]);
1787
+ const uri = useMemo4(() => getWebViewUri(local), [local]);
1775
1788
  const top = useSafeAreaTop2();
1776
1789
  const bottom = useSafeAreaBottom();
1777
1790
  const global2 = getAppsInTossGlobals();
@@ -1783,7 +1796,7 @@ function WebView({ type, local, onMessage, ...props }) {
1783
1796
  document.head.appendChild(style);
1784
1797
  })();
1785
1798
  `;
1786
- const [allowsBackForwardNavigationGestures, setAllowsBackForwardNavigationGestures] = useState6(
1799
+ const [allowsBackForwardNavigationGestures, setAllowsBackForwardNavigationGestures] = useState5(
1787
1800
  props.allowsBackForwardNavigationGestures
1788
1801
  );
1789
1802
  const handler = useBridgeHandler({
@@ -1805,7 +1818,10 @@ function WebView({ type, local, onMessage, ...props }) {
1805
1818
  showAdMobRewardedAd: GoogleAdMob.showAdMobRewardedAd,
1806
1819
  /** AdMobV2 */
1807
1820
  loadAppsInTossAdMob: GoogleAdMob.loadAppsInTossAdMob,
1808
- showAppsInTossAdMob: GoogleAdMob.showAppsInTossAdMob
1821
+ showAppsInTossAdMob: GoogleAdMob.showAppsInTossAdMob,
1822
+ /** IAP */
1823
+ iapCreateOneTimePurchaseOrder: IAP.createOneTimePurchaseOrder,
1824
+ requestOneTimePurchase
1809
1825
  },
1810
1826
  constantHandlerMap: {
1811
1827
  ...graniteConstantBridges,
@@ -1849,11 +1865,12 @@ function WebView({ type, local, onMessage, ...props }) {
1849
1865
  removeStorageItem: Storage.removeItem,
1850
1866
  clearItems: Storage.clearItems,
1851
1867
  /** IAP */
1852
- iapCreateOneTimePurchaseOrder: IAP.createOneTimePurchaseOrder,
1853
- iapGetProductItemList: IAP.getProductItemList
1868
+ iapGetProductItemList: IAP.getProductItemList,
1869
+ iapCreateOneTimePurchaseOrder,
1870
+ processProductGrant
1854
1871
  }
1855
1872
  });
1856
- const headerPropForExternalWebView = useMemo3(() => {
1873
+ const headerPropForExternalWebView = useMemo4(() => {
1857
1874
  const parsedNavigationBar = global2.navigationBar != null ? safeParseNavigationBar(global2.navigationBar) : null;
1858
1875
  const initialAccessoryButton = parsedNavigationBar?.initialAccessoryButton;
1859
1876
  const withBackButton = parsedNavigationBar?.withBackButton ?? true;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@apps-in-toss/framework",
3
3
  "type": "module",
4
- "version": "0.0.0-dev.1758103372343",
4
+ "version": "0.0.0-dev.1758275837494",
5
5
  "description": "The framework for Apps In Toss",
6
6
  "scripts": {
7
7
  "prepack": "yarn build",
@@ -56,11 +56,11 @@
56
56
  "ait": "./bin/ait.js"
57
57
  },
58
58
  "dependencies": {
59
- "@apps-in-toss/analytics": "0.0.0-dev.1758103372343",
60
- "@apps-in-toss/cli": "0.0.0-dev.1758103372343",
61
- "@apps-in-toss/native-modules": "0.0.0-dev.1758103372343",
62
- "@apps-in-toss/plugins": "0.0.0-dev.1758103372343",
63
- "@apps-in-toss/types": "0.0.0-dev.1758103372343",
59
+ "@apps-in-toss/analytics": "0.0.0-dev.1758275837494",
60
+ "@apps-in-toss/cli": "0.0.0-dev.1758275837494",
61
+ "@apps-in-toss/native-modules": "0.0.0-dev.1758275837494",
62
+ "@apps-in-toss/plugins": "0.0.0-dev.1758275837494",
63
+ "@apps-in-toss/types": "0.0.0-dev.1758275837494",
64
64
  "es-hangul": "^2.3.2"
65
65
  },
66
66
  "devDependencies": {
@@ -96,5 +96,5 @@
96
96
  "publishConfig": {
97
97
  "access": "public"
98
98
  },
99
- "gitHead": "dd32f2c8028913b7f866a3a099728410d783dcd6"
99
+ "gitHead": "b68a923a00c75af3ca66633e450370f20f025a34"
100
100
  }