Skip to content

Commit 32035f5

Browse files
committed
Add avatar CommitListItemView and other fixes
1 parent 679ead2 commit 32035f5

File tree

5 files changed

+113
-3
lines changed

5 files changed

+113
-3
lines changed

CodeEdit/Features/Git/Client/GitClient+CommitHistory.swift

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ extension GitClient {
3131
dateFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss Z"
3232

3333
let output = try await run(
34-
"log --pretty=%h¦%H¦%s¦%aN¦%ae¦%cn¦%ce¦%aD¦ \(maxCountString) \(branchNameString) \(fileLocalPath)"
34+
"log --pretty=%h¦%H¦%s¦%aN¦%ae¦%cn¦%ce¦%aD¦%b¦%D¦ \(maxCountString) \(branchNameString) \(fileLocalPath)"
3535
.trimmingCharacters(in: .whitespacesAndNewlines)
3636
)
3737
let remote = try await run("ls-remote --get-url")
@@ -41,6 +41,20 @@ extension GitClient {
4141
.split(separator: "\n")
4242
.map { line -> GitCommit in
4343
let parameters = line.components(separatedBy: "¦")
44+
let infoRef = parameters[safe: 9]
45+
46+
var ref = ""
47+
var tag = ""
48+
49+
if let infoRef = infoRef {
50+
if infoRef.contains("tag:") {
51+
tag = infoRef.components(separatedBy: "tag:")[1].trimmingCharacters(in: .whitespaces)
52+
} else {
53+
let refs = infoRef.split(separator: ",")
54+
ref = refs.count > 1 ? String(refs[1]).trimmingCharacters(in: .whitespaces) : ""
55+
}
56+
}
57+
4458
return GitCommit(
4559
hash: parameters[safe: 0] ?? "",
4660
commitHash: parameters[safe: 1] ?? "",
@@ -49,6 +63,9 @@ extension GitClient {
4963
authorEmail: parameters[safe: 4] ?? "",
5064
committer: parameters[safe: 5] ?? "",
5165
committerEmail: parameters[safe: 6] ?? "",
66+
body: parameters[safe: 8] ?? "",
67+
ref: ref,
68+
tag: tag,
5269
remoteURL: remoteURL,
5370
date: dateFormatter.date(from: parameters[safe: 7] ?? "") ?? Date()
5471
)

CodeEdit/Features/Git/Client/Models/GitCommit.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ struct GitCommit: Equatable, Hashable, Identifiable {
1717
let authorEmail: String
1818
let committer: String
1919
let committerEmail: String
20+
let body: String
21+
let ref: String
22+
let tag: String
2023
let remoteURL: URL?
2124
let date: Date
2225

CodeEdit/Features/NavigatorArea/SourceControlNavigator/History/Views/CommitDetailsHeaderView.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,20 @@ struct CommitDetailsHeaderView: View {
9898
)
9999
.padding(.horizontal, 2.5)
100100
}
101+
.padding(.horizontal, 16)
102+
103+
Divider()
104+
101105
Text(commitDetails())
106+
.fontWeight(.bold)
107+
.padding(.horizontal, 16)
102108
.frame(alignment: .leading)
109+
110+
if !commit.body.isEmpty {
111+
Text(commit.body)
112+
.padding(.horizontal, 16)
113+
.frame(alignment: .leading)
114+
}
103115
}
104116
}
105117
}

CodeEdit/Features/NavigatorArea/SourceControlNavigator/History/Views/CommitDetailsView.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ struct CommitDetailsView: View {
4141

4242
if let commit = commit {
4343
CommitDetailsHeaderView(commit: commit)
44-
.padding(.horizontal, 16)
4544
.padding(.vertical, 16)
4645
Divider()
4746

CodeEdit/Features/NavigatorArea/SourceControlNavigator/History/Views/CommitListItemView.swift

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,38 @@ import SwiftUI
1010
struct CommitListItemView: View {
1111

1212
var commit: GitCommit
13+
14+
private var defaultAvatar: some View {
15+
Image(systemName: "person.crop.circle.fill")
16+
.symbolRenderingMode(.hierarchical)
17+
.resizable()
18+
.foregroundColor(avatarColor)
19+
.frame(width: 32, height: 32)
20+
}
21+
22+
private func generateAvatarHash() -> String {
23+
let hash = commit.authorEmail.md5(trim: true, caseSensitive: false)
24+
return "\(hash)?d=404&s=64" // send 404 if no image available, image size 64x64 (32x32 @2x)
25+
}
26+
27+
private var avatarColor: Color {
28+
let hash = generateAvatarHash().hash
29+
switch hash % 12 {
30+
case 0: return .red
31+
case 1: return .orange
32+
case 2: return .yellow
33+
case 3: return .green
34+
case 4: return .mint
35+
case 5: return .teal
36+
case 6: return .cyan
37+
case 7: return .blue
38+
case 8: return .indigo
39+
case 9: return .purple
40+
case 10: return .brown
41+
case 11: return .pink
42+
default: return .teal
43+
}
44+
}
1345

1446
@Environment(\.openURL)
1547
private var openCommit
@@ -20,11 +52,58 @@ struct CommitListItemView: View {
2052

2153
var body: some View {
2254
HStack(alignment: .top) {
55+
AsyncImage(url: URL(string: "https://www.gravatar.com/avatar/\(generateAvatarHash())")) { phase in
56+
if let image = phase.image {
57+
image
58+
.resizable()
59+
.clipShape(Circle())
60+
.frame(width: 32, height: 32)
61+
} else if phase.error != nil {
62+
defaultAvatar
63+
} else {
64+
defaultAvatar
65+
}
66+
}
2367
VStack(alignment: .leading, spacing: 0) {
2468
Text(commit.author)
2569
.fontWeight(.bold)
2670
.font(.system(size: 11))
27-
Text(commit.message)
71+
72+
if !commit.ref.isEmpty {
73+
HStack {
74+
Image.branch
75+
.imageScale(.small)
76+
.foregroundColor(.primary)
77+
Text(commit.ref)
78+
.font(.system(size: 10, design: .monospaced))
79+
}
80+
.background(
81+
RoundedRectangle(cornerRadius: 3)
82+
.padding(.vertical, -1)
83+
.padding(.horizontal, -2.5)
84+
.foregroundColor(Color(nsColor: .quaternaryLabelColor))
85+
)
86+
.padding(.trailing, 2.5)
87+
}
88+
89+
if !commit.tag.isEmpty {
90+
HStack {
91+
Image.breakpoint
92+
.imageScale(.small)
93+
.foregroundColor(.primary)
94+
Text(commit.tag)
95+
.font(.system(size: 10, design: .monospaced))
96+
}
97+
.background(
98+
RoundedRectangle(cornerRadius: 3)
99+
.padding(.vertical, -1)
100+
.padding(.horizontal, -2.5)
101+
.foregroundColor(Color(nsColor: .selectedContentBackgroundColor))
102+
)
103+
.padding(.trailing, 2.5)
104+
}
105+
106+
Text("\(commit.message) \(commit.body)")
28107
.font(.system(size: 11))
29108
.lineLimit(2)
30109
}

0 commit comments

Comments
 (0)