@apps-in-toss/framework 1.6.0 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ # @apps-in-toss/framework
2
+
3
+ ## 1.6.1
4
+
5
+ ### Patch Changes
6
+
7
+ - WebView 프로세스가 죽는 상황의 유저 경험을 개선합니다.
8
+ - OOM 등으로 인해 웹뷰가 죽으면 계속 흰화면이 보여지는 문제가 있었습니다.
9
+ - 따라서 토스트로 안내 메시지를 띄운 후 웹뷰를 재시작하여, 유저가 서비스를 다시 사용할 수 있게 만듭니다.
10
+ - 또한 키바나에 AppsInTossWebViewProcessDidTerminate 라는 이름의 디버그 로그도 함께 남깁니다.
package/bin/ait.js CHANGED
File without changes
package/dist/index.cjs CHANGED
@@ -724,15 +724,18 @@ var import_react13 = require("react");
724
724
  function useCloseConfirm() {
725
725
  const { brandDisplayName } = getAppsInTossGlobals();
726
726
  const { openConfirm } = (0, import_tds_react_native5.useDialog)();
727
- return (0, import_react13.useCallback)(async ({ onEntered }) => {
728
- return await openConfirm({
729
- title: `${(0, import_es_hangul2.josa)(brandDisplayName, "\uC744/\uB97C")} \uC885\uB8CC\uD560\uAE4C\uC694?`,
730
- leftButton: "\uCDE8\uC18C",
731
- rightButton: "\uC885\uB8CC\uD558\uAE30",
732
- closeOnDimmerClick: true,
733
- onEntered
734
- });
735
- }, [brandDisplayName, openConfirm]);
727
+ return (0, import_react13.useCallback)(
728
+ async ({ onEntered }) => {
729
+ return await openConfirm({
730
+ title: `${(0, import_es_hangul2.josa)(brandDisplayName, "\uC744/\uB97C")} \uC885\uB8CC\uD560\uAE4C\uC694?`,
731
+ leftButton: "\uCDE8\uC18C",
732
+ rightButton: "\uC885\uB8CC\uD558\uAE30",
733
+ closeOnDimmerClick: true,
734
+ onEntered
735
+ });
736
+ },
737
+ [brandDisplayName, openConfirm]
738
+ );
736
739
  }
737
740
 
738
741
  // src/components/NavigationBar/common/useNavigationBarLogging.tsx
@@ -971,30 +974,10 @@ function Menu({ title, iconURL, onPress }) {
971
974
  marginRight: 16,
972
975
  backgroundColor: iconBackgroundColor
973
976
  },
974
- children: iconName ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
975
- import_tds_react_native6.Asset.Icon,
976
- {
977
- frameShape: { width: 20, height: 20 },
978
- color: globals.brandPrimaryColor,
979
- name: iconName
980
- }
981
- ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
982
- import_tds_react_native6.Asset.Image,
983
- {
984
- frameShape: { width: 20, height: 20 },
985
- source: { uri: iconURL }
986
- }
987
- )
988
- }
989
- ),
990
- contents: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
991
- import_tds_react_native6.ListRow.Texts,
992
- {
993
- type: "1RowTypeA",
994
- top: title,
995
- topProps: { color: adaptive.grey700 }
977
+ children: iconName ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_tds_react_native6.Asset.Icon, { frameShape: { width: 20, height: 20 }, color: globals.brandPrimaryColor, name: iconName }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_tds_react_native6.Asset.Image, { frameShape: { width: 20, height: 20 }, source: { uri: iconURL } })
996
978
  }
997
979
  ),
980
+ contents: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_tds_react_native6.ListRow.Texts, { type: "1RowTypeA", top: title, topProps: { color: adaptive.grey700 } }),
998
981
  verticalPadding: "extraSmall",
999
982
  onPress: () => {
1000
983
  logging.menuClick({ title });
@@ -1084,7 +1067,9 @@ function PermissionsMenu() {
1084
1067
  {
1085
1068
  title: "\uAD8C\uD55C \uC124\uC815",
1086
1069
  iconURL: "https://static.toss.im/icons/png/4x/icon-setting-mono.png",
1087
- onPress: () => (0, import_react_native19.openURL)(`servicetoss://apps-in-toss-menu/permissions?appName=${import_react_native19.Granite.appName}&displayAppName=${globals.brandDisplayName}`)
1070
+ onPress: () => (0, import_react_native19.openURL)(
1071
+ `servicetoss://apps-in-toss-menu/permissions?appName=${import_react_native19.Granite.appName}&displayAppName=${globals.brandDisplayName}`
1072
+ )
1088
1073
  }
1089
1074
  );
1090
1075
  }
