Added placeholder loaders to multiple components
• Added: - placeholder loaders to multiple components - status, panels, comment, lists, group items, notifications
This commit is contained in:
parent
a38d9f6133
commit
bc6cf0e624
@ -4,6 +4,7 @@ import Block from './block'
|
|||||||
import ScrollableList from './scrollable_list'
|
import ScrollableList from './scrollable_list'
|
||||||
import ListItem from './list_item'
|
import ListItem from './list_item'
|
||||||
import Dummy from './dummy'
|
import Dummy from './dummy'
|
||||||
|
import ListItemPlaceholder from './placeholder/list_item_placeholder'
|
||||||
|
|
||||||
export default class List extends ImmutablePureComponent {
|
export default class List extends ImmutablePureComponent {
|
||||||
|
|
||||||
@ -45,6 +46,8 @@ export default class List extends ImmutablePureComponent {
|
|||||||
scrollKey={scrollKey}
|
scrollKey={scrollKey}
|
||||||
emptyMessage={emptyMessage}
|
emptyMessage={emptyMessage}
|
||||||
showLoading={showLoading}
|
showLoading={showLoading}
|
||||||
|
placeholderComponent={ListItemPlaceholder}
|
||||||
|
placeholderCount={6}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
items.map((item, i) => (
|
items.map((item, i) => (
|
||||||
|
@ -5,6 +5,7 @@ import { fetchGroups } from '../../actions/groups'
|
|||||||
import PanelLayout from './panel_layout'
|
import PanelLayout from './panel_layout'
|
||||||
import GroupListItem from '../group_list_item'
|
import GroupListItem from '../group_list_item'
|
||||||
import ScrollableList from '../scrollable_list'
|
import ScrollableList from '../scrollable_list'
|
||||||
|
import GroupListItemPlaceholder from '../placeholder/group_list_item_placeholder'
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'groups.sidebar-panel.title', defaultMessage: 'Groups you\'re in' },
|
title: { id: 'groups.sidebar-panel.title', defaultMessage: 'Groups you\'re in' },
|
||||||
@ -86,6 +87,8 @@ class GroupSidebarPanel extends ImmutablePureComponent {
|
|||||||
<ScrollableList
|
<ScrollableList
|
||||||
scrollKey='groups_panel'
|
scrollKey='groups_panel'
|
||||||
showLoading={!fetched}
|
showLoading={!fetched}
|
||||||
|
placeholderComponent={GroupListItemPlaceholder}
|
||||||
|
placeholderCount={6}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
groupIds && groupIds.slice(0, maxCount).map((groupId, i) => (
|
groupIds && groupIds.slice(0, maxCount).map((groupId, i) => (
|
||||||
|
@ -5,6 +5,7 @@ import { expandAccountMediaTimeline } from '../../actions/timelines'
|
|||||||
import { getAccountGallery } from '../../selectors'
|
import { getAccountGallery } from '../../selectors'
|
||||||
import PanelLayout from './panel_layout'
|
import PanelLayout from './panel_layout'
|
||||||
import MediaItem from '../media_item'
|
import MediaItem from '../media_item'
|
||||||
|
import MediaGalleryPanelPlaceholder from '../placeholder/media_gallery_panel_placeholder'
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'media_gallery_panel.title', defaultMessage: 'Media' },
|
title: { id: 'media_gallery_panel.title', defaultMessage: 'Media' },
|
||||||
@ -16,6 +17,7 @@ const mapStateToProps = (state, { account }) => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
accountId,
|
accountId,
|
||||||
|
isLoading: state.getIn(['timelines', `account:${accountId}:media`, 'isLoading'], true),
|
||||||
attachments: getAccountGallery(state, accountId),
|
attachments: getAccountGallery(state, accountId),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -29,6 +31,7 @@ class MediaGalleryPanel extends ImmutablePureComponent {
|
|||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
accountId: PropTypes.string,
|
accountId: PropTypes.string,
|
||||||
account: ImmutablePropTypes.map,
|
account: ImmutablePropTypes.map,
|
||||||
|
isLoading: PropTypes.bool,
|
||||||
attachments: ImmutablePropTypes.list.isRequired,
|
attachments: ImmutablePropTypes.list.isRequired,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
}
|
}
|
||||||
@ -49,24 +52,24 @@ class MediaGalleryPanel extends ImmutablePureComponent {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
intl,
|
|
||||||
account,
|
account,
|
||||||
attachments
|
attachments,
|
||||||
|
intl,
|
||||||
|
isLoading,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
if (!account || !attachments) return null
|
if (!attachments) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PanelLayout
|
<PanelLayout
|
||||||
noPadding
|
noPadding
|
||||||
title={intl.formatMessage(messages.title)}
|
title={intl.formatMessage(messages.title)}
|
||||||
headerButtonTitle={intl.formatMessage(messages.show_all)}
|
headerButtonTitle={!!account ? intl.formatMessage(messages.show_all) : undefined}
|
||||||
headerButtonTo={`/${account.get('acct')}/media`}
|
headerButtonTo={!!account ? `/${account.get('acct')}/media` : undefined}
|
||||||
>
|
>
|
||||||
{
|
|
||||||
attachments.size > 0 &&
|
|
||||||
<div className={[_s.default, _s.flexRow, _s.flexWrap, _s.px10, _s.py10].join(' ')}>
|
<div className={[_s.default, _s.flexRow, _s.flexWrap, _s.px10, _s.py10].join(' ')}>
|
||||||
{
|
{
|
||||||
|
!!account && attachments.size > 0 &&
|
||||||
attachments.slice(0, 16).map((attachment, i) => (
|
attachments.slice(0, 16).map((attachment, i) => (
|
||||||
<MediaItem
|
<MediaItem
|
||||||
isSmall
|
isSmall
|
||||||
@ -76,8 +79,13 @@ class MediaGalleryPanel extends ImmutablePureComponent {
|
|||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
!account || (attachments.size === 0 && isLoading) &&
|
||||||
|
<div className={[_s.default, _s.width100PC].join(' ')}>
|
||||||
|
<MediaGalleryPanelPlaceholder />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
</div>
|
||||||
</PanelLayout>
|
</PanelLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import Divider from '../divider'
|
|||||||
import Icon from '../icon'
|
import Icon from '../icon'
|
||||||
import Text from '../text'
|
import Text from '../text'
|
||||||
import Dummy from '../dummy'
|
import Dummy from '../dummy'
|
||||||
|
import ProfileInfoPanelPlaceholder from '../placeholder/profile_info_panel_placeholder'
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'about', defaultMessage: 'About' },
|
title: { id: 'about', defaultMessage: 'About' },
|
||||||
@ -35,7 +36,15 @@ class ProfileInfoPanel extends ImmutablePureComponent {
|
|||||||
noPanel
|
noPanel
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
if (!account) return null
|
const Wrapper = noPanel ? Dummy : PanelLayout
|
||||||
|
|
||||||
|
if (!account) {
|
||||||
|
return (
|
||||||
|
<Wrapper title={intl.formatMessage(messages.title)}>
|
||||||
|
<ProfileInfoPanelPlaceholder />
|
||||||
|
</Wrapper>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const fields = account.get('fields')
|
const fields = account.get('fields')
|
||||||
const content = { __html: account.get('note_emojified') }
|
const content = { __html: account.get('note_emojified') }
|
||||||
@ -46,8 +55,6 @@ class ProfileInfoPanel extends ImmutablePureComponent {
|
|||||||
const isInvestor = account.get('is_investor')
|
const isInvestor = account.get('is_investor')
|
||||||
const hasBadges = isPro || isDonor || isInvestor
|
const hasBadges = isPro || isDonor || isInvestor
|
||||||
|
|
||||||
const Wrapper = noPanel ? Dummy : PanelLayout
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper title={intl.formatMessage(messages.title)}>
|
<Wrapper title={intl.formatMessage(messages.title)}>
|
||||||
<div className={[_s.default].join(' ')}>
|
<div className={[_s.default].join(' ')}>
|
||||||
|
@ -6,6 +6,7 @@ import { shortNumberFormat } from '../../utils/numbers'
|
|||||||
import PanelLayout from './panel_layout'
|
import PanelLayout from './panel_layout'
|
||||||
import UserStat from '../user_stat'
|
import UserStat from '../user_stat'
|
||||||
import Dummy from '../dummy'
|
import Dummy from '../dummy'
|
||||||
|
import ProfileStatsPanelPlaceholder from '../placeholder/profile_stats_panel_placeholder'
|
||||||
import ResponsiveClassesComponent from '../../features/ui/util/responsive_classes_component'
|
import ResponsiveClassesComponent from '../../features/ui/util/responsive_classes_component'
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
@ -32,12 +33,14 @@ class ProfileStatsPanel extends ImmutablePureComponent {
|
|||||||
noPanel
|
noPanel
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
if (!account) return null
|
|
||||||
|
|
||||||
const Wrapper = noPanel ? Dummy : PanelLayout
|
const Wrapper = noPanel ? Dummy : PanelLayout
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
|
{
|
||||||
|
!account &&
|
||||||
|
<ProfileStatsPanelPlaceholder />
|
||||||
|
}
|
||||||
{
|
{
|
||||||
!!account &&
|
!!account &&
|
||||||
<ResponsiveClassesComponent
|
<ResponsiveClassesComponent
|
||||||
|
@ -5,6 +5,7 @@ import { fetchGabTrends } from '../../actions/gab_trends'
|
|||||||
import PanelLayout from './panel_layout'
|
import PanelLayout from './panel_layout'
|
||||||
import ScrollableList from '../scrollable_list'
|
import ScrollableList from '../scrollable_list'
|
||||||
import TrendsItem from '../trends_item'
|
import TrendsItem from '../trends_item'
|
||||||
|
import TrendsItemPlaceholder from '../placeholder/trends_item_placeholder'
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'trends.title', defaultMessage: 'Trending right now' },
|
title: { id: 'trends.title', defaultMessage: 'Trending right now' },
|
||||||
@ -59,7 +60,9 @@ class TrendsPanel extends ImmutablePureComponent {
|
|||||||
title={intl.formatMessage(messages.title)}
|
title={intl.formatMessage(messages.title)}
|
||||||
>
|
>
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
isLoading={isLoading}
|
showLoading={isLoading}
|
||||||
|
placeholderComponent={TrendsItemPlaceholder}
|
||||||
|
placeholderCount={8}
|
||||||
scrollKey='trending-items'
|
scrollKey='trending-items'
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
|
@ -5,7 +5,8 @@ import {
|
|||||||
} from '../../actions/suggestions'
|
} from '../../actions/suggestions'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import Account from '../../components/account'
|
import Account from '../account'
|
||||||
|
import AccountPlaceholder from '../placeholder/account_placeholder'
|
||||||
import PanelLayout from './panel_layout'
|
import PanelLayout from './panel_layout'
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
@ -16,6 +17,7 @@ const messages = defineMessages({
|
|||||||
|
|
||||||
const mapStateToProps = (state) => ({
|
const mapStateToProps = (state) => ({
|
||||||
suggestions: state.getIn(['suggestions', 'related', 'items']),
|
suggestions: state.getIn(['suggestions', 'related', 'items']),
|
||||||
|
isLoading: state.getIn(['suggestions', 'related', 'isLoading']),
|
||||||
})
|
})
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
@ -33,6 +35,7 @@ class WhoToFollowPanel extends ImmutablePureComponent {
|
|||||||
fetchRelatedSuggestions: PropTypes.func.isRequired,
|
fetchRelatedSuggestions: PropTypes.func.isRequired,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
suggestions: ImmutablePropTypes.list.isRequired,
|
suggestions: ImmutablePropTypes.list.isRequired,
|
||||||
|
isLoading: PropTypes.bool.isRequired,
|
||||||
isLazy: PropTypes.bool,
|
isLazy: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,12 +72,16 @@ class WhoToFollowPanel extends ImmutablePureComponent {
|
|||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
intl,
|
intl,
|
||||||
|
isLoading,
|
||||||
suggestions,
|
suggestions,
|
||||||
dismissRelatedSuggestion,
|
dismissRelatedSuggestion,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
if (suggestions.isEmpty()) return null
|
if (suggestions.isEmpty()) return null
|
||||||
|
|
||||||
|
const Child = isLoading ? AccountPlaceholder : Account
|
||||||
|
const arr = isLoading ? Array.apply(null, { length: 6 }) : suggestions
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PanelLayout
|
<PanelLayout
|
||||||
noPadding
|
noPadding
|
||||||
@ -84,8 +91,8 @@ class WhoToFollowPanel extends ImmutablePureComponent {
|
|||||||
>
|
>
|
||||||
<div className={_s.default}>
|
<div className={_s.default}>
|
||||||
{
|
{
|
||||||
suggestions.map(accountId => (
|
arr.map((accountId) => (
|
||||||
<Account
|
<Child
|
||||||
compact
|
compact
|
||||||
showDismiss
|
showDismiss
|
||||||
key={accountId}
|
key={accountId}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { Fragment } from 'react'
|
||||||
import throttle from 'lodash.throttle'
|
import throttle from 'lodash.throttle'
|
||||||
import { List as ImmutableList } from 'immutable'
|
import { List as ImmutableList } from 'immutable'
|
||||||
import IntersectionObserverArticle from './intersection_observer_article'
|
import IntersectionObserverArticle from './intersection_observer_article'
|
||||||
@ -28,6 +29,8 @@ export default class ScrollableList extends PureComponent {
|
|||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
onScrollToTop: PropTypes.func,
|
onScrollToTop: PropTypes.func,
|
||||||
onScroll: PropTypes.func,
|
onScroll: PropTypes.func,
|
||||||
|
placeholderComponent: PropTypes.node,
|
||||||
|
placeholderCount: PropTypes.node,
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
@ -220,13 +223,34 @@ export default class ScrollableList extends PureComponent {
|
|||||||
hasMore,
|
hasMore,
|
||||||
emptyMessage,
|
emptyMessage,
|
||||||
onLoadMore,
|
onLoadMore,
|
||||||
|
placeholderComponent: Placeholder,
|
||||||
|
placeholderCount,
|
||||||
} = this.props
|
} = this.props
|
||||||
const childrenCount = React.Children.count(children);
|
const childrenCount = React.Children.count(children);
|
||||||
|
|
||||||
const loadMore = (hasMore && onLoadMore) ? <LoadMore visible={!isLoading} onClick={this.handleLoadMore} /> : null
|
const loadMore = (hasMore && onLoadMore) ? <LoadMore visible={!isLoading} onClick={this.handleLoadMore} /> : null
|
||||||
|
|
||||||
if (showLoading) {
|
if (showLoading) {
|
||||||
return <ColumnIndicator type='loading' />
|
if (Placeholder) {
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
{
|
||||||
|
Array.apply(null, {
|
||||||
|
length: placeholderCount
|
||||||
|
}).map((_, i) => (
|
||||||
|
<Placeholder
|
||||||
|
key={`${scrollKey}-placeholder-${i}`}
|
||||||
|
isLast={i === placeholderCount - 1}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</Fragment>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ColumnIndicator type='loading' />
|
||||||
|
)
|
||||||
} else if (isLoading || childrenCount > 0 || hasMore || !emptyMessage) {
|
} else if (isLoading || childrenCount > 0 || hasMore || !emptyMessage) {
|
||||||
return (
|
return (
|
||||||
<div onMouseMove={this.handleMouseMove}>
|
<div onMouseMove={this.handleMouseMove}>
|
||||||
|
@ -12,6 +12,7 @@ import { me, displayMedia } from '../initial_state'
|
|||||||
import scheduleIdleTask from '../utils/schedule_idle_task'
|
import scheduleIdleTask from '../utils/schedule_idle_task'
|
||||||
import ComposeFormContainer from '../features/compose/containers/compose_form_container'
|
import ComposeFormContainer from '../features/compose/containers/compose_form_container'
|
||||||
import ResponsiveClassesComponent from '../features/ui/util/responsive_classes_component'
|
import ResponsiveClassesComponent from '../features/ui/util/responsive_classes_component'
|
||||||
|
import CommentPlaceholder from './placeholder/comment_placeholder'
|
||||||
import StatusContent from './status_content'
|
import StatusContent from './status_content'
|
||||||
import StatusPrepend from './status_prepend'
|
import StatusPrepend from './status_prepend'
|
||||||
import StatusActionBar from './status_action_bar'
|
import StatusActionBar from './status_action_bar'
|
||||||
@ -413,6 +414,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
|
|
||||||
if (isComment && !ancestorStatus && !isChild) {
|
if (isComment && !ancestorStatus && !isChild) {
|
||||||
// Wait to load...
|
// Wait to load...
|
||||||
|
// return <StatusPlaceholder />
|
||||||
if (contextType === 'feature') {
|
if (contextType === 'feature') {
|
||||||
return <ColumnIndicator type='loading' />
|
return <ColumnIndicator type='loading' />
|
||||||
}
|
}
|
||||||
@ -587,20 +589,10 @@ class Status extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
status.get('replies_count') > 0 && !commentsLimited && !isNotification && descendantsIds && descendantsIds.size === 0 &&
|
status.get('replies_count') > 0 && !isChild && !isNotification && !commentsLimited &&
|
||||||
<Fragment>
|
|
||||||
<div className={[_s.default, _s.mr10, _s.ml10, _s.mb10, _s.borderColorSecondary, _s.borderBottom1PX].join(' ')} />
|
|
||||||
<ColumnIndicator type='loading' />
|
|
||||||
</Fragment>
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
descendantsIds && !isChild && !isNotification && descendantsIds.size > 0 && !commentsLimited &&
|
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<div className={[_s.default, _s.mr10, _s.ml10, _s.mb10, _s.borderColorSecondary, _s.borderBottom1PX].join(' ')} />
|
<div className={[_s.default, _s.mr10, _s.ml10, _s.mb10, _s.borderColorSecondary, _s.borderBottom1PX].join(' ')} />
|
||||||
|
|
||||||
{
|
|
||||||
!commentsLimited && descendantsIds.size > 1 &&
|
|
||||||
<div className={[_s.default, _s.px15, _s.py5, _s.mb5, _s.flexRow].join(' ')}>
|
<div className={[_s.default, _s.px15, _s.py5, _s.mb5, _s.flexRow].join(' ')}>
|
||||||
<Text color='secondary' size='small'>
|
<Text color='secondary' size='small'>
|
||||||
{intl.formatMessage(messages.sortBy)}
|
{intl.formatMessage(messages.sortBy)}
|
||||||
@ -612,19 +604,32 @@ class Status extends ImmutablePureComponent {
|
|||||||
className={_s.ml5}
|
className={_s.ml5}
|
||||||
buttonRef={this.setCommentSortButtonRef}
|
buttonRef={this.setCommentSortButtonRef}
|
||||||
onClick={this.handleOnCommentSortOpen}
|
onClick={this.handleOnCommentSortOpen}
|
||||||
|
disabled={descendantsIds.size === 0}
|
||||||
>
|
>
|
||||||
<Text color='inherit' weight='medium' size='small'>
|
<Text color='inherit' weight='medium' size='small'>
|
||||||
{sortByTitle}
|
{sortByTitle}
|
||||||
</Text>
|
</Text>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{
|
||||||
|
descendantsIds.size === 0 &&
|
||||||
|
<Fragment>
|
||||||
|
<CommentPlaceholder />
|
||||||
|
<CommentPlaceholder />
|
||||||
|
<CommentPlaceholder />
|
||||||
|
</Fragment>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
descendantsIds.size > 0 &&
|
||||||
<CommentList
|
<CommentList
|
||||||
ancestorAccountId={status.getIn(['account', 'id'])}
|
ancestorAccountId={status.getIn(['account', 'id'])}
|
||||||
commentsLimited={commentsLimited}
|
commentsLimited={commentsLimited}
|
||||||
descendants={descendantsIds}
|
descendants={descendantsIds}
|
||||||
onViewComments={this.handleClick}
|
onViewComments={this.handleClick}
|
||||||
/>
|
/>
|
||||||
|
}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
@ -9,9 +9,9 @@ import { dequeueTimeline } from '../actions/timelines'
|
|||||||
import { scrollTopTimeline } from '../actions/timelines'
|
import { scrollTopTimeline } from '../actions/timelines'
|
||||||
import { fetchStatus, fetchContext } from '../actions/statuses'
|
import { fetchStatus, fetchContext } from '../actions/statuses'
|
||||||
import StatusContainer from '../containers/status_container'
|
import StatusContainer from '../containers/status_container'
|
||||||
|
import StatusPlaceholder from './placeholder/status_placeholder'
|
||||||
import ScrollableList from './scrollable_list'
|
import ScrollableList from './scrollable_list'
|
||||||
import TimelineQueueButtonHeader from './timeline_queue_button_header'
|
import TimelineQueueButtonHeader from './timeline_queue_button_header'
|
||||||
import ColumnIndicator from './column_indicator'
|
|
||||||
|
|
||||||
const makeGetStatusIds = () => createSelector([
|
const makeGetStatusIds = () => createSelector([
|
||||||
(state, { type, id }) => state.getIn(['settings', type], ImmutableMap()),
|
(state, { type, id }) => state.getIn(['settings', type], ImmutableMap()),
|
||||||
@ -228,8 +228,15 @@ class StatusList extends ImmutablePureComponent {
|
|||||||
} = this.props
|
} = this.props
|
||||||
const { fetchedContext, refreshing } = this.state
|
const { fetchedContext, refreshing } = this.state
|
||||||
|
|
||||||
if (isPartial) {
|
if (isPartial || isLoading && statusIds.size === 0) {
|
||||||
return <ColumnIndicator type='loading' />
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<StatusPlaceholder />
|
||||||
|
<StatusPlaceholder />
|
||||||
|
<StatusPlaceholder />
|
||||||
|
<StatusPlaceholder />
|
||||||
|
</Fragment>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// : hack :
|
// : hack :
|
||||||
|
@ -17,6 +17,7 @@ import ScrollableList from '../components/scrollable_list'
|
|||||||
import TimelineQueueButtonHeader from '../components/timeline_queue_button_header'
|
import TimelineQueueButtonHeader from '../components/timeline_queue_button_header'
|
||||||
import Block from '../components/block'
|
import Block from '../components/block'
|
||||||
import Account from '../components/account'
|
import Account from '../components/account'
|
||||||
|
import NotificationPlaceholder from '../components/placeholder/notification_placeholder'
|
||||||
|
|
||||||
const mapStateToProps = (state) => ({
|
const mapStateToProps = (state) => ({
|
||||||
notifications: state.getIn(['notifications', 'items']),
|
notifications: state.getIn(['notifications', 'items']),
|
||||||
@ -180,6 +181,8 @@ class Notifications extends ImmutablePureComponent {
|
|||||||
onLoadMore={this.handleLoadOlder}
|
onLoadMore={this.handleLoadOlder}
|
||||||
onScrollToTop={this.handleScrollToTop}
|
onScrollToTop={this.handleScrollToTop}
|
||||||
onScroll={this.handleScroll}
|
onScroll={this.handleScroll}
|
||||||
|
placeholderComponent={NotificationPlaceholder}
|
||||||
|
placeholderCount={3}
|
||||||
>
|
>
|
||||||
{scrollableContent}
|
{scrollableContent}
|
||||||
</ScrollableList>
|
</ScrollableList>
|
||||||
|
@ -6,7 +6,7 @@ import {
|
|||||||
fetchContext,
|
fetchContext,
|
||||||
} from '../actions/statuses'
|
} from '../actions/statuses'
|
||||||
import StatusContainer from '../containers/status_container'
|
import StatusContainer from '../containers/status_container'
|
||||||
import ColumnIndicator from '../components/column_indicator'
|
import StatusPlaceholder from '../components/placeholder/status_placeholder'
|
||||||
|
|
||||||
const mapStateToProps = (state, props) => {
|
const mapStateToProps = (state, props) => {
|
||||||
const statusId = props.id || props.params.statusId
|
const statusId = props.id || props.params.statusId
|
||||||
@ -73,7 +73,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
const { status } = this.props
|
const { status } = this.props
|
||||||
|
|
||||||
if (!status) {
|
if (!status) {
|
||||||
return <ColumnIndicator type='loading' />
|
return <StatusPlaceholder />
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
Loading…
Reference in New Issue
Block a user