@apps-in-toss/native-modules 0.0.0-dev.1752115036458 → 0.0.0-dev.1757056983098
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/bridges-meta.json +36 -13
- package/dist/index.cjs +343 -129
- package/dist/index.d.cts +1212 -418
- package/dist/index.d.ts +1212 -418
- package/dist/index.js +315 -108
- package/package.json +7 -8
- package/src/AppsInTossModule/constants.ts +6 -0
- package/src/AppsInTossModule/native-event-emitter/appsInTossEvent.ts +15 -0
- package/src/AppsInTossModule/native-event-emitter/contactsViral.ts +140 -0
- package/src/AppsInTossModule/native-event-emitter/event-plugins/EntryMessageExitedEvent.ts +10 -0
- package/src/AppsInTossModule/native-event-emitter/event-plugins/HomeIconButtonClickHandleEvent.ts +10 -0
- package/src/AppsInTossModule/native-event-emitter/event-plugins/UpdateLocationEvent.ts +60 -0
- package/src/AppsInTossModule/native-event-emitter/index.ts +6 -0
- package/src/AppsInTossModule/native-event-emitter/internal/AppBridgeCallbackEvent.ts +45 -0
- package/src/AppsInTossModule/native-event-emitter/internal/VisibilityChangedByTransparentServiceWebEvent.ts +50 -0
- package/src/AppsInTossModule/native-event-emitter/internal/appBridge.spec.ts +135 -0
- package/src/AppsInTossModule/native-event-emitter/internal/appBridge.ts +79 -0
- package/src/AppsInTossModule/native-event-emitter/internal/onVisibilityChangedByTransparentServiceWeb.ts +20 -0
- package/src/AppsInTossModule/native-event-emitter/nativeEventEmitter.ts +35 -0
- package/src/AppsInTossModule/native-event-emitter/startUpdateLocation.ts +98 -0
- package/src/AppsInTossModule/native-event-emitter/types.ts +4 -0
- package/src/AppsInTossModule/native-modules/AppsInTossModule.ts +89 -0
- package/src/AppsInTossModule/native-modules/ads/googleAdMob.ts +681 -0
- package/src/AppsInTossModule/native-modules/ads/googleAdMobV2.ts +363 -0
- package/src/AppsInTossModule/native-modules/ads/types.ts +123 -0
- package/src/AppsInTossModule/native-modules/appLogin.ts +29 -0
- package/src/AppsInTossModule/native-modules/checkoutPayment.ts +80 -0
- package/src/AppsInTossModule/native-modules/eventLog.spec.ts +300 -0
- package/src/AppsInTossModule/native-modules/eventLog.ts +77 -0
- package/src/AppsInTossModule/native-modules/fetchAlbumPhotos.ts +88 -0
- package/src/AppsInTossModule/native-modules/fetchContacts.ts +121 -0
- package/src/AppsInTossModule/native-modules/getClipboardText.ts +47 -0
- package/src/AppsInTossModule/native-modules/getCurrentLocation.ts +65 -0
- package/src/AppsInTossModule/native-modules/getDeviceId.ts +33 -0
- package/src/AppsInTossModule/native-modules/getGameCenterGameProfile.ts +68 -0
- package/src/AppsInTossModule/native-modules/getOperationalEnvironment.ts +37 -0
- package/src/AppsInTossModule/native-modules/getPermission.ts +58 -0
- package/src/AppsInTossModule/native-modules/getTossAppVersion.ts +33 -0
- package/src/AppsInTossModule/native-modules/getTossShareLink.ts +39 -0
- package/src/AppsInTossModule/native-modules/iap.ts +213 -0
- package/src/AppsInTossModule/native-modules/index.ts +104 -0
- package/src/AppsInTossModule/native-modules/isMinVersionSupported.spec.ts +190 -0
- package/src/AppsInTossModule/native-modules/isMinVersionSupported.ts +68 -0
- package/src/AppsInTossModule/native-modules/openCamera.ts +81 -0
- package/src/AppsInTossModule/native-modules/openGameCenterLeaderboard.ts +44 -0
- package/src/AppsInTossModule/native-modules/openPermissionDialog.ts +54 -0
- package/src/AppsInTossModule/native-modules/requestPermission.ts +63 -0
- package/src/AppsInTossModule/native-modules/saveBase64Data.ts +57 -0
- package/src/AppsInTossModule/native-modules/setClipboardText.ts +39 -0
- package/src/AppsInTossModule/native-modules/setDeviceOrientation.ts +74 -0
- package/src/AppsInTossModule/native-modules/storage.ts +100 -0
- package/src/AppsInTossModule/native-modules/submitGameCenterLeaderBoardScore.ts +74 -0
- package/src/AppsInTossModule/native-modules/tossCore.ts +29 -0
- package/src/BedrockModule/native-modules/core/BedrockCoreModule.ts +8 -0
- package/src/BedrockModule/native-modules/index.ts +4 -0
- package/src/BedrockModule/native-modules/natives/BedrockModule.ts +20 -0
- package/src/BedrockModule/native-modules/natives/closeView.ts +25 -0
- package/src/BedrockModule/native-modules/natives/generateHapticFeedback/index.ts +27 -0
- package/src/BedrockModule/native-modules/natives/generateHapticFeedback/types.ts +38 -0
- package/src/BedrockModule/native-modules/natives/getLocale.ts +46 -0
- package/src/BedrockModule/native-modules/natives/getNetworkStatus/index.ts +59 -0
- package/src/BedrockModule/native-modules/natives/getNetworkStatus/types.ts +1 -0
- package/src/BedrockModule/native-modules/natives/getPlatformOS.ts +37 -0
- package/src/BedrockModule/native-modules/natives/getSchemeUri.ts +27 -0
- package/src/BedrockModule/native-modules/natives/index.ts +11 -0
- package/src/BedrockModule/native-modules/natives/openURL.ts +40 -0
- package/src/BedrockModule/native-modules/natives/setIosSwipeGestureEnabled.ts +43 -0
- package/src/BedrockModule/native-modules/natives/setScreenAwakeMode.ts +66 -0
- package/src/BedrockModule/native-modules/natives/setSecureScreen.ts +31 -0
- package/src/BedrockModule/native-modules/natives/share.ts +36 -0
- package/src/async-bridges.ts +3 -0
- package/src/event-bridges.ts +2 -0
- package/src/index.ts +16 -0
- package/src/types.ts +108 -0
- package/src/utils/compareVersion.spec.ts +176 -0
- package/src/utils/compareVersion.ts +104 -0
- package/src/utils/generateUUID.ts +5 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
|
|
3
|
+
describe('isMinVersionSupported per-test mocks with dynamic import', () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
// 각 테스트 전 모듈 캐시 초기화
|
|
6
|
+
vi.resetModules();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('iOS 환경 테스트: 현재 버전이 최소 버전보다 낮을 때', async () => {
|
|
10
|
+
// doMock을 사용하여 모킹이 해당 테스트에 국한되도록 함
|
|
11
|
+
vi.doMock('./AppsInTossModule.js', () => ({
|
|
12
|
+
AppsInTossModule: {
|
|
13
|
+
tossAppVersion: '1.0.0',
|
|
14
|
+
operationalEnvironment: 'toss',
|
|
15
|
+
},
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
vi.doMock('react-native', () => ({
|
|
19
|
+
Platform: { OS: 'ios' },
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
const { isMinVersionSupported } = await import('./isMinVersionSupported.js');
|
|
23
|
+
const result = isMinVersionSupported({
|
|
24
|
+
android: '1.0.0',
|
|
25
|
+
ios: '2.0.0',
|
|
26
|
+
});
|
|
27
|
+
expect(result).toBe(false);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('Android 환경 테스트: 현재 버전이 최소 버전보다 높을 때', async () => {
|
|
31
|
+
vi.doMock('./AppsInTossModule.js', () => ({
|
|
32
|
+
AppsInTossModule: {
|
|
33
|
+
tossAppVersion: '3.0.0',
|
|
34
|
+
operationalEnvironment: 'toss',
|
|
35
|
+
},
|
|
36
|
+
}));
|
|
37
|
+
|
|
38
|
+
vi.doMock('react-native', () => ({
|
|
39
|
+
Platform: { OS: 'android' },
|
|
40
|
+
}));
|
|
41
|
+
|
|
42
|
+
const { isMinVersionSupported } = await import('./isMinVersionSupported.js');
|
|
43
|
+
const result = isMinVersionSupported({
|
|
44
|
+
android: '2.0.0',
|
|
45
|
+
ios: '1.0.0',
|
|
46
|
+
});
|
|
47
|
+
expect(result).toBe(true);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('iOS 환경 테스트: 현재 버전이 최소 버전과 같을 때', async () => {
|
|
51
|
+
vi.doMock('./AppsInTossModule.js', () => ({
|
|
52
|
+
AppsInTossModule: {
|
|
53
|
+
tossAppVersion: '2.0.0',
|
|
54
|
+
operationalEnvironment: 'toss',
|
|
55
|
+
},
|
|
56
|
+
}));
|
|
57
|
+
|
|
58
|
+
vi.doMock('react-native', () => ({
|
|
59
|
+
Platform: { OS: 'ios' },
|
|
60
|
+
}));
|
|
61
|
+
|
|
62
|
+
const { isMinVersionSupported } = await import('./isMinVersionSupported.js');
|
|
63
|
+
const result = isMinVersionSupported({
|
|
64
|
+
android: '1.0.0',
|
|
65
|
+
ios: '2.0.0',
|
|
66
|
+
});
|
|
67
|
+
expect(result).toBe(true);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('iOS 환경 테스트: minVersion이 "always"일 때', async () => {
|
|
71
|
+
vi.doMock('./AppsInTossModule.js', () => ({
|
|
72
|
+
AppsInTossModule: {
|
|
73
|
+
tossAppVersion: '1.0.0',
|
|
74
|
+
operationalEnvironment: 'toss',
|
|
75
|
+
},
|
|
76
|
+
}));
|
|
77
|
+
|
|
78
|
+
vi.doMock('react-native', () => ({
|
|
79
|
+
Platform: { OS: 'ios' },
|
|
80
|
+
}));
|
|
81
|
+
|
|
82
|
+
const { isMinVersionSupported } = await import('./isMinVersionSupported.js');
|
|
83
|
+
const result = isMinVersionSupported({
|
|
84
|
+
android: '1.0.0',
|
|
85
|
+
ios: 'always',
|
|
86
|
+
});
|
|
87
|
+
expect(result).toBe(true);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('Android 환경 테스트: minVersion이 "always"일 때', async () => {
|
|
91
|
+
vi.doMock('./AppsInTossModule.js', () => ({
|
|
92
|
+
AppsInTossModule: {
|
|
93
|
+
tossAppVersion: '1.0.0',
|
|
94
|
+
operationalEnvironment: 'toss',
|
|
95
|
+
},
|
|
96
|
+
}));
|
|
97
|
+
|
|
98
|
+
vi.doMock('react-native', () => ({
|
|
99
|
+
Platform: { OS: 'android' },
|
|
100
|
+
}));
|
|
101
|
+
|
|
102
|
+
const { isMinVersionSupported } = await import('./isMinVersionSupported.js');
|
|
103
|
+
const result = isMinVersionSupported({
|
|
104
|
+
android: 'always',
|
|
105
|
+
ios: '1.0.0',
|
|
106
|
+
});
|
|
107
|
+
expect(result).toBe(true);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('iOS 환경 테스트: minVersion이 "never"일 때', async () => {
|
|
111
|
+
vi.doMock('./AppsInTossModule.js', () => ({
|
|
112
|
+
AppsInTossModule: {
|
|
113
|
+
tossAppVersion: '1.0.0',
|
|
114
|
+
operationalEnvironment: 'toss',
|
|
115
|
+
},
|
|
116
|
+
}));
|
|
117
|
+
|
|
118
|
+
vi.doMock('react-native', () => ({
|
|
119
|
+
Platform: { OS: 'ios' },
|
|
120
|
+
}));
|
|
121
|
+
|
|
122
|
+
const { isMinVersionSupported } = await import('./isMinVersionSupported.js');
|
|
123
|
+
const result = isMinVersionSupported({
|
|
124
|
+
android: '1.0.0',
|
|
125
|
+
ios: 'never',
|
|
126
|
+
});
|
|
127
|
+
expect(result).toBe(false);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('Android 환경 테스트: minVersion이 "never"일 때', async () => {
|
|
131
|
+
vi.doMock('./AppsInTossModule.js', () => ({
|
|
132
|
+
AppsInTossModule: {
|
|
133
|
+
tossAppVersion: '1.0.0',
|
|
134
|
+
operationalEnvironment: 'toss',
|
|
135
|
+
},
|
|
136
|
+
}));
|
|
137
|
+
|
|
138
|
+
vi.doMock('react-native', () => ({
|
|
139
|
+
Platform: { OS: 'android' },
|
|
140
|
+
}));
|
|
141
|
+
|
|
142
|
+
const { isMinVersionSupported } = await import('./isMinVersionSupported.js');
|
|
143
|
+
const result = isMinVersionSupported({
|
|
144
|
+
android: 'never',
|
|
145
|
+
ios: '1.0.0',
|
|
146
|
+
});
|
|
147
|
+
expect(result).toBe(false);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('minVersion이 없을 때 false를 반환', async () => {
|
|
151
|
+
vi.doMock('./AppsInTossModule.js', () => ({
|
|
152
|
+
AppsInTossModule: {
|
|
153
|
+
tossAppVersion: '1.0.0',
|
|
154
|
+
operationalEnvironment: 'toss',
|
|
155
|
+
},
|
|
156
|
+
}));
|
|
157
|
+
|
|
158
|
+
vi.doMock('react-native', () => ({
|
|
159
|
+
Platform: { OS: 'ios' },
|
|
160
|
+
}));
|
|
161
|
+
|
|
162
|
+
const { isMinVersionSupported } = await import('./isMinVersionSupported.js');
|
|
163
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
164
|
+
// @ts-expect-error: ios 값 누락 의도
|
|
165
|
+
const result = isMinVersionSupported({
|
|
166
|
+
android: '1.0.0',
|
|
167
|
+
});
|
|
168
|
+
expect(result).toBe(false);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('sandbox 환경 테스트: 버전에 상관없이 항상 true를 반환', async () => {
|
|
172
|
+
vi.doMock('./AppsInTossModule.js', () => ({
|
|
173
|
+
AppsInTossModule: {
|
|
174
|
+
tossAppVersion: '1.0.0',
|
|
175
|
+
operationalEnvironment: 'sandbox',
|
|
176
|
+
},
|
|
177
|
+
}));
|
|
178
|
+
|
|
179
|
+
vi.doMock('react-native', () => ({
|
|
180
|
+
Platform: { OS: 'ios' },
|
|
181
|
+
}));
|
|
182
|
+
|
|
183
|
+
const { isMinVersionSupported } = await import('./isMinVersionSupported.js');
|
|
184
|
+
const result = isMinVersionSupported({
|
|
185
|
+
android: '5.0.0',
|
|
186
|
+
ios: '5.0.0',
|
|
187
|
+
});
|
|
188
|
+
expect(result).toBe(true);
|
|
189
|
+
});
|
|
190
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Platform } from 'react-native';
|
|
2
|
+
import { AppsInTossModule } from './AppsInTossModule';
|
|
3
|
+
import { compareVersions } from '../../utils/compareVersion';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @public
|
|
7
|
+
* @category 환경 확인
|
|
8
|
+
* @kind function
|
|
9
|
+
* @name isMinVersionSupported
|
|
10
|
+
* @description
|
|
11
|
+
* 현재 토스 앱 버전이 지정한 최소 버전 이상인지 확인해요.
|
|
12
|
+
*
|
|
13
|
+
* 이 함수는 현재 실행 중인 토스 앱의 버전이 파라미터로 전달된 최소 버전 요구사항을 충족하는지 확인해요. 특정 기능이 최신 버전에서만 동작할 때, 사용자에게 앱 업데이트를 안내할 수 있어요.
|
|
14
|
+
*
|
|
15
|
+
* @param {Object} minVersions 플랫폼별 최소 버전 요구사항을 지정하는 객체예요.
|
|
16
|
+
* @param {(`${number}.${number}.${number}` | 'always' | 'never')} minVersions.android 안드로이드 플랫폼의 최소 버전 요구사항이에요.
|
|
17
|
+
* @param {(`${number}.${number}.${number}` | 'always' | 'never')} minVersions.ios iOS 플랫폼의 최소 버전 요구사항이에요.
|
|
18
|
+
* @returns {boolean} 현재 앱 버전이 최소 버전 이상이면 true, 그렇지 않으면 false를 반환해요.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ### 앱 버전 확인하기
|
|
22
|
+
*
|
|
23
|
+
* ```tsx
|
|
24
|
+
* import { isMinVersionSupported } from '@apps-in-toss/framework';
|
|
25
|
+
* import { Text, View } from 'react-native';
|
|
26
|
+
*
|
|
27
|
+
* function VersionCheck() {
|
|
28
|
+
* const isSupported = isMinVersionSupported({
|
|
29
|
+
* android: '1.2.0',
|
|
30
|
+
* ios: '1.3.0'
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* return (
|
|
34
|
+
* <View>
|
|
35
|
+
* {!isSupported && (
|
|
36
|
+
* <Text>최신 버전으로 업데이트가 필요해요.</Text>
|
|
37
|
+
* )}
|
|
38
|
+
* </View>
|
|
39
|
+
* );
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export function isMinVersionSupported(minVersions: {
|
|
44
|
+
android: `${number}.${number}.${number}` | 'always' | 'never';
|
|
45
|
+
ios: `${number}.${number}.${number}` | 'always' | 'never';
|
|
46
|
+
}): boolean {
|
|
47
|
+
const operationalEnvironment = AppsInTossModule.operationalEnvironment;
|
|
48
|
+
if (operationalEnvironment === 'sandbox') {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const currentVersion = AppsInTossModule.tossAppVersion;
|
|
53
|
+
const isIOS = Platform.OS === 'ios';
|
|
54
|
+
const minVersion = isIOS ? minVersions.ios : minVersions.android;
|
|
55
|
+
|
|
56
|
+
if (minVersion === undefined) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (minVersion === 'always') {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
if (minVersion === 'never') {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return compareVersions(currentVersion, minVersion) >= 0;
|
|
68
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { AppsInTossModule } from './AppsInTossModule';
|
|
2
|
+
import { requestPermission } from './requestPermission';
|
|
3
|
+
import type { ImageResponse } from '../../types';
|
|
4
|
+
|
|
5
|
+
export interface OpenCameraOptions {
|
|
6
|
+
/**
|
|
7
|
+
* 이미지를 Base64 형식으로 반환할지 여부를 나타내는 불리언 값이에요.
|
|
8
|
+
*
|
|
9
|
+
* 기본값: `false`.
|
|
10
|
+
*/
|
|
11
|
+
base64?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* 이미지의 최대 너비를 나타내는 숫자 값이에요.
|
|
14
|
+
*
|
|
15
|
+
* 기본값: `1024`.
|
|
16
|
+
*/
|
|
17
|
+
maxWidth?: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @public
|
|
22
|
+
* @category 카메라
|
|
23
|
+
* @name openCamera
|
|
24
|
+
* @description 카메라를 실행해서 촬영된 이미지를 반환하는 함수예요.
|
|
25
|
+
* @param {OpenCameraOptions} options - 카메라 실행 시 사용되는 옵션 객체예요.
|
|
26
|
+
* @param {boolean} [options.base64=false] - 이미지를 Base64 형식으로 반환할지 여부를 나타내는 불리언 값이에요. 기본값은 `false`예요. `true`로 설정하면 `dataUri` 대신 Base64 인코딩된 문자열을 반환해요.
|
|
27
|
+
* @param {number} [options.maxWidth=1024] - 이미지의 최대 너비를 나타내는 숫자 값이에요. 기본값은 `1024`예요.
|
|
28
|
+
* @returns {Promise<ImageResponse>}
|
|
29
|
+
* 촬영된 이미지 정보를 포함한 객체를 반환해요. 반환 객체의 구성은 다음과 같아요:
|
|
30
|
+
* - `id`: 이미지의 고유 식별자예요.
|
|
31
|
+
* - `dataUri`: 이미지 데이터를 표현하는 데이터 URI예요.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ### 카메라 실행 후 촬영된 사진 가져오기
|
|
35
|
+
*
|
|
36
|
+
* ```tsx
|
|
37
|
+
* import React, { useState } from 'react';
|
|
38
|
+
* import { View, Text, Button, Image } from 'react-native';
|
|
39
|
+
* import { openCamera } from '@apps-in-toss/framework';
|
|
40
|
+
*
|
|
41
|
+
* const base64 = true;
|
|
42
|
+
*
|
|
43
|
+
* // 카메라를 실행하고 촬영된 이미지를 화면에 표시하는 컴포넌트
|
|
44
|
+
* function Camera() {
|
|
45
|
+
* const [image, setImage] = useState(null);
|
|
46
|
+
*
|
|
47
|
+
* const handlePress = async () => {
|
|
48
|
+
* try {
|
|
49
|
+
* const response = await openCamera({ base64 });
|
|
50
|
+
* setImage(response);
|
|
51
|
+
* } catch (error) {
|
|
52
|
+
* console.error('사진을 가져오는 데 실패했어요:', error);
|
|
53
|
+
* }
|
|
54
|
+
* };
|
|
55
|
+
*
|
|
56
|
+
* // base64 형식으로 반환된 이미지를 표시하려면 데이터 URL 스키마 Prefix를 붙여야해요.
|
|
57
|
+
* const imageUri = base64 ? 'data:image/jpeg;base64,' + image.dataUri : image.dataUri;
|
|
58
|
+
*
|
|
59
|
+
* return (
|
|
60
|
+
* <View>
|
|
61
|
+
* {image ? (
|
|
62
|
+
* <Image source={{ uri: imageUri }} style={{ width: 200, height: 200 }} />
|
|
63
|
+
* ) : (
|
|
64
|
+
* <Text>사진이 없어요</Text>
|
|
65
|
+
* )}
|
|
66
|
+
* <Button title="사진 촬영하기" onPress={handlePress} />
|
|
67
|
+
* </View>
|
|
68
|
+
* );
|
|
69
|
+
* }
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export async function openCamera(options?: OpenCameraOptions): Promise<ImageResponse> {
|
|
73
|
+
const permissionStatus = await requestPermission({ name: 'camera', access: 'access' });
|
|
74
|
+
if (permissionStatus === 'denied') {
|
|
75
|
+
throw new Error('카메라 권한이 거부되었어요.');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const photo = await AppsInTossModule.openCamera({ base64: false, maxWidth: 1024, ...options });
|
|
79
|
+
|
|
80
|
+
return photo;
|
|
81
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { openURL } from '@granite-js/react-native';
|
|
2
|
+
import { isMinVersionSupported } from './isMinVersionSupported';
|
|
3
|
+
import { GAME_CENTER_MIN_VERSION } from '../constants';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @public
|
|
7
|
+
* @category 게임센터
|
|
8
|
+
* @name openGameCenterLeaderboard
|
|
9
|
+
* @description 게임센터 리더보드 웹뷰를 열어요.
|
|
10
|
+
* 앱 버전이 최소 지원 버전(`5.221.0`)보다 낮으면 아무 동작도 하지 않고 `undefined`를 반환해요.
|
|
11
|
+
* 게임센터를 사용하는 사용자는 반드시 최소 지원 버전 이상이어야 게임을 실행할 수 있어요.
|
|
12
|
+
* @returns 리더보드 웹뷰를 호출해요. 앱 버전이 낮으면 아무 동작도 하지 않고 `undefined`를 반환해요.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* import { Button } from 'react-native';
|
|
16
|
+
* import { openGameCenterLeaderboard } from '@apps-in-toss/framework';
|
|
17
|
+
*
|
|
18
|
+
* // '리더보드' 버튼을 누르면 게임센터 리더보드 웹뷰가 열려요.
|
|
19
|
+
* function LeaderboardButton() {
|
|
20
|
+
* const onPress = () => {
|
|
21
|
+
* openGameCenterLeaderboard();
|
|
22
|
+
* };
|
|
23
|
+
*
|
|
24
|
+
* return <Button title="리더보드 웹뷰 호출" onPress={onPress} />;
|
|
25
|
+
* }
|
|
26
|
+
*/
|
|
27
|
+
export async function openGameCenterLeaderboard(): Promise<void> {
|
|
28
|
+
if (!isMinVersionSupported(GAME_CENTER_MIN_VERSION)) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const appName = global.__granite?.app?.name;
|
|
33
|
+
|
|
34
|
+
if (appName == null) {
|
|
35
|
+
throw new Error('Cannot get app name');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const url = new URL('servicetoss://game-center/leaderboard?_navbar=hide');
|
|
39
|
+
url.searchParams.set('appName', appName);
|
|
40
|
+
url.searchParams.set('referrer', `appsintoss.${appName}`);
|
|
41
|
+
return openURL(url.toString());
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
declare const global: { __granite: any };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { AppsInTossModule } from './AppsInTossModule';
|
|
2
|
+
import { PermissionAccess, PermissionName, PermissionStatus } from '../../types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @category AppsInTossModules
|
|
6
|
+
* @name openPermissionDialog
|
|
7
|
+
* @description 권한 요청 다이얼로그를 표시하는 함수예요. 사용자는 이 다이얼로그에서 특정 권한을 허용하거나 거부할 수 있어요.
|
|
8
|
+
* @param permission.name {PermissionName} 요청할 권한의 이름이에요. 예를 들어 `clipboard`는 클립보드 접근 권한을, `camera`는 카메라 접근 권한을 나타내요.
|
|
9
|
+
* @param permission.access {PermissionAccess} 요청할 권한의 접근 유형이에요. 예를 들어 `read`는 읽기 권한, `write`는 쓰기 권한을 의미해요.
|
|
10
|
+
* @returns {Promise<'allowed' | 'denied'>} 권한의 현재 상태를 반환해요. 반환값은 다음 중 하나예요:
|
|
11
|
+
* - `allowed`: 권한이 허용된 상태예요.
|
|
12
|
+
* - `denied`: 권한이 거부된 상태예요.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ### 클립보드 읽기 권한 다이얼로그 열기
|
|
16
|
+
*
|
|
17
|
+
* ```tsx
|
|
18
|
+
* import React, { useState } from 'react';
|
|
19
|
+
* import { View, Text, Button } from 'react-native';
|
|
20
|
+
* import { openPermissionDialog, type PermissionStatus } from '@apps-in-toss/framework';
|
|
21
|
+
*
|
|
22
|
+
* function PermissionRequest() {
|
|
23
|
+
* const [permission, setPermission] = useState<PermissionStatus | null>(null);
|
|
24
|
+
*
|
|
25
|
+
* const handleRequestPermission = async () => {
|
|
26
|
+
* try {
|
|
27
|
+
* // 클립보드 읽기 권한을 요청하는 다이얼로그를 표시해요.
|
|
28
|
+
* const status = await openPermissionDialog({
|
|
29
|
+
* name: 'clipboard',
|
|
30
|
+
* access: 'read',
|
|
31
|
+
* });
|
|
32
|
+
* setPermission(status); // 권한 상태를 업데이트해요.
|
|
33
|
+
* } catch (error) {
|
|
34
|
+
* console.error('권한 요청 중 오류가 발생했어요:', error);
|
|
35
|
+
* }
|
|
36
|
+
* };
|
|
37
|
+
*
|
|
38
|
+
* return (
|
|
39
|
+
* <View>
|
|
40
|
+
* <Text>
|
|
41
|
+
* 클립보드 읽기 권한 상태: {permission ? permission : '아직 요청하지 않음'}
|
|
42
|
+
* </Text>
|
|
43
|
+
* <Button title="권한 요청하기" onPress={handleRequestPermission} />
|
|
44
|
+
* </View>
|
|
45
|
+
* );
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export function openPermissionDialog(permission: {
|
|
50
|
+
name: PermissionName;
|
|
51
|
+
access: PermissionAccess;
|
|
52
|
+
}): Promise<Exclude<PermissionStatus, 'notDetermined'>> {
|
|
53
|
+
return AppsInTossModule.openPermissionDialog(permission);
|
|
54
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { getPermission } from './getPermission';
|
|
2
|
+
import { openPermissionDialog } from './openPermissionDialog';
|
|
3
|
+
import { PermissionAccess, PermissionName, PermissionStatus } from '../../types';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @category PermissionManagement
|
|
7
|
+
* @name requestPermission
|
|
8
|
+
* @description 특정 권한을 요청하는 함수예요. 이미 허용되었거나 거부된 권한 상태를 확인한 뒤, 필요할 때 권한 요청 다이얼로그를 표시해요.
|
|
9
|
+
* @param permission.name {PermissionName} 요청할 권한의 이름이에요. 예를 들어 `clipboard`는 클립보드 접근 권한을, `camera`는 카메라 접근 권한을 나타내요.
|
|
10
|
+
* @param permission.access {PermissionAccess} 요청할 권한의 접근 유형이에요. 예를 들어 `read`는 읽기 권한, `write`는 쓰기 권한을 의미해요.
|
|
11
|
+
* @returns {Promise<'allowed' | 'denied'>} 사용자가 선택한 최종 권한 상태를 반환해요.
|
|
12
|
+
* 반환값은 다음 중 하나예요:
|
|
13
|
+
* - `allowed`: 권한이 허용된 경우
|
|
14
|
+
* - `denied`: 권한이 거부된 경우
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ### 클립보드 읽기 권한 요청하기
|
|
18
|
+
*
|
|
19
|
+
* ```tsx
|
|
20
|
+
* import React, { useState } from 'react';
|
|
21
|
+
* import { View, Text, Button } from 'react-native';
|
|
22
|
+
* import { requestPermission, type PermissionStatus } from '@apps-in-toss/framework';
|
|
23
|
+
*
|
|
24
|
+
* function PermissionRequest() {
|
|
25
|
+
* const [permissionStatus, setPermissionStatus] = useState<PermissionStatus | null>(null);
|
|
26
|
+
*
|
|
27
|
+
* const handleRequestPermission = async () => {
|
|
28
|
+
* try {
|
|
29
|
+
* // 클립보드 읽기 권한을 요청해요.
|
|
30
|
+
* const permissionStatus = await requestPermission({
|
|
31
|
+
* name: 'clipboard', // 권한 이름: 클립보드
|
|
32
|
+
* access: 'read', // 접근 유형: 읽기
|
|
33
|
+
* });
|
|
34
|
+
* setPermissionStatus(permissionStatus); // 최종 권한 상태를 저장해요.
|
|
35
|
+
* } catch (error) {
|
|
36
|
+
* console.error('권한 요청 중 오류가 발생했어요:', error);
|
|
37
|
+
* }
|
|
38
|
+
* };
|
|
39
|
+
*
|
|
40
|
+
* return (
|
|
41
|
+
* <View>
|
|
42
|
+
* <Text>
|
|
43
|
+
* 클립보드 읽기 권한 상태: {permissionStatus ? permissionStatus : '아직 요청하지 않음'}
|
|
44
|
+
* </Text>
|
|
45
|
+
* <Button title="권한 요청하기" onPress={handleRequestPermission} />
|
|
46
|
+
* </View>
|
|
47
|
+
* );
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export async function requestPermission(permission: {
|
|
52
|
+
name: PermissionName;
|
|
53
|
+
access: PermissionAccess;
|
|
54
|
+
}): Promise<Exclude<PermissionStatus, 'notDetermined'>> {
|
|
55
|
+
const permissionStatus = await getPermission(permission);
|
|
56
|
+
switch (permissionStatus) {
|
|
57
|
+
case 'allowed':
|
|
58
|
+
case 'denied':
|
|
59
|
+
return permissionStatus;
|
|
60
|
+
default:
|
|
61
|
+
return openPermissionDialog(permission);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { AppsInTossModule } from './AppsInTossModule';
|
|
2
|
+
import { isMinVersionSupported } from './isMinVersionSupported';
|
|
3
|
+
|
|
4
|
+
export interface SaveBase64DataParams {
|
|
5
|
+
data: string;
|
|
6
|
+
fileName: string;
|
|
7
|
+
mimeType: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @public
|
|
12
|
+
* @category 데이터
|
|
13
|
+
* @name saveBase64Data
|
|
14
|
+
* @description 문자열로 인코딩된 Base64 데이터를 지정한 파일 이름과 MIME 타입으로 사용자 기기에 저장해요. 이미지, 텍스트, PDF 등 다양한 형식의 데이터를 저장할 수 있어요.
|
|
15
|
+
* @param {SaveBase64DataParams} params - 저장할 데이터와 파일 정보를 담은 객체예요.
|
|
16
|
+
* @param {string} params.data - Base64 형식으로 인코딩된 데이터 문자열이에요.
|
|
17
|
+
* @param {string} params.fileName - 저장할 파일 이름이에요. 확장자도 같이 붙여줘야해요. 예를 들어, 'example.png'로 저장할 수 있어요.
|
|
18
|
+
* @param {string} params.mimeType - 저장할 파일의 MIME 타입이에요. 예를 들어 'image/png' 로 지정하면 이미지, 'application/pdf'는 PDF 파일이에요. 자세한 내용은 [MIME 문서](https://developer.mozilla.org/ko/docs/Web/HTTP/Guides/MIME_types)를 참고해주세요.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ### Base64 이미지 데이터를 사용자 기기에 저장하기
|
|
22
|
+
*
|
|
23
|
+
* ```tsx
|
|
24
|
+
* import { Button } from 'react-native';
|
|
25
|
+
* import { saveBase64Data } from '@apps-in-toss/framework';
|
|
26
|
+
*
|
|
27
|
+
* // '저장' 버튼을 누르면 이미지가 사용자 기기에 저장돼요.
|
|
28
|
+
* function SaveButton() {
|
|
29
|
+
* const handleSave = async () => {
|
|
30
|
+
* try {
|
|
31
|
+
* await saveBase64Data({
|
|
32
|
+
* data: 'iVBORw0KGgo...',
|
|
33
|
+
* fileName: 'some-photo.png',
|
|
34
|
+
* mimeType: 'image/png',
|
|
35
|
+
* });
|
|
36
|
+
* } catch (error) {
|
|
37
|
+
* console.error('데이터 저장에 실패했어요:', error);
|
|
38
|
+
* }
|
|
39
|
+
* };
|
|
40
|
+
*
|
|
41
|
+
* return <Button title="저장" onPress={handleSave} />;
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export async function saveBase64Data(params: SaveBase64DataParams) {
|
|
46
|
+
const isSupported = isMinVersionSupported({
|
|
47
|
+
android: '5.218.0',
|
|
48
|
+
ios: '5.216.0',
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
if (!isSupported) {
|
|
52
|
+
console.warn('saveBase64Data is not supported in this app version');
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
await AppsInTossModule.saveBase64Data(params);
|
|
57
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { AppsInTossModule } from './AppsInTossModule';
|
|
2
|
+
import { requestPermission } from './requestPermission';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @public
|
|
6
|
+
* @category 클립보드
|
|
7
|
+
* @name setClipboardText
|
|
8
|
+
* @description 텍스트를 클립보드에 복사해서 사용자가 다른 곳에 붙여 넣기 할 수 있어요.
|
|
9
|
+
* @param {Promise<void>} text - 클립보드에 복사할 텍스트예요. 문자열 형식으로 입력해요.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ### 텍스트를 클립보드에 복사하기
|
|
13
|
+
*
|
|
14
|
+
* ```tsx
|
|
15
|
+
* import { Button } from 'react-native';
|
|
16
|
+
* import { setClipboardText } from '@apps-in-toss/framework';
|
|
17
|
+
*
|
|
18
|
+
* // '복사' 버튼을 누르면 "복사할 텍스트"가 클립보드에 복사돼요.
|
|
19
|
+
* function CopyButton() {
|
|
20
|
+
* const handleCopy = async () => {
|
|
21
|
+
* try {
|
|
22
|
+
* await setClipboardText('복사할 텍스트');
|
|
23
|
+
* console.log('텍스트가 복사됐어요!');
|
|
24
|
+
* } catch (error) {
|
|
25
|
+
* console.error('텍스트 복사에 실패했어요:', error);
|
|
26
|
+
* }
|
|
27
|
+
* };
|
|
28
|
+
*
|
|
29
|
+
* return <Button title="복사" onPress={handleCopy} />;
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export async function setClipboardText(text: string): Promise<void> {
|
|
34
|
+
const permissionStatus = await requestPermission({ name: 'clipboard', access: 'write' });
|
|
35
|
+
if (permissionStatus === 'denied') {
|
|
36
|
+
throw new Error('클립보드 쓰기 권한이 거부되었어요.');
|
|
37
|
+
}
|
|
38
|
+
return AppsInTossModule.setClipboardText({ text });
|
|
39
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { AppsInTossModule } from './AppsInTossModule';
|
|
2
|
+
import { isMinVersionSupported } from './isMinVersionSupported';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @public
|
|
6
|
+
* @category 화면 제어
|
|
7
|
+
* @kind function
|
|
8
|
+
* @name setDeviceOrientation
|
|
9
|
+
* @description
|
|
10
|
+
* `setDeviceOrientation` 함수는 기기의 화면 방향을 설정하는 기능을 제공해요.
|
|
11
|
+
* 이 기능은 특정 화면에서 가로 모드나 세로 모드를 강제로 지정해야 할 때 유용해요.
|
|
12
|
+
*
|
|
13
|
+
* `type` 옵션을 통해 원하는 화면 방향을 지정할 수 있어요. 특히, 이 함수는 앱 전체에 영향을 미치므로
|
|
14
|
+
* 특정 화면에서만 사용하려면 화면을 벗어날 때 이전 상태로 복구하는 추가 작업이 필요해요.
|
|
15
|
+
*
|
|
16
|
+
* 예를 들어, 동영상 감상 화면에서는 가로 모드를 강제하고, 화면을 떠날 때 설정을 복구해서
|
|
17
|
+
* 다른 화면들의 방향 설정에 영향을 주지 않도록 할 수 있어요.
|
|
18
|
+
*
|
|
19
|
+
* @param {object} options 화면 방향 설정 값이에요.
|
|
20
|
+
* @param {string} options.type 화면 방향을 지정하는 옵션이에요.
|
|
21
|
+
* 'portrait' | 'landscape' 중 하나를 선택할 수 있어요.
|
|
22
|
+
*
|
|
23
|
+
* @returns {Promise<void>} 화면 방향 설정이 완료되면 해결되는 Promise를 반환해요.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ### 화면 방향 설정하기
|
|
27
|
+
*
|
|
28
|
+
* ```tsx
|
|
29
|
+
* import { Button } from 'react-native';
|
|
30
|
+
* import { setDeviceOrientation } from '@apps-in-toss/framework';
|
|
31
|
+
*
|
|
32
|
+
* function SetDeviceOrientation() {
|
|
33
|
+
* return (
|
|
34
|
+
* <Button
|
|
35
|
+
* title="가로 모드로 변경"
|
|
36
|
+
* onPress={() => {
|
|
37
|
+
* setDeviceOrientation({ type: 'landscape' });
|
|
38
|
+
* }}
|
|
39
|
+
* />
|
|
40
|
+
* );
|
|
41
|
+
* }
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* ### 화면 방향 복구하기
|
|
45
|
+
* 특정 화면을 벗어날 때 이전 상태로 복구하려면 다음과 같이 `useEffect`를 사용하세요.
|
|
46
|
+
*
|
|
47
|
+
* ```tsx
|
|
48
|
+
* import { useEffect } from 'react';
|
|
49
|
+
* import { setDeviceOrientation } from '@apps-in-toss/framework';
|
|
50
|
+
*
|
|
51
|
+
* function VideoScreen() {
|
|
52
|
+
* useEffect(() => {
|
|
53
|
+
* setDeviceOrientation({ type: 'landscape' });
|
|
54
|
+
*
|
|
55
|
+
* return () => {
|
|
56
|
+
* setDeviceOrientation({ type: 'portrait' }); // 설정을 이전 상태로 복구해요.
|
|
57
|
+
* };
|
|
58
|
+
* }, []);
|
|
59
|
+
*
|
|
60
|
+
* return <Text>동영상을 감상하는 화면</Text>;
|
|
61
|
+
* }
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export async function setDeviceOrientation(options: { type: 'portrait' | 'landscape' }): Promise<void> {
|
|
65
|
+
const isSupported = isMinVersionSupported({
|
|
66
|
+
android: '5.215.0',
|
|
67
|
+
ios: '5.215.0',
|
|
68
|
+
});
|
|
69
|
+
if (!isSupported) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return AppsInTossModule.setDeviceOrientation(options);
|
|
74
|
+
}
|