From 75d904fb2b6fb06dc7f97315e49c1225e12aa03a Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Thu, 22 Oct 2026 13:27:28 -0700 Subject: [PATCH] Drop the project page heading and split tasks from settings --- mac/Sources/Byre/Dialogs.swift | 1 + mac/Sources/Byre/Project.swift | 107 +++++++++++++++++++-------------- 2 files changed, 62 insertions(+), 46 deletions(-) diff --git a/mac/Sources/Byre/Dialogs.swift b/mac/Sources/Byre/Dialogs.swift index 5b46c43..a0e2609 100644 --- a/mac/Sources/Byre/Dialogs.swift +++ b/mac/Sources/Byre/Dialogs.swift @@ -53,6 +53,7 @@ final class Overlays { var leadFocus = 0 var tabFocus = 0 var projectFocus = false + var projectSettings = false var taskList = false @ObservationIgnored var pickerFrame: CGRect = .zero @ObservationIgnored var menuHover = false diff --git a/mac/Sources/Byre/Project.swift b/mac/Sources/Byre/Project.swift index 4cd0152..905a6a3 100644 --- a/mac/Sources/Byre/Project.swift +++ b/mac/Sources/Byre/Project.swift @@ -14,14 +14,31 @@ struct ProjectView: View { @FocusState private var focused: Bool var body: some View { - ScrollView { - if let p = store.focusedProject() { - ProjectBlock(project: p, todo: todos[p.id]) - .padding(.horizontal, 16) - .padding(.top, 8) - .padding(.bottom, 16) - } else { - Muted(text: "No project selected.") + VStack(spacing: 0) { + if store.focusedProject() != nil { + HStack(spacing: 4) { + PaneTabButton(label: "Tasks", active: !overlays.projectSettings) { + overlays.projectSettings = false + } + PaneTabButton(label: "Settings", active: overlays.projectSettings) { + 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) @@ -136,53 +153,51 @@ private struct ProjectWorkflowMenu: View { private struct ProjectBlock: View { let project: Project let todo: Result? + let settings: Bool @Environment(Store.self) private var store @Environment(Overlays.self) private var overlays var body: some View { let active = (store.tasks[project.id] ?? []).filter { $0.status == .active } VStack(alignment: .leading, spacing: 0) { - HStack(alignment: .firstTextBaseline, spacing: 6) { - Text(project.name).font(Fonts.font(13, weight: 700)) - Text(project.defaultBranch).font(Fonts.font(11)).foregroundStyle(Palette.muted) - } - .padding(.top, 16) - .padding(.bottom, 6) - 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) - 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) + if settings { + 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) } } - .buttonStyle(WebButtonStyle()) - .help("Create a task in this project on a timer") + .font(Fonts.font(11)) + .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) }