util.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. package ui
  2. import (
  3. "cmp"
  4. "slices"
  5. "strings"
  6. "github.com/ayn2op/discordo/internal/config"
  7. "github.com/ayn2op/tview"
  8. "github.com/diamondburned/arikawa/v3/discord"
  9. "github.com/gdamore/tcell/v3"
  10. )
  11. // ConfigureBox configures the provided box according to the provided theme.
  12. func ConfigureBox(box *tview.Box, cfg *config.Theme) *tview.Box {
  13. border := cfg.Border
  14. normalBorderStyle, activeBorderStyle := border.NormalStyle.Style, border.ActiveStyle.Style
  15. normalBorderSet, activeBorderSet := border.NormalSet.BorderSet, border.ActiveSet.BorderSet
  16. title := cfg.Title
  17. normalTitleStyle, activeTitleStyle := title.NormalStyle.Style, title.ActiveStyle.Style
  18. footer := cfg.Footer
  19. normalFooterStyle, activeFooterStyle := footer.NormalStyle.Style, footer.ActiveStyle.Style
  20. padding := border.Padding
  21. box.
  22. SetBorderStyle(normalBorderStyle).
  23. SetBorderSet(normalBorderSet).
  24. SetBorderPadding(padding[0], padding[1], padding[2], padding[3]).
  25. SetTitleStyle(normalTitleStyle).
  26. SetTitleAlignment(title.Alignment.Alignment).
  27. SetFooterStyle(normalFooterStyle).
  28. SetFooterAlignment(footer.Alignment.Alignment).
  29. SetBlurFunc(func() {
  30. box.
  31. SetBorderStyle(normalBorderStyle).
  32. SetBorderSet(normalBorderSet)
  33. box.SetTitleStyle(normalTitleStyle).SetFooterStyle(normalFooterStyle)
  34. }).
  35. SetFocusFunc(func() {
  36. box.
  37. SetBorderStyle(activeBorderStyle).
  38. SetBorderSet(activeBorderSet)
  39. box.SetTitleStyle(activeTitleStyle).SetFooterStyle(activeFooterStyle)
  40. })
  41. if border.Enabled {
  42. box.SetBorders(tview.BordersAll)
  43. }
  44. return box
  45. }
  46. // Centered creates a new grid with provided primitive aligned in the center.
  47. func Centered(p tview.Primitive, width, height int) tview.Primitive {
  48. return tview.NewGrid().
  49. SetColumns(0, width, 0).
  50. SetRows(0, height, 0).
  51. AddItem(p, 1, 1, 1, 1, 0, 0, true)
  52. }
  53. func ChannelToString(channel discord.Channel, icons config.Icons) string {
  54. var icon string
  55. switch channel.Type {
  56. case discord.DirectMessage, discord.GroupDM:
  57. if channel.Name != "" {
  58. return channel.Name
  59. }
  60. recipients := make([]string, len(channel.DMRecipients))
  61. for i, r := range channel.DMRecipients {
  62. recipients[i] = r.DisplayOrUsername()
  63. }
  64. return strings.Join(recipients, ", ")
  65. case discord.GuildCategory:
  66. icon = icons.GuildCategory
  67. case discord.GuildText:
  68. icon = icons.GuildText
  69. case discord.GuildVoice:
  70. icon = icons.GuildVoice
  71. case discord.GuildStageVoice:
  72. icon = icons.GuildStageVoice
  73. case discord.GuildAnnouncementThread:
  74. icon = icons.GuildAnnouncementThread
  75. case discord.GuildPublicThread:
  76. icon = icons.GuildPublicThread
  77. case discord.GuildPrivateThread:
  78. icon = icons.GuildPrivateThread
  79. case discord.GuildAnnouncement:
  80. icon = icons.GuildAnnouncement
  81. case discord.GuildForum:
  82. icon = icons.GuildForum
  83. case discord.GuildStore:
  84. icon = icons.GuildStore
  85. }
  86. return icon + channel.Name
  87. }
  88. func SortGuildChannels(channels []discord.Channel) {
  89. slices.SortFunc(channels, func(a, b discord.Channel) int {
  90. return cmp.Compare(a.Position, b.Position)
  91. })
  92. }
  93. func SortPrivateChannels(channels []discord.Channel) {
  94. slices.SortFunc(channels, func(a, b discord.Channel) int {
  95. // Descending order
  96. return cmp.Compare(getMessageIDFromChannel(b), getMessageIDFromChannel(a))
  97. })
  98. }
  99. func getMessageIDFromChannel(channel discord.Channel) discord.MessageID {
  100. if channel.LastMessageID.IsValid() {
  101. return channel.LastMessageID
  102. }
  103. return discord.MessageID(channel.ID)
  104. }
  105. func MergeStyle(base, overlay tcell.Style) tcell.Style {
  106. fg := overlay.GetForeground()
  107. if fg == tcell.ColorDefault {
  108. fg = base.GetForeground()
  109. }
  110. bg := overlay.GetBackground()
  111. if bg == tcell.ColorDefault {
  112. bg = base.GetBackground()
  113. }
  114. style := base.Foreground(fg).Background(bg)
  115. style = style.Bold(base.HasBold() || overlay.HasBold())
  116. style = style.Dim(base.HasDim() || overlay.HasDim())
  117. style = style.Italic(base.HasItalic() || overlay.HasItalic())
  118. style = style.Blink(base.HasBlink() || overlay.HasBlink())
  119. style = style.Reverse(base.HasReverse() || overlay.HasReverse())
  120. style = style.StrikeThrough(base.HasStrikeThrough() || overlay.HasStrikeThrough())
  121. if base.HasUnderline() || overlay.HasUnderline() {
  122. style = style.Underline(true)
  123. }
  124. return style
  125. }