Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

카카오톡 공유, URL 공유 기능 구현 #107

Merged
merged 39 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
f9e2c74
[feat] #78 KakaoSDK 연결
ShapeKim98 Aug 15, 2024
2673215
[docs] #78 카카오 SDK 네이티브 앱 키 등록
ShapeKim98 Aug 15, 2024
0e1b270
[feat] #78 KakaShareClient 작성
ShapeKim98 Aug 15, 2024
d33b229
[feat] #78 카카오톡 링크 공유 및 url scheme으로 링크 상세보기 구현
ShapeKim98 Aug 15, 2024
c1fc49d
[fix] #78 syntex 오류 수정
ShapeKim98 Aug 21, 2024
90583ad
[fix] #78 PokitLinkCard의 케밥버튼 액션 옵셔널로 변경
ShapeKim98 Aug 21, 2024
4975c93
[feat] #78 FeatureCategorySharing 모듈 추가
ShapeKim98 Aug 22, 2024
8089d30
[feat] #78 CategorySharing에 대한 DTO 작성
ShapeKim98 Aug 22, 2024
18998f8
[feat] #78 FeatureCategorySharing에 대한 Domain 작성
ShapeKim98 Aug 22, 2024
af5bb5b
[feat] #78 공유 api의 endpoint 및 client 함수 작성
ShapeKim98 Aug 22, 2024
14f436d
[fix] #78 pageable 누락 수정
ShapeKim98 Aug 22, 2024
d6d0d99
[feat] #78 FeatureCategorySharing에 대한 store, view 작성
ShapeKim98 Aug 22, 2024
e32680e
[design] #78 PokitLinkCard
ShapeKim98 Aug 22, 2024
1028120
[refactor] #78 ContentSharing 리펙토링
ShapeKim98 Aug 22, 2024
34f09f5
[feat] #78 네비게이션 path 연결
ShapeKim98 Aug 22, 2024
d19cb7f
[feat] #78 카카오톡 카테고리 공유 구현
ShapeKim98 Aug 22, 2024
f388af6
[feat] #78 카테고리 공유 연결
ShapeKim98 Aug 22, 2024
e44ba7f
[fix] #78 공유 코드 수정
ShapeKim98 Aug 22, 2024
5a47334
[fix] #78 저장하기 api 수정
ShapeKim98 Aug 22, 2024
b9307b7
[ifx] #78 body가 없는 응답에서 error 안던저지는 문제 수정
ShapeKim98 Aug 23, 2024
62a5e9a
[fix] #78 CategorySharing 생성 파라미터 수정
ShapeKim98 Aug 23, 2024
d91a306
[ifx] #78 링크 공유에서 이름 바꿀 때의 핸들링 추가
ShapeKim98 Aug 23, 2024
682f22c
[feat] #78 공유한 사람의 공유 포킷 조회 예외 처리 구현
ShapeKim98 Aug 23, 2024
e5ca246
[feat] #78 PokitRoot에 카카오톡 공유 연결
ShapeKim98 Aug 23, 2024
4b5e011
[fix] 에러처리 수정
stealmh Aug 23, 2024
88c0845
[feat] #78 컨텐츠 url 공유 기능 작성
ShapeKim98 Aug 24, 2024
5aa8122
[feat] #78 FeatureRemind 컨텐츠 url 공유 기능 추가
ShapeKim98 Aug 24, 2024
0b2860f
[feat] #78 FeaturePokit 컨텐츠 url 공유 기능 추가
ShapeKim98 Aug 24, 2024
01f4206
[feat] #78 FeatureSearch 컨텐츠 url 공유 기능 추가
ShapeKim98 Aug 24, 2024
97268ae
[design] #78 카카오 공유하기 문구 변경
ShapeKim98 Aug 24, 2024
8ac2253
[fix] #78 카카오 공유에서 카카오톡 미설치 시 앱스토어 설치로 이동 구현
ShapeKim98 Aug 24, 2024
8ec6a98
[feat] #78 카테고리 오류코드 네이밍 변경 및 FeatureCategorySharing BaseError 적용
ShapeKim98 Aug 24, 2024
1f4b462
[feat] #78 FeatureCategorySetting 오류 핸들링 추가
ShapeKim98 Aug 24, 2024
e5c1b56
[fix] #78 링크 공유 플로우 변경
ShapeKim98 Aug 24, 2024
2cf4a1d
[fix] #78 포킷 추가 성공 delegate 안쓰이는 연관값 제거
ShapeKim98 Aug 24, 2024
4c083c6
[fix] #78 클로저 삭제
ShapeKim98 Aug 25, 2024
585bc3a
[fix] #78 피드백 반영
ShapeKim98 Aug 26, 2024
b26fa40
[fix] #78 ContentDetail 공유하기 기능 누락 수정 및 PokitAlert 취소 버튼 먹통 수정
ShapeKim98 Aug 26, 2024
ebb75a5
[fix] #78 Rebase 마무리
ShapeKim98 Aug 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions Projects/App/Resources/Pokit-info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>AppleKeyID</key>
<string>$(AppleKeyID)</string>
<key>BGTaskSchedulerPermittedIdentifiers</key>
<string>com.pokitmons.pokit.taskidentifier</string>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
Expand All @@ -28,21 +32,34 @@
<string>$(GIDClientID_reversed)</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>kakao$(KAKAO_NATIVE_APP_KEY)</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>GIDClientID</key>
<string>$(GIDClientID)</string>
<key>AppleKeyID</key>
<string>$(AppleKeyID)</string>
<key>TeamID</key>
<string>$(TeamID)</string>
<key>AuthKey</key>
<string>$(AuthKey)</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>KAKAO_NATIVE_APP_KEY</key>
<string>$(KAKAO_NATIVE_APP_KEY)</string>
<key>LSApplicationCategoryType</key>
<string></string>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>kakaokompassauth</string>
<string>kakaolink</string>
</array>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>TeamID</key>
<string>$(TeamID)</string>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
Expand Down Expand Up @@ -75,9 +92,5 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>BGTaskSchedulerPermittedIdentifiers</key>
<string>com.pokitmons.pokit.taskidentifier</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
</dict>
</plist>
5 changes: 5 additions & 0 deletions Projects/App/Sources/AppDelegate/AppDelegateFeature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Foundation

