diff options
Diffstat (limited to 'ui/views/play.go')
-rw-r--r-- | ui/views/play.go | 213 |
1 files changed, 183 insertions, 30 deletions
diff --git a/ui/views/play.go b/ui/views/play.go index 0c09d2a..b9d9230 100644 --- a/ui/views/play.go +++ b/ui/views/play.go @@ -1,21 +1,92 @@ package views import ( + "errors" + "fmt" + "os" + + "github.com/charmbracelet/bubbles/key" "github.com/charmbracelet/bubbles/textinput" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" ) +var chess string = ` + A B C D E F G H ++---------------+ +8 |♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜| 8 +7 |♟ ♟ ♟ ♟ ♟ ♟ ♟ ♟| 7 +6 |. . . . . . . .| 6 +5 |. . . . . . . .| 5 +4 |. . . . . . . .| 4 +3 |. . . . . . . .| 3 +2 |♙ ♙ ♙ ♙ ♙ ♙ ♙ ♙| 2 +1 |♖ ♘ ♗ ♕ ♔ ♗ ♘ ♖| 1 ++---------------+ + A B C D E F G H +` + +type playKeyMap struct { + EnterNewPlay key.Binding + StartNewPlay key.Binding + GoLogout key.Binding + Quit key.Binding +} + +var defaultPlayKeyMap = playKeyMap{ + EnterNewPlay: key.NewBinding( + key.WithKeys("alt+E", "alt+e"), + key.WithHelp("Alt+E", "Enter a play using code"), + ), + StartNewPlay: key.NewBinding( + key.WithKeys("alt+s", "alt+s"), + key.WithHelp("Alt+S", "Start a new play"), + ), + GoLogout: key.NewBinding( + key.WithKeys("alt+Q", "alt+q"), + key.WithHelp("Alt+Q", "Logout"), + ), + Quit: key.NewBinding( + key.WithKeys("Q", "q"), + key.WithHelp(" Q", "Quit"), + ), +} + +type PlayModelPage int + +const ( + LandingPage PlayModelPage = iota + InsertCodePage + StartPlayPage +) + type PlayModel struct { - width int - height int + width int + height int + err error + keys playKeyMap + namePrompt textinput.Model + page PlayModelPage + isLoading bool } func NewPlayModel(width, height int) PlayModel { + namePrompt := textinput.New() + namePrompt.Prompt = " " + namePrompt.TextStyle = inputStyle + namePrompt.Placeholder = "rectangular-lake" + namePrompt.Focus() + namePrompt.CharLimit = 23 + namePrompt.Width = 23 return PlayModel{ - width: width, - height: height, + width: width, + height: height, + err: nil, + keys: defaultPlayKeyMap, + namePrompt: namePrompt, + page: LandingPage, + isLoading: false, } } @@ -30,40 +101,122 @@ func (m PlayModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "q": - return m, SwitchModelCmd(NewAuthModel(m.width, m.height)) + case tea.WindowSizeMsg: + m.width = msg.Width + m.height = msg.Height + return m, nil + case tea.KeyMsg: + switch { + case key.Matches(msg, m.keys.EnterNewPlay): + m.page = InsertCodePage + return m, nil + case key.Matches(msg, m.keys.StartNewPlay): + // TODO: handle new play + return m, nil + case key.Matches(msg, m.keys.GoLogout): + if err := os.Remove(".rahannarc"); err != nil { + m.err = err + return m, nil + } + return m, SwitchModelCmd(NewAuthModel(m.width, m.height+1)) + case key.Matches(msg, m.keys.Quit): + return m, tea.Quit + case msg.Type == tea.KeyEnter: + if m.page == InsertCodePage { + m.err = errors.New("Can't join for now...") + } } } - return m, nil + + var cmd tea.Cmd = nil + + if m.page == InsertCodePage { + m.namePrompt, cmd = m.namePrompt.Update(msg) + } + + return m, tea.Batch(cmd) } func (m PlayModel) View() string { - width, height := m.width, m.height + formWidth := getFormWidth(m.width) - // Create the window with tab content - ui := lipgloss.JoinVertical(lipgloss.Center, - windowStyle.Width(getFormWidth(width)).Render("New Play"), - ) + // Error message + formError := "" + if m.err != nil { + formError = fmt.Sprintf("Error: %v", m.err.Error()) + } - // Center logo and form in available space - contentHeight := lipgloss.Height(logo) + lipgloss.Height(ui) + 2 - paddingTop := (height - contentHeight) / 2 - if paddingTop < 0 { - paddingTop = 0 + // Status message + statusMsg := fmt.Sprintf("Press %s to join", lipgloss.NewStyle().Italic(true).Render("Enter")) + if m.isLoading { + statusMsg = "Creating account..." } - // Combine logo and tabs with vertical centering - output := lipgloss.NewStyle(). - MarginTop(paddingTop). - Render( - lipgloss.JoinVertical(lipgloss.Center, - getLogo(m.width), - lipgloss.PlaceHorizontal(width, lipgloss.Center, ui), - ), - ) - - return output + var content string + + switch m.page { + case LandingPage: + content = chess + m.namePrompt.Blur() + case InsertCodePage: + m.namePrompt.Focus() + content = m.namePrompt.View() + + content = lipgloss.NewStyle(). + Align(lipgloss.Center). + Width(m.width). + Render( + lipgloss.JoinVertical(lipgloss.Left, + lipgloss.NewStyle().Width(23).Render("Insert play code:"), + m.namePrompt.View(), + lipgloss.NewStyle(). + Align(lipgloss.Center). + PaddingTop(2). + Width(23). + Bold(true). + Render(statusMsg), + ), + ) + } + + windowContent := lipgloss.JoinVertical( + lipgloss.Center, + windowStyle. + Width(formWidth). + Render(lipgloss.JoinVertical( + lipgloss.Center, + errorStyle.Align(lipgloss.Center).Width(formWidth-4).Render(formError), + content, + )), + ) + + enterKey := fmt.Sprintf("%s %s", altCodeStyle.Render(m.keys.EnterNewPlay.Help().Key), m.keys.EnterNewPlay.Help().Desc) + startKey := fmt.Sprintf("%s %s", altCodeStyle.Render(m.keys.StartNewPlay.Help().Key), m.keys.StartNewPlay.Help().Desc) + logoutKey := fmt.Sprintf("%s %s", altCodeStyle.Render(m.keys.GoLogout.Help().Key), m.keys.GoLogout.Help().Desc) + quitKey := fmt.Sprintf("%s %s", altCodeStyle.Render(m.keys.Quit.Help().Key), m.keys.Quit.Help().Desc) + + // Vertically align the buttons + buttons := lipgloss.JoinVertical( + lipgloss.Left, + enterKey, + startKey, + logoutKey, + quitKey, + ) + + centeredContent := lipgloss.JoinVertical( + lipgloss.Center, + getLogo(m.width), + windowContent, + lipgloss.NewStyle().MarginTop(2).Render(buttons), + ) + + return lipgloss.Place( + m.width, + m.height, + lipgloss.Center, + lipgloss.Center, + centeredContent, + ) } |