Skip to content

Commit

Permalink
brclient: add unread msg marker to inactive screens
Browse files Browse the repository at this point in the history
  • Loading branch information
miki authored and miki-totefu committed Feb 14, 2023
1 parent 2fdd4f6 commit e03164f
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 1 deletion.
3 changes: 3 additions & 0 deletions brclient/appstate.go
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,7 @@ func (as *appState) changeActiveWindow(win int) {

if win != as.activeCW {
as.prevActiveCW = as.activeCW
as.sendMsg(msgActiveWindowChanged{})
}

// Remove from list of updated windows.
Expand Down Expand Up @@ -2150,6 +2151,7 @@ func newAppState(sendMsg func(tea.Msg), lndLogLines *sloglinesbuffer.Buffer,
cw := as.findOrNewChatWindow(user.ID(), fromNick)
s := as.handleRcvdText(msg.Message, fromNick)
cw.newRecvdMsg(fromNick, s, &cw.uid, ts)
as.sendMsg(msgNewRecvdMsg{})
as.repaintIfActiveWithMention(cw, hasMention(as.c.LocalNick(), s))
}))

Expand All @@ -2158,6 +2160,7 @@ func newAppState(sendMsg func(tea.Msg), lndLogLines *sloglinesbuffer.Buffer,
fromUID := user.ID()
s := as.handleRcvdText(msg.Message, cw.alias)
cw.newRecvdMsg(user.Nick(), s, &fromUID, ts)
as.sendMsg(msgNewRecvdMsg{})
as.repaintIfActiveWithMention(cw, hasMention(as.c.LocalNick(), s))
}))

Expand Down
29 changes: 28 additions & 1 deletion brclient/chatwindow.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"
"sync"
"time"
"unicode/utf8"

"github.com/companyzero/bisonrelay/client/clientintf"
"github.com/companyzero/bisonrelay/internal/strescape"
Expand Down Expand Up @@ -113,6 +114,7 @@ type chatWindow struct {
selEmbedArgs embeddedArgs
selEmbed int
maxEmbeds int
unreadIdx int
}

func (cw *chatWindow) empty() bool {
Expand All @@ -127,7 +129,12 @@ func (cw *chatWindow) appendMsg(msg *chatMsg) {
return
}
cw.Lock()
resetUnreadIdx := (msg.mine || msg.internal || msg.help) &&
cw.unreadIdx == len(cw.msgs)
cw.msgs = append(cw.msgs, msg)
if resetUnreadIdx {
cw.unreadIdx = len(cw.msgs)
}
cw.Unlock()
}

Expand Down Expand Up @@ -198,6 +205,19 @@ func (cw *chatWindow) setMsgSent(msg *chatMsg) {
cw.Unlock()
}

func (cw *chatWindow) markAllRead() {
cw.Lock()
cw.unreadIdx = len(cw.msgs)
cw.Unlock()
}

func (cw *chatWindow) unreadCount() int {
cw.Lock()
count := len(cw.msgs) - cw.unreadIdx
cw.Unlock()
return count
}

func (cw *chatWindow) renderPost(winW int, styles *theme, b *strings.Builder, msg *chatMsg) {
b.WriteString(styles.timestamp.Render(msg.ts.Format("15:04:05 ")))
b.WriteString("<")
Expand Down Expand Up @@ -332,7 +352,14 @@ func (cw *chatWindow) renderContent(winW int, styles *theme, as *appState) strin
// TODO: estimate total length to perform only a single alloc.
cw.maxEmbeds = 0
b := new(strings.Builder)
for _, msg := range cw.msgs {
for i, msg := range cw.msgs {
if i == cw.unreadIdx {
unreadMsg := []byte(" unread ――――――――")
l := utf8.RuneCount(unreadMsg)
b.WriteString(strings.Repeat("―", winW-l))
b.Write(unreadMsg)
b.WriteRune('\n')
}
if msg.post != nil {
cw.renderPost(winW, styles, b, msg)
continue
Expand Down
30 changes: 30 additions & 0 deletions brclient/mainwindow.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,20 @@ func (mws mainWindowState) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
msg.Alt = false
}

wasAtBottom := mws.viewport.AtBottom()

// send to viewport
mws.viewport, cmd = mws.viewport.Update(msg)
cmds = appendCmd(cmds, cmd)

if !wasAtBottom && mws.viewport.AtBottom() {
cw := mws.as.activeChatWindow()
if cw != nil {
cmds = appendCmd(cmds, markAllRead(cw))
mws.updateViewportContent()
}
}

case msg.Type == tea.KeyTab:
mws.updateCompletion()

Expand Down Expand Up @@ -383,6 +393,26 @@ func (mws mainWindowState) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
mws.recalcViewportSize()
mws.updateViewportContent()

case msgActiveWindowChanged:
cw := mws.as.activeChatWindow()
if cw != nil {
if cw.unreadCount() < mws.as.winH {
cmds = appendCmd(cmds, markAllRead(cw))
mws.updateViewportContent()
}
}

case msgNewRecvdMsg:
// Clear unread count from active chat if we're following at
// the bottom of the screen.
if mws.viewport.AtBottom() {
cw := mws.as.activeChatWindow()
if cw != nil {
cmds = appendCmd(cmds, markAllRead(cw))
mws.updateViewportContent()
}
}

case repaintActiveChat:
mws.updateViewportContent()

Expand Down
13 changes: 13 additions & 0 deletions brclient/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"crypto/tls"
"errors"
"time"

"github.com/atotto/clipboard"
tea "github.com/charmbracelet/bubbletea"
Expand Down Expand Up @@ -57,6 +58,8 @@ type msgConfirmedFunds dcrutil.Amount
type msgPaste string
type msgPasteErr error

type msgNewRecvdMsg struct{}

type msgCancelForm struct{}
type msgSubmitForm struct{}

Expand All @@ -66,6 +69,8 @@ type msgProcessEsc struct{}

type msgDownloadCompleted clientdb.FileID

type msgActiveWindowChanged struct{}

func paste() tea.Msg {
str, err := clipboard.ReadAll()
if err != nil {
Expand Down Expand Up @@ -213,3 +218,11 @@ func isEscMsg(msg tea.Msg) bool {
}
return keyMsg.String() == "esc"
}

func markAllRead(cw *chatWindow) tea.Cmd {
return func() tea.Msg {
time.Sleep(1500 * time.Millisecond)
cw.markAllRead()
return repaintActiveChat{}
}
}

0 comments on commit e03164f

Please sign in to comment.