UNPKG

@bigfishtv/cockpit

Version:

116 lines (99 loc) 3.13 kB
import { Component } from 'react' import { connect } from 'react-redux' import deepEqual from 'deep-equal' import { xhrUtils, modalHandler, viewerActions, windowVisible, LoginModal } from '../index' const CHECK_INTERVAL = 5 * 60 * 1000 // refresh every 5 minutes const LAST_FETCH_TIME_STORAGE_KEY = 'COCKPIT_0_viewerLastFetchTime' const VIEWER_URL = '/admin/tank/users/viewer.json' const LOGIN_URL = '/admin/tank/users/login.json' @connect(({ viewer }) => ({ viewer })) export default class ViewerState extends Component { state = { valid: true, windowVisible: windowVisible.windowVisible(), } componentDidMount() { // listen to visibility change this.unsubscribeWindowVisible = windowVisible.onVisibilityChange(windowVisible => { this.setState({ windowVisible }) }) // listen to requests on same site this.removeInterceptor = xhrUtils.interceptResponse(undefined, res => { if (res.status === 401 && res.config.url.match(/^\//) && res.config.url !== LOGIN_URL) { this.setState({ valid: false }) } return Promise.reject(res) }) this.timeout = window.setTimeout(this.fetchViewer, CHECK_INTERVAL) } componentDidUpdate(prevProps, prevState) { // show or hide login modal if (this.state.valid !== prevState.valid) { if (!this.state.valid) { this.modal = modalHandler.add({ Component: LoginModal, props: {}, closable: false, }) } else { modalHandler.remove(this.modal) } } // don't bother checking if user has logged in again // if the window isn't visible if (!this.state.valid && !this.state.windowVisible) { clearTimeout(this.timeout) } // if window becomes visible and the state is invalid, then fetch again // to see if user has logged in another window if (this.state.windowVisible !== prevState.windowVisible) { if (this.state.windowVisible && !this.state.valid) { this.fetchViewer() } } } componentWillUnmount() { this.removeInterceptor() this.unsubscribeWindowVisible() clearTimeout(this.timeout) } fetchViewer = () => { // schedule the next fetch clearTimeout(this.timeout) this.timeout = window.setTimeout(this.fetchViewer, CHECK_INTERVAL) // don't bother fetching if another window has fetched recently if (!this.state.windowVisible && hasFetchedRecently()) { return } try { window.localStorage.setItem(LAST_FETCH_TIME_STORAGE_KEY, `${Date.now()}`) } catch (e) {} xhrUtils.get({ url: VIEWER_URL, quietError: !this.state.valid, failureMessage: 'You have been logged out! Please login again', callback: data => { if (!deepEqual(data, this.props.viewer)) { this.props.dispatch(viewerActions.setViewer(data)) } this.setState({ valid: true }) }, callbackError: response => { if (response.status === 401) { this.setState({ valid: false }) } }, }) } render() { return null } } function hasFetchedRecently() { try { const lastFetchedTime = parseInt(window.localStorage.getItem(LAST_FETCH_TIME_STORAGE_KEY) || '-1') return lastFetchedTime + CHECK_INTERVAL >= Date.now() } catch (e) { return false } }