Send initial state in a <script type="application/json"> tag (#1806)

pull/1764/head^2
Joachim Viide 2017-04-15 03:32:42 +03:00 committed by Eugen
parent 9240ca6cef
commit ef879a8839
9 changed files with 25 additions and 17 deletions

View File

@ -61,8 +61,8 @@ import { hydrateStore } from '../actions/store';
import createStream from '../stream'; import createStream from '../stream';
const store = configureStore(); const store = configureStore();
const initialState = JSON.parse(document.getElementById("initial-state").textContent);
store.dispatch(hydrateStore(window.INITIAL_STATE)); store.dispatch(hydrateStore(initialState));
const browserHistory = useRouterHistory(createBrowserHistory)({ const browserHistory = useRouterHistory(createBrowserHistory)({
basename: '/web' basename: '/web'
@ -95,9 +95,10 @@ const Mastodon = React.createClass({
componentDidMount() { componentDidMount() {
const { locale } = this.props; const { locale } = this.props;
const streamingAPIBaseURL = store.getState().getIn(['meta', 'streaming_api_base_url']);
const accessToken = store.getState().getIn(['meta', 'access_token']); const accessToken = store.getState().getIn(['meta', 'access_token']);
this.subscription = createStream(accessToken, 'user', { this.subscription = createStream(streamingAPIBaseURL, accessToken, 'user', {
connected () { connected () {
store.dispatch(connectTimeline('home')); store.dispatch(connectTimeline('home'));

View File

@ -19,6 +19,7 @@ const messages = defineMessages({
const mapStateToProps = state => ({ const mapStateToProps = state => ({
hasUnread: state.getIn(['timelines', 'community', 'unread']) > 0, hasUnread: state.getIn(['timelines', 'community', 'unread']) > 0,
streamingAPIBaseURL: state.getIn(['meta', 'streaming_api_base_url']),
accessToken: state.getIn(['meta', 'access_token']) accessToken: state.getIn(['meta', 'access_token'])
}); });
@ -29,6 +30,7 @@ const CommunityTimeline = React.createClass({
propTypes: { propTypes: {
dispatch: React.PropTypes.func.isRequired, dispatch: React.PropTypes.func.isRequired,
intl: React.PropTypes.object.isRequired, intl: React.PropTypes.object.isRequired,
streamingAPIBaseURL: React.PropTypes.string.isRequired,
accessToken: React.PropTypes.string.isRequired, accessToken: React.PropTypes.string.isRequired,
hasUnread: React.PropTypes.bool hasUnread: React.PropTypes.bool
}, },
@ -36,7 +38,7 @@ const CommunityTimeline = React.createClass({
mixins: [PureRenderMixin], mixins: [PureRenderMixin],
componentDidMount () { componentDidMount () {
const { dispatch, accessToken } = this.props; const { dispatch, streamingAPIBaseURL, accessToken } = this.props;
dispatch(refreshTimeline('community')); dispatch(refreshTimeline('community'));
@ -44,7 +46,7 @@ const CommunityTimeline = React.createClass({
return; return;
} }
subscription = createStream(accessToken, 'public:local', { subscription = createStream(streamingAPIBaseURL, accessToken, 'public:local', {
connected () { connected () {
dispatch(connectTimeline('community')); dispatch(connectTimeline('community'));

View File

@ -13,6 +13,7 @@ import createStream from '../../stream';
const mapStateToProps = state => ({ const mapStateToProps = state => ({
hasUnread: state.getIn(['timelines', 'tag', 'unread']) > 0, hasUnread: state.getIn(['timelines', 'tag', 'unread']) > 0,
streamingAPIBaseURL: state.getIn(['meta', 'streaming_api_base_url']),
accessToken: state.getIn(['meta', 'access_token']) accessToken: state.getIn(['meta', 'access_token'])
}); });
@ -21,6 +22,7 @@ const HashtagTimeline = React.createClass({
propTypes: { propTypes: {
params: React.PropTypes.object.isRequired, params: React.PropTypes.object.isRequired,
dispatch: React.PropTypes.func.isRequired, dispatch: React.PropTypes.func.isRequired,
streamingAPIBaseURL: React.PropTypes.string.isRequired,
accessToken: React.PropTypes.string.isRequired, accessToken: React.PropTypes.string.isRequired,
hasUnread: React.PropTypes.bool hasUnread: React.PropTypes.bool
}, },
@ -28,9 +30,9 @@ const HashtagTimeline = React.createClass({
mixins: [PureRenderMixin], mixins: [PureRenderMixin],
_subscribe (dispatch, id) { _subscribe (dispatch, id) {
const { accessToken } = this.props; const { streamingAPIBaseURL, accessToken } = this.props;
this.subscription = createStream(accessToken, `hashtag&tag=${id}`, { this.subscription = createStream(streamingAPIBaseURL, accessToken, `hashtag&tag=${id}`, {
received (data) { received (data) {
switch(data.event) { switch(data.event) {

View File

@ -19,6 +19,7 @@ const messages = defineMessages({
const mapStateToProps = state => ({ const mapStateToProps = state => ({
hasUnread: state.getIn(['timelines', 'public', 'unread']) > 0, hasUnread: state.getIn(['timelines', 'public', 'unread']) > 0,
streamingAPIBaseURL: state.getIn(['meta', 'streaming_api_base_url']),
accessToken: state.getIn(['meta', 'access_token']) accessToken: state.getIn(['meta', 'access_token'])
}); });
@ -29,6 +30,7 @@ const PublicTimeline = React.createClass({
propTypes: { propTypes: {
dispatch: React.PropTypes.func.isRequired, dispatch: React.PropTypes.func.isRequired,
intl: React.PropTypes.object.isRequired, intl: React.PropTypes.object.isRequired,
streamingAPIBaseURL: React.PropTypes.string.isRequired,
accessToken: React.PropTypes.string.isRequired, accessToken: React.PropTypes.string.isRequired,
hasUnread: React.PropTypes.bool hasUnread: React.PropTypes.bool
}, },
@ -36,7 +38,7 @@ const PublicTimeline = React.createClass({
mixins: [PureRenderMixin], mixins: [PureRenderMixin],
componentDidMount () { componentDidMount () {
const { dispatch, accessToken } = this.props; const { dispatch, streamingAPIBaseURL, accessToken } = this.props;
dispatch(refreshTimeline('public')); dispatch(refreshTimeline('public'));
@ -44,7 +46,7 @@ const PublicTimeline = React.createClass({
return; return;
} }
subscription = createStream(accessToken, 'public', { subscription = createStream(streamingAPIBaseURL, accessToken, 'public', {
connected () { connected () {
dispatch(connectTimeline('public')); dispatch(connectTimeline('public'));

View File

@ -2,6 +2,7 @@ import { STORE_HYDRATE } from '../actions/store';
import Immutable from 'immutable'; import Immutable from 'immutable';
const initialState = Immutable.Map({ const initialState = Immutable.Map({
streaming_api_base_url: null,
access_token: null, access_token: null,
me: null me: null
}); });

View File

@ -10,8 +10,8 @@ const createWebSocketURL = (url) => {
return a.href; return a.href;
}; };
export default function getStream(accessToken, stream, { connected, received, disconnected, reconnected }) { export default function getStream(streamingAPIBaseURL, accessToken, stream, { connected, received, disconnected, reconnected }) {
const ws = new WebSocketClient(`${createWebSocketURL(STREAMING_API_BASE_URL)}/api/v1/streaming/?access_token=${accessToken}&stream=${stream}`); const ws = new WebSocketClient(`${createWebSocketURL(streamingAPIBaseURL)}/api/v1/streaming/?access_token=${accessToken}&stream=${stream}`);
ws.onopen = connected; ws.onopen = connected;
ws.onmessage = e => received(JSON.parse(e.data)); ws.onmessage = e => received(JSON.parse(e.data));

View File

@ -4,9 +4,10 @@ class HomeController < ApplicationController
before_action :authenticate_user! before_action :authenticate_user!
def index def index
@body_classes = 'app-body' @body_classes = 'app-body'
@token = find_or_create_access_token.token @token = find_or_create_access_token.token
@web_settings = Web::Setting.find_by(user: current_user)&.data || {} @web_settings = Web::Setting.find_by(user: current_user)&.data || {}
@streaming_api_base_url = Rails.configuration.x.streaming_api_base_url
end end
private private

View File

@ -1,7 +1,5 @@
- content_for :header_tags do - content_for :header_tags do
:javascript %script#initial-state{:type => 'application/json'}!= json_escape(render(file: 'home/initial_state', formats: :json))
window.STREAMING_API_BASE_URL = '#{Rails.configuration.x.streaming_api_base_url}';
window.INITIAL_STATE = #{json_escape(render(file: 'home/initial_state', formats: :json))}
= javascript_include_tag 'application', integrity: true = javascript_include_tag 'application', integrity: true

View File

@ -2,6 +2,7 @@ object false
node(:meta) do node(:meta) do
{ {
streaming_api_base_url: @streaming_api_base_url,
access_token: @token, access_token: @token,
locale: I18n.locale, locale: I18n.locale,
me: current_account.id, me: current_account.id,