Skip to content

Commit ec6d57f

Browse files
committed
re-order menu items
1 parent 4c7d9b2 commit ec6d57f

2 files changed

Lines changed: 53 additions & 28 deletions

File tree

Sources/AgentTally/Presentation/MenuRowsBuilder.swift

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ public enum MenuRowsBuilder {
3232
if !rows.isEmpty {
3333
rows.append(.separator)
3434
}
35+
rows.append(contentsOf: refreshRows(for: state, now: now))
36+
rows.append(.separator)
3537
rows.append(
3638
contentsOf: appRows(
37-
for: state,
3839
startAtLogin: startAtLogin,
3940
softwareUpdate: softwareUpdate,
40-
appVersion: appVersion,
41-
now: now
41+
appVersion: appVersion
4242
)
4343
)
4444

@@ -103,11 +103,9 @@ public enum MenuRowsBuilder {
103103
}
104104

105105
private static func appRows(
106-
for state: AppState,
107106
startAtLogin: StartAtLoginViewState,
108107
softwareUpdate: SoftwareUpdateViewState,
109-
appVersion: String?,
110-
now: Date
108+
appVersion: String?
111109
) -> [MenuRow] {
112110
var rows: [MenuRow] = [
113111
.disabled(headerTitle(appVersion: appVersion))
@@ -122,15 +120,6 @@ public enum MenuRowsBuilder {
122120
)
123121
)
124122

125-
rows.append(
126-
.disabled("Last refreshed: \(StatusPresenter.lastRefreshedLabel(for: state, now: now))"))
127-
128-
if state.isRefreshing {
129-
rows.append(.disabled("Refreshing ..."))
130-
} else {
131-
rows.append(.action(title: "Refresh", kind: .refresh, keyEquivalent: "", state: .off))
132-
}
133-
134123
rows.append(
135124
.action(
136125
title: "Open at Login",
@@ -149,6 +138,20 @@ public enum MenuRowsBuilder {
149138
return rows
150139
}
151140

141+
private static func refreshRows(for state: AppState, now: Date) -> [MenuRow] {
142+
var rows: [MenuRow] = [
143+
.disabled("Last refreshed: \(StatusPresenter.lastRefreshedLabel(for: state, now: now))")
144+
]
145+
146+
if state.isRefreshing {
147+
rows.append(.disabled("Refreshing ..."))
148+
} else {
149+
rows.append(.action(title: "Refresh", kind: .refresh, keyEquivalent: "", state: .off))
150+
}
151+
152+
return rows
153+
}
154+
152155
private static func headerTitle(appVersion: String?) -> String {
153156
guard let appVersion = appVersion?.trimmingCharacters(in: .whitespacesAndNewlines),
154157
!appVersion.isEmpty

Tests/MenuRowsHarness.swift

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,36 @@ func testMenuRowsBuilder() throws {
4646
)
4747
try expect(
4848
rows[headerIndex - 1] == .separator,
49-
"spending sections should be separated from the bottom app section"
49+
"refresh rows should be separated from the app controls section"
50+
)
51+
let lastRefreshedIndex = rows.firstIndex { row in
52+
if case .disabled(let label) = row {
53+
return label.hasPrefix("Last refreshed:")
54+
}
55+
return false
56+
}
57+
guard let lastRefreshedIndex else {
58+
throw TestFailure(description: "menu should include a last refreshed row")
59+
}
60+
try expect(
61+
rows[lastRefreshedIndex - 1] == .separator,
62+
"spending sections should be separated from refresh rows"
63+
)
64+
if case .disabled(let label) = rows[lastRefreshedIndex] {
65+
try expect(
66+
label.hasPrefix("Last refreshed:"), "last refreshed should lead the refresh section")
67+
} else {
68+
throw TestFailure(
69+
description: "first row in the refresh section should be 'Last refreshed:'")
70+
}
71+
try expect(
72+
rows[lastRefreshedIndex + 1]
73+
== .action(title: "Refresh", kind: .refresh, keyEquivalent: "", state: .off),
74+
"refresh action should appear below the last refreshed row"
75+
)
76+
try expect(
77+
rows[lastRefreshedIndex + 2] == .separator,
78+
"refresh rows should be separated from app controls"
5079
)
5180
try expect(
5281
rows[headerIndex + 1]
@@ -56,15 +85,8 @@ func testMenuRowsBuilder() throws {
5685
keyEquivalent: "",
5786
state: .off
5887
),
59-
"first row in the bottom app section should be update action"
88+
"update action should appear directly below the version row"
6089
)
61-
if case .disabled(let label) = rows[headerIndex + 2] {
62-
try expect(
63-
label.hasPrefix("Last refreshed:"), "last refreshed should appear below the update action")
64-
} else {
65-
throw TestFailure(
66-
description: "row after update action should be 'Last refreshed:' disabled item")
67-
}
6890
try expect(
6991
rows.contains(.disabled("Today: $49")),
7092
"today cost should round up to the next display dollar"
@@ -144,15 +166,15 @@ func testMenuRowsBuilder() throws {
144166
appVersion: "0.7",
145167
now: now
146168
)
169+
let updateAvailableHeaderIndex = updateAvailableRows.firstIndex(of: .disabled("AgentTally v0.7"))!
147170
try expect(
148-
updateAvailableRows.prefix(2).contains(
149-
.action(
171+
updateAvailableRows[updateAvailableHeaderIndex + 1]
172+
== .action(
150173
title: "Update Available: v0.8...",
151174
kind: .checkForUpdates,
152175
keyEquivalent: "",
153176
state: .off
154-
)
155-
),
177+
),
156178
"available updates should be visible directly below the header"
157179
)
158180
try expect(

0 commit comments

Comments
 (0)