@apps-in-toss/framework 0.0.30 → 0.0.32

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
@@ -831,8 +871,8 @@ import {
831
871
  PartnerWebViewScreen
832
872
  } from "@toss-design-system/react-native";
833
873
  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";
874
+ import { useCallback as useCallback4, useMemo as useMemo3 } from "react";
875
+ import { Platform as Platform7 } from "react-native";
836
876
  import { getSchemeUri as getSchemeUri4, useBedrockEvent } from "react-native-bedrock";
837
877
  import * as bedrockAsyncBridges from "react-native-bedrock/async-bridges";
838
878
  import * as bedrockConstantBridges from "react-native-bedrock/constant-bridges";
@@ -841,26 +881,343 @@ import * as bedrockConstantBridges from "react-native-bedrock/constant-bridges";
841
881
  import {
842
882
  WebView as PlainWebView
843
883
  } from "@react-native-bedrock/native/react-native-webview";
884
+ import { useDialog as useDialog2 } from "@toss-design-system/react-native";
885
+ import { josa as josa2 } from "es-hangul";
886
+ import { forwardRef, useCallback as useCallback2, useEffect as useEffect4, useState as useState2 } from "react";
887
+ import { BackHandler, Platform as Platform6 } from "react-native";
888
+ import { closeView as closeView2, setIosSwipeGestureEnabled } from "react-native-bedrock";
889
+
890
+ // src/components/GameProfile.tsx
891
+ import { Loader } from "@toss-design-system/react-native";
892
+ import { useEffect as useEffect3 } from "react";
893
+ import { Pressable, View } from "react-native";
894
+
895
+ // src/hooks/useGameCenterProfile.ts
844
896
  import { useDialog } from "@toss-design-system/react-native";
845
897
  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";
