diff --git a/internal/client/ui/core/core.go b/internal/client/ui/core/core.go index 1ba0069..36c2b0f 100644 --- a/internal/client/ui/core/core.go +++ b/internal/client/ui/core/core.go @@ -551,6 +551,8 @@ func (m *Model) updateConnected(msg tea.Msg) tea.Cmd { return cmd } + calculateNotifications() + var cmds []tea.Cmd var cmd tea.Cmd @@ -687,3 +689,53 @@ func (m *Model) HasPopup() bool { m.banViewPopup != nil || m.peerAddPopup != nil } + +func calculateNotifications() { + for networkId := range state.State.Networks { + for _, frequency := range state.State.Frequencies[networkId] { + pings, hasNotif := getFrequencyNotification(networkId, frequency.ID) + if hasNotif { + state.State.Notifications[frequency.ID] = pings + } else { + delete(state.State.Notifications, frequency.ID) + } + } + } +} + +func getFrequencyNotification(networkId, 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 + + 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/frequencylist/frequencylist.go b/internal/client/ui/core/frequencylist/frequencylist.go index 537be56..2d2bec2 100644 --- a/internal/client/ui/core/frequencylist/frequencylist.go +++ b/internal/client/ui/core/frequencylist/frequencylist.go @@ -14,7 +14,6 @@ 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 ( @@ -93,11 +92,12 @@ func (m Model) View() string { var builder strings.Builder builder.WriteString(m.renderNetworkName()) - builder.WriteString("\n") + frequencies := m.Frequencies() upper := min(m.base+m.height, len(frequencies)) frequencies = frequencies[m.base:upper] + for i, frequency := range frequencies { maxFrequencyWidth := maxFrequencyWidth @@ -121,7 +121,7 @@ func (m Model) View() string { notif := "" notifStyle := notifStyle - pings, hasNotif := m.getNotifCount(frequency.ID) + pings, hasNotif := state.State.Notifications[frequency.ID] if pings == 0 && hasNotif { notif = notifSymbol[0] // notifStyle = notifStyleDot @@ -360,41 +360,3 @@ 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/networklist/networklist.go b/internal/client/ui/core/networklist/networklist.go index f4463fd..913eece 100644 --- a/internal/client/ui/core/networklist/networklist.go +++ b/internal/client/ui/core/networklist/networklist.go @@ -17,6 +17,7 @@ var ( Border(lipgloss.ThickBorder(), false, true, false, false) selectedIndicator = "šŸ­€\nā–Œ\nšŸ­›" + notification = " \nā——\n " //  ī­° 🭬 peersIcon = ui.IconStyle("ī· ", colors.Turquoise, colors.DarkerCyan, colors.BackgroundDimmer) peersButton = peersIcon.Background(colors.BackgroundDimmer).Padding(0, 1, 1).String() peersButtonSelected = lipgloss.JoinHorizontal( @@ -66,17 +67,41 @@ func (m Model) View() string { for i, networkId := range networks { network := state.State.Networks[networkId] - icon := ui.IconStyleNotif(network.Icon, - lipgloss.Color(network.FgHexColor), - lipgloss.Color(network.BgHexColor), - colors.BackgroundDimmer, 1, - ) + pings, ok := 0, false + frequencies := state.State.Frequencies[networkId] + for _, frequency := range frequencies { + fpings, fok := state.State.Notifications[frequency.ID] + pings += fpings + ok = ok || fok + } + + var icon lipgloss.Style + if ok && pings != 0 { + icon = ui.IconStyleNotif(network.Icon, + lipgloss.Color(network.FgHexColor), + lipgloss.Color(network.BgHexColor), + colors.BackgroundDimmer, pings, + ) + } else { + icon = ui.IconStyle(network.Icon, + lipgloss.Color(network.FgHexColor), + lipgloss.Color(network.BgHexColor), + colors.BackgroundDimmer, + ) + } + if m.index == m.base+i { builder.WriteString(lipgloss.JoinHorizontal( ui.Center, selectedIndicator, icon.Background(colors.BackgroundDimmer).Padding(0, 1, 1, 0).String(), )) + } else if ok { + builder.WriteString(lipgloss.JoinHorizontal( + ui.Center, + notification, + icon.Background(colors.BackgroundDimmer).Padding(0, 1, 1, 0).String(), + )) } else { builder.WriteString(icon.Background(colors.BackgroundDimmer).Padding(0, 1, 1).String()) } diff --git a/internal/client/ui/core/state/state.go b/internal/client/ui/core/state/state.go index efa4732..ee61a2c 100644 --- a/internal/client/ui/core/state/state.go +++ b/internal/client/ui/core/state/state.go @@ -29,6 +29,8 @@ type state struct { 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 Trusteds map[snowflake.ID]ed25519.PublicKey // key is user id + + Notifications map[snowflake.ID]int // key is frequency id or receiver id } var State state = state{ @@ -40,6 +42,7 @@ var State state = state{ Members: map[snowflake.ID]map[snowflake.ID]data.Member{}, Users: map[snowflake.ID]data.User{}, Trusteds: map[snowflake.ID]ed25519.PublicKey{}, + Notifications: map[snowflake.ID]int{}, } type UserData struct { diff --git a/internal/client/ui/ui.go b/internal/client/ui/ui.go index 1d07f40..08071d7 100644 --- a/internal/client/ui/ui.go +++ b/internal/client/ui/ui.go @@ -219,7 +219,6 @@ func clamp(v, lower, upper int) int { šŸ­šŸ¬½ šŸ­ˆšŸ­„ */ - func IconStyle(icon string, iconFg, iconBg, bg lipgloss.Color) lipgloss.Style { bgStyle := lipgloss.NewStyle().Background(iconBg).Foreground(bg) top := bgStyle.Render("🭠🭘 šŸ­£šŸ­•") @@ -237,7 +236,7 @@ var notifications = []string{ func IconStyleNotif(icon string, iconFg, iconBg, bg lipgloss.Color, count int) lipgloss.Style { notifStyle := lipgloss.NewStyle().Background(iconBg).Foreground(colors.Red) - notif := notifications[min(0, max(10, count)-1)] + notif := notifications[max(0, min(10, count)-1)] notif = notifStyle.Render(notif) bgStyle := lipgloss.NewStyle().Background(iconBg).Foreground(bg) @@ -249,4 +248,3 @@ func IconStyleNotif(icon string, iconFg, iconBg, bg lipgloss.Color, count int) l combined := lipgloss.JoinVertical(lipgloss.Left, top, middle, bottom) return lipgloss.NewStyle().SetString(combined) } -