Browse Source

Introduce base/storage to represent the Web Storage API and persistence-related customizations

master
Lyubo Marinov 7 years ago
parent
commit
d7dddb2509

+ 3
- 6
react/features/app/components/AbstractApp.js View File

@@ -14,11 +14,8 @@ import {
14 14
 } from '../../base/participants';
15 15
 import { getProfile } from '../../base/profile';
16 16
 import { Fragment, RouteRegistry } from '../../base/react';
17
-import {
18
-    MiddlewareRegistry,
19
-    PersistencyRegistry,
20
-    ReducerRegistry
21
-} from '../../base/redux';
17
+import { MiddlewareRegistry, ReducerRegistry } from '../../base/redux';
18
+import { PersistenceRegistry } from '../../base/storage';
22 19
 import { toURLString } from '../../base/util';
23 20
 import { OverlayContainer } from '../../overlay';
24 21
 import { BlankPage } from '../../welcome';
@@ -349,7 +346,7 @@ export class AbstractApp extends Component {
349 346
         return (
350 347
             createStore(
351 348
                 reducer,
352
-                PersistencyRegistry.getPersistedState(),
349
+                PersistenceRegistry.getPersistedState(),
353 350
                 middleware));
354 351
     }
355 352
 

+ 7
- 15
react/features/base/lib-jitsi-meet/native/polyfills-browser.js View File

@@ -4,7 +4,13 @@ import 'url-polyfill'; // Polyfill for URL constructor
4 4
 
5 5
 import { Platform } from '../../react';
6 6
 
7
-import Storage from './Storage';
7
+// XXX The library lib-jitsi-meet utilizes window.localStorage at the time of
8
+// this writing and, consequently, the browser-related polyfills implemented
9
+// here by the feature base/lib-jitsi-meet for the purposes of the library
10
+// lib-jitsi-meet are incomplete without the Web Storage API! Should the library
11
+// lib-jitsi-meet (and its dependencies) stop utilizing window.localStorage,
12
+// the following import may be removed:
13
+import '../../storage';
8 14
 
9 15
 /**
10 16
  * Gets the first common prototype of two specified Objects (treating the
@@ -271,11 +277,6 @@ function _visitNode(node, callback) {
271 277
         global.document = document;
272 278
     }
273 279
 
274
-    // localStorage
275
-    if (typeof global.localStorage === 'undefined') {
276
-        global.localStorage = new Storage('@jitsi-meet/');
277
-    }
278
-
279 280
     // location
280 281
     if (typeof global.location === 'undefined') {
281 282
         global.location = {
@@ -332,15 +333,6 @@ function _visitNode(node, callback) {
332 333
         navigator.userAgent = userAgent;
333 334
     }
334 335
 
335
-    // sessionStorage
336
-    //
337
-    // Required by:
338
-    // - herment
339
-    // - Strophe
340
-    if (typeof global.sessionStorage === 'undefined') {
341
-        global.sessionStorage = new Storage();
342
-    }
343
-
344 336
     // WebRTC
345 337
     require('./polyfills-webrtc');
346 338
     require('react-native-callstats/csio-polyfill');

+ 6
- 2
react/features/base/profile/reducer.js View File

@@ -1,6 +1,7 @@
1 1
 // @flow
2 2
 
3
-import { PersistencyRegistry, ReducerRegistry } from '../redux';
3
+import { ReducerRegistry } from '../redux';
4
+import { PersistenceRegistry } from '../storage';
4 5
 
5 6
 import { PROFILE_UPDATED } from './actionTypes';
6 7
 
@@ -10,7 +11,10 @@ const DEFAULT_STATE = {
10 11
 
11 12
 const STORE_NAME = 'features/base/profile';
12 13
 
13
-PersistencyRegistry.register(STORE_NAME, {
14
+/**
15
+ * Sets up the persistence of the feature base/profile.
16
+ */
17
+PersistenceRegistry.register(STORE_NAME, {
14 18
     profile: true
15 19
 });
16 20
 

+ 0
- 3
react/features/base/redux/index.js View File

@@ -1,6 +1,3 @@
1 1
 export * from './functions';
2 2
 export { default as MiddlewareRegistry } from './MiddlewareRegistry';
3
-export { default as PersistencyRegistry } from './PersistencyRegistry';
4 3
 export { default as ReducerRegistry } from './ReducerRegistry';
5
-
6
-import './middleware';

