import SwiftUI struct MessageBubble: View { let message: ChatMessage let isSent: Bool var body: some View { VStack(alignment: isSent ? .trailing : .leading, spacing: 4) { HStack { if isSent { Spacer(minLength: 44) } VStack(alignment: .leading, spacing: 8) { Text(markdownBody) .textSelection(.enabled) if let attachment = message.attachment { Label( "\(attachment.name) ยท \(formattedSize(attachment.size))", systemImage: "paperclip" ) .font(.footnote) .foregroundStyle(isSent ? .white.opacity(0.85) : .secondary) } } .padding(.horizontal, 12) .padding(.vertical, 9) .foregroundStyle(isSent ? .white : .primary) .background(isSent ? Color.accentColor : Color.gray.opacity(0.18)) .clipShape(RoundedRectangle(cornerRadius: 16)) if !isSent { Spacer(minLength: 44) } } Text(message.sentAt.formatted(date: .omitted, time: .shortened)) .font(.caption2) .foregroundStyle(.secondary) } } private var markdownBody: AttributedString { (try? AttributedString(markdown: message.body)) ?? AttributedString(message.body) } private func formattedSize(_ size: Int) -> String { ByteCountFormatter.string(fromByteCount: Int64(size), countStyle: .file) } }