@@ -1187,17 +1172,15 @@ function useMoreButtonBottomSheet() {
1187
1172
  onClose: handleClose,
1188
1173
  onExited: exit,
1189
1174
  children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_tds_react_native8.List, { rowSeparator: "none", children: [
1190
- itemList.map(
1191
- (item) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1192
- Menu,
1193
- {
1194
- title: item.contactItemName,
1195
- iconURL: item.contactIconUrl,
1196
- onPress: () => (0, import_react_native20.openURL)(item.contactUri)
1197
- },
1198
- item.contactItemName
1199
- )
1200
- ),
1175
+ itemList.map((item) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1176
+ Menu,
1177
+ {
1178
+ title: item.contactItemName,
1179
+ iconURL: item.contactIconUrl,
1180
+ onPress: () => (0, import_react_native20.openURL)(item.contactUri)
1181
+ },
1182
+ item.contactItemName
1183
+ )),
1201
1184
  isShareListMenuSupported && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(AppShareListMenu, {}),
1202
1185
  isPermissionsMenuSupported && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PermissionsMenu, {})
1203
1186
  ] })
@@ -1419,16 +1402,16 @@ var AppsInToss = {
1419
1402
  };
1420
1403
 
1421
1404
  // src/components/WebView.tsx
1422
- var import_native_modules22 = require("@apps-in-toss/native-modules");
1405
+ var import_native_modules23 = require("@apps-in-toss/native-modules");
1423
1406
  var appsInTossAsyncBridges = __toESM(require("@apps-in-toss/native-modules/async-bridges"), 1);
1424
1407
  var appsInTossConstantBridges = __toESM(require("@apps-in-toss/native-modules/constant-bridges"), 1);
1425
1408
  var appsInTossEventBridges = __toESM(require("@apps-in-toss/native-modules/event-bridges"), 1);
1426
1409
  var import_react_native_safe_area_context4 = require("@granite-js/native/react-native-safe-area-context");
1427
- var import_react_native37 = require("@granite-js/react-native");
1428
- var import_tds_react_native14 = require("@toss/tds-react-native");
1410
+ var import_react_native38 = require("@granite-js/react-native");
1411
+ var import_tds_react_native15 = require("@toss/tds-react-native");
1429
1412
  var import_private9 = require("@toss/tds-react-native/private");
1430
1413
  var import_react28 = require("react");
1431
- var import_react_native38 = require("react-native");
1414
+ var import_react_native39 = require("react-native");
1432
1415
 
1433
1416
  // src/components/GameWebView.tsx
1434
1417
  var import_native_modules14 = require("@apps-in-toss/native-modules");
@@ -1599,7 +1582,7 @@ function convertIntentURL(url) {
1599
1582
  // src/ads/fetchTossAd.ts
1600
1583
  var import_native_modules15 = require("@apps-in-toss/native-modules");
1601
1584
 
1602
- // ../../.yarn/cache/es-toolkit-npm-1.34.1-4cd6371dcb-aab6d07be3.zip/node_modules/es-toolkit/dist/function/noop.mjs
1585
+ // ../../../.yarn/cache/es-toolkit-npm-1.34.1-4cd6371dcb-aab6d07be3.zip/node_modules/es-toolkit/dist/function/noop.mjs
1603
1586
  function noop() {
1604
1587
  }
1605
1588
 
@@ -1706,16 +1689,13 @@ function postEventTracking(params) {
1706
1689
  deviceIdType: "NONE",
1707
1690
  platform: "RN"
1708
1691
  });
1709
- return fetch(
1710
- endpoint,
1711
- {
1712
- method: "POST",
1713
- headers: {
1714
- "Content-Type": "application/json"
1715
- },
1716
- body: bodyJSON
1717
- }
1718
- ).catch(noop);
1692
+ return fetch(endpoint, {
1693
+ method: "POST",
1694
+ headers: {
1695
+ "Content-Type": "application/json"
1696
+ },
1697
+ body: bodyJSON
1698
+ }).catch(noop);
1719
1699
  }
1720
1700
 
1721
1701
  // src/ads/integratedAd.ts
@@ -2493,9 +2473,45 @@ function useTopNavigation() {
2493
2473
  };
2494
2474
  }
2495
2475
 
2496
- // src/utils/log.ts
2476
+ // src/hooks/useWebViewMemoryDebug.tsx
2497
2477
  var import_native_modules21 = require("@apps-in-toss/native-modules");
2498
2478
  var import_react_native36 = require("@granite-js/react-native");
