| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- import { UserId } from '../../../../../types/user'
- import {
- createContext,
- FC,
- useCallback,
- useContext,
- useEffect,
- useMemo,
- useState,
- } from 'react'
- 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'
- 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'
- import getMeta from '@/utils/meta'
- export type TrackChangesState = {
- onForEveryone: boolean
- onForGuests: boolean
- onForMembers: Record<UserId, boolean | undefined>
- }
- export const TrackChangesStateContext = createContext<
- TrackChangesState | undefined
- >(undefined)
- type SaveTrackChangesRequestBody = {
- on?: boolean
- on_for?: Record<UserId, boolean | undefined>
- on_for_guests?: boolean
- }
- type TrackChangesStateActions = {
- saveTrackChanges: (trackChangesBody: SaveTrackChangesRequestBody) => void
- saveTrackChangesForCurrentUser: (trackChanges: boolean) => void
- }
- const TrackChangesStateActionsContext = createContext<
- TrackChangesStateActions | undefined
- >(undefined)
- export const TrackChangesStateProvider: FC<React.PropsWithChildren> = ({
- children,
- }) => {
- const permissions = usePermissionsContext()
- const { socket } = useConnectionContext()
- const project = useProjectContext()
- const user = useUserContext()
- const { setWantTrackChanges } = useEditorManagerContext()
- // TODO: update project.trackChangesState instead?
- const [trackChangesValue, setTrackChangesValue] = useState<
- ProjectContextValue['trackChangesState']
- >(project.trackChangesState ?? false)
- useSocketListener(socket, 'toggle-track-changes', setTrackChangesValue)
- useEffect(() => {
- setWantTrackChanges(
- trackChangesValue === true ||
- (trackChangesValue !== false &&
- trackChangesValue[user.id ?? '__guests__'])
- )
- }, [setWantTrackChanges, trackChangesValue, user.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])
- const saveTrackChanges = useCallback(
- async (trackChangesBody: SaveTrackChangesRequestBody) => {
- postJSON(`/project/${project._id}/track_changes`, {
- body: trackChangesBody,
- })
- },
- [project._id]
- )
- const saveTrackChangesForCurrentUser = useCallback(
- async (trackChanges: boolean) => {
- if (user.id) {
- if (getMeta('ol-isReviewerRoleEnabled')) {
- saveTrackChanges({
- on_for: {
- ...onForMembers,
- [user.id]: trackChanges,
- },
- })
- } else {
- saveTrackChanges({
- on_for: {
- ...onForMembers,
- [user.id]: trackChanges,
- },
- on_for_guests: onForGuests,
- })
- }
- }
- },
- [onForMembers, onForGuests, user.id, saveTrackChanges]
- )
- const actions = useMemo(
- () => ({
- saveTrackChanges,
- saveTrackChangesForCurrentUser,
- }),
- [saveTrackChanges, saveTrackChangesForCurrentUser]
- )
- useEventListener(
- 'toggle-track-changes',
- useCallback(() => {
- if (
- user.id &&
- project.features.trackChanges &&
- permissions.write &&
- !onForEveryone
- ) {
- const value = onForMembers[user.id]
- if (getMeta('ol-isReviewerRoleEnabled')) {
- actions.saveTrackChanges({
- on_for: {
- ...onForMembers,
- [user.id]: !value,
- },
- })
- } else {
- 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]
- )
- return (
- <TrackChangesStateActionsContext.Provider value={actions}>
- <TrackChangesStateContext.Provider value={value}>
- {children}
- </TrackChangesStateContext.Provider>
- </TrackChangesStateActionsContext.Provider>
- )
- }
- export const useTrackChangesStateContext = () => {
- return useContext(TrackChangesStateContext)
- }
- export const useTrackChangesStateActionsContext = () => {
- const context = useContext(TrackChangesStateActionsContext)
- if (!context) {
- throw new Error(
- 'useTrackChangesStateActionsContext is only available inside TrackChangesStateProvider'
- )
- }
- return context
- }
|