Open task views in a sheet over the left pane

This commit is contained in:
Ian Gulliver
2026-10-21 17:00:07 -07:00
parent ccb08ab6ec
commit 193401021a
22 changed files with 698 additions and 546 deletions
+45 -21
View File
@@ -2,6 +2,10 @@ import Foundation
import Observation
import SwiftData
enum TaskTab: String {
case transcript, board, changes, files, terminal, workflow, project
}
let taskTabs: [TaskTab] = [.transcript, .board, .changes, .files, .terminal, .workflow, .project]
enum JumpTarget: Equatable {
@@ -65,7 +69,8 @@ final class Store {
private(set) var selectedTaskId: String?
var pinned: Int?
var connected = false
private(set) var focus = Focus(tab: .transcript)
private(set) var focus = Focus()
var sheet: Sheet?
var leadSessions: [AgentSession] = []
let leadFeed: Feed
var jump: Jump?
@@ -290,12 +295,12 @@ final class Store {
func jumpTo(_ taskId: String, _ target: JumpTarget) {
jumps += 1
jump = Jump(taskId: taskId, target: target, n: jumps)
focusTask(taskId, .transcript)
focusTask(taskId)
}
func showQuestion(_ taskId: String) {
guard let item = inbox.filter({ $0.taskId == taskId }).min(by: { $0.createdAt < $1.createdAt }) else {
focusTask(taskId, .transcript)
focusTask(taskId)
return
}
if let member = sessions[taskId]?.first(where: { $0.id == item.agentSessionId })?.member, !member.isEmpty {
@@ -458,18 +463,37 @@ final class Store {
projects.first { $0.id == focus.projectId }
}
var shownTab: TaskTab {
let run = selectedTaskId.flatMap { findTask($0) }?.workflow != nil
if run {
return focus.tab == .project ? .project : .workflow
var primaryTab: TaskTab {
guard let id = selectedTaskId else {
return .project
}
return focus.tab == .workflow ? .transcript : focus.tab
return findTask(id)?.workflow != nil ? .workflow : .transcript
}
func setFocus(taskId: String?? = .none, projectId: String?? = .none, tab: TaskTab? = nil) async throws {
func openTab(_ tab: TaskTab) {
if tab == primaryTab || sheet?.tab == tab {
sheet = nil
return
}
sheet = Sheet(owner: .task(selectedTaskId), view: .tab(tab))
}
func openSheet(_ view: SheetView, fromTask: Bool) {
sheet = Sheet(owner: fromTask ? .task(selectedTaskId) : .lead, view: view)
}
func closeSheet() -> Bool {
if sheet == nil {
return false
}
sheet = nil
return true
}
func setFocus(taskId: String?? = .none, projectId: String?? = .none) async throws {
let task = taskId ?? focus.taskId
let project = task != nil ? findTask(task!)?.projectId : (projectId ?? focus.projectId)
var next = Focus(tab: tab ?? focus.tab)
var next = Focus()
if let task, !task.isEmpty {
next.taskId = task
}
@@ -485,21 +509,15 @@ final class Store {
applyFocus(f)
}
func focusTask(_ taskId: String, _ tab: TaskTab = .transcript) {
func focusTask(_ taskId: String) {
spawn("set focus") {
try await self.setFocus(taskId: taskId, tab: tab)
try await self.setFocus(taskId: taskId)
}
}
func focusProject(_ projectId: String) {
spawn("set focus") {
try await self.setFocus(taskId: .some(nil), projectId: projectId, tab: .project)
}
}
func focusTab(_ tab: TaskTab) {
spawn("set focus") {
try await self.setFocus(tab: tab)
try await self.setFocus(taskId: .some(nil), projectId: projectId)
}
}
@@ -510,9 +528,12 @@ final class Store {
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) {
if let tab, tab != .transcript, tab != .workflow {
sheet = Sheet(owner: .task(id), view: .tab(tab))
}
if id != focus.taskId {
spawn("set focus") {
try await self.setFocus(taskId: id, tab: tab)
try await self.setFocus(taskId: id)
}
}
return
@@ -633,6 +654,9 @@ final class Store {
}
func selectTask(_ taskId: String?) {
if case .task(let owner)? = sheet?.owner, owner != taskId {
sheet = sheet?.tab == .project && taskId != nil ? Sheet(owner: .task(taskId), view: .tab(.project)) : nil
}
markVisited(selectedTaskId)
markVisited(taskId)
selectedTaskId = taskId