Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Fix instantly sending RRs #2770

Merged
merged 12 commits into from
Mar 12, 2019
Merged

Fix instantly sending RRs #2770

merged 12 commits into from
Mar 12, 2019

Conversation

dbkr
Copy link
Member

@dbkr dbkr commented Mar 8, 2019

Splits UserActivity into a tristate of 'active' (last < 1s), 'passive' (lasts a
couple of mins) and neither. Read receipts are sent when 'active', read markers
are sent while 'passive'.

Also fixed a document / window mix-up on the 'blur' handler.

Also adds a unit test for UserActivity because it's quite complex now
(and changes UserActivity to make it testable by accessing the singleton
via sharedInstance() rather than exporting it directly).

Fixes element-hq/element-web#9023

Splits UserActivity into a tristate of 'active' (last < 1s), 'passive' (lasts a
couple of mins) and neither. Read receipts are sent when 'active', read markers
are sent while 'passive'.

Also fixed a document / window mix-up on the 'blur' handler.

Also adds a unit test for UserActivity because it's quite complex now
(and changes UserActivity to make it testable by accessing the singleton
via sharedInstance() rather than exporting it directly).

Fixes element-hq/element-web#9023
@dbkr dbkr requested a review from a team March 8, 2019 12:52
@jryans jryans self-assigned this Mar 8, 2019
Copy link
Collaborator

@jryans jryans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this! 😁 It's a bit tricky to visualise how the sequence of timers winding other timers impacts the UX... 😅 Anyway, that's not really new from this PR.

I think a few of the comments would help clarify, so please take a look.

@@ -439,7 +439,7 @@ async function startMatrixClient() {
dis.dispatch({action: 'will_start_client'}, true);

Notifier.start();
UserActivity.start();
UserActivity.sharedInstance().start();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess DMRoomMap below reveals another, slightly different convention for shared instances. In general, the approach of sharedInstance (to create one if it doesn't exist and return) without a separate getter seems simpler to me.

Maybe there's value in filing an issue to unify approaches for simplicity? The peg style is also related, though not quite the same. Anyway, might be worth having a consistent style, especially if want to add this kind of thing more for testing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I'd forgotten about DMRoomMap's approach to singletons. Have filed element-hq/element-web#9090

src/UserActivity.js Show resolved Hide resolved

/**
* This class watches for user activity (moving the mouse or pressing a key)
* and starts/stops attached timers while the user is active.
*
* There are two classes of 'active' a user can be: 'active' and 'passive':
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit strange naming-wise for there to classes of X, where one of the values is also X. So maybe something like:

Suggested change
* There are two classes of 'active' a user can be: 'active' and 'passive':
* There are two classes of 'focused' a user can be: 'active' and 'passive':

If you agree, we may also want to rename the class to UserFocusTracker or something...?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmm, 'focused' makes me think it's more just about tracking whether the window has focus. We could go with Bruno's 'activeActive' and 'passiveActive', or 'activeNow' and 'activeRecently'?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, activeNow vs. activeRecently sounds like the clearest so far to me.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was just about to change this and then realised this would make functions called userCurrentlyActiveNow() and, even better, userCurrentlyActiveRecently(). I'll have a think...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe userActiveNowish() and userActiveRecently()?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was thinking maybe just userActiveNow()

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, that could work as well.

src/UserActivity.js Outdated Show resolved Hide resolved
src/UserActivity.js Show resolved Hide resolved
src/UserActivity.js Show resolved Hide resolved
document.addEventListener("visibilitychange", this._onPageVisibilityChanged);
window.addEventListener("blur", this._onWindowBlurred);
window.addEventListener("focus", this._onUserActivity);
this._document.onmousedown = this._onUserActivity;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a good moment to consistently use addEventListener here as well, rather than a mix of aEL and on<event>?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah yes, good point

@jryans jryans assigned dbkr and unassigned jryans Mar 8, 2019
@dbkr dbkr assigned jryans and unassigned dbkr Mar 8, 2019
this._document.onkeydown = this._onUserActivity;
this._document.addEventListener('mousedown', this._onUserActivity);
this._document.addEventListener('mousemove', this._onUserActivity);
this._document.addEventListener('keydown', this._onUserActivity);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for doing this! 😁 We should also change the ones in stop to call removeEventListener now.

Copy link
Collaborator

@jryans jryans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few things still to fix, I think. I'd like to see how the naming plays out.

@jryans jryans removed their assignment Mar 8, 2019
@jryans
Copy link
Collaborator

jryans commented Mar 8, 2019

(Clearing assignment following recent discussion to stop assigning PRs.)

also fix more indenting
@dbkr dbkr requested a review from jryans March 11, 2019 17:21
Copy link
Collaborator

@jryans jryans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's still more to go here to match the new naming, I think. Overall though, I think we have good terminology now. 😁

this._activeTimeout = new Timer(CURRENTLY_ACTIVE_THRESHOLD_MS);
this._passiveTimeout = new Timer(CURRENTLY_PASSIVE_THRESHOLD_MS);
this._activeNowTimeout = new Timer(CURRENTLY_ACTIVE_THRESHOLD_MS);
this._activeRecentlyTimeout = new Timer(CURRENTLY_PASSIVE_THRESHOLD_MS);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These thresholds should likely also be renamed to match as well.

* See userCurrentlyActive() for what it means for a user to be 'active'.
* Runs the given timer while the user is 'active', aborting when the user is no longer
* considered currently active.
* See userActiveNow() for what it means for a user to be 'active'.
* Can be called multiple times with the same already running timer, which is a NO-OP.
* Can be called before the user becomes active, in which case it is only started
* later on when the user does become active.
* @param {Timer} timer the timer to use
*/
timeWhileActive(timer) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, shouldn't we carry the new naming through to this API as well? We'd then have timeWhileActiveNow and timeWhileActiveRecently.

src/components/structures/TimelinePanel.js Outdated Show resolved Hide resolved
src/components/structures/TimelinePanel.js Outdated Show resolved Hide resolved
@dbkr dbkr requested a review from jryans March 12, 2019 10:43
Copy link
Collaborator

@jryans jryans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! 😁 Thanks for working on the naming changes. I think it's much easier to follow now.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

"New message" notifications disappear instantly
2 participants