Make notifications paginated
This commit is contained in:
parent
90f453c207
commit
b0cf2076e2
@ -2,10 +2,27 @@ package webserver
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (app *Application) Notifications(w http.ResponseWriter, r *http.Request) {
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
app.buffered_render_page(w, "tpl/notifications.tpl", PageGlobalData{TweetTrove: feed.TweetTrove}, feed)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -906,4 +906,14 @@ func TestNotifications(t *testing.T) {
|
|||||||
root, err := html.Parse(resp.Body)
|
root, err := html.Parse(resp.Body)
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
assert.Len(cascadia.QueryAll(root, selector(".notification")), 6)
|
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)
|
||||||
}
|
}
|
||||||
|
@ -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
|
// Get the notifications
|
||||||
var notifications []Notification
|
var notifications []Notification
|
||||||
err := p.DB.Select(¬ifications,
|
err := p.DB.Select(¬ifications,
|
||||||
`select id, type, sent_at, sort_index, user_id, ifnull(action_user_id, 0) action_user_id,
|
`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
|
ifnull(action_tweet_id, 0) action_tweet_id, ifnull(action_retweet_id, 0) action_retweet_id, has_detail, last_scraped_at
|
||||||
from notifications
|
from notifications
|
||||||
where sort_index < ? or ?
|
where (sort_index < ? or ?)
|
||||||
and user_id = ?
|
and user_id = ?
|
||||||
order by sort_index desc
|
order by sort_index desc
|
||||||
`, cursor, cursor == 0, u_id)
|
limit ?
|
||||||
|
`, cursor, cursor == 0, u_id, count)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -510,8 +511,18 @@ func (p Profile) GetNotificationsForUser(u_id UserID, cursor int64) Feed {
|
|||||||
// TODO: proper user id
|
// TODO: proper user id
|
||||||
p.fill_content(&ret.TweetTrove, UserID(0))
|
p.fill_content(&ret.TweetTrove, UserID(0))
|
||||||
|
|
||||||
// TODO:
|
// Set the bottom cursor value
|
||||||
// ret.CursorBottom = ??
|
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
|
return ret
|
||||||
}
|
}
|
||||||
|
@ -325,7 +325,7 @@ func TestNotificationsFeed(t *testing.T) {
|
|||||||
profile, err := persistence.LoadProfile("../../sample_data/profile")
|
profile, err := persistence.LoadProfile("../../sample_data/profile")
|
||||||
require.NoError(err)
|
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.Notifications, 6)
|
||||||
assert.Len(feed.TweetTrove.Tweets, 3)
|
assert.Len(feed.TweetTrove.Tweets, 3)
|
||||||
assert.Len(feed.TweetTrove.Retweets, 1)
|
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[4].NotificationID, NotificationID("FKncQJGVgAQAAAABSQ3bEaTgXL-G8wObqVY"))
|
||||||
assert.Equal(feed.Items[5].NotificationID, NotificationID("FKncQJGVgAQAAAABSQ3bEaTgXL8f40e77r4"))
|
assert.Equal(feed.Items[5].NotificationID, NotificationID("FKncQJGVgAQAAAABSQ3bEaTgXL8f40e77r4"))
|
||||||
assert.Equal(feed.Items[5].TweetID, TweetID(1826778617705115868))
|
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)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user