Fix ⌘F focus, hung-turn Stop, narrow tabs and other QA findings
This commit is contained in:
@@ -652,8 +652,8 @@ private struct DiffLineRow: View {
|
||||
}
|
||||
.padding(.horizontal, 10)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.background(row.kind.background)
|
||||
.background(hover ? Palette.accent.opacity(0.08) : .clear)
|
||||
.background(row.kind.background, in: Rectangle())
|
||||
.background(hover ? Palette.accent.opacity(0.08) : .clear, in: Rectangle())
|
||||
.overlay(alignment: .leading) {
|
||||
if mark {
|
||||
Rectangle().fill(Palette.accent).frame(width: 3)
|
||||
|
||||
@@ -101,6 +101,10 @@ struct FilterField: View {
|
||||
var body: some View {
|
||||
TextField(placeholder, text: $text)
|
||||
.modifier(FieldStyle(focused: focused))
|
||||
#if os(iOS)
|
||||
.textInputAutocapitalization(.never)
|
||||
#endif
|
||||
.autocorrectionDisabled()
|
||||
.focused($focused)
|
||||
.onChange(of: focusSignal, initial: true) { old, new in
|
||||
if new != 0 && (old != new || !focused) {
|
||||
|
||||
@@ -117,29 +117,9 @@ private struct LeftPane: View {
|
||||
let tab = overlays.leftTab
|
||||
VStack(spacing: 0) {
|
||||
HStack(spacing: 4) {
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack(spacing: 4) {
|
||||
PaneTabButton(label: "Lead", active: tab == .lead) {
|
||||
pick(.lead)
|
||||
}
|
||||
PaneTabButton(label: "Status", active: tab == .status) {
|
||||
pick(.status)
|
||||
}
|
||||
PaneTabButton(label: "Notes", active: tab == .notes) {
|
||||
pick(.notes)
|
||||
}
|
||||
PaneTabButton(label: "Workflows", active: tab == .workflows) {
|
||||
pick(.workflows)
|
||||
}
|
||||
PaneTabButton(label: "Server", active: tab == .server) {
|
||||
pick(.server)
|
||||
}
|
||||
PaneTabButton(label: "Settings", active: tab == .settings) {
|
||||
pick(.settings)
|
||||
}
|
||||
}
|
||||
FoldingTabs(tabs: [(.lead, "Lead"), (.status, "Status"), (.notes, "Notes"), (.workflows, "Workflows"), (.server, "Server"), (.settings, "Settings")], active: tab) { t in
|
||||
pick(t)
|
||||
}
|
||||
.scrollBounceBehavior(.basedOnSize, axes: .horizontal)
|
||||
HStack(spacing: 10) {
|
||||
if !store.connected {
|
||||
Text("reconnecting…")
|
||||
@@ -411,12 +391,6 @@ private struct PreviewLink: View {
|
||||
|
||||
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
|
||||
@ViewState private var moreFrame: CGRect = .zero
|
||||
|
||||
private struct Info {
|
||||
var order: [TaskTab]
|
||||
@@ -448,19 +422,41 @@ struct TabStrip: View {
|
||||
return Info(order: order, tab: tab)
|
||||
}
|
||||
|
||||
private func kept(_ info: Info) -> [TaskTab] {
|
||||
let gap: CGFloat = 4
|
||||
let inner = stripWidth - 24
|
||||
func total(_ ts: [TaskTab]) -> CGFloat {
|
||||
ts.reduce(0) { $0 + (widths[$1] ?? 0) + gap }
|
||||
var body: some View {
|
||||
let info = info()
|
||||
FoldingTabs(tabs: info.order.map { ($0, tabLabels[$0]!) }, active: info.tab) { t in
|
||||
store.openTab(t)
|
||||
}
|
||||
let all = info.order
|
||||
if stripWidth == 0 || total(all) <= inner {
|
||||
.padding(.horizontal, 12)
|
||||
.overlay(alignment: .bottom) {
|
||||
Rectangle().fill(Palette.border).frame(height: 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct FoldingTabs<ID: Hashable>: View {
|
||||
let tabs: [(id: ID, label: String)]
|
||||
let active: ID
|
||||
let pick: (ID) -> Void
|
||||
@Environment(Overlays.self) private var overlays
|
||||
@Environment(\.paneAccent) private var accent
|
||||
@ViewState private var widths: [ID: CGFloat] = [:]
|
||||
@ViewState private var moreWidth: CGFloat = 0
|
||||
@ViewState private var stripWidth: CGFloat = 0
|
||||
@ViewState private var moreFrame: CGRect = .zero
|
||||
|
||||
private func kept() -> [ID] {
|
||||
let gap: CGFloat = 4
|
||||
func total(_ ids: [ID]) -> CGFloat {
|
||||
ids.reduce(0) { $0 + (widths[$1] ?? 0) + gap }
|
||||
}
|
||||
let all = tabs.map(\.id)
|
||||
if stripWidth == 0 || total(all) <= stripWidth {
|
||||
return all
|
||||
}
|
||||
let budget = inner - moreWidth - gap
|
||||
var kept: [TaskTab] = []
|
||||
for t in [info.tab] + all.filter({ $0 != info.tab }) {
|
||||
let budget = stripWidth - moreWidth - gap
|
||||
var kept: [ID] = []
|
||||
for t in [active] + all.filter({ $0 != active }) {
|
||||
if !kept.isEmpty && total(kept + [t]) > budget {
|
||||
break
|
||||
}
|
||||
@@ -470,20 +466,19 @@ struct TabStrip: View {
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
let info = info()
|
||||
let kept = kept(info)
|
||||
let hidden = info.order.filter { !kept.contains($0) }
|
||||
let kept = kept()
|
||||
let hidden = tabs.filter { !kept.contains($0.id) }
|
||||
HStack(spacing: 4) {
|
||||
ForEach(info.order.filter { kept.contains($0) }, id: \.self) { t in
|
||||
PaneTabButton(label: tabLabels[t]!, active: t == info.tab) {
|
||||
store.openTab(t)
|
||||
ForEach(tabs.filter { kept.contains($0.id) }, id: \.id) { t in
|
||||
PaneTabButton(label: t.label, active: t.id == active) {
|
||||
pick(t.id)
|
||||
}
|
||||
}
|
||||
if !hidden.isEmpty {
|
||||
MoreButton {
|
||||
overlays.menu = OverlayMenu(anchor: moreFrame, accent: accent, entries: hidden.map { t in
|
||||
MenuEntry(id: t.rawValue, label: tabLabels[t]!) {
|
||||
store.openTab(t)
|
||||
MenuEntry(id: t.label, label: t.label) {
|
||||
pick(t.id)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -495,17 +490,16 @@ struct TabStrip: View {
|
||||
}
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
.padding(.horizontal, 12)
|
||||
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
|
||||
.clipped()
|
||||
.background {
|
||||
HStack(spacing: 4) {
|
||||
ForEach(info.order, id: \.self) { t in
|
||||
PaneTabButton(label: tabLabels[t]!, active: t == info.tab) {}
|
||||
ForEach(tabs, id: \.id) { t in
|
||||
PaneTabButton(label: t.label, active: t.id == active) {}
|
||||
.onGeometryChange(for: CGFloat.self) { g in
|
||||
g.size.width
|
||||
} action: { w in
|
||||
widths[t] = w
|
||||
widths[t.id] = w
|
||||
}
|
||||
}
|
||||
MoreButton {}
|
||||
@@ -523,9 +517,6 @@ struct TabStrip: View {
|
||||
} action: { w in
|
||||
stripWidth = w
|
||||
}
|
||||
.overlay(alignment: .bottom) {
|
||||
Rectangle().fill(Palette.border).frame(height: 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ private struct ServerColorPicker: View {
|
||||
var body: some View {
|
||||
let origin = store.api.origin.absoluteString
|
||||
let current = Servers.shared.record(origin)?.color
|
||||
HStack(spacing: 4) {
|
||||
FlowLayout(spacing: 4) {
|
||||
ForEach(taskPalette.indices, id: \.self) { i in
|
||||
Button {
|
||||
Servers.shared.setColor(origin, i)
|
||||
|
||||
@@ -99,6 +99,11 @@ final class Servers {
|
||||
connections[origin] = nil
|
||||
Task {
|
||||
await connection.stop()
|
||||
let scope = draftOrigin(parseOrigin(origin)!) + "."
|
||||
for record in fetchRecords(FetchDescriptor<DraftRecord>()) where record.scope.hasPrefix(scope) {
|
||||
persistence.delete(record)
|
||||
}
|
||||
saveRecords()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,9 +46,7 @@ func runGo(_ key: String, _ store: Store, _ overlays: Overlays) {
|
||||
}
|
||||
case "f":
|
||||
overlays.switcher?.close()
|
||||
if store.paneFocus.inTaskPane {
|
||||
overlays.filterTodo += 1
|
||||
}
|
||||
overlays.filterTodo += 1
|
||||
case "/":
|
||||
overlays.showAlert(ShortcutsHelp())
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user