tui/page.go (114 lines of code) (raw):

// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tui import ( "os" "strings" "github.com/charmbracelet/bubbles/spinner" tea "github.com/charmbracelet/bubbletea" ) type dynamicPage struct { queue *Queue spinner spinner.Model spinnerLabel string key string value string err error state string content []component preProcessor tea.Cmd postProcessor func(string, *Queue) tea.Cmd preViewFunc func(*Queue) showProgress bool omitFromSettings bool querySlowText string } func (p *dynamicPage) getKey() string { return p.key } func (p *dynamicPage) setValue(s string) { p.value = s } func (p *dynamicPage) getValue() string { return p.value } func (p *dynamicPage) clear() { p.value = "" } func (p *dynamicPage) clearContent() { p.content = []component{} } func (p *dynamicPage) addPostProcessor(f func(string, *Queue) tea.Cmd) { p.postProcessor = f } func (p *dynamicPage) addPreProcessor(f tea.Cmd) { p.preProcessor = f } func (p *dynamicPage) addQueue(q *Queue) { p.queue = q } func (p *dynamicPage) addContent(s ...string) { for _, v := range s { p.content = append(p.content, textBlock(v)) } } func (p *dynamicPage) addPreView(f func(*Queue)) { p.preViewFunc = f } type page struct { dynamicPage } func newPage(key string, content []component) page { p := page{} p.key = key p.content = content p.showProgress = true return p } func (p page) Init() tea.Cmd { return p.preProcessor } func (p page) View() string { if p.preViewFunc != nil { p.preViewFunc(p.queue) } doc := strings.Builder{} doc.WriteString(p.queue.header.render()) if p.showProgress { doc.WriteString(drawProgress(p.queue.calcPercent())) doc.WriteString("\n\n") } for _, v := range p.content { doc.WriteString(bodyStyle.Render(v.render())) doc.WriteString("\n") } doc.WriteString("\n") doc.WriteString(bodyStyle.Render(promptStyle.Render(" Press the Enter Key to continue "))) test := docStyle.Render(doc.String()) return test } // TODO: a test for this is pretty straight forward func (p page) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg.(type) { case successMsg: return p.queue.next() case tea.KeyMsg: switch msg.(tea.KeyMsg).String() { case "alt+b", "ctrl+b": return p.queue.prev() case "ctrl+c", "q": if p.queue.Get("halted") != nil { os.Exit(1) } return p.queue.exitPage() case "enter": if p.postProcessor != nil { if p.state != "querying" { p.state = "querying" p.err = nil return p, p.postProcessor(p.value, p.queue) } return p, nil } return p.queue.next() } } return p, nil }