Add pagination to DM conversation and scrolling back using 'show more' button

This commit is contained in:
Alessio 2024-05-04 15:44:17 -07:00
parent 4d6407492a
commit af3e496468
4 changed files with 65 additions and 3 deletions

View File

@ -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)

View File

@ -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)
}

View File

@ -106,6 +106,7 @@
{{end}}
<div class="chat-messages">
{{if .ActiveRoomID}}
{{template "conversation-top" .}}
{{template "messages-with-poller" .}}
{{end}}
</div>
@ -190,3 +191,24 @@
{{end}}
></span>
{{end}}
{{define "conversation-top"}}
<div class="conversation-top">
{{if .Cursor.CursorPosition.IsEnd}}
<!-- TODO: make a reusable eof-indicator -->
<div class="eof-indicator">Beginning of conversation</div>
{{else}}
<a class="show-more-button button"
hx-get="?cursor={{.Cursor.CursorValue}}" {{/* TODO: this might require a `cursor_to_query_params` if the same view is used for searching */}}
hx-target=".conversation-top"
hx-swap="outerHTML"
>Show more</a>
{{end}}
</div>
{{end}}
{{/* convenience template for htmx requests */}}
{{define "messages-top"}}
{{template "conversation-top" .}}
{{template "messages" .}}
{{end}}

View File

@ -264,9 +264,14 @@ func (p Profile) GetChatRoomsPreview(id UserID) DMChatView {
}
// Get chat room detail, including participants and messages
// TODO: get rid of this function (behavior has been moved to GetChatRoomMessagesByCursor)
func (p Profile) GetChatRoomContents(id DMChatRoomID, latest_timestamp int) DMChatView {
c := NewConversationCursor(id)
c.SinceTimestamp = TimestampFromUnixMilli(int64(latest_timestamp))
return p.GetChatRoomMessagesByCursor(c)
}
func (p Profile) GetChatRoomMessagesByCursor(c DMCursor) DMChatView {
ret := p.NextDMPage(c)
var room DMChatRoom
@ -274,7 +279,7 @@ func (p Profile) GetChatRoomContents(id DMChatRoomID, latest_timestamp int) DMCh
select `+CHAT_ROOMS_ALL_SQL_FIELDS+`
from chat_rooms
where id = ?
`, id)
`, c.ConversationId)
if err != nil {
panic(err)
}