@@ -19,7 +19,6 @@ import (
1919 "bufio"
2020 "context"
2121 "flag"
22- "fmt"
2322 "io"
2423 "time"
2524
@@ -28,13 +27,12 @@ import (
2827 "k8s.io/klog/v2"
2928
3029 tea "github.com/charmbracelet/bubbletea"
31- "github.com/charmbracelet/lipgloss"
3230 "github.com/charmbracelet/x/ansi"
3331)
3432
3533// RunApp runs the TUI app, using the provided fsck instance to fetch updates from to populate the UI.
3634func RunApp (ctx context.Context , f * fsck.Fsck ) error {
37- m := NewFsckAppModel ()
35+ m := newAppModel ()
3836 p := tea .NewProgram (m )
3937
4038 // Redirect logging so as to appear above the UI
@@ -58,13 +56,13 @@ func RunApp(ctx context.Context, f *fsck.Fsck) error {
5856 case <- ctx .Done ():
5957 // Have the UI update one last time to show where we got to (this helps ensure we see 100%
6058 // on the progress bars if we're exiting because the fsck has completed).
61- p .Send (UpdateCmd (f .Status ())())
59+ p .Send (tui . FsckPanelUpdateCmd (f .Status ())())
6260 // Give the UI a bit of time to render...
6361 <- time .After (100 * time .Millisecond )
6462 // And then we're out.
6563 p .Send (tea .Quit ())
6664 case <- time .After (100 * time .Millisecond ):
67- p .Send (UpdateCmd (f .Status ())())
65+ p .Send (tui . FsckPanelUpdateCmd (f .Status ())())
6866 }
6967 }
7068 }()
@@ -75,31 +73,29 @@ func RunApp(ctx context.Context, f *fsck.Fsck) error {
7573 return nil
7674}
7775
78- // NewFsckAppModel creates a new BubbleTea model for the TUI.
79- func NewFsckAppModel () * FsckAppModel {
80- r := & FsckAppModel {}
76+ // newAppModel creates a new BubbleTea model for the TUI.
77+ func newAppModel () * appModel {
78+ r := & appModel {
79+ fsckPanel : tui .NewFsckPanel (),
80+ }
8181 return r
8282}
8383
84- // FsckAppModel represents the UI model for the FSCK TUI.
85- type FsckAppModel struct {
86- // entriesBar is the status/progress bar representing progress through the entry bundles.
87- entriesBar * tui.LayerProgressModel
88- // titlesBars is the list status/progress bars representing progress through the various levels of tiles in the log.
89- // The zeroth entry corresponds to the tiles on level zero.
90- tilesBars []* tui.LayerProgressModel
91-
84+ // appModel represents the UI model for the FSCK TUI.
85+ type appModel struct {
86+ // fsckPanel displays information about the fsck operation.
87+ fsckPanel * tui.FsckPanel
9288 // width is the width of the app window
9389 width int
9490}
9591
9692// Init is called by Bubbleteam early on to set up the app.
97- func (m * FsckAppModel ) Init () tea.Cmd {
93+ func (m * appModel ) Init () tea.Cmd {
9894 return nil
9995}
10096
10197// Update is called by Bubbletea to handle events.
102- func (m * FsckAppModel ) Update (msg tea.Msg ) (tea.Model , tea.Cmd ) {
98+ func (m * appModel ) Update (msg tea.Msg ) (tea.Model , tea.Cmd ) {
10399 switch msg := msg .(type ) {
104100 case tea.KeyMsg :
105101 // Handle user input.
@@ -111,82 +107,24 @@ func (m *FsckAppModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
111107 return m , nil
112108 case tea.WindowSizeMsg :
113109 m .width = msg .Width
114-
115110 var cmd tea.Cmd
116- cmds := []tea.Cmd {}
117-
118- if m .entriesBar != nil {
119- _ , cmd = m .entriesBar .Update (msg )
120- cmds = append (cmds , cmd )
121- }
122-
123- for _ , t := range m .tilesBars {
124- _ , cmd = t .Update (msg )
125- cmds = append (cmds , cmd )
126- }
127- return m , tea .Batch (cmds ... )
128- case updateMsg :
111+ _ , cmd = m .fsckPanel .Update (msg )
112+ return m , cmd
113+ case tui.FsckPanelUpdateMsg :
129114 // Ignore empty updates
130- if len (msg .s .TileRanges ) == 0 {
115+ if len (msg .Status .TileRanges ) == 0 {
131116 return m , nil
132117 }
133118
134- // Create the range progress bars now that we know how details about the tree.
135- if len (m .tilesBars ) != len (msg .s .TileRanges ) {
136- m .entriesBar = tui .NewLayerProgressBar ("Entry bundles" , m .width , 0 )
137-
138- bs := make ([]* tui.LayerProgressModel , 0 , len (msg .s .TileRanges ))
139- for i := range msg .s .TileRanges {
140- bs = append (bs , tui .NewLayerProgressBar (fmt .Sprintf ("Tiles level %02d" , i ), m .width , i ))
141- }
142- m .tilesBars = bs
143- }
144-
145- // Update all the range progress bars with the latest state.
146- _ , cmd := m .entriesBar .Update (tui.LayerUpdateMsg {Ranges : msg .s .EntryRanges })
147- cmds := []tea.Cmd {cmd }
148- for i := range m .tilesBars {
149- _ , cmd = m .tilesBars [i ].Update (tui.LayerUpdateMsg {Ranges : msg .s .TileRanges [i ]})
150- cmds = append (cmds , cmd )
151- }
152-
153- return m , tea .Batch (cmds ... )
119+ var cmd tea.Cmd
120+ _ , cmd = m .fsckPanel .Update (msg )
121+ return m , cmd
154122 default :
155123 return m , nil
156124 }
157125}
158126
159127// View is called by Bubbletea to render the UI components.
160- func (m * FsckAppModel ) View () string {
161- // Build the progress bars, we'll use this below.
162- bars := []string {}
163- for i := len (m .tilesBars ) - 1 ; i >= 0 ; i -- {
164- t := m .tilesBars [i ]
165- bars = append (bars , t .View ())
166- }
167- if m .entriesBar != nil {
168- bars = append (bars , m .entriesBar .View ())
169- }
170- barsView := lipgloss .JoinVertical (lipgloss .Bottom , bars ... )
171-
172- content := lipgloss .NewStyle ().
173- Width (m .width ).
174- Height (lipgloss .Height (barsView )+ 1 ).
175- Align (lipgloss .Center , lipgloss .Top ).
176- Border (lipgloss .NormalBorder (), true , false , false , false ).
177- Render (barsView )
178-
179- return lipgloss .JoinVertical (lipgloss .Top , content )
180- }
181-
182- // updateMsg is used to tell the model about updated status from the fsck library.
183- type updateMsg struct {
184- s fsck.Status
185- }
186-
187- // UpdateCmd returns a Cmd which Bubbletea can execute in order to retrieve and updateMsg.
188- func UpdateCmd (status fsck.Status ) tea.Cmd {
189- return func () tea.Msg {
190- return updateMsg {s : status }
191- }
128+ func (m * appModel ) View () string {
129+ return m .fsckPanel .View ()
192130}
0 commit comments