@rpcbase/client 0.51.0 → 0.53.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/AppProvider/debug.js +4 -0
- package/AppProvider/index.js +35 -0
- package/hashState.js +141 -0
- package/package.json +2 -1
- package/AppProvider/index.web.js +0 -8
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/* @flow */
|
|
2
|
+
import "./debug"
|
|
3
|
+
|
|
4
|
+
import {PostHogProvider} from "posthog-js/react"
|
|
5
|
+
|
|
6
|
+
import {HashStateProvider} from "../hashState"
|
|
7
|
+
|
|
8
|
+
// TODO: flags here should be optional
|
|
9
|
+
import {flagValues} from "config/flags"
|
|
10
|
+
|
|
11
|
+
import {POSTHOG_KEY} from "env"
|
|
12
|
+
|
|
13
|
+
const AppProvider = ({children, ...props}) => {
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<PostHogProvider
|
|
18
|
+
apiKey={POSTHOG_KEY}
|
|
19
|
+
options={{
|
|
20
|
+
api_host: "https://eu.posthog.com",
|
|
21
|
+
// TODO: this doesn't work
|
|
22
|
+
bootstrap: {
|
|
23
|
+
featureFlags: flagValues,
|
|
24
|
+
},
|
|
25
|
+
}}
|
|
26
|
+
>
|
|
27
|
+
<HashStateProvider>
|
|
28
|
+
{children}
|
|
29
|
+
</HashStateProvider>
|
|
30
|
+
</PostHogProvider>
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default AppProvider
|
package/hashState.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/* @flow */
|
|
2
|
+
import {useState, useEffect, createContext, useContext, useCallback} from "react"
|
|
3
|
+
import LZString from "lz-string"
|
|
4
|
+
import _isNil from "lodash/isNil"
|
|
5
|
+
import _omitBy from "lodash/omitBy"
|
|
6
|
+
import isEqual from "fast-deep-equal"
|
|
7
|
+
|
|
8
|
+
import {PAGE_NAVIGATION} from "config/events"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
const EMPTY_STATE_TOKEN = "N4XyA" // lz-string encoded empty state ''
|
|
12
|
+
|
|
13
|
+
// WARNING: this assumes hash_str starts with "#"
|
|
14
|
+
const parse_hash_str = (hash_str = window.location.hash) => {
|
|
15
|
+
if (hash_str.length < 1) {
|
|
16
|
+
return {}
|
|
17
|
+
}
|
|
18
|
+
const current_state_str = hash_str.slice(1)
|
|
19
|
+
let parsed
|
|
20
|
+
try {
|
|
21
|
+
const decoded = LZString.decompressFromEncodedURIComponent(current_state_str)
|
|
22
|
+
parsed = JSON.parse(decoded)
|
|
23
|
+
} catch (e) {
|
|
24
|
+
console.error(e)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return parsed || {}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// On first load, retrieve hashState from URL
|
|
31
|
+
const __initial_state = _omitBy(parse_hash_str(), _isNil)
|
|
32
|
+
|
|
33
|
+
export const encode_payload = (payload) =>
|
|
34
|
+
LZString.compressToEncodedURIComponent(JSON.stringify(payload))
|
|
35
|
+
|
|
36
|
+
// add payload to window hash
|
|
37
|
+
const apply_hash_state = (payload) => {
|
|
38
|
+
const str = encode_payload(payload)
|
|
39
|
+
|
|
40
|
+
if (str === EMPTY_STATE_TOKEN) {
|
|
41
|
+
history.replaceState(null, null, window.location.pathname)
|
|
42
|
+
} else {
|
|
43
|
+
history.replaceState(null, null, `${window.location.pathname}#${encode_payload(payload)}`)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const HashContext = createContext({
|
|
48
|
+
hashState: {},
|
|
49
|
+
serializeHashState: () => null,
|
|
50
|
+
encodeHashLink: () => null,
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
export const useHashState = () => {
|
|
54
|
+
return useContext(HashContext)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const withHashState = (Component) => {
|
|
58
|
+
const WrappedComp = ({children, ...props}) => {
|
|
59
|
+
const hashCtx = useContext(HashContext)
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<Component
|
|
63
|
+
{...props}
|
|
64
|
+
hashState={hashCtx.hashState}
|
|
65
|
+
serializeHashState={hashCtx.serializeHashState}
|
|
66
|
+
encodeHashLink={hashCtx.encodeHashLink}
|
|
67
|
+
/>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
WrappedComp.displayName = `withHashState(${Component.displayName})`
|
|
72
|
+
|
|
73
|
+
return WrappedComp
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export const HashStateProvider = ({children}) => {
|
|
77
|
+
const [hashState, setHashState] = useState(__initial_state)
|
|
78
|
+
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
const onChange = (ev) => {
|
|
81
|
+
const newHashStr = ev.detail.context?.hash
|
|
82
|
+
if (!newHashStr) return
|
|
83
|
+
// WARNING: page.js strips the "#" we add it back
|
|
84
|
+
const parsed = _omitBy(parse_hash_str(`#${newHashStr}`), _isNil)
|
|
85
|
+
const newState = {
|
|
86
|
+
...hashState,
|
|
87
|
+
...parsed,
|
|
88
|
+
}
|
|
89
|
+
// apply only if changed
|
|
90
|
+
if (!isEqual(hashState, newState)) {
|
|
91
|
+
setHashState(newState)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
document.body.addEventListener(PAGE_NAVIGATION, onChange)
|
|
95
|
+
|
|
96
|
+
return () => document.body.removeEventListener(PAGE_NAVIGATION, onChange)
|
|
97
|
+
}, [hashState, setHashState])
|
|
98
|
+
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
apply_hash_state(hashState)
|
|
101
|
+
window.__PRIVATE_HASH_STATE_DO_NOT_USE = hashState
|
|
102
|
+
}, [hashState])
|
|
103
|
+
|
|
104
|
+
const serializeHashState = useCallback((payload) => {
|
|
105
|
+
setHashState((current) => {
|
|
106
|
+
// clone and remove nil values
|
|
107
|
+
const newState = _omitBy(
|
|
108
|
+
{
|
|
109
|
+
...current,
|
|
110
|
+
...payload,
|
|
111
|
+
},
|
|
112
|
+
_isNil,
|
|
113
|
+
)
|
|
114
|
+
return newState
|
|
115
|
+
})
|
|
116
|
+
}, [])
|
|
117
|
+
|
|
118
|
+
const encodeHashLink = useCallback((payload) => {
|
|
119
|
+
const newState = _omitBy(
|
|
120
|
+
{
|
|
121
|
+
...hashState,
|
|
122
|
+
...payload,
|
|
123
|
+
},
|
|
124
|
+
_isNil,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
return encode_payload(newState)
|
|
128
|
+
}, [])
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
<HashContext.Provider
|
|
132
|
+
value={{
|
|
133
|
+
hashState,
|
|
134
|
+
serializeHashState,
|
|
135
|
+
encodeHashLink,
|
|
136
|
+
}}
|
|
137
|
+
>
|
|
138
|
+
{children}
|
|
139
|
+
</HashContext.Provider>
|
|
140
|
+
)
|
|
141
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rpcbase/client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.53.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"test": "echo \"Error: no test specified\" && exit 0"
|
|
6
6
|
},
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"pouchdb-adapter-indexeddb": "8.0.1",
|
|
14
14
|
"pouchdb-core": "8.0.1",
|
|
15
15
|
"pouchdb-find": "8.0.1",
|
|
16
|
+
"posthog-js": "1.70.0",
|
|
16
17
|
"react-i18next": "13.0.1",
|
|
17
18
|
"socket.io-client": "4.7.1"
|
|
18
19
|
}
|