Improve initialState loading
This commit is contained in:
		| @@ -1,8 +1,6 @@ | ||||
| import api, { getLinks } from '../api' | ||||
| import Immutable from 'immutable'; | ||||
|  | ||||
| export const ACCOUNT_SET_SELF = 'ACCOUNT_SET_SELF'; | ||||
|  | ||||
| export const ACCOUNT_FETCH_REQUEST = 'ACCOUNT_FETCH_REQUEST'; | ||||
| export const ACCOUNT_FETCH_SUCCESS = 'ACCOUNT_FETCH_SUCCESS'; | ||||
| export const ACCOUNT_FETCH_FAIL    = 'ACCOUNT_FETCH_FAIL'; | ||||
| @@ -67,13 +65,6 @@ export const FOLLOW_REQUEST_REJECT_REQUEST = 'FOLLOW_REQUEST_REJECT_REQUEST'; | ||||
| export const FOLLOW_REQUEST_REJECT_SUCCESS = 'FOLLOW_REQUEST_REJECT_SUCCESS'; | ||||
| export const FOLLOW_REQUEST_REJECT_FAIL    = 'FOLLOW_REQUEST_REJECT_FAIL'; | ||||
|  | ||||
| export function setAccountSelf(account) { | ||||
|   return { | ||||
|     type: ACCOUNT_SET_SELF, | ||||
|     account | ||||
|   }; | ||||
| }; | ||||
|  | ||||
| export function fetchAccount(id) { | ||||
|   return (dispatch, getState) => { | ||||
|     dispatch(fetchAccountRequest(id)); | ||||
|   | ||||
| @@ -1,8 +0,0 @@ | ||||
| export const ACCESS_TOKEN_SET = 'ACCESS_TOKEN_SET'; | ||||
|  | ||||
| export function setAccessToken(token) { | ||||
|   return { | ||||
|     type: ACCESS_TOKEN_SET, | ||||
|     token: token | ||||
|   }; | ||||
| }; | ||||
							
								
								
									
										17
									
								
								app/assets/javascripts/components/actions/store.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								app/assets/javascripts/components/actions/store.jsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| import Immutable from 'immutable'; | ||||
|  | ||||
| export const STORE_HYDRATE = 'STORE_HYDRATE'; | ||||
|  | ||||
| const convertState = rawState => | ||||
|   Immutable.fromJS(rawState, (k, v) => | ||||
|     Immutable.Iterable.isIndexed(v) ? v.toList() : v.toMap().mapKeys(x => | ||||
|       Number.isNaN(x * 1) ? x : x * 1)); | ||||
|  | ||||
| export function hydrateStore(rawState) { | ||||
|   const state = convertState(rawState); | ||||
|  | ||||
|   return { | ||||
|     type: STORE_HYDRATE, | ||||
|     state | ||||
|   }; | ||||
| }; | ||||
| @@ -7,8 +7,6 @@ import { | ||||
|   refreshTimeline | ||||
| } from '../actions/timelines'; | ||||
| import { updateNotifications } from '../actions/notifications'; | ||||
| import { setAccessToken } from '../actions/meta'; | ||||
| import { setAccountSelf } from '../actions/accounts'; | ||||
| import createBrowserHistory from 'history/lib/createBrowserHistory'; | ||||
| import { | ||||
|   applyRouterMiddleware, | ||||
| @@ -44,9 +42,12 @@ import pt from 'react-intl/locale-data/pt'; | ||||
| import hu from 'react-intl/locale-data/hu'; | ||||
| import uk from 'react-intl/locale-data/uk'; | ||||
| import getMessagesForLocale from '../locales'; | ||||
| import { hydrateStore } from '../actions/store'; | ||||
|  | ||||
| const store = configureStore(); | ||||
|  | ||||
| store.dispatch(hydrateStore(window.INITIAL_STATE)); | ||||
|  | ||||
| const browserHistory = useRouterHistory(createBrowserHistory)({ | ||||
|   basename: '/web' | ||||
| }); | ||||
| @@ -56,29 +57,26 @@ addLocaleData([...en, ...de, ...es, ...fr, ...pt, ...hu, ...uk]); | ||||
| const Mastodon = React.createClass({ | ||||
|  | ||||
|   propTypes: { | ||||
|     token: React.PropTypes.string.isRequired, | ||||
|     timelines: React.PropTypes.object, | ||||
|     account: React.PropTypes.string, | ||||
|     locale: React.PropTypes.string.isRequired | ||||
|   }, | ||||
|  | ||||
|   componentWillMount() { | ||||
|     const { token, account, locale } = this.props; | ||||
|  | ||||
|     store.dispatch(setAccessToken(token)); | ||||
|     store.dispatch(setAccountSelf(JSON.parse(account))); | ||||
|     const { locale } = this.props; | ||||
|  | ||||
|     if (typeof App !== 'undefined') { | ||||
|       this.subscription = App.cable.subscriptions.create('TimelineChannel', { | ||||
|  | ||||
|         received (data) { | ||||
|           switch(data.type) { | ||||
|             case 'update': | ||||
|               return store.dispatch(updateTimeline(data.timeline, JSON.parse(data.message))); | ||||
|             case 'delete': | ||||
|               return store.dispatch(deleteFromTimelines(data.id)); | ||||
|             case 'notification': | ||||
|               return store.dispatch(updateNotifications(JSON.parse(data.message), getMessagesForLocale(locale), locale)); | ||||
|           case 'update': | ||||
|             store.dispatch(updateTimeline(data.timeline, JSON.parse(data.message))); | ||||
|             break; | ||||
|           case 'delete': | ||||
|             store.dispatch(deleteFromTimelines(data.id)); | ||||
|             break; | ||||
|           case 'notification': | ||||
|             store.dispatch(updateNotifications(JSON.parse(data.message), getMessagesForLocale(locale), locale)); | ||||
|             break; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -1,8 +1,10 @@ | ||||
| import { connect }   from 'react-redux'; | ||||
| import NavigationBar from '../components/navigation_bar'; | ||||
|  | ||||
| const mapStateToProps = (state, props) => ({ | ||||
|   account: state.getIn(['accounts', state.getIn(['meta', 'me'])]) | ||||
| }); | ||||
| const mapStateToProps = (state, props) => { | ||||
|   return { | ||||
|     account: state.getIn(['accounts', state.getIn(['meta', 'me'])]) | ||||
|   }; | ||||
| }; | ||||
|  | ||||
| export default connect(mapStateToProps)(NavigationBar); | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| import { | ||||
|   ACCOUNT_SET_SELF, | ||||
|   ACCOUNT_FETCH_SUCCESS, | ||||
|   FOLLOWERS_FETCH_SUCCESS, | ||||
|   FOLLOWERS_EXPAND_SUCCESS, | ||||
| @@ -33,6 +32,7 @@ import { | ||||
|   NOTIFICATIONS_REFRESH_SUCCESS, | ||||
|   NOTIFICATIONS_EXPAND_SUCCESS | ||||
| } from '../actions/notifications'; | ||||
| import { STORE_HYDRATE } from '../actions/store'; | ||||
| import Immutable from 'immutable'; | ||||
|  | ||||
| const normalizeAccount = (state, account) => state.set(account.id, Immutable.fromJS(account)); | ||||
| @@ -67,38 +67,39 @@ const initialState = Immutable.Map(); | ||||
|  | ||||
| export default function accounts(state = initialState, action) { | ||||
|   switch(action.type) { | ||||
|     case ACCOUNT_SET_SELF: | ||||
|     case ACCOUNT_FETCH_SUCCESS: | ||||
|     case NOTIFICATIONS_UPDATE: | ||||
|       return normalizeAccount(state, action.account); | ||||
|     case FOLLOWERS_FETCH_SUCCESS: | ||||
|     case FOLLOWERS_EXPAND_SUCCESS: | ||||
|     case FOLLOWING_FETCH_SUCCESS: | ||||
|     case FOLLOWING_EXPAND_SUCCESS: | ||||
|     case REBLOGS_FETCH_SUCCESS: | ||||
|     case FAVOURITES_FETCH_SUCCESS: | ||||
|     case COMPOSE_SUGGESTIONS_READY: | ||||
|     case SEARCH_SUGGESTIONS_READY: | ||||
|     case FOLLOW_REQUESTS_FETCH_SUCCESS: | ||||
|       return normalizeAccounts(state, action.accounts); | ||||
|     case NOTIFICATIONS_REFRESH_SUCCESS: | ||||
|     case NOTIFICATIONS_EXPAND_SUCCESS: | ||||
|       return normalizeAccountsFromStatuses(normalizeAccounts(state, action.accounts), action.statuses); | ||||
|     case TIMELINE_REFRESH_SUCCESS: | ||||
|     case TIMELINE_EXPAND_SUCCESS: | ||||
|     case ACCOUNT_TIMELINE_FETCH_SUCCESS: | ||||
|     case ACCOUNT_TIMELINE_EXPAND_SUCCESS: | ||||
|     case CONTEXT_FETCH_SUCCESS: | ||||
|       return normalizeAccountsFromStatuses(state, action.statuses); | ||||
|     case REBLOG_SUCCESS: | ||||
|     case FAVOURITE_SUCCESS: | ||||
|     case UNREBLOG_SUCCESS: | ||||
|     case UNFAVOURITE_SUCCESS: | ||||
|       return normalizeAccountFromStatus(state, action.response); | ||||
|     case TIMELINE_UPDATE: | ||||
|     case STATUS_FETCH_SUCCESS: | ||||
|       return normalizeAccountFromStatus(state, action.status); | ||||
|     default: | ||||
|       return state; | ||||
|   case STORE_HYDRATE: | ||||
|     return state.merge(action.state.get('accounts')); | ||||
|   case ACCOUNT_FETCH_SUCCESS: | ||||
|   case NOTIFICATIONS_UPDATE: | ||||
|     return normalizeAccount(state, action.account); | ||||
|   case FOLLOWERS_FETCH_SUCCESS: | ||||
|   case FOLLOWERS_EXPAND_SUCCESS: | ||||
|   case FOLLOWING_FETCH_SUCCESS: | ||||
|   case FOLLOWING_EXPAND_SUCCESS: | ||||
|   case REBLOGS_FETCH_SUCCESS: | ||||
|   case FAVOURITES_FETCH_SUCCESS: | ||||
|   case COMPOSE_SUGGESTIONS_READY: | ||||
|   case SEARCH_SUGGESTIONS_READY: | ||||
|   case FOLLOW_REQUESTS_FETCH_SUCCESS: | ||||
|     return normalizeAccounts(state, action.accounts); | ||||
|   case NOTIFICATIONS_REFRESH_SUCCESS: | ||||
|   case NOTIFICATIONS_EXPAND_SUCCESS: | ||||
|     return normalizeAccountsFromStatuses(normalizeAccounts(state, action.accounts), action.statuses); | ||||
|   case TIMELINE_REFRESH_SUCCESS: | ||||
|   case TIMELINE_EXPAND_SUCCESS: | ||||
|   case ACCOUNT_TIMELINE_FETCH_SUCCESS: | ||||
|   case ACCOUNT_TIMELINE_EXPAND_SUCCESS: | ||||
|   case CONTEXT_FETCH_SUCCESS: | ||||
|     return normalizeAccountsFromStatuses(state, action.statuses); | ||||
|   case REBLOG_SUCCESS: | ||||
|   case FAVOURITE_SUCCESS: | ||||
|   case UNREBLOG_SUCCESS: | ||||
|   case UNFAVOURITE_SUCCESS: | ||||
|     return normalizeAccountFromStatus(state, action.response); | ||||
|   case TIMELINE_UPDATE: | ||||
|   case STATUS_FETCH_SUCCESS: | ||||
|     return normalizeAccountFromStatus(state, action.status); | ||||
|   default: | ||||
|     return state; | ||||
|   } | ||||
| }; | ||||
|   | ||||
| @@ -21,7 +21,7 @@ import { | ||||
|   COMPOSE_LISTABILITY_CHANGE | ||||
| } from '../actions/compose'; | ||||
| import { TIMELINE_DELETE } from '../actions/timelines'; | ||||
| import { ACCOUNT_SET_SELF } from '../actions/accounts'; | ||||
| import { STORE_HYDRATE } from '../actions/store'; | ||||
| import Immutable from 'immutable'; | ||||
|  | ||||
| const initialState = Immutable.Map({ | ||||
| @@ -88,6 +88,8 @@ const insertSuggestion = (state, position, token, completion) => { | ||||
|  | ||||
| export default function compose(state = initialState, action) { | ||||
|   switch(action.type) { | ||||
|     case STORE_HYDRATE: | ||||
|       return state.merge(action.state.get('compose')); | ||||
|     case COMPOSE_MOUNT: | ||||
|       return state.set('mounted', true); | ||||
|     case COMPOSE_UNMOUNT: | ||||
| @@ -97,7 +99,7 @@ export default function compose(state = initialState, action) { | ||||
|     case COMPOSE_VISIBILITY_CHANGE: | ||||
|       return state.set('private', action.checked); | ||||
|     case COMPOSE_LISTABILITY_CHANGE: | ||||
|       return state.set('unlisted', action.checked);       | ||||
|       return state.set('unlisted', action.checked); | ||||
|     case COMPOSE_CHANGE: | ||||
|       return state.set('text', action.text); | ||||
|     case COMPOSE_REPLY: | ||||
| @@ -143,8 +145,6 @@ export default function compose(state = initialState, action) { | ||||
|       } else { | ||||
|         return state; | ||||
|       } | ||||
|     case ACCOUNT_SET_SELF: | ||||
|       return state.set('me', action.account.id).set('private', action.account.locked); | ||||
|     default: | ||||
|       return state; | ||||
|   } | ||||
|   | ||||
| @@ -1,16 +1,16 @@ | ||||
| import { ACCESS_TOKEN_SET } from '../actions/meta'; | ||||
| import { ACCOUNT_SET_SELF } from '../actions/accounts'; | ||||
| import { STORE_HYDRATE } from '../actions/store'; | ||||
| import Immutable from 'immutable'; | ||||
|  | ||||
| const initialState = Immutable.Map(); | ||||
| const initialState = Immutable.Map({ | ||||
|   access_token: null, | ||||
|   me: null | ||||
| }); | ||||
|  | ||||
| export default function meta(state = initialState, action) { | ||||
|   switch(action.type) { | ||||
|     case ACCESS_TOKEN_SET: | ||||
|       return state.set('access_token', action.token); | ||||
|     case ACCOUNT_SET_SELF: | ||||
|       return state.set('me', action.account.id); | ||||
|     default: | ||||
|       return state; | ||||
|   case STORE_HYDRATE: | ||||
|     return state.merge(action.state.get('meta')); | ||||
|   default: | ||||
|     return state; | ||||
|   } | ||||
| }; | ||||
|   | ||||
| @@ -1,11 +1,12 @@ | ||||
| import { createStore, applyMiddleware, compose } from 'redux'; | ||||
| import thunk                                     from 'redux-thunk'; | ||||
| import appReducer                                from '../reducers'; | ||||
| import { loadingBarMiddleware }                  from 'react-redux-loading-bar'; | ||||
| import errorsMiddleware                          from '../middleware/errors'; | ||||
| import thunk from 'redux-thunk'; | ||||
| import appReducer from '../reducers'; | ||||
| import { loadingBarMiddleware } from 'react-redux-loading-bar'; | ||||
| import errorsMiddleware from '../middleware/errors'; | ||||
| import Immutable from 'immutable'; | ||||
|  | ||||
| export default function configureStore(initialState) { | ||||
|   return createStore(appReducer, initialState, compose(applyMiddleware(thunk, loadingBarMiddleware({ | ||||
| export default function configureStore() { | ||||
|   return createStore(appReducer, compose(applyMiddleware(thunk, loadingBarMiddleware({ | ||||
|     promiseTypeSuffixes: ['REQUEST', 'SUCCESS', 'FAIL'], | ||||
|   }), errorsMiddleware()), window.devToolsExtension ? window.devToolsExtension() : f => f)); | ||||
| }; | ||||
|   | ||||
| @@ -3,8 +3,6 @@ | ||||
| module HomeHelper | ||||
|   def default_props | ||||
|     { | ||||
|       token: @token, | ||||
|       account: render(file: 'api/v1/accounts/show', locals: { account: current_user.account }, formats: :json), | ||||
|       locale: I18n.locale, | ||||
|     } | ||||
|   end | ||||
|   | ||||
| @@ -1,4 +1,22 @@ | ||||
| - content_for :header_tags do | ||||
|   :javascript | ||||
|     window.INITIAL_STATE = { | ||||
|       "meta": { | ||||
|         "access_token": "#{@token}", | ||||
|         "locale": "#{I18n.locale}", | ||||
|         "me": #{current_account.id} | ||||
|       }, | ||||
|  | ||||
|       "compose": { | ||||
|         "me": #{current_account.id}, | ||||
|         "private": #{current_account.locked?} | ||||
|       }, | ||||
|  | ||||
|       "accounts": { | ||||
|         #{current_account.id}: #{render(file: 'api/v1/accounts/show', locals: { account: current_user.account }, formats: :json)} | ||||
|       } | ||||
|     }; | ||||
|  | ||||
|   = javascript_include_tag 'application' | ||||
|  | ||||
| = react_component 'Mastodon', default_props, class: 'app-holder', prerender: false | ||||
|   | ||||
		Reference in New Issue
	
	Block a user