feat: 커뮤니티 댓글

- 유료 커뮤니티 구매시 비밀 댓글 쓰기 기능 추가
This commit is contained in:
Yu Sung
2025-06-13 19:18:37 +09:00
parent 522a177063
commit 24c97dbe51
13 changed files with 90 additions and 23 deletions

View File

@@ -9,4 +9,5 @@ struct CreateCommunityPostCommentRequest: Encodable {
let comment: String
let postId: Int
let parentId: Int?
let isSecret: Bool
}

View File

@@ -45,10 +45,22 @@ struct CreatorCommunityCommentItemView: View {
}
VStack(alignment: .leading, spacing: 0) {
HStack(spacing: 6.7) {
Text(commentItem.nickname)
.font(.custom(Font.medium.rawValue, size: 12))
.foregroundColor(Color.gray90)
if commentItem.isSecret {
Text("비밀댓글")
.font(.custom(Font.medium.rawValue, size: 11))
.foregroundColor(Color.grayee)
.padding(.horizontal, 4)
.padding(.vertical, 2)
.background(Color.button.opacity(0.2))
.cornerRadius(3.3)
}
}
Text(commentItem.date)
.font(.custom(Font.medium.rawValue, size: 10.3))
.foregroundColor(Color.gray52)

View File

@@ -14,6 +14,7 @@ struct CreatorCommunityCommentListView: View {
let creatorId: Int
let postId: Int
let isShowSecret: Bool
@State private var commentId: Int = 0
@State private var isShowDeletePopup: Bool = false
@@ -53,6 +54,28 @@ struct CreatorCommunityCommentListView: View {
.padding(.bottom, 13.3)
.padding(.horizontal, 13.3)
if isShowSecret {
HStack(spacing: 8) {
Spacer()
Image(viewModel.isSecret ? "btn_square_select_checked" : "btn_square_select_normal")
.resizable()
.frame(width: 20, height: 20)
.onTapGesture {
viewModel.isSecret.toggle()
}
Text("비밀댓글")
.font(.custom(Font.medium.rawValue, size: 12))
.foregroundColor(viewModel.isSecret ? Color.button : Color.grayee)
.onTapGesture {
viewModel.isSecret.toggle()
}
}
.padding(.bottom, 13.3)
.padding(.horizontal, 13.3)
}
HStack(spacing: 8) {
KFImage(URL(string: UserDefaults.string(forKey: .profileImage)))
.cancelOnDisappear(true)
@@ -193,7 +216,8 @@ struct CreatorCommunityCommentListView_Previews: PreviewProvider {
CreatorCommunityCommentListView(
isPresented: .constant(true),
creatorId: 0,
postId: 0
postId: 0,
isShowSecret: true
)
}
}

View File

@@ -17,6 +17,7 @@ final class CreatorCommunityCommentListViewModel: ObservableObject {
@Published var isShowPopup = false
@Published var comment = ""
@Published var isSecret = false
@Published var totalCommentCount = 0
@Published var commentList = [GetCommunityPostCommentListItem]()
@@ -79,7 +80,7 @@ final class CreatorCommunityCommentListViewModel: ObservableObject {
if !isLoading {
isLoading = true
repository.createCommunityPostComment(comment: comment, postId: postId, parentId: parentId)
repository.createCommunityPostComment(comment: comment, postId: postId, parentId: parentId, isSecret: isSecret)
.sink { result in
switch result {
case .finished:
@@ -100,6 +101,7 @@ final class CreatorCommunityCommentListViewModel: ObservableObject {
self.comment = ""
self.page = 1
self.isLast = false
self.isSecret = false
self.getCommentList()
}
} else {

View File

@@ -192,6 +192,7 @@ struct CreatorCommunityCommentReplyView_Previews: PreviewProvider {
nickname: "댓글",
profileUrl: "",
comment: "부모 댓글입니다.",
isSecret: false,
date: "1시간전",
replyCount: 1
)

View File

@@ -81,7 +81,7 @@ final class CreatorCommunityCommentReplyViewModel: ObservableObject {
if !isLoading {
isLoading = true
repository.createCommunityPostComment(comment: comment, postId: postId, parentId: parentId)
repository.createCommunityPostComment(comment: comment, postId: postId, parentId: parentId, isSecret: false)
.sink { result in
switch result {
case .finished:

View File

@@ -11,10 +11,12 @@ import Kingfisher
struct CreatorCommunityCommentView: View {
let commentCount: Int
let commentItem: GetCommunityPostCommentListItem?
let isShowSecret: Bool
let onClickWriteComment: (String) -> Void
let onClickWriteComment: (String, Bool) -> Void
@State private var comment = ""
@State private var isSecret = false
var body: some View {
VStack(alignment: .leading, spacing: 11) {
@@ -28,6 +30,22 @@ struct CreatorCommunityCommentView: View {
.foregroundColor(Color(hex: "909090"))
Spacer()
if isShowSecret && commentItem == nil {
Image(isSecret ? "btn_square_select_checked" : "btn_square_select_normal")
.resizable()
.frame(width: 20, height: 20)
.onTapGesture {
isSecret.toggle()
}
Text("비밀댓글")
.font(.custom(Font.medium.rawValue, size: 12))
.foregroundColor(isSecret ? Color.button : Color.grayee)
.onTapGesture {
isSecret.toggle()
}
}
}
HStack(spacing: 8) {
@@ -80,7 +98,7 @@ struct CreatorCommunityCommentView: View {
.padding(6.7)
.onTapGesture {
hideKeyboard()
onClickWriteComment(comment)
onClickWriteComment(comment, isSecret)
comment = ""
}
}
@@ -110,10 +128,12 @@ struct CreatorCommunityCommentView_Previews: PreviewProvider {
nickname: "닉네임",
profileUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
comment: "댓글 테스트",
isSecret: false,
date: "1시간전",
replyCount: 0
),
onClickWriteComment: { _ in }
isShowSecret: true,
onClickWriteComment: { _, _ in }
)
}
}

View File

@@ -16,6 +16,7 @@ struct GetCommunityPostCommentListItem: Decodable {
let nickname: String
let profileUrl: String
let comment: String
let isSecret: Bool
let date: String
let replyCount: Int
}

View File

@@ -13,7 +13,7 @@ struct CreatorCommunityAllItemView: View {
let item: GetCommunityPostListResponse
let onClickLike: () -> Void
let onClickComment: () -> Void
let onClickWriteComment: (String) -> Void
let onClickWriteComment: (String, Bool) -> Void
let onClickShowReportMenu: () -> Void
let onClickPurchaseContent: () -> Void
@@ -28,7 +28,7 @@ struct CreatorCommunityAllItemView: View {
item: GetCommunityPostListResponse,
onClickLike: @escaping () -> Void,
onClickComment: @escaping () -> Void,
onClickWriteComment: @escaping (String) -> Void,
onClickWriteComment: @escaping (String, Bool) -> Void,
onClickShowReportMenu: @escaping () -> Void,
onClickPurchaseContent: @escaping () -> Void
) {
@@ -137,6 +137,7 @@ struct CreatorCommunityAllItemView: View {
CreatorCommunityCommentView(
commentCount: item.commentCount,
commentItem: item.firstComment,
isShowSecret: item.existOrdered,
onClickWriteComment: onClickWriteComment
)
.onTapGesture {
@@ -189,7 +190,7 @@ struct CreatorCommunityAllItemView_Previews: PreviewProvider {
),
onClickLike: {},
onClickComment: {},
onClickWriteComment: { _ in },
onClickWriteComment: { _, _ in },
onClickShowReportMenu: {},
onClickPurchaseContent: {}
)

View File

@@ -31,12 +31,14 @@ struct CreatorCommunityAllView: View {
},
onClickComment: {
viewModel.postId = item.postId
viewModel.isShowSecret = item.existOrdered
viewModel.isShowCommentListView = true
},
onClickWriteComment: { comment in
onClickWriteComment: { comment, isSecret in
viewModel.createCommunityPostComment(
comment: comment,
postId: item.postId
postId: item.postId,
isSecret: isSecret
)
},
onClickShowReportMenu: {
@@ -65,7 +67,8 @@ struct CreatorCommunityAllView: View {
CreatorCommunityCommentListView(
isPresented: $viewModel.isShowCommentListView,
creatorId: creatorId,
postId: viewModel.postId
postId: viewModel.postId,
isShowSecret: viewModel.isShowSecret
)
}
)

View File

@@ -23,11 +23,13 @@ class CreatorCommunityAllViewModel: ObservableObject {
@Published var postId = 0
@Published var postPrice = 0
@Published var postIndex = -1
@Published var isShowSecret = false
@Published var isShowCommentListView = false {
didSet {
if !isShowCommentListView {
postId = 0
isShowSecret = false
}
}
}
@@ -130,10 +132,10 @@ class CreatorCommunityAllViewModel: ObservableObject {
.store(in: &subscription)
}
func createCommunityPostComment(comment: String, postId: Int, parentId: Int? = nil) {
func createCommunityPostComment(comment: String, postId: Int, parentId: Int? = nil, isSecret: Bool = false) {
isLoading = true
repository.createCommunityPostComment(comment: comment, postId: postId, parentId: parentId)
repository.createCommunityPostComment(comment: comment, postId: postId, parentId: parentId, isSecret: isSecret)
.sink { result in
switch result {
case .finished:

View File

@@ -14,7 +14,7 @@ enum CreatorCommunityApi {
case getCommunityPostList(creatorId: Int, page: Int, size: Int)
case getCommunityPostDetail(postId: Int)
case communityPostLike(postId: Int)
case createCommunityPostComment(comment: String, postId: Int, parentId: Int?)
case createCommunityPostComment(comment: String, postId: Int, parentId: Int?, isSecret: Bool)
case getCommunityPostCommentList(postId: Int, page: Int, size: Int)
case getCommentReplyList(commentId: Int, page: Int, size: Int)
case modifyComment(request: ModifyCommunityPostCommentRequest)
@@ -89,8 +89,8 @@ extension CreatorCommunityApi: TargetType {
let request = PostCommunityPostLikeRequest(postId: postId)
return .requestJSONEncodable(request)
case .createCommunityPostComment(let comment, let postId, let parentId):
let request = CreateCommunityPostCommentRequest(comment: comment, postId: postId, parentId: parentId)
case .createCommunityPostComment(let comment, let postId, let parentId, let isSecret):
let request = CreateCommunityPostCommentRequest(comment: comment, postId: postId, parentId: parentId, isSecret: isSecret)
return .requestJSONEncodable(request)
case .getCommunityPostCommentList(_, let page, let size):

View File

@@ -33,8 +33,8 @@ class CreatorCommunityRepository {
return api.requestPublisher(.communityPostLike(postId: postId))
}
func createCommunityPostComment(comment: String, postId: Int, parentId: Int?) -> AnyPublisher<Response, MoyaError> {
return api.requestPublisher(.createCommunityPostComment(comment: comment, postId: postId, parentId: parentId))
func createCommunityPostComment(comment: String, postId: Int, parentId: Int?, isSecret: Bool) -> AnyPublisher<Response, MoyaError> {
return api.requestPublisher(.createCommunityPostComment(comment: comment, postId: postId, parentId: parentId, isSecret: isSecret))
}
func getCommunityPostCommentList(postId: Int, page: Int, size: Int) -> AnyPublisher<Response, MoyaError> {