Merge branch 'main' into update-preview

This commit is contained in:
ayn2op 2026-02-23 18:21:33 -05:00
commit 06ee7fdad1
12 changed files with 68 additions and 8 deletions

2
go.mod
View file

@ -8,7 +8,7 @@ require (
github.com/BurntSushi/toml v1.6.0
github.com/alecthomas/chroma/v2 v2.23.1
github.com/andybalholm/brotli v1.2.0
github.com/ayn2op/tview v0.0.0-20260223065535-6a0c066d0bdd
github.com/ayn2op/tview v0.0.0-20260223211434-6859308d597f
github.com/deckarep/gosx-notifier v0.0.0-20180201035817-e127226297fb
github.com/diamondburned/arikawa/v3 v3.6.1-0.20260221051847-b81b70d1a5cb
github.com/diamondburned/ningen/v3 v3.0.1-0.20250920191746-98fbd92e134d

4
go.sum
View file

@ -14,8 +14,8 @@ github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs
github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
github.com/ayn2op/tview v0.0.0-20260223065535-6a0c066d0bdd h1:DdR19f4xNbd3XM9vxmC9LtF5XY1nv0rDMMzn0FSTwd0=
github.com/ayn2op/tview v0.0.0-20260223065535-6a0c066d0bdd/go.mod h1:lZ8RdOegQWBQafTOasGE7Ps1/Ymy4jmXoPt5vz2QsS0=
github.com/ayn2op/tview v0.0.0-20260223211434-6859308d597f h1:ZxDODg1E/RPoTWlXhnhZOKITe1ebBM0Cpy+GiGaa+xk=
github.com/ayn2op/tview v0.0.0-20260223211434-6859308d597f/go.mod h1:lZ8RdOegQWBQafTOasGE7Ps1/Ymy4jmXoPt5vz2QsS0=
github.com/danieljoos/wincred v1.2.3 h1:v7dZC2x32Ut3nEfRH+vhoZGvN72+dQ/snVXo/vMFLdQ=
github.com/danieljoos/wincred v1.2.3/go.mod h1:6qqX0WNrS4RzPZ1tnroDzq9kY3fu1KwE7MRLQK4X0bs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=

View file

@ -102,6 +102,9 @@ func (a *App) quit() {
func (a *App) onInputCapture(event *tcell.EventKey) *tcell.EventKey {
switch {
case keybind.Matches(event, a.cfg.Keybinds.Suspend.Keybind):
a.suspend()
return nil
case keybind.Matches(event, a.cfg.Keybinds.Quit.Keybind):
a.quit()
return nil

View file

@ -0,0 +1,5 @@
//go:build !unix
package app
func (a *App) suspend() {}

View file

@ -0,0 +1,20 @@
//go:build unix
package app
import (
"os"
"os/signal"
"syscall"
)
func (a *App) suspend() {
a.inner.Suspend(func() {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGCONT)
defer signal.Stop(c)
_ = syscall.Kill(0, syscall.SIGTSTP)
<-c
})
}

View file

@ -74,6 +74,16 @@ type (
Separator string `toml:"separator"`
}
SidebarMarkersConfig struct {
Expanded string `toml:"expanded"`
Collapsed string `toml:"collapsed"`
Leaf string `toml:"leaf"`
}
SidebarConfig struct {
Markers SidebarMarkersConfig `toml:"markers"`
}
Config struct {
AutoFocus bool `toml:"auto_focus"`
Mouse bool `toml:"mouse"`
@ -94,6 +104,7 @@ type (
DateSeparator DateSeparator `toml:"date_separator"`
Notifications Notifications `toml:"notifications"`
TypingIndicator TypingIndicator `toml:"typing_indicator"`
Sidebar SidebarConfig `toml:"sidebar"`
Icons Icons `toml:"icons"`

View file

@ -63,6 +63,11 @@ send = true
# Whether to receive typing status or not.
receive = true
[sidebar.markers]
expanded = "▾ "
collapsed = "▸ "
leaf = ""
[icons]
guild_category = ""
guild_text = "#"
@ -87,10 +92,11 @@ focus_previous = "ctrl+h"
focus_next = "ctrl+l"
# Hide/show the guilds tree.
toggle_guilds_tree = "ctrl+b"
quit = "ctrl+c"
# Log out and remove the authentication token from keyring.
# Requires re-login upon restart.
logout = "ctrl+d"
suspend = "ctrl+z"
quit = "ctrl+c"
[keybinds.picker]
toggle = "ctrl+k"
@ -152,6 +158,7 @@ send = "enter"
cancel = "esc"
# Complete usernames when mentioning
tab_complete = "tab"
undo = "ctrl+u"
open_editor = "ctrl+e"
open_file_picker = "ctrl+\\"

View file

@ -96,6 +96,7 @@ type MessageInputKeybinds struct {
Send Keybind `toml:"send"`
Cancel Keybind `toml:"cancel"`
TabComplete Keybind `toml:"tab_complete"`
Undo Keybind `toml:"undo"`
OpenEditor Keybind `toml:"open_editor"`
OpenFilePicker Keybind `toml:"open_file_picker"`
@ -109,6 +110,7 @@ type Keybinds struct {
ToggleGuildsTree Keybind `toml:"toggle_guilds_tree"`
ToggleChannelsPicker Keybind `toml:"toggle_channels_picker"`
ToggleHelp Keybind `toml:"toggle_help"`
Suspend Keybind `toml:"suspend"`
FocusGuildsTree Keybind `toml:"focus_guilds_tree"`
FocusMessagesList Keybind `toml:"focus_messages_list"`
@ -132,6 +134,7 @@ func defaultKeybinds() Keybinds {
ToggleGuildsTree: newKeybind("ctrl+b", "toggle guilds"),
ToggleChannelsPicker: newKeybind("ctrl+k", "channels picker"),
ToggleHelp: newKeybind("ctrl+.", "help"),
Suspend: newKeybind("ctrl+z", "suspend"),
FocusGuildsTree: newKeybind("ctrl+g", "guilds"),
FocusMessagesList: newKeybind("ctrl+t", "messages"),
@ -198,6 +201,7 @@ func defaultKeybinds() Keybinds {
Send: newKeybind("enter", "send"),
Cancel: newKeybind("esc", "cancel"),
TabComplete: newKeybind("tab", "complete"),
Undo: newKeybind("ctrl+u", "undo"),
OpenEditor: newKeybind("ctrl+e", "editor"),
OpenFilePicker: newKeybind("ctrl+\\", "attach"),
},

View file

@ -47,6 +47,11 @@ func newGuildsTree(cfg *config.Config, chatView *View) *guildsTree {
gt.
SetRoot(tview.NewTreeNode("")).
SetTopLevel(1).
SetMarkers(tview.TreeMarkers{
Expanded: cfg.Sidebar.Markers.Expanded,
Collapsed: cfg.Sidebar.Markers.Collapsed,
Leaf: cfg.Sidebar.Markers.Leaf,
}).
SetGraphics(cfg.Theme.GuildsTree.Graphics).
SetGraphicsColor(tcell.GetColor(cfg.Theme.GuildsTree.GraphicsColor)).
SetSelectedFunc(gt.onSelected).
@ -189,7 +194,7 @@ func (gt *guildsTree) getChannelNodeStyle(channelID discord.ChannelID) tcell.Sty
}
func (gt *guildsTree) createGuildNode(n *tview.TreeNode, guild discord.Guild) {
guildNode := tview.NewTreeNode(guild.Name).SetReference(guild.ID)
guildNode := tview.NewTreeNode(guild.Name).SetReference(guild.ID).SetExpandable(true)
gt.setNodeLineStyle(guildNode, gt.getGuildNodeStyle(guild.ID))
n.AddChild(guildNode)
gt.guildNodeByID[guild.ID] = guildNode
@ -201,6 +206,9 @@ func (gt *guildsTree) createChannelNode(node *tview.TreeNode, channel discord.Ch
}
channelNode := tview.NewTreeNode(ui.ChannelToString(channel, gt.cfg.Icons)).SetReference(channel.ID)
if channel.Type == discord.GuildForum {
channelNode.SetExpandable(true)
}
gt.setNodeLineStyle(channelNode, gt.getChannelNodeStyle(channel.ID))
node.AddChild(channelNode)
gt.channelNodeByID[channel.ID] = channelNode

View file

@ -66,6 +66,6 @@ func (v *View) baseFullHelp() [][]keybind.Keybind {
focus,
{cfg.FocusPrevious.Keybind, cfg.FocusNext.Keybind},
{cfg.ToggleGuildsTree.Keybind, cfg.ToggleChannelsPicker.Keybind},
{cfg.ToggleHelp.Keybind, cfg.Logout.Keybind, cfg.Quit.Keybind},
{cfg.ToggleHelp.Keybind, cfg.Suspend.Keybind, cfg.Logout.Keybind, cfg.Quit.Keybind},
}
}

View file

@ -126,6 +126,8 @@ func (mi *messageInput) onInputCapture(event *tcell.EventKey) *tcell.EventKey {
case keybind.Matches(event, mi.cfg.Keybinds.MessageInput.TabComplete.Keybind):
go mi.chatView.app.QueueUpdateDraw(func() { mi.tabComplete() })
return nil
case keybind.Matches(event, mi.cfg.Keybinds.MessageInput.Undo.Keybind):
return tcell.NewEventKey(tcell.KeyCtrlZ, "", tcell.ModNone)
default:
if mi.cfg.TypingIndicator.Send && mi.typingTimer == nil {
mi.typingTimer = time.AfterFunc(typingDuration, func() {
@ -717,7 +719,7 @@ func (mi *messageInput) FullHelp() [][]keybind.Keybind {
}
return [][]keybind.Keybind{
{cfg.Send.Keybind, cfg.Cancel.Keybind, cfg.TabComplete.Keybind},
{cfg.Send.Keybind, cfg.Cancel.Keybind, cfg.TabComplete.Keybind, cfg.Undo.Keybind},
openEditor,
}
}

View file

@ -85,7 +85,7 @@ func (v *View) onReady(event *gateway.ReadyEvent) {
// retain stale pointers to detached tree nodes.
v.guildsTree.resetNodeIndex()
dmNode := tview.NewTreeNode("Direct Messages").SetReference(dmNode{})
dmNode := tview.NewTreeNode("Direct Messages").SetReference(dmNode{}).SetExpandable(true)
v.guildsTree.dmRootNode = dmNode
root := v.guildsTree.