Skip to content

Commit 0d65c96

Browse files
authored
Merge pull request #22 from menubar-apps/10-commit-status
Support Commit Status
2 parents 6d568e7 + 05b3f67 commit 0d65c96

File tree

6 files changed

+337
-140
lines changed

6 files changed

+337
-140
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,32 @@
11
{
2-
"object": {
3-
"pins": [
4-
{
5-
"package": "Alamofire",
6-
"repositoryURL": "https://github.com/Alamofire/Alamofire",
7-
"state": {
8-
"branch": "master",
9-
"revision": "26b8c9a41aa03f0356f957ab62e9ca6b1068afe0",
10-
"version": null
11-
}
12-
},
13-
{
14-
"package": "Defaults",
15-
"repositoryURL": "https://github.com/sindresorhus/Defaults",
16-
"state": {
17-
"branch": "main",
18-
"revision": "5b30f01e46d25f7b59e37d6d96b2030d6c96ac87",
19-
"version": null
20-
}
21-
},
22-
{
23-
"package": "KeychainAccess",
24-
"repositoryURL": "https://github.com/kishikawakatsumi/KeychainAccess",
25-
"state": {
26-
"branch": null,
27-
"revision": "84e546727d66f1adc5439debad16270d0fdd04e7",
28-
"version": "4.2.2"
29-
}
2+
"pins" : [
3+
{
4+
"identity" : "alamofire",
5+
"kind" : "remoteSourceControl",
6+
"location" : "https://github.com/Alamofire/Alamofire",
7+
"state" : {
8+
"branch" : "master",
9+
"revision" : "26b8c9a41aa03f0356f957ab62e9ca6b1068afe0"
3010
}
31-
]
32-
},
33-
"version": 1
11+
},
12+
{
13+
"identity" : "defaults",
14+
"kind" : "remoteSourceControl",
15+
"location" : "https://github.com/sindresorhus/Defaults",
16+
"state" : {
17+
"branch" : "main",
18+
"revision" : "5b30f01e46d25f7b59e37d6d96b2030d6c96ac87"
19+
}
20+
},
21+
{
22+
"identity" : "keychainaccess",
23+
"kind" : "remoteSourceControl",
24+
"location" : "https://github.com/kishikawakatsumi/KeychainAccess",
25+
"state" : {
26+
"revision" : "84e546727d66f1adc5439debad16270d0fdd04e7",
27+
"version" : "4.2.2"
28+
}
29+
}
30+
],
31+
"version" : 2
3432
}

pullBar/AppDelegate.swift

+93-35
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,18 @@ class AppDelegate: NSObject, NSApplicationDelegate {
1919
@Default(.showRequested) var showRequested
2020

2121
@Default(.showAvatar) var showAvatar
22-
@Default(.showChecks) var showChecks
2322
@Default(.showLabels) var showLabels
2423

2524
@Default(.refreshRate) var refreshRate
25+
@Default(.buildType) var buildType
2626

2727
@Default(.githubUsername) var githubUsername
2828
@FromKeychain(.githubToken) var githubToken
29-
29+
3030
let ghClient = GitHubClient()
3131
var statusBarItem: NSStatusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
3232
let menu: NSMenu = NSMenu()
33-
33+
3434
var preferencesWindow: NSWindow!
3535
var aboutWindow: NSWindow!
3636

@@ -106,15 +106,15 @@ extension AppDelegate {
106106
group.leave()
107107
}
108108
}
109-
109+
110110
if showCreated {
111111
group.enter()
112112
ghClient.getCreatedPulls() { pulls in
113113
createdPulls?.append(contentsOf: pulls)
114114
group.leave()
115115
}
116116
}
117-
117+
118118
if showRequested {
119119
group.enter()
120120
ghClient.getReviewRequestedPulls() { pulls in
@@ -126,7 +126,7 @@ extension AppDelegate {
126126
group.notify(queue: .main) {
127127

128128
let isOneSelected = (self.showAssigned.intValue + self.showCreated.intValue + self.showRequested.intValue) == 1
129-
129+
130130

131131
if let assignedPulls = assignedPulls, let createdPulls = createdPulls, let reviewRequestedPulls = reviewRequestedPulls {
132132

@@ -150,9 +150,9 @@ extension AppDelegate {
150150
if isOneSelected {
151151
self.statusBarItem.button?.title = String(createdPulls.count)
152152
}
153-
153+
154154
}
155-
155+
156156
if self.showRequested && !reviewRequestedPulls.isEmpty {
157157
self.menu.addItem(NSMenuItem(title: "Review Requested (\(reviewRequestedPulls.count))", action: nil, keyEquivalent: ""))
158158
for pull in reviewRequestedPulls {
@@ -162,7 +162,7 @@ extension AppDelegate {
162162
if isOneSelected {
163163
self.statusBarItem.button?.title = String(reviewRequestedPulls.count)
164164
}
165-
165+
166166
}
167167

168168

@@ -174,21 +174,28 @@ extension AppDelegate {
174174
func createMenuItem(pull: Edge) -> NSMenuItem {
175175
let issueItem = NSMenuItem(title: "", action: #selector(self.openLink), keyEquivalent: "")
176176

177-
let issueItemTitle = NSMutableAttributedString(string: pull.node.title.trunc(length: 50))
177+
let issueItemTitle = NSMutableAttributedString(string: "")
178+
.appendString(string: pull.node.isReadByViewer ? "" : "", color: .systemBlue)
179+
180+
if (pull.node.isDraft) {
181+
issueItemTitle
182+
.appendIcon(iconName: "git-draft-pull-request", color: NSColor.secondaryLabelColor)
183+
}
184+
185+
issueItemTitle
186+
.appendString(string: pull.node.title.trunc(length: 50), color: NSColor(.primary))
178187
.appendString(string: " #" + String(pull.node.number))
179188
.appendSeparator()
180-
.appendIcon(iconName: pull.node.isDraft ? "git-draft-pull-request" : "git-pull-request", color: pull.node.isDraft ? NSColor.secondaryLabelColor : NSColor(named: "green")!)
181-
.appendString(string: pull.node.isDraft ? "Draft" : "Open", color: pull.node.isDraft ? NSColor.secondaryLabelColor : NSColor(named: "green")!)
182189

183190
issueItemTitle.appendNewLine()
184-
191+
185192
issueItemTitle
186193
.appendIcon(iconName: "repo")
187194
.appendString(string: pull.node.repository.name)
188195
.appendSeparator()
189196
.appendIcon(iconName: "person")
190197
.appendString(string: pull.node.author.login)
191-
198+
192199
if !pull.node.labels.nodes.isEmpty && self.showLabels {
193200
issueItemTitle
194201
.appendNewLine()
@@ -197,7 +204,7 @@ extension AppDelegate {
197204
issueItemTitle
198205
.appendString(string: label.name, color: hexColor(hex: label.color), fontSize: NSFont.smallSystemFontSize)
199206
.appendSeparator()
200-
}
207+
}
201208
}
202209

203210
issueItemTitle.appendNewLine()
@@ -212,7 +219,7 @@ extension AppDelegate {
212219
.appendSeparator()
213220
.appendIcon(iconName: "calendar")
214221
.appendString(string: pull.node.createdAt.getElapsedInterval())
215-
222+
216223
if showAvatar {
217224
var image = NSImage()
218225
if let imageURL = pull.node.author.avatarUrl {
@@ -229,39 +236,90 @@ extension AppDelegate {
229236

230237

231238
if let commits = pull.node.commits {
232-
if commits.nodes[0].commit.checkSuites.nodes.count > 0 {
233-
issueItem.submenu = NSMenu()
234-
issueItemTitle
235-
.appendSeparator()
236-
.appendIcon(iconName: "checklist", color: NSColor.secondaryLabelColor)
239+
240+
if let checkSuites = commits.nodes[0].commit.checkSuites {
241+
242+
if checkSuites.nodes.count > 0 {
243+
issueItem.submenu = NSMenu()
244+
issueItemTitle
245+
.appendSeparator()
246+
.appendIcon(iconName: "checklist", color: NSColor.secondaryLabelColor)
247+
}
248+
for checkSuite in checkSuites.nodes {
249+
250+
if checkSuite.checkRuns.nodes.count > 0 {
251+
issueItem.submenu?.addItem(withTitle: checkSuite.app?.name ?? "empty", action: nil, keyEquivalent: "")
252+
}
253+
for check in checkSuite.checkRuns.nodes {
254+
255+
let buildItem = NSMenuItem(title: check.name, action: #selector(self.openLink), keyEquivalent: "")
256+
buildItem.representedObject = check.detailsUrl
257+
buildItem.toolTip = check.conclusion
258+
if check.conclusion == "SUCCESS" {
259+
buildItem.image = NSImage(named: "check-circle-fill")!.tint(color: NSColor(named: "green")!)
260+
issueItemTitle.appendIcon(iconName: "dot-fill", color: NSColor(named: "green")!)
261+
} else if check.conclusion == "FAILURE" {
262+
buildItem.image = NSImage(named: "x-circle-fill")!.tint(color: NSColor(named: "red")!)
263+
issueItemTitle.appendIcon(iconName: "dot-fill", color: NSColor(named: "red")!)
264+
} else if check.conclusion == "ACTION_REQUIRED" {
265+
buildItem.image = NSImage(named: "issue-draft")!.tint(color: NSColor(named: "yellow")!)
266+
issueItemTitle.appendIcon(iconName: "dot-fill", color: NSColor(named: "yellow")!)
267+
} else {
268+
buildItem.image = NSImage(named: "question")!.tint(color: NSColor.gray)
269+
issueItemTitle.appendIcon(iconName: "dot-fill", color: NSColor.gray)
270+
}
271+
272+
issueItem.submenu?.addItem(buildItem)
273+
}
274+
}
237275
}
238-
for checkSuite in commits.nodes[0].commit.checkSuites.nodes {
276+
277+
else if let statusCheckRollup = commits.nodes[0].commit.statusCheckRollup {
239278

240-
if checkSuite.checkRuns.nodes.count > 0 {
241-
issueItem.submenu?.addItem(withTitle: checkSuite.app?.name ?? "empty", action: nil, keyEquivalent: "")
279+
if statusCheckRollup.contexts.nodes.count > 0 {
280+
issueItem.submenu = NSMenu()
281+
issueItemTitle
282+
.appendSeparator()
283+
.appendIcon(iconName: "checklist", color: NSColor.secondaryLabelColor)
242284
}
243-
for check in checkSuite.checkRuns.nodes {
285+
286+
for check in statusCheckRollup.contexts.nodes {
287+
let itemTitle = NSMutableAttributedString()
288+
itemTitle.appendString(string: check.name ?? check.context ?? "<empty>", color: NSColor(.primary))
289+
itemTitle.appendNewLine()
290+
.appendString(string: check.description ?? check.title ?? "<empty>", color: NSColor(.secondary))
291+
292+
let buildItem = NSMenuItem(title: "", action: #selector(AppDelegate.openLink), keyEquivalent: "")
293+
buildItem.attributedTitle = itemTitle
294+
295+
buildItem.representedObject = check.detailsUrl ?? URL.init(string:check.targetUrl ?? "")
244296

245-
let buildItem = NSMenuItem(title: check.name, action: #selector(self.openLink), keyEquivalent: "")
246-
buildItem.representedObject = check.detailsUrl
247-
buildItem.toolTip = check.conclusion
248-
if check.conclusion == "SUCCESS" {
297+
buildItem.toolTip = check.conclusion ?? check.state ?? ""
298+
299+
let status = check.conclusion ?? check.state ?? ""
300+
switch status {
301+
case "SUCCESS":
249302
buildItem.image = NSImage(named: "check-circle-fill")!.tint(color: NSColor(named: "green")!)
250303
issueItemTitle.appendIcon(iconName: "dot-fill", color: NSColor(named: "green")!)
251-
} else if check.conclusion == "FAILURE" {
304+
case "FAILURE":
252305
buildItem.image = NSImage(named: "x-circle-fill")!.tint(color: NSColor(named: "red")!)
253306
issueItemTitle.appendIcon(iconName: "dot-fill", color: NSColor(named: "red")!)
254-
} else if check.conclusion == "ACTION_REQUIRED" {
307+
case "PENDING":
255308
buildItem.image = NSImage(named: "issue-draft")!.tint(color: NSColor(named: "yellow")!)
256309
issueItemTitle.appendIcon(iconName: "dot-fill", color: NSColor(named: "yellow")!)
257-
} else {
310+
default:
258311
buildItem.image = NSImage(named: "question")!.tint(color: NSColor.gray)
259312
issueItemTitle.appendIcon(iconName: "dot-fill", color: NSColor.gray)
313+
260314
}
261315

262316
issueItem.submenu?.addItem(buildItem)
263317
}
318+
319+
320+
264321
}
322+
265323
}
266324

267325
issueItem.attributedTitle = issueItemTitle
@@ -289,7 +347,7 @@ extension AppDelegate {
289347
preferencesWindow.close()
290348
}
291349
preferencesWindow = NSWindow(
292-
contentRect: NSRect(x: 0, y: 0, width: 500, height: 400),
350+
contentRect: NSRect(x: 0, y: 0, width: 500, height: 500),
293351
styleMask: [.closable, .titled],
294352
backing: .buffered,
295353
defer: false
@@ -299,7 +357,7 @@ extension AppDelegate {
299357
preferencesWindow.contentView = NSHostingView(rootView: contentView)
300358
preferencesWindow.makeKeyAndOrderFront(nil)
301359
preferencesWindow.styleMask.remove(.resizable)
302-
360+
303361
// allow the preference window can be focused automatically when opened
304362
NSApplication.shared.activate(ignoringOtherApps: true)
305363

@@ -328,7 +386,7 @@ extension AppDelegate {
328386
aboutWindow.contentView = NSHostingView(rootView: contentView)
329387
aboutWindow.makeKeyAndOrderFront(nil)
330388
aboutWindow.styleMask.remove(.resizable)
331-
389+
332390
// allow the preference window can be focused automatically when opened
333391
NSApplication.shared.activate(ignoringOtherApps: true)
334392

pullBar/Extensions/DefaultsExtensions.swift

+21-1
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,32 @@ extension Defaults.Keys {
1616
static let showRequested = Key<Bool>("showRequested", default: true)
1717

1818
static let showAvatar = Key<Bool>("showAvatar", default: false)
19-
static let showChecks = Key<Bool>("showChecks", default: true)
2019
static let showLabels = Key<Bool>("showLabels", default: true)
2120

2221
static let refreshRate = Key<Int>("refreshRate", default: 5)
22+
static let buildType = Key<BuildType>("buildType", default: .none)
2323
}
2424

2525
extension KeychainKeys {
2626
static let githubToken: KeychainAccessKey = KeychainAccessKey(key: "githubToken")
2727
}
28+
29+
enum BuildType: String, Defaults.Serializable, CaseIterable, Identifiable {
30+
case checks
31+
case commitStatus
32+
case none
33+
34+
var id: Self { self }
35+
36+
var description: String {
37+
38+
switch self {
39+
case .checks:
40+
return "checks"
41+
case .commitStatus:
42+
return "commit statuses"
43+
case .none:
44+
return "none"
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)