From 9bf320340f2d22edbbccb68e136536ecff1b5ca8 Mon Sep 17 00:00:00 2001 From: Kyren223 Date: Sun, 26 Jan 2025 18:43:03 +0200 Subject: [PATCH] Implemented signal chat on the client side along with adding a user id in the user signals --- internal/client/ui/core/chat/chat.go | 63 ++++++++++++++++---- internal/client/ui/core/core.go | 32 +++++----- internal/client/ui/core/peerlist/peerlist.go | 15 ++++- internal/client/ui/core/state/state.go | 21 ++++--- 4 files changed, 90 insertions(+), 41 deletions(-) diff --git a/internal/client/ui/core/chat/chat.go b/internal/client/ui/core/chat/chat.go index c045c41..f59e56c 100644 --- a/internal/client/ui/core/chat/chat.go +++ b/internal/client/ui/core/chat/chat.go @@ -573,7 +573,7 @@ func (m *Model) sendMessage() tea.Cmd { var receiverId *snowflake.ID = nil if m.receiverIndex != -1 { - // TODO: do nothing for now, until trusted friends are implemented + receiverId = &state.Data.Peers[m.receiverIndex] } var frequencyId *snowflake.ID = nil @@ -590,15 +590,15 @@ func (m *Model) sendMessage() tea.Cmd { }) } -func (m *Model) SetReceiver(receiverIndex int) { +func (m *Model) SetReceiver(receiverIndex int) tea.Cmd { if m.receiverIndex == receiverIndex { - return + return nil } m.ResetBeforeSwitch() m.receiverIndex = receiverIndex m.frequencyIndex = -1 m.networkIndex = -1 - m.RestoreAfterSwitch() + return m.RestoreAfterSwitch() } func (m *Model) SetFrequency(networkIndex, frequencyIndex int) tea.Cmd { @@ -625,24 +625,30 @@ func (m *Model) ResetBeforeSwitch() { return } frequencyId := frequencies[m.frequencyIndex].ID - log.Println("Saving", frequencyId) - state.State.FrequencyState[frequencyId] = state.FrequencyState{ + log.Println("Saving frequency", frequencyId) + state.State.ChatState[frequencyId] = state.FrequencyState{ IncompleteMessage: m.vi.String(), Base: m.base, MaxHeight: m.maxMessagesHeight, } } else if m.receiverIndex != -1 { - // TODO: receiver + receiverId := state.Data.Peers[m.receiverIndex] + log.Println("Saving signal:", receiverId) + state.State.ChatState[receiverId] = state.FrequencyState{ + IncompleteMessage: m.vi.String(), + Base: m.base, + MaxHeight: m.maxMessagesHeight, + } } } func (m *Model) RestoreAfterSwitch() tea.Cmd { - msgs := state.State.FrequencyState + msgs := state.State.ChatState networkId := state.NetworkId(m.networkIndex) if m.frequencyIndex != -1 && networkId != nil { frequencies := state.State.Frequencies[*networkId] frequency := frequencies[m.frequencyIndex] - log.Println("Restoring", frequency.ID) + log.Println("Restoring frequency:", frequency.ID) if val, ok := msgs[frequency.ID]; ok { m.vi.SetString(val.IncompleteMessage) @@ -658,7 +664,23 @@ func (m *Model) RestoreAfterSwitch() tea.Cmd { FrequencyID: &frequency.ID, }) } else if m.receiverIndex != -1 { - // TODO: receiver + peers := state.Data.Peers + peer := peers[m.receiverIndex] + log.Println("Restoring signal:", peer) + + if val, ok := msgs[peer]; ok { + m.vi.SetString(val.IncompleteMessage) + m.base = val.Base + m.SetIndex(Unselected) + m.maxMessagesHeight = val.MaxHeight + + // Don't ask for messages if you already visited this frequency + return nil + } + return gateway.Send(&packet.RequestMessages{ + ReceiverID: &peer, + FrequencyID: nil, + }) } return nil @@ -735,7 +757,8 @@ func (m *Model) renderMessages(screenHeight int) string { frequencyId := frequencies[m.frequencyIndex].ID btree = state.State.Messages[frequencyId] } else { - // TODO: implement support for receiver id + receiverId := state.Data.Peers[m.receiverIndex] + btree = state.State.Messages[receiverId] } if !m.hasReadAccess { @@ -1012,7 +1035,23 @@ func (m *Model) renderHeader(message data.Message, selected bool) []byte { } } else if m.receiverIndex != -1 { - // TODO: receiver + user := state.State.Users[message.SenderID] + trustedPublicKey, isTrusted := state.State.Trusteds[user.ID] + keysMatch := bytes.Equal(trustedPublicKey, user.PublicKey) + + if isTrusted && !keysMatch { + buf = append(buf, ui.UntrustedSymbol...) + } + + var senderStyle lipgloss.Style + if isTrusted && keysMatch { + senderStyle = ui.TrustedUserStyle + } else { + senderStyle = ui.UserStyle + } + + sender := senderStyle.Render(user.Name) + buf = append(buf, sender...) } // Render header time format diff --git a/internal/client/ui/core/core.go b/internal/client/ui/core/core.go index 6e53fbe..4aa5d5d 100644 --- a/internal/client/ui/core/core.go +++ b/internal/client/ui/core/core.go @@ -340,22 +340,18 @@ func (m *Model) updateConnected(msg tea.Msg) tea.Cmd { return nil } case FocusLeftSidebar: - if !m.HasPopup() { - if m.networkList.Index() == networklist.PeersIndex { - // TODO: add n keybind for receiver - } else { - networkId := state.NetworkId(m.networkList.Index()) - if networkId == nil { - return nil - } - member := state.State.Members[*networkId][*state.UserID] - if !member.IsAdmin { - return nil - } - popup := frequencycreation.New(*networkId) - m.frequencyCreationPopup = &popup + if !m.HasPopup() && m.networkList.Index() != networklist.PeersIndex { + networkId := state.NetworkId(m.networkList.Index()) + if networkId == nil { return nil } + member := state.State.Members[*networkId][*state.UserID] + if !member.IsAdmin { + return nil + } + popup := frequencycreation.New(*networkId) + m.frequencyCreationPopup = &popup + return nil } } @@ -550,18 +546,22 @@ func (m *Model) updateConnected(msg tea.Msg) tea.Cmd { if m.networkList.Index() == networklist.PeersIndex { m.peerList, cmd = m.peerList.Update(msg) cmds = append(cmds, cmd) + + cmd = m.chat.SetReceiver(m.peerList.Index()) + cmds = append(cmds, cmd) } else { m.frequencyList.SetNetworkIndex(m.networkList.Index()) m.frequencyList, cmd = m.frequencyList.Update(msg) cmds = append(cmds, cmd) + + cmd = m.chat.SetFrequency(m.networkList.Index(), m.frequencyList.Index()) + cmds = append(cmds, cmd) } m.memberList.SetNetworkAndFrequency(m.networkList.Index(), m.frequencyList.Index()) m.memberList, cmd = m.memberList.Update(msg) cmds = append(cmds, cmd) - cmd = m.chat.SetFrequency(m.networkList.Index(), m.frequencyList.Index()) - cmds = append(cmds, cmd) m.chat, cmd = m.chat.Update(msg) cmds = append(cmds, cmd) diff --git a/internal/client/ui/core/peerlist/peerlist.go b/internal/client/ui/core/peerlist/peerlist.go index 477f791..f4ef377 100644 --- a/internal/client/ui/core/peerlist/peerlist.go +++ b/internal/client/ui/core/peerlist/peerlist.go @@ -3,6 +3,7 @@ package peerlist import ( "bytes" "slices" + "strconv" "strings" tea "github.com/charmbracelet/bubbletea" @@ -20,7 +21,10 @@ var ( Border(lipgloss.ThickBorder(), false, true, false, false) nameStyle = lipgloss.NewStyle(). - MarginBottom(1).Padding(1).Align(lipgloss.Center). + Padding(1).Align(lipgloss.Center). + Border(lipgloss.ThickBorder(), false, false, true) + userIdStyle = lipgloss.NewStyle(). + MarginBottom(1).Padding(1, 2).Align(lipgloss.Center). Border(lipgloss.ThickBorder(), false, false, true) margin = 2 @@ -208,7 +212,14 @@ func (m Model) renderHeader() string { } peersName := nameStyle.Render("User Signals") - return lipgloss.JoinVertical(0, peersName) + userIdStyle := userIdStyle.Width(m.width) + if m.focus { + userIdStyle = userIdStyle.BorderForeground(colors.Focus) + } + id := "Your User ID\n" + strconv.FormatInt(int64(*state.UserID), 10) + userId := userIdStyle.Render(id) + + return lipgloss.JoinVertical(0, peersName, userId) } func (m *Model) SetWidth(width int) { diff --git a/internal/client/ui/core/state/state.go b/internal/client/ui/core/state/state.go index c67fe04..2399f96 100644 --- a/internal/client/ui/core/state/state.go +++ b/internal/client/ui/core/state/state.go @@ -20,9 +20,8 @@ type FrequencyState struct { } type state struct { - // Key is either a frequency or receiver - FrequencyState map[snowflake.ID]FrequencyState // key is frequency id - LastFrequency map[snowflake.ID]snowflake.ID // key is network id + ChatState map[snowflake.ID]FrequencyState // key is frequency id or receiver id + LastFrequency map[snowflake.ID]snowflake.ID // key is network id 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 @@ -33,14 +32,14 @@ type state struct { } var State state = state{ - FrequencyState: map[snowflake.ID]FrequencyState{}, - LastFrequency: map[snowflake.ID]snowflake.ID{}, - Messages: map[snowflake.ID]*btree.BTreeG[data.Message]{}, - 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{}, - Trusteds: map[snowflake.ID]ed25519.PublicKey{}, + ChatState: map[snowflake.ID]FrequencyState{}, + LastFrequency: map[snowflake.ID]snowflake.ID{}, + Messages: map[snowflake.ID]*btree.BTreeG[data.Message]{}, + 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{}, + Trusteds: map[snowflake.ID]ed25519.PublicKey{}, } type UserData struct {