123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- // @flow
- import Logger from 'jitsi-meet-logger';
- import md5 from 'js-md5';
-
- const logger = Logger.getLogger(__filename);
-
- /**
- * The name of the localStorage store where the app persists its values to.
- */
- const PERSISTED_STATE_NAME = 'jitsi-state';
-
- /**
- * The type of the name-config pairs stored in this reducer.
- */
- declare type PersistencyConfigMap = { [name: string]: Object };
-
- /**
- * A registry to allow features to register their redux store
- * subtree to be persisted and also handles the persistency calls too.
- */
- class PersistencyRegistry {
- _checksum: string;
- _elements: PersistencyConfigMap;
-
- /**
- * Initiates the PersistencyRegistry.
- */
- constructor() {
- this._elements = {};
- }
-
- /**
- * Returns the persisted redux state. This function takes
- * the PersistencyRegistry._elements into account as we may have
- * persisted something in the past that we don't want to retreive anymore.
- * The next {@link #persistState} will remove those values.
- *
- * @returns {Object}
- */
- getPersistedState() {
- let filteredPersistedState = {};
- let persistedState = window.localStorage.getItem(PERSISTED_STATE_NAME);
-
- if (persistedState) {
- try {
- persistedState = JSON.parse(persistedState);
- } catch (error) {
- logger.error(
- 'Error parsing persisted state', persistedState, error
- );
- persistedState = {};
- }
-
- filteredPersistedState
- = this._getFilteredState(persistedState);
- }
-
- this._checksum = this._calculateChecksum(filteredPersistedState);
- logger.info('Redux state rehydrated as', filteredPersistedState);
-
- return filteredPersistedState;
- }
-
- /**
- * Initiates a persist operation, but its execution will depend on
- * the current checksums (checks changes).
- *
- * @param {Object} state - The redux state.
- * @returns {void}
- */
- persistState(state: Object) {
- const filteredState = this._getFilteredState(state);
- const newCheckSum = this._calculateChecksum(filteredState);
-
- if (newCheckSum !== this._checksum) {
- try {
- window.localStorage.setItem(
- PERSISTED_STATE_NAME,
- JSON.stringify(filteredState)
- );
- logger.info(
- `Redux state persisted. ${this._checksum} -> ${newCheckSum}`
- );
- this._checksum = newCheckSum;
- } catch (error) {
- logger.error('Error persisting Redux state', error);
- }
- }
- }
-
- /**
- * Registers a new subtree config to be used for the persistency.
- *
- * @param {string} name - The name of the subtree the config belongs to.
- * @param {Object} config - The config object.
- * @returns {void}
- */
- register(name: string, config: Object) {
- this._elements[name] = config;
- }
-
- /**
- * Calculates the checksum of the current or the new values of the state.
- *
- * @private
- * @param {Object} filteredState - The filtered/persisted Redux state.
- * @returns {string}
- */
- _calculateChecksum(filteredState: Object) {
- try {
- return md5.hex(JSON.stringify(filteredState) || '');
- } catch (error) {
- logger.error(
- 'Error calculating checksum for state', filteredState, error
- );
-
- return '';
- }
- }
-
- /**
- * Prepares a filtered state from the actual or the
- * persisted Redux state, based on this registry.
- *
- * @private
- * @param {Object} state - The actual or persisted redux state.
- * @returns {Object}
- */
- _getFilteredState(state: Object) {
- const filteredState = {};
-
- for (const name of Object.keys(this._elements)) {
- if (state[name]) {
- filteredState[name] = this._getFilteredSubtree(
- state[name],
- this._elements[name]
- );
- }
- }
-
- return filteredState;
- }
-
- /**
- * Prepares a filtered subtree based on the config for
- * persisting or for retreival.
- *
- * @private
- * @param {Object} subtree - The redux state subtree.
- * @param {Object} subtreeConfig - The related config.
- * @returns {Object}
- */
- _getFilteredSubtree(subtree, subtreeConfig) {
- const filteredSubtree = {};
-
- for (const persistedKey of Object.keys(subtree)) {
- if (subtreeConfig[persistedKey]) {
- filteredSubtree[persistedKey]
- = subtree[persistedKey];
- }
- }
-
- return filteredSubtree;
- }
- }
-
- export default new PersistencyRegistry();
|