898
+ import { useCallback, useRef, useState } from "react";
899
+ import { closeView, openURL as openURL3 } from "react-native-bedrock";
900
+
901
+ // src/components/GameProfileToast.tsx
902
+ import { Asset, Toast } from "@toss-design-system/react-native";
903
+ import { AdaptiveColorProvider, ColorPreferenceProvider, useOverlay } from "@toss-design-system/react-native/private";
904
+ import { jsx as jsx2 } from "react/jsx-runtime";
905
+ var useGameProfileToast = () => {
906
+ const overlay = useOverlay();
907
+ const openGameProfileToast = (nickname, profileImageUri) => {
908
+ return new Promise((resolve) => {
909
+ overlay.open(({ isOpen, close, exit }) => {
910
+ return /* @__PURE__ */ jsx2(ColorPreferenceProvider, { colorPreference: "dark", children: /* @__PURE__ */ jsx2(AdaptiveColorProvider, { children: /* @__PURE__ */ jsx2(
911
+ Toast,
912
+ {
913
+ open: isOpen,
914
+ onClose: () => {
915
+ resolve();
916
+ close();
917
+ },
918
+ onExited: exit,
919
+ position: "top",
920
+ text: `${nickname}\uB2D8 \uBC18\uAC00\uC6CC\uC694!`,
921
+ icon: /* @__PURE__ */ jsx2(
922
+ Asset.Image,
923
+ {
924
+ style: { borderRadius: 64, overflow: "hidden" },
925
+ frameShape: Asset.frameShape.CleanW32,
926
+ source: { uri: profileImageUri }
927
+ }
928
+ )
929
+ }
930
+ ) }) });
931
+ });
932
+ });
933
+ };
934
+ return { openGameProfileToast };
935
+ };
936
+
937
+ // src/utils/error.ts
938
+ var DEFAULT_ERROR = {
939
+ title: "\uC7A0\uC2DC \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694",
940
+ description: "\uBB38\uC81C\uAC00 \uACC4\uC18D\uB418\uBA74 \uD1A0\uC2A4 \uACE0\uAC1D\uC13C\uD130(1599-4905)\uB85C \uBB38\uC758\uD574\uC8FC\uC138\uC694."
941
+ };
942
+
943
+ // src/utils/market.ts
944
+ import { Platform as Platform2 } from "react-native";
945
+ var PLAYSTORE_LINK = "https://play.google.com/store/apps/details?id=viva.republica.toss";
946
+ var APPSTORE_LINK = "https://itunes.apple.com/app/id839333328";
947
+ var getMarketLink = () => {
948
+ return Platform2.OS === "android" ? PLAYSTORE_LINK : APPSTORE_LINK;
949
+ };
950
+
951
+ // src/utils/openTransparentWebView.ts
952
+ import { openURL as openURL2 } from "react-native-bedrock";
953
+
954
+ // src/native-event-emitter/internal/onVisibilityChangedByTransparentServiceWeb.ts
955
+ function onVisibilityChangedByTransparentServiceWeb(eventParams) {
956
+ return appsInTossEvent.addEventListener("onVisibilityChangedByTransparentServiceWeb", eventParams);
957
+ }
958
+
959
+ // src/private.ts
960
+ var INTERNAL__onVisibilityChangedByTransparentServiceWeb = onVisibilityChangedByTransparentServiceWeb;
961
+
962
+ // src/utils/openTransparentWebView.ts
963
+ var openTransparentWebView = ({
964
+ webUrl,
965
+ cleanupWhenDismissed = true,
966
+ onEvent,
967
+ onError,
968
+ callbackId = "fn",
969
+ params
970
+ }) => {
971
+ const url = new URL("supertoss://transparent-service-web");
972
+ url.searchParams.set("url", webUrl);
973
+ url.searchParams.set("onVisibilityChangeCallback", callbackId);
974
+ Object.entries(params ?? {}).forEach(([key, value]) => {
975
+ url.searchParams.set(key, value);
976
+ });
977
+ const cleanup = INTERNAL__onVisibilityChangedByTransparentServiceWeb({
978
+ options: { callbackId },
979
+ onError: (error) => {
980
+ onError(error);
981
+ cleanup();
982
+ },
983
+ onEvent: (value) => {
984
+ onEvent(value);
985
+ if (cleanupWhenDismissed && value === true) {
986
+ cleanup();
987
+ }
988
+ }
989
+ });
990
+ openURL2(url.toString());
991
+ };
992
+
993
+ // src/hooks/useGameCenterProfile.ts
994
+ var useGameCenterProfile = (isReadyForProfileUI) => {
995
+ const [profileData, setProfileData] = useState(void 0);
996
+ const [isProfileDataLoading, setIsProfileDataLoading] = useState(true);
997
+ const [isProfileDataRefetching, setIsProfileDataRefetching] = useState(false);
998
+ const shouldShowLoadingOverlay = isProfileDataLoading && isReadyForProfileUI;
999
+ const shouldShowProfileNotFoundOverlay = profileData?.statusCode === "PROFILE_NOT_FOUND" && isReadyForProfileUI && !isProfileDataRefetching;
1000
+ const canShowBottomSheetOrToast = !isProfileDataLoading && isReadyForProfileUI;
1001
+ const [isWebviewLoading, setIsWebviewLoading] = useState(false);
1002
+ const isCompletedProfileFlow = useRef(false);
1003
+ const { openAlert, openConfirm } = useDialog();
1004
+ const { openGameProfileToast } = useGameProfileToast();
1005
+ const openErrorAlert = useCallback(async () => {
1006
+ await openAlert({
1007
+ title: DEFAULT_ERROR.title,
1008
+ description: DEFAULT_ERROR.description
1009
+ });
1010
+ closeView();
1011
+ }, [openAlert]);
1012
+ const openProfileWebview = useCallback(() => {
1013
+ if (isWebviewLoading) {
1014
+ return;
1015
+ }
1016
+ setIsWebviewLoading(true);
1017
+ openTransparentWebView({
1018
+ webUrl: `${GAME_PROFILE_WEBVIEW_URL}?appName=${getAppName()}&referrer=appsintoss.${getAppName()}`,
1019
+ onEvent: async (isClosedTransparentWebView) => {
1020
+ if (isClosedTransparentWebView) {
1021
+ try {
1022
+ setIsWebviewLoading(false);
1023
+ setIsProfileDataRefetching(true);
1024
+ const data = await getGameCenterGameProfile();
1025
+ setProfileData(data);
1026
+ setIsProfileDataRefetching(false);
1027
+ if (data?.statusCode === "SUCCESS") {
1028
+ openGameProfileToast(data.nickname, data.profileImageUri);
1029
+ }
1030
+ } catch (_) {
1031
+ setIsProfileDataRefetching(false);
1032
+ openErrorAlert();
1033
+ }
1034
+ }
1035
+ },
1036
+ onError: () => {
1037
+ openErrorAlert();
1038
+ }
1039
+ });
1040
+ }, [isWebviewLoading, openGameProfileToast, openErrorAlert]);
1041
+ const updateAppToSupportedMinVersion = useCallback(async () => {
1042
+ const upddateConfirmDialogLabel = {
1043
+ title: `${josa(getAppsInTossGlobals().brandDisplayName, "\uC744/\uB97C")} \uD558\uB824\uBA74
1044
+ \uC571\uC744 \uC5C5\uB370\uC774\uD2B8\uD574\uC8FC\uC138\uC694`,
1045
+ leftButton: "\uB2EB\uAE30",
1046
+ rightButton: "\uC5C5\uB370\uC774\uD2B8\uD558\uAE30"
1047
+ };
1048
+ const isConfirmed = await openConfirm({
1049
+ title: upddateConfirmDialogLabel.title,
1050
+ leftButton: upddateConfirmDialogLabel.leftButton,
1051
+ rightButton: upddateConfirmDialogLabel.rightButton,
1052
+ closeOnDimmerClick: true
1053
+ });
1054
+ if (!isConfirmed) {
1055
+ closeView();
1056
+ return;
1057
+ }
1058
+ const STORE_SCHEME = getMarketLink();
1059
+ openURL3(`supertoss://web?url=${STORE_SCHEME}&external=browser`);
1060
+ }, [openConfirm]);
1061
+ return {
1062
+ profileData,
1063
+ isProfileDataLoading,
1064
+ isProfileDataRefetching,
1065
+ shouldShowLoadingOverlay,
1066
+ shouldShowProfileNotFoundOverlay,
1067
+ canShowBottomSheetOrToast,
1068
+ isCompletedProfileFlow,
1069
+ updateAppToSupportedMinVersion,
1070
+ setIsProfileDataLoading,
1071
+ openProfileWebview,
1072
+ setProfileData,
1073
+ openErrorAlert,
1074
+ openGameProfileToast
1075
+ };
1076
+ };
1077
+
1078
+ // src/utils/zIndex.ts
1079
+ var Z_INDEX = {
1080
+ /* 게임 프로필을 위한 overlay
1081
+ */
1082
+ PROFILE_OVERLAY: 9998,
1083
+ // 게임을 종료할 수 있는 X 버튼
1084
+ CLOSE_BUTTON: 9999
1085
+ };
1086
+
1087
+ // src/components/GameProfile.tsx
1088
+ import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1089
+ var GameProfile = ({ children, isReadyForProfileUI }) => {
1090
+ const {
1091
+ profileData,
1092
+ isProfileDataRefetching,
1093
+ shouldShowLoadingOverlay,
1094
+ shouldShowProfileNotFoundOverlay,
1095
+ canShowBottomSheetOrToast,
1096
+ isCompletedProfileFlow,
1097
+ openProfileWebview,
1098
+ updateAppToSupportedMinVersion,
1099
+ setIsProfileDataLoading,
1100
+ setProfileData,
1101
+ openErrorAlert,
1102
+ openGameProfileToast
1103
+ } = useGameCenterProfile(isReadyForProfileUI);
1104
+ useEffect3(() => {
1105
+ try {
1106
+ const getProfileData = async () => {
1107
+ const data = await getGameCenterGameProfile();
1108
+ setProfileData(data);
1109
+ setIsProfileDataLoading(false);
1110
+ };
1111
+ getProfileData();
1112
+ } catch (_) {
1113
+ openErrorAlert();
1114
+ setIsProfileDataLoading(false);
1115
+ }
1116
+ }, []);
1117
+ useEffect3(() => {
1118
+ const handleGameProfileFlow = async () => {
1119
+ if (!canShowBottomSheetOrToast) {
1120
+ return;
1121
+ }
1122
+ if (isCompletedProfileFlow.current) {
1123
+ return;
1124
+ }
1125
+ isCompletedProfileFlow.current = true;
1126
+ if (!isMinVersionSupported(GAME_CENTER_MIN_VERSION)) {
1127
+ updateAppToSupportedMinVersion();
1128
+ return;
1129
+ }
1130
+ if (profileData?.statusCode === "SUCCESS") {
1131
+ openGameProfileToast(profileData.nickname, profileData.profileImageUri);
1132
+ return;
1133
+ }
1134
+ if (profileData?.statusCode === "PROFILE_NOT_FOUND") {
1135
+ openProfileWebview();
1136
+ }
1137
+ };
1138
+ handleGameProfileFlow();
1139
+ }, [
1140
+ canShowBottomSheetOrToast,
1141
+ isCompletedProfileFlow,
1142
+ openGameProfileToast,
1143
+ openProfileWebview,
1144
+ profileData,
1145
+ updateAppToSupportedMinVersion
1146
+ ]);
1147
+ if (!isMinVersionSupported(GAME_CENTER_MIN_VERSION)) {
1148
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
1149
+ /* @__PURE__ */ jsx3(View, { style: { flex: 1, position: "relative" }, children }),
1150
+ /* @__PURE__ */ jsx3(
1151
+ Pressable,
1152
+ {
1153
+ style: {
1154
+ ...overlayStyle
1155
+ },
1156
+ onPress: () => {
1157
+ updateAppToSupportedMinVersion();
1158
+ }
1159
+ }
1160
+ )
1161
+ ] });
1162
+ }
1163
+ if (shouldShowLoadingOverlay || isProfileDataRefetching) {
1164
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
1165
+ /* @__PURE__ */ jsx3(View, { style: { flex: 1, position: "relative" }, children }),
1166
+ /* @__PURE__ */ jsx3(
1167
+ View,
1168
+ {
1169
+ style: {
1170
+ ...overlayStyle,
1171
+ justifyContent: "center",
1172
+ alignItems: "center",
1173
+ backgroundColor: "rgba(0, 0, 0, 0.2)"
1174
+ },
1175
+ children: /* @__PURE__ */ jsx3(Loader, { size: "large", type: "light" })
1176
+ }
1177
+ )
1178
+ ] });
1179
+ }
1180
+ if (shouldShowProfileNotFoundOverlay) {
1181
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
1182
+ /* @__PURE__ */ jsx3(View, { style: { flex: 1, position: "relative" }, children }),
1183
+ shouldShowProfileNotFoundOverlay && /* @__PURE__ */ jsx3(
1184
+ Pressable,
1185
+ {
1186
+ style: {
1187
+ ...overlayStyle
1188
+ },
1189
+ onPress: () => {
1190
+ openProfileWebview();
1191
+ }
1192
+ }
1193
+ )
1194
+ ] });
1195
+ }
1196
+ return /* @__PURE__ */ jsx3(Fragment2, { children: /* @__PURE__ */ jsx3(View, { style: { flex: 1, position: "relative" }, children }) });
1197
+ };
1198
+ var overlayStyle = {
1199
+ position: "absolute",
1200
+ top: 0,
1201
+ left: 0,
1202
+ right: 0,
1203
+ bottom: 0,
1204
+ zIndex: Z_INDEX.PROFILE_OVERLAY
1205
+ };
849
1206
 
