Ver código fonte

[RN] Add polyfill for localStorage

It's built on top of React Native's AsyncStorage. They have differing APIs, so
we implement a synchronous API on top of an asynchronous one. This is done by
being optimistic and hoping that operations will happen asynchronously. If one
such operation fails, the error is ignored and life goes on, since operations
are performed in the in-memory cache first.

Note to reviewers: LocalStorage.js lacks Flow annotations because indexable
class declarations are not yet supported:
https://github.com/facebook/flow/issues/1323 and yours truly couldn't find a way
to make the required syntax work without making it unnecessarily complex.
master
Saúl Ibarra Corretgé 8 anos atrás
pai
commit
bfeaf329e1

+ 112
- 0
react/features/base/lib-jitsi-meet/native/LocalStorage.js Ver arquivo

@@ -0,0 +1,112 @@
1
+import { AsyncStorage } from 'react-native';
2
+
3
+/**
4
+ * Prefix used to mark keys stored by our app in the global React Native
5
+ * storage.
6
+ */
7
+const JITSI_KEY_PREFIX = '@jitsi/';
8
+
9
+/**
10
+ * Web Sorage API compatible object used for polyfilling window.localStorage.
11
+ * The Web Storage API is synchronous, whereas AsyncStorage, the builtin generic
12
+ * storage API in React Native, is asynchronous, so this object is optimistic:
13
+ * it will first store the value locally (in memory) so results can be served
14
+ * synchronously, and then save the value asynchronously.
15
+ *
16
+ * If any of the asynchronous operations produces an error, it's ignored.
17
+ */
18
+export default class LocalStorage {
19
+    /**
20
+     * Loads all keys from React Native's AsyncStorage.
21
+     */
22
+    constructor() {
23
+        AsyncStorage.getAllKeys()
24
+            .then(keys => {
25
+                const jitsiKeys
26
+                    = keys.filter(key => key.startsWith(JITSI_KEY_PREFIX));
27
+
28
+                AsyncStorage.multiGet(jitsiKeys)
29
+                    .then(items => {
30
+                        for (const item of items) {
31
+                            const key = item[0].slice(JITSI_KEY_PREFIX.length);
32
+                            const value = item[1];
33
+
34
+                            this[key] = value;
35
+                        }
36
+                    });
37
+            });
38
+    }
39
+
40
+    /**
41
+     * Gets the number of items stored.
42
+     *
43
+     * @returns {number}
44
+     */
45
+    get length() {
46
+        return Object.keys(this).length;
47
+    }
48
+
49
+    /**
50
+     * Removes all keys from the storage.
51
+     *
52
+     * @returns {void}
53
+     */
54
+    clear() {
55
+        const keys = Object.keys(this);
56
+
57
+        for (const key of keys) {
58
+            delete this[key];
59
+            AsyncStorage.removeItem(`${JITSI_KEY_PREFIX}${key}`);
60
+        }
61
+    }
62
+
63
+    /**
64
+     * Gets the element that was stored for the given `key`.
65
+     *
66
+     * @param {string} key - The requested `key`.
67
+     * @returns {string|null}
68
+     */
69
+    getItem(key) {
70
+        if (this.hasOwnProperty(key)) {
71
+            return this[key];
72
+        }
73
+
74
+        return null;
75
+    }
76
+
77
+    /**
78
+     * Gets the nth element in the storage.
79
+     *
80
+     * @param {number} n - The element number that is requested.
81
+     * @returns {string}
82
+     */
83
+    key(n) {
84
+        return Object.keys(this)[n || 0];
85
+    }
86
+
87
+    /**
88
+     * Removes the given `key` from the storage.
89
+     *
90
+     * @param {string} key - The `key` which will be removed.
91
+     * @returns {void}
92
+     */
93
+    removeItem(key) {
94
+        delete this[key];
95
+        AsyncStorage.removeItem(`${JITSI_KEY_PREFIX}${key}`);
96
+    }
97
+
98
+    /**
99
+     * Stores the given `value` for the given `key`. If a value or ready exists
100
+     * for that key, it's updated.
101
+     *
102
+     * @param {string} key - The key for the value which will be stored.
103
+     * @param {string} value - The value which will be stored.
104
+     * @returns {void}
105
+     */
106
+    setItem(key, value) {
107
+        // eslint-disable-next-line no-param-reassign
108
+        value = String(value);
109
+        this[key] = value;
110
+        AsyncStorage.setItem(`${JITSI_KEY_PREFIX}${key}`, value);
111
+    }
112
+}

+ 5
- 0
react/features/base/lib-jitsi-meet/native/polyfills-browser.js Ver arquivo

@@ -2,6 +2,8 @@ import Iterator from 'es6-iterator';
2 2
 import BackgroundTimer from 'react-native-background-timer';
3 3
 import 'url-polyfill'; // Polyfill for URL constructor
4 4
 
5
+import LocalStorage from './LocalStorage';
6
+
5 7
 /**
6 8
  * Gets the first common prototype of two specified Objects (treating the
7 9
  * objects themselves as prototypes as well).
@@ -264,6 +266,9 @@ function _visitNode(node, callback) {
264 266
         global.document = document;
265 267
     }
266 268
 
269
+    // localStorage
270
+    global.localStorage = new LocalStorage();
271
+
267 272
     // location
268 273
     if (typeof global.location === 'undefined') {
269 274
         global.location = {

Carregando…
Cancelar
Salvar