2479
+ var import_tds_react_native14 = require("@toss/tds-react-native");
2480
+ function useHandleWebViewProcessDidTerminate(webViewRef) {
2481
+ const toast = (0, import_tds_react_native14.useToast)();
2482
+ return () => {
2483
+ webViewDebugLog("AppsInTossWebViewProcessDidTerminate", {});
2484
+ toast.open("\uBB38\uC81C\uAC00 \uC0DD\uACA8\uC11C \uBBF8\uB2C8\uC571\uC744 \uB2E4\uC2DC \uC2DC\uC791\uD588\uC5B4\uC694.", {
2485
+ type: "bottom",
2486
+ lottie: `https://static.toss.im/lotties-common/check-green-spot.json`
2487
+ });
2488
+ webViewRef.current?.reload();
2489
+ };
2490
+ }
2491
+ async function webViewMemoryDebugLog(params) {
2492
+ webViewDebugLog("AppsInTossWebViewMemoryDebug", params);
2493
+ }
2494
+ function webViewDebugLog(logName, params) {
2495
+ const global2 = getAppsInTossGlobals();
2496
+ const event = {
2497
+ log_name: logName,
2498
+ log_type: "debug",
2499
+ params: {
2500
+ ...params,
2501
+ app_name: import_react_native36.Granite.appName,
2502
+ deployment_id: global2.deploymentId
2503
+ }
2504
+ };
2505
+ if ((0, import_native_modules21.getOperationalEnvironment)() === "toss") {
2506
+ import_native_modules21.INTERNAL__module.tossCoreEventLog(event);
2507
+ } else {
2508
+ console.log("[webViewDebugLog]", event);
2509
+ }
2510
+ }
2511
+
2512
+ // src/utils/log.ts
2513
+ var import_native_modules22 = require("@apps-in-toss/native-modules");
2514
+ var import_react_native37 = require("@granite-js/react-native");
2499
2515
 
2500
2516
  // src/utils/extractDateFromUUIDv7.ts
