summaryrefslogtreecommitdiff
path: root/internal/client/ui
diff options
context:
space:
mode:
Diffstat (limited to 'internal/client/ui')
-rw-r--r--internal/client/ui/chat/chat.go130
-rw-r--r--internal/client/ui/core/chat/chat.go48
-rw-r--r--internal/client/ui/core/core.go20
-rw-r--r--internal/client/ui/core/network/network.go12
-rw-r--r--internal/client/ui/messagebox/messagebox.go131
-rw-r--r--internal/client/ui/viminput/linedecorations.go17
-rw-r--r--internal/client/ui/viminput/viminput.go89
7 files changed, 175 insertions, 272 deletions
diff --git a/internal/client/ui/chat/chat.go b/internal/client/ui/chat/chat.go
deleted file mode 100644
index c69d0fd..0000000
--- a/internal/client/ui/chat/chat.go
+++ /dev/null
@@ -1,130 +0,0 @@
-package chat
-
-import (
- "fmt"
- "log"
- "strings"
-
- "github.com/charmbracelet/bubbles/cursor"
- "github.com/charmbracelet/bubbles/textarea"
- tea "github.com/charmbracelet/bubbletea"
- "github.com/charmbracelet/lipgloss"
-
- "github.com/kyren223/eko/internal/client/api"
- "github.com/kyren223/eko/internal/client/ui/messagebox"
- "github.com/kyren223/eko/internal/data"
- "github.com/kyren223/eko/internal/packet"
-)
-
-type Model struct {
- messagebox messagebox.Model
- textarea textarea.Model
- err error
-}
-
-func New() Model {
- ta := textarea.New()
- ta.Placeholder = "Send a message..."
- ta.Focus()
-
- ta.Prompt = "┃ "
- ta.CharLimit = 280
-
- ta.SetWidth(30)
- ta.SetHeight(3)
-
- // Remove cursor line styling
- ta.FocusedStyle.CursorLine = lipgloss.NewStyle()
-
- ta.ShowLineNumbers = false
-
- ta.KeyMap.InsertNewline.SetEnabled(false)
-
- return Model{
- textarea: ta,
- messagebox: messagebox.New(30, 20),
- err: nil,
- }
-}
-
-func (m Model) Init() tea.Cmd {
- return tea.Batch(textarea.Blink, api.GetMessages)
-}
-
-func (m Model) View() string {
- return fmt.Sprintf(
- "%s\n%s",
- m.messagebox.View(),
- m.textarea.View(),
- ) + ""
-}
-
-func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
- switch msg := msg.(type) {
- case tea.WindowSizeMsg:
- m.messagebox.Viewport.Width = msg.Width
- m.messagebox.Viewport.Height = msg.Height - m.textarea.Height()
- m.messagebox.Viewport.GotoBottom()
-
- m.textarea.SetWidth(msg.Width)
- log.Println("resized to:", msg.Width, "x", msg.Height)
-
- var mbCmd, taCmd tea.Cmd
- m.messagebox, mbCmd = m.messagebox.Update(msg)
- m.textarea, taCmd = m.textarea.Update(msg)
- return m, tea.Batch(mbCmd, taCmd)
-
- case tea.KeyMsg:
- switch msg.Type {
-
- case tea.KeyEnter:
- value := m.textarea.Value()
-
- content := strings.TrimSpace(value)
- if content == "" {
- return m, nil
- }
- m.textarea.Reset()
-
- return m, api.SendMessage(content)
-
- default:
- var cmd tea.Cmd
- m.textarea, cmd = m.textarea.Update(msg)
- return m, cmd
- }
-
- case packet.Payload:
- switch msg := msg.(type) {
- case *packet.Messages:
- m.messagebox.SetMessages(msg.Messages)
-
- var cmd tea.Cmd
- m.messagebox, cmd = m.messagebox.Update(msg)
- return m, cmd
-
- default:
- return m, nil
- }
-
- case api.AppendMessage:
- m.messagebox.AppendMessage(data.Message(msg))
-
- var cmd tea.Cmd
- m.messagebox, cmd = m.messagebox.Update(msg)
- return m, cmd
-
- case api.UserProfileUpdate:
- var cmd tea.Cmd
- m.messagebox, cmd = m.messagebox.Update(msg)
- return m, cmd
-
- case cursor.BlinkMsg:
- var cmd tea.Cmd
- m.textarea, cmd = m.textarea.Update(msg)
- return m, cmd
-
- default:
- return m, nil
- }
-}
diff --git a/internal/client/ui/core/chat/chat.go b/internal/client/ui/core/chat/chat.go
new file mode 100644
index 0000000..b3597a8
--- /dev/null
+++ b/internal/client/ui/core/chat/chat.go
@@ -0,0 +1,48 @@
+package chat
+
+import (
+ "log"
+
+ "github.com/charmbracelet/bubbles/textarea"
+ tea "github.com/charmbracelet/bubbletea"
+ "github.com/charmbracelet/lipgloss"
+
+ "github.com/kyren223/eko/internal/client/ui/colors"
+ "github.com/kyren223/eko/internal/client/ui/viminput"
+)
+
+type Model struct {
+ vi viminput.Model
+}
+
+func New() Model {
+ vi := viminput.New(30, 3)
+ vi.Placeholder = "Send a message..."
+ vi.PlaceholderStyle = lipgloss.NewStyle().Foreground(colors.Gray)
+ vi.LineDecoration = func(lnum int, line string, cursorLnum int) string {
+ return "┃ "
+ }
+ // vi.ShowLineNumbers = false
+
+ // vi.CharLimit = 280
+
+ // vi.Focus()
+
+ log.Println("Placeholder:", vi.Placeholder)
+
+ return Model{
+ vi: vi,
+ }
+}
+
+func (m Model) Init() tea.Cmd {
+ return tea.Batch(textarea.Blink, nil)
+}
+
+func (m Model) View() string {
+ return m.vi.View()
+}
+
+func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
+ return m, nil
+}
diff --git a/internal/client/ui/core/core.go b/internal/client/ui/core/core.go
index 5031dc0..b4390e0 100644
--- a/internal/client/ui/core/core.go
+++ b/internal/client/ui/core/core.go
@@ -58,14 +58,18 @@ type Model struct {
func New(privKey ed25519.PrivateKey, name string) Model {
m := Model{
- name: name,
- privKey: privKey,
- networkList: networklist.New(),
- loading: loadscreen.New(connectingToServer),
- timer: newTimer(initialTimeout),
- timeout: initialTimeout,
- connected: false,
- focus: FocusNetworkList,
+ name: name,
+ privKey: privKey,
+ id: 0,
+ loading: loadscreen.New(connectingToServer),
+ timer: newTimer(initialTimeout),
+ timeout: initialTimeout,
+ connected: false,
+ networkCreationPopup: nil,
+ frequencyCreationPopup: nil,
+ networkList: networklist.New(),
+ network: network.New(),
+ focus: FocusNetworkList,
}
m.move(0) // Update focus
diff --git a/internal/client/ui/core/network/network.go b/internal/client/ui/core/network/network.go
index 75ea318..3c24350 100644
--- a/internal/client/ui/core/network/network.go
+++ b/internal/client/ui/core/network/network.go
@@ -8,6 +8,7 @@ import (
"github.com/kyren223/eko/internal/client/gateway"
"github.com/kyren223/eko/internal/client/ui"
"github.com/kyren223/eko/internal/client/ui/colors"
+ "github.com/kyren223/eko/internal/client/ui/core/chat"
"github.com/kyren223/eko/internal/client/ui/core/state"
"github.com/kyren223/eko/internal/packet"
)
@@ -31,12 +32,16 @@ type Model struct {
networkIndex int
index int
focus bool
+ chat chat.Model
}
func New() Model {
+ chat := chat.New()
+
return Model{
focus: false,
index: 0,
+ chat: chat,
}
}
@@ -69,13 +74,14 @@ func (m Model) View() string {
builder.WriteString("\n")
}
- result := builder.String()
-
+ sidebar := builder.String()
sep := sepStyle.Height(ui.Height)
if m.focus {
sep = sep.BorderForeground(colors.Focus)
}
- result = lipgloss.JoinHorizontal(lipgloss.Top, result, sep.String())
+ sidebar = lipgloss.JoinHorizontal(lipgloss.Top, sidebar, sep.String())
+
+ result := lipgloss.JoinHorizontal(lipgloss.Top, sidebar, m.chat.View())
return result
}
diff --git a/internal/client/ui/messagebox/messagebox.go b/internal/client/ui/messagebox/messagebox.go
deleted file mode 100644
index 0728cb1..0000000
--- a/internal/client/ui/messagebox/messagebox.go
+++ /dev/null
@@ -1,131 +0,0 @@
-package messagebox
-
-import (
- "slices"
- "strings"
- "time"
-
- "github.com/charmbracelet/bubbles/viewport"
- tea "github.com/charmbracelet/bubbletea"
- "github.com/charmbracelet/lipgloss"
-
- "github.com/kyren223/eko/internal/client/api"
- "github.com/kyren223/eko/internal/data"
- "github.com/kyren223/eko/pkg/snowflake"
-)
-
-var (
- senderStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("5")).Bold(true)
- timestampStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#585c62")).Italic(true)
-)
-
-type user struct {
- name string
- isFetching bool
-}
-
-type Model struct {
- Viewport viewport.Model
- messages []data.Message
- users map[snowflake.ID]user
-}
-
-func New(width, height int) Model {
- return Model{
- Viewport: viewport.New(width, height),
- messages: nil,
- users: make(map[snowflake.ID]user),
- }
-}
-
-func (m Model) Init() tea.Cmd {
- return api.GetMessages
-}
-
-func (m Model) View() string {
- return m.Viewport.View()
-}
-
-func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
- var cmds []tea.Cmd
-
- for id, user := range m.users {
- if !user.isFetching && user.name == "" {
- cmds = append(cmds, api.GetUserById(id))
- user.isFetching = true
- m.users[id] = user
- }
- }
-
- var cmd tea.Cmd
- m.Viewport, cmd = m.Viewport.Update(msg)
- cmds = append(cmds, cmd)
-
- switch msg := msg.(type) {
- case api.UserProfileUpdate:
- m.users[msg.ID] = user{msg.Name, false}
- m.UpdateMessages()
- }
-
- return m, tea.Batch(cmds...)
-}
-
-func (m *Model) AppendMessage(message data.Message) {
- m.messages = append(m.messages, message)
- m.UpdateMessages()
-}
-
-func (m *Model) SetMessages(messages []data.Message) {
- m.messages = messages
- m.UpdateMessages()
-}
-
-func (m *Model) UpdateMessages() {
- for _, message := range m.messages {
- if _, exists := m.users[message.SenderID]; !exists {
- m.users[message.SenderID] = user{name: "", isFetching: false}
- }
- }
-
- m.sortMessages()
- m.updateContent()
- m.Viewport.GotoBottom()
-}
-
-func (m *Model) sortMessages() {
- slices.SortFunc(m.messages, func(a, b data.Message) int {
- if a.ID-b.ID < 0 {
- return -1
- } else {
- return 1
- }
- })
-}
-
-func (m *Model) updateContent() {
- if len(m.messages) == 0 {
- return
- }
-
- var builder strings.Builder
-
- for _, message := range m.messages {
- sender := m.users[message.SenderID].name
- builder.WriteString(senderStyle.Render(sender))
- builder.WriteByte(' ')
-
- timestamp := timestampFromID(message.ID)
- builder.WriteString(timestampStyle.Render(timestamp))
- builder.WriteByte('\n')
-
- builder.WriteString(message.Content)
- builder.WriteByte('\n')
- }
-
- m.Viewport.SetContent(builder.String()[:builder.Len()-1])
-}
-
-func timestampFromID(id snowflake.ID) string {
- localTime := time.UnixMilli(id.Time())
- return localTime.Format("02/01/2006 3:04 PM")
-}
diff --git a/internal/client/ui/viminput/linedecorations.go b/internal/client/ui/viminput/linedecorations.go
new file mode 100644
index 0000000..82e51f1
--- /dev/null
+++ b/internal/client/ui/viminput/linedecorations.go
@@ -0,0 +1,17 @@
+package viminput
+
+import (
+ "strconv"
+
+ "github.com/charmbracelet/lipgloss"
+)
+
+func LineNumberDecoration(style lipgloss.Style) LineDecoration {
+ return func(lnum int, line string, cursorLnum int) string {
+ return style.Render(strconv.FormatInt(int64(lnum), 10))
+ }
+}
+
+func EmptyLineDecoration(lnum int, line string, cursorLnum int) string {
+ return ""
+}
diff --git a/internal/client/ui/viminput/viminput.go b/internal/client/ui/viminput/viminput.go
new file mode 100644
index 0000000..e2b65a8
--- /dev/null
+++ b/internal/client/ui/viminput/viminput.go
@@ -0,0 +1,89 @@
+package viminput
+
+import (
+ tea "github.com/charmbracelet/bubbletea"
+ "github.com/charmbracelet/lipgloss"
+)
+
+type (
+ Keymap struct{}
+ LineDecoration = func(lnum int, line string, cursorLnum int) string
+)
+
+type Line []byte
+
+type Model struct {
+ keymap Keymap
+
+ PlaceholderStyle lipgloss.Style
+ PromptStyle lipgloss.Style
+
+ Placeholder string
+ LineDecoration LineDecoration
+
+ lines []Line
+
+ width int
+ height int
+ focus bool
+}
+
+func New(width, height int) Model {
+ return Model{
+ keymap: Keymap{},
+ PlaceholderStyle: lipgloss.NewStyle(),
+ PromptStyle: lipgloss.NewStyle(),
+ Placeholder: "",
+ LineDecoration: EmptyLineDecoration,
+ width: width,
+ height: height,
+ focus: false,
+ }
+}
+
+func (m Model) Init() tea.Cmd {
+ return nil
+}
+
+func (m Model) View() string {
+ placeholder := m.PlaceholderStyle.Render(m.Placeholder)
+ lineDecoration := m.LineDecoration(1, "", 1)
+
+ result := lipgloss.JoinHorizontal(lipgloss.Top, lineDecoration, placeholder)
+
+ result = lipgloss.NewStyle().Width(m.width).Height(m.height).Render(result)
+
+ return result
+}
+
+func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
+ if !m.focus {
+ return m, nil
+ }
+
+ return m, nil
+}
+
+func (m *Model) SetWidth(width int) {
+ m.width = width
+}
+
+func (m Model) Width() int {
+ return m.width
+}
+
+func (m *Model) SetHeight(height int) {
+ m.height = height
+}
+
+func (m Model) Height() int {
+ return m.height
+}
+
+func (m *Model) Focus() {
+ m.focus = true
+}
+
+func (m *Model) Blur() {
+ m.focus = false
+}