messages_panel.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. package ui
  2. import (
  3. "github.com/diamondburned/arikawa/v3/discord"
  4. "github.com/gdamore/tcell/v2"
  5. "github.com/rivo/tview"
  6. lua "github.com/yuin/gopher-lua"
  7. luar "layeh.com/gopher-luar"
  8. )
  9. type MessagesPanel struct {
  10. *tview.TextView
  11. // The index of the currently selected message. A negative index indicates that there is no currently selected message.
  12. SelectedMessage int
  13. core *Core
  14. }
  15. func NewMessagesPanel(c *Core) *MessagesPanel {
  16. mp := &MessagesPanel{
  17. TextView: tview.NewTextView(),
  18. SelectedMessage: -1,
  19. core: c,
  20. }
  21. mp.SetDynamicColors(true)
  22. mp.SetRegions(true)
  23. mp.SetWordWrap(true)
  24. mp.SetInputCapture(mp.onInputCapture)
  25. mp.SetChangedFunc(func() {
  26. mp.core.Application.Draw()
  27. })
  28. mp.SetTitle("Messages")
  29. mp.SetTitleAlign(tview.AlignLeft)
  30. mp.SetBorder(true)
  31. mp.SetBorderPadding(0, 0, 1, 1)
  32. return mp
  33. }
  34. func (mp *MessagesPanel) onInputCapture(e *tcell.EventKey) *tcell.EventKey {
  35. if mp.core.ChannelsTree.SelectedChannel == nil {
  36. return nil
  37. }
  38. // Messages should return messages ordered from latest to earliest.
  39. ms, err := mp.core.State.Cabinet.Messages(mp.core.ChannelsTree.SelectedChannel.ID)
  40. if err != nil || len(ms) == 0 {
  41. return nil
  42. }
  43. keysTable, ok := mp.core.Config.State.GetGlobal("keys").(*lua.LTable)
  44. if !ok {
  45. keysTable = mp.core.Config.State.NewTable()
  46. }
  47. messagesPanel, ok := keysTable.RawGetString("messagesPanel").(*lua.LTable)
  48. if !ok {
  49. messagesPanel = mp.core.Config.State.NewTable()
  50. }
  51. var fn lua.LValue
  52. messagesPanel.ForEach(func(k, v lua.LValue) {
  53. keyTable := v.(*lua.LTable)
  54. if e.Name() == lua.LVAsString(keyTable.RawGetString("name")) {
  55. fn = keyTable.RawGetString("action")
  56. }
  57. })
  58. if fn != nil {
  59. mp.core.Config.State.CallByParam(lua.P{
  60. Fn: fn,
  61. NRet: 1,
  62. Protect: true,
  63. }, luar.New(mp.core.Config.State, mp.core), luar.New(mp.core.Config.State, e))
  64. // Returned value
  65. ret, ok := mp.core.Config.State.Get(-1).(*lua.LUserData)
  66. if !ok {
  67. return e
  68. }
  69. // Remove returned value
  70. mp.core.Config.State.Pop(1)
  71. ev, ok := ret.Value.(*tcell.EventKey)
  72. if ok {
  73. return ev
  74. }
  75. }
  76. // Defaults
  77. switch e.Name() {
  78. case "Esc":
  79. mp.SelectedMessage = -1
  80. mp.core.Application.SetFocus(mp.core.MainFlex)
  81. mp.
  82. Clear().
  83. Highlight().
  84. SetTitle("")
  85. return nil
  86. }
  87. return e
  88. }
  89. func (mp *MessagesPanel) selectPreviousMessageLua(s *lua.LState) int {
  90. // Messages should return messages ordered from latest to earliest.
  91. ms, err := mp.core.State.Cabinet.Messages(mp.core.ChannelsTree.SelectedChannel.ID)
  92. if err != nil || len(ms) == 0 {
  93. return returnNilLua(s)
  94. }
  95. // If there are no highlighted regions, select the latest (last) message in the messages panel.
  96. if len(mp.GetHighlights()) == 0 {
  97. mp.SelectedMessage = 0
  98. } else {
  99. // If the selected message is the oldest (first) message, select the latest (last) message in the messages panel.
  100. if mp.SelectedMessage == len(ms)-1 {
  101. mp.SelectedMessage = 0
  102. } else {
  103. mp.SelectedMessage++
  104. }
  105. }
  106. mp.Highlight(ms[mp.SelectedMessage].ID.String())
  107. mp.ScrollToHighlight()
  108. return returnNilLua(s)
  109. }
  110. func (mp *MessagesPanel) selectNextMessageLua(s *lua.LState) int {
  111. // Messages should return messages ordered from latest to earliest.
  112. ms, err := mp.core.State.Cabinet.Messages(mp.core.ChannelsTree.SelectedChannel.ID)
  113. if err != nil || len(ms) == 0 {
  114. return returnNilLua(s)
  115. }
  116. // If there are no highlighted regions, select the latest (last) message in the messages panel.
  117. if len(mp.GetHighlights()) == 0 {
  118. mp.SelectedMessage = 0
  119. } else {
  120. // If the selected message is the latest (last) message, select the oldest (first) message in the messages panel.
  121. if mp.SelectedMessage == 0 {
  122. mp.SelectedMessage = len(ms) - 1
  123. } else {
  124. mp.SelectedMessage--
  125. }
  126. }
  127. mp.
  128. Highlight(ms[mp.SelectedMessage].ID.String()).
  129. ScrollToHighlight()
  130. return returnNilLua(s)
  131. }
  132. func (mp *MessagesPanel) selectFirstMessageLua(s *lua.LState) int {
  133. // Messages should return messages ordered from latest to earliest.
  134. ms, err := mp.core.State.Cabinet.Messages(mp.core.ChannelsTree.SelectedChannel.ID)
  135. if err != nil || len(ms) == 0 {
  136. return returnNilLua(s)
  137. }
  138. mp.SelectedMessage = len(ms) - 1
  139. mp.
  140. Highlight(ms[mp.SelectedMessage].ID.String()).
  141. ScrollToHighlight()
  142. return returnNilLua(s)
  143. }
  144. func (mp *MessagesPanel) selectLastMessageLua(s *lua.LState) int {
  145. // Messages should return messages ordered from latest to earliest.
  146. ms, err := mp.core.State.Cabinet.Messages(mp.core.ChannelsTree.SelectedChannel.ID)
  147. if err != nil || len(ms) == 0 {
  148. return returnNilLua(s)
  149. }
  150. mp.SelectedMessage = 0
  151. mp.
  152. Highlight(ms[mp.SelectedMessage].ID.String()).
  153. ScrollToHighlight()
  154. return returnNilLua(s)
  155. }
  156. func (mp *MessagesPanel) openMessageActionsListLua(s *lua.LState) int {
  157. // Messages should return messages ordered from latest to earliest.
  158. ms, err := mp.core.State.Cabinet.Messages(mp.core.ChannelsTree.SelectedChannel.ID)
  159. if err != nil || len(ms) == 0 {
  160. return returnNilLua(s)
  161. }
  162. hs := mp.GetHighlights()
  163. if len(hs) == 0 {
  164. return returnNilLua(s)
  165. }
  166. mID, err := discord.ParseSnowflake(hs[0])
  167. if err != nil {
  168. return returnNilLua(s)
  169. }
  170. _, m := findMessageByID(ms, discord.MessageID(mID))
  171. if m == nil {
  172. return returnNilLua(s)
  173. }
  174. actionsList := NewMessageActionsList(mp.core, m)
  175. mp.core.Application.SetRoot(actionsList, true)
  176. return returnNilLua(s)
  177. }