+ 0
- 30
react/features/base/redux/readme.md View File

@@ -1,30 +0,0 @@
1
-Jitsi Meet - redux state persistency
2
-====================================
3
-Jitsi Meet has a persistency layer that persists a subtree (or specific subtrees) into window.localStorage (on web) or
4
-AsyncStorage (on mobile).
5
-
6
-Usage
7
-=====
8
-If a subtree of the redux store should be persisted (e.g. ``'features/base/profile'``), then persistency for that
9
-subtree should be requested by registering the subtree (and related config) into PersistencyRegistry.
10
-
11
-E.g. to register the field ``profile`` of the Redux subtree ``'features/base/profile'`` to be persisted, use:
12
-
13
-```JavaScript
14
-PersistencyRegistry.register('features/base/profile', {
15
-    profile: true
16
-});
17
-```
18
-
19
-in the ``reducer.js`` of the ``profile`` feature.
20
-
21
-When it's done, Jitsi Meet will automatically persist these subtrees/fields and rehidrate them on startup.
22
-
23
-Throttling
24
-==========
25
-To avoid too frequent write operations in the storage, we utilise throttling in the persistency layer, meaning that the storage
26
-gets persisted only once in every 2 seconds, even if multiple redux state changes occur during this period. This throttling timeout
27
-can be configured in
28
-```
29
-react/features/base/redux/middleware.js#PERSIST_DELAY
30
-```

react/features/base/redux/PersistencyRegistry.js → react/features/base/storage/PersistenceRegistry.js View File

@@ -19,13 +19,13 @@ declare type PersistencyConfigMap = { [name: string]: Object };
19 19
  * A registry to allow features to register their redux store subtree to be
20 20
  * persisted and also handles the persistency calls too.
21 21
  */
