wip: towards channel based status buffer

This commit is contained in:
2023-07-22 22:14:30 +02:00
parent c3373e707b
commit af2d3a19fe

View File

@ -134,7 +134,7 @@ type model struct {
input textinput.Model input textinput.Model
hiddenInput string hiddenInput string
statusMsgs *[]string statusBuffer chan string
} }
func newModel(username, homeDir string) model { func newModel(username, homeDir string) model {
@ -148,7 +148,7 @@ func newModel(username, homeDir string) model {
userDir: path.Join(homeDir, "/.cairde/"), userDir: path.Join(homeDir, "/.cairde/"),
connState: offline, connState: offline,
input: input, input: input,
statusMsgs: new([]string), statusBuffer: make(chan string),
} }
} }
@ -163,11 +163,8 @@ type appInitialisedMsg struct {
acn connectivity.ACN acn connectivity.ACN
} }
func (m model) statusInfo(msg string) { func (m model) initApp() tea.Cmd {
*m.statusMsgs = append(*m.statusMsgs, msg) return func() tea.Msg {
}
func (m model) initApp() tea.Msg {
mrand.Seed(int64(time.Now().Nanosecond())) mrand.Seed(int64(time.Now().Nanosecond()))
port := mrand.Intn(1000) + 9600 port := mrand.Intn(1000) + 9600
controlPort := port + 1 controlPort := port + 1
@ -195,7 +192,7 @@ func (m model) initApp() tea.Msg {
return errMsg{Err: fmt.Errorf("unable to initialise torrc builder: %s", err)} return errMsg{Err: fmt.Errorf("unable to initialise torrc builder: %s", err)}
} }
m.statusInfo("initialising Tor ACN...") m.statusBuffer <- "initialising Tor ACN..."
acn, err := tor.NewTorACNWithAuth( acn, err := tor.NewTorACNWithAuth(
path.Join(m.userDir, "/.tor"), path.Join(m.userDir, "/.tor"),
"", "",
@ -209,7 +206,7 @@ func (m model) initApp() tea.Msg {
return errMsg{Err: fmt.Errorf("unable to bootstrap tor: %s", err)} return errMsg{Err: fmt.Errorf("unable to bootstrap tor: %s", err)}
} }
m.statusInfo("waiting for Tor ACN to bootstrap...") m.statusBuffer <- "waiting for Tor ACN to bootstrap..."
if err := acn.WaitTillBootstrapped(); err != nil { if err := acn.WaitTillBootstrapped(); err != nil {
return errMsg{Err: fmt.Errorf("unable to initialise tor: %s", err)} return errMsg{Err: fmt.Errorf("unable to initialise tor: %s", err)}
} }
@ -228,17 +225,27 @@ func (m model) initApp() tea.Msg {
engineHooks := connections.DefaultEngineHooks{} engineHooks := connections.DefaultEngineHooks{}
app.InstallEngineHooks(engineHooks) app.InstallEngineHooks(engineHooks)
m.statusInfo("the Tor ACN is up") m.statusBuffer <- "the Tor ACN is up"
return appInitialisedMsg{ return appInitialisedMsg{
app: app, app: app,
acn: acn, acn: acn,
} }
}
}
type statusMsg struct{ msg string }
func (m model) handleStatusMessage() tea.Cmd {
return func() tea.Msg {
return statusMsg{msg: <-m.statusBuffer}
}
} }
func (m model) Init() tea.Cmd { func (m model) Init() tea.Cmd {
return tea.Batch( return tea.Batch(
textinput.Blink, textinput.Blink,
m.handleStatusMessage(),
) )
} }
@ -269,6 +276,7 @@ func (m model) shutdown() bool {
m.app.Shutdown() m.app.Shutdown()
m.acn.Close() m.acn.Close()
close(m.statusBuffer)
return true return true
} }
@ -397,12 +405,6 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
cmds []tea.Cmd cmds []tea.Cmd
) )
m.input, cmd = m.input.Update(msg)
cmds = append(cmds, cmd)
m.viewport, cmd = m.viewport.Update(msg)
cmds = append(cmds, cmd)
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.WindowSizeMsg: case tea.WindowSizeMsg:
m.width = msg.Width - 2 m.width = msg.Width - 2
@ -452,7 +454,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case cmdMsg: case cmdMsg:
m.input.Reset() m.input.Reset()
m.statusInfo(msg.output) m.statusBuffer <- msg.output
case shutdownMsg: case shutdownMsg:
m.input.Reset() m.input.Reset()
@ -465,7 +467,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.input.Reset() m.input.Reset()
m.app.CreateProfile(msg.name, msg.password, false) m.app.CreateProfile(msg.name, msg.password, false)
m.statusInfo(fmt.Sprintf("created new profile: %s", msg.name)) m.statusBuffer <- fmt.Sprintf("created new profile: %s", msg.name)
profiles := m.app.ListProfiles() // TODO profiles := m.app.ListProfiles() // TODO
m.profiles = append(m.profiles, profile{ m.profiles = append(m.profiles, profile{
@ -479,10 +481,10 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch m.connState { switch m.connState {
case offline: case offline:
m.statusInfo("offline, run /connect first?") m.statusBuffer <- "offline, run /connect first?"
break break
case connecting: case connecting:
m.statusInfo("still connecting, hold on a sec...") m.statusBuffer <- "still connecting, hold on a sec..."
break break
} }
@ -500,7 +502,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
for _, p := range unlocked { for _, p := range unlocked {
names = append(names, p.name) names = append(names, p.name)
} }
m.statusInfo(fmt.Sprintf("unlocked profile(s): %s", strings.Join(names, " "))) m.statusBuffer <- fmt.Sprintf("unlocked profile(s): %s", strings.Join(names, " "))
} }
m.profiles = unlocked m.profiles = unlocked
@ -508,45 +510,54 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case profileInfoMsg: case profileInfoMsg:
m.input.Reset() m.input.Reset()
if m.connState != connected { if m.connState != connected {
m.statusInfo("offline, run /connect first?") m.statusBuffer <- "offline, run /connect first?"
break break
} }
if len(m.profiles) == 0 { if len(m.profiles) == 0 {
m.statusInfo("no profiles loaded") m.statusBuffer <- "no profiles loaded"
break break
} }
profile := m.profiles[m.profileState] profile := m.profiles[m.profileState]
m.statusInfo(fmt.Sprintf("profile onion: %s", profile.onion)) m.statusBuffer <- fmt.Sprintf("profile onion: %s", profile.onion)
case statusMsg:
existing := m.viewport.View()
m.viewport.SetContent(existing + "\n" + msg.msg)
m.viewport.GotoBottom()
cmds = append(cmds, m.handleStatusMessage())
case clearMsg: case clearMsg:
m.input.Reset() m.input.Reset()
m.statusMsgs = new([]string) m.viewport.SetContent("")
m.viewport.GotoBottom() m.viewport.GotoBottom()
case connectMsg: case connectMsg:
m.input.Reset() m.input.Reset()
cmds = append(cmds, m.initApp) cmds = append(cmds, m.initApp())
case appInitialisedMsg: case appInitialisedMsg:
m.app = msg.app m.app = msg.app
m.acn = msg.acn m.acn = msg.acn
m.connState = connected m.connState = connected
m.statusInfo("create or unlock a profile to get started") m.statusBuffer <- "create or unlock a profile to get started"
m.statusInfo("run /help to see the command listing") m.statusBuffer <- "run /help to see the command listing"
case errMsg: case errMsg:
m.statusInfo(msg.Error()) m.statusBuffer <- msg.Error()
} }
m.input, cmd = m.input.Update(msg)
cmds = append(cmds, cmd)
m.viewport, cmd = m.viewport.Update(msg)
cmds = append(cmds, cmd)
return m, tea.Batch(cmds...) return m, tea.Batch(cmds...)
} }
func (m model) View() string { func (m model) View() string {
body := strings.Builder{} body := strings.Builder{}
// TODO: adjust when more panes are available
m.viewport.SetContent(strings.Join(*m.statusMsgs, "\n"))
channelBar := channelBarStyle. channelBar := channelBarStyle.
Width(m.width). Width(m.width).
AlignVertical(lipgloss.Center). AlignVertical(lipgloss.Center).