Make scrolling a lot better in DMs

This commit is contained in:
Alessio 2024-02-23 18:08:55 -08:00
parent 06dcea0565
commit b146cd9bb5
4 changed files with 52 additions and 4 deletions

View File

@ -14,6 +14,7 @@ import (
type MessageData struct {
persistence.DMChatView
LatestPollingTimestamp int
ScrollBottom bool
}
func (app *Application) Messages(w http.ResponseWriter, r *http.Request) {
@ -28,7 +29,7 @@ func (app *Application) Messages(w http.ResponseWriter, r *http.Request) {
room_id := scraper.DMChatRoomID(parts[0])
if r.URL.Query().Has("poll") {
// TODO: where is this going to be used?
// Not run as a goroutine; this call blocks. It's not actually "background"
app.background_dm_polling_scrape()
}
@ -57,6 +58,9 @@ func (app *Application) Messages(w http.ResponseWriter, r *http.Request) {
chat_view_data.LatestPollingTimestamp, err = strconv.Atoi(latest_timestamp_str)
panic_if(err)
}
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)
chat_view_data.MessageIDs = chat_contents.MessageIDs

View File

@ -1,4 +1,4 @@
{{define "title"}}Followed Users{{end}}
{{define "title"}}Messages{{end}}
{{define "main"}}
<div class="chats-container">

View File

@ -3,5 +3,12 @@
{{range .RoomIDs}}
{{template "chat-list-entry" (dict "room" (index $.Rooms .) "messages" $.DMTrove.Messages "is_active" (eq $.ActiveRoomID .))}}
{{end}}
{{/* Scroll the active chat into view, if there is one */}}
{{if $.ActiveRoomID}}
<script>
document.querySelector(".chat.active-chat").scrollIntoViewIfNeeded(true)
</script>
{{end}}
</div>
{{end}}

View File

@ -53,9 +53,9 @@
{{end}}
<div id="new-messages-poller"
hx-swap="outerHTML scroll:.chat-messages:bottom"
hx-swap="outerHTML {{if $.ScrollBottom}}scroll:.chat-messages:bottom{{end}}"
hx-trigger="load delay:3s"
hx-get="/messages/{{$.ActiveRoomID}}?poll&latest_timestamp={{$.LatestPollingTimestamp}}"
hx-get="/messages/{{$.ActiveRoomID}}?poll&latest_timestamp={{$.LatestPollingTimestamp}}&scroll_bottom={{if $.ScrollBottom}}1{{else}}0{{end}}"
></div>
{{end}}
@ -88,6 +88,43 @@
</script>
{{end}}
</div>
<script>
(function () { // Wrap it all in an IIFE to avoid namespace pollution
const chat_messages = document.querySelector('.chat-messages');
// Disable auto-scroll-bottom on new message loads if the user has scrolled up
chat_messages.addEventListener('scroll', function() {
const _node = document.querySelector("#new-messages-poller");
const node = _node.cloneNode()
_node.remove(); // Removing and re-inserting the element cancels the HTMX polling, otherwise it will use the old values
const scrollPosition = chat_messages.scrollTop;
var bottomOfElement = chat_messages.scrollHeight - chat_messages.clientHeight;
var [path, qs] = node.attributes["hx-get"].value.split("?")
var params = new URLSearchParams(qs)
if (scrollPosition === bottomOfElement) {
// At bottom; new messages should be scrolled into view
node.setAttribute("hx-swap", "outerHTML scroll:.chat-messages:bottom");
params.set("scroll_bottom", "1")
node.setAttribute("hx-get", [path, params.toString()].join("?"))
} else {
// User has scrolled up; disable auto-scrolling when new messages arrive
node.setAttribute("hx-swap", "outerHTML");
params.set("scroll_bottom", "0")
node.setAttribute("hx-get", [path, params.toString()].join("?"))
}
chat_messages.appendChild(node);
htmx.process(node); // Manually enable HTMX on the manually-added node
});
// Scroll to the bottom of the chat window on initial page load
chat_messages.scrollTop = chat_messages.scrollHeight;
})();
</script>
{{end}}
{{define "dm-composer"}}