import ComposableArchitecture
import CoreKit
import KakaoSDKCommon

@Reducer
public struct AppDelegateFeature {
Expand Down Expand Up @@ -39,6 +40,10 @@ public struct AppDelegateFeature {
switch action {
case .didFinishLaunching:
let userNotificationsEventStream = self.userNotifications.delegate()
if let kakaoAppKey = Bundle.main.object(forInfoDictionaryKey: "KAKAO_NATIVE_APP_KEY") as? String {
print("카카오 네이티브 앱 키: \(kakaoAppKey)")
KakaoSDK.initSDK(appKey: kakaoAppKey)
}
return .run { send in
await withThrowingTaskGroup(of: Void.self) { group in
group.addTask {
Expand Down
55 changes: 52 additions & 3 deletions Projects/App/Sources/MainTab/MainTabFeature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,21 @@ import CoreKit
@Reducer
public struct MainTabFeature {
/// - Dependency
@Dependency(\.pasteboard) var pasteBoard
@Dependency(\.pasteboard)
private var pasteBoard
@Dependency(\.categoryClient)
private var categoryClient
/// - State
@ObservableState
public struct State: Equatable {
var selectedTab: MainTab = .pokit
var isBottomSheetPresented: Bool = false
var isLinkSheetPresented: Bool = false
var isErrorSheetPresented: Bool = false
var link: String?

var error: BaseError?

var path: StackState<MainTabPath.State> = .init()
var pokit: PokitRootFeature.State
var remind: RemindFeature.State = .init()
Expand Down Expand Up @@ -55,12 +61,19 @@ public struct MainTabFeature {
case addSheetTypeSelected(TabAddSheetType)
case linkCopyButtonTapped
case onAppear
case onOpenURL(url: URL)
case 경고_확인버튼_클릭
}
public enum InnerAction: Equatable {
case 링크추가및수정이동(contentId: Int)
case linkCopySuccess(URL?)
case 공유포킷_이동(sharedCategory: CategorySharing.SharedCategory)
case 경고_띄움(BaseError)
case errorSheetPresented(Bool)
}
public enum AsyncAction: Equatable {
case 공유받은_카테고리_조회(categoryId: Int)
}
public enum AsyncAction: Equatable { case doNothing }
public enum ScopeAction: Equatable { case doNothing }
public enum DelegateAction: Equatable {
case 링크추가하기
Expand Down Expand Up @@ -142,6 +155,21 @@ private extension MainTabFeature {
await send(.inner(.linkCopySuccess(url)), animation: .pokitSpring)
}
}
case .onOpenURL(url: let url):
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false) else {
return .none
}

let queryItems = components.queryItems ?? []
guard let categoryIdString = queryItems.first(where: { $0.name == "categoryId" })?.value,
let categoryId = Int(categoryIdString) else {
return .none
}

return .send(.async(.공유받은_카테고리_조회(categoryId: categoryId)))
case .경고_확인버튼_클릭:
state.error = nil
return .run { send in await send(.inner(.errorSheetPresented(false))) }
}
}
/// - Inner Effect
Expand All @@ -153,12 +181,33 @@ private extension MainTabFeature {
state.link = url.absoluteString
return .none

case let .경고_띄움(error):
state.error = error
return .run { send in await send(.inner(.errorSheetPresented(true))) }

case let .errorSheetPresented(isPresented):
state.isErrorSheetPresented = isPresented
return .none

default: return .none
}
}
/// - Async Effect
func handleAsyncAction(_ action: Action.AsyncAction, state: inout State) -> Effect<Action> {
return .none
switch action {
case let .공유받은_카테고리_조회(categoryId: categoryId):
return .run { send in
do {
let request = BasePageableRequest(page: 0, size: 10, sort: ["createdAt", "desc"])
let sharedCategory = try await categoryClient.공유받은_카테고리_조회("\(categoryId)", request).toDomain()
await send(.inner(.공유포킷_이동(sharedCategory: sharedCategory)), animation: .smooth)
} catch {
guard let errorResponse = error as? ErrorResponse else { return }
let errorDomain = BaseError(response: errorResponse)
await send(.inner(.경고_띄움(errorDomain)))
}
}
}
}
/// - Scope Effect
func handleScopeAction(_ action: Action.ScopeAction, state: inout State) -> Effect<Action> {
Expand Down
14 changes: 14 additions & 0 deletions Projects/App/Sources/MainTab/MainTabFeatureView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import FeatureContentDetail
import FeatureContentSetting
import FeatureCategoryDetail
import FeatureContentList
import FeatureCategorySharing

@ViewAction(for: MainTabFeature.self)
public struct MainTabView: View {
Expand Down Expand Up @@ -81,6 +82,10 @@ public extension MainTabView {
if let store = store.scope(state: \.링크목록, action: \.링크목록) {
ContentListView(store: store)
}
case .링크공유:
if let store = store.scope(state: \.링크공유, action: \.링크공유) {
CategorySharingView(store: store)
}
}

if self.store.isLinkSheetPresented {
Expand All @@ -93,6 +98,7 @@ public extension MainTabView {
}
}
}
.onOpenURL { send(.onOpenURL(url: $0)) }
}
}
}
Expand Down Expand Up @@ -128,6 +134,14 @@ private extension MainTabView {
) { store in
ContentDetailView(store: store)
}
.sheet(isPresented: $store.isErrorSheetPresented) {
PokitAlert(
store.error?.title ?? "에러",
message: store.error?.message ?? "메세지",
confirmText: "확인",
action: { send(.경고_확인버튼_클릭) }
)
}
.task { await send(.onAppear).finish() }
}

Expand Down
48 changes: 46 additions & 2 deletions Projects/App/Sources/MainTab/MainTabPath.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import FeatureCategorySetting
import FeatureContentDetail
import FeatureContentSetting
import FeatureContentList
import FeatureCategorySharing
import Domain

@Reducer
public struct MainTabPath {
Expand All @@ -26,6 +28,7 @@ public struct MainTabPath {
case 링크추가및수정(ContentSettingFeature.State)
case 카테고리상세(CategoryDetailFeature.State)
case 링크목록(ContentListFeature.State)
case 링크공유(CategorySharingFeature.State)
}

public enum Action {
Expand All @@ -36,6 +39,7 @@ public struct MainTabPath {
case 링크추가및수정(ContentSettingFeature.Action)
case 카테고리상세(CategoryDetailFeature.Action)
case 링크목록(ContentListFeature.Action)
case 링크공유(CategorySharingFeature.Action)
}

public var body: some Reducer<State, Action> {
Expand All @@ -46,6 +50,7 @@ public struct MainTabPath {
Scope(state: \.링크추가및수정, action: \.링크추가및수정) { ContentSettingFeature() }
Scope(state: \.카테고리상세, action: \.카테고리상세) { CategoryDetailFeature() }
Scope(state: \.링크목록, action: \.링크목록) { ContentListFeature() }
Scope(state: \.링크공유, action: \.링크공유) { CategorySharingFeature() }
}
}

Expand Down Expand Up @@ -88,9 +93,15 @@ public extension MainTabFeature {
return .none

/// - 포킷 `추가` or `수정`이 성공적으로 `완료`되었을 때
case let .path(.element(_, action: .포킷추가및수정(.delegate(.settingSuccess(categoryName, categoryId))))):
case .path(.element(_, action: .포킷추가및수정(.delegate(.settingSuccess)))):
state.path.removeLast()
return .none
guard let lastPath = state.path.last else { return .none }
switch lastPath {
case .링크공유:
state.path.removeLast()
return .none
default: return .none
}

/// - 포킷 카테고리 아이템 눌렀을 때
case let .pokit(.delegate(.categoryTapped(category))):
Expand Down Expand Up @@ -185,6 +196,39 @@ public extension MainTabFeature {
return .send(.delegate(.로그아웃))
case .path(.element(_, action: .설정(.delegate(.회원탈퇴)))):
return .send(.delegate(.회원탈퇴))

case let .inner(.공유포킷_이동(sharedCategory: sharedCategory)):
state.path.append(.링크공유(CategorySharingFeature.State(sharedCategory: sharedCategory)))
return .none

/// 링크 공유에서 컨텐츠 상세보기
case let .path(.element(_, action: .링크공유(.delegate(.컨텐츠_아이템_클릭(categoryId: categoryId, content: content))))):
state.contentDetail = ContentDetailFeature.State(content: BaseContentDetail(
id: content.id,
category: BaseCategoryInfo(
categoryId: categoryId,
categoryName: content.categoryName
),
title: content.title,
data: content.data,
memo: content.memo,
createdAt: content.createdAt,
favorites: nil,
alertYn: .no
))
return .none

case let .path(.element(_, action: .링크공유(.delegate(.공유받은_카테고리_추가(sharedCategory))))):
state.path.append(.포킷추가및수정(PokitCategorySettingFeature.State(
type: .공유추가,
categoryId: sharedCategory.categoryId,
categoryImage: BaseCategoryImage(
imageId: sharedCategory.categoryImageId,
imageURL: sharedCategory.categoryImageUrl
),
categoryName: sharedCategory.categoryName
)))
return .none
default: return .none
}
}
Expand Down
5 changes: 4 additions & 1 deletion Projects/CoreKit/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ let coreKit: Target = .target(
.external(name: "Moya"),
.external(name: "GoogleSignIn"),
.external(name: "SwiftJWT"),
.external(name: "SwiftSoup")
.external(name: "SwiftSoup"),
.external(name: "KakaoSDKCommon"),
.external(name: "KakaoSDKShare"),
.external(name: "KakaoSDKTemplate"),
],
settings: .settings(
base: [
Expand Down
6 changes: 2 additions & 4 deletions Projects/CoreKit/Sources/CoreNetwork/BaseResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@
import Foundation

public struct ErrorResponse: Error, Decodable {
let message: String
let code: String
public let message: String
public let code: String
static let base = ErrorResponse(message: "기본에러입니다", code: "CODE")
}

public struct EmptyResponse: Decodable {}
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,12 @@ extension MoyaProvider {
return try await withCheckedThrowingContinuation { continuation in
self.request(target) { response in
switch response {
case .success:
continuation.resume()
case .success(let result):
guard let errorResponse = try? JSONDecoder().decode(ErrorResponse.self, from: result.data) else {
continuation.resume()
return
}
continuation.resume(throwing: errorResponse)

case .failure(let error):
if let response = error.response?.data {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// CategoryKaKaoShareModel.swift
// CoreKit
//
// Created by 김도형 on 8/22/24.
//

import Foundation

public struct CategoryKaKaoShareModel {
let categoryName: String
let categoryId: Int
let imageURL: String

public init(
categoryName: String,
categoryId: Int,
imageURL: String
) {
self.categoryName = categoryName
self.categoryId = categoryId
self.imageURL = imageURL
}
}
Loading