// VoRS -- Vo(IP) Really Simple // Copyright (C) 2024-2025 Sergey Matveev // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, version 3 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . package main import ( "fmt" "log" "sort" "github.com/jroimartin/gocui" vors "go.stargrave.org/vors/v4/internal" ) var ( GUI *gocui.Gui GUIReady bool GUIReadyC = make(chan struct{}) GUIMaxY int CurrentView = 0 ) func printBell() { fmt.Print("\a") } func tabHandle(gui *gocui.Gui, v *gocui.View) error { sids := make([]int, 0, len(Streams)+1) sids = append(sids, -1) StreamsM.RLock() for sid := range Streams { sids = append(sids, int(sid)) } StreamsM.RUnlock() 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+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)) StreamsM.RLock() for sid := range Streams { sids = append(sids, int(sid)) } StreamsM.RUnlock() sort.Ints(sids) for _, sid := range sids { stream := Streams[byte(sid)] v, err = gui.SetView(stream.name, 0, prevY, maxX/2-1, prevY+2) if err != nil { if err != gocui.ErrUnknownView { return err } if stream.name == *Name { v.Title = ">" + stream.name + "<" } else { v.Title = stream.name if err = GUI.SetKeybinding( stream.name, gocui.KeyEnter, gocui.ModNone, func(*gocui.Gui, *gocui.View) error { stream.silenced = !stream.silenced return nil }, ); err != nil { return err } } } _, err = gui.SetView(stream.name+"-vol", maxX/2, prevY, maxX-1, prevY+2) prevY += 3 if err != nil { if err != gocui.ErrUnknownView { return err } } } if !GUIReady { close(GUIReadyC) GUIReady = true gui.SetCurrentView("chat") } return nil }