22
-class PersistencyRegistry {
22
+class PersistenceRegistry {
23 23
     _checksum: string;
24 24
 
25 25
     _elements: PersistencyConfigMap;
26 26
 
27 27
     /**
28
-     * Initializes a new {@ code PersistencyRegistry} instance.
28
+     * Initializes a new {@ code PersistenceRegistry} instance.
29 29
      */
30 30
     constructor() {
31 31
         this._elements = {};
@@ -166,4 +166,4 @@ class PersistencyRegistry {
166 166
     }
167 167
 }
168 168
 
169
-export default new PersistencyRegistry();
169
+export default new PersistenceRegistry();

+ 33
- 0
react/features/base/storage/README.md View File

@@ -0,0 +1,33 @@
1
+Jitsi Meet - redux state persistence
2
+====================================
3
+Jitsi Meet has a persistence layer that persists specific subtrees of the redux
4
+store/state into window.localStorage (on Web) or AsyncStorage (on mobile).
5
+
6
+Usage
7
+=====
8
+If a subtree of the redux store should be persisted (e.g.
9
+`'features/base/profile'`), then persistence for that subtree should be
10
+requested by registering the subtree with `PersistenceRegistry`.
11
+
12
+For example, to register the field `profile` of the redux subtree
13
+`'features/base/profile'` to be persisted, use:
14
+```javascript
15
+PersistenceRegistry.register('features/base/profile', {
16
+    profile: true
17
+});
18
+```
19
+
20
+in the `reducer.js` of the `base/profile` feature.
21
+
22
+When it's done, Jitsi Meet will automatically persist these subtrees and
23
+rehydrate them on startup.
24
+
25
+Throttling
26
+==========
27
+To avoid too frequent write operations in the storage, we utilize throttling in
28
+the persistence layer, meaning that the storage gets persisted only once every 2
29
+seconds, even if multiple redux state changes occur during this period. The
30
+throttling timeout can be configured in
31
+```
32
+react/features/base/storage/middleware.js#PERSIST_STATE_DELAY
33
+```

+ 1
- 0
react/features/base/storage/_.native.js View File

@@ -0,0 +1 @@
1
+export * from './native';

+ 0
- 0
react/features/base/storage/_.web.js View File


+ 4
- 0
react/features/base/storage/index.js View File

@@ -0,0 +1,4 @@
1
+export * from './_';
2
+export { default as PersistenceRegistry } from './PersistenceRegistry';
3
+
4
+import './middleware';

react/features/base/redux/middleware.js → react/features/base/storage/middleware.js View File

@@ -2,13 +2,13 @@
2 2
 
3 3
 import _ from 'lodash';
4 4
 
5
-import { toState } from './functions';
6
-import MiddlewareRegistry from './MiddlewareRegistry';
7
-import PersistencyRegistry from './PersistencyRegistry';
5
+import { MiddlewareRegistry, toState } from '../redux';
6
+
7
+import PersistenceRegistry from './PersistenceRegistry';
8 8
 
9 9
 /**
10
- * The delay that passes between the last state change and the persisting of
11
- * that state in the storage.
10
+ * The delay in milliseconds that passes between the last state change and the
11
+ * persisting of that state in the storage.
12 12
  */
13 13
 const PERSIST_STATE_DELAY = 2000;
14 14
 
@@ -17,21 +17,23 @@ const PERSIST_STATE_DELAY = 2000;
17 17
  */
18 18
 const throttledPersistState
19 19
     = _.throttle(
20
-        state => PersistencyRegistry.persistState(state),
20
+        state => PersistenceRegistry.persistState(state),
21 21
         PERSIST_STATE_DELAY);
22 22
 
23 23
 /**
24 24
  * A master MiddleWare to selectively persist state. Please use the
25
- * {@link persisterconfig.json} to set which subtrees of the Redux state should
25
+ * {@link persisterconfig.json} to set which subtrees of the redux state should
26 26
  * be persisted.
27 27
  *
28 28
  * @param {Store} store - The redux store.
29 29
  * @returns {Function}
30 30
  */
31 31
 MiddlewareRegistry.register(store => next => action => {
32
+    const oldState = toState(store);
32 33
     const result = next(action);
34
+    const newState = toState(store);
33 35
 
34
-    throttledPersistState(toState(store));
36
+    oldState === newState || throttledPersistState(newState);
35 37
 
36 38
     return result;
37 39
 });

react/features/base/lib-jitsi-meet/native/Storage.js → react/features/base/storage/native/Storage.js View File


+ 1
- 0
react/features/base/storage/native/index.js View File

@@ -0,0 +1 @@
1
+import './polyfills-browser';

+ 19
- 0
react/features/base/storage/native/polyfills-browser.js View File

@@ -0,0 +1,19 @@
1
+import Storage from './Storage';
2
+
3
+(global => {
4
+
5
+    // localStorage
6
+    if (typeof global.localStorage === 'undefined') {
7
+        global.localStorage = new Storage('@jitsi-meet/');
8
+    }
9
+
10
+    // sessionStorage
11
+    //
12
+    // Required by:
13
+    // - herment
14
+    // - Strophe
15
+    if (typeof global.sessionStorage === 'undefined') {
16
+        global.sessionStorage = new Storage();
17
+    }
18
+
19
+})(global || window || this); // eslint-disable-line no-invalid-this

+ 1
- 1
react/features/recent-list/components/AbstractRecentList.js View File

@@ -46,7 +46,7 @@ export default class AbstractRecentList extends Component<Props> {
46 46
 }
47 47
 
48 48
 /**
49
- * Maps Redux state to component props.
49
+ * Maps redux state to component props.
50 50
  *
51 51
  * @param {Object} state - The redux state.
52 52
  * @returns {{

+ 5
- 4
react/features/recent-list/reducer.js View File

@@ -1,6 +1,7 @@
1 1
 // @flow
2 2
 
3
-import { PersistencyRegistry, ReducerRegistry } from '../base/redux';
3
+import { ReducerRegistry } from '../base/redux';
4
+import { PersistenceRegistry } from '../base/storage';
4 5
 
5 6
 import {
6 7
     STORE_CURRENT_CONFERENCE,
@@ -30,14 +31,14 @@ export const MAX_LIST_SIZE = 30;
30 31
 const STORE_NAME = 'features/recent-list';
31 32
 
32 33
 /**
33
- * Registers the redux store subtree of this feature for persistency.
34
+ * Sets up the persistence of the feature recent-list.
34 35
  */
35
-PersistencyRegistry.register(STORE_NAME, {
36
+PersistenceRegistry.register(STORE_NAME, {
36 37
     list: true
37 38
 });
38 39
 
39 40
 /**
40
- * Reduces the redux actions of the feature features/recent-list.
41
+ * Reduces the redux actions of the feature recent-list.
41 42
  */
42 43
 ReducerRegistry.register(
43 44
     STORE_NAME,

Loading…
Cancel
Save