Skip to content

Commit a7e92be

Browse files
committed
More work on timeline rendering
1 parent 5837b02 commit a7e92be

6 files changed

Lines changed: 72 additions & 32 deletions

File tree

app/Sauron/UI/Event.hs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ getEventIcon eventType = case eventType of
4646
HeadRefForcePushed -> ""
4747
HeadRefRestored -> ""
4848
CrossReferenced -> "&"
49-
Committed -> ""
50-
Reviewed -> ""
5149
Unknown _ -> "?"
5250

5351
-- | Get a colored icon widget for an event type using GitHub's color scheme
@@ -91,8 +89,6 @@ getEventColorAttr eventType = case eventType of
9189
HeadRefForcePushed -> eventRefDeletedColor
9290
HeadRefRestored -> eventRefRestoredColor
9391
CrossReferenced -> eventReferencedColor
94-
Committed -> eventReferencedColor
95-
Reviewed -> eventReviewColor
9692
Unknown _ -> eventRefRestoredColor
9793

9894
getEventDescription :: EventType -> String
@@ -130,6 +126,4 @@ getEventDescription eventType = case eventType of
130126
HeadRefForcePushed -> "force-pushed the head branch"
131127
HeadRefRestored -> "restored the head branch"
132128
CrossReferenced -> "referenced this"
133-
Committed -> "added a commit"
134-
Reviewed -> "reviewed this"
135129
Unknown t -> [i|#{t} (unknown event type)|]

app/Sauron/UI/Issue.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ renderItemWithBorder now isLast borderFunc item =
183183
case item of
184184
SingleItem (TimelineComment comment) -> renderComment now borderFunc comment
185185
SingleItem (TimelineIssueEvent event) -> renderEvent now isLast event
186+
SingleItem (TimelineCommit commit) -> renderCommitEvent now isLast commit
187+
SingleItem (TimelineReview review) -> renderReviewEvent now isLast review
186188
LabelGroup rep added removed -> renderLabelGroup now isLast rep added removed
187189
ReviewRequestGroup rep events -> renderReviewRequestGroup now isLast rep events
188190

app/Sauron/UI/Issue/Events.hs

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ module Sauron.UI.Issue.Events (
77

88
-- * Rendering
99
, renderEvent
10+
, renderCommitEvent
11+
, renderReviewEvent
1012
, renderLabelGroup
1113
, labelPill
1214

@@ -65,12 +67,14 @@ adaptiveWidth f = Widget Greedy Fixed $ do
6567
consolidateEvents :: [TimelineEvent] -> [TimelineItem]
6668
consolidateEvents [] = []
6769
consolidateEvents (TimelineComment c : rest) = SingleItem (TimelineComment c) : consolidateEvents rest
70+
consolidateEvents (TimelineCommit c : rest) = SingleItem (TimelineCommit c) : consolidateEvents rest
71+
consolidateEvents (TimelineReview r : rest) = SingleItem (TimelineReview r) : consolidateEvents rest
6872
consolidateEvents (TimelineIssueEvent e : rest)
6973
| isLabelEvent e =
7074
let (run, remaining) = span (isMatchingEvent isLabelEvent e) rest
7175
events = e : [ev | TimelineIssueEvent ev <- run]
72-
added = filter (\ev -> issueEventType ev == Labeled) events
73-
removed = filter (\ev -> issueEventType ev == Unlabeled) events
76+
added = filter (\ev -> issueEventEvent ev == Labeled) events
77+
removed = filter (\ev -> issueEventEvent ev == Unlabeled) events
7478
in if length events > 1
7579
then LabelGroup e added removed : consolidateEvents remaining
7680
else SingleItem (TimelineIssueEvent e) : consolidateEvents rest
@@ -90,10 +94,10 @@ isMatchingEvent predicate ref (TimelineIssueEvent ev) =
9094
isMatchingEvent _ _ _ = False
9195

9296
isLabelEvent :: IssueEvent -> Bool
93-
isLabelEvent e = issueEventType e `elem` [Labeled, Unlabeled]
97+
isLabelEvent e = issueEventEvent e `elem` [Labeled, Unlabeled]
9498

9599
isReviewRequestEvent :: IssueEvent -> Bool
96-
isReviewRequestEvent e = issueEventType e == ReviewRequested
100+
isReviewRequestEvent e = issueEventEvent e == ReviewRequested
97101

98102

99103
-- * Rendering
@@ -102,10 +106,10 @@ renderEvent :: UTCTime -> Bool -> IssueEvent -> Widget n
102106
renderEvent now isLast issueEvent =
103107
let actorName :: Text = case issueEventActor issueEvent of
104108
Just (SimpleUser {simpleUserLogin=(N username)}) -> username
105-
Nothing -> fromMaybe "ghost" (issueEventAuthorName issueEvent)
109+
Nothing -> "ghost"
106110
-- Each sized item is (width, widget)
107111
eventSuffixItems :: [(Int, Widget n)]
108-
eventSuffixItems = case issueEventType issueEvent of
112+
eventSuffixItems = case issueEventEvent issueEvent of
109113
Labeled -> case issueEventLabel issueEvent of
110114
Just (IssueLabel {labelName=(N name), labelColor=hexColor}) -> [(5, str " the "), (safeWctwidth name + 2, labelPill hexColor name), (7, str " label")]
111115
Nothing -> [(8, str " a label")]
@@ -115,23 +119,20 @@ renderEvent now isLast issueEvent =
115119
Referenced -> case issueEventCommitId issueEvent of
116120
Just sha -> let short = T.take 7 sha in [(11, str " in commit "), (safeWctwidth short, withAttr hashAttr (str (toString short)))]
117121
Nothing -> []
118-
CrossReferenced -> case issueEventSourceIssue issueEvent of
122+
CrossReferenced -> case issueEventSource issueEvent >>= crossReferenceSourceIssue of
119123
Just sourceIssue ->
120124
let num = show (unIssueNumber (issueNumber sourceIssue))
121125
ref = "#" <> num
122126
title = toString (issueTitle sourceIssue)
123127
quoted = "\"" <> title <> "\""
124128
in [(5, str " from "), (safeWcswidth ref, withAttr hashNumberAttr (str ref)), (1 + safeWcswidth quoted, str " " <+> withAttr normalAttr (str quoted))]
125129
Nothing -> []
126-
Committed -> case issueEventCommitId issueEvent of
127-
Just sha -> let short = T.take 7 sha in [(1 + safeWctwidth short, str " " <+> withAttr hashAttr (str (toString short)))]
128-
Nothing -> []
129130
ReviewRequested -> case issueEventRequestedReviewer issueEvent of
130131
Just (SimpleUser {simpleUserLogin=(N reviewer)}) -> [(1 + safeWctwidth reviewer, str " " <+> withAttr usernameAttr (str (toString reviewer)))]
131132
Nothing -> []
132133
_ -> []
133-
eventText = getEventDescription (issueEventType issueEvent)
134-
iconWidget = getEventIconWithColor (issueEventType issueEvent)
134+
eventText = getEventDescription (issueEventEvent issueEvent)
135+
iconWidget = getEventIconWithColor (issueEventEvent issueEvent)
135136
timeAgo = timeFromNow (diffUTCTime now (issueEventCreatedAt issueEvent))
136137
timeAgoWidget = (safeWcswidth timeAgo, withAttr italicText $ str timeAgo)
137138
descriptionItems = [(safeWcswidth eventText, str eventText)] ++ eventSuffixItems ++ [(1, str " "), timeAgoWidget]
@@ -152,13 +153,64 @@ renderEvent now isLast issueEvent =
152153
else adaptiveWidth $ \_ -> padLeft (Pad 4) $ withAttr timelineBorderAttr $ str ""
153154
in vBox [eventLine, continuationLine]
154155

156+
renderCommitEvent :: UTCTime -> Bool -> TimelineCommitEvent -> Widget n
157+
renderCommitEvent now isLast commit =
158+
let actorName = gitAuthorName (timelineCommitEventAuthor commit)
159+
short = T.take 7 (timelineCommitEventSha commit)
160+
timeAgo = timeFromNow (diffUTCTime now (gitAuthorDate (timelineCommitEventAuthor commit)))
161+
firstMsgLine = T.takeWhile (/= '\n') (timelineCommitEventMessage commit)
162+
iconWidget = withAttr eventReferencedColor (str "")
163+
descriptionItems =
164+
[(16, str "added a commit "), (safeWctwidth short, withAttr hashAttr (str (toString short))), (1, str " "), (safeWcswidth timeAgo, withAttr italicText $ str timeAgo)]
165+
prefixWidth = 1 + 2 + safeWctwidth actorName + 1
166+
eventLine = adaptiveWidth $ \w ->
167+
let availableWidth = w - 4
168+
wrappedLines = wrapWidgets (availableWidth - prefixWidth) descriptionItems
169+
prefix = hBox [iconWidget, str " ", withAttr usernameAttr $ str (toString actorName), str " "]
170+
firstLine = case wrappedLines of
171+
[] -> prefix
172+
(l:_) -> hBox [prefix, hBox (map snd l)]
173+
restLines = case wrappedLines of
174+
[] -> []
175+
(_:ls) -> [padLeft (Pad 3) $ hBox (map snd l) | l <- ls]
176+
msgLine = padLeft (Pad 3) $ hLimit (w - 4 - 3) $ withAttr normalAttr $ str (toString firstMsgLine)
177+
in padLeft (Pad 4) $ vBox (firstLine : restLines ++ [msgLine])
178+
continuationLine = if isLast
179+
then emptyWidget
180+
else adaptiveWidth $ \_ -> padLeft (Pad 4) $ withAttr timelineBorderAttr $ str ""
181+
in vBox [eventLine, continuationLine]
182+
183+
renderReviewEvent :: UTCTime -> Bool -> TimelineReviewEvent -> Widget n
184+
renderReviewEvent now isLast review =
185+
let actorName = case timelineReviewEventUser review of
186+
SimpleUser {simpleUserLogin=(N username)} -> username
187+
timeAgo = timeFromNow (diffUTCTime now (timelineReviewEventSubmittedAt review))
188+
iconWidget = withAttr eventReviewColor (str "")
189+
descriptionItems = [(13, str "reviewed this "), (safeWcswidth timeAgo, withAttr italicText $ str timeAgo)]
190+
prefixWidth = 1 + 2 + safeWctwidth actorName + 1
191+
eventLine = adaptiveWidth $ \w ->
192+
let availableWidth = w - 4
193+
wrappedLines = wrapWidgets (availableWidth - prefixWidth) descriptionItems
194+
prefix = hBox [iconWidget, str " ", withAttr usernameAttr $ str (toString actorName), str " "]
195+
firstLine = case wrappedLines of
196+
[] -> prefix
197+
(l:_) -> hBox [prefix, hBox (map snd l)]
198+
restLines = case wrappedLines of
199+
[] -> []
200+
(_:ls) -> [padLeft (Pad 3) $ hBox (map snd l) | l <- ls]
201+
in padLeft (Pad 4) $ vBox (firstLine : restLines)
202+
continuationLine = if isLast
203+
then emptyWidget
204+
else adaptiveWidth $ \_ -> padLeft (Pad 4) $ withAttr timelineBorderAttr $ str ""
205+
in vBox [eventLine, continuationLine]
206+
155207
renderLabelGroup :: UTCTime -> Bool -> IssueEvent -> [IssueEvent] -> [IssueEvent] -> Widget n
156208
renderLabelGroup now isLast rep added removed =
157209
let actorName :: Text = case issueEventActor rep of
158210
Just (SimpleUser {simpleUserLogin=(N username)}) -> username
159211
Nothing -> "ghost"
160212
timeAgo = timeFromNow (diffUTCTime now (issueEventCreatedAt rep))
161-
iconWidget = getEventIconWithColor (issueEventType rep)
213+
iconWidget = getEventIconWithColor (issueEventEvent rep)
162214
addedItems = mapMaybe eventLabelPillWithWidth added
163215
removedItems = mapMaybe eventLabelPillWithWidth removed
164216
totalLabels = length added + length removed

app/Sauron/UI/Issue/Events/ReviewRequests.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ renderReviewRequestGroup now isLast rep events =
2121
Just (SimpleUser {simpleUserLogin=(N username)}) -> username
2222
Nothing -> "ghost"
2323
timeAgo = timeFromNow (diffUTCTime now (issueEventCreatedAt rep))
24-
iconWidget = getEventIconWithColor (issueEventType rep)
24+
iconWidget = getEventIconWithColor (issueEventEvent rep)
2525
reviewerNames = mapMaybe (\e -> case issueEventRequestedReviewer e of
2626
Just (SimpleUser {simpleUserLogin=(N name)}) -> Just name
2727
Nothing -> Nothing) events

stack.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ extra-deps:
1313
- vty-windows-0.2.0.3
1414
- brick-skylighting-1.0@sha256:64764b6be36c05261959f68ed38b9cb37e1acb6180a3bde5dd98255f62ea7e3b,1812
1515

16+
# - /home/tom/tools/github
1617
- git: https://github.com/codedownio/github.git
1718
# sauron-sep18-2025 branch, which has some changes from upstream:
1819
# - fixes for search query escaping
@@ -30,7 +31,9 @@ extra-deps:
3031
# - issueEventActor: switch to a Maybe
3132
# - Add HeadRefForcePushed event type
3233
# - Add /issues/timeline API support
33-
commit: 3d100995c86b5b574b50f68e6d6f430290f3cee2
34+
# - Parse issue event message
35+
# - GitHub.Data.Issues: auto-derive JSON instances
36+
commit: 4fd5d4525dca35f2e54aea76f4665b97e951ab3a
3437

3538
- git: https://github.com/dogonthehorizon/git-config.git
3639
commit: 8f3fab100e4c8d82b5c6fe7c0cc09510249e98cf

stack.yaml.lock

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,6 @@ packages:
1818
size: 393
1919
original:
2020
hackage: brick-skylighting-1.0@sha256:64764b6be36c05261959f68ed38b9cb37e1acb6180a3bde5dd98255f62ea7e3b,1812
21-
- completed:
22-
commit: 3d100995c86b5b574b50f68e6d6f430290f3cee2
23-
git: https://github.com/codedownio/github.git
24-
name: github
25-
pantry-tree:
26-
sha256: d7bfef8770965b6a32b9a87bef4531f8a8fe35a6dd9f31f38fa879d62d147838
27-
size: 19445
28-
version: 0.30.0.1
29-
original:
30-
commit: 3d100995c86b5b574b50f68e6d6f430290f3cee2
31-
git: https://github.com/codedownio/github.git
3221
- completed:
3322
commit: 8f3fab100e4c8d82b5c6fe7c0cc09510249e98cf
3423
git: https://github.com/dogonthehorizon/git-config.git

0 commit comments

Comments
 (0)