feat(chat-room) 채팅방 API

- 채팅방 입장 API 연동
- 채팅 쿼터가 없을 때 표시할 UI 추가
This commit is contained in:
Yu Sung
2025-09-04 04:20:45 +09:00
parent 96cabbc6a7
commit 2576c851ee
9 changed files with 353 additions and 47 deletions

View File

@@ -19,7 +19,7 @@ struct ChatRoomView: View {
var body: some View {
BaseView(isLoading: $viewModel.isLoading) {
ChatRoomBgView()
ChatRoomBgView(url: viewModel.chatRoomBgImageUrl)
VStack(spacing: 0) {
HStack(spacing: 12) {
@@ -38,6 +38,7 @@ struct ChatRoomView: View {
}
.resizable()
.frame(width: 36, height: 36)
.clipShape(Circle())
VStack(alignment: .leading, spacing: 4) {
Text(viewModel.characterName)
@@ -116,11 +117,26 @@ struct ChatRoomView: View {
let message = viewModel.messages[index]
if message.mine {
UserMessageItemView(message: message)
.id(index)
} else {
AiMessageItemView(
message: message,
characterName: viewModel.characterName
)
.id(index)
}
}
if viewModel.showQuotaNoticeView {
ChatQuotaNoticeItemView(remainingTime: viewModel.countdownText) {
}
.id(viewModel.messages.count)
.padding(.bottom, 12)
.onAppear {
withAnimation(.easeOut(duration: 0.3)) {
proxy.scrollTo(viewModel.messages.count, anchor: .bottom)
}
}
}
}
@@ -139,65 +155,69 @@ struct ChatRoomView: View {
.frame(width: screenSize().width)
.frame(maxHeight: .infinity)
HStack(spacing: 8) {
HStack(spacing: 0) {
ZStack(alignment: .leading) {
if viewModel.messageText.isEmpty {
Text("메시지를 입력하세요.")
.font(.custom(Font.preRegular.rawValue, size: 14))
.foregroundColor(Color(hex: "78909C"))
}
TextField("", text: $viewModel.messageText)
.font(.custom(Font.preRegular.rawValue, size: 14))
.foregroundColor(.white)
.onSubmit {
viewModel.sendMessage()
if !viewModel.showQuotaNoticeView {
HStack(spacing: 8) {
HStack(spacing: 0) {
ZStack(alignment: .leading) {
if viewModel.messageText.isEmpty {
Text("메시지를 입력하세요.")
.font(.custom(Font.preRegular.rawValue, size: 14))
.foregroundColor(Color(hex: "78909C"))
}
TextField("", text: $viewModel.messageText)
.font(.custom(Font.preRegular.rawValue, size: 14))
.foregroundColor(.white)
.onSubmit {
viewModel.sendMessage()
}
}
.frame(maxWidth: .infinity)
}
.padding(.horizontal, 16)
.padding(.vertical, 13)
.background(Color(hex: "263238"))
.cornerRadius(999)
.overlay(
RoundedRectangle(cornerRadius: 999)
.stroke(Color(hex: "263238"), lineWidth: 1)
)
Button(action: {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
viewModel.sendMessage()
}) {
Image("ic_message_send")
.resizable()
.frame(width: 24, height: 24)
}
.frame(maxWidth: .infinity)
}
.padding(.horizontal, 16)
.padding(.vertical, 13)
.background(Color(hex: "263238"))
.cornerRadius(999)
.overlay(
RoundedRectangle(cornerRadius: 999)
.stroke(Color(hex: "263238"), lineWidth: 1)
)
Button(action: {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
viewModel.sendMessage()
}) {
Image("ic_message_send")
.resizable()
.frame(width: 24, height: 24)
}
.padding(.horizontal, 12)
.padding(.vertical, 12)
.frame(width: screenSize().width)
}
.padding(.horizontal, 12)
.padding(.vertical, 12)
.frame(width: screenSize().width)
}
}
.onAppear {
viewModel.enterRoom(roomId: roomId)
}
.onDisappear {
viewModel.stopTimer()
}
}
}
struct ChatRoomBgView: View {
let url: String? = nil
let url: String?
var body: some View {
ZStack {
if let url = url {
KFImage(URL(string: url))
.resizable()
.scaledToFill()
.ignoresSafeArea()
} else {
Image("img_sample")
.resizable()
.scaledToFill()
.aspectRatio(4/5, contentMode: .fill)
.frame(maxWidth: screenSize().width)
.ignoresSafeArea()
}