mastodon.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  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. store.dispatch(fetchCustomEmojis());
  23. const createIdentityContext = state => ({
  24. signedIn: !!state.meta.me,
  25. accountId: state.meta.me,
  26. disabledAccountId: state.meta.disabled_account_id,
  27. accessToken: state.meta.access_token,
  28. permissions: state.role ? state.role.permissions : 0,
  29. });
  30. export default class Mastodon extends React.PureComponent {
  31. static propTypes = {
  32. locale: PropTypes.string.isRequired,
  33. };
  34. static childContextTypes = {
  35. identity: PropTypes.shape({
  36. signedIn: PropTypes.bool.isRequired,
  37. accountId: PropTypes.string,
  38. disabledAccountId: PropTypes.string,
  39. accessToken: PropTypes.string,
  40. }).isRequired,
  41. };
  42. identity = createIdentityContext(initialState);
  43. getChildContext() {
  44. return {
  45. identity: this.identity,
  46. };
  47. }
  48. componentDidMount() {
  49. if (this.identity.signedIn) {
  50. this.disconnect = store.dispatch(connectUserStream());
  51. }
  52. }
  53. componentWillUnmount () {
  54. if (this.disconnect) {
  55. this.disconnect();
  56. this.disconnect = null;
  57. }
  58. }
  59. shouldUpdateScroll (prevRouterProps, { location }) {
  60. return !(location.state?.mastodonModalKey && location.state?.mastodonModalKey !== prevRouterProps?.location?.state?.mastodonModalKey);
  61. }
  62. render () {
  63. const { locale } = this.props;
  64. return (
  65. <IntlProvider locale={locale} messages={messages}>
  66. <ReduxProvider store={store}>
  67. <ErrorBoundary>
  68. <BrowserRouter>
  69. <ScrollContext shouldUpdateScroll={this.shouldUpdateScroll}>
  70. <Route path='/' component={UI} />
  71. </ScrollContext>
  72. </BrowserRouter>
  73. <Helmet defaultTitle={title} titleTemplate={`%s - ${title}`} />
  74. </ErrorBoundary>
  75. </ReduxProvider>
  76. </IntlProvider>
  77. );
  78. }
  79. }