2501
2517
  var extractDateFromUUIDv7 = (uuid) => {
@@ -2521,7 +2537,7 @@ var getGroupId = (url) => {
2521
2537
  };
2522
2538
  var getReferrer2 = () => {
2523
2539
  try {
2524
- const referrer = new URL((0, import_react_native36.getSchemeUri)());
2540
+ const referrer = new URL((0, import_react_native37.getSchemeUri)());
2525
2541
  return referrer.searchParams.get("referrer");
2526
2542
  } catch {
2527
2543
  return "";
@@ -2539,7 +2555,7 @@ var trackScreen = (url) => {
2539
2555
  deployment_timestamp: extractDateFromUUIDv7(env.getDeploymentId()).getTime()
2540
2556
  }
2541
2557
  };
2542
- return (0, import_native_modules21.eventLog)(log);
2558
+ return (0, import_native_modules22.eventLog)(log);
2543
2559
  };
2544
2560
 
2545
2561
  // src/components/WebView.tsx
@@ -2548,12 +2564,12 @@ var operationalEnvironment = appsInTossConstantBridges.getOperationalEnvironment
2548
2564
  var TYPES = ["partner", "external", "game"];
2549
2565
  var WEBVIEW_TYPES = {
2550
2566
  partner: PartnerWebView,
2551
- external: import_tds_react_native14.ExternalWebViewScreen,
2567
+ external: import_tds_react_native15.ExternalWebViewScreen,
2552
2568
  game: GameWebView
2553
2569
  };
2554
2570
  function mergeSchemeQueryParamsInto(url) {
2555
2571
  const baseUrl = new URL(url);
2556
- const schemeUrl = new URL((0, import_react_native37.getSchemeUri)());
2572
+ const schemeUrl = new URL((0, import_react_native38.getSchemeUri)());
2557
2573
  baseUrl.pathname = schemeUrl.pathname;
2558
2574
  for (const [key, value] of schemeUrl.searchParams.entries()) {
2559
2575
  baseUrl.searchParams.set(key, value);
@@ -2565,7 +2581,7 @@ function getWebViewUri(local) {
2565
2581
  const devUrl = `http://${local.host}:${local.port}`;
2566
2582
  return mergeSchemeQueryParamsInto(devUrl).toString();
2567
2583
  }
2568
- const { url: rawUrl } = import_native_modules22.AppsInTossModule.getWebBundleURL({});
2584
+ const { url: rawUrl } = import_native_modules23.AppsInTossModule.getWebBundleURL({});
2569
2585
  const url = mergeSchemeQueryParamsInto(rawUrl);
2570
2586
  const deploymentId = env.getDeploymentId();
2571
2587
  if (deploymentId) {
@@ -2593,14 +2609,14 @@ function WebView({ type, local, onMessage, ...props }) {
2593
2609
  onMessage,
2594
2610
  eventListenerMap: {
2595
2611
  ...appsInTossEventBridges,
2596
- navigationAccessoryEvent: ({ onEvent, onError }) => import_tds_react_native14.tdsEvent.addEventListener("navigationAccessoryEvent", { onEvent, onError }),
2612
+ navigationAccessoryEvent: ({ onEvent, onError }) => import_tds_react_native15.tdsEvent.addEventListener("navigationAccessoryEvent", { onEvent, onError }),
2597
2613
  backEvent: ({ onEvent }) => {
2598
2614
  webBackHandler.addEventListener(onEvent);
2599
2615
  return () => {
2600
2616
  webBackHandler.removeEventListener(onEvent);
2601
2617
  };
2602
2618
  },
2603
- updateLocationEvent: ({ onEvent, onError, options }) => import_native_modules22.appsInTossEvent.addEventListener("updateLocationEvent", { onEvent, onError, options }),
2619
+ updateLocationEvent: ({ onEvent, onError, options }) => import_native_modules23.appsInTossEvent.addEventListener("updateLocationEvent", { onEvent, onError, options }),
2604
2620
  safeAreaInsetsChange: ({ onEvent }) => {
2605
2621
  safeAreaInsetsEmitter.on("safeAreaInsetsChange", onEvent);
2606
2622
  return () => {
@@ -2608,23 +2624,23 @@ function WebView({ type, local, onMessage, ...props }) {
2608
2624
  };
2609
2625
  },
2610
2626
  /** @internal */
2611
- appBridgeCallbackEvent: ({ onEvent, onError, options }) => import_native_modules22.appsInTossEvent.addEventListener("appBridgeCallbackEvent", { onEvent, onError, options }),
2627
+ appBridgeCallbackEvent: ({ onEvent, onError, options }) => import_native_modules23.appsInTossEvent.addEventListener("appBridgeCallbackEvent", { onEvent, onError, options }),
2612
2628
  /** AdMob */
2613
- loadAdMobInterstitialAd: import_native_modules22.GoogleAdMob.loadAdMobInterstitialAd,
2614
- showAdMobInterstitialAd: import_native_modules22.GoogleAdMob.showAdMobInterstitialAd,
2615
- loadAdMobRewardedAd: import_native_modules22.GoogleAdMob.loadAdMobRewardedAd,
2616
- showAdMobRewardedAd: import_native_modules22.GoogleAdMob.showAdMobRewardedAd,
2629
+ loadAdMobInterstitialAd: import_native_modules23.GoogleAdMob.loadAdMobInterstitialAd,
2630
+ showAdMobInterstitialAd: import_native_modules23.GoogleAdMob.showAdMobInterstitialAd,
2631
+ loadAdMobRewardedAd: import_native_modules23.GoogleAdMob.loadAdMobRewardedAd,
2632
+ showAdMobRewardedAd: import_native_modules23.GoogleAdMob.showAdMobRewardedAd,
2617
2633
  /** AdMobV2 */
2618
- loadAppsInTossAdMob: import_native_modules22.GoogleAdMob.loadAppsInTossAdMob,
2619
- showAppsInTossAdMob: import_native_modules22.GoogleAdMob.showAppsInTossAdMob,
2634
+ loadAppsInTossAdMob: import_native_modules23.GoogleAdMob.loadAppsInTossAdMob,
2635
+ showAppsInTossAdMob: import_native_modules23.GoogleAdMob.showAppsInTossAdMob,
2620
2636
  /** IntegratedAd */
2621
2637
  loadFullScreenAd: loadFullScreenAdForWeb,
2622
2638
  showFullScreenAd,
2623
2639
  /** TossAd */
2624
2640
  fetchTossAd,
2625
2641
  /** IAP */
2626
- iapCreateOneTimePurchaseOrder: import_native_modules22.IAP.createOneTimePurchaseOrder,
2627
- requestOneTimePurchase: import_native_modules22.requestOneTimePurchase
2642
+ iapCreateOneTimePurchaseOrder: import_native_modules23.IAP.createOneTimePurchaseOrder,
2643
+ requestOneTimePurchase: import_native_modules23.requestOneTimePurchase
2628
2644
  },
2629
2645
  constantHandlerMap: {
2630
2646
  ...appsInTossConstantBridges,
@@ -2634,13 +2650,13 @@ function WebView({ type, local, onMessage, ...props }) {
2634
2650
  getSafeAreaRight: () => insets.right,
2635
2651
  ...Object.fromEntries(Object.entries(global2).map(([key, value]) => [key, () => value])),
2636
2652
  /** AdMob */
2637
- loadAdMobInterstitialAd_isSupported: import_native_modules22.GoogleAdMob.loadAdMobInterstitialAd.isSupported,
2638
- showAdMobInterstitialAd_isSupported: import_native_modules22.GoogleAdMob.showAdMobInterstitialAd.isSupported,
2639
- loadAdMobRewardedAd_isSupported: import_native_modules22.GoogleAdMob.loadAdMobRewardedAd.isSupported,
2640
- showAdMobRewardedAd_isSupported: import_native_modules22.GoogleAdMob.showAdMobRewardedAd.isSupported,
2653
+ loadAdMobInterstitialAd_isSupported: import_native_modules23.GoogleAdMob.loadAdMobInterstitialAd.isSupported,
2654
+ showAdMobInterstitialAd_isSupported: import_native_modules23.GoogleAdMob.showAdMobInterstitialAd.isSupported,
2655
+ loadAdMobRewardedAd_isSupported: import_native_modules23.GoogleAdMob.loadAdMobRewardedAd.isSupported,
2656
+ showAdMobRewardedAd_isSupported: import_native_modules23.GoogleAdMob.showAdMobRewardedAd.isSupported,
2641
2657
  /** AdMobV2 */
2642
- loadAppsInTossAdMob_isSupported: import_native_modules22.GoogleAdMob.loadAppsInTossAdMob.isSupported,
2643
- showAppsInTossAdMob_isSupported: import_native_modules22.GoogleAdMob.showAppsInTossAdMob.isSupported,
2658
+ loadAppsInTossAdMob_isSupported: import_native_modules23.GoogleAdMob.loadAppsInTossAdMob.isSupported,
2659
+ showAppsInTossAdMob_isSupported: import_native_modules23.GoogleAdMob.showAppsInTossAdMob.isSupported,
2644
2660
  /** IntegratedAd */
2645
2661
  loadFullScreenAd_isSupported: loadFullScreenAdForWeb.isSupported,
2646
2662
  showFullScreenAd_isSupported: showFullScreenAd.isSupported,
@@ -2668,19 +2684,21 @@ function WebView({ type, local, onMessage, ...props }) {
2668
2684
  getCurrentLocation: appsInTossAsyncBridges.getCurrentLocation,
2669
2685
  openCamera: appsInTossAsyncBridges.openCamera,
2670
2686
  /** Storage */
2671
- getStorageItem: import_native_modules22.Storage.getItem,
2672
- setStorageItem: import_native_modules22.Storage.setItem,
2673
- removeStorageItem: import_native_modules22.Storage.removeItem,
2674
- clearItems: import_native_modules22.Storage.clearItems,
2687
+ getStorageItem: import_native_modules23.Storage.getItem,
2688
+ setStorageItem: import_native_modules23.Storage.setItem,
2689
+ removeStorageItem: import_native_modules23.Storage.removeItem,
2690
+ clearItems: import_native_modules23.Storage.clearItems,
2675
2691
  /** IAP */
2676
- iapGetProductItemList: import_native_modules22.IAP.getProductItemList,
2677
- iapCreateOneTimePurchaseOrder: import_native_modules22.iapCreateOneTimePurchaseOrder,
2678
- processProductGrant: import_native_modules22.processProductGrant,
2679
- getPendingOrders: import_native_modules22.IAP.getPendingOrders,
2680
- getCompletedOrRefundedOrders: import_native_modules22.IAP.getCompletedOrRefundedOrders,
2681
- completeProductGrant: import_native_modules22.IAP.completeProductGrant,
2692
+ iapGetProductItemList: import_native_modules23.IAP.getProductItemList,
2693
+ iapCreateOneTimePurchaseOrder: import_native_modules23.iapCreateOneTimePurchaseOrder,
2694
+ processProductGrant: import_native_modules23.processProductGrant,
2695
+ getPendingOrders: import_native_modules23.IAP.getPendingOrders,
2696
+ getCompletedOrRefundedOrders: import_native_modules23.IAP.getCompletedOrRefundedOrders,
2697
+ completeProductGrant: import_native_modules23.IAP.completeProductGrant,
2682
2698
  /** Toss Ads */
2683
- tossAdEventLog
2699
+ tossAdEventLog,
2700
+ /** Private */
2701
+ memoryDebugLog: webViewMemoryDebugLog
2684
2702
  }
2685
2703
  });
2686
2704
  const headerPropForExternalWebView = (0, import_react28.useMemo)(() => {
@@ -2709,10 +2727,11 @@ function WebView({ type, local, onMessage, ...props }) {
2709
2727
  webBackHandler.handleWebBack();
2710
2728
  return true;
2711
2729
  };
2712
- import_react_native38.BackHandler.addEventListener("hardwareBackPress", callback);
2713
- return () => import_react_native38.BackHandler.removeEventListener("hardwareBackPress", callback);
2730
+ import_react_native39.BackHandler.addEventListener("hardwareBackPress", callback);
2731
+ return () => import_react_native39.BackHandler.removeEventListener("hardwareBackPress", callback);
2714
2732
  }, [webBackHandler]);
2715
2733
  const globalScripts = useGlobalScripts();
2734
+ const handleWebViewProcessDidTerminate = useHandleWebViewProcessDidTerminate(webViewRef);
2716
2735
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2717
2736
  BaseWebView,
2718
2737
  {
@@ -2735,14 +2754,14 @@ function WebView({ type, local, onMessage, ...props }) {
2735
2754
  props.onNavigationStateChange?.(event);
2736
2755
  webBackHandler.onNavigationStateChange(event);
2737
2756
  },
2738
- userAgent: import_react_native38.Platform.OS === "ios" ? userAgent : void 0,
2757
+ userAgent: import_react_native39.Platform.OS === "ios" ? userAgent : void 0,
2739
2758
  sharedCookiesEnabled: true,
2740
2759
  webviewDebuggingEnabled: webViewDebuggingEnabled,
2741
2760
  thirdPartyCookiesEnabled: true,
2742
2761
  onMessage: handler.onMessage,
2743
2762
  injectedJavaScript: globalScripts.afterLoad,
2744
2763
  injectedJavaScriptBeforeContentLoaded: mergeScripts(handler.injectedJavaScript, globalScripts.beforeLoad),
2745
- decelerationRate: import_react_native38.Platform.OS === "ios" ? 1 : void 0,
2764
+ decelerationRate: import_react_native39.Platform.OS === "ios" ? 1 : void 0,
2746
2765
  allowsBackForwardNavigationGestures,
2747
2766
  onShouldStartLoadWithRequest: (event) => {
2748
2767
  try {
@@ -2750,7 +2769,7 @@ function WebView({ type, local, onMessage, ...props }) {
2750
2769
  if (["https:", "http:"].includes(url.protocol)) {
2751
2770
  return true;
2752
2771
  } else {
2753
- import_react_native38.Linking.openURL(convertIntentURL(url) ?? url.href);
2772
+ import_react_native39.Linking.openURL(convertIntentURL(url) ?? url.href);
2754
2773
  return false;
2755
2774
  }
2756
2775
  } catch (error) {
@@ -2766,7 +2785,9 @@ function WebView({ type, local, onMessage, ...props }) {
2766
2785
  "servicetoss://*",
2767
2786
  "supertoss://*",
2768
2787
  "intent://*"
2769
- ]
2788
+ ],
2789
+ onContentProcessDidTerminate: handleWebViewProcessDidTerminate,
2790
+ onRenderProcessGone: handleWebViewProcessDidTerminate
2770
2791
  }
2771
2792
  );
2772
2793
  }
package/dist/index.js CHANGED
@@ -691,15 +691,18 @@ import { useCallback as useCallback7 } from "react";
691
691
  function useCloseConfirm() {
692
692
  const { brandDisplayName } = getAppsInTossGlobals();
693
693
  const { openConfirm } = useDialog3();
694
- return useCallback7(async ({ onEntered }) => {
695
- return await openConfirm({
696
- title: `${josa2(brandDisplayName, "\uC744/\uB97C")} \uC885\uB8CC\uD560\uAE4C\uC694?`,
697
- leftButton: "\uCDE8\uC18C",
698
- rightButton: "\uC885\uB8CC\uD558\uAE30",
699
- closeOnDimmerClick: true,
700
- onEntered
701
- });
702
- }, [brandDisplayName, openConfirm]);
694
+ return useCallback7(
695
+ async ({ onEntered }) => {
696
+ return await openConfirm({
697
+ title: `${josa2(brandDisplayName, "\uC744/\uB97C")} \uC885\uB8CC\uD560\uAE4C\uC694?`,
698
+ leftButton: "\uCDE8\uC18C",
699
+ rightButton: "\uC885\uB8CC\uD558\uAE30",
700
+ closeOnDimmerClick: true,
701
+ onEntered
702
+ });
703
+ },
704
+ [brandDisplayName, openConfirm]
705
+ );
703
706
  }
704
707
 
705
708
  // src/components/NavigationBar/common/useNavigationBarLogging.tsx
@@ -938,30 +941,10 @@ function Menu({ title, iconURL, onPress }) {
938
941
  marginRight: 16,
939
942
  backgroundColor: iconBackgroundColor
940
943
  },
941
- children: iconName ? /* @__PURE__ */ jsx5(
942
- Asset2.Icon,
943
- {
944
- frameShape: { width: 20, height: 20 },
945
- color: globals.brandPrimaryColor,
946
- name: iconName
947
- }
948
- ) : /* @__PURE__ */ jsx5(
949
- Asset2.Image,
950
- {
951
- frameShape: { width: 20, height: 20 },
952
- source: { uri: iconURL }
953
- }
954
- )
955
- }
956
- ),
957
- contents: /* @__PURE__ */ jsx5(
958
- ListRow.Texts,
959
- {
960
- type: "1RowTypeA",
961
- top: title,
962
- topProps: { color: adaptive.grey700 }
944
+ children: iconName ? /* @__PURE__ */ jsx5(Asset2.Icon, { frameShape: { width: 20, height: 20 }, color: globals.brandPrimaryColor, name: iconName }) : /* @__PURE__ */ jsx5(Asset2.Image, { frameShape: { width: 20, height: 20 }, source: { uri: iconURL } })
963
945
  }
964
946
  ),
947
+ contents: /* @__PURE__ */ jsx5(ListRow.Texts, { type: "1RowTypeA", top: title, topProps: { color: adaptive.grey700 } }),
965
948
  verticalPadding: "extraSmall",
966
949
  onPress: () => {
967
950
  logging.menuClick({ title });
@@ -1051,7 +1034,9 @@ function PermissionsMenu() {
1051
1034
  {
1052
1035
  title: "\uAD8C\uD55C \uC124\uC815",
1053
1036
  iconURL: "https://static.toss.im/icons/png/4x/icon-setting-mono.png",
1054
- onPress: () => openURL4(`servicetoss://apps-in-toss-menu/permissions?appName=${Granite6.appName}&displayAppName=${globals.brandDisplayName}`)
1037
+ onPress: () => openURL4(
1038
+ `servicetoss://apps-in-toss-menu/permissions?appName=${Granite6.appName}&displayAppName=${globals.brandDisplayName}`
1039
+ )
1055
1040
  }
1056
1041
  );
1057
1042
  }
@@ -1154,17 +1139,15 @@ function useMoreButtonBottomSheet() {
1154
1139
  onClose: handleClose,
1155
1140
  onExited: exit,
1156
1141
  children: /* @__PURE__ */ jsxs2(List, { rowSeparator: "none", children: [
1157
- itemList.map(
1158
- (item) => /* @__PURE__ */ jsx8(
1159
- Menu,
1160
- {
1161
- title: item.contactItemName,
1162
- iconURL: item.contactIconUrl,
1163
- onPress: () => openURL5(item.contactUri)
1164
- },
1165
- item.contactItemName
1166
- )
1167
- ),
1142
+ itemList.map((item) => /* @__PURE__ */ jsx8(
1143
+ Menu,
1144
+ {
1145
+ title: item.contactItemName,
1146
+ iconURL: item.contactIconUrl,
1147
+ onPress: () => openURL5(item.contactUri)
1148
+ },
1149
+ item.contactItemName
1150
+ )),
1168
1151
  isShareListMenuSupported && /* @__PURE__ */ jsx8(AppShareListMenu, {}),
1169
1152
  isPermissionsMenuSupported && /* @__PURE__ */ jsx8(PermissionsMenu, {})
1170
1153
  ] })
@@ -1586,7 +1569,7 @@ import {
1586
1569
  isMinVersionSupported as isMinVersionSupported4
1587
1570
  } from "@apps-in-toss/native-modules";
1588
1571
 
1589
- // ../../.yarn/cache/es-toolkit-npm-1.34.1-4cd6371dcb-aab6d07be3.zip/node_modules/es-toolkit/dist/function/noop.mjs
1572
+ // ../../../.yarn/cache/es-toolkit-npm-1.34.1-4cd6371dcb-aab6d07be3.zip/node_modules/es-toolkit/dist/function/noop.mjs
1590
1573
  function noop() {
1591
1574
  }
1592
1575
 
@@ -1693,16 +1676,13 @@ function postEventTracking(params) {
1693
1676
  deviceIdType: "NONE",
1694
1677
  platform: "RN"
1695
1678
  });
1696
- return fetch(
1697
- endpoint,
1698
- {
1699
- method: "POST",
1700
- headers: {
1701
- "Content-Type": "application/json"
1702
- },
1703
- body: bodyJSON
1704
- }
1705
- ).catch(noop);
1679
+ return fetch(endpoint, {
1680
+ method: "POST",
1681
+ headers: {
1682
+ "Content-Type": "application/json"
1683
+ },
1684
+ body: bodyJSON
1685
+ }).catch(noop);
1706
1686
  }
1707
1687
 
1708
1688
  // src/ads/integratedAd.ts
@@ -2480,6 +2460,42 @@ function useTopNavigation() {
2480
2460
  };
2481
2461
  }
2482
2462
 
2463
+ // src/hooks/useWebViewMemoryDebug.tsx
2464
+ import { getOperationalEnvironment as getOperationalEnvironment7, INTERNAL__module as INTERNAL__module7 } from "@apps-in-toss/native-modules";
2465
+ import { Granite as Granite9 } from "@granite-js/react-native";
2466
+ import { useToast } from "@toss/tds-react-native";
2467
+ function useHandleWebViewProcessDidTerminate(webViewRef) {
2468
+ const toast = useToast();
2469
+ return () => {
2470
+ webViewDebugLog("AppsInTossWebViewProcessDidTerminate", {});
2471
+ toast.open("\uBB38\uC81C\uAC00 \uC0DD\uACA8\uC11C \uBBF8\uB2C8\uC571\uC744 \uB2E4\uC2DC \uC2DC\uC791\uD588\uC5B4\uC694.", {
2472
+ type: "bottom",
2473
+ lottie: `https://static.toss.im/lotties-common/check-green-spot.json`
2474
+ });
2475
+ webViewRef.current?.reload();
2476
+ };
2477
+ }
2478
+ async function webViewMemoryDebugLog(params) {
2479
+ webViewDebugLog("AppsInTossWebViewMemoryDebug", params);
2480
+ }
2481
+ function webViewDebugLog(logName, params) {
2482
+ const global2 = getAppsInTossGlobals();
2483
+ const event = {
2484
+ log_name: logName,
2485
+ log_type: "debug",
2486
+ params: {
2487
+ ...params,
2488
+ app_name: Granite9.appName,
2489
+ deployment_id: global2.deploymentId
2490
+ }
2491
+ };
2492
+ if (getOperationalEnvironment7() === "toss") {
2493
+ INTERNAL__module7.tossCoreEventLog(event);
2494
+ } else {
2495
+ console.log("[webViewDebugLog]", event);
2496
+ }
2497
+ }
2498
+
2483
2499
  // src/utils/log.ts
2484
2500
  import { eventLog as eventLogNative } from "@apps-in-toss/native-modules";
2485
2501
  import { getSchemeUri as getSchemeUri7 } from "@granite-js/react-native";
@@ -2667,7 +2683,9 @@ function WebView({ type, local, onMessage, ...props }) {
2667
2683
  getCompletedOrRefundedOrders: IAP.getCompletedOrRefundedOrders,
2668
2684
  completeProductGrant: IAP.completeProductGrant,
2669
2685
  /** Toss Ads */
2670
- tossAdEventLog
2686
+ tossAdEventLog,
2687
+ /** Private */
2688
+ memoryDebugLog: webViewMemoryDebugLog
2671
2689
  }
2672
2690
  });
