Skip to content

Commit 89fce8d

Browse files
authored
fix: use cache key for side-by-side toggle instead of clearing cache (#77)
## Summary Follow-up to #75 — implements the cache key approach as suggested. - Include side-by-side mode in the diff cache key (`path` vs `path:sbs`) so both renders are cached separately — toggling with `s` is instant after the first render - Invalidate cache on resize since diffs are width-dependent ## Test plan - Toggle side-by-side with `s` on a file, verify it re-renders - Toggle back, verify it's instant (cache hit) - Navigate to another file, come back, verify cache still works - Resize the terminal, verify diff re-renders at the new width
1 parent 12df9f2 commit 89fce8d

1 file changed

Lines changed: 52 additions & 20 deletions

File tree

pkg/ui/panes/diffviewer/diffviewer.go

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ type cachedNode struct {
3030

3131
type nodeCache map[string]*cachedNode
3232

33+
func cacheKey(path string, sideBySide bool) string {
34+
if sideBySide {
35+
return path + ":sbs"
36+
}
37+
return path
38+
}
39+
3340
type Model struct {
3441
common.Common
3542
vp viewport.Model
@@ -75,8 +82,8 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
7582
}
7683
}
7784
diff := strings.Join(lines, "\n")
78-
if _, ok := m.cache[msg.path]; ok {
79-
m.cache[msg.path].diff = diff
85+
if _, ok := m.cache[msg.cacheKey]; ok {
86+
m.cache[msg.cacheKey].diff = diff
8087
}
8188
m.vp.SetContent(diff)
8289
}
@@ -93,20 +100,43 @@ func (m *Model) SetSize(width, height int) tea.Cmd {
93100
m.Height = height
94101
m.vp.SetWidth(m.Width)
95102
m.vp.SetHeight(m.Height - dirHeaderHeight)
103+
m.cache = make(nodeCache)
96104
return m.diff()
97105
}
98106

99107
func (m *Model) diff() tea.Cmd {
100108
if m.file != nil {
101-
if m.file.diff != "" {
109+
key := cacheKey(m.file.path, m.sideBySide)
110+
if cached, ok := m.cache[key]; ok && cached.diff != "" {
111+
m.file = cached
112+
m.vp.SetContent(cached.diff)
102113
return nil
103114
}
104-
return diffFile(m.file, m.Width, m.sideBySide)
115+
node := &cachedNode{
116+
path: m.file.path,
117+
files: m.file.files,
118+
additions: m.file.additions,
119+
deletions: m.file.deletions,
120+
}
121+
m.file = node
122+
m.cache[key] = node
123+
return diffFile(node, m.Width, m.sideBySide)
105124
} else if m.dir != nil {
106-
if m.dir.diff != "" {
125+
key := cacheKey(m.dir.path, m.sideBySide)
126+
if cached, ok := m.cache[key]; ok && cached.diff != "" {
127+
m.dir = cached
128+
m.vp.SetContent(cached.diff)
107129
return nil
108130
}
109-
return diffDir(m.dir, m.Width, m.sideBySide)
131+
node := &cachedNode{
132+
path: m.dir.path,
133+
files: m.dir.files,
134+
additions: m.dir.additions,
135+
deletions: m.dir.deletions,
136+
}
137+
m.dir = node
138+
m.cache[key] = node
139+
return diffDir(node, m.Width, m.sideBySide)
110140
}
111141

112142
return nil
@@ -159,7 +189,8 @@ func (m Model) SetFilePatch(file *gitdiff.File) (Model, tea.Cmd) {
159189
m.dir = nil
160190

161191
fname := filenode.GetFileName(file)
162-
if cached, ok := m.cache[fname]; ok {
192+
key := cacheKey(fname, m.sideBySide)
193+
if cached, ok := m.cache[key]; ok {
163194
m.file = cached
164195
m.vp.SetContent(cached.diff)
165196
return m, nil
@@ -174,15 +205,16 @@ func (m Model) SetFilePatch(file *gitdiff.File) (Model, tea.Cmd) {
174205
additions: additions,
175206
deletions: deletions,
176207
}
177-
m.cache[fname] = m.file
208+
m.cache[key] = m.file
178209

179210
return m, diffFile(m.file, m.Width, m.sideBySide)
180211
}
181212

182213
func (m Model) SetDirPatch(dirPath string, files []*gitdiff.File) (Model, tea.Cmd) {
183214
m.file = nil
184215

185-
if cached, ok := m.cache[dirPath]; ok {
216+
key := cacheKey(dirPath, m.sideBySide)
217+
if cached, ok := m.cache[key]; ok {
186218
m.dir = cached
187219
m.vp.SetContent(cached.diff)
188220
return m, nil
@@ -200,7 +232,7 @@ func (m Model) SetDirPatch(dirPath string, files []*gitdiff.File) (Model, tea.Cm
200232
additions: added,
201233
deletions: deleted,
202234
}
203-
m.cache[dirPath] = m.dir
235+
m.cache[key] = m.dir
204236
return m, diffDir(m.dir, m.Width, m.sideBySide)
205237
}
206238

@@ -224,15 +256,16 @@ func (m *Model) ScrollDown(lines int) {
224256
m.vp.ScrollDown(lines)
225257
}
226258

227-
func diffFile(node *cachedNode, width int, sideBySidePreference bool) tea.Cmd {
259+
func diffFile(node *cachedNode, width int, sideBySide bool) tea.Cmd {
228260
if width == 0 || node == nil || len(node.files) != 1 {
229261
return nil
230262
}
231263

232264
file := node.files[0]
265+
key := cacheKey(node.path, sideBySide)
233266
return func() tea.Msg {
234267
// Only use side-by-side if preference is true AND file is not new/deleted
235-
useSideBySide := sideBySidePreference && !file.IsNew && !file.IsDelete
268+
useSideBySide := sideBySide && !file.IsNew && !file.IsDelete
236269
args := []string{
237270
"--paging=never",
238271
fmt.Sprintf("-w=%d", width),
@@ -248,20 +281,19 @@ func diffFile(node *cachedNode, width int, sideBySidePreference bool) tea.Cmd {
248281
if err != nil {
249282
return common.ErrMsg{Err: err}
250283
}
251-
252-
return diffContentMsg{path: filenode.GetFileName(file), text: string(out)}
284+
return diffContentMsg{cacheKey: key, text: string(out)}
253285
}
254286
}
255287

256-
func diffDir(dir *cachedNode, width int, sideBySidePreference bool) tea.Cmd {
288+
func diffDir(dir *cachedNode, width int, sideBySide bool) tea.Cmd {
257289
if width == 0 || dir == nil {
258290
return nil
259291
}
292+
key := cacheKey(dir.path, sideBySide)
260293
return func() tea.Msg {
261-
// Only use side-by-side if preference is true AND file is not new/deleted
262294
s := common.BgStyles[common.Selected]
263295
c := common.LipglossColorToHex(common.Colors[common.Selected])
264-
useSideBySide := sideBySidePreference
296+
useSideBySide := sideBySide
265297
args := []string{
266298
"--paging=never",
267299
fmt.Sprintf("--file-modified-label=%s",
@@ -290,11 +322,11 @@ func diffDir(dir *cachedNode, width int, sideBySidePreference bool) tea.Cmd {
290322
return common.ErrMsg{Err: err}
291323
}
292324

293-
return diffContentMsg{path: dir.path, text: string(out)}
325+
return diffContentMsg{cacheKey: key, text: string(out)}
294326
}
295327
}
296328

297329
type diffContentMsg struct {
298-
path string
299-
text string
330+
cacheKey string
331+
text string
300332
}

0 commit comments

Comments
 (0)