Drop the project page heading and split tasks from settings

This commit is contained in:
Ian Gulliver
2026-10-22 13:27:28 -07:00
parent d5ffd5b128
commit 75d904fb2b
2 changed files with 62 additions and 46 deletions
+1
View File
@@ -53,6 +53,7 @@ final class Overlays {
var leadFocus = 0 var leadFocus = 0
var tabFocus = 0 var tabFocus = 0
var projectFocus = false var projectFocus = false
var projectSettings = false
var taskList = false var taskList = false
@ObservationIgnored var pickerFrame: CGRect = .zero @ObservationIgnored var pickerFrame: CGRect = .zero
@ObservationIgnored var menuHover = false @ObservationIgnored var menuHover = false
+61 -46
View File
@@ -14,14 +14,31 @@ struct ProjectView: View {
@FocusState private var focused: Bool @FocusState private var focused: Bool
var body: some View { var body: some View {
ScrollView { VStack(spacing: 0) {
if let p = store.focusedProject() { if store.focusedProject() != nil {
ProjectBlock(project: p, todo: todos[p.id]) HStack(spacing: 4) {
.padding(.horizontal, 16) PaneTabButton(label: "Tasks", active: !overlays.projectSettings) {
.padding(.top, 8) overlays.projectSettings = false
.padding(.bottom, 16) }
} else { PaneTabButton(label: "Settings", active: overlays.projectSettings) {
Muted(text: "No project selected.") overlays.projectSettings = true
}
Spacer(minLength: 0)
}
.padding(.horizontal, 12)
.overlay(alignment: .bottom) {
Rectangle().fill(Palette.border).frame(height: 1)
}
}
ScrollView {
if let p = store.focusedProject() {
ProjectBlock(project: p, todo: todos[p.id], settings: overlays.projectSettings)
.padding(.horizontal, 16)
.padding(.top, 8)
.padding(.bottom, 16)
} else {
Muted(text: "No project selected.")
}
} }
} }
.frame(maxWidth: .infinity, maxHeight: .infinity) .frame(maxWidth: .infinity, maxHeight: .infinity)
@@ -136,53 +153,51 @@ private struct ProjectWorkflowMenu: View {
private struct ProjectBlock: View { private struct ProjectBlock: View {
let project: Project let project: Project
let todo: Result<Todo, ApiError>? let todo: Result<Todo, ApiError>?
let settings: Bool
@Environment(Store.self) private var store @Environment(Store.self) private var store
@Environment(Overlays.self) private var overlays @Environment(Overlays.self) private var overlays
var body: some View { var body: some View {
let active = (store.tasks[project.id] ?? []).filter { $0.status == .active } let active = (store.tasks[project.id] ?? []).filter { $0.status == .active }
VStack(alignment: .leading, spacing: 0) { VStack(alignment: .leading, spacing: 0) {
HStack(alignment: .firstTextBaseline, spacing: 6) { if settings {
Text(project.name).font(Fonts.font(13, weight: 700)) heading("Settings")
Text(project.defaultBranch).font(Fonts.font(11)).foregroundStyle(Palette.muted) Grid(alignment: .leading, horizontalSpacing: 12, verticalSpacing: 4) {
} GridRow {
.padding(.top, 16) Text("Audit \(project.defaultBranch)")
.padding(.bottom, 6) ProjectWorkflowMenu(project: project, audit: true)
heading("Tasks") }
if active.isEmpty { GridRow {
Text("No active tasks.") Text("Review tasks")
.foregroundStyle(Palette.muted) ProjectWorkflowMenu(project: project, audit: false)
.padding(.horizontal, 10)
.padding(.vertical, 6)
}
TaskRows(active: active)
heading("TODO")
TodoBlock(project: project, todo: todo, active: active)
heading("Settings")
Grid(alignment: .leading, horizontalSpacing: 12, verticalSpacing: 4) {
GridRow {
Text("Audit \(project.defaultBranch)")
ProjectWorkflowMenu(project: project, audit: true)
}
GridRow {
Text("Review tasks")
ProjectWorkflowMenu(project: project, audit: false)
}
}
.font(Fonts.font(11))
.foregroundStyle(Palette.muted)
HStack(alignment: .firstTextBaseline) {
heading("Schedules")
Spacer()
Button("New") {
Task {
await editSchedule(project, nil, store, overlays)
} }
} }
.buttonStyle(WebButtonStyle()) .font(Fonts.font(11))
.help("Create a task in this project on a timer") .foregroundStyle(Palette.muted)
HStack(alignment: .firstTextBaseline) {
heading("Schedules")
Spacer()
Button("New") {
Task {
await editSchedule(project, nil, store, overlays)
}
}
.buttonStyle(WebButtonStyle())
.help("Create a task in this project on a timer")
}
ScheduleRows(project: project)
} else {
heading("Tasks")
if active.isEmpty {
Text("No active tasks.")
.foregroundStyle(Palette.muted)
.padding(.horizontal, 10)
.padding(.vertical, 6)
}
TaskRows(active: active)
heading("TODO")
TodoBlock(project: project, todo: todo, active: active)
} }
ScheduleRows(project: project)
} }
.frame(maxWidth: .infinity, alignment: .leading) .frame(maxWidth: .infinity, alignment: .leading)
} }