X-Git-Url: https://git.r.bdr.sh/rbdr/mobius/blobdiff_plain/43ecc0f42eaeface5f640479df7372bfb8021f23..61c272e101b6f0444c7b2a666b0b5e828ba6db03:/hotline/ui.go?ds=inline diff --git a/hotline/ui.go b/hotline/ui.go index 5056954..d0fd6c0 100644 --- a/hotline/ui.go +++ b/hotline/ui.go @@ -1,7 +1,6 @@ package hotline import ( - "errors" "fmt" "github.com/davecgh/go-spew/spew" "github.com/gdamore/tcell/v2" @@ -15,17 +14,20 @@ import ( ) type UI struct { - chatBox *tview.TextView - chatInput *tview.InputField - App *tview.Application - Pages *tview.Pages - userList *tview.TextView - agreeModal *tview.Modal - trackerList *tview.List - settingsPage *tview.Box - HLClient *Client + chatBox *tview.TextView + chatInput *tview.InputField + App *tview.Application + Pages *tview.Pages + userList *tview.TextView + trackerList *tview.List + HLClient *Client } +// pages +const ( + pageServerUI = "serverUI" +) + func NewUI(c *Client) *UI { app := tview.NewApplication() chatBox := tview.NewTextView(). @@ -35,7 +37,7 @@ func NewUI(c *Client) *UI { SetChangedFunc(func() { app.Draw() // TODO: docs say this is bad but it's the only way to show content during initial render?? }) - chatBox.Box.SetBorder(true).SetTitle("Chat") + chatBox.Box.SetBorder(true).SetTitle("| Chat |") chatInput := tview.NewInputField() chatInput. @@ -47,7 +49,7 @@ func NewUI(c *Client) *UI { return } - c.Send( + _ = c.Send( *NewTransaction(tranChatSend, nil, NewField(fieldData, []byte(chatInput.GetText())), ), @@ -72,7 +74,6 @@ func NewUI(c *Client) *UI { chatInput: chatInput, userList: userList, trackerList: tview.NewList(), - agreeModal: tview.NewModal(), HLClient: c, } } @@ -95,7 +96,7 @@ func (ui *UI) showBookmarks() *tview.List { list.AddItem(srv.Name, srv.Addr, rune(shortcut+i), func() { ui.Pages.RemovePage("joinServer") - newJS := ui.renderJoinServerForm(addr, login, pass, "bookmarks", true, true) + newJS := ui.renderJoinServerForm("", addr, login, pass, "bookmarks", true, true) ui.Pages.AddPage("joinServer", newJS, true, true) }) @@ -122,10 +123,11 @@ func (ui *UI) getTrackerList() *tview.List { shortcut := 97 // rune for "a" for i, srv := range listing { addr := srv.Addr() + srvName := srv.Name list.AddItem(string(srv.Name), string(srv.Description), rune(shortcut+i), func() { ui.Pages.RemovePage("joinServer") - newJS := ui.renderJoinServerForm(addr, GuestAccount, "", trackerListPage, false, true) + newJS := ui.renderJoinServerForm(string(srvName), addr, GuestAccount, "", trackerListPage, false, true) ui.Pages.AddPage("joinServer", newJS, true, true) ui.Pages.ShowPage("joinServer") @@ -187,8 +189,12 @@ func (ui *UI) renderSettingsForm() *tview.Flex { } func (ui *UI) joinServer(addr, login, password string) error { + // append default port to address if no port supplied + if len(strings.Split(addr, ":")) == 1 { + addr += ":5500" + } if err := ui.HLClient.JoinServer(addr, login, password); err != nil { - return errors.New(fmt.Sprintf("Error joining server: %v\n", err)) + return fmt.Errorf("Error joining server: %v\n", err) } go func() { @@ -197,21 +203,21 @@ func (ui *UI) joinServer(addr, login, password string) error { if err != nil { ui.HLClient.Logger.Errorw("read error", "err", err) - msg := err.Error() if err == io.EOF { - msg = "The server connection has unexpectedly closed." + loginErrModal := tview.NewModal(). + AddButtons([]string{"Ok"}). + SetText("The server connection has closed."). + SetDoneFunc(func(buttonIndex int, buttonLabel string) { + ui.Pages.SwitchToPage("home") + }) + loginErrModal.Box.SetTitle("Server Connection Error") + + ui.Pages.AddPage("loginErr", loginErrModal, false, true) + ui.App.Draw() + return } + ui.Pages.SwitchToPage("home") - loginErrModal := tview.NewModal(). - AddButtons([]string{"Ok"}). - SetText(msg). - SetDoneFunc(func(buttonIndex int, buttonLabel string) { - ui.Pages.SwitchToPage("home") - }) - loginErrModal.Box.SetTitle("Server Connection Error") - - ui.Pages.AddPage("loginErr", loginErrModal, false, true) - ui.App.Draw() return } } @@ -220,24 +226,47 @@ func (ui *UI) joinServer(addr, login, password string) error { return nil } -func (ui *UI) renderJoinServerForm(server, login, password, backPage string, save, defaultConnect bool) *tview.Flex { +func (ui *UI) renderJoinServerForm(name, server, login, password, backPage string, save, defaultConnect bool) *tview.Flex { joinServerForm := tview.NewForm() joinServerForm. + // AddInputField("Name", server, 0, func(textToCheck string, lastChar rune) bool { + // return false + //}, nil). AddInputField("Server", server, 0, nil, nil). AddInputField("Login", login, 0, nil, nil). AddPasswordField("Password", password, 0, '*', nil). AddCheckbox("Save", save, func(checked bool) { + ui.HLClient.Logger.Infow("saving bookmark") // TODO: Implement bookmark saving + + ui.HLClient.pref.AddBookmark(joinServerForm.GetFormItem(0).(*tview.InputField).GetText(), joinServerForm.GetFormItem(0).(*tview.InputField).GetText(), joinServerForm.GetFormItem(1).(*tview.InputField).GetText(), joinServerForm.GetFormItem(2).(*tview.InputField).GetText()) + out, err := yaml.Marshal(ui.HLClient.pref) + if err != nil { + panic(err) + } + + err = ioutil.WriteFile(ui.HLClient.cfgPath, out, 0666) + if err != nil { + panic(err) + } + // pref := ui.HLClient.pref }). AddButton("Cancel", func() { ui.Pages.SwitchToPage(backPage) }). AddButton("Connect", func() { + srvAddr := joinServerForm.GetFormItem(0).(*tview.InputField).GetText() + loginInput := joinServerForm.GetFormItem(1).(*tview.InputField).GetText() err := ui.joinServer( - joinServerForm.GetFormItem(0).(*tview.InputField).GetText(), - joinServerForm.GetFormItem(1).(*tview.InputField).GetText(), + srvAddr, + loginInput, joinServerForm.GetFormItem(2).(*tview.InputField).GetText(), ) + if name == "" { + name = fmt.Sprintf("%s@%s", loginInput, srvAddr) + } + ui.HLClient.serverName = name + if err != nil { ui.HLClient.Logger.Errorw("login error", "err", err) loginErrModal := tview.NewModal(). @@ -281,9 +310,10 @@ func (ui *UI) renderJoinServerForm(server, login, password, backPage string, sav } func (ui *UI) renderServerUI() *tview.Flex { + ui.chatBox.SetText("") // clear any previously existing chatbox text commandList := tview.NewTextView().SetDynamicColors(true) commandList. - SetText("[yellow]^n[-::]: Read News [yellow]^p[-::]: Post News\n[yellow]^l[-::]: View Logs\n"). + SetText("[yellow]^n[-::]: Read News [yellow]^p[-::]: Post News\n[yellow]^l[-::]: View Logs [yellow]^f[-::]: View Files\n"). SetBorder(true). SetTitle("| Keyboard Shortcuts| ") @@ -294,7 +324,7 @@ func (ui *UI) renderServerUI() *tview.Flex { modal.SetDoneFunc(func(buttonIndex int, buttonLabel string) { if buttonIndex == 1 { _ = ui.HLClient.Disconnect() - ui.Pages.SwitchToPage("home") + ui.Pages.RemovePage(pageServerUI) } else { ui.Pages.HidePage("modal") } @@ -307,7 +337,7 @@ func (ui *UI) renderServerUI() *tview.Flex { AddItem(ui.chatBox, 0, 8, false). AddItem(ui.chatInput, 3, 0, true), 0, 1, true). AddItem(ui.userList, 25, 1, false) - serverUI.SetBorder(true).SetTitle("| Mobius - Connected to " + "TODO" + " |").SetTitleAlign(tview.AlignLeft) + serverUI.SetBorder(true).SetTitle("| Mobius - Connected to " + ui.HLClient.serverName + " |").SetTitleAlign(tview.AlignLeft) serverUI.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { if event.Key() == tcell.KeyEscape { ui.Pages.AddPage("modal", modal, false, true) @@ -331,23 +361,28 @@ func (ui *UI) renderServerUI() *tview.Flex { if event.Key() == tcell.KeyCtrlP { newsFlex := tview.NewFlex() - + newsFlex.SetBorderPadding(0, 0, 1, 1) newsPostTextArea := tview.NewTextView() - newsPostTextArea.SetBackgroundColor(tcell.ColorDimGray) + newsPostTextArea.SetBackgroundColor(tcell.ColorDarkSlateGrey) newsPostTextArea.SetChangedFunc(func() { ui.App.Draw() // TODO: docs say this is bad but it's the only way to show content during initial render?? }) - //newsPostTextArea.SetBorderPadding(0, 0, 1, 1) newsPostForm := tview.NewForm(). SetButtonsAlign(tview.AlignRight). - AddButton("Post", nil) + //AddButton("Cancel", nil). // TODO: implement cancel button behavior + AddButton("Send", nil) newsPostForm.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { switch event.Key() { + case tcell.KeyEscape: + ui.Pages.RemovePage("newsInput") case tcell.KeyTab: ui.App.SetFocus(newsPostTextArea) case tcell.KeyEnter: newsText := strings.ReplaceAll(newsPostTextArea.GetText(true), "\n", "\r") + if len(newsText) == 0 { + return event + } err := ui.HLClient.Send( *NewTransaction(tranOldPostNews, nil, NewField(fieldData, []byte(newsText)), @@ -357,7 +392,6 @@ func (ui *UI) renderServerUI() *tview.Flex { ui.HLClient.Logger.Errorw("Error posting news", "err", err) // TODO: display errModal to user } - //newsInput.SetText("") // clear the input field after chat send ui.Pages.RemovePage("newsInput") } @@ -367,17 +401,16 @@ func (ui *UI) renderServerUI() *tview.Flex { newsFlex. SetDirection(tview.FlexRow). SetBorder(true). - SetTitle("News Post") + SetTitle("| Post Message |") newsPostTextArea.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { - ui.HLClient.Logger.Infow("key", "key", event.Key(), "rune", event.Rune()) switch event.Key() { case tcell.KeyEscape: ui.Pages.RemovePage("newsInput") case tcell.KeyTab: ui.App.SetFocus(newsPostForm) case tcell.KeyEnter: - fmt.Fprintf(newsPostTextArea, "\n") + _, _ = fmt.Fprintf(newsPostTextArea, "\n") default: const windowsBackspaceRune = 8 const macBackspaceRune = 127 @@ -389,7 +422,7 @@ func (ui *UI) renderServerUI() *tview.Flex { newsPostTextArea.SetText(curTxt) } default: - fmt.Fprintf(newsPostTextArea, string(event.Rune())) + _, _ = fmt.Fprintf(newsPostTextArea, string(event.Rune())) } } @@ -439,7 +472,7 @@ func (ui *UI) Start() { ) mainMenu.AddItem("Join Server", "", 'j', func() { - joinServerPage := ui.renderJoinServerForm("", GuestAccount, "", "home", false, false) + joinServerPage := ui.renderJoinServerForm("", "", GuestAccount, "", "home", false, false) ui.Pages.AddPage("joinServer", joinServerPage, true, true) }). AddItem("Bookmarks", "", 'b', func() {