summaryrefslogtreecommitdiff
path: root/internal/client/ui/core
diff options
context:
space:
mode:
authorKyren223 <Kyren223@proton.me>2024-11-30 16:55:11 +0200
committerKyren223 <Kyren223@proton.me>2024-11-30 16:55:11 +0200
commit9bbf36550b4871299bad0ff0a7d42617914b543a (patch)
tree76ea564866d870dbf375a3eb5216ee25584704e9 /internal/client/ui/core
parentc54d791d139d02f8145bcb5b79ad8fd5809f189b (diff)
Added frequencies UI
Diffstat (limited to 'internal/client/ui/core')
-rw-r--r--internal/client/ui/core/core.go23
-rw-r--r--internal/client/ui/core/network/network.go157
-rw-r--r--internal/client/ui/core/networklist/networklist.go38
3 files changed, 200 insertions, 18 deletions
diff --git a/internal/client/ui/core/core.go b/internal/client/ui/core/core.go
index 6949aee..6ba25c1 100644
--- a/internal/client/ui/core/core.go
+++ b/internal/client/ui/core/core.go
@@ -13,6 +13,7 @@ import (
"github.com/charmbracelet/lipgloss"
"github.com/kyren223/eko/internal/client/gateway"
"github.com/kyren223/eko/internal/client/ui"
+ "github.com/kyren223/eko/internal/client/ui/core/network"
"github.com/kyren223/eko/internal/client/ui/core/networkcreation"
"github.com/kyren223/eko/internal/client/ui/core/networklist"
"github.com/kyren223/eko/internal/client/ui/core/state"
@@ -32,9 +33,7 @@ var (
const (
FocusNetworkList = iota
- FocusFrequencies
- FocusChat
- FocusUsers
+ FocusNetwork
FocusMax
)
@@ -50,6 +49,7 @@ type Model struct {
networkCreationPopup *networkcreation.Model
networkList networklist.Model
+ network network.Model
focus int
}
@@ -78,7 +78,9 @@ func (m Model) View() string {
return m.loading.View()
}
- result := m.networkList.View()
+ networkList := m.networkList.View()
+ network := m.network.View()
+ result := lipgloss.JoinHorizontal(lipgloss.Top, networkList, network)
result = lipgloss.Place(
ui.Width, ui.Height,
@@ -201,6 +203,13 @@ func (m *Model) updateConnected(msg tea.Msg) tea.Cmd {
m.networkCreationPopup = &popup
return cmd
}
+
+ if msg.String() == "L" && m.focus == FocusNetworkList {
+ m.move(1)
+ } else if msg.String() == "H" && m.focus == FocusNetwork {
+ m.move(-1)
+ }
+
}
}
@@ -208,6 +217,9 @@ func (m *Model) updateConnected(msg tea.Msg) tea.Cmd {
switch m.focus {
case FocusNetworkList:
m.networkList, cmd = m.networkList.Update(msg)
+ m.network.Set(m.networkList.Index())
+ case FocusNetwork:
+ m.network, cmd = m.network.Update(msg)
}
return cmd
@@ -227,9 +239,12 @@ func (m *Model) move(direction int) {
m.focus = max(0, min(FocusMax-1, focus))
m.networkList.Blur()
+ m.network.Blur()
switch m.focus {
case FocusNetworkList:
m.networkList.Focus()
+ case FocusNetwork:
+ m.network.Focus()
default:
assert.Never("missing switch statement field in move", "focus", m.focus)
}
diff --git a/internal/client/ui/core/network/network.go b/internal/client/ui/core/network/network.go
new file mode 100644
index 0000000..5a5d0ec
--- /dev/null
+++ b/internal/client/ui/core/network/network.go
@@ -0,0 +1,157 @@
+package network
+
+import (
+ "strings"
+
+ tea "github.com/charmbracelet/bubbletea"
+ "github.com/charmbracelet/lipgloss"
+ "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/state"
+ "github.com/kyren223/eko/internal/packet"
+)
+
+var (
+ width = 24
+ sepStyle = lipgloss.NewStyle().Width(0).
+ Border(lipgloss.ThickBorder(), false, true, false, false)
+ nameStyle = lipgloss.NewStyle().
+ Margin(0, 0, 1).Padding(1).Width(width).Align(lipgloss.Center).
+ Border(lipgloss.ThickBorder(), false, false, true)
+ margin = 3
+ frequencyStyle = lipgloss.NewStyle().
+ Margin(0, margin).Padding(0, 1).Width(width - (margin * 2)).
+ Align(lipgloss.Left)
+ symbol = "# "
+)
+
+type Model struct {
+ network *packet.FullNetwork
+ history []func(m *Model)
+ index int
+ focus bool
+}
+
+func New() Model {
+ return Model{
+ focus: false,
+ index: 0,
+ network: nil,
+ }
+}
+
+func (m Model) Init() tea.Cmd {
+ return nil
+}
+
+func (m Model) View() string {
+ if m.network == nil {
+ return ""
+ }
+
+ var builder strings.Builder
+
+ bg := lipgloss.Color(m.network.BgHexColor)
+ fg := lipgloss.Color(m.network.FgHexColor)
+ nameStyle := nameStyle.Background(bg).Foreground(fg)
+ if m.focus {
+ nameStyle = nameStyle.BorderForeground(colors.Focus)
+ }
+ builder.WriteString(nameStyle.Render(m.network.Name))
+
+ builder.WriteString("\n")
+ for i, frequency := range m.network.Frequencies {
+ color := colors.White
+ if frequency.HexColor != nil {
+ color = lipgloss.Color(*frequency.HexColor)
+ }
+ frequencyStyle := frequencyStyle.Foreground(color)
+ if m.index == i {
+ frequencyStyle = frequencyStyle.Background(colors.BackgroundHighlight)
+ }
+ builder.WriteString(frequencyStyle.Render(symbol + frequency.Name))
+ builder.WriteString("\n")
+ }
+
+ result := builder.String()
+
+ sep := sepStyle.Height(ui.Height)
+ if m.focus {
+ sep = sep.BorderForeground(colors.Focus)
+ }
+ result = lipgloss.JoinHorizontal(lipgloss.Top, result, sep.String())
+
+ return result
+}
+
+func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
+ switch msg := msg.(type) {
+ case *packet.SwapFrequencies:
+ // Pop first by shifting to the left
+ copy(m.history, m.history[1:])
+ m.history = m.history[:len(m.history)-1]
+ case *packet.Error:
+ if msg.PktType == packet.PacketSwapFrequencies {
+ // Server failed, revert!
+ undo := m.history[len(m.history)-1]
+ m.history = m.history[:len(m.history)-1]
+ undo(&m)
+ }
+
+ case tea.KeyMsg:
+ key := msg.String()
+ switch key {
+ case "K":
+ if 0 < m.index {
+ return m.Swap(-1)
+ }
+ case "J":
+ if m.index < m.FrequenciesLength()-1 {
+ return m.Swap(1)
+ }
+ case "k":
+ m.index = max(0, m.index-1)
+ case "j":
+ m.index = min(m.FrequenciesLength()-1, m.index+1)
+ }
+ }
+ return m, nil
+}
+
+func (m *Model) Focus() {
+ m.focus = true
+}
+
+func (m *Model) Blur() {
+ m.focus = false
+}
+
+func (m Model) Swap(dir int) (Model, tea.Cmd) {
+ cmd := gateway.Send(&packet.SwapFrequencies{
+ Network: m.network.ID,
+ Pos1: m.index,
+ Pos2: m.index + dir,
+ })
+ tmp := m.network.Frequencies[m.index]
+ m.network.Frequencies[m.index] = m.network.Frequencies[m.index+dir]
+ m.network.Frequencies[m.index+dir] = tmp
+ m.index += dir
+ m.history = append(m.history, func(m *Model) {
+ m.index -= dir
+ tmp := m.network.Frequencies[m.index]
+ m.network.Frequencies[m.index] = m.network.Frequencies[m.index+dir]
+ m.network.Frequencies[m.index+dir] = tmp
+ })
+ return m, cmd
+}
+
+func (m *Model) Set(index int) {
+ if index != -1 {
+ m.network = &state.State.Networks[index]
+ }
+}
+
+func (m Model) FrequenciesLength() int {
+ return len(m.network.Frequencies)
+}
diff --git a/internal/client/ui/core/networklist/networklist.go b/internal/client/ui/core/networklist/networklist.go
index 355d3e2..0f7ca7e 100644
--- a/internal/client/ui/core/networklist/networklist.go
+++ b/internal/client/ui/core/networklist/networklist.go
@@ -13,16 +13,21 @@ import (
)
var (
- style = lipgloss.NewStyle().Border(lipgloss.ThickBorder(), true, false)
+ sepStyle = lipgloss.NewStyle().Width(0).
+ Border(lipgloss.ThickBorder(), false, true, false, false)
partialIconStyle = lipgloss.NewStyle().
Width(6).Height(3).
Align(lipgloss.Center).
Border(lipgloss.ThickBorder(), false, false)
selectedIndicator = "šŸ­€\nā–Œ\nšŸ­›"
- trustedUsersIcon = IconStyle("ī· ", lipgloss.Color(colors.Turquoise), lipgloss.Color(colors.DarkerCyan))
+ trustedUsersIcon = IconStyle("ī· ", colors.Turquoise, colors.DarkerCyan)
trustedUsersButton = trustedUsersIcon.Margin(0, 1, 1).String()
- trustedUsersButtonSelected = lipgloss.JoinHorizontal(ui.Center, selectedIndicator, trustedUsersIcon.Margin(0, 1, 1, 0).String())
+ trustedUsersButtonSelected = lipgloss.JoinHorizontal(
+ ui.Center,
+ selectedIndicator,
+ trustedUsersIcon.Margin(0, 1, 1, 0).String(),
+ )
)
func IconStyle(icon string, fg, bg lipgloss.Color) lipgloss.Style {
@@ -38,7 +43,7 @@ type Model struct {
func New() Model {
return Model{
focus: false,
- index: 0,
+ index: -1,
}
}
@@ -47,11 +52,7 @@ func (m Model) Init() tea.Cmd {
}
func (m Model) View() string {
- // border := lipgloss.ThickBorder()
var builder strings.Builder
-
- // top := strings.Repeat(border.Top, 6)
- // builder.WriteString(fmt.Sprintf("%s%s%s\n", border.TopLeft, top, border.TopRight))
builder.WriteString("\n")
if m.index == -1 {
builder.WriteString(trustedUsersButtonSelected)
@@ -60,24 +61,29 @@ func (m Model) View() string {
}
builder.WriteString("\n")
for i, network := range state.State.Networks {
- icon := IconStyle(network.Icon, lipgloss.Color(network.FgHexColor), lipgloss.Color(network.BgHexColor))
+ icon := IconStyle(network.Icon,
+ lipgloss.Color(network.FgHexColor),
+ lipgloss.Color(network.BgHexColor),
+ )
if m.index == i {
- builder.WriteString(lipgloss.JoinHorizontal(ui.Center, selectedIndicator, icon.Margin(0, 1, 1, 0).String()))
+ builder.WriteString(lipgloss.JoinHorizontal(
+ ui.Center,
+ selectedIndicator,
+ icon.Margin(0, 1, 1, 0).String(),
+ ))
} else {
builder.WriteString(icon.Margin(0, 1, 1).String())
}
builder.WriteString("\n")
}
- // bottom := strings.Repeat(border.Bottom, 6)
- // builder.WriteString(fmt.Sprintf("\n%s%s%s", border.BottomLeft, bottom, border.BottomRight))
result := builder.String()
- sep := lipgloss.NewStyle().Border(lipgloss.ThickBorder(), false, true, false, false).Height(ui.Height).Width(0)
+ sep := sepStyle.Height(ui.Height)
if m.focus {
sep = sep.BorderForeground(colors.Focus)
}
- result = lipgloss.JoinHorizontal(lipgloss.Top, result, sep.Render(""))
+ result = lipgloss.JoinHorizontal(lipgloss.Top, result, sep.String())
return result
}
@@ -141,3 +147,7 @@ func (m Model) Swap(dir int) (Model, tea.Cmd) {
})
return m, cmd
}
+
+func (m Model) Index() int {
+ return m.index
+}