커뮤니티 유료 게시글 조회, 구매 기능 추가
This commit is contained in:
parent
0a96509b35
commit
3ae5ea776c
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ic_lock_bb.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
|
@ -0,0 +1,92 @@
|
|||
//
|
||||
// CommunityPostPurchaseDialog.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 5/24/24.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct CommunityPostPurchaseDialog: View {
|
||||
|
||||
@Binding var isShowing: Bool
|
||||
|
||||
let can: Int
|
||||
let confirmAction: () -> Void
|
||||
|
||||
var body: some View {
|
||||
GeometryReader { geo in
|
||||
ZStack {
|
||||
Color.black
|
||||
.opacity(0.5)
|
||||
.frame(width: geo.size.width, height: geo.size.height)
|
||||
|
||||
VStack(spacing: 0) {
|
||||
Text("게시글 보기")
|
||||
.font(.custom(Font.bold.rawValue, size: 18.3))
|
||||
.foregroundColor(Color.graybb)
|
||||
.padding(.top, 40)
|
||||
|
||||
Text("게시글을\n확인하시겠습니까?")
|
||||
.font(.custom(Font.medium.rawValue, size: 15))
|
||||
.foregroundColor(Color.graybb)
|
||||
.multilineTextAlignment(.center)
|
||||
.padding(.top, 12)
|
||||
.padding(.horizontal, 13.3)
|
||||
|
||||
HStack(spacing: 13.3) {
|
||||
Text("취소")
|
||||
.font(.custom(Font.bold.rawValue, size: 15.3))
|
||||
.foregroundColor(Color.button)
|
||||
.padding(.vertical, 16)
|
||||
.frame(width: (geo.size.width - 66.7) / 3)
|
||||
.background(Color.bg)
|
||||
.cornerRadius(8)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 8)
|
||||
.stroke(Color.button, lineWidth: 1)
|
||||
)
|
||||
.onTapGesture {
|
||||
isShowing = false
|
||||
}
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Text("\(can)")
|
||||
.font(.custom(Font.bold.rawValue, size: 15.3))
|
||||
.foregroundColor(Color.white)
|
||||
|
||||
Image("ic_can")
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20)
|
||||
|
||||
Text("으로 보기")
|
||||
.font(.custom(Font.bold.rawValue, size: 15.3))
|
||||
.foregroundColor(Color.white)
|
||||
}
|
||||
.padding(.vertical, 16)
|
||||
.frame(width: (geo.size.width - 66.7) * 2 / 3)
|
||||
.background(Color.button)
|
||||
.cornerRadius(8)
|
||||
.onTapGesture {
|
||||
confirmAction()
|
||||
isShowing = false
|
||||
}
|
||||
}
|
||||
.padding(.top, 26.7)
|
||||
.padding(.bottom, 16.7)
|
||||
}
|
||||
.frame(width: geo.size.width - 26.7, alignment: .center)
|
||||
.background(Color.gray22)
|
||||
.cornerRadius(10)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
CommunityPostPurchaseDialog(
|
||||
isShowing: .constant(true),
|
||||
can: 10,
|
||||
confirmAction: {}
|
||||
)
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// CreatorCommunityAllItemLockView.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 5/24/24.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct CreatorCommunityAllItemLockView: View {
|
||||
|
||||
let price: Int
|
||||
let onClickPurchaseContent: () -> Void
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 26.7) {
|
||||
Image("ic_lock_bb")
|
||||
|
||||
Text("\(price)캔으로 게시글 보기")
|
||||
.font(.custom(Font.bold.rawValue, size: 12))
|
||||
.foregroundColor(Color.button)
|
||||
.padding(.horizontal, 21)
|
||||
.padding(.vertical, 11)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 26.7)
|
||||
.stroke(Color.button, lineWidth: 1)
|
||||
)
|
||||
.onTapGesture { onClickPurchaseContent() }
|
||||
}
|
||||
.frame(width: screenSize().width - 42, height: screenSize().width - 42)
|
||||
.background(Color.gray33)
|
||||
.cornerRadius(5.3)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
CreatorCommunityAllItemLockView(price: 100) {
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ struct CreatorCommunityAllItemView: View {
|
|||
let onClickComment: () -> Void
|
||||
let onClickWriteComment: (String) -> Void
|
||||
let onClickShowReportMenu: () -> Void
|
||||
let onClickPurchaseContent: () -> Void
|
||||
|
||||
@State var isLike = false
|
||||
@State var likeCount = 0
|
||||
|
@ -25,13 +26,15 @@ struct CreatorCommunityAllItemView: View {
|
|||
onClickLike: @escaping () -> Void,
|
||||
onClickComment: @escaping () -> Void,
|
||||
onClickWriteComment: @escaping (String) -> Void,
|
||||
onClickShowReportMenu: @escaping () -> Void
|
||||
onClickShowReportMenu: @escaping () -> Void,
|
||||
onClickPurchaseContent: @escaping () -> Void
|
||||
) {
|
||||
self.item = item
|
||||
self.onClickLike = onClickLike
|
||||
self.onClickComment = onClickComment
|
||||
self.onClickWriteComment = onClickWriteComment
|
||||
self.onClickShowReportMenu = onClickShowReportMenu
|
||||
self.onClickPurchaseContent = onClickPurchaseContent
|
||||
|
||||
self._isLike = State(initialValue: item.isLike)
|
||||
self._likeCount = State(initialValue: item.likeCount)
|
||||
|
@ -58,11 +61,14 @@ struct CreatorCommunityAllItemView: View {
|
|||
|
||||
Spacer()
|
||||
|
||||
if item.price <= 0 || item.existOrdered {
|
||||
Image("ic_seemore_vertical")
|
||||
.padding(.trailing, 8.3)
|
||||
.onTapGesture { onClickShowReportMenu() }
|
||||
}
|
||||
}
|
||||
|
||||
if item.price <= 0 || item.existOrdered {
|
||||
DetectableTextView(text: item.content, textSize: 13.3, font: Font.medium.rawValue)
|
||||
.frame(
|
||||
width: screenSize().width - 16,
|
||||
|
@ -119,6 +125,11 @@ struct CreatorCommunityAllItemView: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CreatorCommunityAllItemLockView(
|
||||
price: item.price,
|
||||
onClickPurchaseContent: onClickPurchaseContent)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 8)
|
||||
.padding(.vertical, 11)
|
||||
|
@ -144,10 +155,12 @@ struct CreatorCommunityAllItemView_Previews: PreviewProvider {
|
|||
creatorProfileUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
|
||||
imageUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
|
||||
content: "너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!",
|
||||
price: 10,
|
||||
date: "3일전",
|
||||
isCommentAvailable: false,
|
||||
isAdult: false,
|
||||
isLike: true,
|
||||
existOrdered: false,
|
||||
likeCount: 10,
|
||||
commentCount: 0,
|
||||
firstComment: nil
|
||||
|
@ -155,7 +168,8 @@ struct CreatorCommunityAllItemView_Previews: PreviewProvider {
|
|||
onClickLike: {},
|
||||
onClickComment: {},
|
||||
onClickWriteComment: { _ in },
|
||||
onClickShowReportMenu: {}
|
||||
onClickShowReportMenu: {},
|
||||
onClickPurchaseContent: {}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,12 @@ struct CreatorCommunityAllView: View {
|
|||
onClickShowReportMenu: {
|
||||
viewModel.postId = item.postId
|
||||
viewModel.isShowReportMenu = true
|
||||
},
|
||||
onClickPurchaseContent: {
|
||||
viewModel.postId = item.postId
|
||||
viewModel.postPrice = item.price
|
||||
viewModel.postIndex = index
|
||||
viewModel.isShowPostPurchaseView = true
|
||||
}
|
||||
)
|
||||
.onAppear {
|
||||
|
@ -121,6 +127,15 @@ struct CreatorCommunityAllView: View {
|
|||
}
|
||||
)
|
||||
}
|
||||
|
||||
if viewModel.isShowPostPurchaseView {
|
||||
CommunityPostPurchaseDialog(
|
||||
isShowing: $viewModel.isShowPostPurchaseView,
|
||||
can: viewModel.postPrice
|
||||
) {
|
||||
viewModel.purchaseCommunityPost()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.popup(isPresented: $viewModel.isShowPopup, type: .toast, position: .top, autohideIn: 2) {
|
||||
|
|
|
@ -21,6 +21,8 @@ class CreatorCommunityAllViewModel: ObservableObject {
|
|||
@Published private(set) var communityPostList = [GetCommunityPostListResponse]()
|
||||
|
||||
@Published var postId = 0
|
||||
@Published var postPrice = 0
|
||||
@Published var postIndex = -1
|
||||
|
||||
@Published var isShowCommentListView = false {
|
||||
didSet {
|
||||
|
@ -46,6 +48,16 @@ class CreatorCommunityAllViewModel: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
@Published var isShowPostPurchaseView = false {
|
||||
didSet {
|
||||
if !isShowPostPurchaseView {
|
||||
postId = 0
|
||||
postPrice = 0
|
||||
postIndex = -1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var creatorId = 0
|
||||
|
||||
var page = 1
|
||||
|
@ -254,4 +266,51 @@ class CreatorCommunityAllViewModel: ObservableObject {
|
|||
self.isLoading = false
|
||||
}
|
||||
}
|
||||
|
||||
func purchaseCommunityPost() {
|
||||
let postId = postId
|
||||
let postIndex = postIndex
|
||||
|
||||
if !isLoading {
|
||||
isLoading = true
|
||||
|
||||
repository
|
||||
.purchaseCommunityPost(postId: postId)
|
||||
.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(ApiResponse<GetCommunityPostListResponse>.self, from: responseData)
|
||||
|
||||
if let data = decoded.data, decoded.success {
|
||||
if postIndex >= 0 {
|
||||
communityPostList[postIndex] = data
|
||||
}
|
||||
} 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
//
|
||||
// PurchasePostRequest.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 5/24/24.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct PurchasePostRequest: Encodable {
|
||||
let postId: Int
|
||||
let container: String = "ios"
|
||||
let timezone: String = TimeZone.current.identifier
|
||||
}
|
|
@ -19,6 +19,7 @@ enum CreatorCommunityApi {
|
|||
case getCommentReplyList(commentId: Int, page: Int, size: Int)
|
||||
case modifyComment(request: ModifyCommunityPostCommentRequest)
|
||||
case getLatestPostListFromCreatorsYouFollow
|
||||
case purchaseCommunityPost(postId: Int)
|
||||
}
|
||||
|
||||
extension CreatorCommunityApi: TargetType {
|
||||
|
@ -48,12 +49,15 @@ extension CreatorCommunityApi: TargetType {
|
|||
|
||||
case .getLatestPostListFromCreatorsYouFollow:
|
||||
return "/creator-community/latest"
|
||||
|
||||
case .purchaseCommunityPost:
|
||||
return "/creator-community/purchase"
|
||||
}
|
||||
}
|
||||
|
||||
var method: Moya.Method {
|
||||
switch self {
|
||||
case .createCommunityPost, .communityPostLike, .createCommunityPostComment:
|
||||
case .createCommunityPost, .communityPostLike, .createCommunityPostComment, .purchaseCommunityPost:
|
||||
return .post
|
||||
|
||||
case .getCommunityPostList, .getCommunityPostCommentList, .getCommentReplyList, .getCommunityPostDetail, .getLatestPostListFromCreatorsYouFollow:
|
||||
|
@ -115,6 +119,9 @@ extension CreatorCommunityApi: TargetType {
|
|||
case .getLatestPostListFromCreatorsYouFollow:
|
||||
let parameters = ["timezone": TimeZone.current.identifier] as [String: Any]
|
||||
return .requestParameters(parameters: parameters, encoding: URLEncoding.queryString)
|
||||
|
||||
case .purchaseCommunityPost(let postId):
|
||||
return .requestJSONEncodable(PurchasePostRequest(postId: postId))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,19 +22,19 @@ struct CreatorCommunityItemView: View {
|
|||
|
||||
Text(item.creatorNickname)
|
||||
.font(.custom(Font.medium.rawValue, size: 13.3))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
.foregroundColor(Color.grayee)
|
||||
|
||||
Spacer()
|
||||
|
||||
Text(item.date)
|
||||
.font(.custom(Font.light.rawValue, size: 13.3))
|
||||
.foregroundColor(Color(hex: "777777"))
|
||||
.foregroundColor(Color.gray77)
|
||||
}
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Text(item.content)
|
||||
.font(.custom(Font.medium.rawValue, size: 12))
|
||||
.foregroundColor(Color(hex: "bbbbbb"))
|
||||
.foregroundColor(Color.graybb)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.lineLimit(3)
|
||||
|
||||
|
@ -45,9 +45,10 @@ struct CreatorCommunityItemView: View {
|
|||
.resizable()
|
||||
.frame(width: 53.3, height: 53.3)
|
||||
.cornerRadius(4.7)
|
||||
.blur(radius: item.existOrdered ? 0 : 15)
|
||||
} else {
|
||||
Rectangle()
|
||||
.foregroundColor(Color(hex: "222222").opacity(0))
|
||||
.foregroundColor(Color.gray22.opacity(0))
|
||||
.frame(width: 53.3, height: 53.3)
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +61,7 @@ struct CreatorCommunityItemView: View {
|
|||
|
||||
Text("\(item.likeCount)")
|
||||
.font(.custom(Font.medium.rawValue, size: 11))
|
||||
.foregroundColor(Color(hex: "777777"))
|
||||
.foregroundColor(Color.gray77)
|
||||
}
|
||||
|
||||
HStack(spacing: 6) {
|
||||
|
@ -70,13 +71,13 @@ struct CreatorCommunityItemView: View {
|
|||
|
||||
Text("\(item.commentCount)")
|
||||
.font(.custom(Font.medium.rawValue, size: 11))
|
||||
.foregroundColor(Color(hex: "777777"))
|
||||
.foregroundColor(Color.gray77)
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(13.3)
|
||||
.background(Color(hex: "222222"))
|
||||
.background(Color.gray22)
|
||||
.cornerRadius(11)
|
||||
}
|
||||
}
|
||||
|
@ -91,10 +92,12 @@ struct CreatorCommunityItemView_Previews: PreviewProvider {
|
|||
creatorProfileUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
|
||||
imageUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
|
||||
content: "안녕하세요",
|
||||
price: 10,
|
||||
date: "3일전",
|
||||
isCommentAvailable: false,
|
||||
isAdult: false,
|
||||
isLike: false,
|
||||
existOrdered: false,
|
||||
likeCount: 10,
|
||||
commentCount: 0,
|
||||
firstComment: nil
|
||||
|
|
|
@ -52,4 +52,8 @@ class CreatorCommunityRepository {
|
|||
func getLatestPostListFromCreatorsYouFollow() -> AnyPublisher<Response, MoyaError> {
|
||||
return api.requestPublisher(.getLatestPostListFromCreatorsYouFollow)
|
||||
}
|
||||
|
||||
func purchaseCommunityPost(postId: Int) -> AnyPublisher<Response, MoyaError> {
|
||||
return api.requestPublisher(.purchaseCommunityPost(postId: postId))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,10 +12,12 @@ struct GetCommunityPostListResponse: Decodable {
|
|||
let creatorProfileUrl: String
|
||||
let imageUrl: String?
|
||||
let content: String
|
||||
let price: Int
|
||||
let date: String
|
||||
let isCommentAvailable: Bool
|
||||
let isAdult: Bool
|
||||
let isLike: Bool
|
||||
let existOrdered: Bool
|
||||
let likeCount: Int
|
||||
let commentCount: Int
|
||||
let firstComment: GetCommunityPostCommentListItem?
|
||||
|
|
|
@ -38,10 +38,12 @@ struct SectionCommunityPostView_Previews: PreviewProvider {
|
|||
creatorProfileUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
|
||||
imageUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
|
||||
content: "라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!",
|
||||
price: 10,
|
||||
date: "3일전",
|
||||
isCommentAvailable: false,
|
||||
isAdult: false,
|
||||
isLike: true,
|
||||
existOrdered: false,
|
||||
likeCount: 10,
|
||||
commentCount: 0,
|
||||
firstComment: nil
|
||||
|
@ -53,10 +55,12 @@ struct SectionCommunityPostView_Previews: PreviewProvider {
|
|||
creatorProfileUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
|
||||
imageUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
|
||||
content: "너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!",
|
||||
price: 10,
|
||||
date: "3일전",
|
||||
isCommentAvailable: false,
|
||||
isAdult: false,
|
||||
isLike: true,
|
||||
existOrdered: false,
|
||||
likeCount: 20,
|
||||
commentCount: 0,
|
||||
firstComment: nil
|
||||
|
|
Loading…
Reference in New Issue