Skip to content

Commit

Permalink
feat(social): getFriends feature
Browse files Browse the repository at this point in the history
  • Loading branch information
mym0404 committed Apr 27, 2024
1 parent 9107263 commit 30ac791
Show file tree
Hide file tree
Showing 12 changed files with 244 additions and 54 deletions.
59 changes: 59 additions & 0 deletions docs/docs/social/get-friends.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
sidebar_position: 4
---

# 카카오톡 친구 가져오기
## 카카오톡 친구 가져오기

[공식 문서](https://developers.kakao.com/docs/latest/ko/kakaotalk-social/android#get-friends)

:::info
API를 사용하기 위해서 카카오 로그인 및 관련 동의 항목이 동의된 상태여야 합니다.

피커와 친구 목록 가져오기 API는 사용 권한이 주어진 앱에서만 사용할 수 있습니다.
:::

현재 로그인한 사용자의 카카오톡 친구 목록을 불러옵니다.
요청 시 친구 목록의 정렬 순서, 한 페이지당 친구 수를 선택적으로 지정할 수 있습니다. 파라미터 없이 요청 시 기본 설정대로 요청이 전송됩니다.

## Usage

`getFriends()`를 이용해 친구 목록을 가져올 수 있습니다.

다음과 같이 정의되어 있습니다.

```tsx
export function getFriends(params: {
options?: KakaoTalkGetFriendsOptions;
}): Promise<KakaoTalkGetFriendsResult>
```

사용되는 타입들은 다음과 같습니다.

```tsx
/**
* 카카오톡 친구
*
* @property id 회원번호
* @property uuid 메시지를 전송하기 위한 고유 아이디. 사용자의 계정 상태에 따라 이 정보는 바뀔 수 있으므로 앱내의 사용자 식별자로는 권장하지 않음.
* @property profileNickname 친구의 닉네임
* @property profileThumbnailImage 썸네일 이미지 URL
* @property favorite 즐겨찾기 추가 여부
* @property allowedMsg 메시지 수신이 허용되었는지 여부. 앱가입 친구의 경우는 feed msg 에 해당. 앱미가입친구는 invite msg 에 해당
*/
export interface KakaoTalkFriend {
id?: number;
uuid: string;
profileNickname: string;
profileThumbnailImage?: string;
favorite?: boolean;
allowedMsg?: boolean;
}
export interface KakaoTalkGetFriendsOptions {
offset?: number;
limit?: number;
order?: 'asc' | 'desc';
friendOrder?: 'nickname' | 'age' | 'favorite';
}
```
2 changes: 1 addition & 1 deletion docs/docs/social/get-talk-profile.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 5
sidebar_position: 2
---

# 내 카카오톡 프로필 가져오기
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/social/select-talk-friends.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 5
sidebar_position: 3
---

# 카카오톡 친구 선택하기
Expand Down
4 changes: 2 additions & 2 deletions example/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@
"https://devrepo.kakao.com/nexus/content/groups/public/"
],
"minSdkVerson": 26,
"newArchEnabled": false
"newArchEnabled": true
},
"ios": {
"newArchEnabled": false
"newArchEnabled": true
}
}
],
Expand Down
9 changes: 9 additions & 0 deletions example/src/app/social.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useState } from 'react';
import { showMessage } from 'react-native-flash-message';
import { formatJson } from '@mj-studio/js-util';
import {
getFriends,
getTalkProfile,
type KakaoTalkProfile,
selectMultipleFriends,
Expand Down Expand Up @@ -54,6 +55,14 @@ export default function Page() {
.catch((e) => showMessage({ type: 'warning', message: e.message }))
}
/>
<Btn
title={'Get Friends'}
onPress={() =>
getFriends({ options: {} })
.then((res) => showMessage({ message: formatJson(res) }))
.catch((e) => showMessage({ type: 'warning', message: e.message }))
}
/>
</StyledScrollView>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import com.kakao.sdk.friend.model.ViewAppearance.AUTO
import com.kakao.sdk.friend.model.ViewAppearance.DARK
import com.kakao.sdk.friend.model.ViewAppearance.LIGHT
import com.kakao.sdk.talk.TalkApiClient
import com.kakao.sdk.talk.model.FriendOrder
import com.kakao.sdk.talk.model.Order
import net.mjstudio.rnkakao.core.util.RNCKakaoResponseNotFoundException
import net.mjstudio.rnkakao.core.util.argArr
import net.mjstudio.rnkakao.core.util.argMap
Expand Down Expand Up @@ -133,6 +135,58 @@ class RNCKakaoSocialModule internal constructor(context: ReactApplicationContext
minPickableCount = options?.getIntElseNull("minPickableCount"),
)

@ReactMethod
override fun getFriends(
options: ReadableMap?,
promise: Promise,
) = onMain {
TalkApiClient.instance.friends(
offset = options?.getIntElseNull("offset"),
limit = options?.getIntElseNull("limit"),
order =
when (options?.getString("order")) {
"asc" -> Order.ASC
"desc" -> Order.DESC
else -> null
},
friendOrder =
when (options?.getString("friendOrder")) {
"nickname" -> FriendOrder.NICKNAME
"age" -> FriendOrder.AGE
"favorite" -> FriendOrder.FAVORITE
else -> null
},
) { friends, error ->
if (error != null) {
promise.rejectWith(error)
} else if (friends?.elements == null) {
promise.rejectWith(RNCKakaoResponseNotFoundException("friends"))
} else {
promise.resolve(
argMap().apply {
putInt("totalCount", friends.totalCount)
putIntIfNotNull("favoriteCount", friends.favoriteCount)
putArray(
"friends",
argArr().pushMapList(
friends.elements!!.map {
argMap().apply {
putIntIfNotNull("id", it.id?.toInt())
putString("uuid", it.uuid)
putString("profileNickname", it.profileNickname)
putString("profileThumbnailImage", it.profileThumbnailImage)
putBooleanIfNotNull("favorite", it.favorite)
putBooleanIfNotNull("allowedMsg", it.allowedMsg)
}
},
),
)
},
)
}
}
}

companion object {
const val NAME = "RNCKakaoSocial"
}
Expand Down
5 changes: 5 additions & 0 deletions packages/social/android/src/oldarch/KakaoSocialSpec.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,9 @@ abstract class KakaoSocialSpec internal constructor(context: ReactApplicationCon
options: ReadableMap?,
promise: Promise,
)

abstract fun getFriends(
options: ReadableMap?,
promise: Promise,
)
}
22 changes: 16 additions & 6 deletions packages/social/ios/RNCKakaoSocial.mm
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,28 @@ - (RNCKakaoSocialManager*)manager {

RCT_EXPORT_MODULE()

- (void)getProfile:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
RCT_EXPORT_METHOD(getProfile
: (RCTPromiseResolveBlock)resolve reject
: (RCTPromiseRejectBlock)reject) {
[[self manager] getProfile:resolve reject:reject];
}

- (void)selectFriends:(BOOL)multiple
mode:(NSString*)mode
options:(NSDictionary*)options
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject {
RCT_EXPORT_METHOD(selectFriends
: (BOOL)multiple mode
: (NSString*)mode options
: (NSDictionary*)options resolve
: (RCTPromiseResolveBlock)resolve reject
: (RCTPromiseRejectBlock)reject) {
[[self manager] selectFriends:multiple mode:mode options:options resolve:resolve reject:reject];
}

RCT_EXPORT_METHOD(getFriends
: (NSDictionary*)options resolve
: (RCTPromiseResolveBlock)resolve reject
: (RCTPromiseRejectBlock)reject) {
[[self manager] getFriendsWithOptions:options resolve:resolve reject:reject];
}

// Don't compile this code when we build for the old architecture.
#ifdef RCT_NEW_ARCH_ENABLED
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
Expand Down
85 changes: 50 additions & 35 deletions packages/social/ios/RNCKakaoSocialManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,41 +32,6 @@ import RNCKakaoCore
}
}

