Limit Gemini
This commit is contained in:
220
main.go
220
main.go
@@ -3,100 +3,204 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
// Brew represents our mock data structure
|
||||
// --- Data Structures ---
|
||||
|
||||
type Brew struct {
|
||||
Name string
|
||||
Hops string
|
||||
Progress int
|
||||
Notes string
|
||||
}
|
||||
|
||||
type InventoryItem struct {
|
||||
Name string
|
||||
Type string
|
||||
Amount float64
|
||||
Unit string
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := tview.NewApplication()
|
||||
pages := tview.NewPages()
|
||||
|
||||
// Colors - Using GetColor for maximum compatibility
|
||||
cyan := tcell.GetColor("cyan")
|
||||
yellow := tcell.GetColor("yellow")
|
||||
green := tcell.GetColor("green")
|
||||
gray := tcell.GetColor("gray")
|
||||
|
||||
// --- Mock Data ---
|
||||
|
||||
// 1. Mock Data
|
||||
brews := []Brew{
|
||||
{"Midnight Stout", "Fuggles, Goldings", 75},
|
||||
{"Neon IPA", "Citra, Mosaic, Galaxy", 40},
|
||||
{"Summer Wheat", "Saaz, Hallertau", 95},
|
||||
{"Pacific Pale Ale", "Cascade, Amarillo", 10},
|
||||
{"Midnight Stout", "Fuggles, Goldings", 75, "Primary fermentation looking good. Smells like coffee."},
|
||||
{"Neon IPA", "Citra, Mosaic, Galaxy", 40, "Dry hopping starts in 2 days."},
|
||||
{"Summer Wheat", "Saaz, Hallertau", 95, "Ready for bottling/kegging."},
|
||||
}
|
||||
|
||||
// 2. Header with ASCII Logo (Top Right)
|
||||
// We use a TextView for the logo to allow right-alignment
|
||||
inventory := []InventoryItem{
|
||||
{"Citra", "Hops", 500, "g"},
|
||||
{"Pilsner Malt", "Grain", 25, "kg"},
|
||||
{"US-05 SafAle", "Yeast", 4, "packets"},
|
||||
}
|
||||
|
||||
// --- Shared UI Components ---
|
||||
|
||||
logo := tview.NewTextView().
|
||||
SetTextAlign(tview.AlignRight).
|
||||
SetDynamicColors(true).
|
||||
SetText(`[yellow]
|
||||
____ __ __ _
|
||||
| __ ) _ __ _____ __| \/ | __ _ ___| |_ ___ _ __
|
||||
| _ \| '__/ _ \ \ /\ / /| |\/| |/ _` + "`" + `/ __| __/ _ \ '__|
|
||||
| |_) | | | __/\ V V / | | | | (_| \__ \ || __/ |
|
||||
|____/|_| \___| \_/\_/ |_| |_|\__,_|___/\__\___|_|
|
||||
[##] ___ ___ ___ _ _
|
||||
/____\ | _ )| _ \| __| | | |
|
||||
| U | | _ \| /| _|| |/\| |
|
||||
|______| |___/|_|_\|___||__/\__|
|
||||
|'=__='|
|
||||
| | __ __ _ ___ _____ ___ ___
|
||||
|______| | \/ | /_\ / __|_ _| __| _ \
|
||||
| |\/| |/ _ \\__ \ | | | _|| /
|
||||
|_| |_/_/ \_\___/ |_| |___|_|_\
|
||||
`)
|
||||
|
||||
title := tview.NewTextView().
|
||||
SetText(" BrewMaster v0.1.0 - Active Brews").
|
||||
SetTextColor(tcell.ColorCyan)
|
||||
viewTitle := tview.NewTextView().SetTextColor(cyan)
|
||||
|
||||
header := tview.NewFlex().
|
||||
AddItem(title, 0, 1, false).
|
||||
AddItem(viewTitle, 0, 1, false).
|
||||
AddItem(logo, 0, 2, false)
|
||||
|
||||
// 3. Main Table (K9s Style)
|
||||
table := tview.NewTable().
|
||||
SetBorders(false).
|
||||
SetSelectable(true, false)
|
||||
commandBar := tview.NewInputField().
|
||||
SetLabelColor(yellow).
|
||||
SetFieldBackgroundColor(tcell.ColorBlack).
|
||||
SetFieldTextColor(tcell.ColorWhite)
|
||||
|
||||
// Set Table Headers
|
||||
headers := []string{"NAME", "HOPS", "PROGRESS", "STATUS"}
|
||||
for c, h := range headers {
|
||||
table.SetCell(0, c, tview.NewTableCell(fmt.Sprintf("[yellow::b]%s", h)).
|
||||
SetSelectable(false))
|
||||
}
|
||||
|
||||
// Populate Mock Data
|
||||
for r, brew := range brews {
|
||||
row := r + 1
|
||||
table.SetCell(row, 0, tview.NewTableCell(brew.Name).SetTextColor(tcell.ColorWhite))
|
||||
table.SetCell(row, 1, tview.NewTableCell(brew.Hops).SetTextColor(tcell.ColorGray))
|
||||
|
||||
// Progress bar style
|
||||
progressStr := fmt.Sprintf("[%d%%] ", brew.Progress)
|
||||
table.SetCell(row, 2, tview.NewTableCell(progressStr).SetTextColor(tcell.ColorGreen))
|
||||
|
||||
status := "Fermenting"
|
||||
if brew.Progress > 90 {
|
||||
status = "Conditioning"
|
||||
}
|
||||
table.SetCell(row, 3, tview.NewTableCell(status).SetTextColor(tcell.ColorLightBlue))
|
||||
}
|
||||
|
||||
// 4. Footer (Help Menu)
|
||||
footer := tview.NewTextView().
|
||||
SetDynamicColors(true).
|
||||
SetText(" [black:gray] <Ctrl-C> Exit [white:black] [black:gray] <Enter> View Details [white:black] ")
|
||||
SetText(" [black:gray] <:> Command [white:black] [black:gray] <Enter> Describe [white:black] [black:gray] <Ctrl-C> Exit [white:black] ")
|
||||
|
||||
// 5. Layout Assembly
|
||||
grid := tview.NewFlex().SetDirection(tview.FlexRow).
|
||||
AddItem(header, 7, 0, false).
|
||||
AddItem(table, 0, 1, true).
|
||||
// --- View Logic Helpers ---
|
||||
|
||||
// Detail View (The "Describe" screen)
|
||||
detailsView := tview.NewTextView().
|
||||
SetDynamicColors(true).
|
||||
SetRegions(true).
|
||||
SetWrap(true)
|
||||
|
||||
showDetails := func(content string) {
|
||||
detailsView.SetText(content)
|
||||
pages.SwitchToPage("details")
|
||||
}
|
||||
|
||||
// --- Page 1: Active Brews ---
|
||||
brewsTable := tview.NewTable().SetSelectable(true, false)
|
||||
for r, b := range brews {
|
||||
brewsTable.SetCell(r, 0, tview.NewTableCell(b.Name).SetTextColor(tcell.ColorWhite))
|
||||
brewsTable.SetCell(r, 1, tview.NewTableCell(b.Hops).SetTextColor(gray))
|
||||
brewsTable.SetCell(r, 2, tview.NewTableCell(fmt.Sprintf("%d%%", b.Progress)).SetTextColor(green))
|
||||
}
|
||||
brewsTable.SetSelectedFunc(func(row, column int) {
|
||||
b := brews[row]
|
||||
detailText := fmt.Sprintf("\n [yellow]NAME:[-] %s\n [yellow]HOPS:[-] %s\n [yellow]PROGRESS:[-] %d%%\n\n [yellow]NOTES:[-]\n %s\n\n [gray]Press <ESC> to return", b.Name, b.Hops, b.Progress, b.Notes)
|
||||
showDetails(detailText)
|
||||
})
|
||||
|
||||
// --- Page 2: Inventory ---
|
||||
invTable := tview.NewTable().SetSelectable(true, false)
|
||||
for r, item := range inventory {
|
||||
invTable.SetCell(r, 0, tview.NewTableCell(item.Name))
|
||||
invTable.SetCell(r, 1, tview.NewTableCell(fmt.Sprintf("%.1f %s", item.Amount, item.Unit)).SetTextColor(green))
|
||||
}
|
||||
invTable.SetSelectedFunc(func(row, column int) {
|
||||
item := inventory[row]
|
||||
detailText := fmt.Sprintf("\n [yellow]ITEM:[-] %s\n [yellow]TYPE:[-] %s\n [yellow]STOCK:[-] %.1f %s\n\n [gray]Inventory check passed. Ready for next brew.\n\n [gray]Press <ESC> to return", item.Name, item.Type, item.Amount, item.Unit)
|
||||
showDetails(detailText)
|
||||
})
|
||||
|
||||
pages.AddPage("brews", brewsTable, true, true)
|
||||
pages.AddPage("inventory", invTable, true, false)
|
||||
pages.AddPage("details", detailsView, true, false)
|
||||
|
||||
// --- Layout Setup ---
|
||||
mainLayout := tview.NewFlex().SetDirection(tview.FlexRow).
|
||||
AddItem(header, 9, 0, false).
|
||||
AddItem(pages, 0, 1, true).
|
||||
AddItem(footer, 1, 0, false)
|
||||
|
||||
// Global Keybindings
|
||||
root := tview.NewFlex().SetDirection(tview.FlexRow).
|
||||
AddItem(mainLayout, 0, 1, true)
|
||||
|
||||
// --- Global Navigation ---
|
||||
|
||||
showCommandBar := func(label string) {
|
||||
if root.GetItemCount() == 1 {
|
||||
commandBar.SetLabel(label)
|
||||
root.AddItem(commandBar, 1, 0, false)
|
||||
app.SetFocus(commandBar)
|
||||
}
|
||||
}
|
||||
|
||||
hideCommandBar := func() {
|
||||
if root.GetItemCount() > 1 {
|
||||
root.RemoveItem(commandBar)
|
||||
commandBar.SetText("")
|
||||
_, activePage := pages.GetFrontPage()
|
||||
app.SetFocus(activePage)
|
||||
}
|
||||
}
|
||||
|
||||
switchTo := func(pageID string, title string) {
|
||||
viewTitle.SetText(" BrewMaster v0.1.0 - " + title)
|
||||
pages.SwitchToPage(pageID)
|
||||
_, active := pages.GetFrontPage()
|
||||
app.SetFocus(active)
|
||||
}
|
||||
switchTo("brews", "Active Brews")
|
||||
|
||||
// --- Input Handling ---
|
||||
|
||||
commandBar.SetDoneFunc(func(key tcell.Key) {
|
||||
if key == tcell.KeyEscape {
|
||||
hideCommandBar()
|
||||
return
|
||||
}
|
||||
if key == tcell.KeyEnter {
|
||||
cmd := strings.ToLower(strings.TrimSpace(commandBar.GetText()))
|
||||
switch cmd {
|
||||
case "q", "quit":
|
||||
app.Stop()
|
||||
case "i", "inv":
|
||||
switchTo("inventory", "Inventory")
|
||||
case "b", "brew":
|
||||
switchTo("brews", "Active Brews")
|
||||
}
|
||||
hideCommandBar()
|
||||
}
|
||||
})
|
||||
|
||||
app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||
if event.Key() == tcell.KeyCtrlC {
|
||||
app.Stop()
|
||||
os.Exit(0)
|
||||
if app.GetFocus() != commandBar {
|
||||
// ESC to go back from Details to whatever was previous
|
||||
if event.Key() == tcell.KeyEscape {
|
||||
currentPage, _ := pages.GetFrontPage()
|
||||
if currentPage == "details" {
|
||||
// Default back to brews for now
|
||||
switchTo("brews", "Active Brews")
|
||||
}
|
||||
}
|
||||
switch event.Rune() {
|
||||
case ':':
|
||||
showCommandBar(": ")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return event
|
||||
})
|
||||
|
||||
if err := app.SetRoot(grid, true).EnableMouse(true).Run(); err != nil {
|
||||
panic(err)
|
||||
if err := app.SetRoot(root, true).Run(); err != nil {
|
||||
fmt.Printf("Error running app: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user