forked from zulip/zulip-mobile
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
presence: move all presence-reporting logic into new HeartbeatComponent
Centralize all presence-reporting logic into a new zero-display React component, currently (and somewhat arbitrarily) located under AppStateHandlers. This fixes at least two issues: * If the user logs in and out, or otherwise performs an additional "initial fetch" without killing the app, the presence timer will be started multiple times. (This was previously concealed by throttling logic in usersActions.reportPresence, which was itself removed in a previous patch in this set.) * If the user goes idle (e.g. by hitting the Home button), the presence timer will still run, and will still attempt to send `active` notifications. (These attempts are often suppressed while the app is in the background, but there's no guarantee of this.) Fixes zulip#3699 (properly), and is work towards zulip#3659. Unfortunately, there is no user-visible change yet: modifications will be needed on the Zulip server side as well.
- Loading branch information
1 parent
a32a1ac
commit 987a9b7
Showing
3 changed files
with
79 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
// @flow strict-local | ||
import { PureComponent } from 'react'; | ||
import { AppState } from 'react-native'; | ||
import type { Auth, Dispatch } from '../types'; | ||
|
||
import { connect } from '../react-redux'; | ||
import { tryGetAuth } from '../account/accountsSelectors'; | ||
import { reportPresence } from '../actions'; | ||
import Heartbeat from './heartbeat'; | ||
|
||
type Props = $ReadOnly<{| | ||
dispatch: Dispatch, | ||
auth: Auth | void, | ||
|}>; | ||
|
||
/** | ||
* Component providing a recurrent `presence` signal. | ||
*/ | ||
// Note that "PureComponent" is of questionable veracity: this component's | ||
// entire purpose is to emit network calls for their observable side effects | ||
// as a side effect of being rendered. | ||
// | ||
// However, it is at least true that there is never a need to call `render()` | ||
// (and therefore `componentDidUpdate()`) if the props haven't changed. | ||
class PresenceHeartbeat extends PureComponent<Props> { | ||
/** Callback for Heartbeat object. */ | ||
onHeartbeat = (state: boolean) => { | ||
// N.B.: If `auth` changes, we do not send out a final `false` presence | ||
// status for the previous `auth`. It's the responsibility of our logout | ||
// handler to determine whether that's necessary. | ||
// | ||
// (TODO: ensure that our logout handlers actually do that.) | ||
if (this.props.auth) { | ||
this.props.dispatch(reportPresence(state)); | ||
} | ||
}; | ||
|
||
heartbeat: Heartbeat = new Heartbeat(this.onHeartbeat, 1000 * 60); | ||
|
||
componentDidMount() { | ||
this.updateHeartbeatState(); // conditional start | ||
AppState.addEventListener('change', this.updateHeartbeatState); | ||
} | ||
|
||
componentWillUnmount() { | ||
AppState.removeEventListener('change', this.updateHeartbeatState); | ||
this.heartbeat.stop(); // unconditional stop | ||
} | ||
|
||
// React to any state change. | ||
updateHeartbeatState = () => { | ||
// heartbeat.toState is idempotent | ||