Skip to content

Commit

Permalink
Cleanup ui setup
Browse files Browse the repository at this point in the history
  • Loading branch information
bahner committed Feb 22, 2024
1 parent 47c3d83 commit daa0836
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 102 deletions.
68 changes: 0 additions & 68 deletions ui/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import (
"time"

"github.com/bahner/go-ma"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
)

// // displaySelfMessage writes a message from ourself to the message window,
Expand All @@ -27,72 +25,6 @@ func (ui *ChatUI) displaySystemMessage(msg string) {
fmt.Fprintf(ui.msgW, "%s %s\n", prompt, msg)
}

func (ui *ChatUI) setupInputField(inputField *tview.InputField, app *tview.Application) {
inputField.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
case tcell.KeyUp:
if ui.currentHistoryIndex < len(ui.inputHistory)-1 {
ui.currentHistoryIndex++
input := ui.inputHistory[len(ui.inputHistory)-1-ui.currentHistoryIndex]
inputField.SetText(input)
return nil // event handled
}
case tcell.KeyDown:
if ui.currentHistoryIndex > 0 {
ui.currentHistoryIndex--
input := ui.inputHistory[len(ui.inputHistory)-1-ui.currentHistoryIndex]
inputField.SetText(input)
return nil // event handled
} else if ui.currentHistoryIndex == 0 {
ui.currentHistoryIndex = -1
inputField.SetText("") // Clear the input field
return nil // event handled
}
}
return event // let other keys pass through
})

inputField.SetDoneFunc(func(key tcell.Key) {
if key == tcell.KeyEnter {
input := inputField.GetText()
if input != "" {
ui.inputHistory = append(ui.inputHistory, input) // Add to history
ui.currentHistoryIndex = -1 // Reset index
ui.chInput <- input // Send input to be handled
inputField.SetText("") // Clear the input field
}
}
})

// the done func is called when the user hits enter, or tabs out of the field
inputField.SetDoneFunc(func(key tcell.Key) {
if key != tcell.KeyEnter {
// we don't want to do anything if they just tabbed away
return
}

line := inputField.GetText()
if len(line) == 0 {
// ignore blank lines
return
}

// bail if requested
if line == "/quit" {
app.Stop()
return
}

ui.inputHistory = append(ui.inputHistory, line)
ui.currentHistoryIndex = -1

// send the line onto the input chan and reset the field text
ui.chInput <- line
inputField.SetText("")
})

}

// handleEvents runs an event loop that sends user input to the chat room
// and displays messages received from the chat room. It also periodically
// refreshes the list of peers in the UI.
Expand Down
81 changes: 81 additions & 0 deletions ui/input.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package ui

import (
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
"github.com/spf13/viper"
)

func (ui *ChatUI) setupInputField() *tview.InputField {

inputField := tview.NewInputField().
SetLabel(viper.GetString("actor.nick") + ": ").
SetFieldWidth(0).
SetFieldBackgroundColor(tcell.ColorBlack)

inputField.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
case tcell.KeyUp:
if ui.currentHistoryIndex < len(ui.inputHistory)-1 {
ui.currentHistoryIndex++
input := ui.inputHistory[len(ui.inputHistory)-1-ui.currentHistoryIndex]
inputField.SetText(input)
return nil // event handled
}
case tcell.KeyDown:
if ui.currentHistoryIndex > 0 {
ui.currentHistoryIndex--
input := ui.inputHistory[len(ui.inputHistory)-1-ui.currentHistoryIndex]
inputField.SetText(input)
return nil // event handled
} else if ui.currentHistoryIndex == 0 {
ui.currentHistoryIndex = -1
inputField.SetText("") // Clear the input field
return nil // event handled
}
}
return event // let other keys pass through
})

inputField.SetDoneFunc(func(key tcell.Key) {
if key == tcell.KeyEnter {
input := inputField.GetText()
if input != "" {
ui.inputHistory = append(ui.inputHistory, input) // Add to history
ui.currentHistoryIndex = -1 // Reset index
ui.chInput <- input // Send input to be handled
inputField.SetText("") // Clear the input field
}
}
})

