Replies: 1 comment
-
Adding some code snippets to get help on this. package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
tea "github.com/charmbracelet/bubbletea"
)
const url = "https://midgard.ninerealms.com/v2/pools"
type errMsg struct{ error }
func (e errMsg) Error() string { return e.error.Error() }
type poolsMsg struct {
pools []Pool
}
type Pool struct {
Asset string `json:"asset"`
}
type model struct {
pools []Pool
Err error
cursor int
}
func (m model) Init() tea.Cmd {
return fetchPools
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case poolsMsg:
m.pools = msg.pools
case errMsg:
m.Err = msg
return m, nil
case tea.KeyMsg:
switch msg.String() {
case "q":
return m, tea.Quit
case "j", "down":
m.cursor++
if m.cursor >= len(m.pools) {
m.cursor = 0
}
return m, nil
case "k", "up":
m.cursor--
if m.cursor < 0 {
m.cursor = len(m.pools) - 1
}
return m, nil
}
}
return m, nil
}
func (m model) View() string {
s := fmt.Sprintf("Checking %s...\n", url)
if m.Err != nil {
s += fmt.Sprintf("something went wrong: %s", m.Err)
} else {
s += fmt.Sprintf("Found %d pools\n", len(m.pools))
for i, pool := range m.pools {
cursor := " " // no cursor
if m.cursor == i {
cursor = ">" // cursor!
}
s += fmt.Sprintf("%s %s\n", cursor, pool.Asset)
}
}
return s + "\n"
}
func main() {
p := tea.NewProgram(model{})
if _, err := p.Run(); err != nil {
fmt.Printf("Alas, there's been an error: %v", err)
os.Exit(1)
}
}
func fetchPools() tea.Msg {
resp, err := http.Get("https://midgard.ninerealms.com/v2/pools")
if err != nil {
return errMsg{err}
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
return errMsg{err}
}
var pools []Pool
err = json.Unmarshal(data, &pools)
if err != nil {
return errMsg{err}
}
return poolsMsg{pools}
} But when I separate things into their own packages, something is going wrong with the HTTP request when it is inside of a nested model. // main.go
package main
import (
"fmt"
"os"
"github.com/stuartwk/http_troubleshooting/pools"
tea "github.com/charmbracelet/bubbletea"
)
type sessionState int
const (
poolsView sessionState = iota
poolView
)
type model struct {
state sessionState
poolsModel pools.Model
}
func (m model) Init() tea.Cmd {
return nil
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmd tea.Cmd
var cmds []tea.Cmd
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "q", "ctrl+c", "esc":
return m, tea.Quit
}
}
switch m.state {
case poolsView:
newPool, newCmd := m.poolsModel.Update(msg)
poolModel, ok := newPool.(pools.Model)
if !ok {
panic("could not asset pools.Model")
}
m.poolsModel = poolModel
cmd = newCmd
default:
return m, nil
}
cmds = append(cmds, cmd)
return m, tea.Batch(cmds...)
}
func (m model) View() string {
switch m.state {
case poolsView:
return m.poolsModel.View()
default:
return m.poolsModel.View()
}
}
func main() {
p := tea.NewProgram(model{})
if _, err := p.Run(); err != nil {
fmt.Printf("Alas, there's been an error: %v", err)
os.Exit(1)
}
} // pools/pools.go
package pools
import (
"encoding/json"
"fmt"
"io"
"net/http"
tea "github.com/charmbracelet/bubbletea"
)
const url = "https://midgard.ninerealms.com/v2/pools"
type errMsg struct{ error }
func (e errMsg) Error() string { return e.error.Error() }
type poolsMsg []Pool
type Pool struct {
Asset string `json:"asset"`
}
type Model struct {
pools []Pool
Err error
cursor int
}
func (m Model) Init() tea.Cmd {
return fetchPools
}
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case poolsMsg:
m.pools = msg
return m, nil
case errMsg:
m.Err = msg
return m, nil
case tea.KeyMsg:
switch msg.String() {
case "j", "down":
m.cursor++
if m.cursor >= len(m.pools) {
m.cursor = 0
}
return m, nil
case "k", "up":
m.cursor--
if m.cursor < 0 {
m.cursor = len(m.pools) - 1
}
return m, nil
}
}
return m, nil
}
func (m Model) View() string {
s := fmt.Sprintf("Fetching %s...\n", url)
if m.Err != nil {
s += fmt.Sprintf("something went wrong: %s", m.Err)
} else {
// log the number of pools there are
s += fmt.Sprintf("Found %d pools\n", len(m.pools))
for i, pool := range m.pools {
cursor := " " // no cursor
if m.cursor == i {
cursor = ">" // cursor!
}
s += fmt.Sprintf("%s %s\n", cursor, pool.Asset)
}
}
return s + "\n"
}
func fetchPools() tea.Msg {
resp, err := http.Get("https://midgard.ninerealms.com/v2/pools")
if err != nil {
return errMsg{err}
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
return errMsg{err}
}
var pools []Pool
err = json.Unmarshal(data, &pools)
if err != nil {
return errMsg{err}
}
return poolsMsg(pools)
} Basically, fetchPools works if it's in not nested, but breaks when it is nested in a sub model. Any help appreciated! |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Hey folks, I'm just getting started with Bubble Tea.
I created a really simple project, which makes an HTTP call, and displays a list based on what is returned: https://github.com/stuartwk/nested_model_troubleshooting. This works fine.
I want to build it out a bit more, so I tried moving the code into a sub model. But the HTTP request isn't working once I moved the code into a sub model. Exact same fetch function, just moved. Returns a statuscode of 0. No data returned or rendered. https://github.com/stuartwk/nested_model_troubleshooting/tree/pools-package
I feel like I'm making a noob mistake and missing something simple. Any ideas why this code works if everything is in the main model, but when I move it into a sub model, it fails? Thanks in advance!
Beta Was this translation helpful? Give feedback.
All reactions