73 lines
2.9 KiB
Swift
73 lines
2.9 KiB
Swift
// 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
|
||
}
|
||
}
|
||
}
|