Documentation
¶
Overview ¶
Package pane runs Bubble Tea models as Concord remote panes: the same model a plugin uses as a standalone terminal app is driven by viewers' keys and resized to their panes, and its View() becomes their frames.
host := pane.NewHost(func(v *pane.Viewer) tea.Model {
return newBoardModel(v.DisplayName) // your normal Bubble Tea model
})
plugin.Run(ctx, cfg, host.Handler())
Each viewer gets their own model (their own cursor, menus, scroll). Shared state -- a game, a board -- lives outside the models; after changing it, call Host.Broadcast with a message the models react to, and every viewer of that channel is re-rendered. A model returning tea.Quit hands that viewer's keyboard back to Concord (the pane stays on screen).
Colors: render with lipgloss as usual. Frames are produced in true color and converted down to each viewer's terminal (Viewer.Profile), so a model never needs to know who's looking.
Index ¶
- func Fit(view string, width, height int) string
- func KeyMsg(e wire.PluginPaneInputPayload) tea.KeyMsg
- type Host
- func (h *Host) Broadcast(channelID uuid.UUID, msg tea.Msg)
- func (h *Host) Enter(c *plugin.Conn, e wire.PluginPaneEnterPayload)
- func (h *Host) Handler() plugin.Handler
- func (h *Host) Input(c *plugin.Conn, e wire.PluginPaneInputPayload)
- func (h *Host) Leave(_ *plugin.Conn, e wire.PluginPaneLeavePayload)
- func (h *Host) Resize(c *plugin.Conn, e wire.PluginPaneResizePayload)
- func (h *Host) Send(viewerID uuid.UUID, msg tea.Msg)
- func (h *Host) Viewer(id uuid.UUID) *Viewer
- func (h *Host) Viewers(channelID uuid.UUID) []*Viewer
- type Imager
- type KeyClaimer
- type NewModel
- type Viewer
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Host ¶
type Host struct {
// contains filtered or unexported fields
}
Host drives one model per viewer across all of a plugin's pane channels. Its methods must be called from Handler callbacks (which run one at a time), not from other goroutines -- send those work via Conn instead, or wrap the call in the plugin's own event.
func (*Host) Broadcast ¶
Broadcast delivers msg to the model of everyone viewing channelID -- e.g. "the board changed" after a move -- and re-renders each of them. Like Send, it's safe to call from inside a model's own Update: delivery then waits until that update is done.
func (*Host) Enter ¶
func (h *Host) Enter(c *plugin.Conn, e wire.PluginPaneEnterPayload)
Enter starts a model for a viewer (or rebuilds it: Concord replays Enter for current viewers after a reconnect).
func (*Host) Handler ¶
Handler returns plugin callbacks for pane events. To handle other events too, set more fields on the returned Handler (or wrap these).
func (*Host) Input ¶
func (h *Host) Input(c *plugin.Conn, e wire.PluginPaneInputPayload)
Input feeds one keypress to the viewer's model.
func (*Host) Leave ¶
func (h *Host) Leave(_ *plugin.Conn, e wire.PluginPaneLeavePayload)
Leave drops the viewer's model.
func (*Host) Resize ¶
func (h *Host) Resize(c *plugin.Conn, e wire.PluginPaneResizePayload)
Resize tells the viewer's model its new size (and theme).
type Imager ¶
Imager is implemented by a pane model that places images from the plugin's client/ folder in its frames. Images is called after View, with boxes in the same cells (0-based, inside the pane). Leave sensible text under each box: viewers who turned images off see that instead.
type KeyClaimer ¶
type KeyClaimer interface {
ClaimedKeys() []string
}
KeyClaimer is implemented by a pane model that sometimes needs Esc, Tab or Shift+Tab (wire.PaneKeyEsc...). Concord uses those keys to move between panels, so they reach a model only while it claims them: ClaimedKeys is asked after every update, and its answer goes out with the frame. Claim Esc while there's something to cancel (a selection, a menu, a prompt, help), Tab and Shift+Tab while a form's fields are open; claim nothing otherwise, so Esc leaves the pane and Tab moves on.
type NewModel ¶
NewModel builds a model for a viewer who just opened a pane. It's sent a tea.WindowSizeMsg with the pane's size before its first render, and again whenever the pane is resized.
type Viewer ¶
type Viewer struct {
ID uuid.UUID
ChannelID uuid.UUID
Name string // username
DisplayName string // how they appear in the server (nickname, display name or username)
Width int
Height int
Theme *wire.PaneTheme // their Concord theme; may be nil
Profile colorprofile.Profile
// contains filtered or unexported fields
}
Viewer is one person with a pane open.
func (*Viewer) Color ¶
func (v *Viewer) Color(name string, fallback lipgloss.TerminalColor) lipgloss.TerminalColor
Color returns the viewer's Concord theme color by name ("red", "cyan", "foreground", ...) as a lipgloss color, or fallback when unknown -- so a pane can match whatever theme each viewer uses.