|
1 | 1 | import type { TreeViewNodeTypes } from '../../../../constants.views'; |
2 | 2 | import { treeViewFileNodeTypes, treeViewRefFileNodeTypes, treeViewRefNodeTypes } from '../../../../constants.views'; |
| 3 | +import type { GitCommit } from '../../../../git/models/commit'; |
3 | 4 | import type { LaunchpadItemNode } from '../../../launchpadView'; |
4 | 5 | import type { RepositoryFolderNode } from '../../abstract/repositoryFolderNode'; |
5 | | -import { ViewNode } from '../../abstract/viewNode'; |
| 6 | +import { ContextValues, ViewNode } from '../../abstract/viewNode'; |
6 | 7 | import type { BranchNode } from '../../branchNode'; |
7 | 8 | import type { BranchTrackingStatusFilesNode } from '../../branchTrackingStatusFilesNode'; |
8 | 9 | import type { BranchTrackingStatusNode } from '../../branchTrackingStatusNode'; |
9 | 10 | import type { CodeSuggestionsNode } from '../../codeSuggestionsNode'; |
10 | 11 | import type { CommitFileNode } from '../../commitFileNode'; |
11 | 12 | import type { CommitNode } from '../../commitNode'; |
| 13 | +import { MessageNode } from '../../common'; |
12 | 14 | import type { CompareBranchNode } from '../../compareBranchNode'; |
13 | 15 | import type { CompareResultsNode } from '../../compareResultsNode'; |
14 | 16 | import type { FileRevisionAsCommitNode } from '../../fileRevisionAsCommitNode'; |
@@ -86,6 +88,77 @@ type FilterNodesByType<T extends keyof TreeViewNodesByType | (keyof TreeViewNode |
86 | 88 | ? TreeViewNodesByType[T[number]] |
87 | 89 | : never; |
88 | 90 |
|
| 91 | +export const markers: [number, string][] = [ |
| 92 | + [0, 'Less than a week ago'], |
| 93 | + [7, 'Over a week ago'], |
| 94 | + [25, 'Over a month ago'], |
| 95 | + [77, 'Over 3 months ago'], |
| 96 | +]; |
| 97 | + |
| 98 | +export function* insertDateMarkers<T extends ViewNode & { commit: GitCommit }>( |
| 99 | + iterable: Iterable<T>, |
| 100 | + parent: ViewNode, |
| 101 | + skip?: number, |
| 102 | + { show }: { show: boolean } = { show: true }, |
| 103 | +): Iterable<ViewNode> { |
| 104 | + if (!parent.view.config.showRelativeDateMarkers || !show) { |
| 105 | + // eslint-disable-next-line @typescript-eslint/no-unsafe-return |
| 106 | + return yield* iterable; |
| 107 | + } |
| 108 | + |
| 109 | + let index = skip ?? 0; |
| 110 | + let time = undefined; |
| 111 | + const now = Date.now(); |
| 112 | + |
| 113 | + let first = true; |
| 114 | + |
| 115 | + for (const node of iterable) { |
| 116 | + if (index < markers.length) { |
| 117 | + let [daysAgo, marker] = markers[index]; |
| 118 | + if (time === undefined) { |
| 119 | + const date = new Date(now); |
| 120 | + time = date.setDate(date.getDate() - daysAgo); |
| 121 | + } |
| 122 | + |
| 123 | + const date = new Date(node.commit.committer.date).setUTCHours(0, 0, 0, 0); |
| 124 | + if (date <= time) { |
| 125 | + while (index < markers.length - 1) { |
| 126 | + [daysAgo] = markers[index + 1]; |
| 127 | + const nextDate = new Date(now); |
| 128 | + const nextTime = nextDate.setDate(nextDate.getDate() - daysAgo); |
| 129 | + |
| 130 | + if (date > nextTime) break; |
| 131 | + |
| 132 | + index++; |
| 133 | + time = undefined; |
| 134 | + [, marker] = markers[index]; |
| 135 | + } |
| 136 | + |
| 137 | + // Don't show the marker if it is the first node |
| 138 | + if (!first) { |
| 139 | + yield new MessageNode( |
| 140 | + parent.view, |
| 141 | + parent, |
| 142 | + '', |
| 143 | + marker, |
| 144 | + undefined, |
| 145 | + undefined, |
| 146 | + ContextValues.DateMarker, |
| 147 | + ); |
| 148 | + } |
| 149 | + |
| 150 | + index++; |
| 151 | + time = undefined; |
| 152 | + } |
| 153 | + } |
| 154 | + |
| 155 | + first = false; |
| 156 | + yield node; |
| 157 | + } |
| 158 | + |
| 159 | + return undefined; |
| 160 | +} |
| 161 | + |
89 | 162 | export function isViewNode(node: unknown): node is ViewNode; |
90 | 163 | export function isViewNode<T extends keyof TreeViewNodesByType | (keyof TreeViewNodesByType)[]>( |
91 | 164 | node: unknown, |
|
0 commit comments