Comment on diff lines in the Changes view

This commit is contained in:
Ian Gulliver
2026-10-18 07:30:00 -07:00
parent 10c6c84f74
commit e7beca74f2
7 changed files with 304 additions and 41 deletions
+81 -1
View File
@@ -11,6 +11,19 @@ private struct Saved: Codable {
var composer: [String: Composer] = [:]
var checked: [String: [String]] = [:]
var texts: [String: String] = [:]
var comments: [String: [LineComment]]? = nil
}
struct LineAnchor: Codable, Hashable {
let path: String
let line: Int
let old: Bool
let quote: String
}
struct LineComment: Codable {
let anchor: LineAnchor
var text: String
}
final class DraftSend {
@@ -40,6 +53,7 @@ final class Drafts {
private var lostImages: [String: Int] = [:]
private var checked: [String: [String]] = [:]
private var texts: [String: String] = [:]
private var comments: [String: [LineComment]] = [:]
@ObservationIgnored private let scope: String
@ObservationIgnored private var timer: Task<Void, Never>?
@ObservationIgnored private var dirty = false
@@ -59,6 +73,7 @@ final class Drafts {
}
checked = saved.checked
texts = saved.texts
comments = saved.comments ?? [:]
}
func reload() {
@@ -94,6 +109,10 @@ final class Drafts {
changed = true
}
}
for taskId in comments.keys where store.findTask(taskId)?.status != .active {
comments[taskId] = nil
changed = true
}
for id in Set(checked.keys).union(texts.keys) where !store.inbox.contains(where: { $0.id == id }) {
checked[id] = nil
texts[id] = nil
@@ -122,7 +141,7 @@ final class Drafts {
return
}
dirty = false
var out = Saved(checked: checked, texts: texts)
var out = Saved(checked: checked, texts: texts, comments: comments)
let keys = Set(composerTexts.keys).union(composerImages.keys).union(sending.map(\.key)).union(lostImages.keys)
for key in keys {
let inFlight = sending.filter { $0.key == key }
@@ -233,6 +252,67 @@ final class Drafts {
save()
}
func lineComments(_ taskId: String) -> [LineComment] {
comments[taskId] ?? []
}
func lineComment(_ taskId: String, _ anchor: LineAnchor) -> LineComment? {
comments[taskId]?.first { $0.anchor == anchor }
}
func toggleLineComment(_ taskId: String, _ anchor: LineAnchor) {
var list = comments[taskId] ?? []
if let i = list.firstIndex(where: { $0.anchor == anchor }) {
if !trimmed(list[i].text).isEmpty {
return
}
list.remove(at: i)
} else {
list.append(LineComment(anchor: anchor, text: ""))
}
comments[taskId] = list.isEmpty ? nil : list
save()
}
func setLineComment(_ taskId: String, _ anchor: LineAnchor, _ text: String) {
guard let i = comments[taskId]?.firstIndex(where: { $0.anchor == anchor }), comments[taskId]![i].text != text else {
return
}
comments[taskId]![i].text = text
save()
}
func dropLineComment(_ taskId: String, _ anchor: LineAnchor) {
comments[taskId]?.removeAll { $0.anchor == anchor }
if comments[taskId]?.isEmpty == true {
comments[taskId] = nil
}
save()
}
func takeLineComments(_ taskId: String) -> [LineComment] {
let all = comments[taskId] ?? []
let ready = all.filter { !trimmed($0.text).isEmpty }
let rest = all.filter { trimmed($0.text).isEmpty }
comments[taskId] = rest.isEmpty ? nil : rest
dirty = true
flush()
return ready
}
func restoreLineComments(_ taskId: String, _ back: [LineComment]) {
var list = back
for c in comments[taskId] ?? [] {
if let i = list.firstIndex(where: { $0.anchor == c.anchor }) {
list[i].text = [list[i].text, c.text].filter { !trimmed($0).isEmpty }.joined(separator: "\n\n")
} else {
list.append(c)
}
}
comments[taskId] = list
save()
}
func clearAnswer(_ id: String) {
checked[id] = nil
texts[id] = nil