package ui import ( "image" "github.com/gdamore/tcell/v2" "github.com/rivo/tview" ) const ( coverRows = 20 // poster height in terminal rows minCoverRows = 6 // a smaller poster is not worth showing minTextRows = 10 // the poster never takes these rows from the text ) // detailPane shows a poster above a text. The poster shrinks on short panes // and is dropped when the text would get too little room. type detailPane struct { *tview.Flex app *App cover *coverView text *tview.TextView want string // key of the poster that should be shown hasCover bool // a poster (or its loading note) is part of the content coverSize int // rows currently given to the poster } func newDetailPane(app *App) *detailPane { d := &detailPane{ Flex: tview.NewFlex().SetDirection(tview.FlexRow), app: app, cover: newCoverView(), text: tview.NewTextView().SetDynamicColors(true).SetWordWrap(true), } d.AddItem(d.cover, 0, 0, false).AddItem(d.text, 0, 1, false) d.SetBorder(true).SetTitle(" Details ") return d } // Show displays the text and, if there is one, the poster. func (d *detailPane) Show(text string, ref coverRef) { d.text.SetText(text).ScrollToBeginning() if !d.app.covers || ref.fetch == nil { d.want, d.hasCover = "", false d.cover.setImage(nil) return } d.want, d.hasCover = ref.key, true d.cover.setNote("loading cover…") want := ref.key d.app.loadCover(ref, func(img *image.RGBA, err error) { if d.want != want { return // the selection moved on } if err != nil { d.hasCover = false // nothing to show: give the room back to the text d.cover.setImage(nil) return } d.cover.setImage(img) }) } // Clear empties the pane. func (d *detailPane) Clear() { d.Show("", coverRef{}) } func (d *detailPane) Draw(screen tcell.Screen) { _, _, _, h := d.GetInnerRect() rows := 0 if d.hasCover { rows = min(coverRows, h-minTextRows) if rows < minCoverRows { rows = 0 } } if rows != d.coverSize { d.coverSize = rows d.ResizeItem(d.cover, rows, 0) } d.Flex.Draw(screen) }