diff --git a/app/assets/javascripts/components/components/status_list.jsx b/app/assets/javascripts/components/components/status_list.jsx index 0e64f0ee6a3..69a2354c762 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 = ; } - const scrollableArea = ( -
-
- {prepend} + if (isLoading || statusIds.size > 0 || !emptyMessage) { + scrollableArea = ( +
+
+ {prepend} - {statusIds.map((statusId) => { - return ; - })} + {statusIds.map((statusId) => { + return ; + })} - {loadMore} + {loadMore} +
-
- ); + ); + } else { + scrollableArea = ( +
+ {emptyMessage} +
+ ); + } 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 4a0e7684dce..6cb9e54828f 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 ( - + } /> ); }, diff --git a/app/assets/javascripts/components/features/home_timeline/index.jsx b/app/assets/javascripts/components/features/home_timeline/index.jsx index 5d2263f1562..23e1987018b 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 ( - + }} />} /> ); }, diff --git a/app/assets/javascripts/components/features/notifications/index.jsx b/app/assets/javascripts/components/features/notifications/index.jsx index 6d10768ded9..9532b8af823 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 = ; } - const scrollableArea = ( -
-
- {notifications.map(item => )} - {loadMore} + if (isLoading || notifications.size > 0) { + scrollableArea = ( +
+
+ {notifications.map(item => )} + {loadMore} +
-
- ); + ); + } else { + scrollableArea = ( +
+ +
+ ); + } if (trackScroll) { return ( diff --git a/app/assets/javascripts/components/features/status/index.jsx b/app/assets/javascripts/components/features/status/index.jsx index 40c0460a594..e17c078d275 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 77ec2705f08..8d281048e1b 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 912405a9f63..bc56891f39f 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; + } + } +}