cmd/client/gui.go | 69 ++++++++++++++++++++++++++++++++++++++++++++++------- cmd/client/main.go | 15 +++++++++++++-- cmd/server/gui.go | 1 + cmd/server/main.go | 12 ++++++++++++ doc/features.texi | 3 ++- doc/proto.texi | 2 +- internal/var.go | 1 + diff --git a/cmd/client/gui.go b/cmd/client/gui.go index 4b06cacd58e6d44afd319636c5bcc54f8d3bc14cb63ac22b39938d08518cb9e2..4f4051cc5076f99e79b2ef4735148b898fe3e4cf53d572e6a303c3d6a4382b6e 100644 --- a/cmd/client/gui.go +++ b/cmd/client/gui.go @@ -17,16 +17,19 @@ package main import ( "fmt" + "log" "sort" "github.com/jroimartin/gocui" + vors "go.stargrave.org/vors/v3/internal" ) var ( - GUI *gocui.Gui - GUIReady bool - GUIReadyC = make(chan struct{}) - GUIMaxY int + GUI *gocui.Gui + GUIReady bool + GUIReadyC = make(chan struct{}) + GUIMaxY int + CurrentView = 0 ) func guiQuit(gui *gocui.Gui, v *gocui.View) error { @@ -39,19 +42,65 @@ muteToggle() return nil } +func tabHandle(gui *gocui.Gui, v *gocui.View) error { + sids := make([]int, 0, len(Streams)+1) + sids = append(sids, -1) + for sid := range Streams { + sids = append(sids, int(sid)) + } + sort.Ints(sids) + if CurrentView+1 >= len(sids) { + CurrentView = 0 + } else { + CurrentView++ + } + if CurrentView == 0 { + gui.SetCurrentView("chat") + } else { + gui.SetCurrentView(Streams[byte(sids[CurrentView])].name) + } + return nil +} + +func chatEnter(gui *gocui.Gui, v *gocui.View) error { + msg := v.Buffer() + if len(msg) > 1 { + Ctrl <- vors.ArgsEncode([]byte(vors.CmdChat), []byte(msg[:len(msg)-1])) + log.Println("me:", msg[:len(msg)-1]) + } + v.Clear() + v.SetCursor(0, 0) + return nil +} + func guiLayout(gui *gocui.Gui) error { var maxX int maxX, GUIMaxY = gui.Size() prevY := 0 - v, err := gui.SetView("logs", 0, prevY, maxX-1, prevY+10+2) - prevY += 10 + 2 + v, err := gui.SetView("logs", 0, prevY, maxX-1, prevY+7+2) + prevY += 7 + 2 if err != nil { if err != gocui.ErrUnknownView { return err } v.Title = fmt.Sprintf("Logs room=%s", *Room) v.Autoscroll = true + v.Wrap = true } + v, err = gui.SetView("chat", 0, prevY, maxX-1, prevY+2) + if err != nil { + if err != gocui.ErrUnknownView { + return err + } + v.Title = "chat" + v.Editable = true + if err := GUI.SetKeybinding( + "chat", gocui.KeyEnter, gocui.ModNone, chatEnter, + ); err != nil { + return err + } + } + prevY += 3 sids := make([]int, 0, len(Streams)) for sid := range Streams { sids = append(sids, int(sid)) @@ -65,7 +114,11 @@ if err != nil { if err != gocui.ErrUnknownView { return err } - v.Title = stream.name + if stream.name == *Name { + v.Title = ">" + stream.name + "<" + } else { + v.Title = stream.name + } } _, err = gui.SetView(stream.name+"-vol", maxX/2, prevY, maxX-1, prevY+2) prevY += 3 @@ -78,7 +131,7 @@ } if !GUIReady { close(GUIReadyC) GUIReady = true - gui.SetCurrentView(*Name) + gui.SetCurrentView("chat") } return nil } diff --git a/cmd/client/main.go b/cmd/client/main.go index 902492b8a990f14522361ba9d91b1dd335260054f3e1aaeded824b659796540b..620dee6289b3cde532a8ab2c3533e93e1c3cb8662cb5238dd61c62c01374e92b 100644 --- a/cmd/client/main.go +++ b/cmd/client/main.go @@ -312,10 +312,13 @@ defer GUI.Close() GUI.SelFgColor = gocui.ColorCyan GUI.Highlight = true GUI.SetManagerFunc(guiLayout) - if err := GUI.SetKeybinding("", 'q', gocui.ModNone, guiQuit); err != nil { + if err := GUI.SetKeybinding("", gocui.KeyTab, gocui.ModNone, tabHandle); err != nil { + log.Fatal(err) + } + if err := GUI.SetKeybinding("", gocui.KeyF1, gocui.ModNone, mute); err != nil { log.Fatal(err) } - if err := GUI.SetKeybinding("", gocui.KeyEnter, gocui.ModNone, mute); err != nil { + if err := GUI.SetKeybinding("", gocui.KeyF10, gocui.ModNone, guiQuit); err != nil { log.Fatal(err) } @@ -545,6 +548,14 @@ log.Println("unknown sid:", sid) continue } s.muted = false + case vors.CmdChat: + sid := args[1][0] + s := Streams[sid] + if s == nil { + log.Println("unknown sid:", sid) + continue + } + log.Println(s.name, ":", string(args[2])) default: log.Fatal("unexpected cmd:", cmd) } diff --git a/cmd/server/gui.go b/cmd/server/gui.go index 5d2e1212537a48d674d583a1a585abc69ee491272d7ac00cb2f4c52fcd64dea6..f2161c15b2a7df8d8902890d72129bb853bdd597f65640c778b576a9308d535d 100644 --- a/cmd/server/gui.go +++ b/cmd/server/gui.go @@ -51,6 +51,7 @@ return err } v.Title = "Logs" v.Autoscroll = true + v.Wrap = true } roomNames := make([]string, 0, len(Rooms)) for n := range Rooms { diff --git a/cmd/server/main.go b/cmd/server/main.go index 9ede9f61c29b3f27937506d7154b31c8315d267d9a4b8f97f575bf85fa70fbd4..75d0b078bdbdc51234e0fe2cf4c798e45dd1b62df8d0927cc02de4a30d411d85 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -328,6 +328,18 @@ continue } go func(tx chan []byte) { tx <- s }(p.tx) } + case vors.CmdChat: + if len(args) != 2 { + logger.Error("wrong len(args)") + continue + } + msg := vors.ArgsEncode([]byte(vors.CmdChat), []byte{peer.sid}, args[1]) + for _, p := range room.peers { + if p.sid == peer.sid { + continue + } + go func(tx chan []byte) { tx <- msg }(p.tx) + } default: logger.Error("unknown", "cmd", cmd) } diff --git a/doc/features.texi b/doc/features.texi index 2d6c6950bfac18a97f799d83270ee195de2dd3f999ab0954dd7aef0c81aeb947..279c12122a65e8e9d38df340871e5cffea605ec4406938a572f11f141fb263cd 100644 --- a/doc/features.texi +++ b/doc/features.texi @@ -18,7 +18,8 @@ server's public key knowledge. @item Fast ChaCha20 encryption with SipHash24 message authentication. -@item Rooms, optionally password protected. +@item Rooms, optionally password protected. Peers are able to broadcast +text message to everyone in the room. @item Fancy TUI client with mute-toggle ability by external utilities. diff --git a/doc/proto.texi b/doc/proto.texi index 1e2d75422ea51248b4426f8abf053b37acda599a3362b27d4d78d13270d17554..57a7a83e6ad8ec27a835417a6a77abcd60ee02b63213dfd60708748b8292c895 100644 --- a/doc/proto.texi +++ b/doc/proto.texi @@ -93,4 +93,4 @@ Clients are notified about new peers appearance with @code{ADD} commands, telling their SIDs, usernames and keys. @code{DEL} notifies about leaving peers. @code{MUTED}, @code{UNMUTED} notifies peer's mute -toggling. +toggling. @code{CHAT} broadcasts the message in the room. diff --git a/internal/var.go b/internal/var.go index 97f6d19e7963811e734035f3cef751c96c7843ebeddaeb6ec33de37ce3e71a87..2cb501d58961996c23762668791718e823adec7c15f82a4fb5893e85497c4aae 100644 --- a/internal/var.go +++ b/internal/var.go @@ -15,6 +15,7 @@ CmdAdd = "ADD" CmdDel = "DEL" CmdMuted = "MUTED" CmdUnmuted = "UNMUTED" + CmdChat = "CHAT" ) var (