Make notifications paginated

This commit is contained in:
Alessio 2024-11-01 23:23:03 -07:00
parent 90f453c207
commit b0cf2076e2
4 changed files with 73 additions and 9 deletions

View File

@ -2,10 +2,27 @@ package webserver
import (
"net/http"
"strconv"
)
func (app *Application) Notifications(w http.ResponseWriter, r *http.Request) {
feed := app.Profile.GetNotificationsForUser(app.ActiveUser.ID, 0)
cursor_val := 0
cursor_param := r.URL.Query().Get("cursor")
if cursor_param != "" {
var err error
cursor_val, err = strconv.Atoi(cursor_param)
if err != nil {
app.error_400_with_message(w, r, "invalid cursor (must be a number)")
return
}
}
app.buffered_render_page(w, "tpl/notifications.tpl", PageGlobalData{TweetTrove: feed.TweetTrove}, feed)
feed := app.Profile.GetNotificationsForUser(app.ActiveUser.ID, int64(cursor_val), 50) // TODO: parameterizable
if is_htmx(r) && cursor_val != 0 {
// It's a Show More request
app.buffered_render_htmx(w, "timeline", PageGlobalData{TweetTrove: feed.TweetTrove}, feed)
} else {
app.buffered_render_page(w, "tpl/notifications.tpl", PageGlobalData{TweetTrove: feed.TweetTrove}, feed)
}
}

View File

@ -906,4 +906,14 @@ func TestNotifications(t *testing.T) {
root, err := html.Parse(resp.Body)
require.NoError(err)
assert.Len(cascadia.QueryAll(root, selector(".notification")), 6)
// Show more
recorder = httptest.NewRecorder()
req = httptest.NewRequest("GET", "/notifications?cursor=1726604756351", nil)
req.Header.Set("HX-Request", "true")
app.ServeHTTP(recorder, req)
resp = recorder.Result()
root, err = html.Parse(resp.Body)
require.NoError(err)
assert.Len(cascadia.QueryAll(root, selector(".notification")), 5)
}

View File

@ -402,17 +402,18 @@ func NewFeed() Feed {
}
}
func (p Profile) GetNotificationsForUser(u_id UserID, cursor int64) Feed {
func (p Profile) GetNotificationsForUser(u_id UserID, cursor int64, count int64) Feed {
// Get the notifications
var notifications []Notification
err := p.DB.Select(&notifications,
`select id, type, sent_at, sort_index, user_id, ifnull(action_user_id, 0) action_user_id,
ifnull(action_tweet_id, 0) action_tweet_id, ifnull(action_retweet_id, 0) action_retweet_id, has_detail, last_scraped_at
from notifications
where sort_index < ? or ?
where (sort_index < ? or ?)
and user_id = ?
order by sort_index desc
`, cursor, cursor == 0, u_id)
limit ?
`, cursor, cursor == 0, u_id, count)
if err != nil {
panic(err)
}
@ -510,8 +511,18 @@ func (p Profile) GetNotificationsForUser(u_id UserID, cursor int64) Feed {
// TODO: proper user id
p.fill_content(&ret.TweetTrove, UserID(0))
// TODO:
// ret.CursorBottom = ??
// Set the bottom cursor value
ret.CursorBottom = Cursor{}
if len(ret.Items) < int(count) {
ret.CursorBottom.CursorPosition = CURSOR_END
} else {
ret.CursorBottom.CursorPosition = CURSOR_MIDDLE
last_item := ret.Items[len(ret.Items)-1]
last_notif, is_ok := ret.Notifications[last_item.NotificationID]
if !is_ok {
panic("last item isn't a notification???")
}
ret.CursorBottom.CursorValue = int(last_notif.SortIndex) // TODO: CursorValue should be int64
}
return ret
}

View File

@ -325,7 +325,7 @@ func TestNotificationsFeed(t *testing.T) {
profile, err := persistence.LoadProfile("../../sample_data/profile")
require.NoError(err)
feed := profile.GetNotificationsForUser(UserID(1488963321701171204), 12345678912345)
feed := profile.GetNotificationsForUser(UserID(1488963321701171204), 0, 6)
assert.Len(feed.TweetTrove.Notifications, 6)
assert.Len(feed.TweetTrove.Tweets, 3)
assert.Len(feed.TweetTrove.Retweets, 1)
@ -352,4 +352,30 @@ func TestNotificationsFeed(t *testing.T) {
assert.Equal(feed.Items[4].NotificationID, NotificationID("FKncQJGVgAQAAAABSQ3bEaTgXL-G8wObqVY"))
assert.Equal(feed.Items[5].NotificationID, NotificationID("FKncQJGVgAQAAAABSQ3bEaTgXL8f40e77r4"))
assert.Equal(feed.Items[5].TweetID, TweetID(1826778617705115868))
assert.Equal(feed.CursorBottom.CursorPosition, persistence.CURSOR_MIDDLE)
assert.Equal(feed.CursorBottom.CursorValue, 1723494244885)
// Paginated version
// -----------------
// Limit 3, after sort_index of the 1st one above
feed = profile.GetNotificationsForUser(UserID(1488963321701171204), 1726604756351, 3)
assert.Len(feed.TweetTrove.Notifications, 3)
assert.Len(feed.Items, 3)
assert.Equal(feed.Items[0].NotificationID, NotificationID("FDzeDIfVUAIAAvsBiJONcqYgiLgXOolO9t0"))
assert.Equal(feed.Items[1].NotificationID, NotificationID("FKncQJGVgAQAAAABSQ3bEaTgXL8VBxefepo"))
assert.Equal(feed.Items[2].NotificationID, NotificationID("FKncQJGVgAQAAAABSQ3bEaTgXL_S11Ev36g"))
assert.Equal(feed.CursorBottom.CursorPosition, persistence.CURSOR_MIDDLE)
assert.Equal(feed.CursorBottom.CursorValue, 1724251072880)
// At end of feed
// --------------
// cursor = last notification's sort index
feed = profile.GetNotificationsForUser(UserID(1488963321701171204), 1723494244885, 3)
assert.Len(feed.Items, 0)
assert.Equal(feed.CursorBottom.CursorPosition, persistence.CURSOR_END)
}