// // TranscriptDisplayItems.swift // kordophone2 // // Created by James Magahern on 8/24/25. // import Foundation import SwiftUI extension TranscriptView.ViewModel { internal func rebuildDisplayItems(animated: Bool = false) { var displayItems: [DisplayItem] = [] var lastDate: Date = .distantPast var lastSender: Display.Sender? = nil let client = XPCClient() let isGroupChat = displayedConversation?.isGroupChat ?? false let dateAnnotationTimeInterval: TimeInterval = 60 * 30 for message in messages { if message.sender != lastSender { displayItems.append(.spacer(15.0, message.id)) } let isPastDateThreshold = message.date.timeIntervalSince(lastDate) > dateAnnotationTimeInterval if isPastDateThreshold { displayItems.append(.date(message.date)) } if isGroupChat && !message.sender.isMe && (isPastDateThreshold || message.sender != lastSender) { displayItems.append(.senderAttribition(message)) } for attachment in message.attachments { displayItems.append(.attachment(attachment)) if !attachment.isPreviewDownloaded { Task.detached { try await client.downloadAttachment(attachmentId: attachment.id, preview: true) } } } if !message.text.isEmpty { displayItems.append(.message(message)) } lastSender = message.sender lastDate = message.date } let animation: Animation? = animated ? .default : nil withAnimation(animation) { self.displayItems = displayItems } } } enum DisplayItem: Identifiable { case message(Display.Message) case attachment(Display.ImageAttachment) case senderAttribition(Display.Message) case spacer(CGFloat, Display.Message.ID) case date(Date) var id: String { switch self { case .message(let message): message.id case .attachment(let attachment): attachment.id case .senderAttribition(let message): "\(message.sender.displayName) @ \(message.id)" case .date(let date): date.description case .spacer(let space, let id): "\(space)=\(id)" } } }