@apps-in-toss/framework 0.0.31 → 0.0.33

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.js CHANGED
@@ -445,11 +445,14 @@ __export(async_bridges_exports, {
445
445
  fetchContacts: () => fetchContacts,
446
446
  getClipboardText: () => getClipboardText,
447
447
  getCurrentLocation: () => getCurrentLocation,
448
+ getGameCenterGameProfile: () => getGameCenterGameProfile,
448
449
  getTossShareLink: () => getTossShareLink,
449
450
  openCamera: () => openCamera,
451
+ openGameCenterLeaderboard: () => openGameCenterLeaderboard,
450
452
  saveBase64Data: () => saveBase64Data,
451
453
  setClipboardText: () => setClipboardText,
452
- setDeviceOrientation: () => setDeviceOrientation
454
+ setDeviceOrientation: () => setDeviceOrientation,
455
+ submitGameCenterLeaderBoardScore: () => submitGameCenterLeaderBoardScore
453
456
  });
454
457
 
455
458
  // src/native-modules/setClipboardText.ts
@@ -601,6 +604,43 @@ async function saveBase64Data(params) {
601
604
  await AppsInTossModule.saveBase64Data(params);
602
605
  }
603
606
 
607
+ // src/constant/game-center.ts
608
+ var GAME_PROFILE_WEBVIEW_URL = "https://service.toss.im/game-center/profile";
609
+ var GAME_CENTER_MIN_VERSION = {
610
+ android: "5.221.0",
611
+ ios: "5.221.0"
612
+ };
613
+
614
+ // src/native-modules/getGameCenterGameProfile.ts
615
+ async function getGameCenterGameProfile() {
616
+ const isSupported = isMinVersionSupported(GAME_CENTER_MIN_VERSION);
617
+ if (!isSupported) {
618
+ return;
619
+ }
620
+ return AppsInTossModule.getGameCenterGameProfile({});
621
+ }
622
+
623
+ // src/native-modules/openGameCenterLeaderboard.ts
624
+ import { openURL } from "react-native-bedrock";
625
+ async function openGameCenterLeaderboard() {
626
+ if (!isMinVersionSupported(GAME_CENTER_MIN_VERSION)) {
627
+ return;
628
+ }
629
+ const url = new URL("servicetoss://game-center/leaderboard?_navbar=hide");
630
+ url.searchParams.set("appName", getAppName());
631
+ url.searchParams.set("referrer", `appsintoss.${getAppName()}`);
632
+ return openURL(url.toString());
633
+ }
634
+
635
+ // src/native-modules/submitGameCenterLeaderBoardScore.ts
636
+ async function submitGameCenterLeaderBoardScore(params) {
637
+ const isSupported = isMinVersionSupported(GAME_CENTER_MIN_VERSION);
638
+ if (!isSupported) {
639
+ return;
640
+ }
641
+ return AppsInTossModule.submitGameCenterLeaderBoardScore(params);
642
+ }
643
+
604
644
  // src/core/registerApp.tsx
