show loading spinner for suggested content
This commit is contained in:
parent
afecace3ad
commit
0394854128
4 changed files with 87 additions and 27 deletions
|
@ -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 (
|
||||
<div
|
||||
className={classnames('spinner', {
|
||||
'spinner--dark': !light && (dark || theme === LIGHT_THEME),
|
||||
'spinner--light': !dark && (light || theme === DARK_THEME),
|
||||
'spinner--splash': type === 'splash',
|
||||
'spinner--small': type === 'small',
|
||||
})}
|
||||
>
|
||||
<div className="rect rect1" />
|
||||
<div className="rect rect2" />
|
||||
<div className="rect rect3" />
|
||||
<div className="rect rect4" />
|
||||
<div className="rect rect5" />
|
||||
</div>
|
||||
);
|
||||
type State = {
|
||||
show: boolean,
|
||||
};
|
||||
|
||||
Spinner.defaultProps = {
|
||||
dark: false,
|
||||
light: false,
|
||||
};
|
||||
class Spinner extends PureComponent<Props, State> {
|
||||
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 (
|
||||
<div
|
||||
className={classnames('spinner', {
|
||||
'spinner--dark': !light && (dark || theme === LIGHT_THEME),
|
||||
'spinner--light': !dark && (light || theme === DARK_THEME),
|
||||
'spinner--splash': type === 'splash',
|
||||
'spinner--small': type === 'small',
|
||||
})}
|
||||
>
|
||||
<div className="rect rect1" />
|
||||
<div className="rect rect2" />
|
||||
<div className="rect rect3" />
|
||||
<div className="rect rect4" />
|
||||
<div className="rect rect5" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Spinner;
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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<Props> {
|
||||
render() {
|
||||
const { suggested } = this.props;
|
||||
const { suggested, loading } = this.props;
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="page__empty">
|
||||
<Spinner delayed />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return suggested ? (
|
||||
<div className="card__content subscriptions__suggested">
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue