2024-08-12 05:50:54 -04:00
|
|
|
import { UserId } from '../../../../../types/user'
|
2024-10-23 06:14:35 -04:00
|
|
|
import {
|
|
|
|
createContext,
|
|
|
|
FC,
|
|
|
|
useCallback,
|
|
|
|
useContext,
|
|
|
|
useEffect,
|
|
|
|
useMemo,
|
|
|
|
useState,
|
|
|
|
} from 'react'
|
2024-08-12 05:50:54 -04:00
|
|
|
import useSocketListener from '@/features/ide-react/hooks/use-socket-listener'
|
|
|
|
import { useConnectionContext } from '@/features/ide-react/context/connection-context'
|
|
|
|
import { useProjectContext } from '@/shared/context/project-context'
|
|
|
|
import { useEditorManagerContext } from '@/features/ide-react/context/editor-manager-context'
|
|
|
|
import { useUserContext } from '@/shared/context/user-context'
|
2024-10-23 06:14:35 -04:00
|
|
|
import { postJSON } from '@/infrastructure/fetch-json'
|
|
|
|
import useEventListener from '@/shared/hooks/use-event-listener'
|
|
|
|
import { ProjectContextValue } from '@/shared/context/types/project-context'
|
|
|
|
import { usePermissionsContext } from '@/features/ide-react/context/permissions-context'
|
2024-08-12 05:50:54 -04:00
|
|
|
|
2024-10-23 06:14:35 -04:00
|
|
|
export type TrackChangesState = {
|
|
|
|
onForEveryone: boolean
|
|
|
|
onForGuests: boolean
|
|
|
|
onForMembers: Record<UserId, boolean | undefined>
|
|
|
|
}
|
2024-08-12 05:50:54 -04:00
|
|
|
|
|
|
|
export const TrackChangesStateContext = createContext<
|
|
|
|
TrackChangesState | undefined
|
|
|
|
>(undefined)
|
|
|
|
|
2024-10-23 06:14:35 -04:00
|
|
|
type SaveTrackChangesRequestBody = {
|
|
|
|
on?: boolean
|
|
|
|
on_for?: Record<UserId, boolean | undefined>
|
|
|
|
on_for_guests?: boolean
|
|
|
|
}
|
|
|
|
|
|
|
|
type TrackChangesStateActions = {
|
|
|
|
saveTrackChanges: (trackChangesBody: SaveTrackChangesRequestBody) => void
|
|
|
|
}
|
|
|
|
|
|
|
|
const TrackChangesStateActionsContext = createContext<
|
|
|
|
TrackChangesStateActions | undefined
|
|
|
|
>(undefined)
|
|
|
|
|
2024-08-12 05:50:54 -04:00
|
|
|
export const TrackChangesStateProvider: FC = ({ children }) => {
|
2024-10-23 06:14:35 -04:00
|
|
|
const permissions = usePermissionsContext()
|
2024-08-12 05:50:54 -04:00
|
|
|
const { socket } = useConnectionContext()
|
|
|
|
const project = useProjectContext()
|
|
|
|
const user = useUserContext()
|
|
|
|
const { setWantTrackChanges } = useEditorManagerContext()
|
|
|
|
|
|
|
|
// TODO: update project.trackChangesState instead?
|
2024-10-23 06:14:35 -04:00
|
|
|
const [trackChangesValue, setTrackChangesValue] = useState<
|
|
|
|
ProjectContextValue['trackChangesState']
|
|
|
|
>(project.trackChangesState ?? false)
|
2024-08-12 05:50:54 -04:00
|
|
|
|
2024-10-23 06:14:35 -04:00
|
|
|
useSocketListener(socket, 'toggle-track-changes', setTrackChangesValue)
|
2024-08-12 05:50:54 -04:00
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
setWantTrackChanges(
|
2024-10-23 06:14:35 -04:00
|
|
|
trackChangesValue === true ||
|
|
|
|
(trackChangesValue !== false &&
|
|
|
|
trackChangesValue[user.id ?? '__guests__'])
|
2024-08-12 05:50:54 -04:00
|
|
|
)
|
2024-10-23 06:14:35 -04:00
|
|
|
}, [setWantTrackChanges, trackChangesValue, user.id])
|
|
|
|
|
|
|
|
const actions = useMemo(
|
|
|
|
() => ({
|
|
|
|
async saveTrackChanges(trackChangesBody: SaveTrackChangesRequestBody) {
|
|
|
|
postJSON(`/project/${project._id}/track_changes`, {
|
|
|
|
body: trackChangesBody,
|
|
|
|
})
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
[project._id]
|
|
|
|
)
|
|
|
|
|
|
|
|
const trackChangesIsObject =
|
|
|
|
trackChangesValue !== true && trackChangesValue !== false
|
|
|
|
const onForEveryone = trackChangesValue === true
|
|
|
|
const onForGuests =
|
|
|
|
onForEveryone ||
|
|
|
|
(trackChangesIsObject && trackChangesValue.__guests__ === true)
|
|
|
|
|
|
|
|
const onForMembers = useMemo(() => {
|
|
|
|
const onForMembers: Record<UserId, boolean | undefined> = {}
|
|
|
|
if (trackChangesIsObject) {
|
|
|
|
for (const key of Object.keys(trackChangesValue)) {
|
|
|
|
if (key !== '__guests__') {
|
|
|
|
onForMembers[key as UserId] = trackChangesValue[key as UserId]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return onForMembers
|
|
|
|
}, [trackChangesIsObject, trackChangesValue])
|
|
|
|
|
|
|
|
useEventListener(
|
|
|
|
'toggle-track-changes',
|
|
|
|
useCallback(() => {
|
|
|
|
if (
|
|
|
|
user.id &&
|
|
|
|
project.features.trackChanges &&
|
|
|
|
permissions.write &&
|
|
|
|
!onForEveryone
|
|
|
|
) {
|
|
|
|
const value = onForMembers[user.id]
|
|
|
|
actions.saveTrackChanges({
|
|
|
|
on_for: {
|
|
|
|
...onForMembers,
|
|
|
|
[user.id]: !value,
|
|
|
|
},
|
|
|
|
on_for_guests: onForGuests,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}, [
|
|
|
|
actions,
|
|
|
|
onForMembers,
|
|
|
|
onForGuests,
|
|
|
|
onForEveryone,
|
|
|
|
permissions.write,
|
|
|
|
project.features.trackChanges,
|
|
|
|
user.id,
|
|
|
|
])
|
|
|
|
)
|
|
|
|
|
|
|
|
const value = useMemo(
|
|
|
|
() => ({ onForEveryone, onForGuests, onForMembers }),
|
|
|
|
[onForEveryone, onForGuests, onForMembers]
|
|
|
|
)
|
2024-08-12 05:50:54 -04:00
|
|
|
|
|
|
|
return (
|
2024-10-23 06:14:35 -04:00
|
|
|
<TrackChangesStateActionsContext.Provider value={actions}>
|
|
|
|
<TrackChangesStateContext.Provider value={value}>
|
|
|
|
{children}
|
|
|
|
</TrackChangesStateContext.Provider>
|
|
|
|
</TrackChangesStateActionsContext.Provider>
|
2024-08-12 05:50:54 -04:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
export const useTrackChangesStateContext = () => {
|
|
|
|
return useContext(TrackChangesStateContext)
|
|
|
|
}
|
2024-10-23 06:14:35 -04:00
|
|
|
|
|
|
|
export const useTrackChangesStateActionsContext = () => {
|
|
|
|
const context = useContext(TrackChangesStateActionsContext)
|
|
|
|
if (!context) {
|
|
|
|
throw new Error(
|
|
|
|
'useTrackChangesStateActionsContext is only available inside TrackChangesStateProvider'
|
|
|
|
)
|
|
|
|
}
|
|
|
|
return context
|
|
|
|
}
|