macOS client parity review
This commit is contained in:
@@ -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 }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user