-
Notifications
You must be signed in to change notification settings - Fork 0
[Feat] 프로필 중간 구현 #190
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
[Feat] 프로필 중간 구현 #190
Changes from all commits
f08ed09
cb26461
f6233d4
89af4e8
c32b489
bf0c54e
1c83c17
7028c72
dbbfdaa
43aed0a
3e26aea
b96cfde
ae4f9eb
46dd12f
772678b
e104cc7
53c19da
9872ff0
b726c69
9670616
0c2f361
f099d68
a5fec53
f6cc929
cca5a81
c981c62
b7ff92c
f51e193
70646be
4d1c7af
574b658
55b691a
3b87eaf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| // | ||
| // FetchAccountInfoUseCase.swift | ||
| // Wable-iOS | ||
| // | ||
| // Created by 김진웅 on 5/14/25. | ||
| // | ||
|
|
||
| import Combine | ||
| import Foundation | ||
|
|
||
| protocol FetchAccountInfoUseCase { | ||
| func execute() async throws -> AccountInfo | ||
| } | ||
|
|
||
| final class FetchAccountInfoUseCaseImpl: FetchAccountInfoUseCase { | ||
| private let repository: ProfileRepository | ||
|
|
||
| init(repository: ProfileRepository) { | ||
| self.repository = repository | ||
| } | ||
|
|
||
| func execute() async throws -> AccountInfo { | ||
| return try await repository.fetchAccountInfo() | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| // | ||
| // FetchUserCommentListUseCase.swift | ||
| // Wable-iOS | ||
| // | ||
| // Created by 김진웅 on 5/14/25. | ||
| // | ||
|
|
||
| import Combine | ||
| import Foundation | ||
|
|
||
| protocol FetchUserCommentListUseCase { | ||
| func execute(for userID: Int, last commentID: Int) -> AnyPublisher<[UserComment], WableError> | ||
| } | ||
|
|
||
| final class FetchUserCommentListUseCaseImpl: FetchUserCommentListUseCase { | ||
| private let repository: CommentRepository | ||
|
|
||
| init(repository: CommentRepository) { | ||
| self.repository = repository | ||
| } | ||
|
|
||
| func execute(for userID: Int, last commentID: Int) -> AnyPublisher<[UserComment], WableError> { | ||
| guard userID > .zero else { | ||
| return .fail(.notFoundMember) | ||
| } | ||
|
|
||
| return repository.fetchUserCommentList(memberID: userID, cursor: commentID) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| // | ||
| // FetchUserContentUseCase.swift | ||
| // Wable-iOS | ||
| // | ||
| // Created by 김진웅 on 5/14/25. | ||
| // | ||
|
|
||
| import Combine | ||
| import Foundation | ||
|
|
||
| protocol FetchUserContentListUseCase { | ||
| func execute(for userID: Int, last contentID: Int) -> AnyPublisher<[UserContent], WableError> | ||
| } | ||
|
|
||
| final class FetchUserContentUseCaseImpl: FetchUserContentListUseCase { | ||
| private let repository: ContentRepository | ||
|
|
||
| init(repository: ContentRepository) { | ||
| self.repository = repository | ||
| } | ||
|
|
||
| func execute(for userID: Int, last contentID: Int) -> AnyPublisher<[UserContent], WableError> { | ||
| if userID < .zero { | ||
| return .fail(.notFoundMember) | ||
| } | ||
|
|
||
| return repository.fetchUserContentList(memberID: userID, cursor: contentID) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| // | ||
| // FetchUserProfileUseCase.swift | ||
| // Wable-iOS | ||
| // | ||
| // Created by 김진웅 on 5/14/25. | ||
| // | ||
|
|
||
| import Combine | ||
| import Foundation | ||
|
|
||
| protocol FetchUserProfileUseCase { | ||
| func execute(userID: Int) -> AnyPublisher<UserProfile?, WableError> | ||
| } | ||
|
|
||
| final class FetchUserProfileUseCaseImpl: FetchUserProfileUseCase { | ||
| private let repository: ProfileRepository | ||
|
|
||
| init(repository: ProfileRepository) { | ||
| self.repository = repository | ||
| } | ||
|
|
||
| func execute(userID: Int) -> AnyPublisher<UserProfile?, WableError> { | ||
| guard userID > .zero else { | ||
| return .fail(.notFoundMember) | ||
| } | ||
|
|
||
| return repository.fetchUserProfile(memberID: userID) | ||
| .map { $0 } | ||
| .eraseToAnyPublisher() | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| // | ||
| // RemoveUserSessionUseCase.swift | ||
| // Wable-iOS | ||
| // | ||
| // Created by 김진웅 on 5/14/25. | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| protocol RemoveUserSessionUseCase { | ||
| func removeUserSession() | ||
| } | ||
|
|
||
| final class RemoveUserSessionUseCaseImpl: RemoveUserSessionUseCase { | ||
| private let repository: UserSessionRepository | ||
|
|
||
| init(repository: UserSessionRepository) { | ||
| self.repository = repository | ||
| } | ||
|
|
||
| func removeUserSession() { | ||
| guard let userID = repository.fetchActiveUserID() else { | ||
| WableLogger.log("유저 아이디를 찾을 수 없음.", for: .debug) | ||
| return | ||
| } | ||
|
|
||
| repository.removeUserSession(forUserID: userID) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,27 @@ | ||||||||||||||
| // | ||||||||||||||
| // WithdrawUseCase.swift | ||||||||||||||
| // Wable-iOS | ||||||||||||||
| // | ||||||||||||||
| // Created by 김진웅 on 5/14/25. | ||||||||||||||
| // | ||||||||||||||
|
|
||||||||||||||
| import Combine | ||||||||||||||
| import Foundation | ||||||||||||||
|
|
||||||||||||||
| protocol WithdrawUseCase { | ||||||||||||||
| func execute(reasons: [WithdrawalReason]) -> AnyPublisher<Bool, WableError> | ||||||||||||||
| } | ||||||||||||||
|
Comment on lines
+11
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider using async/await for consistency. This use case uses Combine publishers while protocol WithdrawUseCase {
- func execute(reasons: [WithdrawalReason]) -> AnyPublisher<Bool, WableError>
+ func execute(reasons: [WithdrawalReason]) async throws -> Bool
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||
|
|
||||||||||||||
| final class WithdrawUseCaseImpl: WithdrawUseCase { | ||||||||||||||
| private let repository: AccountRepository | ||||||||||||||
|
|
||||||||||||||
| init(repository: AccountRepository) { | ||||||||||||||
| self.repository = repository | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| func execute(reasons: [WithdrawalReason]) -> AnyPublisher<Bool, WableError> { | ||||||||||||||
| return repository.deleteAccount(reason: reasons.map { $0.rawValue }) | ||||||||||||||
| .map { _ in true } | ||||||||||||||
| .eraseToAnyPublisher() | ||||||||||||||
| } | ||||||||||||||
|
Comment on lines
+22
to
+26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Implement async method consistently with PR objectives. The implementation should follow the async/await pattern for consistency with other use cases and to align with the PR's focus on improving code readability. -func execute(reasons: [WithdrawalReason]) -> AnyPublisher<Bool, WableError> {
- return repository.deleteAccount(reason: reasons.map { $0.rawValue })
- .map { _ in true }
- .eraseToAnyPublisher()
+async func execute(reasons: [WithdrawalReason]) async throws -> Bool {
+ try await repository.deleteAccount(reason: reasons.map { $0.rawValue })
+ return true
}Note: This assumes that the
🤖 Prompt for AI Agents |
||||||||||||||
| } | ||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -70,6 +70,33 @@ final class APIProvider<Target: BaseTargetType>: MoyaProvider<Target> { | |
| .eraseToAnyPublisher() | ||
| } | ||
|
|
||
| func request<D: Decodable>( | ||
| _ target: Target, | ||
| for type: D.Type | ||
| ) async throws -> D { | ||
| let response = try await withCheckedThrowingContinuation { continuation in | ||
| self.request(target) { result in | ||
| switch result { | ||
| case .success(let moyaResponse): | ||
| continuation.resume(returning: moyaResponse) | ||
| case .failure(let error): | ||
| continuation.resume(throwing: NetworkError.unknown(error)) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| do { | ||
| let baseResponse = try jsonDecoder.decode(BaseResponse<D>.self, from: response.data) | ||
| return try validateResponse(baseResponse) | ||
| } catch let decodingError as DecodingError { | ||
| throw NetworkError.decodedError(decodingError) | ||
| } catch let error as NetworkError { | ||
| throw error | ||
| } catch { | ||
| throw NetworkError.unknown(error) | ||
| } | ||
| } | ||
|
Comment on lines
+73
to
+98
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
|
|
||
| private func validateResponse<D>(_ baseResponse: BaseResponse<D>) throws -> D { | ||
| guard baseResponse.success else { | ||
| throw convertNetworkError(statusCode: baseResponse.status, message: baseResponse.message) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,7 +25,7 @@ extension CommentTargetType: BaseTargetType { | |
| var endPoint: String? { | ||
| switch self { | ||
| case .fetchUserCommentList(memberID: let memberID, _): | ||
| return "/v3/member/\(memberID)/member-comments" | ||
| return "/v3/member/\(memberID)/comments" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ㅎㅎ ... 고생하셨씁니다 |
||
| case .fetchContentCommentList(contentID: let contentID, _): | ||
| return "/v3/content/\(contentID)/comments" | ||
| case .deleteComment(commentID: let commentID): | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
❓ Verification inconclusive
Consider using async/await instead of Combine.
According to the PR objectives, this PR aims to introduce async/await syntax. Consider updating this implementation to use async/await instead of Combine publishers for better code readability and alignment with the PR goals.
protocol FetchUserCommentListUseCase { - func execute(for userID: Int, last commentID: Int) -> AnyPublisher<[UserComment], WableError> + func execute(for userID: Int, last commentID: Int) async throws -> [UserComment] } final class FetchUserCommentListUseCaseImpl: FetchUserCommentListUseCase { private let repository: CommentRepository init(repository: CommentRepository) { self.repository = repository } - func execute(for userID: Int, last commentID: Int) -> AnyPublisher<[UserComment], WableError> { + func execute(for userID: Int, last commentID: Int) async throws -> [UserComment] { guard userID > .zero else { - return .fail(.notFoundMember) + throw WableError.notFoundMember } - return repository.fetchUserCommentList(memberID: userID, cursor: commentID) + return try await repository.fetchUserCommentList(memberID: userID, cursor: commentID) } }🏁 Script executed:
Length of output: 47
Adopt async/await across use-case and repository
To align with this PR’s async/await goal, update both the use-case and its repository dependency:
• In FetchUserCommentListUseCase (protocol + implementation), change
to
and throw on
userID <= 0, then call• In CommentRepository (and its conforming types), change
to
and update all implementations accordingly.
🤖 Prompt for AI Agents