Implemented signal chat on the client side along with adding a user id

in the user signals
This commit is contained in:
2025-01-26 18:43:03 +02:00
parent 1d76c3f831
commit 9bf320340f
4 changed files with 90 additions and 41 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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) {

View File

@@ -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 {