Skip to content

Commit 801aab1

Browse files
committed
feat: linkage
1 parent 903a749 commit 801aab1

File tree

9 files changed

+133
-41
lines changed

9 files changed

+133
-41
lines changed

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212
## Commands
1313

1414
<!-- commands -->
15-
| Command | Title |
16-
| --------------------------------- | ----------------------------- |
17-
| `git-panel.history` | Git Panel: History |
18-
| `git-panel.history.filter` | Git Panel: Git History Filter |
19-
| `git-panel.history.clear` | Git Panel: Clear Selection |
20-
| `git-panel.history.refresh` | Git Panel: Refresh History |
21-
| `git-panel.history.switch.branch` | Git Panel: Select Branch |
15+
| Command | Title |
16+
| --------------------------------- | ---------------------------- |
17+
| `git-panel.history` | GitPanel: History |
18+
| `git-panel.history.filter` | GitPanel: Git History Filter |
19+
| `git-panel.history.clear` | GitPanel: Clear Selection |
20+
| `git-panel.history.refresh` | GitPanel: Refresh History |
21+
| `git-panel.history.switch.branch` | GitPanel: Select Branch |
2222
<!-- commands -->
2323

2424
## Sponsors

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@
164164
"typescript": "~5.6.2",
165165
"vite": "^6.0.5",
166166
"vscode-ext-gen": "^0.4.1",
167-
"vue-tsc": "^2.2.0"
167+
"vue-tsc": "^2.2.0",
168+
"vue-virtual-scroller": "^1.1.2"
168169
}
169170
}

pnpm-lock.yaml

