clone

a terminal ui for alamo drafthouse showtimes, as movie cards or a timeline of every screen

main
showings / internal / state / render.go
render.go 2.8K
1package state23import (4 "fmt"5 "strings"67 "github.com/charmbracelet/lipgloss"8)910func (m *Model) renderShowtimesView() string {11 var content []string1213 content = append(content, m.renderHeader())14 content = append(content, separatorStyle.Render(separatorText))15 content = append(content, "")16 content = append(content, m.viewport.View())17 content = append(content, "")18 content = append(content, m.renderFooter())1920 return lipgloss.JoinVertical(lipgloss.Left, content...)21}2223func (m *Model) renderHeader() string {24 name := ""25 if m.cinemaName != "" {26 name = cinemaNameStyle.Render(m.cinemaName) + " "27 }2829 dateInfo := m.renderFilterInfo()3031 mode := ""32 if m.ganttMode {33 mode = " " + modeBadgeStyle.Render(" Timeline ")34 }3536 return name + dateInfo + mode37}3839func (m *Model) renderFilterInfo() string {40 if m.selectedDate == nil {41 return filterStyle.Render(" All dates ")42 }4344 formatted := m.selectedDate.Format("Mon Jan 2")45 return filterActive.Render(" " + formatted + " ")46}4748func (m *Model) renderFooter() string {49 hint := hintText50 if m.ganttMode {51 hint = hintTextGantt52 }53 rendered := hintStyle.Render(hint)5455 scrollPct := ""56 if m.viewport.TotalLineCount() > m.viewport.Height {57 pct := int(m.viewport.ScrollPercent() * 100)58 scrollPct = scrollStyle.Render(fmt.Sprintf(" %d%% ", pct))59 }6061 return rendered + " " + scrollPct62}6364func (m *Model) renderWithModal(base string) string {65 // Build the modal content66 var items []string67 items = append(items, modalTitleStyle.Render("Select Location"))68 items = append(items, "")6970 // Find max venue name length for consistent row widths71 maxLen := 072 for _, v := range m.venues {73 if len(v.Name) > maxLen {74 maxLen = len(v.Name)75 }76 }77 rowWidth := maxLen + 4 // "* " prefix + padding7879 for i, v := range m.venues {80 isCurrent := v.Slug == m.venue81 isHovered := i == m.venueCursor8283 // Color dot indicator84 dot := modalDotStyle(i).Render("●")8586 prefix := " "87 if isCurrent {88 prefix = "* "89 }9091 label := prefix + v.Name9293 var style lipgloss.Style94 if isHovered && isCurrent {95 style = modalSelectedCurrentStyle96 } else if isHovered {97 style = modalSelectedStyle98 } else if isCurrent {99 style = modalCurrentStyle100 } else {101 style = modalItemStyle102 }103104 styled := style.Width(rowWidth).Render(label)105 items = append(items, dot+" "+styled)106 }107108 items = append(items, "")109 items = append(items, modalHintStyle.Render("↑↓ navigate enter select esc close"))110111 inner := strings.Join(items, "\n")112 modal := modalBoxStyle.Render(inner)113114 // Center the modal on a dim background that fills the screen.115 // The base view is not shown to avoid ANSI compositing issues --116 // instead we use a uniform dim background.117 return lipgloss.Place(118 m.width, m.height,119 lipgloss.Center, lipgloss.Center,120 modal,121 lipgloss.WithWhitespaceChars("░"),122 lipgloss.WithWhitespaceForeground(lipgloss.Color("236")),123 )124}