850
1207
  // src/components/GameWebViewNavigationBar/GameNavigationBar.tsx
851
1208
  import { SvgXml } from "@react-native-bedrock/native/react-native-svg";
852
1209
  import { PageNavbar } from "@toss-design-system/react-native";
853
- import { Platform as Platform4, TouchableOpacity, View as View2 } from "react-native";
1210
+ import { Platform as Platform5, TouchableOpacity, View as View3 } from "react-native";
854
1211
 
855
1212
  // src/components/GameWebViewNavigationBar/HeaderRight.tsx
856
- import { StyleSheet, View } from "react-native";
1213
+ import { StyleSheet, View as View2 } from "react-native";
857
1214
 
858
1215
  // src/components/GameWebViewNavigationBar/byPlatform.ts
859
- import { Platform as Platform2 } from "react-native";
1216
+ import { Platform as Platform3 } from "react-native";
860
1217
  function byPlatform({
861
1218
  ...props
862
1219
  }) {
863
- return (props[Platform2.OS] ?? props.fallback)();
1220
+ return (props[Platform3.OS] ?? props.fallback)();
864
1221
  }
865
1222
 
866
1223
  // src/components/GameWebViewNavigationBar/constants.ts
@@ -868,18 +1225,18 @@ var RIGHT_MARGIN = 24;
868
1225
  var IOS_DEFAULT_MARGIN = 20;
