Introduce base/storage to represent the Web Storage API and persistence-related customizations
This commit is contained in:
parent
83243d5980
commit
d7dddb2509
|
@ -14,11 +14,8 @@ import {
|
|||
} from '../../base/participants';
|
||||
import { getProfile } from '../../base/profile';
|
||||
import { Fragment, RouteRegistry } from '../../base/react';
|
||||
import {
|
||||
MiddlewareRegistry,
|
||||
PersistencyRegistry,
|
||||
ReducerRegistry
|
||||
} from '../../base/redux';
|
||||
import { MiddlewareRegistry, ReducerRegistry } from '../../base/redux';
|
||||
import { PersistenceRegistry } from '../../base/storage';
|
||||
import { toURLString } from '../../base/util';
|
||||
import { OverlayContainer } from '../../overlay';
|
||||
import { BlankPage } from '../../welcome';
|
||||
|
@ -349,7 +346,7 @@ export class AbstractApp extends Component {
|
|||
return (
|
||||
createStore(
|
||||
reducer,
|
||||
PersistencyRegistry.getPersistedState(),
|
||||
PersistenceRegistry.getPersistedState(),
|
||||
middleware));
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,13 @@ import 'url-polyfill'; // Polyfill for URL constructor
|
|||
|
||||
import { Platform } from '../../react';
|
||||
|
||||
import Storage from './Storage';
|
||||
// XXX The library lib-jitsi-meet utilizes window.localStorage at the time of
|
||||
// this writing and, consequently, the browser-related polyfills implemented
|
||||
// here by the feature base/lib-jitsi-meet for the purposes of the library
|
||||
// lib-jitsi-meet are incomplete without the Web Storage API! Should the library
|
||||
// lib-jitsi-meet (and its dependencies) stop utilizing window.localStorage,
|
||||
// the following import may be removed:
|
||||
import '../../storage';
|
||||
|
||||
/**
|
||||
* Gets the first common prototype of two specified Objects (treating the
|
||||
|
@ -271,11 +277,6 @@ function _visitNode(node, callback) {
|
|||
global.document = document;
|
||||
}
|
||||
|
||||
// localStorage
|
||||
if (typeof global.localStorage === 'undefined') {
|
||||
global.localStorage = new Storage('@jitsi-meet/');
|
||||
}
|
||||
|
||||
// location
|
||||
if (typeof global.location === 'undefined') {
|
||||
global.location = {
|
||||
|
@ -332,15 +333,6 @@ function _visitNode(node, callback) {
|
|||
navigator.userAgent = userAgent;
|
||||
}
|
||||
|
||||
// sessionStorage
|
||||
//
|
||||
// Required by:
|
||||
// - herment
|
||||
// - Strophe
|
||||
if (typeof global.sessionStorage === 'undefined') {
|
||||
global.sessionStorage = new Storage();
|
||||
}
|
||||
|
||||
// WebRTC
|
||||
require('./polyfills-webrtc');
|
||||
require('react-native-callstats/csio-polyfill');
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// @flow
|
||||
|
||||
import { PersistencyRegistry, ReducerRegistry } from '../redux';
|
||||
import { ReducerRegistry } from '../redux';
|
||||
import { PersistenceRegistry } from '../storage';
|
||||
|
||||
import { PROFILE_UPDATED } from './actionTypes';
|
||||
|
||||
|
@ -10,7 +11,10 @@ const DEFAULT_STATE = {
|
|||
|
||||
const STORE_NAME = 'features/base/profile';
|
||||
|
||||
PersistencyRegistry.register(STORE_NAME, {
|
||||
/**
|
||||
* Sets up the persistence of the feature base/profile.
|
||||
*/
|
||||
PersistenceRegistry.register(STORE_NAME, {
|
||||
profile: true
|
||||
});
|
||||
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
export * from './functions';
|
||||
export { default as MiddlewareRegistry } from './MiddlewareRegistry';
|
||||
export { default as PersistencyRegistry } from './PersistencyRegistry';
|
||||
export { default as ReducerRegistry } from './ReducerRegistry';
|
||||
|
||||
import './middleware';
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
Jitsi Meet - redux state persistency
|
||||
====================================
|
||||
Jitsi Meet has a persistency layer that persists a subtree (or specific subtrees) into window.localStorage (on web) or
|
||||
AsyncStorage (on mobile).
|
||||
|
||||
Usage
|
||||
=====
|
||||
If a subtree of the redux store should be persisted (e.g. ``'features/base/profile'``), then persistency for that
|
||||
subtree should be requested by registering the subtree (and related config) into PersistencyRegistry.
|
||||
|
||||
E.g. to register the field ``profile`` of the Redux subtree ``'features/base/profile'`` to be persisted, use:
|
||||
|
||||
```JavaScript
|
||||
PersistencyRegistry.register('features/base/profile', {
|
||||
profile: true
|
||||
});
|
||||
```
|
||||
|
||||
in the ``reducer.js`` of the ``profile`` feature.
|
||||
|
||||
When it's done, Jitsi Meet will automatically persist these subtrees/fields and rehidrate them on startup.
|
||||
|
||||
Throttling
|
||||
==========
|
||||
To avoid too frequent write operations in the storage, we utilise throttling in the persistency layer, meaning that the storage
|
||||
gets persisted only once in every 2 seconds, even if multiple redux state changes occur during this period. This throttling timeout
|
||||
can be configured in
|
||||
```
|
||||
react/features/base/redux/middleware.js#PERSIST_DELAY
|
||||
```
|
|
@ -19,13 +19,13 @@ 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 {
|
||||
class PersistenceRegistry {
|
||||
_checksum: string;
|
||||
|
||||
_elements: PersistencyConfigMap;
|
||||
|
||||
/**
|
||||
* Initializes a new {@ code PersistencyRegistry} instance.
|
||||
* Initializes a new {@ code PersistenceRegistry} instance.
|
||||
*/
|
||||
constructor() {
|
||||
this._elements = {};
|
||||
|
@ -166,4 +166,4 @@ class PersistencyRegistry {
|
|||
}
|
||||
}
|
||||
|
||||
export default new PersistencyRegistry();
|
||||
export default new PersistenceRegistry();
|
|
@ -0,0 +1,33 @@
|
|||
Jitsi Meet - redux state persistence
|
||||
====================================
|
||||
Jitsi Meet has a persistence layer that persists specific subtrees of the redux
|
||||
store/state into window.localStorage (on Web) or AsyncStorage (on mobile).
|
||||
|
||||
Usage
|
||||
=====
|
||||
If a subtree of the redux store should be persisted (e.g.
|
||||
`'features/base/profile'`), then persistence for that subtree should be
|
||||
requested by registering the subtree with `PersistenceRegistry`.
|
||||
|
||||
For example, to register the field `profile` of the redux subtree
|
||||
`'features/base/profile'` to be persisted, use:
|
||||
```javascript
|
||||
PersistenceRegistry.register('features/base/profile', {
|
||||
profile: true
|
||||
});
|
||||
```
|
||||
|
||||
in the `reducer.js` of the `base/profile` feature.
|
||||
|
||||
When it's done, Jitsi Meet will automatically persist these subtrees and
|
||||
rehydrate them on startup.
|
||||
|
||||
Throttling
|
||||
==========
|
||||
To avoid too frequent write operations in the storage, we utilize throttling in
|
||||
the persistence layer, meaning that the storage gets persisted only once every 2
|
||||
seconds, even if multiple redux state changes occur during this period. The
|
||||
throttling timeout can be configured in
|
||||
```
|
||||
react/features/base/storage/middleware.js#PERSIST_STATE_DELAY
|
||||
```
|
|
@ -0,0 +1 @@
|
|||
export * from './native';
|
|
@ -0,0 +1,4 @@
|
|||
export * from './_';
|
||||
export { default as PersistenceRegistry } from './PersistenceRegistry';
|
||||
|
||||
import './middleware';
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
import _ from 'lodash';
|
||||
|
||||
import { toState } from './functions';
|
||||
import MiddlewareRegistry from './MiddlewareRegistry';
|
||||
import PersistencyRegistry from './PersistencyRegistry';
|
||||
import { MiddlewareRegistry, toState } from '../redux';
|
||||
|
||||
import PersistenceRegistry from './PersistenceRegistry';
|
||||
|
||||
/**
|
||||
* The delay that passes between the last state change and the persisting of
|
||||
* that state in the storage.
|
||||
* The delay in milliseconds that passes between the last state change and the
|
||||
* persisting of that state in the storage.
|
||||
*/
|
||||
const PERSIST_STATE_DELAY = 2000;
|
||||
|
||||
|
@ -17,21 +17,23 @@ const PERSIST_STATE_DELAY = 2000;
|
|||
*/
|
||||
const throttledPersistState
|
||||
= _.throttle(
|
||||
state => PersistencyRegistry.persistState(state),
|
||||
state => PersistenceRegistry.persistState(state),
|
||||
PERSIST_STATE_DELAY);
|
||||
|
||||
/**
|
||||
* A master MiddleWare to selectively persist state. Please use the
|
||||
* {@link persisterconfig.json} to set which subtrees of the Redux state should
|
||||
* {@link persisterconfig.json} to set which subtrees of the redux state should
|
||||
* be persisted.
|
||||
*
|
||||
* @param {Store} store - The redux store.
|
||||
* @returns {Function}
|
||||
*/
|
||||
MiddlewareRegistry.register(store => next => action => {
|
||||
const oldState = toState(store);
|
||||
const result = next(action);
|
||||
const newState = toState(store);
|
||||
|
||||
throttledPersistState(toState(store));
|
||||
oldState === newState || throttledPersistState(newState);
|
||||
|
||||
return result;
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
import './polyfills-browser';
|
|
@ -0,0 +1,19 @@
|
|||
import Storage from './Storage';
|
||||
|
||||
(global => {
|
||||
|
||||
// localStorage
|
||||
if (typeof global.localStorage === 'undefined') {
|
||||
global.localStorage = new Storage('@jitsi-meet/');
|
||||
}
|
||||
|
||||
// sessionStorage
|
||||
//
|
||||
// Required by:
|
||||
// - herment
|
||||
// - Strophe
|
||||
if (typeof global.sessionStorage === 'undefined') {
|
||||
global.sessionStorage = new Storage();
|
||||
}
|
||||
|
||||
})(global || window || this); // eslint-disable-line no-invalid-this
|
|
@ -46,7 +46,7 @@ export default class AbstractRecentList extends Component<Props> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Maps Redux state to component props.
|
||||
* Maps redux state to component props.
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @returns {{
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// @flow
|
||||
|
||||
import { PersistencyRegistry, ReducerRegistry } from '../base/redux';
|
||||
import { ReducerRegistry } from '../base/redux';
|
||||
import { PersistenceRegistry } from '../base/storage';
|
||||
|
||||
import {
|
||||
STORE_CURRENT_CONFERENCE,
|
||||
|
@ -30,14 +31,14 @@ export const MAX_LIST_SIZE = 30;
|
|||
const STORE_NAME = 'features/recent-list';
|
||||
|
||||
/**
|
||||
* Registers the redux store subtree of this feature for persistency.
|
||||
* Sets up the persistence of the feature recent-list.
|
||||
*/
|
||||
PersistencyRegistry.register(STORE_NAME, {
|
||||
PersistenceRegistry.register(STORE_NAME, {
|
||||
list: true
|
||||
});
|
||||
|
||||
/**
|
||||
* Reduces the redux actions of the feature features/recent-list.
|
||||
* Reduces the redux actions of the feature recent-list.
|
||||
*/
|
||||
ReducerRegistry.register(
|
||||
STORE_NAME,
|
||||
|
|
Loading…
Reference in New Issue