Skip to content

Commit

Permalink
brclient: sort posts by most recent activity
Browse files Browse the repository at this point in the history
  • Loading branch information
miki authored and miki-totefu committed May 17, 2023
1 parent 0da5271 commit 326e95c
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 26 deletions.
57 changes: 47 additions & 10 deletions brclient/appstate.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,13 @@ type appState struct {
canPayServer bool
canPayServerTestTime time.Time

postsMtx sync.Mutex
posts []clientdb.PostSummary
post *rpc.PostMetadata
postSumm clientdb.PostSummary
myComments []string // Unreplicated comments
postStatus []rpc.PostMetadataStatus
postsMtx sync.Mutex
posts []clientdb.PostSummary
post *rpc.PostMetadata
postSumm clientdb.PostSummary
myComments []string // Unreplicated comments
postStatus []rpc.PostMetadataStatus
unreadPosts map[clientintf.PostID]struct{}

contentMtx sync.Mutex
remoteFiles map[clientintf.UserID]map[clientdb.FileID]clientdb.RemoteFile
Expand Down Expand Up @@ -233,6 +234,12 @@ type appStateErr struct {
func (as *appState) run() error {
as.wg.Add(1)
var err error

go func() {
// Initial loading of posts.
as.loadPosts()
}()

go func() {
as.log.Infof("Starting %s version %s", appName, version.String())
err = as.c.Run(as.ctx)
Expand Down Expand Up @@ -1867,14 +1874,14 @@ func (as *appState) requestRecv(amount, server, key string, caCert []byte) error
}

func (as *appState) createPost(post string) {
as.loadPosts()
summ, err := as.c.CreatePost(post, "")
if err != nil {
as.cwHelpMsg("Unable to create post: %v", err)
} else {
as.cwHelpMsg("Created post %s", summ.ID)
as.postsMtx.Lock()
as.posts = append(as.posts, summ)
as.sortPosts()
as.postsMtx.Unlock()
as.sendMsg(summ)
}
Expand All @@ -1887,15 +1894,17 @@ func (as *appState) loadPosts() {
} else {
as.postsMtx.Lock()
as.posts = posts
as.sortPosts()
as.postsMtx.Unlock()
}
}

func (as *appState) allPosts() []clientdb.PostSummary {
func (as *appState) allPosts() ([]clientdb.PostSummary, map[clientintf.PostID]struct{}) {
as.postsMtx.Lock()
res := as.posts
m := maps.Clone(as.unreadPosts)
as.postsMtx.Unlock()
return res
return res, m
}

func (as *appState) activePost() (rpc.PostMetadata, clientdb.PostSummary,
Expand All @@ -1905,6 +1914,7 @@ func (as *appState) activePost() (rpc.PostMetadata, clientdb.PostSummary,
as.postsMtx.Lock()
if as.post != nil {
res = *as.post
delete(as.unreadPosts, as.postSumm.ID)
}
summ := as.postSumm
status := as.postStatus
Expand All @@ -1929,6 +1939,7 @@ func (as *appState) activatePost(summ *clientdb.PostSummary) {
as.post = &post
as.postSumm = *summ
as.postStatus = postStatus
delete(as.unreadPosts, summ.ID)
as.postsMtx.Unlock()
}

Expand All @@ -1937,6 +1948,7 @@ func (as *appState) commentPost(from clientintf.UserID, pid clientintf.PostID,

as.postsMtx.Lock()
as.myComments = append(as.myComments, comment)
as.sortPosts()
as.postsMtx.Unlock()
as.sendMsg(sentPostComment{})

Expand All @@ -1946,6 +1958,22 @@ func (as *appState) commentPost(from clientintf.UserID, pid clientintf.PostID,
}
}

// sortPosts sorts the posts in as.posts. MUST be called with the postsMtx
// locked.
func (as *appState) sortPosts() {
sort.Slice(as.posts, func(i, j int) bool {
idt := as.posts[i].LastStatusTS
if idt.IsZero() {
idt = as.posts[i].Date
}
jdt := as.posts[j].LastStatusTS
if jdt.IsZero() {
jdt = as.posts[j].Date
}
return jdt.Before(idt)
})
}

func (as *appState) getUserPost(cw *chatWindow, pid clientintf.PostID) {
cw.newInternalMsg(fmt.Sprintf("Fetching post %s", pid))
as.repaintIfActive(cw)
Expand Down Expand Up @@ -2573,7 +2601,11 @@ func newAppState(sendMsg func(tea.Msg), lndLogLines *sloglinesbuffer.Buffer,
summ.Title, summ.ID, nick)

// Store new post.
as.loadPosts()
as.postsMtx.Lock()
as.posts = append(as.posts, summ)
as.sortPosts()
as.unreadPosts[summ.ID] = struct{}{}
as.postsMtx.Unlock()

// Signal updated feed window.
as.chatWindowsMtx.Lock()
Expand Down Expand Up @@ -2627,6 +2659,9 @@ func newAppState(sendMsg func(tea.Msg), lndLogLines *sloglinesbuffer.Buffer,
as.postStatus = append(as.postStatus, status)
}

as.unreadPosts[pid] = struct{}{}
as.sortPosts()

as.postsMtx.Unlock()

if statusFrom != as.c.PublicID() {
Expand Down Expand Up @@ -3552,6 +3587,8 @@ func newAppState(sendMsg func(tea.Msg), lndLogLines *sloglinesbuffer.Buffer,

collator: collate.New(language.Und),

unreadPosts: make(map[clientintf.PostID]struct{}),

missingKXUsers: make(map[client.UserID]time.Time),

inboundMsgs: &genericlist.List[inboundRemoteMsg]{},
Expand Down
16 changes: 16 additions & 0 deletions brclient/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -3379,6 +3379,22 @@ var commands = []tuicmd{
return nil
},
handler: subcmdNeededHandler,
}, {
cmd: "testcolor",
usableOffline: true,
descr: "Test a color spec",
usage: "<attr>:<fg>:<bg>",
handler: func(args []string, as *appState) error {
if len(args) < 1 {
return usageError{msg: "color <attr>:<fg>:<bg> must be specified"}
}
style, err := colorDefnToLGStyle(args[0])
if err != nil {
return err
}
as.diagMsg(style.Render("On sangen hauskaa, että polkupyörä on maanteiden jokapäiväinen ilmiö."))
return nil
},
}, {
cmd: "quit",
usableOffline: true,
Expand Down
30 changes: 18 additions & 12 deletions brclient/feedwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"fmt"
"sort"
"strings"

"github.com/charmbracelet/bubbles/viewport"
Expand All @@ -16,9 +15,10 @@ import (
// feedWindow tracks what needs to be initialized before the app can
// properly start.
type feedWindow struct {
as *appState
posts []clientdb.PostSummary
idx int
as *appState
posts []clientdb.PostSummary
unread map[clientintf.PostID]struct{}
idx int

viewport viewport.Model
}
Expand Down Expand Up @@ -56,6 +56,8 @@ func (fw *feedWindow) renderPostSumm(post clientdb.PostSummary,

if fw.idx == i {
b.WriteString(st.focused.Render(pf("%s %s by %s", date, title, author)))
} else if _, ok := fw.unread[post.ID]; ok {
b.WriteString(st.unreadPost.Render(pf("%s %s by %s", date, title, author)))
} else {
b.WriteString(st.timestamp.Render(date))
b.WriteString(" ")
Expand Down Expand Up @@ -83,13 +85,17 @@ func (fw *feedWindow) renderPostSumm(post clientdb.PostSummary,
}

func (fw *feedWindow) listPosts() {
fw.posts = fw.as.allPosts()
sort.Slice(fw.posts, func(i, j int) bool {
return fw.posts[i].Date.Sub(fw.posts[j].Date) < 0
})
fw.idx = len(fw.posts) - 1
if fw.idx < 0 {
fw.idx = 0
fw.posts, fw.unread = fw.as.allPosts()
_, summ, _, _ := fw.as.activePost()
if fw.idx == -1 {
idx := 0
for i := range fw.posts {
if fw.posts[i].ID == summ.ID {
idx = i
break
}
}
fw.idx = idx
}
}

Expand Down Expand Up @@ -213,7 +219,7 @@ func (fw feedWindow) View() string {
func newFeedWindow(as *appState, feedActiveIdx, yOffsetHint int) (feedWindow, tea.Cmd) {
as.loadPosts()
as.markWindowSeen(activeCWFeed)
fw := feedWindow{as: as}
fw := feedWindow{as: as, idx: -1}
fw.listPosts()
if feedActiveIdx > -1 && feedActiveIdx < len(fw.posts) {
fw.idx = feedActiveIdx
Expand Down
17 changes: 13 additions & 4 deletions brclient/theme.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type theme struct {
nick lipgloss.Style
nickMe lipgloss.Style
nickGC lipgloss.Style
unreadPost lipgloss.Style
msg lipgloss.Style
unsent lipgloss.Style
online lipgloss.Style
Expand All @@ -37,6 +38,10 @@ type theme struct {

func textToColor(in string) (lipgloss.Color, error) {
var c lipgloss.Color
if len(in) > 0 && in[0] == '#' {
return lipgloss.Color(in), nil
}

switch strings.ToLower(in) {
case "na":
case "black":
Expand Down Expand Up @@ -80,22 +85,24 @@ func colorDefnToLGStyle(color string) (lipgloss.Style, error) {
style = style.Underline(true)
case "reverse":
style = style.Reverse(true)
case "", "na":
default:
return style, fmt.Errorf("invalid attribute: %v", k)
}
}

fg, err := textToColor(s[1])
if err != nil {
return style, err
// return style, err
return style, fmt.Errorf("invalid foreground color: %v", err)
}
style.Foreground(fg)
style = style.Foreground(fg)

bg, err := textToColor(s[2])
if err != nil {
return style, err
return style, fmt.Errorf("invalid background color: %v", err)
}
style.Background(bg)
style = style.Background(bg)

return style, nil
}
Expand Down Expand Up @@ -158,6 +165,8 @@ func newTheme(args *config) (*theme, error) {
timestampHelp: lipgloss.NewStyle().
Bold(false).
Foreground(lipgloss.Color("#6b6b6b")),
unreadPost: lipgloss.NewStyle().
Foreground(lipgloss.Color("6")),

/*
nick: lipgloss.NewStyle().
Expand Down

0 comments on commit 326e95c

Please sign in to comment.