AppContainer.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. import { Container } from 'unstated';
  2. import GrowiRenderer from '../util/GrowiRenderer';
  3. import { i18nFactory } from '../util/i18n';
  4. /**
  5. * Service container related to options for Application
  6. * @extends {Container} unstated Container
  7. */
  8. export default class AppContainer extends Container {
  9. constructor() {
  10. super();
  11. this.config = JSON.parse(document.getElementById('growi-context-hydrate').textContent || '{}');
  12. const currentUserElem = document.getElementById('growi-current-user');
  13. if (currentUserElem != null) {
  14. this.currentUser = JSON.parse(currentUserElem.textContent);
  15. }
  16. const userLocaleId = this.currentUser?.lang;
  17. this.i18n = i18nFactory(userLocaleId);
  18. this.containerInstances = {};
  19. this.componentInstances = {};
  20. this.rendererInstances = {};
  21. }
  22. /**
  23. * Workaround for the mangling in production build to break constructor.name
  24. */
  25. static getClassName() {
  26. return 'AppContainer';
  27. }
  28. initApp() {
  29. this.injectToWindow();
  30. }
  31. initContents() {
  32. const body = document.querySelector('body');
  33. this.isDocSaved = true;
  34. this.originRenderer = new GrowiRenderer(this);
  35. const isPluginEnabled = body.dataset.pluginEnabled === 'true';
  36. if (isPluginEnabled) {
  37. this.initPlugins();
  38. }
  39. this.injectToWindow();
  40. }
  41. initPlugins() {
  42. const growiPlugin = window.growiPlugin;
  43. growiPlugin.installAll(this, this.originRenderer);
  44. }
  45. injectToWindow() {
  46. window.appContainer = this;
  47. const originRenderer = this.getOriginRenderer();
  48. window.growiRenderer = originRenderer;
  49. // backward compatibility
  50. window.crowi = this;
  51. window.crowiRenderer = originRenderer;
  52. window.crowiPlugin = window.growiPlugin;
  53. }
  54. get currentUserId() {
  55. if (this.currentUser == null) {
  56. return null;
  57. }
  58. return this.currentUser._id;
  59. }
  60. get currentUsername() {
  61. if (this.currentUser == null) {
  62. return null;
  63. }
  64. return this.currentUser.username;
  65. }
  66. getConfig() {
  67. return this.config;
  68. }
  69. /**
  70. * Register unstated container instance
  71. * @param {object} instance unstated container instance
  72. */
  73. registerContainer(instance) {
  74. if (instance == null) {
  75. throw new Error('The specified instance must not be null');
  76. }
  77. const className = instance.constructor.getClassName();
  78. if (this.containerInstances[className] != null) {
  79. throw new Error('The specified instance couldn\'t register because the same type object has already been registered');
  80. }
  81. this.containerInstances[className] = instance;
  82. }
  83. /**
  84. * Get registered unstated container instance
  85. * !! THIS METHOD SHOULD ONLY BE USED FROM unstated CONTAINERS !!
  86. * !! From component instances, inject containers with `import { Subscribe } from 'unstated'` !!
  87. *
  88. * @param {string} className
  89. */
  90. getContainer(className) {
  91. return this.containerInstances[className];
  92. }
  93. /**
  94. * Register React component instance
  95. * @param {string} id
  96. * @param {object} instance React component instance
  97. */
  98. registerComponentInstance(id, instance) {
  99. if (instance == null) {
  100. throw new Error('The specified instance must not be null');
  101. }
  102. this.componentInstances[id] = instance;
  103. }
  104. /**
  105. * Get registered React component instance
  106. * @param {string} id
  107. */
  108. getComponentInstance(id) {
  109. return this.componentInstances[id];
  110. }
  111. getOriginRenderer() {
  112. return this.originRenderer;
  113. }
  114. /**
  115. * factory method
  116. */
  117. getRenderer(mode) {
  118. if (this.rendererInstances[mode] != null) {
  119. return this.rendererInstances[mode];
  120. }
  121. const renderer = new GrowiRenderer(this, this.originRenderer);
  122. // setup
  123. renderer.initMarkdownItConfigurers(mode);
  124. renderer.setup(mode);
  125. // register
  126. this.rendererInstances[mode] = renderer;
  127. return renderer;
  128. }
  129. }