@objc public func getFriends(
options: [String: Any],
resolve: @escaping RCTPromiseResolveBlock,
reject: @escaping RCTPromiseRejectBlock
) {
let order: Order? = switch options["order"] {
case let x as String where x == "asc": .Asc
case let x as String where x == "desc": .Desc
default: nil
}
let friendOrder: FriendOrder? = switch options["friendOrder"] {
case let x as String where x == "nickname": .Nickname
case let x as String where x == "age": .Age
case let x as String where x == "favorite": .Favorite
default: nil
}

onMain {
TalkApi.shared
.friends(
offset: options["offset"] as? Int,
limit: options["limit"] as? Int,
order: order,
friendOrder: friendOrder
) { friends, error in
if let error {
RNCKakaoUtil.reject(reject, error)
} else if let friends {
} else {
RNCKakaoUtil.reject(reject, RNCKakaoError.responseNotFound(name: "friends"))
}
}
}
}

@objc public func selectFriends(
_ multiple: Bool,
mode: String,
Expand Down Expand Up @@ -138,6 +103,56 @@ import RNCKakaoCore
}
}
}

@objc public func getFriends(
options: [String: Any],
resolve: @escaping RCTPromiseResolveBlock,
reject: @escaping RCTPromiseRejectBlock
) {
let order: Order? = switch options["order"] {
case let x as String where x == "asc": .Asc
case let x as String where x == "desc": .Desc
default: nil
}
let friendOrder: FriendOrder? = switch options["friendOrder"] {
case let x as String where x == "nickname": .Nickname
case let x as String where x == "age": .Age
case let x as String where x == "favorite": .Favorite
default: nil
}

onMain {
TalkApi.shared
.friends(
offset: options["offset"] as? Int,
limit: options["limit"] as? Int,
order: order,
friendOrder: friendOrder
) { friends, error in
if let error {
RNCKakaoUtil.reject(reject, error)
} else if let friends, let items = friends.elements {
resolve([
"totalCount": friends.totalCount,
"favoriteCount": friends.favoriteCount as Any,
"friends": items
.map {
[
"id": $0.id as Any,
"uuid": $0.uuid,
"profileNickname": $0.profileNickname as Any,
"profileThumbnailImage": $0.profileThumbnailImage as Any,
"favorite": $0.favorite as Any,
"allowedMsg": $0.allowedMsg as Any
]
}
])
} else {
RNCKakaoUtil.reject(reject, RNCKakaoError.responseNotFound(name: "friends"))
}
}
}
}
}

