From 0394854128ebda7d59c332f7429c6e504f9ae031 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Tue, 4 Dec 2018 15:12:03 -0500 Subject: [PATCH] show loading spinner for suggested content --- src/renderer/component/spinner/view.jsx | 94 ++++++++++++++----- .../component/subscribeSuggested/index.js | 3 +- .../component/subscribeSuggested/view.jsx | 12 ++- src/renderer/redux/selectors/subscriptions.js | 5 +- 4 files changed, 87 insertions(+), 27 deletions(-) diff --git a/src/renderer/component/spinner/view.jsx b/src/renderer/component/spinner/view.jsx index 4d5030b83..e30f04f5b 100644 --- a/src/renderer/component/spinner/view.jsx +++ b/src/renderer/component/spinner/view.jsx @@ -1,5 +1,5 @@ // @flow -import * as React from 'react'; +import React, { PureComponent } from 'react'; import classnames from 'classnames'; import { DARK_THEME, LIGHT_THEME } from 'constants/themes'; @@ -8,32 +8,78 @@ type Props = { light?: boolean, // always a light spinner theme: string, type: ?string, + delayed: boolean, }; -const Spinner = (props: Props) => { - const { dark, light, theme, type } = props; - - return ( -
-
-
-
-
-
-
- ); +type State = { + show: boolean, }; -Spinner.defaultProps = { - dark: false, - light: false, -}; +class Spinner extends PureComponent { + static defaultProps = { + // We may want a dark/light spinner regardless of the current theme + dark: false, + light: false, + delayed: false, + }; + + constructor() { + super(); + + this.state = { show: false }; + this.delayedTimeout = null; + } + + componentDidMount() { + const { delayed } = this.props; + if (!delayed) { + // We can disable this because the default state is to render nothing so there won't be any content thrashing + // eslint-disable-next-line react/no-did-mount-set-state + this.setState({ show: true }); + } else { + // If the delayed prop is passed in, wait some time before showing the loading indicator + // We don't want the spinner to just flash for a fraction of a second + this.delayedTimeout = setTimeout(() => { + // eslint-disable-next-line react/no-did-mount-set-state + this.setState({ show: true }); + }, 750); + } + } + + componentWillUnmount() { + if (this.delayedTimeout) { + clearTimeout(this.delayedTimeout); + this.delayedTimeout = null; + } + } + + delayedTimeout: ?TimeoutID; + + render() { + const { dark, light, theme, type } = this.props; + const { show } = this.state; + + if (!show) { + return null; + } + + return ( +
+
+
+
+
+
+
+ ); + } +} export default Spinner; diff --git a/src/renderer/component/subscribeSuggested/index.js b/src/renderer/component/subscribeSuggested/index.js index 782664e65..f82582bae 100644 --- a/src/renderer/component/subscribeSuggested/index.js +++ b/src/renderer/component/subscribeSuggested/index.js @@ -1,9 +1,10 @@ import { connect } from 'react-redux'; -import { selectSuggestedChannels } from 'redux/selectors/subscriptions'; +import { selectSuggestedChannels, selectIsFetchingSuggested } from 'redux/selectors/subscriptions'; import SuggestedSubscriptions from './view'; const select = state => ({ suggested: selectSuggestedChannels(state), + loading: selectIsFetchingSuggested(state), }); export default connect( diff --git a/src/renderer/component/subscribeSuggested/view.jsx b/src/renderer/component/subscribeSuggested/view.jsx index b9368e95e..952ec3485 100644 --- a/src/renderer/component/subscribeSuggested/view.jsx +++ b/src/renderer/component/subscribeSuggested/view.jsx @@ -1,14 +1,24 @@ // @flow import React, { PureComponent } from 'react'; import CategoryList from 'component/categoryList'; +import Spinner from 'component/spinner'; type Props = { suggested: Array<{ label: string, uri: string }>, + loading: boolean, }; class SuggestedSubscriptions extends PureComponent { render() { - const { suggested } = this.props; + const { suggested, loading } = this.props; + + if (loading) { + return ( +
+ +
+ ); + } return suggested ? (
diff --git a/src/renderer/redux/selectors/subscriptions.js b/src/renderer/redux/selectors/subscriptions.js index 1b3d66690..7b556ff3d 100644 --- a/src/renderer/redux/selectors/subscriptions.js +++ b/src/renderer/redux/selectors/subscriptions.js @@ -24,7 +24,10 @@ export const selectViewMode = createSelector(selectState, state => state.viewMod // Suggested subscriptions from internal apis export const selectSuggested = createSelector(selectState, state => state.suggested); -export const selectLoadingSuggested = createSelector(selectState, state => state.loadingSuggested); +export const selectIsFetchingSuggested = createSelector( + selectState, + state => state.loadingSuggested +); export const selectSuggestedChannels = createSelector( selectSubscriptions, selectSuggested,