Skip to content

Commit b63d084

Browse files
committed
refactor: refactor treeview by useTreeView
1 parent deffa1b commit b63d084

File tree

6 files changed

+159
-255
lines changed

6 files changed

+159
-255
lines changed

src/commands/diff.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
import { Uri, window } from 'vscode'
22
import { executeCommand, useWorkspaceFolders } from 'reactive-vscode'
33

4-
import type { DiffTreeView } from '@/views/diff'
54
import { useGitService } from '@/git'
65
import { GIT_STATUS } from '@/constant'
76
import { toGitUri } from '@/utils'
7+
import { useDiffTreeView } from '@/views/diff'
88

9-
export default function diffCommand(diffProvider: DiffTreeView) {
9+
export default function diffCommand() {
1010
const { getPreviousCommit } = useGitService()
1111
const workspaceFolders = useWorkspaceFolders()
12+
const diffProvider = useDiffTreeView()
1213

1314
return async (fileInfo: { path: string, status: string }) => {
14-
const commit = diffProvider.getSelectedCommitHash()
15+
const commit = (await diffProvider).selectedCommitHash.value
1516
if (!commit) {
1617
return
1718
}

src/commands/index.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,11 @@ import { useCommands } from 'reactive-vscode'
33
import refreshCommand from './refresh'
44
import diffCommand from './diff'
55

6-
import type { DiffTreeView } from '@/views/diff'
76
import { EXTENSION_SYMBOL } from '@/constant'
87

9-
interface CommandProvider {
10-
diffProvider: DiffTreeView
11-
}
12-
13-
export function initCommands({ diffProvider }: CommandProvider) {
8+
export function initCommands() {
149
useCommands({
1510
[`${EXTENSION_SYMBOL}.history.refresh`]: refreshCommand,
16-
[`${EXTENSION_SYMBOL}.openDiff`]: diffCommand(diffProvider),
11+
[`${EXTENSION_SYMBOL}.openDiff`]: diffCommand(),
1712
})
1813
}

src/index.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import { Disposable, window } from 'vscode'
1+
import { Disposable } from 'vscode'
22
import { defineExtension, useDisposable } from 'reactive-vscode'
33

44
import { useGitPanelView } from './views/webview'
5-
import { DiffTreeView } from './views/diff'
5+
import { useDiffTreeView } from './views/diff/DiffTreeView'
66
import { logger } from './utils'
77
import { initCommands } from './commands'
8-
import { EXTENSION_SYMBOL } from './constant'
98
import { initDecoration } from './decoration'
109
import { useStorage } from './storage'
1110
import { useGitChangeMonitor } from './git/GitChangeMonitor'
@@ -15,18 +14,17 @@ const { activate, deactivate } = defineExtension(() => {
1514

1615
useStorage().clearCommits()
1716
useGitPanelView()
18-
const gitChangeMonitor = useGitChangeMonitor()
17+
const { tree } = useDiffTreeView()
1918

20-
const diffProvider = DiffTreeView.getInstance()
21-
window.createTreeView(`${EXTENSION_SYMBOL}.changes`, {
22-
treeDataProvider: diffProvider,
23-
showCollapseAll: true,
24-
})
19+
const gitChangeMonitor = useGitChangeMonitor()
2520

2621
initDecoration()
27-
initCommands({ diffProvider })
22+
initCommands()
2823

29-
useDisposable(new Disposable(gitChangeMonitor.dispose))
24+
useDisposable(new Disposable(() => {
25+
tree.dispose()
26+
gitChangeMonitor.dispose()
27+
}))
3028
})
3129

3230
export { activate, deactivate }

src/views/diff/DiffTreeView.ts

Lines changed: 74 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -1,222 +1,114 @@
1-
import type { Event, TreeDataProvider, TreeItem } from 'vscode'
2-
import { EventEmitter, TreeItemCollapsibleState } from 'vscode'
1+
import { TreeItemCollapsibleState } from 'vscode'
2+
import type { TreeViewNode } from 'reactive-vscode'
33
import { computed, createSingletonComposable, ref, useTreeView } from 'reactive-vscode'
44

55
import { CommitNode } from './entity/CommitNode'
6-
import { FileTreeView } from './FileTreeView'
6+
import { useFileTreeView } from './FileTreeView'
77
import type { CommitDetails } from './types'
88
import { useGitService } from '@/git'
99
import { useStorage } from '@/storage'
1010
import { EXTENSION_SYMBOL } from '@/constant'
1111

12-
export class DiffTreeView implements TreeDataProvider<CommitNode> {
13-
private readonly _onDidChangeTreeData: EventEmitter<CommitNode | undefined | null | void> = new EventEmitter<CommitNode | undefined | null | void>()
14-
readonly onDidChangeTreeData: Event<CommitNode | undefined | null | void> = this._onDidChangeTreeData.event
15-
private storage = useStorage()
16-
private fileTreeProvider: FileTreeView
17-
private selectedCommitHash?: string
18-
private static instance: DiffTreeView
12+
export const useDiffTreeView = createSingletonComposable(() => {
13+
const git = useGitService()
14+
const storage = useStorage()
15+
const fileTree = useFileTreeView()
16+
const selectedCommitHash = ref('')
17+
const commitDetails = ref<CommitDetails | null>(null)
18+
const files = ref<TreeViewNode[]>([])
1919

20-
private constructor() {
21-
this.fileTreeProvider = new FileTreeView()
22-
}
23-
24-
static getInstance(): DiffTreeView {
25-
if (!DiffTreeView.instance) {
26-
DiffTreeView.instance = new DiffTreeView()
27-
}
28-
return DiffTreeView.instance
29-
}
30-
31-
refresh(commitHash?: string): void {
32-
this.selectedCommitHash = commitHash
33-
this._onDidChangeTreeData.fire()
34-
}
35-
36-
getTreeItem(element: CommitNode): TreeItem {
37-
return element
38-
}
39-
40-
private async getCommitByHash(hash?: string): Promise<CommitDetails | null> {
20+
async function loadCommitDetails(hash: string) {
4121
try {
42-
if (!hash) {
43-
throw new Error('Commit hash is required')
44-
}
45-
46-
// First try to get from cache
47-
let commit = this.storage.getCommit(hash)
22+
let commit = storage.getCommit(hash)
4823

4924
if (!commit) {
50-
// Only fetch all commits if not found in cache
51-
const { getHistory } = useGitService()
52-
const history = await getHistory()
53-
const historyCommit = history.all.find(c => c.hash === hash)
54-
if (!historyCommit) {
55-
return null
56-
}
25+
const { all: history } = await git.getHistory()
26+
const historyCommit = history.find(c => c.hash === hash)
27+
if (!historyCommit)
28+
return
5729

5830
commit = {
5931
...historyCommit,
6032
}
33+
34+
storage.saveCommits(Array.from(history))
6135
}
6236

63-
return commit
37+
commitDetails.value = commit
38+
const { files: commitFiles, total } = await fileTree.getChildren(hash)
39+
40+
files.value = [
41+
{
42+
treeItem: new CommitNode(
43+
'Changed Files',
44+
`${total} Files Changed`,
45+
total > 0 ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.None,
46+
'files',
47+
),
48+
children: commitFiles,
49+
},
50+
]
6451
}
6552
catch (error) {
6653
console.error('Error getting commit details:', error)
67-
return null
54+
commitDetails.value = null
55+
files.value = []
6856
}
6957
}
7058

71-
async getChildren(element?: CommitNode): Promise<CommitNode[]> {
72-
if (!element && this.selectedCommitHash) {
73-
const commitDetails = await this.getCommitByHash(this.selectedCommitHash)
74-
75-
if (!commitDetails) {
76-
return []
77-
}
78-
79-
this.fileTreeProvider.refresh(commitDetails.hash)
59+
const treeNodes = computed<TreeViewNode[]>(() => {
60+
if (!commitDetails.value)
61+
return []
8062

81-
const { files, total } = await this.fileTreeProvider.getChildren()
82-
83-
return [
84-
new CommitNode(
63+
return [
64+
{
65+
treeItem: new CommitNode(
8566
'Author',
86-
`${commitDetails.authorName} <${commitDetails.authorEmail}>`,
67+
`${commitDetails.value.authorName} <${commitDetails.value.authorEmail}>`,
8768
TreeItemCollapsibleState.None,
8869
'person',
8970
),
90-
new CommitNode(
71+
},
72+
{
73+
treeItem: new CommitNode(
9174
'Date',
92-
new Date(commitDetails.date).toLocaleString(),
75+
new Date(commitDetails.value.date).toLocaleString(),
9376
TreeItemCollapsibleState.None,
9477
'calendar',
9578
),
96-
new CommitNode(
79+
},
80+
{
81+
treeItem: new CommitNode(
9782
'Hash',
98-
commitDetails.hash,
83+
commitDetails.value.hash,
9984
TreeItemCollapsibleState.None,
10085
'git-commit',
10186
),
102-
new CommitNode(
103-
'Changed Files',
104-
`${total} Files Changed`,
105-
total > 0 ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.None,
106-
'files',
107-
files,
108-
),
109-
]
110-
}
111-
112-
return element?.children as CommitNode[] || []
87+
},
88+
...files.value,
89+
]
90+
})
91+
92+
const tree = useTreeView(
93+
`${EXTENSION_SYMBOL}.changes`,
94+
treeNodes,
95+
{
96+
showCollapseAll: true,
97+
},
98+
)
99+
100+
async function refresh(hash: string) {
101+
if (hash === selectedCommitHash.value)
102+
return
103+
104+
selectedCommitHash.value = hash
105+
fileTree.refresh(hash)
106+
await loadCommitDetails(hash)
113107
}
114108

115-
// Getter for selectedCommitHash
116-
public getSelectedCommitHash(): string | undefined {
117-
return this.selectedCommitHash
109+
return {
110+
tree,
111+
refresh,
112+
selectedCommitHash,
118113
}
119-
}
120-
121-
// export const useDiffTreeView = createSingletonComposable(() => {
122-
// const { git, parseGitStatus } = useGitService()
123-
// const selectedCommitHash = ref<string[]>([])
124-
125-
// const tree = useTreeView(
126-
// `${EXTENSION_SYMBOL}.changes`,
127-
// [],
128-
// {
129-
// canSelectMany: false,
130-
// },
131-
// )
132-
133-
// const treeData = computed(() => {
134-
// if (selectedCommitHash.value.length === 1) {
135-
// const commitDetail = selectedCommitHash.value[0]
136-
// return [
137-
// new CommitNode(
138-
// 'Author',
139-
// `${commitDetail.authorName} <${commitDetail.authorEmail}>`,
140-
// TreeItemCollapsibleState.None,
141-
// 'person',
142-
// ),
143-
// new CommitNode(
144-
// 'Date',
145-
// new Date(commitDetail.date).toLocaleString(),
146-
// TreeItemCollapsibleState.None,
147-
// 'calendar',
148-
// ),
149-
// new CommitNode(
150-
// 'Hash',
151-
// commitDetail.hash,
152-
// TreeItemCollapsibleState.None,
153-
// 'git-commit',
154-
// ),
155-
// new CommitNode(
156-
// 'Changed Files',
157-
// `${total} Files Changed`,
158-
// total > 0 ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.None,
159-
// 'files',
160-
// files,
161-
// ),
162-
// ]
163-
// }
164-
// return selectedCommitHash.value.map(hash => tree.getItem(hash))
165-
// })
166-
167-
// const refresh = (commitsHash: string[]) => {
168-
// selectedCommitHash.value = commitsHash
169-
// tree.refresh()
170-
// }
171-
172-
// const getCommitByHash = async (hash?: string): Promise<CommitDetails | null> => {
173-
// try {
174-
// if (!hash) {
175-
// throw new Error('Commit hash is required')
176-
// }
177-
178-
// // First try to get from cache
179-
// let commit = storageService.getCommit(hash)
180-
181-
// if (!commit) {
182-
// // Only fetch all commits if not found in cache
183-
// const history = await git.getHistory()
184-
// const historyCommit = history.all.find(c => c.hash === hash)
185-
// if (!historyCommit) {
186-
// return null
187-
// }
188-
189-
// commit = {
190-
// hash: historyCommit.hash,
191-
// authorName: historyCommit.author_name,
192-
// authorEmail: historyCommit.author_email,
193-
// date: historyCommit.date,
194-
// message: historyCommit.message,
195-
// body: historyCommit.body,
196-
// stats: historyCommit.stats,
197-
// }
198-
// }
199-
200-
// return commit
201-
// }
202-
// catch (error) {
203-
// console.error('Error getting commit details:', error)
204-
// return null
205-
// }
206-
// }
207-
208-
// const getFiles = async () => {
209-
// try {
210-
// const status = await git.status()
211-
// }
212-
// catch (error) {
213-
// console.error('Error getting files:', error)
214-
// }
215-
// }
216-
217-
// return {
218-
// diffTreeView: tree,
219-
// selectedCommitHash,
220-
// refresh,
221-
// }
222-
// })
114+
})

0 commit comments

Comments
 (0)