605
645
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
606
646
  function AppsInTossContainer(Container, { children, ...initialProps }) {
@@ -755,38 +795,15 @@ loadAdMobRewardedAd.isSupported = createIsSupported();
755
795
  showAdMobInterstitialAd.isSupported = createIsSupported();
756
796
  showAdMobRewardedAd.isSupported = createIsSupported();
757
797
 
758
- // src/native-modules/getTossAppVersion.ts
759
- function getTossAppVersion() {
760
- return AppsInTossModule.tossAppVersion;
761
- }
762
-
763
798
  // src/native-modules/getDeviceId.ts
764
799
  function getDeviceId() {
765
800
  return AppsInTossModule.deviceId;
766
801
  }
767
802
 
768
- // src/native-modules/storage.ts
769
- function getItem(key) {
770
- return AppsInTossModule.getStorageItem({ key });
771
- }
772
- function setItem(key, value) {
773
- return AppsInTossModule.setStorageItem({
774
- key,
775
- value
776
- });
777
- }
778
- function removeItem(key) {
779
- return AppsInTossModule.removeStorageItem({ key });
780
- }
781
- function clearItems() {
782
- return AppsInTossModule.clearStorage({});
803
+ // src/native-modules/getTossAppVersion.ts
804
+ function getTossAppVersion() {
805
+ return AppsInTossModule.tossAppVersion;
783
806
  }
784
- var Storage = {
785
- getItem,
786
- setItem,
787
- removeItem,
788
- clearItems
789
- };
790
807
 
791
808
  // src/native-modules/iap.ts
792
809
  async function createOneTimePurchaseOrder(params) {
@@ -814,6 +831,29 @@ var IAP = {
814
831
  getProductItemList
815
832
  };
816
833
 
834
+ // src/native-modules/storage.ts
835
+ function getItem(key) {
836
+ return AppsInTossModule.getStorageItem({ key });
837
+ }
838
+ function setItem(key, value) {
839
+ return AppsInTossModule.setStorageItem({
840
+ key,
841
+ value
842
+ });
843
+ }
844
+ function removeItem(key) {
845
+ return AppsInTossModule.removeStorageItem({ key });
846
+ }
847
+ function clearItems() {
848
+ return AppsInTossModule.clearStorage({});
849
+ }
850
+ var Storage = {
851
+ getItem,
852
+ setItem,
853
+ removeItem,
854
+ clearItems
855
+ };
856
+
817
857
  // src/native-modules/index.ts
818
858
  var TossPay = {
819
859
  checkoutPayment
@@ -828,11 +868,13 @@ var GoogleAdMob = {
828
868
  // src/components/WebView.tsx
829
869
  import {
830
870
  ExternalWebViewScreen,
831
- PartnerWebViewScreen
871
+ PartnerWebViewScreen,
872
+ tdsEvent,
873
+ usePartnerNavigation
832
874
  } from "@toss-design-system/react-native";
833
875
  import { useSafeAreaBottom, useSafeAreaTop as useSafeAreaTop2 } from "@toss-design-system/react-native/private";
834
- import { useCallback as useCallback3, useMemo as useMemo3 } from "react";
835
- import { Platform as Platform6 } from "react-native";
876
+ import { useCallback as useCallback4, useMemo as useMemo3 } from "react";
877
+ import { Platform as Platform7 } from "react-native";
836
878
  import { getSchemeUri as getSchemeUri4, useBedrockEvent } from "react-native-bedrock";
837
879
  import * as bedrockAsyncBridges from "react-native-bedrock/async-bridges";
838
880
  import * as bedrockConstantBridges from "react-native-bedrock/constant-bridges";
@@ -841,26 +883,343 @@ import * as bedrockConstantBridges from "react-native-bedrock/constant-bridges";
841
883
  import {
842
884
  WebView as PlainWebView
843
885
  } from "@react-native-bedrock/native/react-native-webview";
886
+ import { useDialog as useDialog2 } from "@toss-design-system/react-native";
887
+ import { josa as josa2 } from "es-hangul";
888
+ import { forwardRef, useCallback as useCallback2, useEffect as useEffect4, useState as useState2 } from "react";
889
+ import { BackHandler, Platform as Platform6 } from "react-native";
890
+ import { closeView as closeView2, setIosSwipeGestureEnabled } from "react-native-bedrock";
891
+
892
+ // src/components/GameProfile.tsx
893
+ import { Loader } from "@toss-design-system/react-native";
894
+ import { useEffect as useEffect3 } from "react";
895
+ import { Pressable, View } from "react-native";
896
+
897
+ // src/hooks/useGameCenterProfile.ts
844
898
  import { useDialog } from "@toss-design-system/react-native";
845
899
  import { josa } from "es-hangul";
846
- import { forwardRef, useCallback, useEffect as useEffect3 } from "react";
847
- import { BackHandler, Platform as Platform5, View as View3 } from "react-native";
848
- import { closeView, setIosSwipeGestureEnabled } from "react-native-bedrock";
900
+ import { useCallback, useRef, useState } from "react";
901
+ import { closeView, openURL as openURL3 } from "react-native-bedrock";
902
+
903
+ // src/components/GameProfileToast.tsx
904
+ import { Asset, Toast } from "@toss-design-system/react-native";
905
+ import { AdaptiveColorProvider, ColorPreferenceProvider, useOverlay } from "@toss-design-system/react-native/private";
906
+ import { jsx as jsx2 } from "react/jsx-runtime";
907
+ var useGameProfileToast = () => {
908
+ const overlay = useOverlay();
909
+ const openGameProfileToast = (nickname, profileImageUri) => {
910
+ return new Promise((resolve) => {
911
+ overlay.open(({ isOpen, close, exit }) => {
912
+ return /* @__PURE__ */ jsx2(ColorPreferenceProvider, { colorPreference: "dark", children: /* @__PURE__ */ jsx2(AdaptiveColorProvider, { children: /* @__PURE__ */ jsx2(
913
+ Toast,
914
+ {
915
+ open: isOpen,
916
+ onClose: () => {
917
+ resolve();
918
+ close();
919
+ },
920
+ onExited: exit,
921
+ position: "top",
922
+ text: `${nickname}\uB2D8 \uBC18\uAC00\uC6CC\uC694!`,
923
+ icon: /* @__PURE__ */ jsx2(
924
+ Asset.Image,
925
+ {
926
+ style: { borderRadius: 64, overflow: "hidden" },
927
+ frameShape: Asset.frameShape.CleanW32,
928
+ source: { uri: profileImageUri }
929
+ }
930
+ )
931
+ }
932
+ ) }) });
933
+ });
934
+ });
935
+ };
936
+ return { openGameProfileToast };
937
+ };
938
+
939
+ // src/utils/error.ts
940
+ var DEFAULT_ERROR = {
941
+ title: "\uC7A0\uC2DC \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694",
942
+ description: "\uBB38\uC81C\uAC00 \uACC4\uC18D\uB418\uBA74 \uD1A0\uC2A4 \uACE0\uAC1D\uC13C\uD130(1599-4905)\uB85C \uBB38\uC758\uD574\uC8FC\uC138\uC694."
943
+ };
944
+
945
+ // src/utils/market.ts
946
+ import { Platform as Platform2 } from "react-native";
947
+ var PLAYSTORE_LINK = "https://play.google.com/store/apps/details?id=viva.republica.toss";
948
+ var APPSTORE_LINK = "https://itunes.apple.com/app/id839333328";
949
+ var getMarketLink = () => {
950
+ return Platform2.OS === "android" ? PLAYSTORE_LINK : APPSTORE_LINK;
951
+ };
952
+
953
+ // src/utils/openTransparentWebView.ts
954
+ import { openURL as openURL2 } from "react-native-bedrock";
955
+
956
+ // src/native-event-emitter/internal/onVisibilityChangedByTransparentServiceWeb.ts
957
+ function onVisibilityChangedByTransparentServiceWeb(eventParams) {
958
+ return appsInTossEvent.addEventListener("onVisibilityChangedByTransparentServiceWeb", eventParams);
959
+ }
960
+
961
+ // src/private.ts
962
+ var INTERNAL__onVisibilityChangedByTransparentServiceWeb = onVisibilityChangedByTransparentServiceWeb;
963
+
964
+ // src/utils/openTransparentWebView.ts
965
+ var openTransparentWebView = ({
966
+ webUrl,
967
+ cleanupWhenDismissed = true,
968
+ onEvent,
969
+ onError,
970
+ callbackId = "fn",
971
+ params
972
+ }) => {
973
+ const url = new URL("supertoss://transparent-service-web");
974
+ url.searchParams.set("url", webUrl);
975
+ url.searchParams.set("onVisibilityChangeCallback", callbackId);
976
+ Object.entries(params ?? {}).forEach(([key, value]) => {
977
+ url.searchParams.set(key, value);
978
+ });
979
+ const cleanup = INTERNAL__onVisibilityChangedByTransparentServiceWeb({
980
+ options: { callbackId },
981
+ onError: (error) => {
982
+ onError(error);
983
+ cleanup();
984
+ },
985
+ onEvent: (value) => {
986
+ onEvent(value);
987
+ if (cleanupWhenDismissed && value === true) {
988
+ cleanup();
989
+ }
990
+ }
991
+ });
992
+ openURL2(url.toString());
993
+ };
994
+
995
+ // src/hooks/useGameCenterProfile.ts
996
+ var useGameCenterProfile = (isReadyForProfileUI) => {
997
+ const [profileData, setProfileData] = useState(void 0);
998
+ const [isProfileDataLoading, setIsProfileDataLoading] = useState(true);
999
+ const [isProfileDataRefetching, setIsProfileDataRefetching] = useState(false);
1000
+ const shouldShowLoadingOverlay = isProfileDataLoading && isReadyForProfileUI;
1001
+ const shouldShowProfileNotFoundOverlay = profileData?.statusCode === "PROFILE_NOT_FOUND" && isReadyForProfileUI && !isProfileDataRefetching;
1002
+ const canShowBottomSheetOrToast = !isProfileDataLoading && isReadyForProfileUI;
1003
+ const [isWebviewLoading, setIsWebviewLoading] = useState(false);
1004
+ const isCompletedProfileFlow = useRef(false);
1005
+ const { openAlert, openConfirm } = useDialog();
1006
+ const { openGameProfileToast } = useGameProfileToast();
1007
+ const openErrorAlert = useCallback(async () => {
1008
+ await openAlert({
1009
+ title: DEFAULT_ERROR.title,
1010
+ description: DEFAULT_ERROR.description
1011
+ });
1012
+ closeView();
1013
+ }, [openAlert]);
1014
+ const openProfileWebview = useCallback(() => {
1015
+ if (isWebviewLoading) {
1016
+ return;
1017
+ }
1018
+ setIsWebviewLoading(true);
1019
+ openTransparentWebView({
1020
+ webUrl: `${GAME_PROFILE_WEBVIEW_URL}?appName=${getAppName()}&referrer=appsintoss.${getAppName()}`,
1021
+ onEvent: async (isClosedTransparentWebView) => {
1022
+ if (isClosedTransparentWebView) {
1023
+ try {
1024
+ setIsWebviewLoading(false);
1025
+ setIsProfileDataRefetching(true);
1026
+ const data = await getGameCenterGameProfile();
1027
+ setProfileData(data);
1028
+ setIsProfileDataRefetching(false);
1029
+ if (data?.statusCode === "SUCCESS") {
1030
+ openGameProfileToast(data.nickname, data.profileImageUri);
1031
+ }
1032
+ } catch (_) {
1033
+ setIsProfileDataRefetching(false);
1034
+ openErrorAlert();
1035
+ }
1036
+ }
1037
+ },
1038
+ onError: () => {
1039
+ openErrorAlert();
1040
+ }
1041
+ });
1042
+ }, [isWebviewLoading, openGameProfileToast, openErrorAlert]);
1043
+ const updateAppToSupportedMinVersion = useCallback(async () => {
1044
+ const upddateConfirmDialogLabel = {
1045
+ title: `${josa(getAppsInTossGlobals().brandDisplayName, "\uC744/\uB97C")} \uD558\uB824\uBA74
1046
+ \uC571\uC744 \uC5C5\uB370\uC774\uD2B8\uD574\uC8FC\uC138\uC694`,
1047
+ leftButton: "\uB2EB\uAE30",
1048
+ rightButton: "\uC5C5\uB370\uC774\uD2B8\uD558\uAE30"
1049
+ };
1050
+ const isConfirmed = await openConfirm({
1051
+ title: upddateConfirmDialogLabel.title,
1052
+ leftButton: upddateConfirmDialogLabel.leftButton,
1053
+ rightButton: upddateConfirmDialogLabel.rightButton,
1054
+ closeOnDimmerClick: true
1055
+ });
1056
+ if (!isConfirmed) {
1057
+ closeView();
1058
+ return;
1059
+ }
1060
+ const STORE_SCHEME = getMarketLink();
1061
+ openURL3(`supertoss://web?url=${STORE_SCHEME}&external=browser`);
1062
+ }, [openConfirm]);
1063
+ return {
1064
+ profileData,
1065
+ isProfileDataLoading,
1066
+ isProfileDataRefetching,
1067
+ shouldShowLoadingOverlay,
1068
+ shouldShowProfileNotFoundOverlay,
1069
+ canShowBottomSheetOrToast,
1070
+ isCompletedProfileFlow,
1071
+ updateAppToSupportedMinVersion,
1072
+ setIsProfileDataLoading,
1073
+ openProfileWebview,
1074
+ setProfileData,
1075
+ openErrorAlert,
1076
+ openGameProfileToast
1077
+ };
1078
+ };
1079
+
1080
+ // src/utils/zIndex.ts
1081
+ var Z_INDEX = {
1082
+ /* 게임 프로필을 위한 overlay
1083
+ */
1084
+ PROFILE_OVERLAY: 9998,
1085
+ // 게임을 종료할 수 있는 X 버튼
1086
+ CLOSE_BUTTON: 9999
1087
+ };
1088
+
1089
+ // src/components/GameProfile.tsx
1090
+ import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1091
+ var GameProfile = ({ children, isReadyForProfileUI }) => {
1092
+ const {
1093
+ profileData,
1094
+ isProfileDataRefetching,
1095
+ shouldShowLoadingOverlay,
1096
+ shouldShowProfileNotFoundOverlay,
1097
+ canShowBottomSheetOrToast,
1098
+ isCompletedProfileFlow,
1099
+ openProfileWebview,
1100
+ updateAppToSupportedMinVersion,
1101
+ setIsProfileDataLoading,
1102
+ setProfileData,
1103
+ openErrorAlert,
1104
+ openGameProfileToast
1105
+ } = useGameCenterProfile(isReadyForProfileUI);
1106
+ useEffect3(() => {
1107
+ try {
1108
+ const getProfileData = async () => {
1109
+ const data = await getGameCenterGameProfile();
1110
+ setProfileData(data);
1111
+ setIsProfileDataLoading(false);
1112
+ };
1113
+ getProfileData();
1114
+ } catch (_) {
1115
+ openErrorAlert();
1116
+ setIsProfileDataLoading(false);
1117
+ }
1118
+ }, []);
1119
+ useEffect3(() => {
1120
+ const handleGameProfileFlow = async () => {
1121
+ if (!canShowBottomSheetOrToast) {
1122
+ return;
1123
+ }
1124
+ if (isCompletedProfileFlow.current) {
1125
+ return;
1126
+ }
1127
+ isCompletedProfileFlow.current = true;
1128
+ if (!isMinVersionSupported(GAME_CENTER_MIN_VERSION)) {
1129
+ updateAppToSupportedMinVersion();
1130
+ return;
1131
+ }
1132
+ if (profileData?.statusCode === "SUCCESS") {
1133
+ openGameProfileToast(profileData.nickname, profileData.profileImageUri);
1134
+ return;
1135
+ }
1136
+ if (profileData?.statusCode === "PROFILE_NOT_FOUND") {
1137
+ openProfileWebview();
1138
+ }
1139
+ };
1140
+ handleGameProfileFlow();
1141
+ }, [
1142
+ canShowBottomSheetOrToast,
1143
+ isCompletedProfileFlow,
1144
+ openGameProfileToast,
1145
+ openProfileWebview,
1146
+ profileData,
1147
+ updateAppToSupportedMinVersion
1148
+ ]);
1149
+ if (!isMinVersionSupported(GAME_CENTER_MIN_VERSION)) {
1150
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
1151
+ /* @__PURE__ */ jsx3(View, { style: { flex: 1, position: "relative" }, children }),
1152
+ /* @__PURE__ */ jsx3(
1153
+ Pressable,
1154
+ {
1155
+ style: {
1156
+ ...overlayStyle
1157
+ },
1158
+ onPress: () => {
1159
+ updateAppToSupportedMinVersion();
1160
+ }
1161
+ }
1162
+ )
1163
+ ] });
1164
+ }
1165
+ if (shouldShowLoadingOverlay || isProfileDataRefetching) {
1166
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
1167
+ /* @__PURE__ */ jsx3(View, { style: { flex: 1, position: "relative" }, children }),
1168
+ /* @__PURE__ */ jsx3(
1169
+ View,
1170
+ {
1171
+ style: {
1172
+ ...overlayStyle,
1173
+ justifyContent: "center",
1174
+ alignItems: "center",
1175
+ backgroundColor: "rgba(0, 0, 0, 0.2)"
1176
+ },
1177
+ children: /* @__PURE__ */ jsx3(Loader, { size: "large", type: "light" })
1178
+ }
1179
+ )
1180
+ ] });
1181
+ }
1182
+ if (shouldShowProfileNotFoundOverlay) {
1183
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
1184
+ /* @__PURE__ */ jsx3(View, { style: { flex: 1, position: "relative" }, children }),
1185
+ shouldShowProfileNotFoundOverlay && /* @__PURE__ */ jsx3(
1186
+ Pressable,
1187
+ {
1188
+ style: {
1189
+ ...overlayStyle
1190
+ },
1191
+ onPress: () => {
1192
+ openProfileWebview();
1193
+ }
1194
+ }
1195
+ )
1196
+ ] });
1197
+ }
1198
+ return /* @__PURE__ */ jsx3(Fragment2, { children: /* @__PURE__ */ jsx3(View, { style: { flex: 1, position: "relative" }, children }) });
1199
+ };
1200
+ var overlayStyle = {
1201
+ position: "absolute",
1202
+ top: 0,
1203
+ left: 0,
1204
+ right: 0,
1205
+ bottom: 0,
1206
+ zIndex: Z_INDEX.PROFILE_OVERLAY
1207
+ };
849
1208
 
