"Fossies" - the Fresh Open Source Software Archive

Member "jitsi-meet-7555/react/features/base/redux/StateListenerRegistry.ts" (28 Sep 2023, 7018 Bytes) of package /linux/misc/jitsi-meet-7555.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) TypeScript source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 import { Store } from 'redux';
    2 
    3 import { IReduxState, IStore } from '../../app/types';
    4 
    5 import { equals } from './functions';
    6 import logger from './logger';
    7 
    8 /**
    9  * The type listener supported for registration with
   10  * {@link StateListenerRegistry} in association with a {@link Selector}.
   11  *
   12  * @param {any} selection - The value derived from the redux store/state by the
   13  * associated {@code Selector}. Immutable!
   14  * @param {Store} store - The redux store. Provided in case the {@code Listener}
   15  * needs to {@code dispatch} or {@code getState}. The latter is advisable only
   16  * if the {@code Listener} is not to respond to changes to that state.
   17  * @param {any} prevSelection - The value previously derived from the redux
   18  * store/state by the associated {@code Selector}. The {@code Listener} is
   19  * invoked only if {@code prevSelection} and {@code selection} are different.
   20  * Immutable!
   21  */
   22 type Listener
   23     = (selection: any, store: IStore, prevSelection: any) => void;
   24 
   25 /**
   26  * The type selector supported for registration with
   27  * {@link StateListenerRegistry} in association with a {@link Listener}.
   28  *
   29  * @param {IReduxState} state - The redux state from which the {@code Selector} is to
   30  * derive data.
   31  * @param {any} prevSelection - The value previously derived from the redux
   32  * store/state by the {@code Selector}. Provided in case the {@code Selector}
   33  * needs to derive the returned value from the specified {@code state} and
   34  * {@code prevSelection}. Immutable!
   35  * @returns {any} The value derived from the specified {@code state} and/or
   36  * {@code prevSelection}. The associated {@code Listener} will only be invoked
   37  * if the returned value is other than {@code prevSelection}.
   38  */
   39 type Selector = (state: IReduxState, prevSelection: any) => any;
   40 
   41 /**
   42  * Options that can be passed to the register method.
   43  */
   44 type RegistrationOptions = {
   45 
   46     /**
   47      * @property {boolean} [deepEquals=false] - Whether or not a deep equals check should be performed on the selection
   48      * returned by {@link Selector}.
   49      */
   50     deepEquals?: boolean;
   51 };
   52 
   53 /**
   54  * A type of a {@link Selector}-{@link Listener} association in which the
   55  * {@code Listener} listens to changes in the values derived from a redux
   56  * store/state by the {@code Selector}.
   57  */
   58 type SelectorListener = {
   59 
   60     /**
   61      * The {@code Listener} which listens to changes in the values selected by
   62      * {@link selector}.
   63      */
   64     listener: Listener;
   65 
   66     /**
   67      * The {@link RegistrationOptions} passed during the registration to be applied on the listener.
   68      */
   69     options?: RegistrationOptions;
   70 
   71     /**
   72      * The {@code Selector} which selects values whose changes are listened to
   73      * by {@link listener}.
   74      */
   75     selector: Selector;
   76 };
   77 
   78 /**
   79  * A registry listeners which listen to changes in a redux store/state.
   80  */
   81 class StateListenerRegistry {
   82     /**
   83      * The {@link Listener}s registered with this {@code StateListenerRegistry}
   84      * to be notified when the values derived by associated {@link Selector}s
   85      * from a redux store/state change.
   86      */
   87     _selectorListeners: Set<SelectorListener> = new Set();
   88 
   89     /**
   90      * Invoked by a specific redux store any time an action is dispatched, and
   91      * some part of the state (tree) may potentially have changed.
   92      *
   93      * @param {Object} context - The redux store invoking the listener and the
   94      * private state of this {@code StateListenerRegistry} associated with the
   95      * redux store.
   96      * @returns {void}
   97      */
   98     _listener({ prevSelections, store }: {
   99             prevSelections: Map<SelectorListener, any>;
  100             store: Store<any, any>;
  101     }) {
  102         for (const selectorListener of this._selectorListeners) {
  103             const prevSelection = prevSelections.get(selectorListener);
  104 
  105             try {
  106                 const selection
  107                     = selectorListener.selector(
  108                         store.getState(),
  109                         prevSelection);
  110                 const useDeepEquals = selectorListener?.options?.deepEquals;
  111 
  112                 if ((useDeepEquals && !equals(prevSelection, selection))
  113                         || (!useDeepEquals && prevSelection !== selection)) {
  114                     prevSelections.set(selectorListener, selection);
  115                     selectorListener.listener(selection, store, prevSelection);
  116                 }
  117             } catch (e) {
  118                 // Don't let one faulty listener prevent other listeners from
  119                 // being notified about their associated changes.
  120                 logger.error(e);
  121             }
  122         }
  123     }
  124 
  125     /**
  126      * Registers a specific listener to be notified when the value derived by a
  127      * specific {@code selector} from a redux store/state changes.
  128      *
  129      * @param {Function} selector - The pure {@code Function} of the redux
  130      * store/state (and the previous selection of made by {@code selector})
  131      * which selects the value listened to by the specified {@code listener}.
  132      * @param {Function} listener - The listener to register with this
  133      * {@code StateListenerRegistry} so that it gets invoked when the value
  134      * returned by the specified {@code selector} changes.
  135      * @param {RegistrationOptions} [options] - Any options to be applied to the registration.
  136      * @returns {void}
  137      */
  138     register(selector: Selector, listener: Listener, options?: RegistrationOptions) {
  139         if (typeof selector !== 'function' || typeof listener !== 'function') {
  140             throw new Error('Invalid selector or listener!');
  141         }
  142 
  143         this._selectorListeners.add({
  144             listener,
  145             selector,
  146             options
  147         });
  148     }
  149 
  150     /**
  151      * Subscribes to a specific redux store (so that this instance gets notified
  152      * any time an action is dispatched, and some part of the state (tree) of
  153      * the specified redux store may potentially have changed).
  154      *
  155      * @param {Store} store - The redux store to which this
  156      * {@code StateListenerRegistry} is to {@code subscribe}.
  157      * @returns {void}
  158      */
  159     subscribe(store: Store<any, any>) {
  160         // XXX If StateListenerRegistry is not utilized by the app to listen to
  161         // state changes, do not bother subscribing to the store at all.
  162         if (this._selectorListeners.size) {
  163             store.subscribe(
  164                 this._listener.bind(
  165                     this,
  166                     {
  167                         /**
  168                          * The previous selections of the {@code Selector}s
  169                          * registered with this {@code StateListenerRegistry}.
  170                          *
  171                          * @type Map<any>
  172                          */
  173                         prevSelections: new Map(),
  174 
  175                         /**
  176                          * The redux store.
  177                          *
  178                          * @type Store
  179                          */
  180                         store
  181                     }));
  182         }
  183     }
  184 }
  185 
  186 export default new StateListenerRegistry();