2673
2691
  const headerPropForExternalWebView = useMemo7(() => {
@@ -2700,6 +2718,7 @@ function WebView({ type, local, onMessage, ...props }) {
2700
2718
  return () => BackHandler2.removeEventListener("hardwareBackPress", callback);
2701
2719
  }, [webBackHandler]);
2702
2720
  const globalScripts = useGlobalScripts();
2721
+ const handleWebViewProcessDidTerminate = useHandleWebViewProcessDidTerminate(webViewRef);
2703
2722
  return /* @__PURE__ */ jsx18(
2704
2723
  BaseWebView,
2705
2724
  {
@@ -2753,7 +2772,9 @@ function WebView({ type, local, onMessage, ...props }) {
2753
2772
  "servicetoss://*",
2754
2773
  "supertoss://*",
2755
2774
  "intent://*"
2756
- ]
2775
+ ],
2776
+ onContentProcessDidTerminate: handleWebViewProcessDidTerminate,
2777
+ onRenderProcessGone: handleWebViewProcessDidTerminate
2757
2778
  }
2758
2779
  );
2759
2780
  }
package/package.json CHANGED
@@ -1,10 +1,9 @@
1
1
  {
2
2
  "name": "@apps-in-toss/framework",
3
3
  "type": "module",
4
- "version": "1.6.0",
4
+ "version": "1.6.1",
5
5
  "description": "The framework for Apps In Toss",
6
6
  "scripts": {
7
- "prepack": "yarn build",
8
7
  "typecheck": "tsc --noEmit",
9
8
  "test": "vitest --no-watch",
10
9
  "test:no-parallel": "vitest --no-watch --config=vitest.no-parallel.config.mts",
@@ -56,11 +55,11 @@
56
55
  "ait": "./bin/ait.js"
57
56
  },
58
57
  "dependencies": {
59
- "@apps-in-toss/analytics": "1.6.0",
60
- "@apps-in-toss/cli": "1.6.0",
61
- "@apps-in-toss/native-modules": "1.6.0",
62
- "@apps-in-toss/plugins": "1.6.0",
63
- "@apps-in-toss/types": "1.6.0",
58
+ "@apps-in-toss/analytics": "1.6.1",
59
+ "@apps-in-toss/cli": "1.6.1",
60
+ "@apps-in-toss/native-modules": "1.6.1",
61
+ "@apps-in-toss/plugins": "1.6.1",
62
+ "@apps-in-toss/types": "1.6.1",
64
63
  "es-hangul": "^2.3.2"
65
64
  },
66
65
  "devDependencies": {
@@ -75,9 +74,9 @@
75
74
  "@types/react": "18.3.3",
76
75
  "es-toolkit": "^1.34.1",
77
76
  "eslint": "^9.7.0",
78
- "execa": "^9.5.2",
77
+ "execa": "9.3.0",
79
78
  "jsdom": "^25.0.1",
80
- "kill-port": "^2.0.1",
79
+ "kill-port": "2.0.1",
81
80
  "react": "18.2.0",
82
81
  "react-native": "0.72.6",
83
82
  "tsup": "^8.3.5",
@@ -92,9 +91,5 @@
92
91
  "@types/react": "*",
93
92
  "react": "*",
94
93
  "react-native": "*"
95
- },
96
- "publishConfig": {
97
- "access": "public"
98
- },
99
- "gitHead": "ee1ce0d363246b54246472599e0312cd2d2c1ff5"
100
- }
94
+ }
95
+ }