869
1226
 
870
1227
  // src/components/GameWebViewNavigationBar/HeaderRight.tsx
871
- import { jsx as jsx2 } from "react/jsx-runtime";
1228
+ import { jsx as jsx4 } from "react/jsx-runtime";
872
1229
  function IOSHeaderRight(props) {
873
- return /* @__PURE__ */ jsx2(View, { style: styles.ios, ...props });
1230
+ return /* @__PURE__ */ jsx4(View2, { style: styles.ios, ...props });
874
1231
  }
875
1232
  function AndroidHeaderRight(props) {
876
- return /* @__PURE__ */ jsx2(View, { style: styles.android, ...props });
1233
+ return /* @__PURE__ */ jsx4(View2, { style: styles.android, ...props });
877
1234
  }
878
1235
  function HeaderRight(props) {
879
1236
  return byPlatform({
880
- ios: () => /* @__PURE__ */ jsx2(IOSHeaderRight, { ...props }),
881
- android: () => /* @__PURE__ */ jsx2(AndroidHeaderRight, { ...props }),
882
- fallback: () => /* @__PURE__ */ jsx2(IOSHeaderRight, { ...props })
1237
+ ios: () => /* @__PURE__ */ jsx4(IOSHeaderRight, { ...props }),
1238
+ android: () => /* @__PURE__ */ jsx4(AndroidHeaderRight, { ...props }),
1239
+ fallback: () => /* @__PURE__ */ jsx4(IOSHeaderRight, { ...props })
883
1240
  });
884
1241
  }
