@rpcbase/client 0.106.0 → 0.110.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/hashState.js CHANGED
@@ -3,7 +3,8 @@ import {useState, useEffect, createContext, useContext, useCallback} from "react
3
3
  import LZString from "lz-string"
4
4
  import _isNil from "lodash/isNil"
5
5
  import _omitBy from "lodash/omitBy"
6
- import isEqual from "fast-deep-equal"
6
+
7
+ import isEqualValues from "./isEqualValues"
7
8
 
8
9
 
9
10
  const PAGE_NAVIGATION_EVENT = "RB_PAGE_NAVIGATION"
@@ -87,7 +88,7 @@ export const HashStateProvider = ({children}) => {
87
88
  ...parsed,
88
89
  }
89
90
  // apply only if changed
90
- if (!isEqual(hashState, newState)) {
91
+ if (!isEqualValues(hashState, newState)) {
91
92
  setHashState(newState)
92
93
  }
93
94
  }
@@ -0,0 +1,47 @@
1
+ /* @flow */
2
+ const isEqual = require("fast-deep-equal/react")
3
+
4
+
5
+ const isPlainObject = (obj) => {
6
+ return Object.prototype.toString.call(obj) === "[object Object]"
7
+ }
8
+
9
+ const sortValuesConsideringObjects = (values) => {
10
+ return values
11
+ .map(val => (isPlainObject(val) ? sortValuesConsideringObjects(Object.values(val)) : val))
12
+ .sort()
13
+ }
14
+
15
+ const isEqualValues = (a, b) => {
16
+ // Extract values and sort them if they belong to plain objects
17
+ const valsA = isPlainObject(a) ? sortValuesConsideringObjects(Object.values(a)) : a
18
+ const valsB = isPlainObject(b) ? sortValuesConsideringObjects(Object.values(b)) : b
19
+
20
+ if (valsA === null && valsB === null) {
21
+ return true
22
+ }
23
+
24
+ if (Array.isArray(valsA) || Array.isArray(valsB)) {
25
+ return isEqual(valsA, valsB)
26
+ }
27
+
28
+ // Check value count
29
+ if (valsA.length !== valsB.length) return false
30
+
31
+ // Compare the sorted arrays of values
32
+ for (let i = 0; i < valsA.length; i++) {
33
+ if (typeof valsA[i] === "object" && typeof valsB[i] === "object") {
34
+ if (!isEqualValues(valsA[i], valsB[i])) {
35
+ return false
36
+ }
37
+ } else {
38
+ if (!isEqual(valsA[i], valsB[i])) {
39
+ return false
40
+ }
41
+ }
42
+ }
43
+ return true
44
+ }
45
+
46
+
47
+ module.exports = isEqualValues
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpcbase/client",
3
- "version": "0.106.0",
3
+ "version": "0.110.0",
4
4
  "scripts": {
5
5
  "build-firebase": "webpack -c firebase/webpack.config.js",
6
6
  "build": "yarn build-firebase",
@@ -3,10 +3,13 @@ import assert from "assert"
3
3
  import {Platform} from "react-native"
4
4
  import {useCallback, useEffect, useState, useMemo, useId, useRef} from "react"
5
5
  import debug from "debug"
6
- import isEqual from "fast-deep-equal/react"
7
6
  import _omit from "lodash/omit"
7
+ import LZString from "lz-string"
8
8
 
9
- import get_uid from "../auth/get_uid"
9
+ import isEqualValues from "../../isEqualValues"
10
+ import get_uid from "../../auth/get_uid"
11
+
12
+ import useData from "./useData"
10
13
 
11
14
 
12
15
  const log = debug("rb:rts:useQuery")
@@ -27,6 +30,7 @@ const getUseQuery = (register_query) => (
27
30
  return _uid
28
31
  }, [])
29
32
 
33
+ // used to track if data was loaded synchronously (no need to show any loader)
30
34
  const hasInitiallySetFromStorage = useRef(false)