850
1209
  // src/components/GameWebViewNavigationBar/GameNavigationBar.tsx
851
1210
  import { SvgXml } from "@react-native-bedrock/native/react-native-svg";
852
1211
  import { PageNavbar } from "@toss-design-system/react-native";
853
- import { Platform as Platform4, TouchableOpacity, View as View2 } from "react-native";
1212
+ import { Platform as Platform5, TouchableOpacity, View as View3 } from "react-native";
854
1213
 
855
1214
  // src/components/GameWebViewNavigationBar/HeaderRight.tsx
856
- import { StyleSheet, View } from "react-native";
1215
+ import { StyleSheet, View as View2 } from "react-native";
857
1216
 
858
1217
  // src/components/GameWebViewNavigationBar/byPlatform.ts
859
- import { Platform as Platform2 } from "react-native";
1218
+ import { Platform as Platform3 } from "react-native";
860
1219
  function byPlatform({
861
1220
  ...props
862
1221
  }) {
863
- return (props[Platform2.OS] ?? props.fallback)();
1222
+ return (props[Platform3.OS] ?? props.fallback)();
864
1223
  }
865
1224
 
866
1225
  // src/components/GameWebViewNavigationBar/constants.ts
@@ -868,18 +1227,18 @@ var RIGHT_MARGIN = 24;
868
1227
  var IOS_DEFAULT_MARGIN = 20;
