feat(community): 크리에이터 커뮤니티 게시물 고정 기능을 추가한다
This commit is contained in:
@@ -257,6 +257,7 @@ struct CreatorCommunityAllItemView_Previews: PreviewProvider {
|
||||
isCommentAvailable: false,
|
||||
isAdult: false,
|
||||
isLike: true,
|
||||
isFixed: false,
|
||||
existOrdered: false,
|
||||
likeCount: 10,
|
||||
commentCount: 0,
|
||||
|
||||
@@ -74,6 +74,12 @@ struct CreatorCommunityAllView: View {
|
||||
CreatorCommunityMenuView(
|
||||
isShowing: $viewModel.isShowReportMenu,
|
||||
isShowCreatorMenu: creatorId == UserDefaults.int(forKey: .userId),
|
||||
isFixed: viewModel.isPostFixed,
|
||||
fixedAction: {
|
||||
if creatorId == UserDefaults.int(forKey: .userId) {
|
||||
viewModel.updateCommunityPostFixed()
|
||||
}
|
||||
},
|
||||
modifyAction: {
|
||||
let postId = viewModel.postId
|
||||
AppState.shared
|
||||
@@ -165,6 +171,7 @@ struct CreatorCommunityAllView: View {
|
||||
let item = viewModel.communityPostList[index]
|
||||
CreatorCommunityAllGridItemView(item: item)
|
||||
.id(index)
|
||||
.aspectRatio(1, contentMode: .fit)
|
||||
.onTapGesture {
|
||||
selectedListIndex = index
|
||||
listAnchorIndex = index
|
||||
@@ -173,6 +180,9 @@ struct CreatorCommunityAllView: View {
|
||||
isGridMode = false
|
||||
}
|
||||
}
|
||||
.onLongPressGesture(minimumDuration: 0.5) {
|
||||
viewModel.openReportMenu(item: item)
|
||||
}
|
||||
.onAppear {
|
||||
if index == viewModel.communityPostList.count - 1 {
|
||||
viewModel.getCommunityPostList()
|
||||
@@ -243,8 +253,7 @@ struct CreatorCommunityAllView: View {
|
||||
)
|
||||
},
|
||||
onClickShowReportMenu: {
|
||||
viewModel.postId = item.postId
|
||||
viewModel.isShowReportMenu = true
|
||||
viewModel.openReportMenu(item: item)
|
||||
},
|
||||
onClickPurchaseContent: {
|
||||
viewModel.postId = item.postId
|
||||
@@ -328,20 +337,27 @@ private struct CreatorCommunityAllGridItemView: View {
|
||||
.scaledToFit()
|
||||
.frame(width: 24, height: 24)
|
||||
} else if let imageUrl = item.imageUrl, !imageUrl.isEmpty {
|
||||
AsyncImage(url: URL(string: imageUrl)) { phase in
|
||||
switch phase {
|
||||
case .empty:
|
||||
Color.gray33
|
||||
case .success(let image):
|
||||
image
|
||||
.resizable()
|
||||
.scaledToFill()
|
||||
case .failure:
|
||||
Color(hex: "263238")
|
||||
@unknown default:
|
||||
Color.gray33
|
||||
Rectangle()
|
||||
.fill(Color.clear)
|
||||
.aspectRatio(1, contentMode: .fit)
|
||||
.overlay {
|
||||
AsyncImage(url: URL(string: imageUrl)) { phase in
|
||||
switch phase {
|
||||
case .empty:
|
||||
Color.gray33
|
||||
case .success(let image):
|
||||
image
|
||||
.resizable()
|
||||
.scaledToFill()
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
case .failure:
|
||||
Color(hex: "263238")
|
||||
@unknown default:
|
||||
Color.gray33
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.clipped()
|
||||
} else {
|
||||
Color(hex: "263238")
|
||||
|
||||
@@ -355,6 +371,17 @@ private struct CreatorCommunityAllGridItemView: View {
|
||||
}
|
||||
.aspectRatio(1, contentMode: .fit)
|
||||
.clipped()
|
||||
.overlay(alignment: .topTrailing) {
|
||||
if item.isFixed == true {
|
||||
Image("ic_pin")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 14, height: 14)
|
||||
.padding(8)
|
||||
.shadow(color: .black.opacity(0.45), radius: 2, x: 0, y: 1)
|
||||
.allowsHitTesting(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var isPaidLocked: Bool {
|
||||
|
||||
@@ -21,6 +21,7 @@ class CreatorCommunityAllViewModel: ObservableObject {
|
||||
@Published private(set) var communityPostList = [GetCommunityPostListResponse]()
|
||||
|
||||
@Published var postId = 0
|
||||
@Published var isPostFixed = false
|
||||
@Published var postPrice = 0
|
||||
@Published var postIndex = -1
|
||||
@Published var isShowSecret = false
|
||||
@@ -124,6 +125,12 @@ class CreatorCommunityAllViewModel: ObservableObject {
|
||||
isShowCommentListView = true
|
||||
}
|
||||
|
||||
func openReportMenu(item: GetCommunityPostListResponse) {
|
||||
postId = item.postId
|
||||
isPostFixed = item.isFixed == true
|
||||
isShowReportMenu = true
|
||||
}
|
||||
|
||||
func openCommentListForDeepLink(postId: Int) {
|
||||
guard postId > 0 else {
|
||||
return
|
||||
@@ -289,6 +296,56 @@ class CreatorCommunityAllViewModel: ObservableObject {
|
||||
self.isLoading = false
|
||||
}
|
||||
}
|
||||
|
||||
func updateCommunityPostFixed() {
|
||||
let postId = postId
|
||||
let nextIsFixed = !isPostFixed
|
||||
|
||||
guard postId > 0 else {
|
||||
return
|
||||
}
|
||||
|
||||
isLoading = true
|
||||
|
||||
let request = UpdateCommunityPostFixedRequest(postId: postId, isFixed: nextIsFixed)
|
||||
repository.updateCommunityPostFixed(request: request)
|
||||
.sink { result in
|
||||
switch result {
|
||||
case .finished:
|
||||
DEBUG_LOG("finish")
|
||||
case .failure(let error):
|
||||
ERROR_LOG(error.localizedDescription)
|
||||
}
|
||||
} receiveValue: { [unowned self] response in
|
||||
let responseData = response.data
|
||||
|
||||
do {
|
||||
let jsonDecoder = JSONDecoder()
|
||||
let decoded = try jsonDecoder.decode(ApiResponseWithoutData.self, from: responseData)
|
||||
|
||||
if decoded.success {
|
||||
self.isPostFixed = nextIsFixed
|
||||
DispatchQueue.main.async {
|
||||
self.refreshCommunityPostListKeepingLoadedCount()
|
||||
}
|
||||
} else {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.isShowPopup = true
|
||||
}
|
||||
|
||||
self.isLoading = false
|
||||
}
|
||||
.store(in: &subscription)
|
||||
}
|
||||
|
||||
func purchaseCommunityPost() {
|
||||
let postId = postId
|
||||
@@ -337,6 +394,13 @@ class CreatorCommunityAllViewModel: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
private func refreshCommunityPostListKeepingLoadedCount() {
|
||||
pageSize = max(communityPostList.count, 10)
|
||||
page = 1
|
||||
isLast = false
|
||||
getCommunityPostList()
|
||||
}
|
||||
|
||||
private func shouldShowSecretCommentOption(item: GetCommunityPostListResponse) -> Bool {
|
||||
item.price > 0 && item.existOrdered && item.creatorId != UserDefaults.int(forKey: .userId)
|
||||
}
|
||||
|
||||
@@ -11,7 +11,9 @@ struct CreatorCommunityMenuView: View {
|
||||
@Binding var isShowing: Bool
|
||||
|
||||
let isShowCreatorMenu: Bool
|
||||
let isFixed: Bool
|
||||
|
||||
let fixedAction: () -> Void
|
||||
let modifyAction: () -> Void
|
||||
let deleteAction: () -> Void
|
||||
let reportAction: () -> Void
|
||||
@@ -28,6 +30,23 @@ struct CreatorCommunityMenuView: View {
|
||||
|
||||
VStack(spacing: 13.3) {
|
||||
if isShowCreatorMenu {
|
||||
HStack(spacing: 13.3) {
|
||||
Image(isFixed ? "ic_pin_cancel" : "ic_pin")
|
||||
|
||||
Text(isFixed ? "고정 해제" : "최상단에 고정")
|
||||
.appFont(size: 16.7, weight: .medium)
|
||||
.foregroundColor(.white)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(.vertical, 8)
|
||||
.padding(.horizontal, 26.7)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
isShowing = false
|
||||
fixedAction()
|
||||
}
|
||||
|
||||
HStack(spacing: 13.3) {
|
||||
Image("ic_make_message")
|
||||
|
||||
@@ -90,6 +109,8 @@ struct CreatorCommunityMenuView: View {
|
||||
CreatorCommunityMenuView(
|
||||
isShowing: .constant(true),
|
||||
isShowCreatorMenu: true,
|
||||
isFixed: false,
|
||||
fixedAction: {},
|
||||
modifyAction: {},
|
||||
deleteAction: {},
|
||||
reportAction: {}
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
import Foundation
|
||||
import Moya
|
||||
|
||||
struct UpdateCommunityPostFixedRequest: Encodable {
|
||||
let postId: Int
|
||||
let isFixed: Bool
|
||||
}
|
||||
|
||||
enum CreatorCommunityApi {
|
||||
case createCommunityPost(parameters: [MultipartFormData])
|
||||
case modifyCommunityPost(parameters: [MultipartFormData])
|
||||
@@ -20,6 +25,7 @@ enum CreatorCommunityApi {
|
||||
case modifyComment(request: ModifyCommunityPostCommentRequest)
|
||||
case getLatestPostListFromCreatorsYouFollow
|
||||
case purchaseCommunityPost(postId: Int)
|
||||
case updateCommunityPostFixed(request: UpdateCommunityPostFixedRequest)
|
||||
}
|
||||
|
||||
extension CreatorCommunityApi: TargetType {
|
||||
@@ -52,6 +58,9 @@ extension CreatorCommunityApi: TargetType {
|
||||
|
||||
case .purchaseCommunityPost:
|
||||
return "/creator-community/purchase"
|
||||
|
||||
case .updateCommunityPostFixed:
|
||||
return "/creator-community/fixed"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +72,7 @@ extension CreatorCommunityApi: TargetType {
|
||||
case .getCommunityPostList, .getCommunityPostCommentList, .getCommentReplyList, .getCommunityPostDetail, .getLatestPostListFromCreatorsYouFollow:
|
||||
return .get
|
||||
|
||||
case .modifyComment, .modifyCommunityPost:
|
||||
case .modifyComment, .modifyCommunityPost, .updateCommunityPostFixed:
|
||||
return .put
|
||||
}
|
||||
}
|
||||
@@ -122,6 +131,9 @@ extension CreatorCommunityApi: TargetType {
|
||||
|
||||
case .purchaseCommunityPost(let postId):
|
||||
return .requestJSONEncodable(PurchasePostRequest(postId: postId))
|
||||
|
||||
case .updateCommunityPostFixed(let request):
|
||||
return .requestJSONEncodable(request)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -104,6 +104,7 @@ struct CreatorCommunityItemView_Previews: PreviewProvider {
|
||||
isCommentAvailable: false,
|
||||
isAdult: false,
|
||||
isLike: false,
|
||||
isFixed: false,
|
||||
existOrdered: false,
|
||||
likeCount: 10,
|
||||
commentCount: 0,
|
||||
|
||||
@@ -56,4 +56,8 @@ class CreatorCommunityRepository {
|
||||
func purchaseCommunityPost(postId: Int) -> AnyPublisher<Response, MoyaError> {
|
||||
return api.requestPublisher(.purchaseCommunityPost(postId: postId))
|
||||
}
|
||||
|
||||
func updateCommunityPostFixed(request: UpdateCommunityPostFixedRequest) -> AnyPublisher<Response, MoyaError> {
|
||||
return api.requestPublisher(.updateCommunityPostFixed(request: request))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ struct GetCommunityPostListResponse: Decodable {
|
||||
let isCommentAvailable: Bool
|
||||
let isAdult: Bool
|
||||
let isLike: Bool
|
||||
var isFixed: Bool?
|
||||
let existOrdered: Bool
|
||||
let likeCount: Int
|
||||
let commentCount: Int
|
||||
|
||||
@@ -58,6 +58,7 @@ struct SectionCommunityPostView_Previews: PreviewProvider {
|
||||
isCommentAvailable: false,
|
||||
isAdult: false,
|
||||
isLike: true,
|
||||
isFixed: false,
|
||||
existOrdered: false,
|
||||
likeCount: 10,
|
||||
commentCount: 0,
|
||||
@@ -77,6 +78,7 @@ struct SectionCommunityPostView_Previews: PreviewProvider {
|
||||
isCommentAvailable: false,
|
||||
isAdult: false,
|
||||
isLike: true,
|
||||
isFixed: false,
|
||||
existOrdered: false,
|
||||
likeCount: 20,
|
||||
commentCount: 0,
|
||||
|
||||
Reference in New Issue
Block a user