/// /// 친구 피커의 이름
Expand Down
17 changes: 16 additions & 1 deletion packages/social/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { NativeModules, Platform } from 'react-native';

import type {
KakaoTalkFriend,
KakaoTalkFriendProfile,
KakaoTalkFriendSelectOptions,
KakaoTalkFriendSelectResult,
KakaoTalkGetFriendsOptions,
KakaoTalkGetFriendsResult,
KakaoTalkProfile,
Spec,
} from './spec/NativeKakaoSocial';
Expand All @@ -12,7 +16,10 @@ export type {
KakaoTalkFriendProfile,
KakaoTalkFriendSelectOptions,
KakaoTalkFriendSelectResult,
} from './spec/NativeKakaoSocial';
KakaoTalkGetFriendsOptions,
KakaoTalkFriend,
KakaoTalkGetFriendsResult,
};

const LINKING_ERROR =
"The package '@react-native-kakao/social' doesn't seem to be linked. Make sure: \n\n" +
Expand Down Expand Up @@ -63,3 +70,11 @@ export function selectMultipleFriends({
}) {
return Native.selectFriends(true, mode, options);
}

export function getFriends({
options = {},
}: {
options?: KakaoTalkGetFriendsOptions;
}): Promise<KakaoTalkGetFriendsResult> {
return Native.getFriends(options);
}
Loading

0 comments on commit 30ac791

Please sign in to comment.