You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

98 lines
2.9 KiB

  1. import PropTypes from 'prop-types';
  2. import React from 'react';
  3. import { Helmet } from 'react-helmet';
  4. import { IntlProvider, addLocaleData } from 'react-intl';
  5. import { Provider as ReduxProvider } from 'react-redux';
  6. import { BrowserRouter, Route } from 'react-router-dom';
  7. import { ScrollContext } from 'react-router-scroll-4';
  8. import configureStore from 'mastodon/store/configureStore';
  9. import UI from 'mastodon/features/ui';
  10. import { fetchCustomEmojis } from 'mastodon/actions/custom_emojis';
  11. import { hydrateStore } from 'mastodon/actions/store';
  12. import { connectUserStream } from 'mastodon/actions/streaming';
  13. import ErrorBoundary from 'mastodon/components/error_boundary';
  14. import initialState, { title as siteTitle } from 'mastodon/initial_state';
  15. import { getLocale } from 'mastodon/locales';
  16. const { localeData, messages } = getLocale();
  17. addLocaleData(localeData);
  18. const title = process.env.NODE_ENV === 'production' ? siteTitle : `${siteTitle} (Dev)`;
  19. export const store = configureStore();
  20. const hydrateAction = hydrateStore(initialState);
  21. store.dispatch(hydrateAction);
  22. if (initialState.meta.me) {
  23. store.dispatch(fetchCustomEmojis());
  24. }
  25. const createIdentityContext = state => ({
  26. signedIn: !!state.meta.me,
  27. accountId: state.meta.me,
  28. disabledAccountId: state.meta.disabled_account_id,
  29. accessToken: state.meta.access_token,
  30. permissions: state.role ? state.role.permissions : 0,
  31. });
  32. export default class Mastodon extends React.PureComponent {
  33. static propTypes = {
  34. locale: PropTypes.string.isRequired,
  35. };
  36. static childContextTypes = {
  37. identity: PropTypes.shape({
  38. signedIn: PropTypes.bool.isRequired,
  39. accountId: PropTypes.string,
  40. disabledAccountId: PropTypes.string,
  41. accessToken: PropTypes.string,
  42. }).isRequired,
  43. };
  44. identity = createIdentityContext(initialState);
  45. getChildContext() {
  46. return {
  47. identity: this.identity,
  48. };
  49. }
  50. componentDidMount() {
  51. if (this.identity.signedIn) {
  52. this.disconnect = store.dispatch(connectUserStream());
  53. }
  54. }
  55. componentWillUnmount () {
  56. if (this.disconnect) {
  57. this.disconnect();
  58. this.disconnect = null;
  59. }
  60. }
  61. shouldUpdateScroll (prevRouterProps, { location }) {
  62. return !(location.state?.mastodonModalKey && location.state?.mastodonModalKey !== prevRouterProps?.location?.state?.mastodonModalKey);
  63. }
  64. render () {
  65. const { locale } = this.props;
  66. return (
  67. <IntlProvider locale={locale} messages={messages}>
  68. <ReduxProvider store={store}>
  69. <ErrorBoundary>
  70. <BrowserRouter>
  71. <ScrollContext shouldUpdateScroll={this.shouldUpdateScroll}>
  72. <Route path='/' component={UI} />
  73. </ScrollContext>
  74. </BrowserRouter>
  75. <Helmet defaultTitle={title} titleTemplate={`%s - ${title}`} />
  76. </ErrorBoundary>
  77. </ReduxProvider>
  78. </IntlProvider>
  79. );
  80. }
  81. }