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
+39 -16
View File
@@ -4,7 +4,7 @@ import SwiftUI
enum TabBadge {
case none
case count(Int)
case count(Int, String)
case spinner
}
@@ -16,8 +16,9 @@ struct TabBadgeView: View {
switch badge {
case .none:
EmptyView()
case .count(let n):
case .count(let n, let help):
Badge(count: n)
.help(help)
case .spinner:
Spinner(color: accent)
.help("review in progress")
@@ -109,7 +110,7 @@ struct PaneTabButton: View {
TabBadgeView(badge: badge)
}
.font(Fonts.font(13, weight: attention ? 700 : 400))
.foregroundStyle(attention ? Palette.warn : active || hover ? Palette.text : Palette.muted)
.foregroundStyle(hover ? Palette.text : attention ? Palette.warn : active ? Palette.text : Palette.muted)
.padding(.horizontal, 10)
.padding(.top, 8)
.padding(.bottom, 6)
@@ -149,6 +150,7 @@ private struct LeftPane: View {
if !store.connected {
Text("reconnecting…")
.foregroundStyle(Palette.danger)
.fixedSize()
}
Circle()
.fill(store.connected ? Palette.ok : Palette.danger)
@@ -156,9 +158,9 @@ private struct LeftPane: View {
.help(store.connected ? "live" : "reconnecting")
Text(store.me?.displayName ?? "")
.foregroundStyle(Palette.muted)
.truncationMode(.tail)
}
.lineLimit(1)
.fixedSize()
}
.padding(.horizontal, 12)
.overlay(alignment: .bottom) {
@@ -280,12 +282,7 @@ private struct TaskBar: View {
HStack(spacing: 12) {
Spacer(minLength: 0)
ForEach(previews, id: \.port) { p in
Link(destination: previewURL(store.api.origin, p.port)) {
Text("\(p.name) ↗")
.foregroundStyle(accent)
.lineLimit(1)
}
.help("Open \(p.name) (port \(p.port)) in a new window")
PreviewLink(preview: p, url: previewURL(store.api.origin, p.port))
}
}
.frame(maxWidth: .infinity)
@@ -340,9 +337,28 @@ private struct TaskBar: View {
}
}
private struct PreviewLink: View {
let preview: Components.Schemas.Preview
let url: URL
@Environment(\.paneAccent) private var accent
@ViewState private var hover = false
var body: some View {
Link(destination: url) {
Text("\(preview.name) ↗")
.foregroundStyle(accent)
.underline(hover)
.lineLimit(1)
}
.help("Open \(preview.name) (port \(preview.port)) in a new window")
.onHover { hover = $0 }
}
}
private struct TabStrip: View {
@Environment(Store.self) private var store
@Environment(Overlays.self) private var overlays
@Environment(\.paneAccent) private var accent
@ViewState private var widths: [TaskTab: CGFloat] = [:]
@ViewState private var moreWidth: CGFloat = 0
@ViewState private var stripWidth: CGFloat = 0
@@ -363,7 +379,7 @@ private struct TabStrip: View {
if t == .reviews && reviewing {
return .spinner
}
return count(t) > 0 ? .count(count(t)) : .none
return count(t) > 0 ? .count(count(t), t == .inbox ? "inbox items" : "open findings in the latest review") : .none
}
}
@@ -427,8 +443,8 @@ private struct TabStrip: View {
}
}
if !hidden.isEmpty {
moreButton(flagged.map(info.badge)) {
overlays.menu = OverlayMenu(anchor: moreFrame, entries: hidden.map { t in
MoreButton(badges: flagged.map(info.badge)) {
overlays.menu = OverlayMenu(anchor: moreFrame, accent: accent, entries: hidden.map { t in
MenuEntry(id: t.rawValue, label: tabLabels[t]!, badge: info.badge(t)) {
store.focusTab(t)
}
@@ -455,7 +471,7 @@ private struct TabStrip: View {
widths[t] = w
}
}
moreButton([]) {}
MoreButton(badges: []) {}
.onGeometryChange(for: CGFloat.self) { g in
g.size.width
} action: { w in
@@ -474,8 +490,14 @@ private struct TabStrip: View {
Rectangle().fill(Palette.border).frame(height: 1)
}
}
}
private func moreButton(_ badges: [TabBadge], _ action: @escaping () -> Void) -> some View {
private struct MoreButton: View {
let badges: [TabBadge]
let action: () -> Void
@ViewState private var hover = false
var body: some View {
Button(action: action) {
HStack(spacing: 6) {
Text("More ▾")
@@ -484,7 +506,7 @@ private struct TabStrip: View {
}
}
.font(Fonts.font(13, weight: badges.isEmpty ? 400 : 700))
.foregroundStyle(badges.isEmpty ? Palette.muted : Palette.warn)
.foregroundStyle(hover ? Palette.text : badges.isEmpty ? Palette.muted : Palette.warn)
.padding(.horizontal, 10)
.padding(.top, 8)
.padding(.bottom, 6)
@@ -497,6 +519,7 @@ private struct TabStrip: View {
.buttonStyle(.plain)
.fixedSize()
.help("More tabs")
.onHover { hover = $0 }
}
}