From 91bd232fe2ad5fefbe479ec4763584fd0e7a092b Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Tue, 9 Feb 2021 14:23:15 -0500 Subject: [PATCH] Add example illustrating how to send messages via channels in realtime --- examples/realtime/main.go | 92 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 examples/realtime/main.go diff --git a/examples/realtime/main.go b/examples/realtime/main.go new file mode 100644 index 0000000..c2bd4c9 --- /dev/null +++ b/examples/realtime/main.go @@ -0,0 +1,92 @@ +package main + +// A simple example that shows how to send activity to Bubble Tea in real-time +// through a channel. + +import ( + "fmt" + "math/rand" + "os" + "time" + + "github.com/charmbracelet/bubbles/spinner" + tea "github.com/charmbracelet/bubbletea" +) + +// A message used to indicate that activity has occured. In the real world (for +// example, chat) this would contain actual data. +type responseMsg struct{} + +// Simulate a process that sends events at an irregular interval in real time. +// In this case, we'll send events on the channel at a random interval between +// 100 to 1000 milliseconds. As a command, Bubble Tea will run this +// asyncronously. +func listenForActivity(sub chan struct{}) tea.Cmd { + return func() tea.Msg { + for { + time.Sleep(time.Millisecond * time.Duration(rand.Int63n(900)+100)) + sub <- struct{}{} + } + } +} + +// A command that waits for the activity on a channel. +func waitForActivity(sub chan struct{}) tea.Cmd { + return func() tea.Msg { + return responseMsg(<-sub) + } +} + +type model struct { + sub chan struct{} // where we'll receive activity notifications + responses int // how many responses we've received + spinner spinner.Model + quitting bool +} + +func (m model) Init() tea.Cmd { + return tea.Batch( + spinner.Tick, + listenForActivity(m.sub), // generate activity + waitForActivity(m.sub), // wait for activity + ) +} + +func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + switch msg.(type) { + case tea.KeyMsg: + m.quitting = true + return m, tea.Quit + case responseMsg: + m.responses++ // record external activity + return m, waitForActivity(m.sub) // wait for next event + case spinner.TickMsg: + var cmd tea.Cmd + m.spinner, cmd = m.spinner.Update(msg) + return m, cmd + default: + return m, nil + } +} + +func (m model) View() string { + s := fmt.Sprintf("\n %s Events received: %d\n\n Press any key to exit\n", m.spinner.View(), m.responses) + if m.quitting { + s += "\n" + } + return s +} + +func main() { + rand.Seed(time.Now().UTC().UnixNano()) + + p := tea.NewProgram(model{ + sub: make(chan struct{}), + spinner: spinner.NewModel(), + }) + + if p.Start() != nil { + fmt.Println("could not start program") + os.Exit(1) + } +}