// the done func is called when the user hits enter, or tabs out of the field
inputField.SetDoneFunc(func(key tcell.Key) {
if key != tcell.KeyEnter {
// we don't want to do anything if they just tabbed away
return
}

line := inputField.GetText()
if len(line) == 0 {
// ignore blank lines
return
}

// bail if requested
if line == "/quit" {
ui.app.Stop()
return
}

ui.inputHistory = append(ui.inputHistory, line)
ui.currentHistoryIndex = -1

// send the line onto the input chan and reset the field text
ui.chInput <- line
inputField.SetText("")
})

return inputField

}
23 changes: 23 additions & 0 deletions ui/msgbox.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package ui

import "github.com/rivo/tview"

func setupMsgbox(app *tview.Application) *tview.TextView {

// make a text view to contain our chat messages
msgBox := tview.NewTextView()
msgBox.SetDynamicColors(true)
msgBox.SetBorder(true)
msgBox.SetScrollable(true)
msgBox.SetTitle(defaultLimbo)

// text views are io.Writers, but they don't automatically refresh.
// this sets a change handler to force the app to redraw when we get
// new messages to display.
msgBox.SetChangedFunc(func() {
app.Draw()
msgBox.ScrollToEnd()
})

return msgBox
}
47 changes: 13 additions & 34 deletions ui/ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ import (
"github.com/bahner/go-ma-actor/entity/actor"
"github.com/bahner/go-ma-actor/p2p"
"github.com/bahner/go-ma/msg"
"github.com/gdamore/tcell/v2"
p2ppubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/rivo/tview"
"github.com/spf13/viper"
)

const (
Expand Down Expand Up @@ -68,26 +66,7 @@ func NewChatUI(p *p2p.P2P, a *actor.Actor) (*ChatUI, error) {
app := tview.NewApplication()

// make a text view to contain our chat messages
msgBox := tview.NewTextView()
msgBox.SetDynamicColors(true)
msgBox.SetBorder(true)
msgBox.SetScrollable(true)
msgBox.SetTitle(defaultLimbo)

// text views are io.Writers, but they don't automatically refresh.
// this sets a change handler to force the app to redraw when we get
// new messages to display.
msgBox.SetChangedFunc(func() {
app.Draw()
msgBox.ScrollToEnd()
})

// an input field for typing messages into
chInput := make(chan string, 32)
input := tview.NewInputField().
SetLabel(viper.GetString("actor.nick") + ": ").
SetFieldWidth(0).
SetFieldBackgroundColor(tcell.ColorBlack)
msgBox := setupMsgbox(app)

// make a text view to hold the list of peers in the room, updated by ui.refreshPeers()
peersList := tview.NewTextView()
Expand All @@ -101,29 +80,29 @@ func NewChatUI(p *p2p.P2P, a *actor.Actor) (*ChatUI, error) {
AddItem(msgBox, 0, 1, false).
AddItem(peersList, 20, 1, false)

// flex is a vertical box with the chatPanel on top and the input field at the bottom.

flex := tview.NewFlex().
SetDirection(tview.FlexRow).
AddItem(chatPanel, 0, 1, false).
AddItem(input, 1, 1, true)

app.SetRoot(flex, true)

ui := &ChatUI{
a: a,
p: p,
app: app,
peersList: peersList,
msgW: msgBox,
msgBox: msgBox,
chInput: chInput,
chInput: make(chan string, 32),
chMessage: make(chan *msg.Message, UI_MESSAGES_CHANNEL_BUFFERSIZE),
chDone: make(chan struct{}, 1),
}

// A little kludgy, but acceptable for now.
ui.setupInputField(input, app)
// The ordering here is a little kludgy, but acceptable for now.
// the input fiield setup became rather verbose, so it was moved to its own file.
input := ui.setupInputField()

// flex is a vertical box with the chatPanel on top and the input field at the bottom.
flex := tview.NewFlex().
SetDirection(tview.FlexRow).
AddItem(chatPanel, 0, 1, false).
AddItem(input, 1, 1, true)

app.SetRoot(flex, true)

return ui, nil
}
Expand Down

0 comments on commit daa0836

Please sign in to comment.