diff --git a/js/src/common/Application.js b/js/src/common/Application.js index 94e631cf2..9cbf0bab2 100644 --- a/js/src/common/Application.js +++ b/js/src/common/Application.js @@ -12,6 +12,7 @@ import mapRoutes from './utils/mapRoutes'; import RequestError from './utils/RequestError'; import ScrollListener from './utils/ScrollListener'; import liveHumanTimes from './utils/liveHumanTimes'; +import patchMithril from './utils/patchMithril'; import { extend } from './extend'; import Forum from './models/Forum'; @@ -166,6 +167,8 @@ export default class Application { } boot() { + patchMithril(window); + this.initializers.toArray().forEach((initializer) => initializer(this)); this.store.pushPayload({ data: this.data.resources }); diff --git a/js/src/common/FlarumRegistry.ts b/js/src/common/FlarumRegistry.ts new file mode 100644 index 000000000..a342b8668 --- /dev/null +++ b/js/src/common/FlarumRegistry.ts @@ -0,0 +1,60 @@ +interface ExportRegistry { + moduleExports: object; + + onLoads: object; + + /** + * Add an instance to the registry. + * This serves as the equivalent of `flarum.core.compat[id] = object` + */ + add(namespace: string, id: string, object: any): void; + + /** + * Add a function to run when object of id "id" is added (or overriden). + * If such an object is already registered, the handler will be applied immediately. + */ + onLoad(namespace: string, id: string, handler: Function): void; + + /** + * Retrieve an object of type `id` from the registry. + */ + get(namespace: string, id: string): any; +} + +export default class FlarumRegistry implements ExportRegistry { + moduleExports = new Map(); + onLoads = new Map(); + + protected genKey(namespace: string, id: string): string { + return `${namespace};${id}`; + } + + add(namespace: string, id: string, object: any) { + const key = this.genKey(namespace, id); + + const onLoads = this.onLoads.get(key); + if (onLoads) { + onLoads.reduce((acc, handler) => handler(acc), object); + } + + this.moduleExports.set(key, object); + } + + onLoad(namespace: string, id: string, handler: Function) { + const key = this.genKey(namespace, id); + + const loadedObject = this.moduleExports.get(key); + if (loadedObject) { + this.moduleExports[id] = handler(loadedObject); + } else { + const currOnLoads = this.onLoads.get(key); + this.onLoads.set(key, [...(currOnLoads || []), handler]); + } + } + + get(namespace: string, id: string): any { + const key = this.genKey(namespace, id); + + return this.moduleExports.get(key); + } +} diff --git a/js/src/common/index.js b/js/src/common/index.js index c2d576780..dfb1a1b02 100644 --- a/js/src/common/index.js +++ b/js/src/common/index.js @@ -1,5 +1,5 @@ // Expose jQuery, mithril and dayjs to the window browser object -import 'expose-loader?exposes[]=$&exposes[]=jQuery!jquery'; +import 'expose-loader?exposes=$,jQuery!jquery'; import 'expose-loader?exposes=m!mithril'; import 'expose-loader?exposes=dayjs!dayjs'; @@ -16,9 +16,9 @@ import localizedFormat from 'dayjs/plugin/localizedFormat'; dayjs.extend(relativeTime); dayjs.extend(localizedFormat); -import patchMithril from './utils/patchMithril'; +import FlarumRegistry from './FlarumRegistry'; -patchMithril(window); +window.flreg = new FlarumRegistry(); import * as Extend from './extend/index';