31
35
  const hasFirstReply = useRef(false)
32
36
  const hasNetworkReply = useRef(false)
@@ -46,31 +50,7 @@ const getUseQuery = (register_query) => (
46
50
 
47
51
  const [source, setSource] = useState()
48
52
 
49
- const [data, setData] = useState(() => {
50
- if (!useStorage) {
51
- return
52
- }
53
-
54
- if (Platform.OS === "web") {
55
- const item = localStorage.getItem(storageKey)
56
- if (!item) return
57
-
58
- hasInitiallySetFromStorage.current = true
59
-
60
- let parsedItem
61
- try {
62
- parsedItem = JSON.parse(item)
63
- } catch (err) {
64
- //
65
- }
66
- if (parsedItem) {
67
- return parsedItem
68
- }
69
- } else {
70
- // TODO: fast storage not implemented on mobile
71
- console.log("fast storage mobile nOT IMPLEMENTED")
72
- }
73
- })
53
+ const [data, setData] = useData({useStorage, storageKey, hasInitiallySetFromStorage})
74
54
 
75
55
  const [error, setError] = useState()
76
56
 
@@ -93,7 +73,7 @@ const getUseQuery = (register_query) => (
93
73
  // we only save network queries
94
74
  if (useStorage && context.source === "network") {
95
75
  if (Platform.OS === "web") {
96
- localStorage.setItem(storageKey, JSON.stringify(newData))
76
+ localStorage.setItem(storageKey, LZString.compressToUTF16(JSON.stringify(newData)))
97
77
  } else {
98
78
  // TODO: rn fast storage async
99
79
  }
@@ -162,7 +142,7 @@ const getUseQuery = (register_query) => (
162
142
  hasFirstReply.current = true
163
143
 
164
144
  // skip if we already have the data
165
- if (isEqual(data, newData)) {
145
+ if (isEqualValues(data, newData)) {
166
146
  applyContext(context)
167
147
  return
168
148
  }
@@ -178,7 +158,7 @@ const getUseQuery = (register_query) => (
178
158
  return
179
159
  }
180
160
 
181
- if (!isEqual(data, newData)) {
161
+ if (!isEqualValues(data, newData)) {
182
162
  applyContext(context)
183
163
  applyNewData(newData, context)
184
164
  } else {
@@ -0,0 +1,55 @@
1
+ /* @flow */
2
+ import {useState} from "react"
3
+ import {Platform} from "react-native"
4
+ import LZString from "lz-string"
5
+
6
+
7
+ const useData = ({useStorage, storageKey, hasInitiallySetFromStorage}) => {
8
+ const [data, setData] = useState(() => {
9
+ if (!useStorage) {
10
+ return
11
+ }
12
+
13
+ if (Platform.OS === "web") {
14
+ const itemStr = localStorage.getItem(storageKey)
15
+ if (!itemStr) return
16
+
17
+ let decompressedItem
18
+ try {
19
+ decompressedItem = LZString.decompressFromUTF16(itemStr)
20
+ } catch (err) {
21
+ //
22
+ }
23
+
24
+ if (!decompressedItem) {
25
+ localStorage.removeItem(storageKey)
26
+ return
27
+ }
28
+
29
+
30
+ let parsedItem
31
+ try {
32
+ parsedItem = JSON.parse(decompressedItem)
33
+ } catch (err) {
34
+ //
35
+ }
36
+ //
37
+ if (!parsedItem) {
38
+ localStorage.removeItem(storageKey)
39
+ return
40
+ }
41
+
42
+ // success
43
+ hasInitiallySetFromStorage.current = true
44
+ return parsedItem
45
+
46
+ } else {
47
+ // TODO: fast storage not implemented on mobile
48
+ console.log("fast storage mobile nOT IMPLEMENTED")
49
+ }
50
+ })
51
+
52
+ return [data, setData]
53
+ }
54
+
55
+ export default useData