869
1228
 
870
1229
  // src/components/GameWebViewNavigationBar/HeaderRight.tsx
871
- import { jsx as jsx2 } from "react/jsx-runtime";
1230
+ import { jsx as jsx4 } from "react/jsx-runtime";
872
1231
  function IOSHeaderRight(props) {
873
- return /* @__PURE__ */ jsx2(View, { style: styles.ios, ...props });
1232
+ return /* @__PURE__ */ jsx4(View2, { style: styles.ios, ...props });
874
1233
  }
875
1234
  function AndroidHeaderRight(props) {
876
- return /* @__PURE__ */ jsx2(View, { style: styles.android, ...props });
1235
+ return /* @__PURE__ */ jsx4(View2, { style: styles.android, ...props });
877
1236
  }
878
1237
  function HeaderRight(props) {
879
1238
  return byPlatform({
880
- ios: () => /* @__PURE__ */ jsx2(IOSHeaderRight, { ...props }),
881
- android: () => /* @__PURE__ */ jsx2(AndroidHeaderRight, { ...props }),
882
- fallback: () => /* @__PURE__ */ jsx2(IOSHeaderRight, { ...props })
1239
+ ios: () => /* @__PURE__ */ jsx4(IOSHeaderRight, { ...props }),
1240
+ android: () => /* @__PURE__ */ jsx4(AndroidHeaderRight, { ...props }),
1241
+ fallback: () => /* @__PURE__ */ jsx4(IOSHeaderRight, { ...props })
883
1242
  });
884
1243
  }
