forked from fedi/mastodon
Send initial state in a <script type="application/json"> tag (#1806)
This commit is contained in:
parent
9240ca6cef
commit
ef879a8839
|
@ -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'));
|
||||||
|
|
|
@ -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'));
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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'));
|
||||||
|
|
|
@ -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
|
||||||
});
|
});
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue