// // UserMessageItemView.swift // SodaLive // // Created by klaus on 9/2/25. // import SwiftUI struct UserMessageBubbleShape: Shape { func path(in rect: CGRect) -> Path { let path = UIBezierPath() // 시작점 (왼쪽 상단, 16px 반지름) path.move(to: CGPoint(x: 16, y: 0)) // 상단 라인 (오른쪽 상단 4px 반지름까지) path.addLine(to: CGPoint(x: rect.width - 4, y: 0)) // 오른쪽 상단 모서리 (4px 반지름) path.addArc(withCenter: CGPoint(x: rect.width - 4, y: 4), radius: 4, startAngle: -CGFloat.pi / 2, endAngle: 0, clockwise: true) // 오른쪽 라인 (오른쪽 하단 16px 반지름까지) path.addLine(to: CGPoint(x: rect.width, y: rect.height - 16)) // 오른쪽 하단 모서리 (16px 반지름) path.addArc(withCenter: CGPoint(x: rect.width - 16, y: rect.height - 16), radius: 16, startAngle: 0, endAngle: CGFloat.pi / 2, clockwise: true) // 하단 라인 (왼쪽 하단 16px 반지름까지) path.addLine(to: CGPoint(x: 16, y: rect.height)) // 왼쪽 하단 모서리 (16px 반지름) path.addArc(withCenter: CGPoint(x: 16, y: rect.height - 16), radius: 16, startAngle: CGFloat.pi / 2, endAngle: CGFloat.pi, clockwise: true) // 왼쪽 라인 (왼쪽 상단 16px 반지름까지) path.addLine(to: CGPoint(x: 0, y: 16)) // 왼쪽 상단 모서리 (16px 반지름) path.addArc(withCenter: CGPoint(x: 16, y: 16), radius: 16, startAngle: CGFloat.pi, endAngle: -CGFloat.pi / 2, clockwise: true) path.close() return Path(path.cgPath) } } struct UserMessageItemView: View { let message: ServerChatMessage var body: some View { HStack(alignment: .bottom, spacing: 4) { Spacer() // 시간 표시 VStack { Text(formatTime(from: message.createdAt)) .font(.custom(Font.preRegular.rawValue, size: 10)) .foregroundColor(.white) } // 메시지 버블 HStack(spacing: 9) { VStack(alignment: .trailing, spacing: 4) { // 메시지 텍스트 HStack(spacing: 10) { styledMessageText(message.message) .lineLimit(nil) .multilineTextAlignment(.leading) } .padding(.horizontal, 10) .padding(.vertical, 8) .background(Color.button) .clipShape(UserMessageBubbleShape()) } } } .frame(maxWidth: .infinity, alignment: .trailing) } private func formatTime(from timestamp: Int64) -> String { let date = Date(timeIntervalSince1970: TimeInterval(timestamp / 1000)) return date.convertDateFormat(dateFormat: "a h:mm") } private func styledMessageText(_ message: String) -> Text { var result = Text("") let components = message.components(separatedBy: "(") for (index, component) in components.enumerated() { if index == 0 { // 첫 번째 컴포넌트는 항상 일반 텍스트 if !component.isEmpty { result = result + Text(component) .font(.custom(Font.preRegular.rawValue, size: 16)) .foregroundColor(.white) } } else { // "(" 이후의 텍스트 처리 if let closeIndex = component.firstIndex(of: ")") { let beforeClose = String(component[..