jiti-meet/react/features/base/react/RouteRegistry.js

120 lines
3.1 KiB
JavaScript

/* @flow */
import { Component } from 'react';
/**
* Object describing application route.
*
* @typedef {Object} Route
* @property {Component} component - React Component constructor.
* @property {string} path - URL route, required for web routing.
*/
type Route = {
component: Class<Component<*>>, // eslint-disable-line no-undef
path: string
};
/**
* A registry for Navigator routes, allowing features to register themselves
* without needing to create additional inter-feature dependencies.
*/
class RouteRegistry {
_elements: Array<Route>;
/**
* Initializes a new RouteRegistry instance.
*/
constructor() {
/**
* The set of registered routes.
*
* @private
* @type {Route[]}
*/
this._elements = [];
}
/**
* Determines whether two specific Routes are equal i.e. they describe one
* and the same abstract route.
*
* @param {Object} a - The Route to compare to b.
* @param {Object} b - The Route to compare to a.
* @returns {boolean} True if the specified a and b describe one and the
* same abstract route; otherwise, false.
*/
areRoutesEqual(a: Route, b: Route) {
if (a === b) { // reflexive
return true;
}
if (!a) {
return !b;
}
if (!b) {
return !a;
}
const aKeys = Object.keys(a);
const bKeys = Object.keys(b);
return (
aKeys.length === bKeys.length /* symmetric */
&& aKeys.every(key => a[key] === b[key]));
}
/**
* Returns all registered routes.
*
* @returns {Route[]}
*/
getRoutes() {
// We use the destructuring operator to 'clone' the route object to
// prevent modifications from outside (e.g. React Native's Navigator
// extends it with additional properties).
return this._elements.map(r => {
return { ...r };
});
}
/* eslint-disable no-undef */
/**
* Returns registered route by name if any.
*
* @param {Component} component - The React Component (class) of the route
* to retrieve.
* @returns {Route|null}
*/
getRouteByComponent(component: Class<Component<*>>) {
/* eslint-enable no-undef */
const route = this._elements.find(r => r.component === component);
// We use destructuring operator to 'clone' route object to prevent
// modifications from outside (e.g. React Native's Navigator extends
// it with some additional properties).
return route ? { ...route } : null;
}
/**
* Adds a route to this registry.
*
* @param {Route} route - Route definition object.
* @returns {void}
*/
register(route: Route) {
if (this._elements.includes(route)) {
throw new Error(
`Route ${String(route.component)} is registered already!`);
}
this._elements.push(route);
}
}
/**
* The public singleton instance of the RouteRegistry class.
*/
export default new RouteRegistry();