summaryrefslogtreecommitdiff
path: root/internal/client
diff options
context:
space:
mode:
authorKyren223 <Kyren223@proton.me>2025-01-30 19:04:52 +0200
committerKyren223 <Kyren223@proton.me>2025-01-30 19:04:52 +0200
commit088baa6d3a63a7a6dea80afd07c48da99e2d19e8 (patch)
tree3709ce4eb93f25256bbedad220d0bc7e7f6348dd /internal/client
parenta0fb12ca9a8cf762f8eb94c8d3b688dbc776018c (diff)
Implemented frequency-level notifications and pings
Diffstat (limited to 'internal/client')
-rw-r--r--internal/client/ui/core/chat/chat.go90
-rw-r--r--internal/client/ui/core/frequencylist/frequencylist.go70
-rw-r--r--internal/client/ui/core/state/state.go4
3 files changed, 122 insertions, 42 deletions
diff --git a/internal/client/ui/core/chat/chat.go b/internal/client/ui/core/chat/chat.go
index ffdcd54..ceb8aeb 100644
--- a/internal/client/ui/core/chat/chat.go
+++ b/internal/client/ui/core/chat/chat.go
@@ -117,12 +117,12 @@ type Model struct {
receiverIndex int
frequencyIndex int
- base int
- index int
- selectedMessage *data.Message
- editingMessage *data.Message
- lastReadMessageId *snowflake.ID
- keepLastRead bool
+ base int
+ index int
+ selectedMessage *data.Message
+ editingMessage *data.Message
+ lastReadMsg *snowflake.ID
+ keepLastRead bool
messagesHeight int
maxMessagesHeight int
@@ -152,7 +152,7 @@ func New() Model {
index: Unselected,
selectedMessage: nil,
editingMessage: nil,
- lastReadMessageId: nil,
+ lastReadMsg: nil,
keepLastRead: false,
messagesHeight: 0,
maxMessagesHeight: -1,
@@ -206,15 +206,17 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
frequency := frequencies[m.frequencyIndex]
member := state.State.Members[*networkId][*state.UserID]
- if m.base == SnapToBottom {
- lastRead := state.GetLastReadMessage(frequency.ID)
- if lastRead != nil && m.lastReadMessageId != nil &&
- state.Data.LastReadMessage[frequency.ID] != nil &&
- *m.lastReadMessageId != *lastRead &&
- *m.lastReadMessageId != *state.Data.LastReadMessage[frequency.ID] {
+ lastMsg := state.GetLastReadMessage(frequency.ID)
+ if m.base != SnapToBottom {
+ m.keepLastRead = false
+ } else if lastMsg != nil {
+ lastReadMsg := state.Data.LastReadMessage[frequency.ID]
+ if m.keepLastRead && m.lastReadMsg != nil && lastReadMsg != nil &&
+ *lastReadMsg != *lastMsg && *lastReadMsg != *m.lastReadMsg {
m.keepLastRead = false
}
- m.lastReadMessageId = lastRead
+
+ state.Data.LastReadMessage[frequency.ID] = lastMsg
}
m.hasReadAccess = frequency.Perms != packet.PermNoAccess || member.IsAdmin
@@ -251,15 +253,17 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
} else if m.receiverIndex != -1 {
receiverId := state.Data.Peers[m.receiverIndex]
- if m.base == SnapToBottom {
- lastRead := state.GetLastReadMessage(receiverId)
- if lastRead != nil && m.lastReadMessageId != nil &&
- state.Data.LastReadMessage[receiverId] != nil &&
- *m.lastReadMessageId != *lastRead &&
- *m.lastReadMessageId != *state.Data.LastReadMessage[receiverId] {
- m.keepLastRead = false
- }
- m.lastReadMessageId = lastRead
+ lastMsg := state.GetLastReadMessage(receiverId)
+ if m.base == SnapToBottom && lastMsg != nil {
+ lastReadMsg := state.Data.LastReadMessage[receiverId]
+
+ // if m.lastReadMsg != nil && lastReadMsg != nil &&
+ // *lastReadMsg != *lastMsg &&
+ // *lastReadMsg != *m.lastReadMsg {
+ // m.keepLastRead = false
+ // }
+
+ *lastReadMsg = *lastMsg
}
}
@@ -694,7 +698,7 @@ func (m *Model) ResetBeforeSwitch() {
m.base = SnapToBottom
m.SetIndex(Unselected)
m.maxMessagesHeight = -1
- m.lastReadMessageId = nil
+ m.lastReadMsg = nil
}()
networkId := state.NetworkId(m.networkIndex)
@@ -711,10 +715,7 @@ func (m *Model) ResetBeforeSwitch() {
MaxHeight: m.maxMessagesHeight,
}
- if m.lastReadMessageId != nil {
- log.Println("Setting last msg ID")
- state.SetLastReadMessage(frequencyId, *m.lastReadMessageId)
- }
+ state.SendUserDatUpdate()
} else if m.receiverIndex != -1 {
receiverId := state.Data.Peers[m.receiverIndex]
@@ -725,9 +726,7 @@ func (m *Model) ResetBeforeSwitch() {
MaxHeight: m.maxMessagesHeight,
}
- if m.lastReadMessageId != nil {
- state.SetLastReadMessage(receiverId, *m.lastReadMessageId)
- }
+ state.SendUserDatUpdate()
}
}
@@ -739,8 +738,9 @@ func (m *Model) RestoreAfterSwitch() tea.Cmd {
frequency := frequencies[m.frequencyIndex]
log.Println("Restoring frequency:", frequency.ID)
- m.lastReadMessageId = state.Data.LastReadMessage[frequency.ID]
- if m.lastReadMessageId != nil {
+ m.lastReadMsg = state.Data.LastReadMessage[frequency.ID]
+ if m.lastReadMsg != nil {
+ log.Println("LAST READ MSG", m.lastReadMsg)
m.keepLastRead = true
}
@@ -761,8 +761,8 @@ func (m *Model) RestoreAfterSwitch() tea.Cmd {
receiverId := state.Data.Peers[m.receiverIndex]
log.Println("Restoring signal:", receiverId)
- m.lastReadMessageId = state.Data.LastReadMessage[receiverId]
- if m.lastReadMessageId != nil {
+ m.lastReadMsg = state.Data.LastReadMessage[receiverId]
+ if m.lastReadMsg != nil {
m.keepLastRead = true
}
@@ -881,18 +881,30 @@ func (m *Model) renderMessages(screenHeight int) string {
renderedGroups := []string{}
group := []data.Message{}
- lastReadId := m.lastReadMessageId
+ lastReadId := state.Data.LastReadMessage[*id]
if m.keepLastRead {
- lastReadId = state.Data.LastReadMessage[*id]
+ // assert.NotNil(m.lastReadMsg, "TODO: REMOVE THIS", "lastReadId", lastReadId, "m.lastReadMsg", m.lastReadMsg)
+ // assert.Assert(*m.lastReadMsg != *lastReadId, "TODO: REMOVE THIS", "lastReadId", lastReadId, "m.lastReadMsg", m.lastReadMsg)
+ if m.lastReadMsg != nil && lastReadId != nil && *m.lastReadMsg == *lastReadId {
+ log.Println("TODO: REMOVE THIS", "lastReadId", lastReadId, "m.lastReadMsg", m.lastReadMsg)
+ }
+ lastReadId = m.lastReadMsg
}
last := snowflake.ID(0)
btree.Descend(func(message data.Message) bool {
last = message.ID
- isLastRead := lastReadId != nil && *lastReadId == message.ID
+ // >= is needed so if the message was deleted
+ // Any prior messages will still be separated by "new"
+ isLastRead := lastReadId != nil && *lastReadId >= message.ID
if len(group) == 0 {
group = append(group, message)
+
+ if isLastRead {
+ lastReadId = nil
+ }
+
return true
}
@@ -921,6 +933,8 @@ func (m *Model) renderMessages(screenHeight int) string {
renderedGroups = append(renderedGroups, newSep+"\n")
remainingHeight--
+
+ lastReadId = nil // Stop the rest of the messages from having NEW
}
return remainingHeight > 0
diff --git a/internal/client/ui/core/frequencylist/frequencylist.go b/internal/client/ui/core/frequencylist/frequencylist.go
index 1c7fe22..537be56 100644
--- a/internal/client/ui/core/frequencylist/frequencylist.go
+++ b/internal/client/ui/core/frequencylist/frequencylist.go
@@ -14,6 +14,7 @@ import (
"github.com/kyren223/eko/internal/data"
"github.com/kyren223/eko/internal/packet"
"github.com/kyren223/eko/pkg/assert"
+ "github.com/kyren223/eko/pkg/snowflake"
)
var (
@@ -44,6 +45,13 @@ var (
ellipsis = "…"
BackgroundStyle = lipgloss.NewStyle().Background(colors.BackgroundDim)
+
+ notifSymbol = []string{
+ "  ", " 󰲠 ", " 󰲢 ", " 󰲤 ", " 󰲦 ", " 󰲨 ", " 󰲪 ", " 󰲬 ", " 󰲮 ", " 󰲰 ", " 󰲲 ",
+ }
+ notifStyleDot = lipgloss.NewStyle().Foreground(colors.White)
+ notifStyle = lipgloss.NewStyle().Foreground(colors.Red)
+ notifWidth = 3
)
type Model struct {
@@ -91,6 +99,8 @@ func (m Model) View() string {
upper := min(m.base+m.height, len(frequencies))
frequencies = frequencies[m.base:upper]
for i, frequency := range frequencies {
+ maxFrequencyWidth := maxFrequencyWidth
+
frequencyStyle := frequencyStyle.Foreground(lipgloss.Color(frequency.HexColor))
if m.index == m.base+i {
frequencyStyle = frequencyStyle.Background(colors.BackgroundHighlight)
@@ -109,6 +119,24 @@ func (m Model) View() string {
symbol = symbolNoAccessAdmin
}
+ notif := ""
+ notifStyle := notifStyle
+ pings, hasNotif := m.getNotifCount(frequency.ID)
+ if pings == 0 && hasNotif {
+ notif = notifSymbol[0]
+ // notifStyle = notifStyleDot
+ } else if hasNotif {
+ notif = notifSymbol[min(pings, 10)]
+ }
+
+ if m.index == m.base+i {
+ notifStyle = notifStyle.Background(colors.BackgroundHighlight)
+ }
+ if notif != "" {
+ maxFrequencyWidth -= notifWidth
+ notif = notifStyle.Render(notif)
+ }
+
frequencyName := ""
if lipgloss.Width(frequency.Name) <= maxFrequencyWidth {
frequencyName = lipgloss.NewStyle().
@@ -119,8 +147,10 @@ func (m Model) View() string {
MaxWidth(maxFrequencyWidth-1).
Render(frequency.Name) + ellipsis
}
+ frequencyName = lipgloss.NewStyle().Width(maxFrequencyWidth).
+ Render(frequencyName)
- frequency := frequencyStyle.Render(symbol + frequencyName)
+ frequency := frequencyStyle.Render(symbol + frequencyName + notif)
builder.WriteString(backgroundStyle.Render(frequency))
builder.WriteString("\n")
}
@@ -330,3 +360,41 @@ func (m Model) renderNetworkName() string {
func (m *Model) SetWidth(width int) {
m.width = width
}
+
+func (m *Model) getNotifCount(frequencyId snowflake.ID) (_ int, _ bool) {
+ lastReadMsg := state.Data.LastReadMessage[frequencyId]
+ if lastReadMsg == nil {
+ return 0, false
+ }
+
+ btree := state.State.Messages[frequencyId]
+ if btree == nil {
+ return 0, false
+ }
+
+ pings := 0
+ hasNotif := false
+
+ networkId := state.NetworkId(m.networkIndex)
+ isAdmin := state.State.Members[*networkId][*state.UserID].IsAdmin
+
+ btree.AscendGreaterOrEqual(data.Message{ID: *lastReadMsg + 1}, func(item data.Message) bool {
+ hasNotif = true
+
+ if item.Ping == nil {
+ return true
+ }
+
+ if *item.Ping == packet.PingEveryone {
+ pings++
+ } else if *item.Ping == packet.PingAdmins && isAdmin {
+ pings++
+ } else if *item.Ping == *state.UserID {
+ pings++
+ }
+
+ return pings <= 10
+ })
+
+ return pings, hasNotif
+}
diff --git a/internal/client/ui/core/state/state.go b/internal/client/ui/core/state/state.go
index 04d592e..efa4732 100644
--- a/internal/client/ui/core/state/state.go
+++ b/internal/client/ui/core/state/state.go
@@ -236,9 +236,7 @@ func GetLastReadMessage(id snowflake.ID) *snowflake.ID {
return &msg.ID
}
-func SetLastReadMessage(id snowflake.ID, message snowflake.ID) {
- Data.LastReadMessage[id] = &message
-
+func SendUserDatUpdate() {
data := JsonUserData()
gateway.SendAsync(&packet.SetUserData{
Data: &data,