885
1242
  var styles = StyleSheet.create({
@@ -894,37 +1251,37 @@ var styles = StyleSheet.create({
894
1251
 
895
1252
  // src/components/GameWebViewNavigationBar/useSafeAreaTop.ts
896
1253
  import { useSafeAreaInsets } from "@react-native-bedrock/native/react-native-safe-area-context";
897
- import { Platform as Platform3 } from "react-native";
1254
+ import { Platform as Platform4 } from "react-native";
898
1255
  function useSafeAreaTop() {
899
1256
  const safeAreaInsets = useSafeAreaInsets();
900
- const hasDynamicIsland = Platform3.OS === "ios" && safeAreaInsets.top > 50;
1257
+ const hasDynamicIsland = Platform4.OS === "ios" && safeAreaInsets.top > 50;
901
1258
  const safeAreaTop = hasDynamicIsland ? safeAreaInsets.top - 5 : safeAreaInsets.top;
902
1259
  return safeAreaTop;
903
1260
  }
904
1261
 
905
1262
  // src/components/GameWebViewNavigationBar/GameNavigationBar.tsx
906
- import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1263
+ import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
907
1264
  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
1265
  function GameNavigationBar({ onClose }) {
909
1266
  const safeAreaTop = useSafeAreaTop();
910
- return /* @__PURE__ */ jsxs2(Fragment2, { children: [
911
- /* @__PURE__ */ jsx3(PageNavbar, { preference: { type: "none" } }),
912
- /* @__PURE__ */ jsx3(
913
- View2,
1267
+ return /* @__PURE__ */ jsxs3(Fragment3, { children: [
1268
+ /* @__PURE__ */ jsx5(PageNavbar, { preference: { type: "none" } }),
1269
+ /* @__PURE__ */ jsx5(
1270
+ View3,
914
1271
  {
915
1272
  style: {
916
1273
  width: "100%",
917
- height: Platform4.OS === "ios" ? 44 : 54,
1274
+ height: Platform5.OS === "ios" ? 44 : 54,
918
1275
  flexDirection: "row",
919
1276
  alignItems: "center",
920
1277
  justifyContent: "flex-end",
921
1278
  position: "absolute",
922
- zIndex: 9999,
1279
+ zIndex: Z_INDEX.CLOSE_BUTTON,
923
1280
  marginTop: safeAreaTop,
924
- paddingRight: Platform4.OS === "ios" ? 10 : 8
1281
+ paddingRight: Platform5.OS === "ios" ? 10 : 8
925
1282
  },
926
1283
  pointerEvents: "box-none",
927
- children: /* @__PURE__ */ jsx3(HeaderRight, { children: /* @__PURE__ */ jsx3(
1284
+ children: /* @__PURE__ */ jsx5(HeaderRight, { children: /* @__PURE__ */ jsx5(
928
1285
  TouchableOpacity,
929
1286
  {
930
1287
  hitSlop: { left: 8, right: 8 },
@@ -932,10 +1289,10 @@ function GameNavigationBar({ onClose }) {
932
1289
  accessible: true,
933
1290
  accessibilityLabel: "\uAC8C\uC784\uC885\uB8CC",
934
1291
  style: {
935
- padding: Platform4.OS === "ios" ? 7 : 9
1292
+ padding: Platform5.OS === "ios" ? 7 : 9
936
1293
  },
937
1294
  onPress: onClose,
938
- children: /* @__PURE__ */ jsx3(SvgXml, { xml: originXML, width: 30, height: 30 })
1295
+ children: /* @__PURE__ */ jsx5(SvgXml, { xml: originXML, width: 30, height: 30 })
939
1296
  }
940
1297
  ) })
941
1298
  }
@@ -944,23 +1301,24 @@ function GameNavigationBar({ onClose }) {
944
1301
  }
945
1302
 
946
1303
  // src/components/GameWebView.tsx
947
- import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1304
+ import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
948
1305
  var GameWebView = forwardRef(function GameWebView2(props, ref) {
949
- const { openConfirm } = useDialog();
1306
+ const { openConfirm } = useDialog2();
950
1307
  const { brandDisplayName } = getAppsInTossGlobals();
951
- const handleClose = useCallback(async () => {
1308
+ const [isEntryMessageExited, setIsEntryMessageExited] = useState2(false);
1309
+ const handleClose = useCallback2(async () => {
952
1310
  const isConfirmed = await openConfirm({
953
- title: `${josa(brandDisplayName, "\uC744/\uB97C")} \uC885\uB8CC\uD560\uAE4C\uC694?`,
1311
+ title: `${josa2(brandDisplayName, "\uC744/\uB97C")} \uC885\uB8CC\uD560\uAE4C\uC694?`,
954
1312
  leftButton: "\uCDE8\uC18C",
955
1313
  rightButton: "\uC885\uB8CC\uD558\uAE30",
956
1314
  closeOnDimmerClick: true
957
1315
  });
958
1316
  if (isConfirmed) {
959
- closeView();
1317
+ closeView2();
960
1318
  }
961
1319
  }, [brandDisplayName, openConfirm]);
962
- useEffect3(() => {
963
- if (Platform5.OS === "ios") {
1320
+ useEffect4(() => {
1321
+ if (Platform6.OS === "ios") {
964
1322
  setIosSwipeGestureEnabled({ isEnabled: false });
965
1323
  return () => {
966
1324
  setIosSwipeGestureEnabled({ isEnabled: true });
@@ -968,7 +1326,7 @@ var GameWebView = forwardRef(function GameWebView2(props, ref) {
968
1326
  }
969
1327
  return;
970
1328
  }, []);
971
- useEffect3(() => {
1329
+ useEffect4(() => {
972
1330
  const backHandler = () => {
973
1331
  handleClose();
974
1332
  return true;
@@ -978,14 +1336,21 @@ var GameWebView = forwardRef(function GameWebView2(props, ref) {
978
1336
  BackHandler.removeEventListener("hardwareBackPress", backHandler);
979
1337
  };
980
1338
  }, [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 }) })
1339
+ useEffect4(() => {
1340
+ appsInTossEvent.addEventListener("entryMessageExited", {
1341
+ onEvent: () => {
1342
+ setIsEntryMessageExited(true);
1343
+ }
1344
+ });
1345
+ }, []);
1346
+ return /* @__PURE__ */ jsxs4(Fragment4, { children: [
1347
+ /* @__PURE__ */ jsx6(GameNavigationBar, { onClose: handleClose }),
1348
+ getOperationalEnvironment() === "toss" ? /* @__PURE__ */ jsx6(GameProfile, { isReadyForProfileUI: isEntryMessageExited, children: /* @__PURE__ */ jsx6(PlainWebView, { ref, ...props }) }) : /* @__PURE__ */ jsx6(PlainWebView, { ref, ...props })
984
1349
  ] });
985
1350
  });
986
1351
 
987
1352
  // src/bridge-handler/useBridgeHandler.tsx
988
- import { useCallback as useCallback2, useMemo as useMemo2, useRef } from "react";
1353
+ import { useCallback as useCallback3, useMemo as useMemo2, useRef as useRef2 } from "react";
989
1354
  function serializeError(error) {
990
1355
  return JSON.stringify(error, (_, value) => {
991
1356
  if (value instanceof Error) {
@@ -1034,7 +1399,7 @@ function useBridgeHandler({
1034
1399
  eventListenerMap,
1035
1400
  injectedJavaScript: originalInjectedJavaScript
1036
1401
  }) {
1037
- const ref = useRef(null);
1402
+ const ref = useRef2(null);
1038
1403
  const injectedJavaScript = useMemo2(
1039
1404
  () => [
1040
1405
  `window.__CONSTANT_HANDLER_MAP = ${JSON.stringify(
@@ -1061,7 +1426,7 @@ function useBridgeHandler({
1061
1426
  window.__BEDROCK_NATIVE_EMITTER.emit('${functionName}/onError/${eventId}', ${JSON.stringify(error, null, 0)});
1062
1427
  `);
1063
1428
  };
1064
- const $onMessage = useCallback2(
1429
+ const $onMessage = useCallback3(
1065
1430
  async (e) => {
1066
1431
  onMessage?.(e);
1067
1432
  const data = JSON.parse(e.nativeEvent.data);
@@ -1128,10 +1493,132 @@ __export(event_bridges_exports, {
1128
1493
  // src/hooks/useCreateUserAgent.ts
1129
1494
  import { useWindowDimensions } from "react-native";
1130
1495
  import { getPlatformOS } from "react-native-bedrock";
1496
+ var FontA11yCategory = {
1497
+ Large: "Large",
1498
+ xLarge: "xLarge",
1499
+ xxLarge: "xxLarge",
1500
+ xxxLarge: "xxxLarge",
1501
+ A11y_Medium: "A11y_Medium",
1502
+ A11y_Large: "A11y_Large",
1503
+ A11y_xLarge: "A11y_xLarge",
1504
+ A11y_xxLarge: "A11y_xxLarge",
1505
+ A11y_xxxLarge: "A11y_xxxLarge"
1506
+ };
1507
+ var androidFontScaleMap = {
1508
+ 100: FontA11yCategory.Large,
1509
+ 110: FontA11yCategory.xLarge,
1510
+ 120: FontA11yCategory.xxLarge,
1511
+ 135: FontA11yCategory.xxxLarge,
1512
+ 160: FontA11yCategory.A11y_Medium,
1513
+ 190: FontA11yCategory.A11y_Large,
1514
+ 235: FontA11yCategory.A11y_xLarge,
1515
+ 275: FontA11yCategory.A11y_xxLarge,
1516
+ 310: FontA11yCategory.A11y_xxxLarge
1517
+ };
1518
+ var iosScaleToAndroidScale = {
1519
+ 0.823: 100,
1520
+ 0.882: 100,
1521
+ 0.941: 100,
1522
+ 1: 100,
1523
+ 1.118: 110,
1524
+ 1.235: 120,
1525
+ 1.353: 135,
1526
+ 1.786: 160,
1527
+ 2.143: 190,
1528
+ 2.643: 235,
1529
+ 3.143: 275,
1530
+ 3.571: 310
1531
+ };
1532
+ function convertToAndroidStyleScale(fontScale, platform) {
1533
+ if (platform === "android") {
1534
+ if (fontScale <= 1) {
1535
+ return 100;
1536
+ }
1537
+ const scaledValue = Math.round(fontScale * 100);
1538
+ const keys = Object.keys(androidFontScaleMap).map(Number).sort((a, b) => a - b);
1539
+ let closestKey = keys[0];
1540
+ let minDiff = Math.abs(scaledValue - closestKey);
1541
+ for (const key of keys) {
1542
+ const diff = Math.abs(scaledValue - key);
1543
+ if (diff < minDiff) {
1544
+ minDiff = diff;
1545
+ closestKey = key;
1546
+ }
1547
+ }
1548
+ return closestKey;
1549
+ } else {
1550
+ const iosScales = Object.keys(iosScaleToAndroidScale).map(Number);
1551
+ let closestScale = iosScales[0];
1552
+ let minDiff = Math.abs(fontScale - closestScale);
1553
+ for (const scale of iosScales) {
1554
+ const diff = Math.abs(fontScale - scale);
1555
+ if (diff < minDiff) {
1556
+ minDiff = diff;
1557
+ closestScale = scale;
1558
+ }
1559
+ }
1560
+ return iosScaleToAndroidScale[closestScale];
1561
+ }
1562
+ }
1563
+ function mapIOSFontScaleToCategory(fontScale) {
1564
+ if (fontScale < 1) {
1565
+ return FontA11yCategory.Large;
1566
+ }
1567
+ if (Math.abs(fontScale - 1) < 0.05) {
1568
+ return FontA11yCategory.Large;
1569
+ }
1570
+ if (Math.abs(fontScale - 1.118) < 0.05) {
1571
+ return FontA11yCategory.xLarge;
1572
+ }
1573
+ if (Math.abs(fontScale - 1.235) < 0.05) {
1574
+ return FontA11yCategory.xxLarge;
1575
+ }
1576
+ if (Math.abs(fontScale - 1.353) < 0.05) {
1577
+ return FontA11yCategory.xxxLarge;
1578
+ }
1579
+ if (Math.abs(fontScale - 1.786) < 0.05) {
1580
+ return FontA11yCategory.A11y_Medium;
1581
+ }
1582
+ if (Math.abs(fontScale - 2.143) < 0.05) {
1583
+ return FontA11yCategory.A11y_Large;
1584
+ }
1585
+ if (Math.abs(fontScale - 2.643) < 0.05) {
1586
+ return FontA11yCategory.A11y_xLarge;
1587
+ }
1588
+ if (Math.abs(fontScale - 3.143) < 0.05) {
1589
+ return FontA11yCategory.A11y_xxLarge;
1590
+ }
1591
+ if (Math.abs(fontScale - 3.571) < 0.05) {
1592
+ return FontA11yCategory.A11y_xxxLarge;
1593
+ }
1594
+ return FontA11yCategory.Large;
1595
+ }
1596
+ function mapAndroidFontScaleToCategory(fontScale) {
1597
+ if (fontScale <= 1) {
1598
+ return androidFontScaleMap[100];
1599
+ }
1600
+ const scaledValue = Math.round(fontScale * 100);
1601
+ const keys = Object.keys(androidFontScaleMap).map(Number).sort((a, b) => a - b);
1602
+ if (keys.length === 0) {
1603
+ return androidFontScaleMap[100];
1604
+ }
1605
+ let closestKey = keys[0];
1606
+ let minDiff = Math.abs(scaledValue - closestKey);
1607
+ for (const key of keys) {
1608
+ const diff = Math.abs(scaledValue - key);
1609
+ if (diff < minDiff) {
1610
+ minDiff = diff;
1611
+ closestKey = key;
1612
+ }
1613
+ }
1614
+ return androidFontScaleMap[closestKey];
1615
+ }
1616
+ function mapFontScaleToCategory(fontScale, platform) {
1617
+ return platform === "ios" ? mapIOSFontScaleToCategory(fontScale) : mapAndroidFontScaleToCategory(fontScale);
1618
+ }
1131
1619
  function useCreateUserAgent({
1132
1620
  batteryModePreference,
1133
1621
  colorPreference,
1134
- fontA11y,
1135
1622
  locale,
1136
1623
  navbarPreference,
1137
1624
  pureSafeArea,
@@ -1140,14 +1627,16 @@ function useCreateUserAgent({
1140
1627
  }) {
1141
1628
  const platform = getPlatformOS();
1142
1629
  const appVersion = getTossAppVersion();
1143
- const fontScale = useWindowDimensions().fontScale;
1630
+ const { fontScale } = useWindowDimensions();
1144
1631
  const platformString = platform === "ios" ? "iPhone" : "Android";
1632
+ const fontA11y = mapFontScaleToCategory(fontScale, platform);
1633
+ const normalizedFontScale = convertToAndroidStyleScale(fontScale, platform);
1145
1634
  return [
1146
1635
  `TossApp/${appVersion}`,
1147
1636
  batteryModePreference && `TossBatteryModePreference/${batteryModePreference}`,
1148
1637
  colorPreference && `TossColorPreference/${colorPreference}`,
1149
- fontA11y && `TossFontAccessibility/${fontA11y}`,
1150
- fontScale && `TossFontScale/${fontScale}`,
1638
+ `TossFontAccessibility/${fontA11y}`,
1639
+ `TossFontScale/${normalizedFontScale}`,
1151
1640
  locale && `TossLocale/${locale}`,
1152
1641
  navbarPreference && `TossNavbarPreference/${navbarPreference}`,
1153
1642
  pureSafeArea && `TossPureSafeArea/${pureSafeArea}`,
@@ -1158,12 +1647,12 @@ function useCreateUserAgent({
1158
1647
  }
1159
1648
 
1160
1649
  // src/hooks/useGeolocation.ts
1161
- import { useState, useEffect as useEffect4 } from "react";
1650
+ import { useState as useState3, useEffect as useEffect5 } from "react";
1162
1651
  import { useVisibility } from "react-native-bedrock";
1163
1652
  function useGeolocation({ accuracy, distanceInterval, timeInterval }) {
1164
1653
  const isVisible = useVisibility();
1165
- const [location, setLocation] = useState(null);
1166
- useEffect4(() => {
1654
+ const [location, setLocation] = useState3(null);
1655
+ useEffect5(() => {
1167
1656
  if (!isVisible) {
1168
1657
  return;
1169
1658
  }
@@ -1229,7 +1718,7 @@ var trackScreen = (url) => {
1229
1718
  };
1230
1719
 
1231
1720
  // src/components/WebView.tsx
1232
- import { jsx as jsx5 } from "react/jsx-runtime";
1721
+ import { jsx as jsx7 } from "react/jsx-runtime";
1233
1722
  var appsInTossGlobals = getAppsInTossGlobals();
1234
1723
  var operationalEnvironment = getOperationalEnvironment();
1235
1724
  var TYPES = ["partner", "external", "game"];
@@ -1345,7 +1834,7 @@ function WebView({ type, local, onMessage, ...props }) {
1345
1834
  }, [type, props]);
1346
1835
  const BaseWebView = WEBVIEW_TYPES[type];
1347
1836
  const webViewDebuggingEnabled = operationalEnvironment === "sandbox";
1348
- const handleNavigationStateChange = useCallback3((event) => {
1837
+ const handleNavigationStateChange = useCallback4((event) => {
1349
1838
  if (event.url) {
1350
1839
  trackScreen(event.url);
1351
1840
  }
@@ -1353,7 +1842,7 @@ function WebView({ type, local, onMessage, ...props }) {
1353
1842
  const userAgent = useCreateUserAgent({
1354
1843
  colorPreference: "light"
1355
1844
  });
1356
- return /* @__PURE__ */ jsx5(
1845
+ return /* @__PURE__ */ jsx7(
1357
1846
  BaseWebView,
1358
1847
  {
1359
1848
  ref: handler.ref,
@@ -1366,14 +1855,15 @@ function WebView({ type, local, onMessage, ...props }) {
1366
1855
  "User-Agent": userAgent
1367
1856
  }
1368
1857
  },
1369
- userAgent: Platform6.OS === "ios" ? userAgent : void 0,
1858
+ userAgent: Platform7.OS === "ios" ? userAgent : void 0,
1370
1859
  sharedCookiesEnabled: true,
1371
1860
  webviewDebuggingEnabled: webViewDebuggingEnabled,
1372
1861
  thirdPartyCookiesEnabled: true,
1373
1862
  onMessage: handler.onMessage,
1374
1863
  onNavigationStateChange: handleNavigationStateChange,
1375
1864
  injectedJavaScript: handler.injectedJavaScript,
1376
- injectedJavaScriptBeforeContentLoaded: handler.injectedJavaScript
1865
+ injectedJavaScriptBeforeContentLoaded: handler.injectedJavaScript,
1866
+ decelerationRate: Platform7.OS === "ios" ? 1 : void 0
1377
1867
  }
1378
1868
  );
1379
1869
  }
@@ -1395,14 +1885,6 @@ var Accuracy2 = /* @__PURE__ */ ((Accuracy3) => {
1395
1885
  return Accuracy3;
1396
1886
  })(Accuracy2 || {});
1397
1887
 
1398
- // src/native-event-emitter/internal/onVisibilityChangedByTransparentServiceWeb.ts
1399
- function onVisibilityChangedByTransparentServiceWeb(eventParams) {
1400
- return appsInTossEvent.addEventListener("onVisibilityChangedByTransparentServiceWeb", eventParams);
1401
- }
1402
-
1403
- // src/private.ts
1404
- var INTERNAL__onVisibilityChangedByTransparentServiceWeb = onVisibilityChangedByTransparentServiceWeb;
1405
-
1406
1888
  // src/index.ts
1407
1889
  export * from "@apps-in-toss/analytics";
1408
1890
  var Analytics2 = {
@@ -1430,15 +1912,18 @@ export {
1430
1912
  getClipboardText,
1431
1913
  getCurrentLocation,
1432
1914
  getDeviceId,
1915
+ getGameCenterGameProfile,
1433
1916
  getOperationalEnvironment,
1434
1917
  getTossAppVersion,
1435
1918
  getTossShareLink,
1436
1919
  isMinVersionSupported,
1437
1920
  openCamera,
1921
+ openGameCenterLeaderboard,
1438
1922
  saveBase64Data,
1439
1923
  setClipboardText,
1440
1924
  setDeviceOrientation,
1441
1925
  startUpdateLocation,
1926
+ submitGameCenterLeaderBoardScore,
1442
1927
  useCreateUserAgent,
1443
1928
  useGeolocation
1444
1929
  };