diff --git a/README.md b/README.md index bf90371..984052c 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ please select the package link from below. | [Core](https://rnkakao.dev/docs/intro) | ![common-android](https://img.shields.io/badge/common-2.20.1-green?style=flat-square) | ![common-ios](https://img.shields.io/badge/common-2.22.0-lightblue?style=flat-square) | [![badge](https://img.shields.io/npm/dm/@react-native-kakao/core.svg?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@react-native-kakao/core) | โœ… | | [Share](https://rnkakao.dev/docs/share/intro) | ![share-android](https://img.shields.io/badge/share-2.20.1-green?style=flat-square) | ![share-ios](https://img.shields.io/badge/share-2.22.0-lightblue?style=flat-square) | [![badge](https://img.shields.io/npm/dm/@react-native-kakao/share.svg?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@react-native-kakao/share) | โœ… | | [User](https://rnkakao.dev/docs/user/intro) | ![user-android](https://img.shields.io/badge/user-2.20.1-green?style=flat-square) | ![user-ios](https://img.shields.io/badge/user-2.22.0-lightblue?style=flat-square) | [![badge](https://img.shields.io/npm/dm/@react-native-kakao/user.svg?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@react-native-kakao/user) | โœ… | -| [Social](https://rnkakao.dev/docs/social/intro) | ![talk-android](https://img.shields.io/badge/talk-2.20.1-green?style=flat-square) ![friend-android](https://img.shields.io/badge/friend-2.20.1-green?style=flat-square) | ![talk-ios](https://img.shields.io/badge/talk-2.22.0-lightblue?style=flat-square) ![friend-ios](https://img.shields.io/badge/friend-2.22.0-lightblue?style=flat-square) | [![badge](https://img.shields.io/npm/dm/@react-native-kakao/friend.svg?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@react-native-kakao/friend) | ๐Ÿ“ฆ | +| [Social](https://rnkakao.dev/docs/social/intro) | ![talk-android](https://img.shields.io/badge/talk-2.20.1-green?style=flat-square) ![friend-android](https://img.shields.io/badge/friend-2.20.1-green?style=flat-square) | ![talk-ios](https://img.shields.io/badge/talk-2.22.0-lightblue?style=flat-square) ![friend-ios](https://img.shields.io/badge/friend-2.22.0-lightblue?style=flat-square) | [![badge](https://img.shields.io/npm/dm/@react-native-kakao/social.svg?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@react-native-kakao/friend) | ๐Ÿ“ฆ | | [Navi](https://rnkakao.dev/docs/navi/intro) | ![navi-android](https://img.shields.io/badge/navi-2.20.1-green?style=flat-square) | ![navi-ios](https://img.shields.io/badge/navi-2.22.0-lightblue?style=flat-square) | [![badge](https://img.shields.io/npm/dm/@react-native-kakao/navi.svg?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@react-native-kakao/navi) | โœ… | | [Cert](https://rnkakao.dev/docs/cert/intro) | | | [![badge](https://img.shields.io/npm/dm/@react-native-kakao/cert.svg?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@react-native-kakao/cert) | ๐Ÿ“ฆ | | [Talk](https://rnkakao.dev/docs/talk/intro) | | | [![badge](https://img.shields.io/npm/dm/@react-native-kakao/talk.svg?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@react-native-kakao/talk) | ๐Ÿ“ฆ | diff --git a/docs/docs/advanced/_category_.json b/docs/docs/advanced/_category_.json new file mode 100644 index 0000000..f5b3325 --- /dev/null +++ b/docs/docs/advanced/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Advanced", + "position": 999, + "link": { + "type": "generated-index", + "description": "๋” ์ž์„ธํ•œ ๋‚ด์šฉ๋“ค์— ๋Œ€ํ•˜์—ฌ" + } +} diff --git a/docs/docs/advanced/error-handling.mdx b/docs/docs/advanced/error-handling.mdx new file mode 100644 index 0000000..d769f3b --- /dev/null +++ b/docs/docs/advanced/error-handling.mdx @@ -0,0 +1,170 @@ +--- +sidebar_position: 1 +--- + +# ์—๋Ÿฌ ํ•ธ๋“ค๋ง + +์ด ๊ธ€์—์„œ ๋งํ•˜๋Š” ์—๋Ÿฌ๋Š” APIํ˜ธ์ถœ ์‹œ์— `Promise`๊ฐ€ `reject`๋˜์–ด `catch`๊ฐ™์€ ๋กœ์ง์œผ๋กœ ์žก์•„๋‚ผ ์ˆ˜ ์žˆ๋Š” ์—๋Ÿฌ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. + +## APIํ˜ธ์ถœ์— ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์‹œ์ ์˜ ๋™๊ธฐํ™” + +:::info +ํ˜„์žฌ ์ง€์›ํ•˜๋Š” ํ”Œ๋žซํผ์ธ `Android`์™€ `iOS` ๊ธฐ์ค€์œผ๋กœ ์—๋Ÿฌ๊ฐ€ ์–ด๋–ค ์ƒํ™ฉ์— ๋ฐœ์ƒํ•˜๋Š”์ง€๋Š” **๋กœ์ง์ ์œผ๋กœ ๊ฑฐ์˜ ์ฐจ์ด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.** +::: + +์˜ˆ๋ฅผ ๋“ค์–ด, Native Kakao SDK์˜ Android์™€ iOS์˜ ์œ ์ € ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” `me` ํ•จ์ˆ˜๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. + +Kakao SDK๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ์ฝœ๋ฐฑ ๋ฐฉ์‹์˜ ๊ตฌํ˜„(์ด ํŒจํ‚ค์ง€๋Š” ReactiveX๋Š” ๊ตณ์ด ์“ฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.)์„ ์ทจํ•ฉ๋‹ˆ๋‹ค. + +๋Œ€๋ถ€๋ถ„์˜ API wrapper ํ•จ์ˆ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜•ํƒœ๋ฅผ ์ทจํ•ฉ๋‹ˆ๋‹ค. + +```swift title='ios.swift' +@objc public func me( + _ resolve: @escaping RCTPromiseResolveBlock, + reject: @escaping RCTPromiseRejectBlock +) { + onMain { + UserApi.shared.me { user, error in + if let error { + RNCKakaoUtil.reject(reject, error) + } else if let user { + resolve([ + "id": user.id as Any + //... + ]) + } else { + RNCKakaoUtil.reject(reject, "user not found") + } + } + } +} +``` + +```kotlin title='android.kt' +@ReactMethod +override fun me(promise: Promise) = + onMain { + UserApiClient.instance.me { user, error -> + if (error != null) { + promise.rejectWith(error) + } else if (user == null) { + promise.rejectWith("user not found") + } else { + promise.resolve( + argMap().apply { + putIntIfNotNull("id", user.id?.toInt()) + // ... + }, + ) + } + } + } +``` + +Kakao SDK์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋“ค์€ ํ˜•ํƒœ๊ฐ€ ๋™์ผํ•˜๊ฒŒ ํ•ญ์ƒ ์ฒซ ์ธ์ž๋Š” ๊ฒฐ๊ณผ๊ฐ’, ๋‘ ๋ฒˆ์งธ ์ธ์ž๋Š” ์—๋Ÿฌ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. + +๋งŒ์•ฝ ์—๋Ÿฌ๊ฐ€ `null` ๊ฐ’์ด ์•„๋‹ˆ๋ผ๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +๋˜ํ•œ ์ด ํŒจํ‚ค์ง€์—์„  ์ฒซ ์ธ์ž๊ฐ€ ์œ ์˜๋ฏธํ•œ ๊ฐ’์ด ํฌํ•จ๋˜์–ด์„œ ์˜ค๋Š”์ง€๋„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. + +:::note +์ด ๋™์ž‘์€ ์•„๋งˆ๋„ ์˜๋ฏธ์—†๋Š” ํ–‰์œ„(TILT)์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. +::: + +๋‘˜ ๋‹ค ์•„๋‹ˆ๋ผ๋ฉด ์„ฑ๊ณต์ ์œผ๋กœ ๊ฒฐ๊ณผ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + +## ์—๋Ÿฌ์˜ ํ˜•ํƒœ + +JavaScript๋กœ `catch`๋กœ ์ „๋‹ฌ๋˜๋Š” ์—๋Ÿฌ ๊ฐ์ฒด๋Š” ํ”Œ๋žซํผ๋ณ„๋กœ ์กฐ๊ธˆ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. + +Native Kakao SDK๋Š” ํ”Œ๋žซํผ๋ณ„๋กœ ์—๋Ÿฌ ์ฝ”๋“œ๋กœ ์†Œํ†ตํ•˜์ง€๋งŒ ์ด ํŒจํ‚ค์ง€์—์„  ๋ชจ๋“  ์—๋Ÿฌ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ฉํ•˜๊ธฐ๋ณด๋‹จ ๊ทธ๋Œ€๋กœ ์œ ์˜๋ฏธํ•œ ๊ฐ’์„ ๋‹ด์•„ +transitivityํ•˜๊ฒŒ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ์‹์„ ์ทจํ•ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ๋Œ€๋ถ€๋ถ„์˜ ์—๋Ÿฌ๋Š” `code`๋กœ ํŒ๋‹จ ๊ฐ€๋Šฅํ•˜๋ฉฐ ๋Œ€๋žต ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค. + +์ด๊ฒƒ์€ ์ด ํŒจํ‚ค์ง€๊ฐ€ ํŽธ๋ฆฌํ•œ ์—๋Ÿฌ ํ•ธ๋“ค๋ง์„ ์œ„ํ•ด ์˜๋ฏธ์žˆ๋Š” ๊ฐ’์„ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด ๋งŽ์€ ๊ด€์‹ฌ์„ ๊ธฐ์šธ์—ฌ ๊ฐœ๋ฐœ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +- Android + +```js +{ + "message": "authentication tokens don't exist.", + "code": "TokenNotFound", + "nativeStackAndroid": [], + "userInfo": { + "isAppsFailed": false, + "isInvalidTokenError": false, + "isClientFailed": true, + "fatal": true, + "isAuthFailed": false, + "isApiFailed": false, + "nativeErrorMessage": "authentication tokens don't exist." + } +} +``` + +- iOS + +```js +{ + "code": "TokenNotFound", + "message": "authentication tokens not exist.", + "nativeStackIOS": [ + "0 KakaoExample 0x000000010069dc9c RCTJSErrorFromCodeMessageAndNSError + 112", + "1 KakaoExample 0x00000001009a023c ___ZZN8facebook5react15ObjCTurboModule13createPromiseERNS_3jsi7RuntimeENSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEU13block_pointerFvU13block_pointerFvP11objc_objectEU13block_pointerFvP8NSStringSH_P7NSErrorEEENK3$_0clES4_RKNS2_5ValueEPSQ_m_block_invoke.59 + 388", + "2 KakaoExample 0x00000001002c5e20 $sSo8NSStringCSgACSo7NSErrorCSgIeyByyy_SSSgAGs5Error_pSgIegggg_TR + 380", + // ... + ], + "domain": "RNCKakaoErrorDomain", + "userInfo": { + "isAuthFailed": false, + "isInvalidTokenError": false, + "isAppsFailed": false, + "isClientFailed": true, + "isApiFailed": false, + "fatal": false, + "nativeErrorMessage": "The operation couldnโ€™t be completed. (KakaoSDKCommon.SdkError error 0.)" + } +} + +``` + +์ค‘์š”ํ•œ ๊ฒƒ์€ `code`, `message`์ด๊ณ  ๊ธฐํƒ€ ๋ถ€๊ฐ€์ ์ธ ์ •๋ณด๋Š” `userInfo`์— ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. + +:::warning ๊ฒฝ๊ณ  +`code`๋Š” Native Kakao SDK์˜ Enum์˜ case ์ด๋ฆ„๋“ค์„ ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ์˜จ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— Native Kakao SDK์—์„œ +๋‘ ์ผ€์ด์Šค์˜ ์ด๋ฆ„์ด ๋‹ค๋ฅด๊ฒŒ ์ •์˜๋˜์—ˆ๋‹ค๋ฉด ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. +::: + +## ์—๋Ÿฌ๋ฅผ ํ•ธ๋“ค๋งํ•˜๋Š” ์˜ˆ์‹œ + +์‹ค์ œ ์–ด๋– ํ•œ `code`๊ฐ’๋“ค์ด ์กด์žฌํ•˜๋Š”์ง€๋Š” Android, iOS ๊ณต์‹ API ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•ด์„œ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ๋Œ€๋žต ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋Œ€๋ถ€๋ถ„์˜ ์—๋Ÿฌ๋ฅผ ์ •ํ™•ํžˆ ๊ตฌ๋ณ„ํ•ด ํ•ธ๋“ค๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +```tsx + selectSingleFriend({ mode: 'popup', options: {} }) + .then((res) => showMessage({ message: formatJson(res) })) + .catch((e) => { + if (e && typeof e === 'object') { + if (e.code === 'TokenNotFound') { + showMessage({ type: 'warning', message: 'ํ† ํฐ์„ ์–ป์–ด์˜ค์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค' }); + } else { + // ... + } + } else { + showMessage({ type: 'warning', message: '์•Œ ์ˆ˜ ์—†๋Š” ์—๋Ÿฌ์ž…๋‹ˆ๋‹ค' }); + } + }) +``` + + + +## Android์˜ ActivityNotFoundException + +Android์˜ `Context`๊ฐ€ ํ•„์š”ํ•œ API๋“ค์€ React Native Module์—์„œ ์ œ๊ณตํ•˜๋Š” `getCurrentActivity()`๋ฅผ ํ†ตํ•ด ๋™์ž‘๋ฉ๋‹ˆ๋‹ค. + +`ReactApplicationContext`๋Š” theme์— ๋Œ€ํ•œ ์ •๋ณด๋‚˜ `startActivity`๊ฐ™์€ ํ–‰์œ„์—์„œ ์ถ”๊ฐ€์ ์ธ ํ”Œ๋ž˜๊ทธ๋ฅผ ์š”๊ตฌํ•˜์—ฌ ์˜ˆ๊ธฐ์น˜ ๋ชปํ•œ +๊ฒฐ๊ณผ๋กœ ๊ท€๊ฒฐ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +๋”ฐ๋ผ์„œ `getCurrentActivity()`๊ฐ€ `null`์ด ๋ฐ˜ํ™˜๋  ๊ฒฝ์šฐ์—๋„ ์—๋Ÿฌ๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. diff --git a/docs/docs/advanced/thread.mdx b/docs/docs/advanced/thread.mdx new file mode 100644 index 0000000..f533d82 --- /dev/null +++ b/docs/docs/advanced/thread.mdx @@ -0,0 +1,25 @@ +--- +sidebar_position: 2 +--- + +# ์“ฐ๋ ˆ๋“œ + +## API๊ฐ€ ๋™์ž‘ํ•˜๋Š” ์“ฐ๋ ˆ๋“œ + +๋ชจ๋“  API๋Š” ๋ช…์‹œ์ ์œผ๋กœ **Main Thread**์—์„œ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. + +์‚ฌ์‹ค์ƒ Kakao Native SDK์˜ ํ•จ์ˆ˜๋“ค์€ ์ฝœ๋ฐฑ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•˜๊ณ  ์ฝœ๋ฐฑ ๋‚ด๋ถ€๋Š” Main Thread์—์„œ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ๋ชจ๋“  ๋กœ์ง์„ Main Thread์—์„œ ์‹คํ–‰์‹œํ‚ด์œผ๋กœ์จ ํ˜น์‹œ ๋ชจ๋ฅผ ์—๋Ÿฌ๋ฅผ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค. + +์ด ํŒจํ‚ค์ง€์—์„œ ์ œ๊ณตํ•˜๋Š” ํ•จ์ˆ˜๋“ค์€ ๋Œ€๋ถ€๋ถ„ Native SDK๋ฅผ ํฌํŒ…ํ•œ ์ผ๋ฐ˜์ ์ธ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฌด๊ฑฐ์šด ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ํŒ๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค. + +์ด ๋™์ž‘์€ ์ถ”ํ›„์— ์„ฑ๋Šฅ์ ์ธ ๊ฐœ์„ ์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ๋…ผ์˜๋  ์‹œ, ์–ธ์ œ๋“ ์ง€ ์ˆ˜์ •๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +:::tip +iOS์˜ Native Module์—์„œ requireMainQueueSetup์€ ์•ฑ์˜ ๋ถ€ํŒ… ์‹œ๊ฐ„์„ ๋Š˜๋ฆด ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ํ•„์š”ํ•˜์ง€ ์•Š๊ธฐ๋•Œ๋ฌธ์— ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +::: + + + + diff --git a/docs/docs/share/intro.mdx b/docs/docs/share/intro.mdx index bec2be4..a9e2292 100644 --- a/docs/docs/share/intro.mdx +++ b/docs/docs/share/intro.mdx @@ -4,10 +4,13 @@ sidebar_position: 1 + + + + import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; - # ์‹œ์ž‘ํ•˜๊ธฐ ## ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— @@ -20,6 +23,14 @@ import TabItem from '@theme/TabItem'; [๊ณต์‹ ๋ฌธ์„œ](https://developers.kakao.com/docs/latest/ko/message/common)๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค. +![image](https://raw.githubusercontent.com/mym0404/image-archive/master/202404271646217.webp) + +:::tip +์œ„ ์ด๋ฏธ์ง€๋Š” ์นด์นด์˜คํ†ก์ด ์„ค์น˜๋˜์ง€ ์•Š์€ ํ™˜๊ฒฝ์—์„œ ์‹คํ–‰์‹œ์ผฐ์„ ๋•Œ ์›น ๋ธŒ๋ผ์šฐ์ €๋„ ์ด์šฉํ•ด์„œ ๊ณต์œ ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ์„ ๋ณด์—ฌ์ฃผ๋Š” ์ด๋ฏธ์ง€์ž…๋‹ˆ๋‹ค. + +์นด์นด์˜คํ†ก์ด ์„ค์น˜๋œ ๊ธฐ๊ธฐ์ธ ๊ฒฝ์šฐ ์นด์นด์˜คํ†ก์—์„œ ๊ณต์œ ๊ฐ€ ๋™์ž‘๋ฉ๋‹ˆ๋‹ค. +::: + ## ์„ค์น˜ํ•˜๊ธฐ @@ -44,4 +55,4 @@ import TabItem from '@theme/TabItem'; ์นด์นด์˜ค ๊ณต์œ  ๋ฐ ์นด์นด์˜ค ๋ฉ”์„ธ์ง€๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ์— ์•ž์„œ ์นด์นด์˜ค ๊ฐœ๋ฐœ์ž ์ฝ˜์†”์—์„œ ์ถ”๊ฐ€๋กœ ์„ค์ •ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. -[๊ณต์‹ ๋ฌธ์„œ](https://developers.kakao.com/docs/latest/ko/message/prerequisite)๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”. \ No newline at end of file +[๊ณต์‹ ๋ฌธ์„œ](https://developers.kakao.com/docs/latest/ko/message/prerequisite)๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”. diff --git a/docs/docs/social/select-talk-friends.mdx b/docs/docs/social/select-talk-friends.mdx index 031c580..4d0de17 100644 --- a/docs/docs/social/select-talk-friends.mdx +++ b/docs/docs/social/select-talk-friends.mdx @@ -17,6 +17,18 @@ API๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ์นด์นด์˜ค ๋กœ๊ทธ์ธ ๋ฐ ๊ด€๋ จ ๋™์˜ ํ•ญ๋ชฉ์ด ์‚ฌ์šฉ ๊ถŒํ•œ ์‹ ์ฒญ์— ๋Œ€ํ•ด์„œ๋Š” [๊ณต์‹ ๋ฌธ์„œ](https://developers.kakao.com/docs/latest/ko/kakaotalk-social/common#policy-request-permission)๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”. ::: +![image](https://raw.githubusercontent.com/mym0404/image-archive/master/202404271649815.webp) + +๋™์˜ ํ•ญ๋ชฉ์ด ์ด์šฉ์ค‘ ๋™์˜๋กœ ์„ค์ •๋˜์–ด์žˆ๋‹ค๋ฉด ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ์ด์šฉํ•˜๋ ค๋Š” API๋ฅผ ํ˜ธ์ถœํ•˜๋ ค ํ•  ์‹œ์— ๊ถŒํ•œ ํ—ˆ์šฉ ์•ˆ๋‚ด๊ฐ€ ์œ„ ์ด๋ฏธ์ง€๊ฐ™์ด ๋…ธ์ถœ๋ฉ๋‹ˆ๋‹ค. + +{"full + +`mode='full'` ํ˜•ํƒœ์˜ ์ „์ฒด ํ™”๋ฉด์„ ์ฑ„์šฐ๋Š” ํ”ผ์ปค์ž…๋‹ˆ๋‹ค. + +{"full + +`mode='popup'` ํ˜•ํƒœ์˜ ํŒ์—… ํ˜•์‹์˜ ํ”ผ์ปค์ž…๋‹ˆ๋‹ค. + ## ๊ณตํ†ต ํƒ€์ž…๋“ค ์นœ๊ตฌ ํ”ผ์ปค๋ฅผ ์„ค์ •ํ•˜๋Š” ์˜ต์…˜ ๊ฐ์ฒด์™€ ์นœ๊ตฌ ๊ฐ์ฒด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜๋ฉ๋‹ˆ๋‹ค. diff --git a/docs/docs/user/login.mdx b/docs/docs/user/login.mdx index c11d623..969d887 100644 --- a/docs/docs/user/login.mdx +++ b/docs/docs/user/login.mdx @@ -6,6 +6,12 @@ sidebar_position: 5 ## ๋กœ๊ทธ์ธํ•˜๊ธฐ +์นด์นด์˜ค ๋กœ๊ทธ์ธํ•˜๊ธฐ๋ฅผ ์ด์šฉํ•ด ํšŒ์›๊ฐ€์ž…, ๋กœ๊ทธ์ธ, ์ถ”๊ฐ€ ๋™์˜๋‚ด์—ญ ๋ฐ›๊ธฐ, ์•ฝ๊ด€ ๋™์˜์‹œํ‚ค๊ธฐ ๋“ฑ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +![image](https://raw.githubusercontent.com/mym0404/image-archive/master/202404271643817.webp) + +## Usage + `login()` ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์ฃผ๋ฉด ๋ฐ”๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ```tsx @@ -100,4 +106,4 @@ login() ## ์นด์นด์˜คํ†ก์ด ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ์ง€ ํ™•์ธํ•˜๊ธฐ -`isKakaoTalkLoginAvailable()`๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ˜ํ™˜๊ฐ’์€ `Promise` ์ž…๋‹ˆ๋‹ค. \ No newline at end of file +`isKakaoTalkLoginAvailable()`๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ˜ํ™˜๊ฐ’์€ `Promise` ์ž…๋‹ˆ๋‹ค. diff --git a/docs/docusaurus.config.ts b/docs/docusaurus.config.ts index 8337284..93b2b3d 100644 --- a/docs/docusaurus.config.ts +++ b/docs/docusaurus.config.ts @@ -37,7 +37,7 @@ const config: Config = { { docs: { sidebarPath: './sidebars.ts', - editUrl: `${repoUrl}/tree/main/doc/`, + editUrl: `${repoUrl}/tree/main/docs/`, }, theme: { customCss: './src/css/custom.css', diff --git a/example/src/app/index.tsx b/example/src/app/index.tsx index db7e977..b95c475 100644 --- a/example/src/app/index.tsx +++ b/example/src/app/index.tsx @@ -46,7 +46,7 @@ export default function Page() { {'Native Kakao Sdk All In One Solution'} - + - selectSingleFriend({ mode: 'full', options: {} }) + selectSingleFriend({ mode: 'popup', options: {} }) .then((res) => showMessage({ message: formatJson(res) })) - .catch((e) => showMessage({ type: 'warning', message: e.message })) + .catch((e) => { + if (e && typeof e === 'object') { + if (e.code === 'TokenNotFound') { + showMessage({ type: 'warning', message: 'ํ† ํฐ์„ ์–ป์–ด์˜ค์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค' }); + } else { + // ... + } + } + }) } /> - selectMultipleFriends({ mode: 'full', options: {} }) + selectMultipleFriends({ mode: 'popup', options: {} }) .then((res) => showMessage({ message: formatJson(res) })) .catch((e) => showMessage({ type: 'warning', message: e.message })) } diff --git a/packages/core/android/src/main/java/net/mjstudio/rnkakao/core/util/DebugE.kt b/packages/core/android/src/main/java/net/mjstudio/rnkakao/core/util/DebugE.kt new file mode 100644 index 0000000..3f417b1 --- /dev/null +++ b/packages/core/android/src/main/java/net/mjstudio/rnkakao/core/util/DebugE.kt @@ -0,0 +1,16 @@ +package net.mjstudio.rnkakao.core.util + +import android.util.Log +import net.mjstudio.rnkakao.core.BuildConfig + +private fun debugE(message: Any?) { + if (BuildConfig.DEBUG) Log.e("RNCKakao", "โญ๏ธ" + message.toString()) +} + +fun debugE(vararg message: Any?) { + var str = "" + for (i in message) { + str += i.toString() + ", " + } + debugE(str) +} diff --git a/packages/core/android/src/main/java/net/mjstudio/rnkakao/core/util/RNCKakaoUtil.kt b/packages/core/android/src/main/java/net/mjstudio/rnkakao/core/util/RNCKakaoUtil.kt index cc3a09d..42c1723 100644 --- a/packages/core/android/src/main/java/net/mjstudio/rnkakao/core/util/RNCKakaoUtil.kt +++ b/packages/core/android/src/main/java/net/mjstudio/rnkakao/core/util/RNCKakaoUtil.kt @@ -10,51 +10,60 @@ import com.facebook.react.bridge.UiThreadUtil import com.facebook.react.bridge.WritableArray import com.facebook.react.bridge.WritableMap import com.kakao.sdk.common.model.ApiError +import com.kakao.sdk.common.model.AppsError +import com.kakao.sdk.common.model.AuthError +import com.kakao.sdk.common.model.ClientError import java.util.Date +private const val UNKNOWN_ERROR = "RNC_KAKAO_UNKNOWN" + fun Promise.rejectWith(e: Throwable) { - val message = e.localizedMessage ?: "unknown" - if (e is ApiError) { - val code = e.reason.errorCode - val statusCode = e.statusCode - - reject( - code.toString(), - "${e.reason.name} $message", - Arguments.createMap().apply { - putString("code", code.toString()) - putInt("statusCode", statusCode) - putString("message", message) - putInt("nativeErrorCode", code) - putString("nativeErrorMessage", message) - putBoolean("isInvalidTokenError", e.isInvalidTokenError()) - }, - ) - } else { - reject( - "unknown", - message, - Arguments.createMap().apply { - putInt("code", -1) - putString("message", message) - putInt("nativeErrorCode", -1) - putString("nativeErrorMessage", message) - }, - ) + val message = e.localizedMessage ?: "" + + val userInfo = + argMap().apply { + putBoolean("fatal", true) + putString("nativeErrorMessage", message) + putBoolean("isApiFailed", false) + putBoolean("isAuthFailed", false) + putBoolean("isClientFailed", false) + putBoolean("isAppsFailed", false) + putBoolean("isInvalidTokenError", false) + } + + when (e) { + is ClientError -> { + userInfo.putBoolean("isClientFailed", true) + userInfo.putBoolean("isInvalidTokenError", e.isInvalidTokenError()) + reject(e.reason.name, e.msg, userInfo) + } + is ApiError -> { + userInfo.putBoolean("isApiFailed", true) + userInfo.putBoolean("isInvalidTokenError", e.isInvalidTokenError()) + reject(e.reason.name, e.msg, userInfo) + } + is AuthError -> { + userInfo.putBoolean("isAuthFailed", true) + userInfo.putBoolean("isInvalidTokenError", e.isInvalidTokenError()) + reject(e.reason.name, e.msg, userInfo) + } + is AppsError -> { + userInfo.putBoolean("isAppsFailed", true) + userInfo.putBoolean("isInvalidTokenError", e.isInvalidTokenError()) + reject(e.reason.name, e.msg, userInfo) + } + else -> { + reject( + UNKNOWN_ERROR, + message, + userInfo, + ) + } } } fun Promise.rejectWith(s: String) { - reject( - "unknown", - s, - Arguments.createMap().apply { - putInt("code", -1) - putString("message", s) - putInt("nativeErrorCode", -1) - putString("nativeErrorMessage", s) - }, - ) + rejectWith(RuntimeException(s)) } inline fun ReadableArray.filterIsInstance(): List { diff --git a/packages/core/ios/Util/RNCkakaoUtil.swift b/packages/core/ios/Util/RNCkakaoUtil.swift index 6077168..e3b3ff9 100644 --- a/packages/core/ios/Util/RNCkakaoUtil.swift +++ b/packages/core/ios/Util/RNCkakaoUtil.swift @@ -3,39 +3,35 @@ import React import UIKit private let DEFAULT_APP_DISPLAY_NAME = "RNKakao" +private let UNKNOWN_ERROR = "RNC_KAKAO_UNKNOWN" + +private enum RNCKakaoError: Error { + case unknown(message: String) +} public class RNCKakaoUtil { static let RNCKakaoErrorDomain = "RNCKakaoErrorDomain" - public class func reject( - _ reject: RCTPromiseRejectBlock, - _ exception: NSException - ) { + public class func reject(_ reject: RCTPromiseRejectBlock, _ error: Error) { var userInfo = [String: Any]() - userInfo["fatal"] = true - userInfo["code"] = "unknown" - userInfo["message"] = exception.reason - userInfo["nativeErrorCode"] = exception.name.rawValue - userInfo["nativeErrorMessage"] = exception.reason - - let error = NSError(domain: RNCKakaoErrorDomain, code: 444, userInfo: userInfo) - reject(exception.name.rawValue, exception.reason, error) - } + let message = error.localizedDescription - public class func reject(_ reject: RCTPromiseRejectBlock, _ error: Error) { - var userInfo = [String: Any]() userInfo["fatal"] = false - userInfo["code"] = "unknown" - userInfo["message"] = error.localizedDescription - userInfo["nativeErrorCode"] = -1 - userInfo["nativeErrorMessage"] = error.localizedDescription + userInfo["nativeErrorMessage"] = message + userInfo["isApiFailed"] = false + userInfo["isAuthFailed"] = false + userInfo["isClientFailed"] = false + userInfo["isAppsFailed"] = false + userInfo["isInvalidTokenError"] = false if let kakaoError = error as? SdkError { userInfo["isApiFailed"] = kakaoError.isApiFailed userInfo["isAuthFailed"] = kakaoError.isAuthFailed userInfo["isClientFailed"] = kakaoError.isClientFailed + userInfo["isAppsFailed"] = kakaoError.isAppsFailed userInfo["isInvalidTokenError"] = kakaoError.isInvalidTokenError() + switch kakaoError { case let .ClientFailed(reason, errorMessage): reject( @@ -48,35 +44,34 @@ public class RNCKakaoUtil { userInfo["requiredScopes"] = requiredScopes } reject( - String(reason.rawValue), - errorInfo?.msg ?? kakaoError.localizedDescription, + "\(reason)", + errorInfo?.msg ?? message, NSError(domain: RNCKakaoErrorDomain, code: 444, userInfo: userInfo) ) case let .AuthFailed(reason, errorInfo): reject( - reason.rawValue, - errorInfo?.errorDescription ?? kakaoError.localizedDescription, + "\(reason)", + errorInfo?.errorDescription ?? message, NSError(domain: RNCKakaoErrorDomain, code: 444, userInfo: userInfo) ) case let .AppsFailed(reason, errorInfo): reject( - reason.rawValue, - errorInfo?.errorMsg ?? kakaoError.localizedDescription, + "\(reason)", + errorInfo?.errorMsg ?? message, NSError(domain: RNCKakaoErrorDomain, code: 444, userInfo: userInfo) ) } } else { reject( - "unknown", - error.localizedDescription, + UNKNOWN_ERROR, + message, NSError(domain: RNCKakaoErrorDomain, code: 444, userInfo: userInfo) ) } } public class func reject(_ reject: RCTPromiseRejectBlock, _ message: String) { - let error = NSError(domain: RNCKakaoErrorDomain, code: 444, userInfo: ["message": message]) - reject(DEFAULT_APP_DISPLAY_NAME, message, error) + self.reject(reject, RNCKakaoError.unknown(message: message)) } private class func getTopmostViewController(