macOS client parity review

This commit is contained in:
Ian Gulliver
2026-10-17 10:54:06 -07:00
parent b85de9a2d0
commit 31037e1c9f
24 changed files with 651 additions and 225 deletions
+41 -8
View File
@@ -6,6 +6,7 @@ let taskTabs: [TaskTab] = [.transcript, .changes, .files, .terminal, .inbox, .re
private let historyPage = 1000
private let leadPage = 50
private let routeHash = Re(#"^#/(task|project)/(\w+)(?:/(\w+))?$"#)
struct TaskState {
enum Kind {
@@ -44,7 +45,7 @@ final class Store {
var composerFocus: String?
var summaryReads: [String: Int64] = [:]
private(set) var leadMore = false
var todoStarting: Set<String> = []
var todoBusy: [String: String] = [:]
private(set) var drafts: Drafts?
let images = ImageDrafts()
let events = Listeners<ByreEvent>()
@@ -76,39 +77,48 @@ final class Store {
drafts!.prune(self)
}
var todoStarting: Set<String> {
Set(todoBusy.keys)
}
func startTodo(_ projectId: String, _ title: String, discuss: Bool, _ overlays: Overlays) {
let key = "\(projectId)\n\(title)"
if todoStarting.contains(key) {
if todoBusy[key] != nil {
return
}
todoStarting.insert(key)
todoBusy[key] = discuss ? "discuss" : "start"
Task {
do {
_ = try await api.client.startTodoItem(path: .init(projectId: projectId), body: .json(.init(title: title, model: models[0], discuss: discuss))).created
} catch {
overlays.showAlert(errorText(error))
}
todoStarting.remove(key)
todoBusy[key] = nil
}
}
func startSuggestion(_ projectId: String, _ title: String, brief: String, _ overlays: Overlays) {
let key = "\(projectId)\n\(title)"
if todoStarting.contains(key) {
if todoBusy[key] != nil {
return
}
todoStarting.insert(key)
todoBusy[key] = "start"
Task {
do {
_ = try await api.client.createTask(path: .init(projectId: projectId), body: .json(.init(title: title, prompt: brief, model: models[0]))).created
} catch {
overlays.showAlert(errorText(error))
}
todoStarting.remove(key)
todoBusy[key] = nil
}
}
func discussSuggestion(_ title: String, brief: String, _ overlays: Overlays) {
func discussSuggestion(_ projectId: String, _ title: String, brief: String, _ overlays: Overlays) {
let key = "\(projectId)\n\(title)"
if todoBusy[key] != nil {
return
}
todoBusy[key] = "discuss"
let lead = currentLead()
let live = lead != nil && lead!.state != .completed
Task {
@@ -117,6 +127,7 @@ final class Store {
} catch {
overlays.showAlert(errorText(error))
}
todoBusy[key] = nil
}
}
@@ -310,6 +321,28 @@ final class Store {
}
}
func route(_ hash: String) {
let m = routeHash.exec(hash)
let kind = m?[1] ?? nil
let id = m?[2] ?? nil
let name = m?[3] ?? nil
let tab = taskTabs.first { $0.rawValue == name }
if kind == "task", let id {
if id != focus.taskId || (tab != nil && tab != focus.tab) {
spawn("set focus") {
try await self.setFocus(taskId: id, tab: tab)
}
}
return
}
let projectId = kind == "project" ? id : nil
if focus.taskId != nil || projectId != focus.projectId {
spawn("set focus") {
try await self.setFocus(taskId: .some(nil), projectId: .some(projectId))
}
}
}
private func loadHistory(_ taskId: String, _ feed: Feed) async throws {
var got: [ByreEvent] = []
while true {