885
1244
  var styles = StyleSheet.create({
@@ -894,37 +1253,37 @@ var styles = StyleSheet.create({
894
1253
 
895
1254
  // src/components/GameWebViewNavigationBar/useSafeAreaTop.ts
896
1255
  import { useSafeAreaInsets } from "@react-native-bedrock/native/react-native-safe-area-context";
897
- import { Platform as Platform3 } from "react-native";
1256
+ import { Platform as Platform4 } from "react-native";
898
1257
  function useSafeAreaTop() {
899
1258
  const safeAreaInsets = useSafeAreaInsets();
900
- const hasDynamicIsland = Platform3.OS === "ios" && safeAreaInsets.top > 50;
1259
+ const hasDynamicIsland = Platform4.OS === "ios" && safeAreaInsets.top > 50;
901
1260
  const safeAreaTop = hasDynamicIsland ? safeAreaInsets.top - 5 : safeAreaInsets.top;
902
1261
  return safeAreaTop;
903
1262
  }
904
1263
 
905
1264
  // src/components/GameWebViewNavigationBar/GameNavigationBar.tsx
906
- import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1265
+ import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
907
1266
  var originXML = '<svg fill="none" height="30" viewBox="0 0 30 30" width="30" xmlns="https://www.w3.org/2000/svg"><rect fill="#031832" fill-opacity=".46" height="30" rx="15" width="30"/><rect height="29.5" rx="14.75" stroke="#d9d9ff" stroke-opacity=".11" stroke-width=".5" width="29.5" x=".25" y=".25"/><path clip-rule="evenodd" d="m16.5119 15.0014 4.7092-4.7092c.0929-.0928.1666-.2031.2169-.32441.0503-.12134.0762-.25141.0762-.38276.0001-.13136-.0258-.26144-.076-.38281s-.1239-.23166-.2167-.32457c-.0929-.09291-.2031-.16662-.3245-.21692-.1213-.05031-.2514-.07622-.3827-.07626-.1314-.00004-.2615.0258-.3828.07603-.1214.05023-.2317.12388-.3246.21673l-4.7092 4.70997-4.71-4.70997c-.1897-.17718-.4408-.27373-.70034-.26927s-.5072.10959-.69069.2932c-.1835.1836-.28848.43132-.29279.69087-.00432.25954.09238.51057.26968.70017l4.71004 4.7092-4.71004 4.7092c-.1392.1401-.23385.3183-.27204.5121-.0382.1939-.01823.3946.05739.5771s.20351.3386.36759.4486.35702.169.55456.1697c.25583 0 .51164-.0975.70664-.2925l4.71-4.71 4.7092 4.71c.0927.093.2029.1668.3243.2172.1213.0504.2514.0763.3828.0763s.2614-.0259.3828-.0763c.1213-.0504.2315-.1242.3243-.2172.0929-.0929.1667-.2032.217-.3246s.0762-.2515.0762-.3829-.0259-.2616-.0762-.383-.1241-.2317-.217-.3245z" fill="#fdfdfe" fill-opacity=".89" fill-rule="evenodd"/></svg>';
908
1267
  function GameNavigationBar({ onClose }) {
909
1268
  const safeAreaTop = useSafeAreaTop();
910
- return /* @__PURE__ */ jsxs2(Fragment2, { children: [
911
- /* @__PURE__ */ jsx3(PageNavbar, { preference: { type: "none" } }),
912
- /* @__PURE__ */ jsx3(
913
- View2,
1269
+ return /* @__PURE__ */ jsxs3(Fragment3, { children: [
1270
+ /* @__PURE__ */ jsx5(PageNavbar, { preference: { type: "none" } }),
1271
+ /* @__PURE__ */ jsx5(
1272
+ View3,
914
1273
  {
915
1274
  style: {
916
1275
  width: "100%",
917
- height: Platform4.OS === "ios" ? 44 : 54,
1276
+ height: Platform5.OS === "ios" ? 44 : 54,
918
1277
  flexDirection: "row",
919
1278
  alignItems: "center",
920
1279
  justifyContent: "flex-end",
921
1280
  position: "absolute",
922
- zIndex: 9999,
1281
+ zIndex: Z_INDEX.CLOSE_BUTTON,
923
1282
  marginTop: safeAreaTop,
924
- paddingRight: Platform4.OS === "ios" ? 10 : 8
1283
+ paddingRight: Platform5.OS === "ios" ? 10 : 8
925
1284
  },
926
1285
  pointerEvents: "box-none",
927
- children: /* @__PURE__ */ jsx3(HeaderRight, { children: /* @__PURE__ */ jsx3(
1286
+ children: /* @__PURE__ */ jsx5(HeaderRight, { children: /* @__PURE__ */ jsx5(
928
1287
  TouchableOpacity,
929
1288
  {
930
1289
  hitSlop: { left: 8, right: 8 },
@@ -932,10 +1291,10 @@ function GameNavigationBar({ onClose }) {
932
1291
  accessible: true,
933
1292
  accessibilityLabel: "\uAC8C\uC784\uC885\uB8CC",
934
1293
  style: {
935
- padding: Platform4.OS === "ios" ? 7 : 9
1294
+ padding: Platform5.OS === "ios" ? 7 : 9
936
1295
  },
937
1296
  onPress: onClose,
938
- children: /* @__PURE__ */ jsx3(SvgXml, { xml: originXML, width: 30, height: 30 })
1297
+ children: /* @__PURE__ */ jsx5(SvgXml, { xml: originXML, width: 30, height: 30 })
939
1298
  }
940
1299
  ) })
941
1300
  }
@@ -944,23 +1303,24 @@ function GameNavigationBar({ onClose }) {
944
1303
  }
945
1304
 
946
1305
  // src/components/GameWebView.tsx
947
- import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1306
+ import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
948
1307
  var GameWebView = forwardRef(function GameWebView2(props, ref) {
949
- const { openConfirm } = useDialog();
1308
+ const { openConfirm } = useDialog2();
950
1309
  const { brandDisplayName } = getAppsInTossGlobals();
951
- const handleClose = useCallback(async () => {
1310
+ const [isEntryMessageExited, setIsEntryMessageExited] = useState2(false);
1311
+ const handleClose = useCallback2(async () => {
952
1312
  const isConfirmed = await openConfirm({
953
- title: `${josa(brandDisplayName, "\uC744/\uB97C")} \uC885\uB8CC\uD560\uAE4C\uC694?`,
1313
+ title: `${josa2(brandDisplayName, "\uC744/\uB97C")} \uC885\uB8CC\uD560\uAE4C\uC694?`,
954
1314
  leftButton: "\uCDE8\uC18C",
955
1315
  rightButton: "\uC885\uB8CC\uD558\uAE30",
956
1316
  closeOnDimmerClick: true
957
1317
  });
958
1318
  if (isConfirmed) {
959
- closeView();
1319
+ closeView2();
960
1320
  }
961
1321
  }, [brandDisplayName, openConfirm]);
962
- useEffect3(() => {
963
- if (Platform5.OS === "ios") {
1322
+ useEffect4(() => {
1323
+ if (Platform6.OS === "ios") {
964
1324
  setIosSwipeGestureEnabled({ isEnabled: false });
965
1325
  return () => {
966
1326
  setIosSwipeGestureEnabled({ isEnabled: true });
@@ -968,7 +1328,7 @@ var GameWebView = forwardRef(function GameWebView2(props, ref) {
968
1328
  }
969
1329
  return;
970
1330
  }, []);
971
- useEffect3(() => {
1331
+ useEffect4(() => {
972
1332
  const backHandler = () => {
973
1333
  handleClose();
974
1334
  return true;
@@ -978,14 +1338,21 @@ var GameWebView = forwardRef(function GameWebView2(props, ref) {
978
1338
  BackHandler.removeEventListener("hardwareBackPress", backHandler);
979
1339
  };
980
1340
  }, [handleClose]);
981
- return /* @__PURE__ */ jsxs3(Fragment3, { children: [
982
- /* @__PURE__ */ jsx4(GameNavigationBar, { onClose: handleClose }),
983
- /* @__PURE__ */ jsx4(View3, { style: { flex: 1 }, children: /* @__PURE__ */ jsx4(PlainWebView, { ref, ...props }) })
1341
+ useEffect4(() => {
1342
+ appsInTossEvent.addEventListener("entryMessageExited", {
1343
+ onEvent: () => {
1344
+ setIsEntryMessageExited(true);
1345
+ }
1346
+ });
1347
+ }, []);
1348
+ return /* @__PURE__ */ jsxs4(Fragment4, { children: [
1349
+ /* @__PURE__ */ jsx6(GameNavigationBar, { onClose: handleClose }),
1350
+ getOperationalEnvironment() === "toss" ? /* @__PURE__ */ jsx6(GameProfile, { isReadyForProfileUI: isEntryMessageExited, children: /* @__PURE__ */ jsx6(PlainWebView, { ref, ...props }) }) : /* @__PURE__ */ jsx6(PlainWebView, { ref, ...props })
984
1351
  ] });
985
1352
  });
986
1353
 
987
1354
  // src/bridge-handler/useBridgeHandler.tsx
988
- import { useCallback as useCallback2, useMemo as useMemo2, useRef } from "react";
1355
+ import { useCallback as useCallback3, useMemo as useMemo2, useRef as useRef2 } from "react";
989
1356
  function serializeError(error) {
990
1357
  return JSON.stringify(error, (_, value) => {
991
1358
  if (value instanceof Error) {
@@ -1034,7 +1401,7 @@ function useBridgeHandler({
1034
1401
  eventListenerMap,
1035
1402
  injectedJavaScript: originalInjectedJavaScript
1036
1403
  }) {
1037
- const ref = useRef(null);
1404
+ const ref = useRef2(null);
1038
1405
  const injectedJavaScript = useMemo2(
1039
1406
  () => [
1040
1407
  `window.__CONSTANT_HANDLER_MAP = ${JSON.stringify(
@@ -1061,7 +1428,7 @@ function useBridgeHandler({
1061
1428
  window.__BEDROCK_NATIVE_EMITTER.emit('${functionName}/onError/${eventId}', ${JSON.stringify(error, null, 0)});
1062
1429
  `);
1063
1430
  };
1064
- const $onMessage = useCallback2(
1431
+ const $onMessage = useCallback3(
1065
1432
  async (e) => {
1066
1433
  onMessage?.(e);
1067
1434
  const data = JSON.parse(e.nativeEvent.data);
@@ -1282,12 +1649,12 @@ function useCreateUserAgent({
1282
1649
  }
1283
1650
 
1284
1651
  // src/hooks/useGeolocation.ts
1285
- import { useState, useEffect as useEffect4 } from "react";
1652
+ import { useState as useState3, useEffect as useEffect5 } from "react";
1286
1653
  import { useVisibility } from "react-native-bedrock";
1287
1654
  function useGeolocation({ accuracy, distanceInterval, timeInterval }) {
1288
1655
  const isVisible = useVisibility();
1289
- const [location, setLocation] = useState(null);
1290
- useEffect4(() => {
1656
+ const [location, setLocation] = useState3(null);
1657
+ useEffect5(() => {
1291
1658
  if (!isVisible) {
1292
1659
  return;
1293
1660
  }
@@ -1353,7 +1720,7 @@ var trackScreen = (url) => {
1353
1720
  };
1354
1721
 
1355
1722
  // src/components/WebView.tsx
1356
- import { jsx as jsx5 } from "react/jsx-runtime";
1723
+ import { jsx as jsx7 } from "react/jsx-runtime";
1357
1724
  var appsInTossGlobals = getAppsInTossGlobals();
1358
1725
  var operationalEnvironment = getOperationalEnvironment();
1359
1726
  var TYPES = ["partner", "external", "game"];
@@ -1393,11 +1760,16 @@ function WebView({ type, local, onMessage, ...props }) {
1393
1760
  const top = useSafeAreaTop2();
1394
1761
  const bottom = useSafeAreaBottom();
1395
1762
  const global2 = getAppsInTossGlobals();
1763
+ const partner = usePartnerNavigation();
1396
1764
  const handler = useBridgeHandler({
1397
1765
  onMessage,
1398
1766
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
1399
1767
  eventListenerMap: {
1400
1768
  ...event_bridges_exports,
1769
+ navigationAccessoryEvent: ({ onEvent, onError }) => tdsEvent.addEventListener("navigationAccessoryEvent", {
1770
+ onEvent,
1771
+ onError
1772
+ }),
1401
1773
  backEvent: ({ onEvent, onError, options }) => bedrockEvent.addEventListener("backEvent", { onEvent, onError, options }),
1402
1774
  entryMessageExited: ({ onEvent, onError }) => appsInTossEvent.addEventListener("entryMessageExited", { onEvent, onError }),
1403
1775
  updateLocationEvent: ({ onEvent, onError, options }) => appsInTossEvent.addEventListener("updateLocationEvent", { onEvent, onError, options }),
@@ -1426,6 +1798,8 @@ function WebView({ type, local, onMessage, ...props }) {
1426
1798
  asyncHandlerMap: {
1427
1799
  ...bedrockAsyncBridges,
1428
1800
  ...async_bridges_exports,
1801
+ addAccessoryButton: async (params) => partner.addAccessoryButton(params),
1802
+ removeAccessoryButton: async () => partner.removeAccessoryButton(),
1429
1803
  /** internal */
1430
1804
  openPermissionDialog: AppsInTossModule.openPermissionDialog,
1431
1805
  /** Storage */
@@ -1445,9 +1819,7 @@ function WebView({ type, local, onMessage, ...props }) {
1445
1819
  header: {
1446
1820
  ..."header" in props ? props.header : {},
1447
1821
  icon: toIcon(ensureValue(appsInTossGlobals.brandIcon, "icon")),
1448
- title: ensureValue(appsInTossGlobals.brandDisplayName, "displayName"),
1449
- rightButtons: void 0
1450
- // TODO: onClick 이벤트를 받아야 하기에 런타임에서 설정 받아야 함
1822
+ title: ensureValue(appsInTossGlobals.brandDisplayName, "displayName")
1451
1823
  }
1452
1824
  };
1453
1825
  return headerOnlyProp;
@@ -1469,7 +1841,7 @@ function WebView({ type, local, onMessage, ...props }) {
1469
1841
  }, [type, props]);
1470
1842
  const BaseWebView = WEBVIEW_TYPES[type];
1471
1843
  const webViewDebuggingEnabled = operationalEnvironment === "sandbox";
1472
- const handleNavigationStateChange = useCallback3((event) => {
1844
+ const handleNavigationStateChange = useCallback4((event) => {
1473
1845
  if (event.url) {
1474
1846
  trackScreen(event.url);
1475
1847
  }
@@ -1477,7 +1849,7 @@ function WebView({ type, local, onMessage, ...props }) {
1477
1849
  const userAgent = useCreateUserAgent({
1478
1850
  colorPreference: "light"
1479
1851
  });
1480
- return /* @__PURE__ */ jsx5(
1852
+ return /* @__PURE__ */ jsx7(
1481
1853
  BaseWebView,
1482
1854
  {
1483
1855
  ref: handler.ref,
@@ -1490,14 +1862,15 @@ function WebView({ type, local, onMessage, ...props }) {
1490
1862
  "User-Agent": userAgent
1491
1863
  }
1492
1864
  },
1493
- userAgent: Platform6.OS === "ios" ? userAgent : void 0,
1865
+ userAgent: Platform7.OS === "ios" ? userAgent : void 0,
1494
1866
  sharedCookiesEnabled: true,
1495
1867
  webviewDebuggingEnabled: webViewDebuggingEnabled,
1496
1868
  thirdPartyCookiesEnabled: true,
1497
1869
  onMessage: handler.onMessage,
1498
1870
  onNavigationStateChange: handleNavigationStateChange,
1499
1871
  injectedJavaScript: handler.injectedJavaScript,
1500
- injectedJavaScriptBeforeContentLoaded: handler.injectedJavaScript
1872
+ injectedJavaScriptBeforeContentLoaded: handler.injectedJavaScript,
1873
+ decelerationRate: Platform7.OS === "ios" ? 1 : void 0
1501
1874
  }
1502
1875
  );
1503
1876
  }
@@ -1519,14 +1892,6 @@ var Accuracy2 = /* @__PURE__ */ ((Accuracy3) => {
1519
1892
  return Accuracy3;
1520
1893
  })(Accuracy2 || {});
1521
1894
 
1522
- // src/native-event-emitter/internal/onVisibilityChangedByTransparentServiceWeb.ts
1523
- function onVisibilityChangedByTransparentServiceWeb(eventParams) {
1524
- return appsInTossEvent.addEventListener("onVisibilityChangedByTransparentServiceWeb", eventParams);
1525
- }
1526
-
1527
- // src/private.ts
1528
- var INTERNAL__onVisibilityChangedByTransparentServiceWeb = onVisibilityChangedByTransparentServiceWeb;
1529
-
1530
1895
  // src/index.ts
1531
1896
  export * from "@apps-in-toss/analytics";
1532
1897
  var Analytics2 = {
@@ -1554,15 +1919,18 @@ export {
1554
1919
  getClipboardText,
1555
1920
  getCurrentLocation,
1556
1921
  getDeviceId,
1922
+ getGameCenterGameProfile,
1557
1923
  getOperationalEnvironment,
1558
1924
  getTossAppVersion,
1559
1925
  getTossShareLink,
1560
1926
  isMinVersionSupported,
1561
1927
  openCamera,
1928
+ openGameCenterLeaderboard,
1562
1929
  saveBase64Data,
1563
1930
  setClipboardText,
1564
1931
  setDeviceOrientation,
1565
1932
  startUpdateLocation,
1933
+ submitGameCenterLeaderBoardScore,
1566
1934
  useCreateUserAgent,
1567
1935
  useGeolocation
1568
1936
  };