summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorKyren223 <Kyren223@proton.me>2025-01-10 16:49:03 +0200
committerKyren223 <Kyren223@proton.me>2025-01-10 16:49:03 +0200
commit97ca4e2d704bfd949712f7d3476be2ec34c92533 (patch)
tree7705e428d3e8fc58b57b134accc5693195188430 /internal
parent4bff6ccf4e0a328766f44312631b09bc8eb98af8 (diff)
Fixed network and frequency list on the client
Diffstat (limited to 'internal')
-rw-r--r--internal/client/ui/core/chat/chat.go2
-rw-r--r--internal/client/ui/core/core.go128
-rw-r--r--internal/client/ui/core/frequencylist/frequencylist.go74
-rw-r--r--internal/client/ui/core/networklist/networklist.go72
-rw-r--r--internal/client/ui/core/state/state.go167
5 files changed, 237 insertions, 206 deletions
diff --git a/internal/client/ui/core/chat/chat.go b/internal/client/ui/core/chat/chat.go
index 8798977..cbc511e 100644
--- a/internal/client/ui/core/chat/chat.go
+++ b/internal/client/ui/core/chat/chat.go
@@ -261,7 +261,7 @@ func (m *Model) ResetBeforeSwitch() {
network := networks[m.networkIndex]
frequencyId := network.Frequencies[m.frequencyIndex].ID
log.Println("Saving", frequencyId)
- state.State.FrequencyState[frequencyId] = state.Frequency{
+ state.State.FrequencyState[frequencyId] = state.FrequencyState{
IncompleteMessage: m.vi.String(),
Offset: m.offset,
MaxHeight: m.maxMessagesHeight,
diff --git a/internal/client/ui/core/core.go b/internal/client/ui/core/core.go
index 1e2bc6a..5c45f05 100644
--- a/internal/client/ui/core/core.go
+++ b/internal/client/ui/core/core.go
@@ -3,15 +3,12 @@ package core
import (
"crypto/ed25519"
"fmt"
- "log"
- "slices"
"time"
"github.com/charmbracelet/bubbles/spinner"
"github.com/charmbracelet/bubbles/timer"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
- "github.com/google/btree"
"github.com/kyren223/eko/internal/client/gateway"
"github.com/kyren223/eko/internal/client/ui"
"github.com/kyren223/eko/internal/client/ui/core/chat"
@@ -22,7 +19,6 @@ import (
"github.com/kyren223/eko/internal/client/ui/core/networklist"
"github.com/kyren223/eko/internal/client/ui/core/state"
"github.com/kyren223/eko/internal/client/ui/loadscreen"
- "github.com/kyren223/eko/internal/data"
"github.com/kyren223/eko/internal/packet"
"github.com/kyren223/eko/pkg/assert"
"github.com/kyren223/eko/pkg/snowflake"
@@ -186,124 +182,16 @@ func (m *Model) updateConnected(msg tea.Msg) tea.Cmd {
}
case *packet.NetworksInfo:
- if msg.Set {
- state.State.Networks = msg.Networks
- } else {
- networks := state.State.Networks
-
- for _, newNetwork := range msg.Networks {
- add := true
- for i, existingNetwork := range networks {
- if existingNetwork.ID == newNetwork.ID {
- add = false
- if newNetwork.Position == -1 {
- newNetwork.Position = existingNetwork.Position
- }
- networks[i] = newNetwork
- break
- }
- }
- if add {
- networks = append(networks, newNetwork)
- }
- }
-
- networks = slices.DeleteFunc(networks, func(network packet.FullNetwork) bool {
- return slices.Contains(msg.RemovedNetworks, network.ID)
- })
- slices.SortFunc(networks, func(a, b packet.FullNetwork) int {
- return a.Position - b.Position
- })
- log.Println(networks)
- state.State.Networks = networks
- }
+ state.UpdateNetworks(msg)
case *packet.MembersInfo:
- var network *packet.FullNetwork
- for i, fullNetwork := range state.State.Networks {
- if fullNetwork.ID == msg.Network {
- network = &state.State.Networks[i]
- }
- }
-
- members := network.Members
- for _, updatedMember := range msg.Members {
- add := true
- for i, existingMember := range members {
- if existingMember.User.ID == updatedMember.User.ID {
- add = false
- members[i] = updatedMember
- break
- }
- }
- if add {
- members = append(members, updatedMember)
- }
- }
-
- members = slices.DeleteFunc(members, func(member data.GetNetworkMembersRow) bool {
- return slices.Contains(msg.RemovedMembers, member.User.ID)
- })
- log.Println(members)
- network.Members = members
+ state.UpdateMembers(msg)
case *packet.FrequenciesInfo:
- var network *packet.FullNetwork
- for i, fullNetwork := range state.State.Networks {
- if fullNetwork.ID == msg.Network {
- network = &state.State.Networks[i]
- }
- }
-
- frequencies := network.Frequencies
- for _, newFrequency := range msg.Frequencies {
- add := true
- for i, existingFrequency := range frequencies {
- if existingFrequency.ID == newFrequency.ID {
- add = false
- if newFrequency.Position == -1 {
- newFrequency.Position = existingFrequency.Position
- }
- frequencies[i] = newFrequency
- break
- }
- }
- if add {
- frequencies = append(frequencies, newFrequency)
- }
- }
-
- frequencies = slices.DeleteFunc(frequencies, func(frequency data.Frequency) bool {
- return slices.Contains(msg.RemovedFrequencies, frequency.ID)
- })
- slices.SortFunc(frequencies, func(a, b data.Frequency) int {
- return int(a.Position - b.Position)
- })
- log.Println(frequencies)
- network.Frequencies = frequencies
+ state.UpdateFrequencies(msg)
case *packet.MessagesInfo:
- for _, id := range msg.RemovedMessages {
- for _, btree := range state.State.Messages {
- btree.Delete(data.Message{ID: id})
- }
- }
-
- for _, message := range msg.Messages {
- msgSource := message.FrequencyID
- if msgSource == nil {
- msgSource = message.ReceiverID
- }
- bt := state.State.Messages[*msgSource]
- if bt == nil {
- bt = btree.NewG(2, func(a, b data.Message) bool {
- return a.ID < b.ID
- })
- state.State.Messages[*msgSource] = bt
- }
- bt.ReplaceOrInsert(message)
-
- }
+ state.UpdateMessages(msg)
case tea.KeyMsg:
switch msg.String() {
@@ -317,9 +205,11 @@ func (m *Model) updateConnected(msg tea.Msg) tea.Cmd {
case FocusFrequencyList:
if m.frequencyCreationPopup == nil {
index := m.networkList.Index()
- network := state.State.Networks[index]
- popup := frequencycreation.New(network.ID)
- m.frequencyCreationPopup = &popup
+ networkId := state.NetworkId(index)
+ if networkId != nil {
+ popup := frequencycreation.New(*networkId)
+ m.frequencyCreationPopup = &popup
+ }
}
}
diff --git a/internal/client/ui/core/frequencylist/frequencylist.go b/internal/client/ui/core/frequencylist/frequencylist.go
index 80d350b..8cef2be 100644
--- a/internal/client/ui/core/frequencylist/frequencylist.go
+++ b/internal/client/ui/core/frequencylist/frequencylist.go
@@ -9,6 +9,7 @@ import (
"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/data"
"github.com/kyren223/eko/internal/packet"
)
@@ -47,7 +48,7 @@ func (m Model) Init() tea.Cmd {
}
func (m Model) View() string {
- if m.Network() == nil {
+ if state.NetworkId(m.networkIndex) == nil {
return ""
}
@@ -62,7 +63,7 @@ func (m Model) View() string {
builder.WriteString(nameStyle.Render(m.Network().Name))
builder.WriteString("\n")
- for i, frequency := range m.Network().Frequencies {
+ for i, frequency := range m.Frequencies() {
frequencyStyle := frequencyStyle.Foreground(lipgloss.Color(frequency.HexColor))
if m.index == i {
frequencyStyle = frequencyStyle.Background(colors.BackgroundHighlight)
@@ -120,13 +121,13 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
m.index = min(m.FrequenciesLength()-1, m.index+1)
case "x":
- frequenciesCount := len(m.Network().Frequencies)
+ frequenciesCount := len(m.Frequencies())
if frequenciesCount == 1 {
// Don't delete the last frequency!
return m, nil
}
// TODO: consider adding a confirmation popup
- frequencyId := m.Network().Frequencies[m.index].ID
+ frequencyId := m.Frequencies()[m.index].ID
if m.index == frequenciesCount-1 {
m.index--
}
@@ -154,15 +155,15 @@ func (m Model) Swap(dir int) (Model, tea.Cmd) {
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
+ tmp := m.Frequencies()[m.index]
+ m.Frequencies()[m.index] = m.Frequencies()[m.index+dir]
+ m.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
+ tmp := m.Frequencies()[m.index]
+ m.Frequencies()[m.index] = m.Frequencies()[m.index+dir]
+ m.Frequencies()[m.index+dir] = tmp
})
return m, cmd
}
@@ -172,11 +173,12 @@ func (m *Model) SetNetworkIndex(networkIndex int) {
return
}
- if 0 <= m.networkIndex && m.networkIndex < len(state.State.Networks) {
- network := state.State.Networks[m.networkIndex]
- if 0 <= m.index && m.index < len(network.Frequencies) {
- frequencyId := network.Frequencies[m.index].ID
- state.State.LastFrequency[network.ID] = frequencyId
+ networkId := state.NetworkId(m.networkIndex)
+ if networkId != nil {
+ frequencies := state.State.Frequencies[*networkId]
+ if 0 <= m.index && m.index < len(frequencies) {
+ frequencyId := frequencies[m.index].ID
+ state.State.LastFrequency[*networkId] = frequencyId
}
}
@@ -190,26 +192,46 @@ func (m *Model) SetNetworkIndex(networkIndex int) {
m.index = 0
// Try restoring last ID
- network := state.State.Networks[m.networkIndex]
- if id, ok := state.State.LastFrequency[network.ID]; ok {
- for i, frequency := range network.Frequencies {
- if frequency.ID == id {
- m.index = i
- break
- }
+ networkId = state.NetworkId(m.networkIndex)
+ if networkId == nil {
+ return
+ }
+ id, ok := state.State.LastFrequency[*networkId]
+ if !ok {
+ return
+ }
+ frequencies := state.State.Frequencies[*networkId]
+ for i, frequency := range frequencies {
+ if frequency.ID == id {
+ m.index = i
+ break
}
}
}
func (m Model) FrequenciesLength() int {
- return len(m.Network().Frequencies)
+ networkId := state.NetworkId(m.networkIndex)
+ if networkId == nil {
+ return 0
+ }
+ return len(state.State.Frequencies[*networkId])
+}
+
+func (m Model) Network() *data.Network {
+ networkId := state.NetworkId(m.networkIndex)
+ if networkId == nil {
+ return nil
+ }
+ network := state.State.Networks[*networkId]
+ return &network
}
-func (m Model) Network() *packet.FullNetwork {
- if m.networkIndex < 0 || m.networkIndex > len(state.State.Networks)-1 {
+func (m Model) Frequencies() []data.Frequency {
+ networkId := state.NetworkId(m.networkIndex)
+ if networkId == nil {
return nil
}
- return &state.State.Networks[m.networkIndex]
+ return state.State.Frequencies[*networkId]
}
func (m *Model) Index() int {
diff --git a/internal/client/ui/core/networklist/networklist.go b/internal/client/ui/core/networklist/networklist.go
index 23350a3..597a391 100644
--- a/internal/client/ui/core/networklist/networklist.go
+++ b/internal/client/ui/core/networklist/networklist.go
@@ -1,7 +1,6 @@
package networklist
import (
- "slices"
"strings"
tea "github.com/charmbracelet/bubbletea"
@@ -48,18 +47,17 @@ func IconStyle(icon string, fg, bg lipgloss.Color) lipgloss.Style {
return lipgloss.NewStyle().SetString(combined)
}
-const TrustedIndex = -1
+const PeersIndex = -1
type Model struct {
- history []func(m *Model)
- index int
- focus bool
+ index int
+ focus bool
}
func New() Model {
return Model{
focus: false,
- index: TrustedIndex,
+ index: PeersIndex,
}
}
@@ -70,7 +68,7 @@ func (m Model) Init() tea.Cmd {
func (m Model) View() string {
var builder strings.Builder
builder.WriteString("\n")
- if m.index == TrustedIndex {
+ if m.index == PeersIndex {
builder.WriteString(trustedUsersButtonSelected)
} else {
builder.WriteString(trustedUsersButton)
@@ -81,7 +79,7 @@ func (m Model) View() string {
lipgloss.Color(network.FgHexColor),
lipgloss.Color(network.BgHexColor),
)
- if m.index == i {
+ if *state.NetworkId(m.index) == i {
builder.WriteString(lipgloss.JoinHorizontal(
ui.Center,
selectedIndicator,
@@ -106,18 +104,6 @@ func (m Model) View() string {
func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
switch msg := msg.(type) {
- case *packet.SwapUserNetworks:
- // 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.PacketSwapUserNetworks {
- // Server failed, revert!
- undo := m.history[len(m.history)-1]
- m.history = m.history[:len(m.history)-1]
- undo(&m)
- }
-
case tea.KeyMsg:
if !m.focus {
return m, nil
@@ -139,20 +125,14 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
m.index = min(len(state.State.Networks)-1, m.index+1)
case "Q":
- if state.State.UserID == nil || m.index == TrustedIndex {
+ if state.State.UserID == nil || m.index == PeersIndex {
return m, nil
}
- networks := state.State.Networks
- network := networks[m.index]
-
- // Remove network from the list so it's not visible
- state.State.Networks = slices.Delete(networks, m.index, m.index+1)
-
- // Set back to trusted bcz that's always valid
+ // Set back to peers icon bcz that's always valid
// Where if u were on the network u just left
// it'd be an issue (or if u left all networks)
- m.index = TrustedIndex
+ m.index = PeersIndex
no := false
return m, gateway.Send(&packet.SetMember{
@@ -161,28 +141,22 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
Muted: nil,
Banned: nil,
BanReason: nil,
- Network: network.ID,
+ Network: *state.NetworkId(m.index),
User: *state.State.UserID,
})
case "D":
- if state.State.UserID == nil || m.index == TrustedIndex {
+ if state.State.UserID == nil || m.index == PeersIndex {
return m, nil
}
- networks := state.State.Networks
- network := networks[m.index]
-
- // Remove network from the list so it's not visible
- state.State.Networks = slices.Delete(networks, m.index, m.index+1)
-
- // Set back to trusted bcz that's always valid
+ // Set back to peers icon bcz that's always valid
// Where if u were on the network u just left
// it'd be an issue (or if u left all networks)
- m.index = TrustedIndex
+ m.index = PeersIndex
return m, gateway.Send(&packet.DeleteNetwork{
- Network: network.ID,
+ Network: *state.NetworkId(m.index),
})
}
@@ -199,21 +173,13 @@ func (m *Model) Blur() {
}
func (m Model) Swap(dir int) (Model, tea.Cmd) {
- cmd := gateway.Send(&packet.SwapUserNetworks{
- Pos1: m.index,
- Pos2: m.index + dir,
- })
- tmp := state.State.Networks[m.index]
- state.State.Networks[m.index] = state.State.Networks[m.index+dir]
- state.State.Networks[m.index+dir] = tmp
+ tmp := state.Data.Networks[m.index]
+ state.Data.Networks[m.index] = state.Data.Networks[m.index+dir]
+ state.Data.Networks[m.index+dir] = tmp
m.index += dir
- m.history = append(m.history, func(m *Model) {
- m.index -= dir
- tmp := state.State.Networks[m.index]
- state.State.Networks[m.index] = state.State.Networks[m.index+dir]
- state.State.Networks[m.index+dir] = tmp
+ return m, gateway.Send(&packet.SetUserData{
+ Data: state.JsonUserData(),
})
- return m, cmd
}
func (m Model) Index() int {
diff --git a/internal/client/ui/core/state/state.go b/internal/client/ui/core/state/state.go
index 1041d23..db5ab6a 100644
--- a/internal/client/ui/core/state/state.go
+++ b/internal/client/ui/core/state/state.go
@@ -1,13 +1,17 @@
package state
import (
+ "encoding/json"
+ "slices"
+
"github.com/google/btree"
"github.com/kyren223/eko/internal/data"
"github.com/kyren223/eko/internal/packet"
+ "github.com/kyren223/eko/pkg/assert"
"github.com/kyren223/eko/pkg/snowflake"
)
-type Frequency struct {
+type FrequencyState struct {
IncompleteMessage string
Offset int
MaxHeight int
@@ -17,17 +21,166 @@ type state struct {
UserID *snowflake.ID
// Key is either a frequency or receiver
- FrequencyState map[snowflake.ID]Frequency
- LastFrequency map[snowflake.ID]snowflake.ID // key is network
+ FrequencyState map[snowflake.ID]FrequencyState // key is frequency id
+ LastFrequency map[snowflake.ID]snowflake.ID // key is network id
- Messages map[snowflake.ID]*btree.BTreeG[data.Message]
- Networks []packet.FullNetwork
+ Messages map[snowflake.ID]*btree.BTreeG[data.Message] // key is frequency id or receiver id
+ Networks map[snowflake.ID]data.Network // key is network id
+ Frequencies map[snowflake.ID][]data.Frequency // key is network id
+ Members map[snowflake.ID]map[snowflake.ID]data.Member // key is network id then user id
+ Users map[snowflake.ID]data.User // key is user id
}
var State state = state{
UserID: nil,
- FrequencyState: map[snowflake.ID]Frequency{},
+ FrequencyState: map[snowflake.ID]FrequencyState{},
LastFrequency: map[snowflake.ID]snowflake.ID{},
Messages: map[snowflake.ID]*btree.BTreeG[data.Message]{},
- Networks: []packet.FullNetwork{},
+ Networks: map[snowflake.ID]data.Network{},
+ Frequencies: map[snowflake.ID][]data.Frequency{},
+ Members: map[snowflake.ID]map[snowflake.ID]data.Member{},
+ Users: map[snowflake.ID]data.User{},
+}
+
+type UserData struct {
+ Networks []snowflake.ID
+}
+
+var Data UserData = UserData{
+ Networks: []snowflake.ID{},
+}
+
+func UpdateNetworks(info *packet.NetworksInfo) {
+ networks := State.Networks
+
+ for _, removedNetworkId := range info.RemovedNetworks {
+ delete(networks, removedNetworkId)
+ delete(State.Frequencies, removedNetworkId)
+ delete(State.Members, removedNetworkId)
+
+ for i, network := range Data.Networks {
+ if network == removedNetworkId {
+ copy(Data.Networks[i:], Data.Networks[i+1:])
+ Data.Networks = Data.Networks[:len(Data.Networks)-1]
+ break
+ }
+ }
+ }
+
+ for _, network := range info.Networks {
+ if _, ok := networks[network.ID]; !ok {
+ Data.Networks = append(Data.Networks, network.ID)
+ }
+
+ networks[network.ID] = network.Network
+ State.Frequencies[network.ID] = network.Frequencies
+ for _, member := range network.Members {
+ State.Members[network.ID][member.UserID] = member
+ }
+
+ for _, user := range network.Users {
+ State.Users[user.ID] = user
+ }
+ }
+}
+
+func UpdateFrequencies(info *packet.FrequenciesInfo) {
+ // TODO: check this
+ frequencies := State.Frequencies[info.Network]
+ for _, newFrequency := range info.Frequencies {
+ add := true
+ for i, existingFrequency := range frequencies {
+ if existingFrequency.ID == newFrequency.ID {
+ add = false
+ if newFrequency.Position == -1 {
+ newFrequency.Position = existingFrequency.Position
+ }
+ frequencies[i] = newFrequency
+ break
+ }
+ }
+ if add {
+ frequencies = append(frequencies, newFrequency)
+ }
+ }
+
+ frequencies = slices.DeleteFunc(frequencies, func(frequency data.Frequency) bool {
+ return slices.Contains(info.RemovedFrequencies, frequency.ID)
+ })
+ slices.SortFunc(frequencies, func(a, b data.Frequency) int {
+ return int(a.Position - b.Position)
+ })
+}
+
+func UpdateMessages(info *packet.MessagesInfo) {
+ for _, id := range info.RemovedMessages {
+ for _, btree := range State.Messages {
+ btree.Delete(data.Message{ID: id})
+ }
+ }
+
+ for _, message := range info.Messages {
+ msgSource := message.FrequencyID
+ if msgSource == nil {
+ msgSource = message.ReceiverID
+ }
+ bt := State.Messages[*msgSource]
+ if bt == nil {
+ bt = btree.NewG(2, func(a, b data.Message) bool {
+ return a.ID < b.ID
+ })
+ State.Messages[*msgSource] = bt
+ }
+ bt.ReplaceOrInsert(message)
+ }
+}
+
+func UpdateMembers(info *packet.MembersInfo) {
+ members := State.Members[info.Network]
+ for _, member := range info.Members {
+ members[member.UserID] = member
+ }
+ for _, removedMember := range info.RemovedMembers {
+ delete(members, removedMember)
+
+ if removedMember != *State.UserID {
+ continue
+ }
+ delete(State.Networks, info.Network)
+ delete(State.Frequencies, info.Network)
+ delete(State.Members, info.Network)
+
+ for i, network := range Data.Networks {
+ if network == info.Network {
+ copy(Data.Networks[i:], Data.Networks[i+1:])
+ Data.Networks = Data.Networks[:len(Data.Networks)-1]
+ break
+ }
+ }
+ }
+ for _, user := range info.Users {
+ State.Users[user.ID] = user
+ }
+}
+
+func NetworkId(index int) *snowflake.ID {
+ if 0 <= index && index < len(Data.Networks) {
+ return &Data.Networks[index]
+ }
+ return nil
+}
+
+func JsonUserData() string {
+ bytes, err := json.Marshal(Data)
+ assert.NoError(err, "marshling should never fail")
+ return string(bytes)
+}
+
+func FromJsonUserDat(s string) {
+ var data UserData
+ err := json.Unmarshal([]byte(s), &data)
+ if err != nil {
+ return
+ }
+ Data = data
}