@@ -29,12 +29,14 @@ func Launch() {
2929}
3030
3131type testModel struct {
32- vp viewport.Model
33- width int
34- height int
35- menu * frame.ListView
36- dialog * frame.Dialog
37- showDialog bool
32+ vp viewport.Model
33+ width int
34+ height int
35+ menu * frame.ListView
36+ dialog * frame.Dialog
37+ showDialog bool
38+ filePicker * frame.FilePicker
39+ showFilePicker bool
3840}
3941
4042func newTestModel () testModel {
@@ -61,6 +63,12 @@ func newTestModel() testModel {
6163 "Ok" ,
6264 )
6365 m .showDialog = false
66+
67+ // Create a file picker starting from home directory
68+ home , _ := os .UserHomeDir ()
69+ m .filePicker = frame .NewFilePicker (home )
70+ m .showFilePicker = false
71+
6472 return m
6573}
6674
@@ -74,13 +82,78 @@ func (m testModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
7482 return m , tea .Quit
7583 case "d" :
7684 m .showDialog = ! m .showDialog
85+ case "f" :
86+ m .showFilePicker = ! m .showFilePicker
87+ // Toggle between load and save mode for testing
88+ if m .showFilePicker {
89+ m .filePicker .SetSaveMode (false ) // Load mode by default, press 's' for save
90+ }
91+ case "s" :
92+ if m .showFilePicker {
93+ // Toggle save mode
94+ m .filePicker .SetSaveMode (! m .filePicker .IsSaveMode ())
95+ }
7796 case "tab" , "right" :
7897 if m .showDialog {
7998 m .dialog .FocusRight ()
99+ } else if m .showFilePicker {
100+ // Tab cycles through: file list -> [filename input] -> OK -> Cancel -> file list
101+ if m .filePicker .IsSaveMode () {
102+ if m .filePicker .Focused == 0 {
103+ m .filePicker .FocusFilename ()
104+ } else if m .filePicker .Focused == 1 {
105+ m .filePicker .FocusOk ()
106+ } else if m .filePicker .Focused == 2 {
107+ m .filePicker .FocusCancel ()
108+ } else {
109+ m .filePicker .FocusFileList ()
110+ }
111+ } else {
112+ if m .filePicker .Focused == 0 {
113+ m .filePicker .FocusOk ()
114+ } else if m .filePicker .Focused == 1 {
115+ m .filePicker .FocusCancel ()
116+ } else {
117+ m .filePicker .FocusFileList ()
118+ }
119+ }
80120 }
81121 case "shift+tab" , "left" :
82122 if m .showDialog {
83123 m .dialog .FocusLeft ()
124+ } else if m .showFilePicker {
125+ // Shift+Tab cycles backward
126+ if m .filePicker .IsSaveMode () {
127+ if m .filePicker .Focused == 0 {
128+ m .filePicker .FocusCancel ()
129+ } else if m .filePicker .Focused == 1 {
130+ m .filePicker .FocusFileList ()
131+ } else if m .filePicker .Focused == 2 {
132+ m .filePicker .FocusFilename ()
133+ } else {
134+ m .filePicker .FocusOk ()
135+ }
136+ } else {
137+ if m .filePicker .Focused == 0 {
138+ m .filePicker .FocusCancel ()
139+ } else if m .filePicker .Focused == 1 {
140+ m .filePicker .FocusFileList ()
141+ } else {
142+ m .filePicker .FocusOk ()
143+ }
144+ }
145+ }
146+ if m .showDialog {
147+ m .dialog .FocusLeft ()
148+ } else if m .showFilePicker {
149+ // Shift+Tab moves through file picker buttons backward
150+ if m .filePicker .Focused == 0 {
151+ m .filePicker .FocusCancel ()
152+ } else if m .filePicker .Focused == 1 {
153+ m .filePicker .FocusFileList ()
154+ } else {
155+ m .filePicker .FocusOk ()
156+ }
84157 }
85158 case "enter" , " " :
86159 if m .showDialog {
@@ -91,23 +164,47 @@ func (m testModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
91164 // Left button (Cancel) pressed
92165 m .showDialog = false
93166 }
167+ } else if m .showFilePicker && m .filePicker .Focused == 0 {
168+ // Enter on file list: enter directory or select file
169+ selected := m .filePicker .SelectCurrent ()
170+ if selected != "" {
171+ // File selected - close picker
172+ m .showFilePicker = false
173+ }
94174 }
95175 case "j" , "down" :
96- if ! m .showDialog {
176+ if ! m .showDialog && ! m . showFilePicker {
97177 m .vp .LineDown (1 )
178+ } else if m .showFilePicker {
179+ m .filePicker .MoveDown ()
98180 }
99181 case "k" , "up" :
100- if ! m .showDialog {
182+ if ! m .showDialog && ! m . showFilePicker {
101183 m .vp .LineUp (1 )
184+ } else if m .showFilePicker {
185+ m .filePicker .MoveUp ()
186+ }
187+ case "u" :
188+ if m .showFilePicker {
189+ m .filePicker .GoUp ()
102190 }
103191 case "J" :
104- if ! m .showDialog {
192+ if ! m .showDialog && ! m . showFilePicker {
105193 m .menu .MoveDown ()
106194 }
107195 case "K" :
108- if ! m .showDialog {
196+ if ! m .showDialog && ! m . showFilePicker {
109197 m .menu .MoveUp ()
110198 }
199+ case "backspace" :
200+ if m .showFilePicker && m .filePicker .Focused == 1 {
201+ m .filePicker .Backspace ()
202+ }
203+ default :
204+ // Handle typing in filename input
205+ if m .showFilePicker && m .filePicker .Focused == 1 && len (msg .String ()) == 1 {
206+ m .filePicker .TypeChar (rune (msg .String ()[0 ]))
207+ }
111208 }
112209 case tea.WindowSizeMsg :
113210 // Reserve 3 lines for header/footer and padding
@@ -181,6 +278,14 @@ func (m testModel) View() string {
181278 return m .overlayDialog (dialogOutput , final )
182279 }
183280
281+ // Step 9: Render file picker if shown (overlay on top of background).
282+ if m .showFilePicker {
283+ m .filePicker .Width = 70
284+ m .filePicker .Height = frameH - 4
285+ pickerOutput := m .filePicker .Render ()
286+ return m .overlayDialog (pickerOutput , final )
287+ }
288+
184289 return final
185290}
186291
0 commit comments