mirror of
https://github.com/discourse/discourse.git
synced 2026-08-09 12:38:21 -05:00
FEATURE: respect user presence when chat is on screen (#36652)
Handle, timeout of user so we stop reading and scrolling when user is in background or no longer active --------- Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com> Co-authored-by: David Taylor <david@taylorhq.com>
This commit is contained in:
co-authored by
Joffrey JAFFEUX
David Taylor
parent
5e46fd35f9
commit
d85becccef
@@ -75,7 +75,7 @@ export default {
|
||||
// present
|
||||
// When 20 minutes pass we stop long polling due to "shouldLongPollCallback".
|
||||
onPresenceChange({
|
||||
unseenTime: LONG_POLL_AFTER_UNSEEN_TIME,
|
||||
userUnseenTime: LONG_POLL_AFTER_UNSEEN_TIME,
|
||||
callback: (present) => {
|
||||
if (present && messageBus.onVisibilityChange) {
|
||||
messageBus.onVisibilityChange();
|
||||
|
||||
@@ -7,11 +7,10 @@ const DEFAULT_BROWSER_HIDDEN_MS = 0;
|
||||
|
||||
let browserHiddenAt = null;
|
||||
let lastUserActivity = Date.now();
|
||||
let userSeenJustNow = false;
|
||||
|
||||
let callbackWaitingForPresence = false;
|
||||
|
||||
let testPresence = true;
|
||||
let debounceUpdateDateTimeout = null;
|
||||
|
||||
// Check whether the document is currently visible, and the user is actively using the site
|
||||
// Will return false if the browser went into the background more than `browserHiddenTime` milliseconds ago
|
||||
@@ -52,17 +51,22 @@ export function onPresenceChange({
|
||||
if (userUnseenTime < DEFAULT_USER_UNSEEN_MS) {
|
||||
throw `userUnseenTime must be at least ${DEFAULT_USER_UNSEEN_MS}`;
|
||||
}
|
||||
if (browserHiddenTime < 0) {
|
||||
throw "browserHiddenTime must be non-negative";
|
||||
}
|
||||
callbacks.push({
|
||||
userUnseenTime,
|
||||
browserHiddenTime,
|
||||
lastState: true,
|
||||
lastState: userPresent({ userUnseenTime, browserHiddenTime }),
|
||||
callback,
|
||||
});
|
||||
}
|
||||
|
||||
export function removeOnPresenceChange(callback) {
|
||||
const i = callbacks.findIndex((c) => c.callback === callback);
|
||||
callbacks.splice(i, 1);
|
||||
if (i > -1) {
|
||||
callbacks.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
function processChanges() {
|
||||
@@ -71,11 +75,6 @@ function processChanges() {
|
||||
browserHiddenAt = browserHidden ? Date.now() : null;
|
||||
}
|
||||
|
||||
if (userSeenJustNow) {
|
||||
lastUserActivity = Date.now();
|
||||
userSeenJustNow = false;
|
||||
}
|
||||
|
||||
callbackWaitingForPresence = false;
|
||||
for (const callback of callbacks) {
|
||||
const currentState = userPresent({
|
||||
@@ -86,6 +85,9 @@ function processChanges() {
|
||||
if (callback.lastState !== currentState) {
|
||||
try {
|
||||
callback.callback(currentState);
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("Error in presence change callback:", e);
|
||||
} finally {
|
||||
callback.lastState = currentState;
|
||||
}
|
||||
@@ -98,9 +100,25 @@ function processChanges() {
|
||||
}
|
||||
|
||||
export function seenUser() {
|
||||
userSeenJustNow = true;
|
||||
// a boolean check is going to be 10x to 80x faster than Date.now()
|
||||
// scroll, touchmove, click, keydown can all happen very frequently
|
||||
// this debounces to de-risk
|
||||
if (callbackWaitingForPresence) {
|
||||
if (debounceUpdateDateTimeout) {
|
||||
clearTimeout(debounceUpdateDateTimeout);
|
||||
debounceUpdateDateTimeout = null;
|
||||
}
|
||||
// we are in the background waiting for presence, do this right away
|
||||
lastUserActivity = Date.now();
|
||||
processChanges();
|
||||
} else {
|
||||
// app is in foreground, debounce updates to lastUserActivity
|
||||
if (!debounceUpdateDateTimeout) {
|
||||
debounceUpdateDateTimeout = setTimeout(() => {
|
||||
debounceUpdateDateTimeout = null;
|
||||
lastUserActivity = Date.now();
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +145,7 @@ if (!isTesting()) {
|
||||
// Some of these events occur very frequently. Therefore seenUser() is as fast as possible.
|
||||
document.addEventListener("touchmove", seenUser, { passive: true });
|
||||
document.addEventListener("click", seenUser, { passive: true });
|
||||
document.addEventListener("keydown", seenUser, { passive: true });
|
||||
window.addEventListener("scroll", seenUser, { passive: true });
|
||||
window.addEventListener("focus", seenUser, { passive: true });
|
||||
|
||||
|
||||
Reference in New Issue
Block a user