mirror of
https://github.com/overleaf/overleaf.git
synced 2024-10-31 21:21:03 -04:00
2340b1b25e
* Move DetachProvider outside EditorProvider * Add "[PDF]" prefix to detached window title GitOrigin-RevId: 7d09f4053069b20d55a2a04a8f29f90b973e50b9
143 lines
3.5 KiB
JavaScript
143 lines
3.5 KiB
JavaScript
import {
|
|
createContext,
|
|
useContext,
|
|
useCallback,
|
|
useMemo,
|
|
useEffect,
|
|
useState,
|
|
} from 'react'
|
|
import PropTypes from 'prop-types'
|
|
import sysend from 'sysend'
|
|
import getMeta from '../../utils/meta'
|
|
import { buildUrlWithDetachRole } from '../utils/url-helper'
|
|
import useCallbackHandlers from '../hooks/use-callback-handlers'
|
|
|
|
export const DetachContext = createContext()
|
|
|
|
DetachContext.Provider.propTypes = {
|
|
value: PropTypes.shape({
|
|
role: PropTypes.oneOf(['detacher', 'detached', null]),
|
|
setRole: PropTypes.func.isRequired,
|
|
broadcastEvent: PropTypes.func.isRequired,
|
|
addEventHandler: PropTypes.func.isRequired,
|
|
deleteEventHandler: PropTypes.func.isRequired,
|
|
}).isRequired,
|
|
}
|
|
|
|
const debugPdfDetach = getMeta('ol-debugPdfDetach')
|
|
|
|
const SYSEND_CHANNEL = `detach-${getMeta('ol-project_id')}`
|
|
|
|
export function DetachProvider({ children }) {
|
|
const [lastDetachedConnectedAt, setLastDetachedConnectedAt] = useState()
|
|
const [role, setRole] = useState(() => getMeta('ol-detachRole') || null)
|
|
const {
|
|
addHandler: addEventHandler,
|
|
deleteHandler: deleteEventHandler,
|
|
callHandlers: callEventHandlers,
|
|
} = useCallbackHandlers()
|
|
|
|
useEffect(() => {
|
|
if (debugPdfDetach) {
|
|
console.log('Effect', { role })
|
|
}
|
|
window.history.replaceState({}, '', buildUrlWithDetachRole(role).toString())
|
|
}, [role])
|
|
|
|
useEffect(() => {
|
|
sysend.on(SYSEND_CHANNEL, message => {
|
|
if (debugPdfDetach) {
|
|
console.log(`Receiving:`, message)
|
|
}
|
|
callEventHandlers(message)
|
|
})
|
|
return () => sysend.off(SYSEND_CHANNEL)
|
|
}, [callEventHandlers])
|
|
|
|
const broadcastEvent = useCallback(
|
|
(event, data) => {
|
|
if (!role) {
|
|
if (debugPdfDetach) {
|
|
console.log('Not Broadcasting (no role)', {
|
|
role,
|
|
event,
|
|
data,
|
|
})
|
|
}
|
|
return
|
|
}
|
|
if (debugPdfDetach) {
|
|
console.log('Broadcasting', {
|
|
role,
|
|
event,
|
|
data,
|
|
})
|
|
}
|
|
const message = {
|
|
role,
|
|
event,
|
|
}
|
|
if (data) {
|
|
message.data = data
|
|
}
|
|
sysend.broadcast(SYSEND_CHANNEL, message)
|
|
},
|
|
[role]
|
|
)
|
|
|
|
useEffect(() => {
|
|
broadcastEvent('connected')
|
|
}, [broadcastEvent])
|
|
|
|
useEffect(() => {
|
|
const onBeforeUnload = () => broadcastEvent('closed')
|
|
window.addEventListener('beforeunload', onBeforeUnload)
|
|
return () => window.removeEventListener('beforeunload', onBeforeUnload)
|
|
}, [broadcastEvent])
|
|
|
|
useEffect(() => {
|
|
const updateLastDetachedConnectedAt = message => {
|
|
if (message.role === 'detached' && message.event === 'connected') {
|
|
setLastDetachedConnectedAt(new Date())
|
|
}
|
|
}
|
|
addEventHandler(updateLastDetachedConnectedAt)
|
|
return () => deleteEventHandler(updateLastDetachedConnectedAt)
|
|
}, [addEventHandler, deleteEventHandler])
|
|
|
|
const value = useMemo(
|
|
() => ({
|
|
role,
|
|
setRole,
|
|
broadcastEvent,
|
|
lastDetachedConnectedAt,
|
|
addEventHandler,
|
|
deleteEventHandler,
|
|
}),
|
|
[
|
|
role,
|
|
setRole,
|
|
broadcastEvent,
|
|
lastDetachedConnectedAt,
|
|
addEventHandler,
|
|
deleteEventHandler,
|
|
]
|
|
)
|
|
|
|
return (
|
|
<DetachContext.Provider value={value}>{children}</DetachContext.Provider>
|
|
)
|
|
}
|
|
|
|
DetachProvider.propTypes = {
|
|
children: PropTypes.any,
|
|
}
|
|
|
|
export function useDetachContext(propTypes) {
|
|
const data = useContext(DetachContext)
|
|
if (!data) {
|
|
throw new Error('useDetachContext is only available inside DetachProvider')
|
|
}
|
|
PropTypes.checkPropTypes(propTypes, data, 'data', 'DetachContext.Provider')
|
|
return data
|
|
}
|