|
1 | 1 | <script setup lang="ts">
|
2 |
| -import { onMounted, ref, watch } from 'vue' |
| 2 | +import { computed, onMounted, ref, watch } from 'vue' |
| 3 | +import GitGraph from './components/GitGraph.vue' |
3 | 4 |
|
4 | 5 | interface Commit {
|
5 | 6 | hash: string
|
6 | 7 | author_name: string
|
7 | 8 | author_email: string
|
8 | 9 | message: string
|
9 | 10 | body: string
|
| 11 | + parents?: string[] |
| 12 | + date: string |
10 | 13 | }
|
11 | 14 |
|
12 | 15 | interface State {
|
@@ -39,173 +42,98 @@ window.addEventListener('message', (event: { data: any }) => {
|
39 | 42 |
|
40 | 43 | // Save state when it changes
|
41 | 44 | watch([commits, selectedHash, filter], () => {
|
42 |
| - const state: State = { |
43 |
| - commits: commits.value, |
44 |
| - selectedHash: selectedHash.value, |
45 |
| - filter: filter.value, |
| 45 | + try { |
| 46 | + const state: State = { |
| 47 | + commits: commits.value.map(commit => ({ |
| 48 | + ...commit, |
| 49 | + parents: Array.isArray(commit.parents) ? [...commit.parents] : [], |
| 50 | + })), |
| 51 | + selectedHash: selectedHash.value || '', |
| 52 | + filter: filter.value || '', |
| 53 | + } |
| 54 | + vscode.postMessage({ command: 'setState', state }) |
| 55 | + } |
| 56 | + catch (err) { |
| 57 | + console.error('Failed to save state:', err) |
46 | 58 | }
|
47 |
| - vscode.postMessage({ command: 'setState', state }) |
48 | 59 | }, { deep: true })
|
49 | 60 |
|
50 |
| -function refreshHistory() { |
51 |
| - commits.value = [] |
52 |
| - vscode.postMessage({ command: 'getHistory', forceRefresh: true }) |
53 |
| -} |
| 61 | +// function refreshHistory() { |
| 62 | +// commits.value = [] |
| 63 | +// vscode.postMessage({ command: 'getHistory', forceRefresh: true }) |
| 64 | +// } |
54 | 65 |
|
55 | 66 | onMounted(() => {
|
56 | 67 | // Request git history
|
57 | 68 | vscode.postMessage({ command: 'getHistory', forceRefresh: true })
|
58 | 69 | })
|
59 | 70 |
|
60 |
| -function selectCommit(hash: string) { |
61 |
| - selectedHash.value = hash |
62 |
| -} |
| 71 | +const transformedCommits = computed(() => { |
| 72 | + return commits.value.map(commit => ({ |
| 73 | + hash: commit.hash, |
| 74 | + message: commit.message, |
| 75 | + author: commit.author_name, |
| 76 | + date: commit.date, |
| 77 | + parents: commit.parents || [], |
| 78 | + })) |
| 79 | +}) |
63 | 80 | </script>
|
64 | 81 |
|
65 | 82 | <template>
|
66 | 83 | <div class="git-panel">
|
67 | 84 | <div class="toolbar">
|
68 |
| - <button class="refresh-button" @click="refreshHistory"> |
69 |
| - <span class="codicon codicon-refresh" /> |
70 |
| - Refresh |
71 |
| - </button> |
| 85 | + <input |
| 86 | + v-model="filter" |
| 87 | + type="text" |
| 88 | + placeholder="Search commits..." |
| 89 | + class="search-input" |
| 90 | + > |
72 | 91 | </div>
|
| 92 | + |
| 93 | + <GitGraph |
| 94 | + :commits="transformedCommits" |
| 95 | + class="git-graph-container" |
| 96 | + /> |
| 97 | + |
73 | 98 | <div v-if="error" class="error">
|
74 | 99 | {{ error }}
|
75 | 100 | </div>
|
76 |
| - <div v-else-if="commits.length === 0" class="loading"> |
77 |
| - Loading git history... |
78 |
| - </div> |
79 |
| - <div v-else class="commits"> |
80 |
| - <div class="filter"> |
81 |
| - <input |
82 |
| - v-model="filter" |
83 |
| - type="text" |
84 |
| - placeholder="Filter commits..." |
85 |
| - class="filter-input" |
86 |
| - > |
87 |
| - </div> |
88 |
| - <div |
89 |
| - v-for="commit in commits" |
90 |
| - :key="commit.hash" |
91 |
| - class="commit" |
92 |
| - :class="{ selected: commit.hash === selectedHash }" |
93 |
| - @click="selectCommit(commit.hash)" |
94 |
| - > |
95 |
| - <div class="commit-header"> |
96 |
| - <span class="commit-hash">{{ commit.hash.substring(0, 7) }}</span> |
97 |
| - <span class="commit-author">{{ commit.author_name }}</span> |
98 |
| - </div> |
99 |
| - <div class="commit-message"> |
100 |
| - {{ commit.message }} |
101 |
| - </div> |
102 |
| - </div> |
103 |
| - </div> |
104 | 101 | </div>
|
105 | 102 | </template>
|
106 | 103 |
|
107 | 104 | <style scoped>
|
108 | 105 | .git-panel {
|
109 |
| - padding: 10px; |
110 |
| -} |
111 |
| -
|
112 |
| -.error { |
113 |
| - color: red; |
114 |
| - padding: 10px; |
115 |
| -} |
116 |
| -
|
117 |
| -.loading { |
118 |
| - padding: 10px; |
119 |
| - color: #666; |
| 106 | + height: 100vh; |
| 107 | + display: flex; |
| 108 | + flex-direction: column; |
| 109 | + background-color: var(--vscode-sideBar-background); |
120 | 110 | }
|
121 | 111 |
|
122 | 112 | .toolbar {
|
123 |
| - margin-bottom: 10px; |
124 |
| -} |
125 |
| -
|
126 |
| -.refresh-button { |
127 |
| - background-color: var(--vscode-button-background); |
128 |
| - color: var(--vscode-button-foreground); |
129 |
| - border: none; |
130 |
| - padding: 4px 8px; |
131 |
| - border-radius: 2px; |
132 |
| - cursor: pointer; |
133 |
| -} |
134 |
| -
|
135 |
| -.refresh-button:hover { |
136 |
| - background-color: var(--vscode-button-hoverBackground); |
137 |
| -} |
138 |
| -
|
139 |
| -.refresh-button:active { |
140 |
| - background-color: var(--vscode-button-activeBackground); |
141 |
| -} |
142 |
| -
|
143 |
| -.filter { |
144 |
| - margin-bottom: 10px; |
| 113 | + padding: 8px; |
| 114 | + border-bottom: 1px solid var(--vscode-panel-border); |
145 | 115 | }
|
146 | 116 |
|
147 |
| -.filter-input { |
| 117 | +.search-input { |
148 | 118 | width: 100%;
|
149 | 119 | padding: 4px 8px;
|
150 | 120 | border: 1px solid var(--vscode-input-border);
|
151 |
| - background: var(--vscode-input-background); |
| 121 | + background-color: var(--vscode-input-background); |
152 | 122 | color: var(--vscode-input-foreground);
|
153 |
| - border-radius: 2px; |
| 123 | + outline: none; |
154 | 124 | }
|
155 | 125 |
|
156 |
| -.filter-input:focus { |
157 |
| - outline: 1px solid var(--vscode-focusBorder); |
158 |
| - border-color: transparent; |
| 126 | +.search-input:focus { |
| 127 | + border-color: var(--vscode-focusBorder); |
159 | 128 | }
|
160 | 129 |
|
161 |
| -.commits { |
162 |
| - display: flex; |
163 |
| - flex-direction: column; |
164 |
| - gap: 10px; |
| 130 | +.git-graph-container { |
| 131 | + flex: 1; |
| 132 | + overflow: auto; |
165 | 133 | }
|
166 | 134 |
|
167 |
| -.commit { |
| 135 | +.error { |
| 136 | + color: var(--vscode-errorForeground); |
168 | 137 | padding: 8px;
|
169 |
| - border: 1px solid var(--vscode-panel-border); |
170 |
| - border-radius: 4px; |
171 |
| - cursor: pointer; |
172 |
| - transition: background-color 0.1s; |
173 |
| -} |
174 |
| -
|
175 |
| -.commit:hover { |
176 |
| - background-color: var(--vscode-list-hoverBackground); |
177 |
| -} |
178 |
| -
|
179 |
| -.commit.selected { |
180 |
| - background-color: var(--vscode-list-activeSelectionBackground); |
181 |
| - color: var(--vscode-list-activeSelectionForeground); |
182 |
| -} |
183 |
| -
|
184 |
| -.commit-header { |
185 |
| - display: flex; |
186 |
| - gap: 8px; |
187 |
| - margin-bottom: 4px; |
188 |
| -} |
189 |
| -
|
190 |
| -.commit-hash { |
191 |
| - color: var(--vscode-textLink-foreground); |
192 |
| - font-family: monospace; |
193 |
| -} |
194 |
| -
|
195 |
| -.commit.selected .commit-hash { |
196 |
| - color: inherit; |
197 |
| -} |
198 |
| -
|
199 |
| -.commit-author { |
200 |
| - color: var(--vscode-textPreformat-foreground); |
201 |
| -} |
202 |
| -
|
203 |
| -.commit-message { |
204 |
| - color: var(--vscode-foreground); |
205 |
| -} |
206 |
| -
|
207 |
| -.commit.selected .commit-message, |
208 |
| -.commit.selected .commit-author { |
209 |
| - color: inherit; |
210 | 138 | }
|
211 | 139 | </style>
|
0 commit comments