Lines changed: 34 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/channel/constant.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,4 @@ export const WEBVIEW_CHANNEL = {
77
// vscode to webview channel
88
export const CHANNEL = {
99
HISTORY: 'history',
10-
HISTORY_LOADED: 'history-loaded',
1110
}

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export function activate(context: vscode.ExtensionContext) {
1616
const provider = new GitPanelViewProvider(vscode.Uri.file(__dirname), context, gitService)
1717
vscode.window.registerWebviewViewProvider(GitPanelViewProvider.viewType, provider)
1818

19-
const gitChangesProvider = new GitChangesProvider()
19+
const gitChangesProvider = GitChangesProvider.getInstance()
2020
vscode.window.createTreeView('git-panel.changes', {
2121
treeDataProvider: gitChangesProvider,
2222
showCollapseAll: true,

src/views/diff/GitChangesProvider.ts

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,45 +9,56 @@ export class GitChangesProvider implements vscode.TreeDataProvider<CommitNode> {
99
readonly onDidChangeTreeData: vscode.Event<CommitNode | undefined | null | void> = this._onDidChangeTreeData.event
1010
private gitService: GitService
1111
private fileTreeProvider: FileTreeProvider
12+
private selectedCommitHash?: string
13+
private static instance: GitChangesProvider
1214

13-
constructor() {
15+
private constructor() {
1416
this.gitService = new GitService()
1517
this.fileTreeProvider = new FileTreeProvider(this.gitService)
1618
}
1719

18-
refresh(): void {
20+
static getInstance(): GitChangesProvider {
21+
if (!GitChangesProvider.instance) {
22+
GitChangesProvider.instance = new GitChangesProvider()
23+
}
24+
return GitChangesProvider.instance
25+
}
26+
27+
refresh(commitHash?: string): void {
28+
this.selectedCommitHash = commitHash
1929
this._onDidChangeTreeData.fire()
2030
}
2131

2232
getTreeItem(element: CommitNode): vscode.TreeItem {
2333
return element
2434
}
2535

26-
private async getFirstCommitDetails(): Promise<CommitDetails | null> {
36+
private async getCommitByHash(hash?: string): Promise<CommitDetails | null> {
2737
try {
2838
const history = await this.gitService.getHistory()
2939
if (history.all.length === 0) {
3040
return null
3141
}
3242

33-
const firstCommit = history.all[0]
43+
const commit = history.all.find(c => c.hash === hash) || history.all[0]
3444
return {
35-
hash: firstCommit.hash,
36-
authorName: firstCommit.author_name,
37-
authorEmail: firstCommit.author_email,
38-
date: firstCommit.date,
39-
stats: firstCommit.stats,
45+
hash: commit.hash,
46+
authorName: commit.author_name,
47+
authorEmail: commit.author_email,
48+
date: commit.date,
49+
stats: commit.stats,
4050
}
4151
}
4252
catch (error) {
43-
console.error('Error getting first commit details:', error)
53+
console.error('Error getting commit details:', error)
4454
return null
4555
}
4656
}
4757

4858
async getChildren(element?: CommitNode): Promise<CommitNode[]> {
4959
if (!element) {
50-
const commitDetails = await this.getFirstCommitDetails()
60+
const commitDetails = await this.getCommitByHash(this.selectedCommitHash)
61+
5162
if (!commitDetails) {
5263
return []
5364
}
@@ -79,14 +90,14 @@ export class GitChangesProvider implements vscode.TreeDataProvider<CommitNode> {
7990
),
8091
new CommitNode(
8192
'Changed Files',
82-
'Changed Files',
93+
`${changedFiles.length} Files Changed`,
8394
changedFiles.length > 0 ? vscode.TreeItemCollapsibleState.Expanded : vscode.TreeItemCollapsibleState.None,
8495
'files',
85-
changedFiles
96+
changedFiles,
8697
),
8798
]
8899
}
89-
else if (element.label === 'Changed Files' && element.children) {
100+
else if (element.children) {
90101
return element.children as CommitNode[]
91102
}
92103

src/views/history/App.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ window.addEventListener('message', (event: { data: any }) => {
3333
const message = event.data
3434
switch (message.command) {
3535
case CHANNEL.HISTORY:
36-
commits.value = message.data as Commit[]
36+
commits.value = message.commits as Commit[]
3737
break
3838
case 'error':
3939
error.value = message.message
@@ -63,7 +63,7 @@ watch([commits, selectedHash, filter], () => {
6363
6464
onMounted(() => {
6565
// Request git history
66-
vscode.postMessage({ command: WEBVIEW_CHANNEL.GET_HISTORY, forceRefresh: true })
66+
vscode.postMessage({ command: WEBVIEW_CHANNEL.GET_HISTORY })
6767
})
6868
6969
const transformedCommits = computed(() => {

src/views/history/components/GitGraph.vue

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import { computed } from 'vue'
2+
import { computed, onMounted, onUnmounted, ref } from 'vue'
33
import dayjs from 'dayjs'
44
55
import type { Commit } from '@/git'
@@ -19,17 +19,17 @@ const props = defineProps<{
1919
// isMerge?: boolean
2020
// }
2121
22+
const ITEMS_PER_PAGE = 45
23+
const currentPage = ref(1)
24+
const observer = ref<IntersectionObserver | null>(null)
25+
const loadingTriggerRef = ref<HTMLElement | null>(null)
26+
2227
function handleCommitClick(commit: Commit & { date: string }) {
2328
try {
2429
if (window.vscode) {
2530
window.vscode.postMessage({
2631
command: WEBVIEW_CHANNEL.SHOW_COMMIT_DETAILS,
27-
commit: {
28-
hash: commit.hash,
29-
message: commit.message,
30-
date: commit.date,
31-
stats: commit.stats,
32-
},
32+
commitHash: commit.hash,
3333
})
3434
}
3535
}
@@ -56,6 +56,30 @@ const graphData = computed(() => {
5656
date: dayjs(commit.date).format('YYYY-MM-DD HH:mm'),
5757
}))
5858
})
59+
60+
const visibleCommits = computed(() => {
61+
const end = currentPage.value * ITEMS_PER_PAGE
62+
return graphData.value.slice(0, end)
63+
})
64+
65+
onMounted(() => {
66+
observer.value = new IntersectionObserver((entries) => {
67+
const target = entries[0]
68+
if (target.isIntersecting && currentPage.value * ITEMS_PER_PAGE < graphData.value.length) {
69+
currentPage.value++
70+
}
71+
})
72+
73+
if (loadingTriggerRef.value) {
74+
observer.value.observe(loadingTriggerRef.value)
75+
}
76+
})
77+
78+
onUnmounted(() => {
79+
if (observer.value) {
80+
observer.value.disconnect()
81+
}
82+
})
5983
</script>
6084

6185
<template>
@@ -78,7 +102,7 @@ const graphData = computed(() => {
78102
</thead>
79103
<tbody>
80104
<tr
81-
v-for="commit in graphData"
105+
v-for="commit in visibleCommits"
82106
:key="commit.hash"
83107
class="commit-row"
84108
@click="handleCommitClick(commit)"
@@ -103,6 +127,13 @@ const graphData = computed(() => {
103127
{{ commit.date }}
104128
</td>
105129
</tr>
130+
<tr ref="loadingTriggerRef" class="loading-trigger">
131+
<td colspan="5" class="loading-cell">
132+
<div v-if="visibleCommits.length < graphData.length" class="loading-text">
133+
Loading more commits...
134+
</div>
135+
</td>
136+
</tr>
106137
</tbody>
107138
</table>
108139
</div>
@@ -196,6 +227,16 @@ tr:hover {
196227
background-color: var(--vscode-list-hoverBackground);
197228
}
198229
230+
.loading-cell {
231+
text-align: center;
232+
padding: 8px;
233+
color: var(--vscode-descriptionForeground);
234+
}
235+
236+
.loading-text {
237+
font-size: 12px;
238+
}
239+
199240
/* Ensure the graph lines remain visible when hovering */
200241
tr:hover .commit-line {
201242
opacity: 0.8;

0 commit comments

Comments
 (0)