feat: 커뮤니티 글쓰기/수정

- 이미지 gif 등록 기능 추가
This commit is contained in:
Yu Sung
2025-07-03 18:01:06 +09:00
parent 419feeab6d
commit da3ca96960
4 changed files with 123 additions and 104 deletions

View File

@@ -6,7 +6,9 @@
//
import SwiftUI
import PhotosUI
import Kingfisher
import SDWebImageSwiftUI
struct CreatorCommunityModifyView: View {
@@ -14,7 +16,7 @@ struct CreatorCommunityModifyView: View {
@StateObject var keyboardHandler = KeyboardHandler()
@StateObject private var viewModel = CreatorCommunityModifyViewModel()
@State private var isShowPhotoPicker = false
@State private var selectedItem: PhotosPickerItem? = nil
let onSuccess: () -> Void
var body: some View {
@@ -26,34 +28,29 @@ struct CreatorCommunityModifyView: View {
ScrollView(.vertical, showsIndicators: false) {
VStack(spacing: 0) {
VStack(spacing: 0) {
VStack(spacing: 13.3) {
Text("이미지")
.font(.custom(Font.bold.rawValue, size: 16.7))
.foregroundColor(Color(hex: "eeeeee"))
.frame(maxWidth: .infinity, alignment: .leading)
ZStack {
if let selectedImage = viewModel.postImage {
Image(uiImage: selectedImage)
PhotosPicker(
selection: $selectedItem,
matching: .any(of: [.images]),
photoLibrary: .shared()) {
ZStack(alignment: .bottomTrailing) {
if let selectedImage = viewModel.postImageData {
AnimatedImage(data: selectedImage)
.resizable()
.scaledToFill()
.frame(width: 107, height: 107)
.background(Color(hex: "3e3358"))
.frame(width: 300)
.cornerRadius(8)
.clipped()
} else if let postImageUrl = viewModel.postImageUrl {
KFImage(URL(string: postImageUrl))
.cancelOnDisappear(true)
.downsampling(
size: CGSize(
width: 107,
height: 107
)
)
AnimatedImage(url: URL(string: postImageUrl))
.resizable()
.scaledToFill()
.frame(width: 107, height: 107)
.background(Color(hex: "3e3358"))
.frame(width: 300)
.cornerRadius(8)
.clipped()
} else {
@@ -62,20 +59,35 @@ struct CreatorCommunityModifyView: View {
.scaledToFit()
.padding(13.3)
.frame(width: 107, height: 107)
.background(Color(hex: "13181B"))
.background(Color.bg)
.cornerRadius(8)
.clipped()
}
Image("ic_camera")
.padding(10)
.background(Color(hex: "3BB9F1"))
.background(Color.button)
.cornerRadius(30)
.offset(x: 50, y: 36)
.offset(x: 15, y: 0)
}
.frame(alignment: .bottomTrailing)
.contentShape(Rectangle())
.onTapGesture { isShowPhotoPicker = true }
}
.onChange(of: selectedItem) { newItem in
Task {
if let item = newItem {
do {
// Data (GIF )
if let data = try await item.loadTransferable(type: Data.self) {
viewModel.postImageData = data
}
} catch {
viewModel.errorMessage = "이미지를 로드하지 못했습니다."
viewModel.isShowPopup = true
DEBUG_LOG("이미지 로드 실패: \(error)")
}
}
}
}
HStack(alignment: .top, spacing: 0) {
Text("")
@@ -230,14 +242,6 @@ struct CreatorCommunityModifyView: View {
}
}
}
if isShowPhotoPicker {
ImagePicker(
isShowing: $isShowPhotoPicker,
selectedImage: $viewModel.postImage,
sourceType: .photoLibrary
)
}
}
.onTapGesture { hideKeyboard() }
.edgesIgnoringSafeArea(.bottom)
@@ -249,7 +253,7 @@ struct CreatorCommunityModifyView: View {
.padding(.vertical, 13.3)
.frame(width: screenSize().width - 66.7, alignment: .center)
.font(.custom(Font.medium.rawValue, size: 12))
.background(Color(hex: "9970ff"))
.background(Color.button)
.foregroundColor(Color.white)
.multilineTextAlignment(.center)
.cornerRadius(20)

View File

@@ -20,7 +20,7 @@ final class CreatorCommunityModifyViewModel: ObservableObject {
@Published var content = ""
@Published var isAdult = false
@Published var isAvailableComment = true
@Published var postImage: UIImage? = nil
@Published var postImageData: Data? = nil
@Published var postImageUrl: String? = nil
@Published private(set) var communityPost: GetCommunityPostListResponse?
@@ -95,13 +95,14 @@ final class CreatorCommunityModifyViewModel: ObservableObject {
let jsonData = try? encoder.encode(request)
if let jsonData = jsonData {
if let postImage = postImage, let imageData = postImage.jpegData(compressionQuality: 0.8) {
if let postImageData = postImageData {
multipartData.append(
MultipartFormData(
provider: .data(imageData),
provider: .data(postImageData),
name: "postImage",
fileName: "\(UUID().uuidString)_\(Date().timeIntervalSince1970 * 1000).jpg",
mimeType: "image/*")
fileName: "\(UUID().uuidString)_\(Date().timeIntervalSince1970 * 1000)",
mimeType: "image/*"
)
)
}

View File

@@ -6,15 +6,19 @@
//
import SwiftUI
import PhotosUI
import SDWebImageSwiftUI
struct CreatorCommunityWriteView: View {
@StateObject var keyboardHandler = KeyboardHandler()
@StateObject private var viewModel = CreatorCommunityWriteViewModel()
@State private var selectedItem: PhotosPickerItem? = nil
@State private var isShowRecordingVoiceView = false
@State private var isShowPhotoPicker = false
@State private var fileName: String = "녹음"
let onSuccess: () -> Void
var body: some View {
@@ -26,19 +30,22 @@ struct CreatorCommunityWriteView: View {
ScrollView(.vertical, showsIndicators: false) {
VStack(spacing: 0) {
VStack(spacing: 0) {
VStack(spacing: 13.3) {
Text("이미지")
.font(.custom(Font.bold.rawValue, size: 16.7))
.foregroundColor(Color.grayee)
.frame(maxWidth: .infinity, alignment: .leading)
ZStack {
if let selectedImage = viewModel.postImage {
Image(uiImage: selectedImage)
PhotosPicker(
selection: $selectedItem,
matching: .any(of: [.images]),
photoLibrary: .shared()) {
ZStack(alignment: .bottomTrailing) {
if let selectedImage = viewModel.postImageData {
AnimatedImage(data: selectedImage)
.resizable()
.scaledToFill()
.frame(width: 107, height: 107)
.background(Color(hex: "3e3358"))
.frame(width: 300)
.cornerRadius(8)
.clipped()
} else {
@@ -56,11 +63,26 @@ struct CreatorCommunityWriteView: View {
.padding(10)
.background(Color.button)
.cornerRadius(30)
.offset(x: 50, y: 36)
.offset(x: 15, y: 0)
}
.frame(alignment: .bottomTrailing)
.contentShape(Rectangle())
.onTapGesture { isShowPhotoPicker = true }
}
.onChange(of: selectedItem) { newItem in
Task {
if let item = newItem {
do {
// Data (GIF )
if let data = try await item.loadTransferable(type: Data.self) {
viewModel.postImageData = data
}
} catch {
viewModel.errorMessage = "이미지를 로드하지 못했습니다."
viewModel.isShowPopup = true
DEBUG_LOG("이미지 로드 실패: \(error)")
}
}
}
}
HStack(alignment: .top, spacing: 0) {
Text("")
@@ -72,9 +94,9 @@ struct CreatorCommunityWriteView: View {
.foregroundColor(Color.gray77)
}
.frame(maxWidth: .infinity)
.padding(.top, 24)
.padding(.top, 16)
if let _ = viewModel.postImage {
if let _ = viewModel.postImageData {
VStack(spacing: 13.3) {
HStack(spacing: 0) {
Text("오디오 녹음")
@@ -190,7 +212,7 @@ struct CreatorCommunityWriteView: View {
.padding(.top, 26.7)
}
if let _ = viewModel.postImage {
if let _ = viewModel.postImageData {
VStack(spacing: 13.3) {
Text("가격 설정")
.font(.custom(Font.bold.rawValue, size: 16.7))
@@ -308,14 +330,6 @@ struct CreatorCommunityWriteView: View {
}
}
if isShowPhotoPicker {
ImagePicker(
isShowing: $isShowPhotoPicker,
selectedImage: $viewModel.postImage,
sourceType: .photoLibrary
)
}
if isShowRecordingVoiceView {
CreatorCommunityRecordingVoiceView(
isShowing: $isShowRecordingVoiceView,

View File

@@ -28,7 +28,7 @@ final class CreatorCommunityWriteViewModel: ObservableObject {
}
}
@Published var isAvailableComment = true
@Published var postImage: UIImage? = nil
@Published var postImageData: Data? = nil
@Published var priceString = "0" {
didSet {
@@ -60,12 +60,12 @@ final class CreatorCommunityWriteViewModel: ObservableObject {
let jsonData = try? encoder.encode(request)
if let jsonData = jsonData {
if let postImage = postImage, let imageData = postImage.jpegData(compressionQuality: 0.8) {
if let postImageData = postImageData {
multipartData.append(
MultipartFormData(
provider: .data(imageData),
provider: .data(postImageData),
name: "postImage",
fileName: "\(UUID().uuidString)_\(Date().timeIntervalSince1970 * 1000).jpg",
fileName: "\(UUID().uuidString)_\(Date().timeIntervalSince1970 * 1000)",
mimeType: "image/*"
)
)