diff options
7 files changed, 89 insertions, 44 deletions
diff --git a/app/assets/javascripts/components/components/status_list.jsx b/app/assets/javascripts/components/components/status_list.jsx index 0e64f0ee6..69a2354c7 100644 --- a/app/assets/javascripts/components/components/status_list.jsx +++ b/app/assets/javascripts/components/components/status_list.jsx @@ -14,7 +14,8 @@ const StatusList = React.createClass({ onScroll: React.PropTypes.func, trackScroll: React.PropTypes.bool, isLoading: React.PropTypes.bool, - prepend: React.PropTypes.node + prepend: React.PropTypes.node, + emptyMessage: React.PropTypes.node }, getDefaultProps () { @@ -71,27 +72,36 @@ const StatusList = React.createClass({ }, render () { - const { statusIds, onScrollToBottom, trackScroll, isLoading, prepend } = this.props; + const { statusIds, onScrollToBottom, trackScroll, isLoading, prepend, emptyMessage } = this.props; let loadMore = ''; + let scrollableArea = ''; if (!isLoading && statusIds.size > 0) { loadMore = <LoadMore onClick={this.handleLoadMore} />; } - const scrollableArea = ( - <div className='scrollable' ref={this.setRef}> - <div> - {prepend} + if (isLoading || statusIds.size > 0 || !emptyMessage) { + scrollableArea = ( + <div className='scrollable' ref={this.setRef}> + <div> + {prepend} - {statusIds.map((statusId) => { - return <StatusContainer key={statusId} id={statusId} />; - })} + {statusIds.map((statusId) => { + return <StatusContainer key={statusId} id={statusId} />; + })} - {loadMore} + {loadMore} + </div> </div> - </div> - ); + ); + } else { + scrollableArea = ( + <div className='empty-column-indicator' ref={this.setRef}> + {emptyMessage} + </div> + ); + } if (trackScroll) { return ( diff --git a/app/assets/javascripts/components/features/hashtag_timeline/index.jsx b/app/assets/javascripts/components/features/hashtag_timeline/index.jsx index 4a0e7684d..6cb9e5482 100644 --- a/app/assets/javascripts/components/features/hashtag_timeline/index.jsx +++ b/app/assets/javascripts/components/features/hashtag_timeline/index.jsx @@ -8,6 +8,7 @@ import { deleteFromTimelines } from '../../actions/timelines'; import ColumnBackButtonSlim from '../../components/column_back_button_slim'; +import { FormattedMessage } from 'react-intl'; import createStream from '../../stream'; const mapStateToProps = state => ({ @@ -76,7 +77,7 @@ const HashtagTimeline = React.createClass({ return ( <Column icon='hashtag' heading={id}> <ColumnBackButtonSlim /> - <StatusListContainer type='tag' id={id} /> + <StatusListContainer type='tag' id={id} emptyMessage={<FormattedMessage id='empty_column.hashtag' defaultMessage='There is nothing in this hashtag yet.' />} /> </Column> ); }, diff --git a/app/assets/javascripts/components/features/home_timeline/index.jsx b/app/assets/javascripts/components/features/home_timeline/index.jsx index 5d2263f15..23e198701 100644 --- a/app/assets/javascripts/components/features/home_timeline/index.jsx +++ b/app/assets/javascripts/components/features/home_timeline/index.jsx @@ -1,8 +1,9 @@ import PureRenderMixin from 'react-addons-pure-render-mixin'; import StatusListContainer from '../ui/containers/status_list_container'; import Column from '../ui/components/column'; -import { defineMessages, injectIntl } from 'react-intl'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import ColumnSettingsContainer from './containers/column_settings_container'; +import { Link } from 'react-router'; const messages = defineMessages({ title: { id: 'column.home', defaultMessage: 'Home' } @@ -22,7 +23,7 @@ const HomeTimeline = React.createClass({ return ( <Column icon='home' heading={intl.formatMessage(messages.title)}> <ColumnSettingsContainer /> - <StatusListContainer {...this.props} type='home' /> + <StatusListContainer {...this.props} type='home' emptyMessage={<FormattedMessage id='empty_column.home' defaultMessage="You aren’t following anyone yet. Visit {public} or use search to get started and meet other users." values={{ public: <Link to='/timelines/public'><FormattedMessage id='empty_column.home.public_timeline' defaultMessage='the public timeline' /></Link> }} />} /> </Column> ); }, diff --git a/app/assets/javascripts/components/features/notifications/index.jsx b/app/assets/javascripts/components/features/notifications/index.jsx index 6d10768de..9532b8af8 100644 --- a/app/assets/javascripts/components/features/notifications/index.jsx +++ b/app/assets/javascripts/components/features/notifications/index.jsx @@ -5,7 +5,7 @@ import Column from '../ui/components/column'; import { expandNotifications, clearNotifications } from '../../actions/notifications'; import NotificationContainer from './containers/notification_container'; import { ScrollContainer } from 'react-router-scroll'; -import { defineMessages, injectIntl } from 'react-intl'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import ColumnSettingsContainer from './containers/column_settings_container'; import { createSelector } from 'reselect'; import Immutable from 'immutable'; @@ -76,20 +76,29 @@ const Notifications = React.createClass({ render () { const { intl, notifications, trackScroll, isLoading } = this.props; - let loadMore = ''; + let loadMore = ''; + let scrollableArea = ''; if (!isLoading && notifications.size > 0) { loadMore = <LoadMore onClick={this.handleLoadMore} />; } - const scrollableArea = ( - <div className='scrollable' onScroll={this.handleScroll} ref={this.setRef}> - <div> - {notifications.map(item => <NotificationContainer key={item.get('id')} notification={item} accountId={item.get('account')} />)} - {loadMore} + if (isLoading || notifications.size > 0) { + scrollableArea = ( + <div className='scrollable' onScroll={this.handleScroll} ref={this.setRef}> + <div> + {notifications.map(item => <NotificationContainer key={item.get('id')} notification={item} accountId={item.get('account')} />)} + {loadMore} + </div> </div> - </div> - ); + ); + } else { + scrollableArea = ( + <div className='empty-column-indicator' ref={this.setRef}> + <FormattedMessage id='empty_column.notifications' defaultMessage="You don't have any notifications yet. Interact with others to start the conversation." /> + </div> + ); + } if (trackScroll) { return ( diff --git a/app/assets/javascripts/components/features/status/index.jsx b/app/assets/javascripts/components/features/status/index.jsx index 40c0460a5..e17c078d2 100644 --- a/app/assets/javascripts/components/features/status/index.jsx +++ b/app/assets/javascripts/components/features/status/index.jsx @@ -1,29 +1,34 @@ -import { connect } from 'react-redux'; -import PureRenderMixin from 'react-addons-pure-render-mixin'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { fetchStatus } from '../../actions/statuses'; -import Immutable from 'immutable'; -import EmbeddedStatus from '../../components/status'; -import LoadingIndicator from '../../components/loading_indicator'; -import DetailedStatus from './components/detailed_status'; -import ActionBar from './components/action_bar'; -import Column from '../ui/components/column'; -import { favourite, reblog } from '../../actions/interactions'; +import { connect } from 'react-redux'; +import PureRenderMixin from 'react-addons-pure-render-mixin'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { fetchStatus } from '../../actions/statuses'; +import Immutable from 'immutable'; +import EmbeddedStatus from '../../components/status'; +import LoadingIndicator from '../../components/loading_indicator'; +import DetailedStatus from './components/detailed_status'; +import ActionBar from './components/action_bar'; +import Column from '../ui/components/column'; +import { + favourite, + unfavourite, + reblog, + unreblog +} from '../../actions/interactions'; import { replyCompose, mentionCompose -} from '../../actions/compose'; -import { deleteStatus } from '../../actions/statuses'; +} from '../../actions/compose'; +import { deleteStatus } from '../../actions/statuses'; import { initReport } from '../../actions/reports'; import { makeGetStatus, getStatusAncestors, getStatusDescendants -} from '../../selectors'; -import { ScrollContainer } from 'react-router-scroll'; -import ColumnBackButton from '../../components/column_back_button'; -import StatusContainer from '../../containers/status_container'; -import { openMedia } from '../../actions/modal'; +} from '../../selectors'; +import { ScrollContainer } from 'react-router-scroll'; +import ColumnBackButton from '../../components/column_back_button'; +import StatusContainer from '../../containers/status_container'; +import { openMedia } from '../../actions/modal'; import { isMobile } from '../../is_mobile' const makeMapStateToProps = () => { diff --git a/app/assets/javascripts/components/reducers/compose.jsx b/app/assets/javascripts/components/reducers/compose.jsx index 77ec2705f..8d281048e 100644 --- a/app/assets/javascripts/components/reducers/compose.jsx +++ b/app/assets/javascripts/components/reducers/compose.jsx @@ -126,8 +126,8 @@ export default function compose(state = initialState, action) { return state.withMutations(map => { map.set('in_reply_to', action.status.get('id')); map.set('text', statusToTextMentions(state, action.status)); - map.set('unlisted', action.status.get('visibility') === 'unlisted'); - map.set('private', action.status.get('visibility') === 'private'); + map.set('unlisted', action.status.get('visibility') === 'unlisted' || state.get('default_privacy') === 'unlisted'); + map.set('private', action.status.get('visibility') === 'private' || state.get('default_privacy') === 'private'); }); case COMPOSE_REPLY_CANCEL: return state.withMutations(map => { diff --git a/app/assets/stylesheets/components.scss b/app/assets/stylesheets/components.scss index 912405a9f..bc56891f3 100644 --- a/app/assets/stylesheets/components.scss +++ b/app/assets/stylesheets/components.scss @@ -1182,3 +1182,22 @@ button.active i.fa-retweet { background: rgba($color8, 0.1); } } + +.empty-column-indicator { + color: lighten($color1, 20%); + text-align: center; + padding: 20px; + padding-top: 100px; + font-size: 15px; + font-weight: 400; + cursor: default; + + a { + color: $color4; + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } +} |