diff --git a/Projects/App/Sources/MainTab/MainTabPath.swift b/Projects/App/Sources/MainTab/MainTabPath.swift index 63b9c359..68d1e33c 100644 --- a/Projects/App/Sources/MainTab/MainTabPath.swift +++ b/Projects/App/Sources/MainTab/MainTabPath.swift @@ -101,7 +101,13 @@ public extension MainTabFeature { /// - 포킷 `추가` or `수정`이 성공적으로 `완료`되었을 때 case .path(.element(_, action: .포킷추가및수정(.delegate(.settingSuccess)))): state.path.removeLast() - guard let lastPath = state.path.last else { return .none } + guard let lastPath = state.path.last else { + switch state.selectedTab { + case .pokit: return .none + case .recommend: + return .send(.recommend(.delegate(.포킷_추가하기_완료))) + } + } switch lastPath { case .링크공유: state.path.removeLast() diff --git a/Projects/DSKit/Sources/Components/PokitLinkCard.swift b/Projects/DSKit/Sources/Components/PokitLinkCard.swift index ef2a339c..a6bbf4b7 100644 --- a/Projects/DSKit/Sources/Components/PokitLinkCard.swift +++ b/Projects/DSKit/Sources/Components/PokitLinkCard.swift @@ -175,9 +175,6 @@ public struct PokitLinkCard: View { image .resizable() .aspectRatio(contentMode: .fill) - } else if phase.error != nil { - placeholder - .onAppear { fetchMetaData?() } } else { placeholder } @@ -186,6 +183,10 @@ public struct PokitLinkCard: View { .frame(width: 124, height: 94) .clipShape(RoundedRectangle(cornerRadius: 8, style: .continuous)) } + .onCompletion { result in + guard case .failure(_) = result else { return } + fetchMetaData?() + } } private var divider: some View { diff --git a/Projects/Domain/Sources/Base/BaseInterest.swift b/Projects/Domain/Sources/Base/BaseInterest.swift index bc84bc10..9d2c7d94 100644 --- a/Projects/Domain/Sources/Base/BaseInterest.swift +++ b/Projects/Domain/Sources/Base/BaseInterest.swift @@ -9,7 +9,7 @@ import Foundation public struct BaseInterest: Equatable, Identifiable, Hashable { public let id = UUID() - public let code: Code + public let code: String public let description: String public func hash(into hasher: inout Hasher) { @@ -19,29 +19,4 @@ public struct BaseInterest: Equatable, Identifiable, Hashable { public static func ==(lhs: BaseInterest, rhs: BaseInterest) -> Bool { lhs.code == rhs.code } - - public init(code: Code, description: String) { - self.code = code - self.description = description - } -} - -extension BaseInterest { - public enum Code: String { - case `default` = "DEFAULT" - case 스포츠_레저 = "SPORTS" - case 문구_오피스 = "OFFICE" - case 패션 = "FASHION" - case 여행 = "TRAVEL" - case 경제_시사 = "ECONOMY" - case 영화_드라마 = "MOVIE_DRAMA" - case 맛집 = "RESTAURANT" - case 인테리어 = "INTERIOR" - case IT = "IT" - case 디자인 = "DESIGN" - case 자기계발 = "SELF_IMPROVEMENT" - case 유머 = "HUMOR" - case 음악 = "MUSIC" - case 취업정보 = "JOB_INFO" - } } diff --git a/Projects/Domain/Sources/DTO/Base/BaseInterest+Extension.swift b/Projects/Domain/Sources/DTO/Base/BaseInterest+Extension.swift index 93b5ff16..20b4f677 100644 --- a/Projects/Domain/Sources/DTO/Base/BaseInterest+Extension.swift +++ b/Projects/Domain/Sources/DTO/Base/BaseInterest+Extension.swift @@ -12,7 +12,7 @@ import CoreKit public extension InterestResponse { func toDomian() -> BaseInterest { return BaseInterest( - code: BaseInterest.Code(rawValue: self.code) ?? .default, + code: self.code, description: self.description ) } diff --git a/Projects/Feature/FeatureContentCard/Sources/ContentCard/ContentCardFeature.swift b/Projects/Feature/FeatureContentCard/Sources/ContentCard/ContentCardFeature.swift index 8b579616..d5bfae8c 100644 --- a/Projects/Feature/FeatureContentCard/Sources/ContentCard/ContentCardFeature.swift +++ b/Projects/Feature/FeatureContentCard/Sources/ContentCard/ContentCardFeature.swift @@ -148,9 +148,8 @@ private extension ContentCardFeature { return .none } return .run { send in - let imageURL = try await swiftSoupClient.parseOGImageURL(url) - guard let imageURL else { return } - await send(.inner(.메타데이터_조회_수행_반영(imageURL))) + let imageURL = try? await swiftSoupClient.parseOGImageURL(url) + await send(.inner(.메타데이터_조회_수행_반영(imageURL ?? Constants.기본_썸네일_주소.absoluteString))) } case .즐겨찾기_API: return .run { [id = state.content.id] send in diff --git a/Projects/Feature/FeatureContentSetting/Sources/ContentSetting/ContentSettingFeature.swift b/Projects/Feature/FeatureContentSetting/Sources/ContentSetting/ContentSettingFeature.swift index d80271bc..a10909a1 100644 --- a/Projects/Feature/FeatureContentSetting/Sources/ContentSetting/ContentSettingFeature.swift +++ b/Projects/Feature/FeatureContentSetting/Sources/ContentSetting/ContentSettingFeature.swift @@ -253,9 +253,9 @@ private extension ContentSettingFeature { return .none case .메타데이터_조회_수행(url: let url): return .run { send in - async let title = swiftSoup.parseOGTitle(url) - async let imageURL = swiftSoup.parseOGImageURL(url) - try await send( + async let title = try? swiftSoup.parseOGTitle(url) + async let imageURL = try? swiftSoup.parseOGImageURL(url) + await send( .inner(.메타데이텨_조회_반영(title: title, imageURL: imageURL)), animation: .pokitDissolve ) diff --git a/Projects/Feature/FeatureRecommend/Sources/Recommend/RecommendFeature.swift b/Projects/Feature/FeatureRecommend/Sources/Recommend/RecommendFeature.swift index a84aab5f..9f3376db 100644 --- a/Projects/Feature/FeatureRecommend/Sources/Recommend/RecommendFeature.swift +++ b/Projects/Feature/FeatureRecommend/Sources/Recommend/RecommendFeature.swift @@ -120,6 +120,7 @@ public struct RecommendFeature { case 알림_버튼_눌렀을때 case 컨텐츠_신고_API_반영 case 포킷_추가하기_버튼_눌렀을때 + case 포킷_추가하기_완료 } } @@ -259,7 +260,7 @@ private extension RecommendFeature { return .none case let .관심사_조회_API_반영(interests): state.domain.interests = interests.filter({ interest in - interest.code != .default + interest.code != "default" }) state.showKeywordSheet = true return .none @@ -371,7 +372,16 @@ private extension RecommendFeature { /// - Delegate Effect func handleDelegateAction(_ action: Action.DelegateAction, state: inout State) -> Effect { - return .none + switch action { + case .포킷_추가하기_완료: + guard state.addContent != nil else { return .none } + state.showSelectSheet = true + return shared(.async(.카테고리_목록_조회_API), state: &state) + case .저장하기_완료: + state.addContent = nil + return .none + default: return .none + } } /// - Shared Effect diff --git a/Projects/Feature/FeatureRecommend/Sources/Recommend/RecommendKeywordBottomSheet.swift b/Projects/Feature/FeatureRecommend/Sources/Recommend/RecommendKeywordBottomSheet.swift index b0e0e682..3963338c 100644 --- a/Projects/Feature/FeatureRecommend/Sources/Recommend/RecommendKeywordBottomSheet.swift +++ b/Projects/Feature/FeatureRecommend/Sources/Recommend/RecommendKeywordBottomSheet.swift @@ -16,6 +16,8 @@ struct RecommendKeywordBottomSheet: View { private var selectedInterests: Set @State private var height: CGFloat = 0 + @State + private var isTouchActive: Bool = false private let interests: [BaseInterest] private let onSave: ((Set) -> Void)? @@ -70,6 +72,7 @@ struct RecommendKeywordBottomSheet: View { } .presentationDetents([.height(height)]) .ignoresSafeArea(edges: [.bottom, .top]) + .onDisappear { onSave?(selectedInterests) } } func onSave(_ perform: @escaping (Set) -> Void) -> Self { @@ -112,15 +115,24 @@ extension RecommendKeywordBottomSheet { : isMaxCount ? .disable : .default(.primary), size: .medium ) { + guard !isTouchActive else { return } + if isSelected { selectedInterests.remove(field) } else { - selectedInterests.insert(field) + if selectedInterests.count < 3 { + selectedInterests.insert(field) + } } } } .animation(.pokitDissolve, value: selectedInterests) } + .simultaneousGesture( + DragGesture(minimumDistance: 0) + .onChanged { _ in isTouchActive = true } + .onEnded { _ in isTouchActive = false } + ) } } diff --git a/Projects/Util/Sources/Constants.swift b/Projects/Util/Sources/Constants.swift index 0c7521fe..4c12153f 100644 --- a/Projects/Util/Sources/Constants.swift +++ b/Projects/Util/Sources/Constants.swift @@ -23,7 +23,7 @@ public enum Constants { public static let 개인정보_처리방침_주소: URL = URL(string: "https://www.notion.so/de3468b3be1744538c22a333ae1d0ec8")! public static let 마케팅_정보_수신_주소: URL = URL(string: "https://www.notion.so/bb6d0d6569204d5e9a7b67e5825f9d10")! public static let 고객문의_주소: URL = URL(string: "https://www.instagram.com/pokit.official/")! - public static let 기본_썸네일_주소: URL = URL(string: "https://pokit-storage.s3.ap-northeast-2.amazonaws.com/logo/pokit.png")! + public static let 기본_썸네일_주소: URL = URL(string: "https://pokit-s3.s3.ap-northeast-2.amazonaws.com/logo/pokit.png")! public static let 포킷_최대_갯수_문구: String = "최대 30개의 포킷을 생성할 수 있습니다.\n포킷을 삭제한 뒤에 추가해주세요." public static let 복사한_링크_저장하기_문구: String = "복사한 링크 저장하기"