feat: merge channels & guilds TreeView for ease-of-use (#37)

* feat: merge channels & guilds TreeView for ease-of-use

* docs: update README preview
This commit is contained in:
rigormorrtiss 2021-08-30 13:57:35 +04:00 • committed by GitHub
parent 88e27fa413
commit 93a422bc9e
5 changed files with 50 additions and 75 deletions

BIN
.github/preview.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

After

Width:  |  Height:  |  Size: 197 KiB

View file

@ -43,10 +43,9 @@ By default, Discordo utilizes OS-specific keyring to store credentials such as c
### Default Keybindings
- `Alt` + `g`: Sets the focus on the guilds treeview.
- `Alt` + `c`: Sets the focus on the channels treeview.
- `Alt` + `m`: Sets the focus on the messages textview.
- `Alt` + `i`: Sets the focus on the message inputfield.
- `Alt` + `g`: Sets the focus on the guilds TreeView.
- `Alt` + `m`: Sets the focus on the messages TextView.
- `Alt` + `i`: Sets the focus on the message InputField.
### Clipboard

View file

@ -16,7 +16,6 @@ var (
app *tview.Application
loginForm *tview.Form
guildsTreeView *tview.TreeView
channelsTreeView *tview.TreeView
messagesTextView *tview.TextView
messageInputField *tview.InputField
mainFlex *tview.Flex
@ -37,10 +36,9 @@ func main() {
EnableMouse(config.Mouse).
SetInputCapture(onAppInputCapture)
guildsTreeView = ui.NewGuildsTreeView(onGuildsTreeViewSelected)
channelsTreeView = ui.NewChannelsTreeView(onChannelsTreeViewSelected)
messagesTextView = ui.NewMessagesTextView(app)
messageInputField = ui.NewMessageInputField(onMessageInputFieldInputCapture)
mainFlex = ui.NewMainFlex(guildsTreeView, channelsTreeView, messagesTextView, messageInputField)
mainFlex = ui.NewMainFlex(guildsTreeView, messagesTextView, messageInputField)
token := config.Token
if t := util.GetPassword("token"); t != "" {
@ -72,8 +70,6 @@ func onAppInputCapture(e *tcell.EventKey) *tcell.EventKey {
switch e.Name() {
case "Alt+Rune[g]":
app.SetFocus(guildsTreeView)
case "Alt+Rune[c]":
app.SetFocus(channelsTreeView)
case "Alt+Rune[m]":
app.SetFocus(messagesTextView)
case "Alt+Rune[i]":
@ -145,14 +141,14 @@ func onSessionReady(_ *discordgo.Session, r *discordgo.Ready) {
return false
})
rootN := guildsTreeView.GetRoot()
n := guildsTreeView.GetRoot()
for _, g := range r.Guilds {
gn := tview.NewTreeNode(g.Name).
SetReference(g.ID)
rootN.AddChild(gn)
n.AddChild(gn)
}
guildsTreeView.SetCurrentNode(rootN)
guildsTreeView.SetCurrentNode(n)
}
func onSessionMessageCreate(_ *discordgo.Session, m *discordgo.MessageCreate) {
@ -161,40 +157,41 @@ func onSessionMessageCreate(_ *discordgo.Session, m *discordgo.MessageCreate) {
}
}
func onGuildsTreeViewSelected(gn *tview.TreeNode) {
selectedChannel = nil
app.SetFocus(channelsTreeView)
messagesTextView.
Clear().
SetTitle("")
func onGuildsTreeViewSelected(n *tview.TreeNode) {
switch n.GetLevel() {
case 1:
if len(n.GetChildren()) != 0 {
n.SetExpanded(!n.IsExpanded())
return
}
gID := gn.GetReference().(string)
g, _ := session.State.Guild(gID)
cs := g.Channels
sort.Slice(cs, func(i, j int) bool {
return cs[i].Position < cs[j].Position
})
selectedChannel = nil
n.ClearChildren()
messagesTextView.
Clear().
SetTitle("")
rootN := channelsTreeView.GetRoot()
rootN.ClearChildren()
// Top-level channels
ui.CreateTopLevelChannelsTreeNodes(session.State, rootN, cs)
// Category channels
ui.CreateCategoryChannelsTreeNodes(session.State, rootN, cs)
// Second-level channels
ui.CreateSecondLevelChannelsTreeNodes(session.State, channelsTreeView, rootN, cs)
gID := n.GetReference().(string)
g, _ := session.State.Guild(gID)
channelsTreeView.SetCurrentNode(rootN)
}
cs := g.Channels
sort.Slice(cs, func(i, j int) bool {
return cs[i].Position < cs[j].Position
})
func onChannelsTreeViewSelected(n *tview.TreeNode) {
cID := n.GetReference().(string)
c, _ := session.State.Channel(cID)
switch c.Type {
case discordgo.ChannelTypeGuildCategory:
n.SetExpanded(!n.IsExpanded())
case discordgo.ChannelTypeGuildText, discordgo.ChannelTypeGuildNews:
if len(n.GetChildren()) == 0 {
// Top-level channels
ui.CreateTopLevelChannelsTreeNodes(session.State, n, cs)
// Category channels
ui.CreateCategoryChannelsTreeNodes(session.State, n, cs)
// Second-level channels
ui.CreateSecondLevelChannelsTreeNodes(session.State, guildsTreeView, cs)
default:
cID := n.GetReference().(string)
c, _ := session.State.Channel(cID)
if c.Type == discordgo.ChannelTypeGuildCategory {
n.SetExpanded(!n.IsExpanded())
} else if c.Type == discordgo.ChannelTypeGuildNews || c.Type == discordgo.ChannelTypeGuildText {
selectedChannel = c
app.SetFocus(messageInputField)
@ -207,8 +204,6 @@ func onChannelsTreeViewSelected(n *tview.TreeNode) {
SetTitle(title)
go writeMessages(c.ID)
} else {
n.SetExpanded(!n.IsExpanded())
}
}
}

View file

@ -5,17 +5,13 @@ import (
)
// NewMainFlex creates and returns a new main flex.
func NewMainFlex(gTreeV *tview.TreeView, cTreeV *tview.TreeView, textV *tview.TextView, i *tview.InputField) *tview.Flex {
lf := tview.NewFlex().
SetDirection(tview.FlexRow).
AddItem(gTreeV, 0, 1, false).
AddItem(cTreeV, 0, 2, false)
func NewMainFlex(treeV *tview.TreeView, textV *tview.TextView, i *tview.InputField) *tview.Flex {
rf := tview.NewFlex().
SetDirection(tview.FlexRow).
AddItem(textV, 0, 1, false).
AddItem(i, 3, 1, false)
mf := tview.NewFlex().
AddItem(lf, 0, 1, false).
AddItem(treeV, 0, 1, false).
AddItem(rf, 0, 4, false)
return mf

View file

@ -21,21 +21,6 @@ func NewGuildsTreeView(onGuildsTreeViewSelected func(*tview.TreeNode)) *tview.Tr
return v
}
// NewChannelsTreeView creates and returns a new channels treeview.
func NewChannelsTreeView(onChannelsTreeViewSelected func(*tview.TreeNode)) *tview.TreeView {
v := tview.NewTreeView()
v.
SetTopLevel(1).
SetRoot(tview.NewTreeNode("")).
SetSelectedFunc(onChannelsTreeViewSelected).
SetBorder(true).
SetBorderPadding(0, 0, 1, 0).
SetTitle("Channels").
SetTitleAlign(tview.AlignLeft)
return v
}
// NewTextChannelTreeNode creates and returns a new text channel treenode.
func NewTextChannelTreeNode(c *discordgo.Channel) *tview.TreeNode {
n := tview.NewTreeNode("[::d]#" + c.Name + "[::-]").
@ -58,8 +43,8 @@ func GetTreeNodeByReference(r interface{}, treeV *tview.TreeView) (mn *tview.Tre
return
}
// CreateTopLevelChannelsTreeNodes creates treenodes for the top-level (orphan) channels.
func CreateTopLevelChannelsTreeNodes(s *discordgo.State, rootN *tview.TreeNode, cs []*discordgo.Channel) {
// CreateTopLevelChannelsTreeNodes creates TreeNodes for the top-level (orphan) channels.
func CreateTopLevelChannelsTreeNodes(s *discordgo.State, n *tview.TreeNode, cs []*discordgo.Channel) {
for _, c := range cs {
if (c.Type == discordgo.ChannelTypeGuildText || c.Type == discordgo.ChannelTypeGuildNews) && (c.ParentID == "") {
if !util.HasPermission(s, s.User.ID, c.ID, discordgo.PermissionViewChannel) {
@ -67,14 +52,14 @@ func CreateTopLevelChannelsTreeNodes(s *discordgo.State, rootN *tview.TreeNode,
}
cn := NewTextChannelTreeNode(c)
rootN.AddChild(cn)
n.AddChild(cn)
continue
}
}
}
// CreateCategoryChannelsTreeNodes creates treenodes for the category channels.
func CreateCategoryChannelsTreeNodes(s *discordgo.State, rootN *tview.TreeNode, cs []*discordgo.Channel) {
// CreateCategoryChannelsTreeNodes creates TreeNodes for the category (parent) channels.
func CreateCategoryChannelsTreeNodes(s *discordgo.State, n *tview.TreeNode, cs []*discordgo.Channel) {
CategoryLoop:
for _, c := range cs {
if c.Type == discordgo.ChannelTypeGuildCategory {
@ -86,27 +71,27 @@ CategoryLoop:
if child.ParentID == c.ID {
cn := tview.NewTreeNode(c.Name).
SetReference(c.ID)
rootN.AddChild(cn)
n.AddChild(cn)
continue CategoryLoop
}
}
cn := tview.NewTreeNode(c.Name).
SetReference(c.ID)
rootN.AddChild(cn)
n.AddChild(cn)
}
}
}
// CreateSecondLevelChannelsTreeNodes creates treenodes for the second-level (category children) channels.
func CreateSecondLevelChannelsTreeNodes(s *discordgo.State, channelsTreeView *tview.TreeView, rootN *tview.TreeNode, cs []*discordgo.Channel) {
// CreateSecondLevelChannelsTreeNodes creates TreeNodes for the second-level (category children) channels.
func CreateSecondLevelChannelsTreeNodes(s *discordgo.State, treeV *tview.TreeView, cs []*discordgo.Channel) {
for _, c := range cs {
if (c.Type == discordgo.ChannelTypeGuildText || c.Type == discordgo.ChannelTypeGuildNews) && (c.ParentID != "") {
if !util.HasPermission(s, s.User.ID, c.ID, discordgo.PermissionViewChannel) {
continue
}
if pn := GetTreeNodeByReference(c.ParentID, channelsTreeView); pn != nil {
if pn := GetTreeNodeByReference(c.ParentID, treeV); pn != nil {
cn := NewTextChannelTreeNode(c)
pn.AddChild(cn)
}