diff options
author | Eugen Rochko <eugen@zeonfederated.com> | 2016-09-19 23:25:59 +0200 |
---|---|---|
committer | Eugen Rochko <eugen@zeonfederated.com> | 2016-09-19 23:26:21 +0200 |
commit | 337462aa5e68014aa15788e4513e190b2e434d7e (patch) | |
tree | a760e80e2bc9b1fef55f118ddeb8603b20155a61 | |
parent | f820edb463109e313e836d8e2f210927a0eba7d1 (diff) |
Re-organizing components to be more modular, adding loading bars
31 files changed, 155 insertions, 126 deletions
diff --git a/app/assets/javascripts/components.js b/app/assets/javascripts/components.js index d4d9b97e4..16e33e58e 100644 --- a/app/assets/javascripts/components.js +++ b/app/assets/javascripts/components.js @@ -6,4 +6,4 @@ window.ReactDOM = require('react-dom'); //= require_tree ./components -window.Root = require('./components/containers/root'); +window.Mastodon = require('./components/containers/mastodon'); diff --git a/app/assets/javascripts/components/components/frontend.jsx b/app/assets/javascripts/components/components/frontend.jsx deleted file mode 100644 index faa141af8..000000000 --- a/app/assets/javascripts/components/components/frontend.jsx +++ /dev/null @@ -1,50 +0,0 @@ -import ColumnsArea from './columns_area'; -import Column from './column'; -import Drawer from './drawer'; -import ComposeFormContainer from '../containers/compose_form_container'; -import FollowFormContainer from '../containers/follow_form_container'; -import UploadFormContainer from '../containers/upload_form_container'; -import StatusListContainer from '../containers/status_list_container'; -import NotificationsContainer from '../containers/notifications_container'; -import NavigationContainer from '../containers/navigation_container'; -import PureRenderMixin from 'react-addons-pure-render-mixin'; - -const Frontend = React.createClass({ - - mixins: [PureRenderMixin], - - render () { - return ( - <div style={{ flex: '0 0 auto', display: 'flex', width: '100%', height: '100%', background: '#1a1c23' }}> - <Drawer> - <div style={{ flex: '1 1 auto' }}> - <NavigationContainer /> - <ComposeFormContainer /> - <UploadFormContainer /> - </div> - - <FollowFormContainer /> - </Drawer> - - <ColumnsArea> - <Column icon='home' heading='Home'> - <StatusListContainer type='home' /> - </Column> - - <Column icon='at' heading='Mentions'> - <StatusListContainer type='mentions' /> - </Column> - - <Column> - {this.props.children} - </Column> - </ColumnsArea> - - <NotificationsContainer /> - </div> - ); - } - -}); - -export default Frontend; diff --git a/app/assets/javascripts/components/containers/root.jsx b/app/assets/javascripts/components/containers/mastodon.jsx index e30330beb..ba6e568ac 100644 --- a/app/assets/javascripts/components/containers/root.jsx +++ b/app/assets/javascripts/components/containers/mastodon.jsx @@ -1,6 +1,5 @@ import { Provider } from 'react-redux'; import configureStore from '../store/configureStore'; -import Frontend from '../components/frontend'; import { setTimeline, updateTimeline, deleteFromTimelines, refreshTimeline } from '../actions/timelines'; import { setAccessToken } from '../actions/meta'; import { setAccountSelf } from '../actions/accounts'; @@ -10,10 +9,11 @@ import Account fro import Settings from '../features/settings'; import Status from '../features/status'; import Subscriptions from '../features/subscriptions'; +import UI from '../features/ui'; const store = configureStore(); -const Root = React.createClass({ +const Mastodon = React.createClass({ propTypes: { token: React.PropTypes.string.isRequired, @@ -58,7 +58,7 @@ const Root = React.createClass({ return ( <Provider store={store}> <Router history={hashHistory}> - <Route path='/' component={Frontend}> + <Route path='/' component={UI}> <Route path='/settings' component={Settings} /> <Route path='/subscriptions' component={Subscriptions} /> <Route path='/statuses/:statusId' component={Status} /> @@ -71,4 +71,4 @@ const Root = React.createClass({ }); -export default Root; +export default Mastodon; diff --git a/app/assets/javascripts/components/features/status/index.jsx b/app/assets/javascripts/components/features/status/index.jsx index 72ff6a944..7a810d474 100644 --- a/app/assets/javascripts/components/features/status/index.jsx +++ b/app/assets/javascripts/components/features/status/index.jsx @@ -31,12 +31,12 @@ const Status = React.createClass({ mixins: [PureRenderMixin], componentWillMount () { - this.props.dispatch(fetchStatus(this.props.params.statusId)); + this.props.dispatch(fetchStatus(Number(this.props.params.statusId))); }, componentWillReceiveProps (nextProps) { if (nextProps.params.statusId !== this.props.params.statusId && nextProps.params.statusId) { - this.props.dispatch(fetchStatus(nextProps.params.statusId)); + this.props.dispatch(fetchStatus(Number(nextProps.params.statusId))); } }, diff --git a/app/assets/javascripts/components/components/character_counter.jsx b/app/assets/javascripts/components/features/ui/components/character_counter.jsx index dd9218844..dd9218844 100644 --- a/app/assets/javascripts/components/components/character_counter.jsx +++ b/app/assets/javascripts/components/features/ui/components/character_counter.jsx diff --git a/app/assets/javascripts/components/components/column.jsx b/app/assets/javascripts/components/features/ui/components/column.jsx index 7109bcc19..7109bcc19 100644 --- a/app/assets/javascripts/components/components/column.jsx +++ b/app/assets/javascripts/components/features/ui/components/column.jsx diff --git a/app/assets/javascripts/components/components/column_header.jsx b/app/assets/javascripts/components/features/ui/components/column_header.jsx index 21def69c7..21def69c7 100644 --- a/app/assets/javascripts/components/components/column_header.jsx +++ b/app/assets/javascripts/components/features/ui/components/column_header.jsx diff --git a/app/assets/javascripts/components/components/columns_area.jsx b/app/assets/javascripts/components/features/ui/components/columns_area.jsx index e45a6466d..e45a6466d 100644 --- a/app/assets/javascripts/components/components/columns_area.jsx +++ b/app/assets/javascripts/components/features/ui/components/columns_area.jsx diff --git a/app/assets/javascripts/components/components/compose_form.jsx b/app/assets/javascripts/components/features/ui/components/compose_form.jsx index 40d9b7773..1aa0b447f 100644 --- a/app/assets/javascripts/components/components/compose_form.jsx +++ b/app/assets/javascripts/components/features/ui/components/compose_form.jsx @@ -1,5 +1,5 @@ import CharacterCounter from './character_counter'; -import Button from './button'; +import Button from '../../../components/button'; import PureRenderMixin from 'react-addons-pure-render-mixin'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ReplyIndicator from './reply_indicator'; diff --git a/app/assets/javascripts/components/components/drawer.jsx b/app/assets/javascripts/components/features/ui/components/drawer.jsx index dfba11ad2..dfba11ad2 100644 --- a/app/assets/javascripts/components/components/drawer.jsx +++ b/app/assets/javascripts/components/features/ui/components/drawer.jsx diff --git a/app/assets/javascripts/components/components/follow_form.jsx b/app/assets/javascripts/components/features/ui/components/follow_form.jsx index 0563c511f..a9d73a9a1 100644 --- a/app/assets/javascripts/components/components/follow_form.jsx +++ b/app/assets/javascripts/components/features/ui/components/follow_form.jsx @@ -1,4 +1,4 @@ -import IconButton from './icon_button'; +import IconButton from '../../../components/icon_button'; import PureRenderMixin from 'react-addons-pure-render-mixin'; const FollowForm = React.createClass({ diff --git a/app/assets/javascripts/components/components/media_gallery.jsx b/app/assets/javascripts/components/features/ui/components/media_gallery.jsx index 20f9a3d87..20f9a3d87 100644 --- a/app/assets/javascripts/components/components/media_gallery.jsx +++ b/app/assets/javascripts/components/features/ui/components/media_gallery.jsx diff --git a/app/assets/javascripts/components/components/navigation_bar.jsx b/app/assets/javascripts/components/features/ui/components/navigation_bar.jsx index 2e7d6e6e1..b5d374a88 100644 --- a/app/assets/javascripts/components/components/navigation_bar.jsx +++ b/app/assets/javascripts/components/features/ui/components/navigation_bar.jsx @@ -1,8 +1,8 @@ import PureRenderMixin from 'react-addons-pure-render-mixin'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import Avatar from './avatar'; -import IconButton from './icon_button'; -import DisplayName from './display_name'; +import Avatar from '../../../components/avatar'; +import IconButton from '../../../components/icon_button'; +import DisplayName from '../../../components/display_name'; import { Link } from 'react-router'; const NavigationBar = React.createClass({ diff --git a/app/assets/javascripts/components/components/reply_indicator.jsx b/app/assets/javascripts/components/features/ui/components/reply_indicator.jsx index 9598a5874..316a23b54 100644 --- a/app/assets/javascripts/components/components/reply_indicator.jsx +++ b/app/assets/javascripts/components/features/ui/components/reply_indicator.jsx @@ -1,8 +1,8 @@ import PureRenderMixin from 'react-addons-pure-render-mixin'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import Avatar from './avatar'; -import IconButton from './icon_button'; -import DisplayName from './display_name'; +import Avatar from '../../../components/avatar'; +import IconButton from '../../../components/icon_button'; +import DisplayName from '../../../components/display_name'; const ReplyIndicator = React.createClass({ diff --git a/app/assets/javascripts/components/components/upload_button.jsx b/app/assets/javascripts/components/features/ui/components/upload_button.jsx index a77aacc10..d1b093242 100644 --- a/app/assets/javascripts/components/components/upload_button.jsx +++ b/app/assets/javascripts/components/features/ui/components/upload_button.jsx @@ -1,5 +1,5 @@ import PureRenderMixin from 'react-addons-pure-render-mixin'; -import Button from './button'; +import Button from '../../../components/button'; const UploadButton = React.createClass({ diff --git a/app/assets/javascripts/components/components/upload_form.jsx b/app/assets/javascripts/components/features/ui/components/upload_form.jsx index f0b6f7992..d584e9ab7 100644 --- a/app/assets/javascripts/components/components/upload_form.jsx +++ b/app/assets/javascripts/components/features/ui/components/upload_form.jsx @@ -1,7 +1,7 @@ import PureRenderMixin from 'react-addons-pure-render-mixin'; import ImmutablePropTypes from 'react-immutable-proptypes'; import UploadButton from './upload_button'; -import IconButton from './icon_button'; +import IconButton from '../../../components/icon_button'; const UploadForm = React.createClass({ diff --git a/app/assets/javascripts/components/containers/compose_form_container.jsx b/app/assets/javascripts/components/features/ui/containers/compose_form_container.jsx index d49217a90..a092a1e8e 100644 --- a/app/assets/javascripts/components/containers/compose_form_container.jsx +++ b/app/assets/javascripts/components/features/ui/containers/compose_form_container.jsx @@ -1,6 +1,6 @@ import { connect } from 'react-redux'; import ComposeForm from '../components/compose_form'; -import { changeCompose, submitCompose, cancelReplyCompose } from '../actions/compose'; +import { changeCompose, submitCompose, cancelReplyCompose } from '../../../actions/compose'; function selectStatus(state) { let statusId = state.getIn(['compose', 'in_reply_to'], null); diff --git a/app/assets/javascripts/components/containers/follow_form_container.jsx b/app/assets/javascripts/components/features/ui/containers/follow_form_container.jsx index b5f787aba..a21c1291b 100644 --- a/app/assets/javascripts/components/containers/follow_form_container.jsx +++ b/app/assets/javascripts/components/features/ui/containers/follow_form_container.jsx @@ -1,6 +1,6 @@ import { connect } from 'react-redux'; import FollowForm from '../components/follow_form'; -import { changeFollow, submitFollow } from '../actions/follow'; +import { changeFollow, submitFollow } from '../../../actions/follow'; const mapStateToProps = function (state, props) { return { diff --git a/app/assets/javascripts/components/containers/navigation_container.jsx b/app/assets/javascripts/components/features/ui/containers/navigation_container.jsx index 4aeea4c37..4aeea4c37 100644 --- a/app/assets/javascripts/components/containers/navigation_container.jsx +++ b/app/assets/javascripts/components/features/ui/containers/navigation_container.jsx diff --git a/app/assets/javascripts/components/containers/notifications_container.jsx b/app/assets/javascripts/components/features/ui/containers/notifications_container.jsx index 68173b34e..2db1603fc 100644 --- a/app/assets/javascripts/components/containers/notifications_container.jsx +++ b/app/assets/javascripts/components/features/ui/containers/notifications_container.jsx @@ -1,6 +1,6 @@ import { connect } from 'react-redux'; import { NotificationStack } from 'react-notification'; -import { dismissNotification } from '../actions/notifications'; +import { dismissNotification } from '../../../actions/notifications'; const mapStateToProps = (state, props) => { return { diff --git a/app/assets/javascripts/components/containers/status_list_container.jsx b/app/assets/javascripts/components/features/ui/containers/status_list_container.jsx index a4fba95e1..4ea599fc0 100644 --- a/app/assets/javascripts/components/containers/status_list_container.jsx +++ b/app/assets/javascripts/components/features/ui/containers/status_list_container.jsx @@ -1,8 +1,8 @@ import { connect } from 'react-redux'; -import StatusList from '../components/status_list'; -import { replyCompose } from '../actions/compose'; -import { reblog, favourite } from '../actions/interactions'; -import { selectStatus } from '../reducers/timelines'; +import StatusList from '../../../components/status_list'; +import { replyCompose } from '../../../actions/compose'; +import { reblog, favourite } from '../../../actions/interactions'; +import { selectStatus } from '../../../reducers/timelines'; const mapStateToProps = function (state, props) { return { diff --git a/app/assets/javascripts/components/containers/upload_form_container.jsx b/app/assets/javascripts/components/features/ui/containers/upload_form_container.jsx index b168e8187..6554f944f 100644 --- a/app/assets/javascripts/components/containers/upload_form_container.jsx +++ b/app/assets/javascripts/components/features/ui/containers/upload_form_container.jsx @@ -1,6 +1,6 @@ import { connect } from 'react-redux'; import UploadForm from '../components/upload_form'; -import { uploadCompose, undoUploadCompose } from '../actions/compose'; +import { uploadCompose, undoUploadCompose } from '../../../actions/compose'; const mapStateToProps = function (state, props) { return { diff --git a/app/assets/javascripts/components/features/ui/index.jsx b/app/assets/javascripts/components/features/ui/index.jsx new file mode 100644 index 000000000..fbfa361f2 --- /dev/null +++ b/app/assets/javascripts/components/features/ui/index.jsx @@ -0,0 +1,56 @@ +import ColumnsArea from './components/columns_area'; +import Column from './components/column'; +import Drawer from './components/drawer'; +import ComposeFormContainer from './containers/compose_form_container'; +import FollowFormContainer from './containers/follow_form_container'; +import UploadFormContainer from './containers/upload_form_container'; +import StatusListContainer from './containers/status_list_container'; +import NotificationsContainer from './containers/notifications_container'; +import NavigationContainer from './containers/navigation_container'; +import PureRenderMixin from 'react-addons-pure-render-mixin'; +import LoadingBar from 'react-redux-loading-bar'; + +const UI = React.createClass({ + + propTypes: { + router: React.PropTypes.object + }, + + mixins: [PureRenderMixin], + + render () { + return ( + <div style={{ flex: '0 0 auto', display: 'flex', width: '100%', height: '100%', background: '#1a1c23' }}> + <Drawer> + <div style={{ flex: '1 1 auto' }}> + <NavigationContainer /> + <ComposeFormContainer /> + <UploadFormContainer /> + </div> + + <FollowFormContainer /> + </Drawer> + + <ColumnsArea> + <Column icon='home' heading='Home'> + <StatusListContainer type='home' /> + </Column> + + <Column icon='at' heading='Mentions'> + <StatusListContainer type='mentions' /> + </Column> + + <Column> + {this.props.children} + </Column> + </ColumnsArea> + + <NotificationsContainer /> + <LoadingBar style={{ backgroundColor: '#2b90d9', left: '0', top: '0' }} /> + </div> + ); + } + +}); + +export default UI; diff --git a/app/assets/javascripts/components/reducers/compose.jsx b/app/assets/javascripts/components/reducers/compose.jsx index c0d9f4ff2..688c494c0 100644 --- a/app/assets/javascripts/components/reducers/compose.jsx +++ b/app/assets/javascripts/components/reducers/compose.jsx @@ -1,4 +1,16 @@ -import * as constants from '../actions/compose'; +import { + COMPOSE_CHANGE, + COMPOSE_REPLY, + COMPOSE_REPLY_CANCEL, + COMPOSE_SUBMIT_REQUEST, + COMPOSE_SUBMIT_SUCCESS, + COMPOSE_SUBMIT_FAIL, + COMPOSE_UPLOAD_REQUEST, + COMPOSE_UPLOAD_SUCCESS, + COMPOSE_UPLOAD_FAIL, + COMPOSE_UPLOAD_UNDO, + COMPOSE_UPLOAD_PROGRESS +} from '../actions/compose'; import { TIMELINE_DELETE } from '../actions/timelines'; import Immutable from 'immutable'; @@ -13,41 +25,41 @@ const initialState = Immutable.Map({ export default function compose(state = initialState, action) { switch(action.type) { - case constants.COMPOSE_CHANGE: + case COMPOSE_CHANGE: return state.set('text', action.text); - case constants.COMPOSE_REPLY: + case COMPOSE_REPLY: return state.withMutations(map => { map.set('in_reply_to', action.status.get('id')); map.set('text', `@${action.status.getIn(['account', 'acct'])} `); }); - case constants.COMPOSE_REPLY_CANCEL: + case COMPOSE_REPLY_CANCEL: return state.withMutations(map => { map.set('in_reply_to', null); map.set('text', ''); }); - case constants.COMPOSE_SUBMIT_REQUEST: + case COMPOSE_SUBMIT_REQUEST: return state.set('is_submitting', true); - case constants.COMPOSE_SUBMIT_SUCCESS: + case COMPOSE_SUBMIT_SUCCESS: return state.withMutations(map => { map.set('text', ''); map.set('is_submitting', false); map.set('in_reply_to', null); map.update('media_attachments', list => list.clear()); }); - case constants.COMPOSE_SUBMIT_FAIL: + case COMPOSE_SUBMIT_FAIL: return state.set('is_submitting', false); - case constants.COMPOSE_UPLOAD_REQUEST: + case COMPOSE_UPLOAD_REQUEST: return state.set('is_uploading', true); - case constants.COMPOSE_UPLOAD_SUCCESS: + case COMPOSE_UPLOAD_SUCCESS: return state.withMutations(map => { map.update('media_attachments', list => list.push(Immutable.fromJS(action.media))); map.set('is_uploading', false); }); - case constants.COMPOSE_UPLOAD_FAIL: + case COMPOSE_UPLOAD_FAIL: return state.set('is_uploading', false); - case constants.COMPOSE_UPLOAD_UNDO: + case COMPOSE_UPLOAD_UNDO: return state.update('media_attachments', list => list.filterNot(item => item.get('id') === action.media_id)); - case constants.COMPOSE_UPLOAD_PROGRESS: + case COMPOSE_UPLOAD_PROGRESS: return state.set('progress', Math.round((action.loaded / action.total) * 100)); case TIMELINE_DELETE: if (action.id === state.get('in_reply_to')) { diff --git a/app/assets/javascripts/components/reducers/follow.jsx b/app/assets/javascripts/components/reducers/follow.jsx index 838f12259..e1dc293c6 100644 --- a/app/assets/javascripts/components/reducers/follow.jsx +++ b/app/assets/javascripts/components/reducers/follow.jsx @@ -1,22 +1,27 @@ -import * as constants from '../actions/follow'; -import Immutable from 'immutable'; +import { + FOLLOW_CHANGE, + FOLLOW_SUBMIT_REQUEST, + FOLLOW_SUBMIT_SUCCESS, + FOLLOW_SUBMIT_FAIL +} from '../actions/follow'; +import Immutable from 'immutable'; const initialState = Immutable.Map({ text: '', is_submitting: false }); -export default function compose(state = initialState, action) { +export default function follow(state = initialState, action) { switch(action.type) { - case constants.FOLLOW_CHANGE: + case FOLLOW_CHANGE: return state.set('text', action.text); - case constants.FOLLOW_SUBMIT_REQUEST: + case FOLLOW_SUBMIT_REQUEST: return state.set('is_submitting', true); - case constants.FOLLOW_SUBMIT_SUCCESS: + case FOLLOW_SUBMIT_SUCCESS: return state.withMutations(map => { map.set('text', '').set('is_submitting', false); }); - case constants.FOLLOW_SUBMIT_FAIL: + case FOLLOW_SUBMIT_FAIL: return state.set('is_submitting', false); default: return state; diff --git a/app/assets/javascripts/components/reducers/index.jsx b/app/assets/javascripts/components/reducers/index.jsx index 6d275654a..da9ab1a21 100644 --- a/app/assets/javascripts/components/reducers/index.jsx +++ b/app/assets/javascripts/components/reducers/index.jsx @@ -1,14 +1,16 @@ -import { combineReducers } from 'redux-immutable'; -import timelines from './timelines'; -import meta from './meta'; -import compose from './compose'; -import follow from './follow'; -import notifications from './notifications'; +import { combineReducers } from 'redux-immutable'; +import timelines from './timelines'; +import meta from './meta'; +import compose from './compose'; +import follow from './follow'; +import notifications from './notifications'; +import { loadingBarReducer } from 'react-redux-loading-bar'; export default combineReducers({ timelines, meta, compose, follow, - notifications + notifications, + loadingBar: loadingBarReducer, }); diff --git a/app/assets/javascripts/components/reducers/notifications.jsx b/app/assets/javascripts/components/reducers/notifications.jsx index bdd2de993..694d9ff4b 100644 --- a/app/assets/javascripts/components/reducers/notifications.jsx +++ b/app/assets/javascripts/components/reducers/notifications.jsx @@ -24,7 +24,7 @@ function notificationFromError(state, error) { return state.push(n); }; -export default function meta(state = initialState, action) { +export default function notifications(state = initialState, action) { switch(action.type) { case COMPOSE_SUBMIT_FAIL: case COMPOSE_UPLOAD_FAIL: diff --git a/app/assets/javascripts/components/reducers/timelines.jsx b/app/assets/javascripts/components/reducers/timelines.jsx index 04a49e16d..2bc4e6eb6 100644 --- a/app/assets/javascripts/components/reducers/timelines.jsx +++ b/app/assets/javascripts/components/reducers/timelines.jsx @@ -45,7 +45,7 @@ export function selectStatus(state, id) { return status; }; -function statusToMaps(state, status) { +function normalizeStatus(state, status) { // Separate account let account = status.get('account'); status = status.set('account', account.get('id')); @@ -55,7 +55,7 @@ function statusToMaps(state, status) { if (reblog !== null) { status = status.set('reblog', reblog.get('id')); - state = statusToMaps(state, reblog); + state = normalizeStatus(state, reblog); } // Replies @@ -80,26 +80,26 @@ function statusToMaps(state, status) { }); }; -function timelineToMaps(state, timeline, statuses) { +function normalizeTimeline(state, timeline, statuses) { statuses.forEach((status, i) => { - state = statusToMaps(state, status); + state = normalizeStatus(state, status); state = state.setIn([timeline, i], status.get('id')); }); return state; }; -function accountTimelineToMaps(state, accountId, statuses) { +function normalizeAccountTimeline(state, accountId, statuses) { statuses.forEach((status, i) => { - state = statusToMaps(state, status); + state = normalizeStatus(state, status); state = state.updateIn(['accounts_timelines', accountId], Immutable.List(), list => list.set(i, status.get('id'))); }); return state; }; -function updateTimelineWithMaps(state, timeline, status) { - state = statusToMaps(state, status); +function updateTimeline(state, timeline, status) { + state = normalizeStatus(state, status); state = state.update(timeline, list => list.unshift(status.get('id'))); state = state.updateIn(['accounts_timelines', status.getIn(['account', 'id'])], Immutable.List(), list => list.unshift(status.get('id'))); @@ -114,20 +114,20 @@ function deleteStatus(state, id) { return state.deleteIn(['statuses', id]); }; -function accountToMaps(state, account) { +function normalizeAccount(state, account) { return state.setIn(['accounts', account.get('id')], account); }; -function contextToMaps(state, status, ancestors, descendants) { - state = statusToMaps(state, status); +function normalizeContext(state, status, ancestors, descendants) { + state = normalizeStatus(state, status); let ancestorsIds = ancestors.map(ancestor => { - state = statusToMaps(state, ancestor); + state = normalizeStatus(state, ancestor); return ancestor.get('id'); }).toOrderedSet(); let descendantsIds = descendants.map(descendant => { - state = statusToMaps(state, descendant); + state = normalizeStatus(state, descendant); return descendant.get('id'); }).toOrderedSet(); @@ -140,14 +140,14 @@ function contextToMaps(state, status, ancestors, descendants) { export default function timelines(state = initialState, action) { switch(action.type) { case TIMELINE_SET: - return timelineToMaps(state, action.timeline, Immutable.fromJS(action.statuses)); + return normalizeTimeline(state, action.timeline, Immutable.fromJS(action.statuses)); case TIMELINE_UPDATE: - return updateTimelineWithMaps(state, action.timeline, Immutable.fromJS(action.status)); + return updateTimeline(state, action.timeline, Immutable.fromJS(action.status)); case TIMELINE_DELETE: return deleteStatus(state, action.id); case REBLOG_SUCCESS: case FAVOURITE_SUCCESS: - return statusToMaps(state, Immutable.fromJS(action.response)); + return normalizeStatus(state, Immutable.fromJS(action.response)); case ACCOUNT_SET_SELF: return state.withMutations(map => { map.setIn(['accounts', action.account.id], Immutable.fromJS(action.account)); @@ -157,11 +157,11 @@ export default function timelines(state = initialState, action) { case FOLLOW_SUBMIT_SUCCESS: case ACCOUNT_FOLLOW_SUCCESS: case ACCOUNT_UNFOLLOW_SUCCESS: - return accountToMaps(state, Immutable.fromJS(action.account)); + return normalizeAccount(state, Immutable.fromJS(action.account)); case STATUS_FETCH_SUCCESS: - return contextToMaps(state, Immutable.fromJS(action.status), Immutable.fromJS(action.context.ancestors), Immutable.fromJS(action.context.descendants)); + return normalizeContext(state, Immutable.fromJS(action.status), Immutable.fromJS(action.context.ancestors), Immutable.fromJS(action.context.descendants)); case ACCOUNT_TIMELINE_FETCH_SUCCESS: - return accountTimelineToMaps(state, action.id, Immutable.fromJS(action.statuses)); + return normalizeAccountTimeline(state, action.id, Immutable.fromJS(action.statuses)); default: return state; } diff --git a/app/assets/javascripts/components/store/configureStore.jsx b/app/assets/javascripts/components/store/configureStore.jsx index 1f2fcf2cf..89f498217 100644 --- a/app/assets/javascripts/components/store/configureStore.jsx +++ b/app/assets/javascripts/components/store/configureStore.jsx @@ -1,7 +1,10 @@ import { createStore, applyMiddleware, compose } from 'redux'; -import thunk from 'redux-thunk'; -import appReducer from '../reducers'; +import thunk from 'redux-thunk'; +import appReducer from '../reducers'; +import { loadingBarMiddleware } from 'react-redux-loading-bar'; export default function configureStore(initialState) { - return createStore(appReducer, initialState, compose(applyMiddleware(thunk), window.devToolsExtension ? window.devToolsExtension() : f => f)); -} + return createStore(appReducer, initialState, compose(applyMiddleware(thunk, loadingBarMiddleware({ + promiseTypeSuffixes: ['REQUEST', 'SUCCESS', 'FAIL'], + })), window.devToolsExtension ? window.devToolsExtension() : f => f)); +}; diff --git a/app/views/home/index.html.haml b/app/views/home/index.html.haml index 34028462c..f06c26e9d 100644 --- a/app/views/home/index.html.haml +++ b/app/views/home/index.html.haml @@ -1 +1 @@ -= react_component 'Root', default_props, class: 'app-holder', prerender: false += react_component 'Mastodon', default_props, class: 'app-holder', prerender: false diff --git a/package.json b/package.json index 5234a37f0..f8df13a2f 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "react-immutable-proptypes": "^2.1.0", "react-notification": "^6.1.1", "react-redux": "^4.4.5", + "react-redux-loading-bar": "^2.3.3", "react-router": "^2.8.0", "redux": "^3.5.2", "redux-immutable": "^3.0.8", |