mirror of
https://github.com/Kyren223/eko.git
synced 2026-05-01 09:14:40 +00:00
Implemented client-side message sending
This commit is contained in:
@@ -7,8 +7,12 @@ import (
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
|
||||
"github.com/kyren223/eko/internal/client/gateway"
|
||||
"github.com/kyren223/eko/internal/client/ui/colors"
|
||||
"github.com/kyren223/eko/internal/client/ui/core/state"
|
||||
"github.com/kyren223/eko/internal/client/ui/viminput"
|
||||
"github.com/kyren223/eko/internal/packet"
|
||||
"github.com/kyren223/eko/pkg/snowflake"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -28,6 +32,10 @@ type Model struct {
|
||||
vi viminput.Model
|
||||
focus bool
|
||||
locked bool
|
||||
|
||||
networkIndex int // Note this might be invalid, rely on frequencyIndex
|
||||
receiverIndex *int
|
||||
frequencyIndex *int
|
||||
}
|
||||
|
||||
func New() Model {
|
||||
@@ -126,12 +134,17 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
|
||||
}
|
||||
|
||||
if m.locked {
|
||||
InNormal := m.vi.Mode() == viminput.NormalMode
|
||||
if key, ok := msg.(tea.KeyMsg); ok && InNormal {
|
||||
if key.String() == "q" {
|
||||
if key, ok := msg.(tea.KeyMsg); ok {
|
||||
InNormal := m.vi.Mode() == viminput.NormalMode
|
||||
if key.String() == "q" && InNormal {
|
||||
m.locked = false
|
||||
return m, nil
|
||||
}
|
||||
|
||||
if key.Type == tea.KeyEnter {
|
||||
cmd := m.sendMessage()
|
||||
return m, cmd
|
||||
}
|
||||
}
|
||||
|
||||
var cmd tea.Cmd
|
||||
@@ -165,3 +178,41 @@ func (m *Model) Blur() {
|
||||
func (m Model) Locked() bool {
|
||||
return m.locked
|
||||
}
|
||||
|
||||
func (m *Model) sendMessage() tea.Cmd {
|
||||
message := m.vi.String()
|
||||
if len(message) > MaxCharCount {
|
||||
return nil
|
||||
}
|
||||
if len(strings.TrimSpace(message)) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
m.vi.Reset()
|
||||
|
||||
var receiverId *snowflake.ID = nil
|
||||
if m.receiverIndex != nil {
|
||||
// TODO: do nothing for now, until trusted friends are implemented
|
||||
}
|
||||
|
||||
var frequencyId *snowflake.ID = nil
|
||||
if m.frequencyIndex != nil {
|
||||
network := state.State.Networks[m.networkIndex]
|
||||
frequencyId = &network.Frequencies[*m.frequencyIndex].ID
|
||||
}
|
||||
|
||||
return gateway.Send(&packet.SendMessage{
|
||||
ReceiverID: receiverId,
|
||||
FrequencyID: frequencyId,
|
||||
Content: message,
|
||||
})
|
||||
}
|
||||
|
||||
func (m *Model) SetNetworkIndex(networkIndex int) {
|
||||
m.networkIndex = networkIndex
|
||||
}
|
||||
|
||||
func (m *Model) Set(receiverIndex, frequencyIndex *int) {
|
||||
m.receiverIndex = receiverIndex
|
||||
m.frequencyIndex = frequencyIndex
|
||||
}
|
||||
|
||||
@@ -288,9 +288,12 @@ func (m *Model) updateConnected(msg tea.Msg) tea.Cmd {
|
||||
switch m.focus {
|
||||
case FocusNetworkList:
|
||||
m.networkList, cmd = m.networkList.Update(msg)
|
||||
m.frequencyList.Set(m.networkList.Index())
|
||||
m.frequencyList.SetNetworkIndex(m.networkList.Index())
|
||||
m.chat.SetNetworkIndex(m.networkList.Index())
|
||||
case FocusFrequencyList:
|
||||
m.frequencyList, cmd = m.frequencyList.Update(msg)
|
||||
index := m.frequencyList.Index()
|
||||
m.chat.Set(nil, &index)
|
||||
case FocusChat:
|
||||
m.chat, cmd = m.chat.Update(msg)
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ func (m Model) Swap(dir int) (Model, tea.Cmd) {
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
func (m *Model) Set(index int) {
|
||||
func (m *Model) SetNetworkIndex(index int) {
|
||||
m.networkIndex = index
|
||||
}
|
||||
|
||||
@@ -162,3 +162,7 @@ func (m Model) Network() *packet.FullNetwork {
|
||||
}
|
||||
return &state.State.Networks[m.networkIndex]
|
||||
}
|
||||
|
||||
func (m *Model) Index() int {
|
||||
return m.index
|
||||
}
|
||||
|
||||
@@ -504,6 +504,10 @@ func (m *Model) handleNormalModeKeys(key tea.KeyMsg) {
|
||||
|
||||
case "p":
|
||||
paste := m.Paste()
|
||||
if paste == "" {
|
||||
return
|
||||
}
|
||||
|
||||
newline := paste[len(paste)-1] == '\n'
|
||||
if newline {
|
||||
paste = paste[:len(paste)-1]
|
||||
@@ -561,6 +565,10 @@ func (m *Model) handleNormalModeKeys(key tea.KeyMsg) {
|
||||
}
|
||||
case "P":
|
||||
paste := m.Paste()
|
||||
if paste == "" {
|
||||
return
|
||||
}
|
||||
|
||||
newline := paste[len(paste)-1] == '\n'
|
||||
if newline {
|
||||
paste = paste[:len(paste)-1]
|
||||
@@ -626,20 +634,27 @@ func (m *Model) handleInsertModeKeys(key tea.KeyMsg) {
|
||||
return
|
||||
}
|
||||
|
||||
if key.Type == tea.KeyEnter {
|
||||
line := m.lines[m.cursorLine]
|
||||
after := line[m.cursorColumn:]
|
||||
m.lines[m.cursorLine] = line[:m.cursorColumn]
|
||||
// Note: commented out because enter is used to send a message
|
||||
// even in insert mode, an alternative that discord uses is
|
||||
// to use Shift+Enter for this functionality but unfortunately
|
||||
// this is not supported in bubbletea (probably due to terminal limitations)
|
||||
// If there is a way to add this for Shift+Enter please notify me
|
||||
// at Kyren223@proton.me
|
||||
|
||||
var newline []rune
|
||||
newline = append(newline, after...)
|
||||
m.lines = slices.Insert(m.lines, m.cursorLine+1, newline)
|
||||
|
||||
m.SetCursorLine(m.cursorLine + 1)
|
||||
m.SetCursorColumn(0)
|
||||
|
||||
return
|
||||
}
|
||||
// if key.Type == tea.KeyEnter {
|
||||
// line := m.lines[m.cursorLine]
|
||||
// after := line[m.cursorColumn:]
|
||||
// m.lines[m.cursorLine] = line[:m.cursorColumn]
|
||||
//
|
||||
// var newline []rune
|
||||
// newline = append(newline, after...)
|
||||
// m.lines = slices.Insert(m.lines, m.cursorLine+1, newline)
|
||||
//
|
||||
// m.SetCursorLine(m.cursorLine + 1)
|
||||
// m.SetCursorColumn(0)
|
||||
//
|
||||
// return
|
||||
// }
|
||||
|
||||
keyStr := key.String()
|
||||
length := len(keyStr)
|
||||
@@ -1759,13 +1774,13 @@ func (m *Model) handleVisualModeKeys(key tea.KeyMsg) {
|
||||
}
|
||||
|
||||
if motion == "p" || motion == "P" {
|
||||
copyPaste := m.Paste()
|
||||
copyOfPaste := m.Paste()
|
||||
m.Yank(paste)
|
||||
key.Runes[0] = 'P' // In visual it should always use backwards P
|
||||
m.handleNormalModeKeys(key)
|
||||
|
||||
if motion == "p" {
|
||||
m.Yank(copyPaste) // Restore
|
||||
m.Yank(copyOfPaste) // Restore
|
||||
}
|
||||
// Note: we don't restore for "P" because we use it like
|
||||
// <leader>p (we paste over and keep what we had)
|
||||
@@ -1872,14 +1887,14 @@ func (m *Model) handleVisualLineModeKeys(key tea.KeyMsg) {
|
||||
m.SetCursorColumn(0)
|
||||
}
|
||||
|
||||
copyPaste := m.Paste()
|
||||
copyOfPaste := m.Paste()
|
||||
m.Yank(paste)
|
||||
key.Runes[0] = 'p' // In visual line it should always use forward p
|
||||
// This is bcz we are pasting on a blank line
|
||||
m.handleNormalModeKeys(key)
|
||||
|
||||
if motion == "p" {
|
||||
m.Yank(copyPaste) // Restore
|
||||
m.Yank(copyOfPaste) // Restore
|
||||
}
|
||||
// Note: we don't restore for "P" because we use it like
|
||||
// <leader>p (we paste over and keep what we had)
|
||||
@@ -1994,3 +2009,32 @@ func (m *Model) Count() int {
|
||||
}
|
||||
return sum + len(m.lines) - 1
|
||||
}
|
||||
|
||||
func (m *Model) String() string {
|
||||
var builder strings.Builder
|
||||
for _, line := range m.lines {
|
||||
builder.WriteString(string(line))
|
||||
builder.WriteByte('\n')
|
||||
}
|
||||
message := builder.String()
|
||||
message = message[:len(message)-1] // strip last \n
|
||||
return message
|
||||
}
|
||||
|
||||
func (m *Model) Reset() {
|
||||
m.lines = [][]rune{[]rune("")}
|
||||
m.undoStack = []State{{[][]rune{[]rune("")}, 0, 0}}
|
||||
m.redoStack = []State{}
|
||||
m.cursorLine = 0
|
||||
m.cursorColumn = 0
|
||||
m.goalColumn = InvalidGoal
|
||||
m.count = NoCount
|
||||
m.pending = NullChar
|
||||
m.gmod = false
|
||||
m.fchar = NullChar
|
||||
m.fmod = NullChar
|
||||
m.tlast = false
|
||||
m.imod = false
|
||||
m.amod = false
|
||||
m.offset = 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user