|
@@ -1,15 +1,9 @@
|
|
|
package ui
|
|
package ui
|
|
|
|
|
|
|
|
import (
|
|
import (
|
|
|
- "strings"
|
|
|
|
|
-
|
|
|
|
|
"github.com/ayntgl/discordo/config"
|
|
"github.com/ayntgl/discordo/config"
|
|
|
- "github.com/diamondburned/arikawa/v3/discord"
|
|
|
|
|
- "github.com/diamondburned/arikawa/v3/gateway"
|
|
|
|
|
"github.com/gdamore/tcell/v2"
|
|
"github.com/gdamore/tcell/v2"
|
|
|
"github.com/rivo/tview"
|
|
"github.com/rivo/tview"
|
|
|
- lua "github.com/yuin/gopher-lua"
|
|
|
|
|
- luar "layeh.com/gopher-luar"
|
|
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
type focused int
|
|
type focused int
|
|
@@ -47,7 +41,14 @@ func NewCore(cfg *config.Config) *Core {
|
|
|
Config: cfg,
|
|
Config: cfg,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ tview.Styles.PrimitiveBackgroundColor = tcell.GetColor(cfg.Theme.Background)
|
|
|
|
|
+ tview.Styles.BorderColor = tcell.GetColor(cfg.Theme.Border)
|
|
|
|
|
+ tview.Styles.TitleColor = tcell.GetColor(cfg.Theme.Title)
|
|
|
|
|
+
|
|
|
|
|
+ c.Application.EnableMouse(c.Config.Mouse)
|
|
|
c.Application.SetInputCapture(c.onInputCapture)
|
|
c.Application.SetInputCapture(c.onInputCapture)
|
|
|
|
|
+ c.Application.SetBeforeDrawFunc(c.beforeDraw)
|
|
|
|
|
+
|
|
|
c.GuildsTree = NewGuildsTree(c)
|
|
c.GuildsTree = NewGuildsTree(c)
|
|
|
c.ChannelsTree = NewChannelsTree(c)
|
|
c.ChannelsTree = NewChannelsTree(c)
|
|
|
c.MessagesPanel = NewMessagesPanel(c)
|
|
c.MessagesPanel = NewMessagesPanel(c)
|
|
@@ -56,65 +57,10 @@ func NewCore(cfg *config.Config) *Core {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (c *Core) Run(token string) error {
|
|
func (c *Core) Run(token string) error {
|
|
|
- c.register()
|
|
|
|
|
- err := c.Config.State.DoString(string(config.LuaConfig))
|
|
|
|
|
- if err != nil {
|
|
|
|
|
- return err
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- themeTable, ok := c.Config.State.GetGlobal("theme").(*lua.LTable)
|
|
|
|
|
- if !ok {
|
|
|
|
|
- themeTable = c.Config.State.NewTable()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- backgroundColor := tcell.GetColor(lua.LVAsString(themeTable.RawGetString("background")))
|
|
|
|
|
- borderColor := tcell.GetColor(lua.LVAsString(themeTable.RawGetString("border")))
|
|
|
|
|
- titleColor := tcell.GetColor(lua.LVAsString(themeTable.RawGetString("title")))
|
|
|
|
|
-
|
|
|
|
|
- c.GuildsTree.SetBackgroundColor(backgroundColor)
|
|
|
|
|
- c.GuildsTree.SetBorderColor(borderColor)
|
|
|
|
|
- c.GuildsTree.SetTitleColor(titleColor)
|
|
|
|
|
-
|
|
|
|
|
- c.ChannelsTree.SetBackgroundColor(backgroundColor)
|
|
|
|
|
- c.ChannelsTree.SetBorderColor(borderColor)
|
|
|
|
|
- c.ChannelsTree.SetTitleColor(titleColor)
|
|
|
|
|
-
|
|
|
|
|
- c.MessagesPanel.SetBackgroundColor(backgroundColor)
|
|
|
|
|
- c.MessagesPanel.SetBorderColor(borderColor)
|
|
|
|
|
- c.MessagesPanel.SetTitleColor(titleColor)
|
|
|
|
|
-
|
|
|
|
|
- c.MessageInput.SetBackgroundColor(backgroundColor)
|
|
|
|
|
- c.MessageInput.SetBorderColor(borderColor)
|
|
|
|
|
- c.MessageInput.SetTitleColor(titleColor)
|
|
|
|
|
- c.MessageInput.SetPlaceholderStyle(tcell.StyleDefault.Background(backgroundColor))
|
|
|
|
|
-
|
|
|
|
|
- c.Application.SetBeforeDrawFunc(func(s tcell.Screen) bool {
|
|
|
|
|
- if backgroundColor == 0 {
|
|
|
|
|
- s.Clear()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return false
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- c.Application.EnableMouse(lua.LVAsBool(c.Config.State.GetGlobal("mouse")))
|
|
|
|
|
-
|
|
|
|
|
c.State = NewState(token, c)
|
|
c.State = NewState(token, c)
|
|
|
return c.State.Run()
|
|
return c.State.Run()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (c *Core) register() {
|
|
|
|
|
- c.Config.State.SetGlobal("key", c.Config.State.NewFunction(c.Config.KeyLua))
|
|
|
|
|
- // Messages panel
|
|
|
|
|
- c.Config.State.SetGlobal("openMessageActionsList", c.Config.State.NewFunction(c.MessagesPanel.openMessageActionsListLua))
|
|
|
|
|
- c.Config.State.SetGlobal("selectPreviousMessage", c.Config.State.NewFunction(c.MessagesPanel.selectPreviousMessageLua))
|
|
|
|
|
- c.Config.State.SetGlobal("selectNextMessage", c.Config.State.NewFunction(c.MessagesPanel.selectNextMessageLua))
|
|
|
|
|
- c.Config.State.SetGlobal("selectFirstMessage", c.Config.State.NewFunction(c.MessagesPanel.selectFirstMessageLua))
|
|
|
|
|
- c.Config.State.SetGlobal("selectLastMessage", c.Config.State.NewFunction(c.MessagesPanel.selectLastMessageLua))
|
|
|
|
|
- // Message input
|
|
|
|
|
- c.Config.State.SetGlobal("openExternalEditor", c.Config.State.NewFunction(c.MessageInput.openExternalEditorLua))
|
|
|
|
|
- c.Config.State.SetGlobal("pasteClipboardContent", c.Config.State.NewFunction(c.MessageInput.pasteClipboardContentLua))
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
func (c *Core) DrawMainFlex() {
|
|
func (c *Core) DrawMainFlex() {
|
|
|
leftFlex := tview.NewFlex().
|
|
leftFlex := tview.NewFlex().
|
|
|
SetDirection(tview.FlexRow).
|
|
SetDirection(tview.FlexRow).
|
|
@@ -129,52 +75,21 @@ func (c *Core) DrawMainFlex() {
|
|
|
AddItem(rightFlex, 0, 4, false)
|
|
AddItem(rightFlex, 0, 4, false)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (c *Core) onInputCapture(e *tcell.EventKey) *tcell.EventKey {
|
|
|
|
|
- // If the main flex is nil, that is, it is not initialized yet, then the login form is currently focused.
|
|
|
|
|
- if c.MainFlex == nil {
|
|
|
|
|
- return e
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- keysTable, ok := c.Config.State.GetGlobal("keys").(*lua.LTable)
|
|
|
|
|
- if !ok {
|
|
|
|
|
- keysTable = c.Config.State.NewTable()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- applicationTable, ok := keysTable.RawGetString("application").(*lua.LTable)
|
|
|
|
|
- if !ok {
|
|
|
|
|
- applicationTable = c.Config.State.NewTable()
|
|
|
|
|
|
|
+func (c *Core) beforeDraw(screen tcell.Screen) bool {
|
|
|
|
|
+ if c.Config.Theme.Background == "default" {
|
|
|
|
|
+ screen.Clear()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- var fn lua.LValue
|
|
|
|
|
- applicationTable.ForEach(func(k, v lua.LValue) {
|
|
|
|
|
- keyTable := v.(*lua.LTable)
|
|
|
|
|
- if e.Name() == lua.LVAsString(keyTable.RawGetString("name")) {
|
|
|
|
|
- fn = keyTable.RawGetString("action")
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- if fn != nil {
|
|
|
|
|
- c.Config.State.CallByParam(lua.P{
|
|
|
|
|
- Fn: fn,
|
|
|
|
|
- NRet: 1,
|
|
|
|
|
- Protect: true,
|
|
|
|
|
- }, luar.New(c.Config.State, c), luar.New(c.Config.State, e))
|
|
|
|
|
- // Returned value
|
|
|
|
|
- ret, ok := c.Config.State.Get(-1).(*lua.LUserData)
|
|
|
|
|
- if !ok {
|
|
|
|
|
- return e
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ return false
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- // Remove returned value
|
|
|
|
|
- c.Config.State.Pop(1)
|
|
|
|
|
- ev, ok := ret.Value.(*tcell.EventKey)
|
|
|
|
|
- if ok {
|
|
|
|
|
- return ev
|
|
|
|
|
- }
|
|
|
|
|
|
|
+func (c *Core) onInputCapture(event *tcell.EventKey) *tcell.EventKey {
|
|
|
|
|
+ // If the main flex is nil, that is, it is not initialized yet, then the login form is currently focused.
|
|
|
|
|
+ if c.MainFlex == nil {
|
|
|
|
|
+ return event
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Default
|
|
|
|
|
- switch e.Key() {
|
|
|
|
|
|
|
+ switch event.Key() {
|
|
|
case tcell.KeyEsc:
|
|
case tcell.KeyEsc:
|
|
|
c.focused = 0
|
|
c.focused = 0
|
|
|
case tcell.KeyBacktab:
|
|
case tcell.KeyBacktab:
|
|
@@ -197,7 +112,7 @@ func (c *Core) onInputCapture(e *tcell.EventKey) *tcell.EventKey {
|
|
|
c.setFocus()
|
|
c.setFocus()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return e
|
|
|
|
|
|
|
+ return event
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (c *Core) setFocus() {
|
|
func (c *Core) setFocus() {
|
|
@@ -215,101 +130,3 @@ func (c *Core) setFocus() {
|
|
|
|
|
|
|
|
c.Application.SetFocus(p)
|
|
c.Application.SetFocus(p)
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
-func (c *Core) onStateReady(r *gateway.ReadyEvent) {
|
|
|
|
|
- rootNode := c.GuildsTree.GetRoot()
|
|
|
|
|
- for _, gf := range r.UserSettings.GuildFolders {
|
|
|
|
|
- if gf.ID == 0 {
|
|
|
|
|
- for _, gID := range gf.GuildIDs {
|
|
|
|
|
- g, err := c.State.Cabinet.Guild(gID)
|
|
|
|
|
- if err != nil {
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- guildNode := tview.NewTreeNode(g.Name)
|
|
|
|
|
- guildNode.SetReference(g.ID)
|
|
|
|
|
- rootNode.AddChild(guildNode)
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- var b strings.Builder
|
|
|
|
|
-
|
|
|
|
|
- if gf.Color != discord.NullColor {
|
|
|
|
|
- b.WriteByte('[')
|
|
|
|
|
- b.WriteString(gf.Color.String())
|
|
|
|
|
- b.WriteByte(']')
|
|
|
|
|
- } else {
|
|
|
|
|
- b.WriteString("[#ED4245]")
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if gf.Name != "" {
|
|
|
|
|
- b.WriteString(gf.Name)
|
|
|
|
|
- } else {
|
|
|
|
|
- b.WriteString("Folder")
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- b.WriteString("[-]")
|
|
|
|
|
-
|
|
|
|
|
- folderNode := tview.NewTreeNode(b.String())
|
|
|
|
|
- rootNode.AddChild(folderNode)
|
|
|
|
|
-
|
|
|
|
|
- for _, gID := range gf.GuildIDs {
|
|
|
|
|
- g, err := c.State.Cabinet.Guild(gID)
|
|
|
|
|
- if err != nil {
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- guildNode := tview.NewTreeNode(g.Name)
|
|
|
|
|
- guildNode.SetReference(g.ID)
|
|
|
|
|
- folderNode.AddChild(guildNode)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- c.GuildsTree.SetCurrentNode(rootNode)
|
|
|
|
|
- c.Application.SetFocus(c.GuildsTree)
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-func (c *Core) onStateGuildCreate(g *gateway.GuildCreateEvent) {
|
|
|
|
|
- guildNode := tview.NewTreeNode(g.Name)
|
|
|
|
|
- guildNode.SetReference(g.ID)
|
|
|
|
|
-
|
|
|
|
|
- rootNode := c.GuildsTree.GetRoot()
|
|
|
|
|
- rootNode.AddChild(guildNode)
|
|
|
|
|
-
|
|
|
|
|
- c.GuildsTree.SetCurrentNode(rootNode)
|
|
|
|
|
- c.Application.SetFocus(c.GuildsTree)
|
|
|
|
|
- c.Application.Draw()
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-func (c *Core) onStateGuildDelete(g *gateway.GuildDeleteEvent) {
|
|
|
|
|
- rootNode := c.GuildsTree.GetRoot()
|
|
|
|
|
- var parentNode *tview.TreeNode
|
|
|
|
|
- rootNode.Walk(func(node, _ *tview.TreeNode) bool {
|
|
|
|
|
- if node.GetReference() == g.ID {
|
|
|
|
|
- parentNode = node
|
|
|
|
|
- return false
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return true
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- if parentNode != nil {
|
|
|
|
|
- rootNode.RemoveChild(parentNode)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- c.Application.Draw()
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-func (c *Core) onStateMessageCreate(m *gateway.MessageCreateEvent) {
|
|
|
|
|
- if c.ChannelsTree.SelectedChannel != nil && c.ChannelsTree.SelectedChannel.ID == m.ChannelID {
|
|
|
|
|
- _, err := c.MessagesPanel.Write(buildMessage(c, m.Message))
|
|
|
|
|
- if err != nil {
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if len(c.MessagesPanel.GetHighlights()) == 0 {
|
|
|
|
|
- c.MessagesPanel.ScrollToEnd()
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|