// Package tui implements a terminal user interface. package tui import ( "fmt" "github.com/rivo/tview" "suruatoel.xyz/timefiles/application" "suruatoel.xyz/timefiles/lib" ) // TUI represents the terminal user interface. // // timeApp is the application to manage the time files. // // uiApp is the tview application. // // uiScreen is the main screen of the terminal application. type TUI struct { timeApp *application.Application uiApp *tview.Application uiScreen *MainScreen } // NewTUI creates a new terminal user interface. func NewTUI() (*TUI, error) { tui := TUI{} tui.timeApp = application.NewApplication(&tui) tui.uiApp = tview.NewApplication() ui, uiErr := NewMainScreen(&tui) if uiErr != nil { return nil, uiErr } tui.uiScreen = ui return &tui, nil } // Run loads the initial application data and runs the terminal user interface. It will wait for the UI to finish and // for all asynchronous jobs to be completed before returning. func (ui *TUI) Run() error { ui.timeApp.Load() ui.timeApp.GetTimer() ui.timeApp.GetTimeSummary() ui.timeApp.GetTimeTotals() err := ui.uiApp.Run() ui.timeApp.Wait() return err } // Focus delegates the focus request of the UI to TUI.uiApp. func (ui *TUI) Focus(p tview.Primitive) { ui.uiApp.SetFocus(p) } // SetTimerStart sets the status for updating the timer. func (ui *TUI) SetTimerStart() { ui.uiApp.QueueUpdateDraw(func() { ui.uiScreen.SetStatus("Updating timer") }) } // SetTimer updates the UI with the timer. func (ui *TUI) SetTimer(timer *lib.Time, err error) { ui.uiApp.QueueUpdateDraw(func() { if err == nil { ui.uiScreen.SetStatus("Timer updated") } else { ui.uiScreen.SetStatus(fmt.Sprintf("Failed to update timer: %s", err)) } ui.uiScreen.SetTimer(timer) }) } // SetSummaryStart sets the status for gathering the time summary. func (ui *TUI) SetSummaryStart() { ui.uiApp.QueueUpdateDraw(func() { ui.uiScreen.SetStatus("Getting summary") }) } // SetSummary updates the UI with the time summary. func (ui *TUI) SetSummary(summary []*lib.Time, err error) { ui.uiApp.QueueUpdateDraw(func() { if err == nil { ui.uiScreen.SetStatus("Summary calculated") } else { ui.uiScreen.SetStatus(fmt.Sprintf("Failed get summary: %s", err)) } ui.uiScreen.SetSummary(summary) }) } // SetTotalsStart sets the status for calculating the time totals. func (ui *TUI) SetTotalsStart() { ui.uiApp.QueueUpdateDraw(func() { ui.uiScreen.SetStatus("Calculated totals") }) } // SetTotals updates the UI with the time totals. func (ui *TUI) SetTotals(totalTime lib.TotalTime, err error) { ui.uiApp.QueueUpdateDraw(func() { if err == nil { ui.uiScreen.SetStatus("Totals calculated") } else { ui.uiScreen.SetStatus(fmt.Sprintf("Failed get totals: %s", err)) } ui.uiScreen.SetTotals(totalTime) }) }