refactor(cmd): separate chat UI widgets from application
This commit is contained in:
parent
1589d7b47f
commit
b3ac0dc6b4
6 changed files with 248 additions and 217 deletions
|
|
@ -4,9 +4,7 @@ import (
|
|||
"log/slog"
|
||||
|
||||
"github.com/ayn2op/discordo/internal/config"
|
||||
"github.com/ayn2op/discordo/internal/keyring"
|
||||
"github.com/ayn2op/discordo/internal/login"
|
||||
"github.com/ayn2op/discordo/internal/ui"
|
||||
"github.com/ayn2op/tview"
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"golang.design/x/clipboard"
|
||||
|
|
@ -20,33 +18,21 @@ const (
|
|||
)
|
||||
|
||||
type application struct {
|
||||
cfg *config.Config
|
||||
|
||||
*tview.Application
|
||||
pages *tview.Pages
|
||||
flex *tview.Flex
|
||||
guildsTree *guildsTree
|
||||
messagesList *messagesList
|
||||
messageInput *messageInput
|
||||
chatView *chatView
|
||||
cfg *config.Config
|
||||
}
|
||||
|
||||
func newApplication(cfg *config.Config) *application {
|
||||
app := &application{
|
||||
cfg: cfg,
|
||||
|
||||
Application: tview.NewApplication(),
|
||||
pages: tview.NewPages(),
|
||||
flex: tview.NewFlex(),
|
||||
guildsTree: newGuildsTree(cfg),
|
||||
messagesList: newMessagesList(cfg),
|
||||
messageInput: newMessageInput(cfg),
|
||||
Application: tview.NewApplication(),
|
||||
cfg: cfg,
|
||||
}
|
||||
|
||||
if err := clipboard.Init(); err != nil {
|
||||
slog.Error("failed to init clipboard", "err", err)
|
||||
}
|
||||
|
||||
app.pages.SetInputCapture(app.onPagesInputCapture)
|
||||
app.
|
||||
EnableMouse(cfg.Mouse).
|
||||
SetInputCapture(app.onInputCapture).
|
||||
|
|
@ -65,12 +51,12 @@ func (a *application) run(token string) error {
|
|||
return a.SetRoot(loginForm, true).Run()
|
||||
}
|
||||
|
||||
a.chatView = newChatView(a.Application, a.cfg)
|
||||
if err := openState(token); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.init()
|
||||
return a.SetRoot(a.pages, true).Run()
|
||||
return a.SetRoot(a.chatView, true).Run()
|
||||
}
|
||||
|
||||
func (a *application) quit() {
|
||||
|
|
@ -83,23 +69,6 @@ func (a *application) quit() {
|
|||
a.Stop()
|
||||
}
|
||||
|
||||
func (a *application) init() {
|
||||
a.pages.Clear()
|
||||
a.flex.Clear()
|
||||
|
||||
right := tview.NewFlex().
|
||||
SetDirection(tview.FlexRow).
|
||||
AddItem(a.messagesList, 0, 1, false).
|
||||
AddItem(a.messageInput, 3, 1, false)
|
||||
|
||||
// The guilds tree is always focused first at start-up.
|
||||
a.flex.
|
||||
AddItem(a.guildsTree, 0, 1, true).
|
||||
AddItem(right, 0, 4, false)
|
||||
|
||||
a.pages.AddAndSwitchToPage(flexPageName, a.flex, true)
|
||||
}
|
||||
|
||||
func (a *application) onInputCapture(event *tcell.EventKey) *tcell.EventKey {
|
||||
switch event.Name() {
|
||||
case a.cfg.Keys.Quit:
|
||||
|
|
@ -112,117 +81,3 @@ func (a *application) onInputCapture(event *tcell.EventKey) *tcell.EventKey {
|
|||
|
||||
return event
|
||||
}
|
||||
|
||||
func (a *application) onPagesInputCapture(event *tcell.EventKey) *tcell.EventKey {
|
||||
switch event.Name() {
|
||||
case a.cfg.Keys.FocusGuildsTree:
|
||||
a.messageInput.removeMentionsList()
|
||||
a.focusGuildsTree()
|
||||
return nil
|
||||
case a.cfg.Keys.FocusMessagesList:
|
||||
a.messageInput.removeMentionsList()
|
||||
a.SetFocus(a.messagesList)
|
||||
return nil
|
||||
case a.cfg.Keys.FocusMessageInput:
|
||||
a.focusMessageInput()
|
||||
return nil
|
||||
case a.cfg.Keys.FocusPrevious:
|
||||
a.focusPrevious()
|
||||
return nil
|
||||
case a.cfg.Keys.FocusNext:
|
||||
a.focusNext()
|
||||
return nil
|
||||
case a.cfg.Keys.Logout:
|
||||
a.quit()
|
||||
|
||||
if err := keyring.DeleteToken(); err != nil {
|
||||
slog.Error("failed to delete token from keyring", "err", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
case a.cfg.Keys.ToggleGuildsTree:
|
||||
a.toggleGuildsTree()
|
||||
return nil
|
||||
}
|
||||
|
||||
return event
|
||||
}
|
||||
|
||||
func (a *application) toggleGuildsTree() {
|
||||
// The guilds tree is visible if the number of items is two.
|
||||
if a.flex.GetItemCount() == 2 {
|
||||
a.flex.RemoveItem(a.guildsTree)
|
||||
if a.guildsTree.HasFocus() {
|
||||
a.SetFocus(a.flex)
|
||||
}
|
||||
} else {
|
||||
a.init()
|
||||
a.SetFocus(a.guildsTree)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *application) focusGuildsTree() bool {
|
||||
// The guilds tree is not hidden if the number of items is two.
|
||||
if a.flex.GetItemCount() == 2 {
|
||||
a.SetFocus(a.guildsTree)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *application) focusMessageInput() bool {
|
||||
if !a.messageInput.GetDisabled() {
|
||||
a.SetFocus(a.messageInput)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *application) focusPrevious() {
|
||||
switch a.GetFocus() {
|
||||
case a.guildsTree:
|
||||
a.SetFocus(a.messageInput)
|
||||
case a.messagesList: // Handle both a.messagesList and a.flex as well as other edge cases (if there is).
|
||||
if ok := a.focusGuildsTree(); !ok {
|
||||
a.SetFocus(a.messageInput)
|
||||
}
|
||||
case a.messageInput:
|
||||
a.SetFocus(a.messagesList)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *application) focusNext() {
|
||||
switch a.GetFocus() {
|
||||
case a.guildsTree:
|
||||
a.SetFocus(a.messagesList)
|
||||
case a.messagesList:
|
||||
a.SetFocus(a.messageInput)
|
||||
case a.messageInput: // Handle both a.messageInput and a.flex as well as other edge cases (if there is).
|
||||
if ok := a.focusGuildsTree(); !ok {
|
||||
a.SetFocus(a.messagesList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *application) showConfirmModal(prompt string, buttons []string, onDone func(label string)) {
|
||||
previousFocus := a.GetFocus()
|
||||
|
||||
modal := tview.NewModal().
|
||||
SetText(prompt).
|
||||
AddButtons(buttons).
|
||||
SetDoneFunc(func(_ int, buttonLabel string) {
|
||||
a.pages.RemovePage(confirmModalPageName).SwitchToPage(flexPageName)
|
||||
a.SetFocus(previousFocus)
|
||||
|
||||
if onDone != nil {
|
||||
onDone(buttonLabel)
|
||||
}
|
||||
})
|
||||
|
||||
a.pages.
|
||||
AddAndSwitchToPage(confirmModalPageName, ui.Centered(modal, 0, 0), true).
|
||||
ShowPage(flexPageName)
|
||||
}
|
||||
|
|
|
|||
176
cmd/chatview.go
Normal file
176
cmd/chatview.go
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
|
||||
"github.com/ayn2op/discordo/internal/config"
|
||||
"github.com/ayn2op/discordo/internal/keyring"
|
||||
"github.com/ayn2op/discordo/internal/ui"
|
||||
"github.com/ayn2op/tview"
|
||||
"github.com/gdamore/tcell/v2"
|
||||
)
|
||||
|
||||
type chatView struct {
|
||||
*tview.Pages
|
||||
|
||||
mainFlex *tview.Flex
|
||||
rightFlex *tview.Flex
|
||||
|
||||
guildsTree *guildsTree
|
||||
messagesList *messagesList
|
||||
messageInput *messageInput
|
||||
|
||||
app *tview.Application
|
||||
cfg *config.Config
|
||||
}
|
||||
|
||||
func newChatView(app *tview.Application, cfg *config.Config) *chatView {
|
||||
cv := &chatView{
|
||||
Pages: tview.NewPages(),
|
||||
|
||||
mainFlex: tview.NewFlex(),
|
||||
rightFlex: tview.NewFlex(),
|
||||
|
||||
guildsTree: newGuildsTree(cfg),
|
||||
messagesList: newMessagesList(cfg),
|
||||
messageInput: newMessageInput(cfg),
|
||||
|
||||
app: app,
|
||||
cfg: cfg,
|
||||
}
|
||||
|
||||
cv.SetInputCapture(cv.onInputCapture)
|
||||
|
||||
cv.init()
|
||||
return cv
|
||||
}
|
||||
|
||||
func (cv *chatView) init() {
|
||||
cv.Clear()
|
||||
cv.mainFlex.Clear()
|
||||
|
||||
cv.rightFlex.
|
||||
SetDirection(tview.FlexRow).
|
||||
AddItem(cv.messagesList, 0, 1, false).
|
||||
AddItem(cv.messageInput, 3, 1, false)
|
||||
// The guilds tree is always focused first at start-up.
|
||||
cv.mainFlex.
|
||||
AddItem(cv.guildsTree, 0, 1, true).
|
||||
AddItem(cv.rightFlex, 0, 4, false)
|
||||
|
||||
cv.AddAndSwitchToPage(flexPageName, cv.mainFlex, true)
|
||||
}
|
||||
|
||||
func (cv *chatView) toggleGuildsTree() {
|
||||
// The guilds tree is visible if the number of items is two.
|
||||
if cv.mainFlex.GetItemCount() == 2 {
|
||||
cv.mainFlex.RemoveItem(cv.guildsTree)
|
||||
if cv.guildsTree.HasFocus() {
|
||||
cv.app.SetFocus(cv.mainFlex)
|
||||
}
|
||||
} else {
|
||||
cv.init()
|
||||
cv.app.SetFocus(cv.guildsTree)
|
||||
}
|
||||
}
|
||||
|
||||
func (cv *chatView) focusGuildsTree() bool {
|
||||
// The guilds tree is not hidden if the number of items is two.
|
||||
if cv.mainFlex.GetItemCount() == 2 {
|
||||
cv.app.SetFocus(cv.guildsTree)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (cv *chatView) focusMessageInput() bool {
|
||||
if !cv.messageInput.GetDisabled() {
|
||||
cv.app.SetFocus(cv.messageInput)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (cv *chatView) focusPrevious() {
|
||||
switch cv.app.GetFocus() {
|
||||
case cv.guildsTree:
|
||||
cv.app.SetFocus(cv.messageInput)
|
||||
case cv.messagesList: // Handle both a.messagesList and a.flex as well as other edge cases (if there is).
|
||||
if ok := cv.focusGuildsTree(); !ok {
|
||||
cv.app.SetFocus(cv.messageInput)
|
||||
}
|
||||
case cv.messageInput:
|
||||
cv.app.SetFocus(cv.messagesList)
|
||||
}
|
||||
}
|
||||
|
||||
func (cv *chatView) focusNext() {
|
||||
switch cv.app.GetFocus() {
|
||||
case cv.guildsTree:
|
||||
cv.app.SetFocus(cv.messagesList)
|
||||
case cv.messagesList:
|
||||
cv.app.SetFocus(cv.messageInput)
|
||||
case cv.messageInput: // Handle both a.messageInput and a.flex as well as other edge cases (if there is).
|
||||
if ok := cv.focusGuildsTree(); !ok {
|
||||
cv.app.SetFocus(cv.messagesList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (cv *chatView) onInputCapture(event *tcell.EventKey) *tcell.EventKey {
|
||||
switch event.Name() {
|
||||
case cv.cfg.Keys.FocusGuildsTree:
|
||||
cv.messageInput.removeMentionsList()
|
||||
cv.focusGuildsTree()
|
||||
return nil
|
||||
case cv.cfg.Keys.FocusMessagesList:
|
||||
cv.messageInput.removeMentionsList()
|
||||
cv.app.SetFocus(cv.messagesList)
|
||||
return nil
|
||||
case cv.cfg.Keys.FocusMessageInput:
|
||||
cv.focusMessageInput()
|
||||
return nil
|
||||
case cv.cfg.Keys.FocusPrevious:
|
||||
cv.focusPrevious()
|
||||
return nil
|
||||
case cv.cfg.Keys.FocusNext:
|
||||
cv.focusNext()
|
||||
return nil
|
||||
case cv.cfg.Keys.Logout:
|
||||
app.quit()
|
||||
|
||||
if err := keyring.DeleteToken(); err != nil {
|
||||
slog.Error("failed to delete token from keyring", "err", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
case cv.cfg.Keys.ToggleGuildsTree:
|
||||
cv.toggleGuildsTree()
|
||||
return nil
|
||||
}
|
||||
|
||||
return event
|
||||
}
|
||||
|
||||
func (cv *chatView) showConfirmModal(prompt string, buttons []string, onDone func(label string)) {
|
||||
previousFocus := cv.app.GetFocus()
|
||||
|
||||
modal := tview.NewModal().
|
||||
SetText(prompt).
|
||||
AddButtons(buttons).
|
||||
SetDoneFunc(func(_ int, buttonLabel string) {
|
||||
cv.RemovePage(confirmModalPageName).SwitchToPage(flexPageName)
|
||||
cv.app.SetFocus(previousFocus)
|
||||
|
||||
if onDone != nil {
|
||||
onDone(buttonLabel)
|
||||
}
|
||||
})
|
||||
|
||||
cv.
|
||||
AddAndSwitchToPage(confirmModalPageName, ui.Centered(modal, 0, 0), true).
|
||||
ShowPage(flexPageName)
|
||||
}
|
||||
|
|
@ -143,7 +143,7 @@ PARENT_CHANNELS:
|
|||
}
|
||||
|
||||
func (gt *guildsTree) onSelected(node *tview.TreeNode) {
|
||||
app.messageInput.reset()
|
||||
app.chatView.messageInput.reset()
|
||||
|
||||
if len(node.GetChildren()) != 0 {
|
||||
node.SetExpanded(!node.IsExpanded())
|
||||
|
|
@ -181,21 +181,21 @@ func (gt *guildsTree) onSelected(node *tview.TreeNode) {
|
|||
}
|
||||
|
||||
if guildID := channel.GuildID; guildID.IsValid() {
|
||||
app.messagesList.requestGuildMembers(guildID, messages)
|
||||
app.chatView.messagesList.requestGuildMembers(guildID, messages)
|
||||
}
|
||||
|
||||
app.messagesList.reset()
|
||||
app.messagesList.setTitle(*channel)
|
||||
app.messagesList.drawMessages(messages)
|
||||
app.messagesList.ScrollToEnd()
|
||||
app.chatView.messagesList.reset()
|
||||
app.chatView.messagesList.setTitle(*channel)
|
||||
app.chatView.messagesList.drawMessages(messages)
|
||||
app.chatView.messagesList.ScrollToEnd()
|
||||
|
||||
hasNoPerm := channel.Type != discord.DirectMessage && channel.Type != discord.GroupDM && !discordState.HasPermissions(channel.ID, discord.PermissionSendMessages)
|
||||
app.messageInput.SetDisabled(hasNoPerm)
|
||||
app.chatView.messageInput.SetDisabled(hasNoPerm)
|
||||
if hasNoPerm {
|
||||
app.messageInput.SetPlaceholder("You do not have permission to send messages in this channel.")
|
||||
app.chatView.messageInput.SetPlaceholder("You do not have permission to send messages in this channel.")
|
||||
} else {
|
||||
app.messageInput.SetPlaceholder("Message...")
|
||||
app.SetFocus(app.messageInput)
|
||||
app.chatView.messageInput.SetPlaceholder("Message...")
|
||||
app.SetFocus(app.chatView.messageInput)
|
||||
}
|
||||
|
||||
gt.selectedChannelID = channel.ID
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ func (mi *messageInput) onInputCapture(event *tcell.EventKey) *tcell.EventKey {
|
|||
return tcell.NewEventKey(tcell.KeyCtrlV, 0, tcell.ModNone)
|
||||
|
||||
case mi.cfg.Keys.MessageInput.Send:
|
||||
if app.pages.GetVisibile(mentionsListPageName) {
|
||||
if app.chatView.GetVisibile(mentionsListPageName) {
|
||||
mi.tabComplete(false)
|
||||
return nil
|
||||
}
|
||||
|
|
@ -117,7 +117,7 @@ func (mi *messageInput) onInputCapture(event *tcell.EventKey) *tcell.EventKey {
|
|||
mi.openFilePicker()
|
||||
return nil
|
||||
case mi.cfg.Keys.MessageInput.Cancel:
|
||||
if app.pages.GetVisibile(mentionsListPageName) {
|
||||
if app.chatView.GetVisibile(mentionsListPageName) {
|
||||
mi.stopTabCompletion()
|
||||
} else {
|
||||
mi.reset()
|
||||
|
|
@ -130,7 +130,7 @@ func (mi *messageInput) onInputCapture(event *tcell.EventKey) *tcell.EventKey {
|
|||
}
|
||||
|
||||
if mi.cfg.AutocompleteLimit > 0 {
|
||||
if app.pages.GetVisibile(mentionsListPageName) {
|
||||
if app.chatView.GetVisibile(mentionsListPageName) {
|
||||
switch event.Name() {
|
||||
case mi.cfg.Keys.MentionsList.Up:
|
||||
mi.mentionsList.InputHandler()(tcell.NewEventKey(tcell.KeyUp, 0, tcell.ModNone), nil)
|
||||
|
|
@ -155,7 +155,7 @@ func (mi *messageInput) paste() {
|
|||
}
|
||||
|
||||
func (mi *messageInput) send() {
|
||||
if !app.guildsTree.selectedChannelID.IsValid() {
|
||||
if !app.chatView.guildsTree.selectedChannelID.IsValid() {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -164,13 +164,13 @@ func (mi *messageInput) send() {
|
|||
return
|
||||
}
|
||||
|
||||
text = processText(app.guildsTree.selectedChannelID, []byte(text))
|
||||
text = processText(app.chatView.guildsTree.selectedChannelID, []byte(text))
|
||||
if text == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if mi.edit {
|
||||
m, err := app.messagesList.selectedMessage()
|
||||
m, err := app.chatView.messagesList.selectedMessage()
|
||||
if err != nil {
|
||||
slog.Error("failed to get selected message", "err", err)
|
||||
return
|
||||
|
|
@ -185,8 +185,8 @@ func (mi *messageInput) send() {
|
|||
} else {
|
||||
data := mi.sendMessageData
|
||||
data.Content = text
|
||||
if _, err := discordState.SendMessageComplex(app.guildsTree.selectedChannelID, *data); err != nil {
|
||||
slog.Error("failed to send message in channel", "channel_id", app.guildsTree.selectedChannelID, "err", err)
|
||||
if _, err := discordState.SendMessageComplex(app.chatView.guildsTree.selectedChannelID, *data); err != nil {
|
||||
slog.Error("failed to send message in channel", "channel_id", app.chatView.guildsTree.selectedChannelID, "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -198,8 +198,8 @@ func (mi *messageInput) send() {
|
|||
}
|
||||
|
||||
mi.reset()
|
||||
app.messagesList.Highlight()
|
||||
app.messagesList.ScrollToEnd()
|
||||
app.chatView.messagesList.Highlight()
|
||||
app.chatView.messagesList.ScrollToEnd()
|
||||
}
|
||||
|
||||
func processText(cID discord.ChannelID, src []byte) string {
|
||||
|
|
@ -236,7 +236,7 @@ func expandMentions(cID discord.ChannelID, src []byte) []byte {
|
|||
return mentionRegex.ReplaceAllFunc(src, func(input []byte) []byte {
|
||||
output := input
|
||||
name := string(input[1:])
|
||||
discordState.MemberStore.Each(app.guildsTree.selectedGuildID, func(m *discord.Member) bool {
|
||||
discordState.MemberStore.Each(app.chatView.guildsTree.selectedGuildID, func(m *discord.Member) bool {
|
||||
if strings.EqualFold(m.User.Username, name) && channelHasUser(cID, m.User.ID) {
|
||||
output = []byte(m.User.ID.Mention())
|
||||
return true
|
||||
|
|
@ -259,8 +259,8 @@ func (mi *messageInput) tabComplete(isAuto bool) {
|
|||
}
|
||||
pos := posEnd - (len(name) + 1)
|
||||
|
||||
gID := app.guildsTree.selectedGuildID
|
||||
cID := app.guildsTree.selectedChannelID
|
||||
gID := app.chatView.guildsTree.selectedGuildID
|
||||
cID := app.chatView.guildsTree.selectedChannelID
|
||||
|
||||
if !isAuto {
|
||||
if mi.cfg.AutocompleteLimit == 0 {
|
||||
|
|
@ -373,10 +373,10 @@ func (mi *messageInput) searchMember(gID discord.GuildID, name string) {
|
|||
}
|
||||
|
||||
mi.lastSearch = time.Now()
|
||||
app.messagesList.waitForChunkEvent()
|
||||
app.messagesList.setFetchingChunk(true, 0)
|
||||
app.chatView.messagesList.waitForChunkEvent()
|
||||
app.chatView.messagesList.setFetchingChunk(true, 0)
|
||||
discordState.MemberState.SearchMember(gID, name)
|
||||
mi.cache.Create(key, app.messagesList.waitForChunkEvent())
|
||||
mi.cache.Create(key, app.chatView.messagesList.waitForChunkEvent())
|
||||
}
|
||||
|
||||
func (mi *messageInput) showMentionList(col int) {
|
||||
|
|
@ -387,7 +387,7 @@ func (mi *messageInput) showMentionList(col int) {
|
|||
l := mi.mentionsList
|
||||
x, _, _, _ := mi.GetInnerRect()
|
||||
_, y, _, _ := mi.GetRect()
|
||||
_, _, maxW, maxH := app.messagesList.GetInnerRect()
|
||||
_, _, maxW, maxH := app.chatView.messagesList.GetInnerRect()
|
||||
if t := int(mi.cfg.Theme.MentionsList.MaxHeight); t != 0 {
|
||||
maxH = min(maxH, t)
|
||||
}
|
||||
|
|
@ -409,7 +409,7 @@ func (mi *messageInput) showMentionList(col int) {
|
|||
|
||||
l.SetRect(x, y, w, h)
|
||||
|
||||
app.pages.
|
||||
app.chatView.
|
||||
AddAndSwitchToPage(mentionsListPageName, l, false).
|
||||
ShowPage(flexPageName)
|
||||
app.SetFocus(mi)
|
||||
|
|
@ -448,7 +448,7 @@ func (mi *messageInput) addMentionItem(gID discord.GuildID, m *discord.Member) b
|
|||
}
|
||||
|
||||
func (mi *messageInput) removeMentionsList() {
|
||||
app.pages.
|
||||
app.chatView.
|
||||
RemovePage(mentionsListPageName).
|
||||
SwitchToPage(flexPageName)
|
||||
}
|
||||
|
|
@ -504,7 +504,7 @@ func (mi *messageInput) addTitle(s string) {
|
|||
}
|
||||
|
||||
func (mi *messageInput) openFilePicker() {
|
||||
if !app.guildsTree.selectedChannelID.IsValid() {
|
||||
if !app.chatView.guildsTree.selectedChannelID.IsValid() {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ func (ml *messagesList) selectedMessage() (*discord.Message, error) {
|
|||
return nil, errors.New("no message is currently selected")
|
||||
}
|
||||
|
||||
m, err := discordState.Cabinet.Message(app.guildsTree.selectedChannelID, ml.selectedMessageID)
|
||||
m, err := discordState.Cabinet.Message(app.chatView.guildsTree.selectedChannelID, ml.selectedMessageID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not retrieve selected message: %w", err)
|
||||
}
|
||||
|
|
@ -248,7 +248,7 @@ func (ml *messagesList) selectedMessage() (*discord.Message, error) {
|
|||
}
|
||||
|
||||
func (ml *messagesList) selectedMessageIndex() (int, error) {
|
||||
ms, err := discordState.Cabinet.Messages(app.guildsTree.selectedChannelID)
|
||||
ms, err := discordState.Cabinet.Messages(app.chatView.guildsTree.selectedChannelID)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
|
@ -294,9 +294,9 @@ func (ml *messagesList) onInputCapture(event *tcell.EventKey) *tcell.EventKey {
|
|||
}
|
||||
|
||||
func (ml *messagesList) _select(name string) {
|
||||
ms, err := discordState.Cabinet.Messages(app.guildsTree.selectedChannelID)
|
||||
ms, err := discordState.Cabinet.Messages(app.chatView.guildsTree.selectedChannelID)
|
||||
if err != nil {
|
||||
slog.Error("failed to get messages", "err", err, "channel_id", app.guildsTree.selectedChannelID)
|
||||
slog.Error("failed to get messages", "err", err, "channel_id", app.chatView.guildsTree.selectedChannelID)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -450,7 +450,7 @@ func (ml *messagesList) showAttachmentsList(urls []string, attachments []discord
|
|||
SetHighlightFullLine(true).
|
||||
ShowSecondaryText(false).
|
||||
SetDoneFunc(func() {
|
||||
app.pages.RemovePage(attachmentsListPageName).SwitchToPage(flexPageName)
|
||||
app.chatView.RemovePage(attachmentsListPageName).SwitchToPage(flexPageName)
|
||||
app.SetFocus(ml)
|
||||
})
|
||||
list.
|
||||
|
|
@ -486,7 +486,7 @@ func (ml *messagesList) showAttachmentsList(urls []string, attachments []discord
|
|||
})
|
||||
}
|
||||
|
||||
app.pages.
|
||||
app.chatView.
|
||||
AddAndSwitchToPage(attachmentsListPageName, ui.Centered(list, 0, 0), true).
|
||||
ShowPage(flexPageName)
|
||||
}
|
||||
|
|
@ -548,7 +548,7 @@ func (ml *messagesList) reply(mention bool) {
|
|||
}
|
||||
}
|
||||
|
||||
data := app.messageInput.sendMessageData
|
||||
data := app.chatView.messageInput.sendMessageData
|
||||
data.Reference = &discord.MessageReference{MessageID: ml.selectedMessageID}
|
||||
data.AllowedMentions = &api.AllowedMentions{RepliedUser: option.False}
|
||||
|
||||
|
|
@ -558,9 +558,9 @@ func (ml *messagesList) reply(mention bool) {
|
|||
title = "[@] " + title
|
||||
}
|
||||
|
||||
app.messageInput.sendMessageData = data
|
||||
app.messageInput.addTitle(title + name)
|
||||
app.SetFocus(app.messageInput)
|
||||
app.chatView.messageInput.sendMessageData = data
|
||||
app.chatView.messageInput.addTitle(title + name)
|
||||
app.SetFocus(app.chatView.messageInput)
|
||||
}
|
||||
|
||||
func (ml *messagesList) edit() {
|
||||
|
|
@ -581,10 +581,10 @@ func (ml *messagesList) edit() {
|
|||
return
|
||||
}
|
||||
|
||||
app.messageInput.SetTitle("Editing")
|
||||
app.messageInput.edit = true
|
||||
app.messageInput.SetText(message.Content, true)
|
||||
app.SetFocus(app.messageInput)
|
||||
app.chatView.messageInput.SetTitle("Editing")
|
||||
app.chatView.messageInput.edit = true
|
||||
app.chatView.messageInput.SetText(message.Content, true)
|
||||
app.SetFocus(app.chatView.messageInput)
|
||||
}
|
||||
|
||||
func (ml *messagesList) confirmDelete() {
|
||||
|
|
@ -594,7 +594,7 @@ func (ml *messagesList) confirmDelete() {
|
|||
}
|
||||
}
|
||||
|
||||
app.showConfirmModal(
|
||||
app.chatView.showConfirmModal(
|
||||
"Are you sure you want to delete this message?",
|
||||
[]string{"Yes", "No"},
|
||||
onChoice,
|
||||
|
|
@ -621,16 +621,16 @@ func (ml *messagesList) delete() {
|
|||
}
|
||||
}
|
||||
|
||||
if err := discordState.DeleteMessage(app.guildsTree.selectedChannelID, msg.ID, ""); err != nil {
|
||||
slog.Error("failed to delete message", "channel_id", app.guildsTree.selectedChannelID, "message_id", msg.ID, "err", err)
|
||||
if err := discordState.DeleteMessage(app.chatView.guildsTree.selectedChannelID, msg.ID, ""); err != nil {
|
||||
slog.Error("failed to delete message", "channel_id", app.chatView.guildsTree.selectedChannelID, "message_id", msg.ID, "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
ml.selectedMessageID = 0
|
||||
ml.Highlight()
|
||||
|
||||
if err := discordState.MessageRemove(app.guildsTree.selectedChannelID, msg.ID); err != nil {
|
||||
slog.Error("failed to delete message", "channel_id", app.guildsTree.selectedChannelID, "message_id", msg.ID, "err", err)
|
||||
if err := discordState.MessageRemove(app.chatView.guildsTree.selectedChannelID, msg.ID); err != nil {
|
||||
slog.Error("failed to delete message", "channel_id", app.chatView.guildsTree.selectedChannelID, "message_id", msg.ID, "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
34
cmd/state.go
34
cmd/state.go
|
|
@ -45,11 +45,11 @@ func openState(token string) error {
|
|||
discordState.AddHandler(onReadUpdate)
|
||||
|
||||
discordState.AddHandler(func(event *gateway.GuildMembersChunkEvent) {
|
||||
app.messagesList.setFetchingChunk(false, uint(len(event.Members)))
|
||||
app.chatView.messagesList.setFetchingChunk(false, uint(len(event.Members)))
|
||||
})
|
||||
|
||||
discordState.AddHandler(func(event *gateway.GuildMemberRemoveEvent) {
|
||||
app.messageInput.cache.Invalidate(event.GuildID.String()+" "+event.User.Username, discordState.MemberState.SearchLimit)
|
||||
app.chatView.messageInput.cache.Invalidate(event.GuildID.String()+" "+event.User.Username, discordState.MemberState.SearchLimit)
|
||||
})
|
||||
|
||||
discordState.StateLog = func(err error) {
|
||||
|
|
@ -79,18 +79,18 @@ func onRaw(event *ws.RawEvent) {
|
|||
|
||||
func onReadUpdate(event *read.UpdateEvent) {
|
||||
var guildNode *tview.TreeNode
|
||||
app.guildsTree.
|
||||
app.chatView.guildsTree.
|
||||
GetRoot().
|
||||
Walk(func(node, parent *tview.TreeNode) bool {
|
||||
switch node.GetReference() {
|
||||
case event.GuildID:
|
||||
node.SetTextStyle(app.guildsTree.getGuildNodeStyle(event.GuildID))
|
||||
node.SetTextStyle(app.chatView.guildsTree.getGuildNodeStyle(event.GuildID))
|
||||
guildNode = node
|
||||
return false
|
||||
case event.ChannelID:
|
||||
// private channel
|
||||
if !event.GuildID.IsValid() {
|
||||
style := app.guildsTree.getChannelNodeStyle(event.ChannelID)
|
||||
style := app.chatView.guildsTree.getChannelNodeStyle(event.ChannelID)
|
||||
node.SetTextStyle(style)
|
||||
return false
|
||||
}
|
||||
|
|
@ -102,7 +102,7 @@ func onReadUpdate(event *read.UpdateEvent) {
|
|||
if guildNode != nil {
|
||||
guildNode.Walk(func(node, parent *tview.TreeNode) bool {
|
||||
if node.GetReference() == event.ChannelID {
|
||||
node.SetTextStyle(app.guildsTree.getChannelNodeStyle(event.ChannelID))
|
||||
node.SetTextStyle(app.chatView.guildsTree.getChannelNodeStyle(event.ChannelID))
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
@ -115,7 +115,7 @@ func onReadUpdate(event *read.UpdateEvent) {
|
|||
|
||||
func onReady(r *gateway.ReadyEvent) {
|
||||
dmNode := tview.NewTreeNode("Direct Messages")
|
||||
root := app.guildsTree.
|
||||
root := app.chatView.guildsTree.
|
||||
GetRoot().
|
||||
ClearChildren().
|
||||
AddChild(dmNode)
|
||||
|
|
@ -134,20 +134,20 @@ func onReady(r *gateway.ReadyEvent) {
|
|||
continue
|
||||
}
|
||||
|
||||
app.guildsTree.createGuildNode(root, *guild)
|
||||
app.chatView.guildsTree.createGuildNode(root, *guild)
|
||||
} else {
|
||||
app.guildsTree.createFolderNode(folder)
|
||||
app.chatView.guildsTree.createFolderNode(folder)
|
||||
}
|
||||
}
|
||||
|
||||
app.guildsTree.SetCurrentNode(root)
|
||||
app.SetFocus(app.guildsTree)
|
||||
app.chatView.guildsTree.SetCurrentNode(root)
|
||||
app.SetFocus(app.chatView.guildsTree)
|
||||
app.Draw()
|
||||
}
|
||||
|
||||
func onMessageCreate(message *gateway.MessageCreateEvent) {
|
||||
if app.guildsTree.selectedChannelID == message.ChannelID {
|
||||
app.messagesList.drawMessage(app.messagesList, message.Message)
|
||||
if app.chatView.guildsTree.selectedChannelID == message.ChannelID {
|
||||
app.chatView.messagesList.drawMessage(app.chatView.messagesList, message.Message)
|
||||
app.Draw()
|
||||
}
|
||||
|
||||
|
|
@ -157,21 +157,21 @@ func onMessageCreate(message *gateway.MessageCreateEvent) {
|
|||
}
|
||||
|
||||
func onMessageUpdate(message *gateway.MessageUpdateEvent) {
|
||||
if app.guildsTree.selectedChannelID == message.ChannelID {
|
||||
if app.chatView.guildsTree.selectedChannelID == message.ChannelID {
|
||||
onMessageDelete(&gateway.MessageDeleteEvent{ID: message.ID, ChannelID: message.ChannelID, GuildID: message.GuildID})
|
||||
}
|
||||
}
|
||||
|
||||
func onMessageDelete(message *gateway.MessageDeleteEvent) {
|
||||
if app.guildsTree.selectedChannelID == message.ChannelID {
|
||||
if app.chatView.guildsTree.selectedChannelID == message.ChannelID {
|
||||
messages, err := discordState.Cabinet.Messages(message.ChannelID)
|
||||
if err != nil {
|
||||
slog.Error("failed to get messages from state", "err", err, "channel_id", message.ChannelID)
|
||||
return
|
||||
}
|
||||
|
||||
app.messagesList.reset()
|
||||
app.messagesList.drawMessages(messages)
|
||||
app.chatView.messagesList.reset()
|
||||
app.chatView.messagesList.drawMessages(messages)
|
||||
app.Draw()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue