// What a file approval would edit, shown on the feed card and the thread screen in place of the raw // prompt. Claude sends no diff before approval, so most show the file name alone. import SwiftUI /// "Wants to edit" over one file, or "Wants to edit 3 files" over a row for each: the name in /// monospace and, when the gateway counted them, the lines added and removed on the right. On the /// thread screen the title is amber and one file's first changed lines follow, removed in red and /// added in green. Past `limit` files, one line counts the rest. struct FileEditRows: View { var edit: FileEdit var limit = Int.max var inThread = false var body: some View { VStack(alignment: .leading, spacing: 2) { Text(edit.title) .font(.system(size: inThread ? 11 : 12, weight: inThread ? .semibold : .regular)) .foregroundStyle(inThread ? Theme.you : Theme.secondaryText) ForEach(edit.files.prefix(limit)) { file in HStack(spacing: 6) { Text(code: file.name) .foregroundStyle(.white) .lineLimit(1) .truncationMode(.middle) Spacer(minLength: 4) if let counts = counts(file) { counts .lineLimit(1) .layoutPriority(1) } } .font(.system(size: 12)) } if edit.files.count > limit { Text("\(edit.files.count - limit) more") .font(.system(size: 11)) .foregroundStyle(Theme.secondaryText) } if inThread, !edit.preview.isEmpty { VStack(alignment: .leading, spacing: 1) { ForEach(edit.preview) { line in Text(code: line.text) .foregroundStyle(color(line.change)) .lineLimit(1) } } .font(.system(size: 11)) .padding(.top, 4) } } .accessibilityElement(children: .combine) } /// "+9 −6" in monospace, green and red, leaving out a count the gateway did not send. private func counts(_ file: PendingFile) -> Text? { let parts = [ file.counts.additions.map { Text(code: $0).foregroundStyle(Theme.add) }, file.counts.deletions.map { Text(code: $0).foregroundStyle(Theme.bad) }, ].compactMap(\.self) guard let first = parts.first else { return nil } return parts.dropFirst().reduce(first) { Text("\($0)\(Text(code: " "))\($1)") } } private func color(_ change: FileEdit.Line.Change) -> Color { switch change { case .added: Theme.add case .removed: Theme.bad case .context: Theme.secondaryText } } }