|
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