Skip to content

Commit c25c8c3

Browse files
authored
fix(dialog): respect auto_hide config when dismissing dialogs (#276)
Fixes issue where input window would incorrectly appear after dismissing question or permission dialogs when `config.ui.input.auto_hide=true`
1 parent 084127a commit c25c8c3

2 files changed

Lines changed: 298 additions & 2 deletions

File tree

lua/opencode/ui/dialog.lua

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,13 @@ function Dialog:teardown()
145145
self._active = false
146146
self:_clear_keymaps()
147147

148-
-- Show input window if it was hidden
148+
-- Show input window if it was hidden, but only if auto_hide is disabled
149149
if self._config.hide_input then
150+
local config = require('opencode.config')
150151
local input_window = require('opencode.ui.input_window')
151-
input_window._show()
152+
if not config.ui.input.auto_hide then
153+
input_window._show()
154+
end
152155
end
153156
end
154157

tests/unit/dialog_spec.lua

Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
local Dialog = require('opencode.ui.dialog')
2+
local state = require('opencode.state')
3+
local config = require('opencode.config')
4+
5+
describe('Dialog', function()
6+
local input_buf, output_buf, input_win, output_win
7+
local original_auto_hide
8+
9+
before_each(function()
10+
-- Save original config
11+
original_auto_hide = config.ui.input.auto_hide
12+
13+
-- Create test buffers and windows
14+
input_buf = vim.api.nvim_create_buf(false, true)
15+
output_buf = vim.api.nvim_create_buf(false, true)
16+
input_win = vim.api.nvim_open_win(input_buf, true, {
17+
relative = 'editor',
18+
width = 80,
19+
height = 10,
20+
row = 0,
21+
col = 0,
22+
})
23+
output_win = vim.api.nvim_open_win(output_buf, false, {
24+
relative = 'editor',
25+
width = 80,
26+
height = 10,
27+
row = 11,
28+
col = 0,
29+
})
30+
31+
state.windows = {
32+
input_buf = input_buf,
33+
input_win = input_win,
34+
output_buf = output_buf,
35+
output_win = output_win,
36+
}
37+
38+
-- Mock input_window module
39+
package.loaded['opencode.ui.input_window'] = nil
40+
end)
41+
42+
after_each(function()
43+
-- Restore original config
44+
config.ui.input.auto_hide = original_auto_hide
45+
46+
-- Clean up windows and buffers
47+
pcall(vim.api.nvim_win_close, input_win, true)
48+
pcall(vim.api.nvim_win_close, output_win, true)
49+
pcall(vim.api.nvim_buf_delete, input_buf, { force = true })
50+
pcall(vim.api.nvim_buf_delete, output_buf, { force = true })
51+
52+
state.windows = nil
53+
package.loaded['opencode.ui.input_window'] = nil
54+
end)
55+
56+
describe('teardown with hide_input enabled', function()
57+
it('should show input window when auto_hide is disabled', function()
58+
config.ui.input.auto_hide = false
59+
60+
local show_called = false
61+
local input_window = {
62+
_show = function()
63+
show_called = true
64+
end,
65+
_hide = function() end,
66+
}
67+
package.loaded['opencode.ui.input_window'] = input_window
68+
69+
local dialog = Dialog.new({
70+
buffer = output_buf,
71+
on_select = function() end,
72+
get_option_count = function()
73+
return 3
74+
end,
75+
hide_input = true,
76+
})
77+
78+
dialog:setup()
79+
dialog:teardown()
80+
81+
assert.is_true(show_called, 'input window should be shown when auto_hide is disabled')
82+
end)
83+
84+
it('should NOT show input window when auto_hide is enabled', function()
85+
config.ui.input.auto_hide = true
86+
87+
local show_called = false
88+
local input_window = {
89+
_show = function()
90+
show_called = true
91+
end,
92+
_hide = function() end,
93+
}
94+
package.loaded['opencode.ui.input_window'] = input_window
95+
96+
local dialog = Dialog.new({
97+
buffer = output_buf,
98+
on_select = function() end,
99+
get_option_count = function()
100+
return 3
101+
end,
102+
hide_input = true,
103+
})
104+
105+
dialog:setup()
106+
dialog:teardown()
107+
108+
assert.is_false(show_called, 'input window should NOT be shown when auto_hide is enabled')
109+
end)
110+
111+
it('should not call _show when hide_input is disabled', function()
112+
config.ui.input.auto_hide = false
113+
114+
local show_called = false
115+
local input_window = {
116+
_show = function()
117+
show_called = true
118+
end,
119+
_hide = function() end,
120+
}
121+
package.loaded['opencode.ui.input_window'] = input_window
122+
123+
local dialog = Dialog.new({
124+
buffer = output_buf,
125+
on_select = function() end,
126+
get_option_count = function()
127+
return 3
128+
end,
129+
hide_input = false, -- Dialog doesn't manage input window
130+
})
131+
132+
dialog:setup()
133+
dialog:teardown()
134+
135+
assert.is_false(show_called, 'input window should not be managed when hide_input is false')
136+
end)
137+
end)
138+
139+
describe('setup with hide_input enabled', function()
140+
it('should hide input window during setup', function()
141+
config.ui.input.auto_hide = false
142+
143+
local hide_called = false
144+
local input_window = {
145+
_show = function() end,
146+
_hide = function()
147+
hide_called = true
148+
end,
149+
}
150+
package.loaded['opencode.ui.input_window'] = input_window
151+
152+
local dialog = Dialog.new({
153+
buffer = output_buf,
154+
on_select = function() end,
155+
get_option_count = function()
156+
return 3
157+
end,
158+
hide_input = true,
159+
})
160+
161+
dialog:setup()
162+
163+
assert.is_true(hide_called, 'input window should be hidden during dialog setup')
164+
end)
165+
166+
it('should hide input window during setup even with auto_hide enabled', function()
167+
config.ui.input.auto_hide = true
168+
169+
local hide_called = false
170+
local input_window = {
171+
_show = function() end,
172+
_hide = function()
173+
hide_called = true
174+
end,
175+
}
176+
package.loaded['opencode.ui.input_window'] = input_window
177+
178+
local dialog = Dialog.new({
179+
buffer = output_buf,
180+
on_select = function() end,
181+
get_option_count = function()
182+
return 3
183+
end,
184+
hide_input = true,
185+
})
186+
187+
dialog:setup()
188+
189+
assert.is_true(hide_called, 'input window should be hidden during dialog setup regardless of auto_hide')
190+
end)
191+
end)
192+
193+
describe('regression test for question and permission dialogs', function()
194+
it('should not show input after answering question with auto_hide enabled', function()
195+
config.ui.input.auto_hide = true
196+
197+
local show_called = false
198+
local hide_called = false
199+
local input_window = {
200+
_show = function()
201+
show_called = true
202+
end,
203+
_hide = function()
204+
hide_called = true
205+
end,
206+
}
207+
package.loaded['opencode.ui.input_window'] = input_window
208+
209+
-- Simulate question dialog flow
210+
local dialog = Dialog.new({
211+
buffer = output_buf,
212+
on_select = function() end,
213+
get_option_count = function()
214+
return 3
215+
end,
216+
hide_input = true,
217+
})
218+
219+
dialog:setup()
220+
assert.is_true(hide_called, 'input should be hidden when question appears')
221+
222+
show_called = false -- reset
223+
dialog:teardown()
224+
assert.is_false(show_called, 'input should NOT be shown after answering question with auto_hide enabled')
225+
end)
226+
227+
it('should not show input after responding to permission with auto_hide enabled', function()
228+
config.ui.input.auto_hide = true
229+
230+
local show_called = false
231+
local hide_called = false
232+
local input_window = {
233+
_show = function()
234+
show_called = true
235+
end,
236+
_hide = function()
237+
hide_called = true
238+
end,
239+
}
240+
package.loaded['opencode.ui.input_window'] = input_window
241+
242+
-- Simulate permission dialog flow
243+
local dialog = Dialog.new({
244+
buffer = output_buf,
245+
on_select = function() end,
246+
get_option_count = function()
247+
return 3
248+
end,
249+
hide_input = true,
250+
})
251+
252+
dialog:setup()
253+
assert.is_true(hide_called, 'input should be hidden when permission prompt appears')
254+
255+
show_called = false -- reset
256+
dialog:teardown()
257+
assert.is_false(show_called, 'input should NOT be shown after responding to permission with auto_hide enabled')
258+
end)
259+
260+
it('should show input after answering question with auto_hide disabled', function()
261+
config.ui.input.auto_hide = false
262+
263+
local show_called = false
264+
local hide_called = false
265+
local input_window = {
266+
_show = function()
267+
show_called = true
268+
end,
269+
_hide = function()
270+
hide_called = true
271+
end,
272+
}
273+
package.loaded['opencode.ui.input_window'] = input_window
274+
275+
-- Simulate question dialog flow
276+
local dialog = Dialog.new({
277+
buffer = output_buf,
278+
on_select = function() end,
279+
get_option_count = function()
280+
return 3
281+
end,
282+
hide_input = true,
283+
})
284+
285+
dialog:setup()
286+
assert.is_true(hide_called, 'input should be hidden when question appears')
287+
288+
show_called = false -- reset
289+
dialog:teardown()
290+
assert.is_true(show_called, 'input should be shown after answering question with auto_hide disabled')
291+
end)
292+
end)
293+
end)

0 commit comments

Comments
 (0)