diff --git a/internal/webserver/handler_messages.go b/internal/webserver/handler_messages.go index 1ae85f5..4211b76 100644 --- a/internal/webserver/handler_messages.go +++ b/internal/webserver/handler_messages.go @@ -57,10 +57,18 @@ func (app *Application) message_detail(w http.ResponseWriter, r *http.Request) { if r.URL.Query().Get("scroll_bottom") != "0" { chat_view_data.ScrollBottom = true } - chat_contents := app.Profile.GetChatRoomContents(room_id, chat_view_data.LatestPollingTimestamp) - chat_view_data.MergeWith(chat_contents.DMTrove) + + c := persistence.NewConversationCursor(room_id) + c.SinceTimestamp = scraper.TimestampFromUnixMilli(int64(chat_view_data.LatestPollingTimestamp)) + if cursor_value := r.URL.Query().Get("cursor"); cursor_value != "" { + until_time, err := strconv.Atoi(cursor_value) + panic_if(err) // TODO: 400 not 500 + c.UntilTimestamp = scraper.TimestampFromUnixMilli(int64(until_time)) + } + chat_contents := app.Profile.GetChatRoomMessagesByCursor(c) chat_view_data.DMChatView.MergeWith(chat_contents.DMTrove) chat_view_data.MessageIDs = chat_contents.MessageIDs + chat_view_data.Cursor = chat_contents.Cursor if len(chat_view_data.MessageIDs) > 0 { last_message_id := chat_view_data.MessageIDs[len(chat_view_data.MessageIDs)-1] chat_view_data.LatestPollingTimestamp = int(chat_view_data.Messages[last_message_id].SentAt.UnixMilli()) @@ -72,6 +80,12 @@ func (app *Application) message_detail(w http.ResponseWriter, r *http.Request) { app.buffered_render_htmx(w, "messages-with-poller", global_data, chat_view_data) return } + + // Scrolling-back should add new messages to the top of the page + if r.URL.Query().Has("cursor") { + app.buffered_render_htmx(w, "messages-top", global_data, chat_view_data) + return + } } app.buffered_render_page(w, "tpl/messages.tpl", global_data, chat_view_data) diff --git a/internal/webserver/server_test.go b/internal/webserver/server_test.go index ec573b3..674425d 100644 --- a/internal/webserver/server_test.go +++ b/internal/webserver/server_test.go @@ -821,3 +821,24 @@ func TestMessagesRoomPollForUpdatesEmptyResult(t *testing.T) { Val: "/messages/1488963321701171204-1178839081222115328?poll&latest_timestamp=1686025129144&scroll_bottom=1", }) } + +// Scroll back in the messages +func TestMessagesPaginate(t *testing.T) { + assert := assert.New(t) + require := require.New(t) + + // Boilerplate for setting an active user + app := webserver.NewApp(profile) + app.IsScrapingDisabled = true + app.ActiveUser = scraper.User{ID: 1488963321701171204, Handle: "Offline_Twatter"} // Simulate a login + + // Chat detail + recorder := httptest.NewRecorder() + req := httptest.NewRequest("GET", "/messages/1488963321701171204-1178839081222115328?cursor=1686025129142", 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(".dm-message")), 2) +} diff --git a/internal/webserver/tpl/tweet_page_includes/chat_view.tpl b/internal/webserver/tpl/tweet_page_includes/chat_view.tpl index 04041c1..939a22c 100644 --- a/internal/webserver/tpl/tweet_page_includes/chat_view.tpl +++ b/internal/webserver/tpl/tweet_page_includes/chat_view.tpl @@ -106,6 +106,7 @@ {{end}}
@@ -190,3 +191,24 @@ {{end}} > {{end}} + +{{define "conversation-top"}} +