Skip to content

Commit bdb1670

Browse files
committed
feat: Correctly init DataProxy
We now render the `DataProxyProvider` children only when the DataProxy is correctly initialized on the web. To know this, we rely on the cozy-web-dataproxy app to send a "ready" message once it is indeed ready. This is meant to avoid some timing issues, where the app is ready to request the DataProxy, but the DataProxy is not initialized yet.
1 parent e1c2653 commit bdb1670

File tree

1 file changed

+56
-15
lines changed

1 file changed

+56
-15
lines changed

packages/cozy-dataproxy-lib/src/dataproxy/DataProxyProvider.jsx

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as Comlink from 'comlink'
2-
import React, { useContext, useState, useEffect } from 'react'
2+
import React, { useContext, useState, useEffect, useCallback } from 'react'
33

44
import { useClient } from 'cozy-client'
55
import { isFlagshipApp } from 'cozy-device-helper'
@@ -19,11 +19,12 @@ export const useDataProxy = () => {
1919
return context
2020
}
2121

22-
export const DataProxyProvider = React.memo(({ children, options = {} }) => {
22+
export const DataProxyProvider = React.memo(({ children }) => {
2323
const client = useClient()
2424
const webviewIntent = useWebviewIntent()
2525
const [iframeUrl, setIframeUrl] = useState()
2626
const [dataProxy, setDataProxy] = useState()
27+
const [value, setValue] = useState()
2728
const [dataProxyServicesAvailable, setDataProxyServicesAvailable] =
2829
useState(undefined)
2930

@@ -111,27 +112,68 @@ export const DataProxyProvider = React.memo(({ children, options = {} }) => {
111112
}
112113
}, [client, webviewIntent])
113114

114-
const onIframeLoaded = () => {
115+
const onIframeLoaded = useCallback(() => {
115116
const ifr = document.getElementById('DataProxy')
116117
const remote = Comlink.wrap(Comlink.windowEndpoint(ifr.contentWindow))
117118
setDataProxy(() => remote)
118-
}
119+
}, [setDataProxy])
119120

120-
const search = async search => {
121-
log.log('Send search query to DataProxy')
122-
const result = await dataProxy.search(search, options)
121+
const onReceiveMessage = useCallback(
122+
event => {
123+
if (!event.origin.includes('dataproxy')) {
124+
return
125+
}
126+
const eventData = event?.data
127+
if (eventData && typeof eventData === 'object') {
128+
if (
129+
eventData.type === 'DATAPROXYMESSAGE' &&
130+
eventData.payload === 'READY'
131+
) {
132+
onIframeLoaded()
133+
}
134+
}
135+
},
136+
[onIframeLoaded]
137+
)
123138

124-
return result
125-
}
139+
useEffect(function () {
140+
window.addEventListener('message', onReceiveMessage)
141+
return function () {
142+
window.removeEventListener('message', onReceiveMessage)
143+
}
144+
})
126145

127-
const value = {
128-
dataProxyServicesAvailable,
129-
search
130-
}
146+
useEffect(() => {
147+
const doAsync = async () => {
148+
// Make a global search
149+
const search = async (search, options) => {
150+
log.log('Send search query to DataProxy')
151+
const result = await dataProxy.search(search, options)
152+
return result
153+
}
154+
155+
const newValue = {
156+
dataProxyServicesAvailable,
157+
search
158+
}
159+
160+
client.links.forEach(link => {
161+
if (link.registerDataProxy) {
162+
// This is required as the DataProxy is not ready when the DataProxyLink is created
163+
link.registerDataProxy(newValue)
164+
}
165+
})
166+
167+
setValue(newValue)
168+
}
169+
if (dataProxy && client?.links) {
170+
doAsync()
171+
}
172+
}, [dataProxy, client, dataProxyServicesAvailable])
131173

132174
return (
133175
<DataProxyContext.Provider value={value}>
134-
{children}
176+
{value && children}
135177
{iframeUrl ? (
136178
<iframe
137179
id="DataProxy"
@@ -143,7 +185,6 @@ export const DataProxyProvider = React.memo(({ children, options = {} }) => {
143185
height: 0
144186
}}
145187
sandbox="allow-same-origin allow-scripts"
146-
onLoad={onIframeLoaded}
147188
></iframe>
148189
) : undefined}
149190
</DataProxyContext.Provider>

0 commit comments

Comments
 (0)