Merge pull request #15397 from overleaf/ii-ide-page-prototype-review-panel

Init review panel for React IDE page

GitOrigin-RevId: fc23201055ae892c5c1d5cb88e472a0bb0cd6c25
This commit is contained in:
ilkin-overleaf
2023-11-03 09:00:02 +00:00
committed by Copybot
parent 9eb8743014
commit 0c403bf8e3
9 changed files with 440 additions and 8 deletions
@@ -9,6 +9,7 @@ import React, {
} from 'react'
import { ReactScopeValueStore } from '@/features/ide-react/scope-value-store/react-scope-value-store'
import populateLayoutScope from '@/features/ide-react/scope-adapters/layout-context-adapter'
import populateReviewPanelScope from '@/features/ide-react/scope-adapters/review-panel-context-adapter'
import { IdeProvider } from '@/shared/context/ide-context'
import {
createIdeEventEmitter,
@@ -22,8 +23,8 @@ import { postJSON } from '@/infrastructure/fetch-json'
import { EventLog } from '@/features/ide-react/editor/event-log'
import { populateSettingsScope } from '@/features/ide-react/scope-adapters/settings-adapter'
import { populateOnlineUsersScope } from '@/features/ide-react/context/online-users-context'
import { ReactScopeEventEmitter } from '@/features/ide-react/scope-event-emitter/react-scope-event-emitter'
import { populateReferenceScope } from '@/features/ide-react/context/references-context'
import { ReactScopeEventEmitter } from '@/features/ide-react/scope-event-emitter/react-scope-event-emitter'
type IdeReactContextValue = {
projectId: string
@@ -75,6 +76,7 @@ function createReactScopeValueStore() {
populateOnlineUsersScope(scopeStore)
populateReferenceScope(scopeStore)
populateFileTreeScope(scopeStore)
populateReviewPanelScope(scopeStore)
scopeStore.allowNonExistentPath('hasLintingError')
scopeStore.allowNonExistentPath('loadingThreads')
@@ -0,0 +1,273 @@
import { useState, useMemo, useCallback } from 'react'
import useScopeValue from '../../../../../shared/hooks/use-scope-value'
import { sendMB } from '../../../../../infrastructure/event-tracking'
import { dispatchReviewPanelLayout as handleLayoutChange } from '@/features/source-editor/extensions/changes/change-manager'
import { useProjectContext } from '@/shared/context/project-context'
import { useLayoutContext } from '@/shared/context/layout-context'
import { ReviewPanelStateReactIde } from '../types/review-panel-state'
import * as ReviewPanel from '../types/review-panel-state'
import {
SubView,
ThreadId,
} from '../../../../../../../types/review-panel/review-panel'
function useReviewPanelState(): ReviewPanelStateReactIde {
const { reviewPanelOpen, setReviewPanelOpen } = useLayoutContext()
const {
features: { trackChangesVisible },
} = useProjectContext()
const [subView, setSubView] = useScopeValue<ReviewPanel.Value<'subView'>>(
'reviewPanel.subView'
)
const [loading] = useScopeValue<ReviewPanel.Value<'loading'>>(
'reviewPanel.overview.loading'
)
const [nVisibleSelectedChanges] = useScopeValue<
ReviewPanel.Value<'nVisibleSelectedChanges'>
>('reviewPanel.nVisibleSelectedChanges')
const [collapsed, setCollapsed] = useScopeValue<
ReviewPanel.Value<'collapsed'>
>('reviewPanel.overview.docsCollapsedState')
const [commentThreads] = useScopeValue<ReviewPanel.Value<'commentThreads'>>(
'reviewPanel.commentThreads',
true
)
const [docs] = useScopeValue<ReviewPanel.Value<'docs'>>('docs')
const [entries] = useScopeValue<ReviewPanel.Value<'entries'>>(
'reviewPanel.entries',
true
)
const [loadingThreads] =
useScopeValue<ReviewPanel.Value<'loadingThreads'>>('loadingThreads')
const [permissions] =
useScopeValue<ReviewPanel.Value<'permissions'>>('permissions')
const [users] = useScopeValue<ReviewPanel.Value<'users'>>('users', true)
const [resolvedComments] = useScopeValue<
ReviewPanel.Value<'resolvedComments'>
>('reviewPanel.resolvedComments', true)
const [wantTrackChanges] = useScopeValue<
ReviewPanel.Value<'wantTrackChanges'>
>('editor.wantTrackChanges')
const [openDocId] =
useScopeValue<ReviewPanel.Value<'openDocId'>>('editor.open_doc_id')
const [shouldCollapse, setShouldCollapse] = useScopeValue<
ReviewPanel.Value<'shouldCollapse'>
>('reviewPanel.fullTCStateCollapsed')
const [lineHeight] = useScopeValue<number>(
'reviewPanel.rendererData.lineHeight'
)
const [toggleTrackChangesForEveryone] = useScopeValue<
ReviewPanel.UpdaterFn<'toggleTrackChangesForEveryone'>
>('toggleTrackChangesForEveryone')
const [toggleTrackChangesForUser] = useScopeValue<
ReviewPanel.UpdaterFn<'toggleTrackChangesForUser'>
>('toggleTrackChangesForUser')
const [toggleTrackChangesForGuests] = useScopeValue<
ReviewPanel.UpdaterFn<'toggleTrackChangesForGuests'>
>('toggleTrackChangesForGuests')
const [trackChangesState] = useScopeValue<
ReviewPanel.Value<'trackChangesState'>
>('reviewPanel.trackChangesState')
const [trackChangesOnForEveryone] = useScopeValue<
ReviewPanel.Value<'trackChangesOnForEveryone'>
>('reviewPanel.trackChangesOnForEveryone')
const [trackChangesOnForGuests] = useScopeValue<
ReviewPanel.Value<'trackChangesOnForGuests'>
>('reviewPanel.trackChangesOnForGuests')
const [trackChangesForGuestsAvailable] = useScopeValue<
ReviewPanel.Value<'trackChangesForGuestsAvailable'>
>('reviewPanel.trackChangesForGuestsAvailable')
const [resolveComment] =
useScopeValue<ReviewPanel.UpdaterFn<'resolveComment'>>('resolveComment')
const [submitNewComment] =
useScopeValue<ReviewPanel.UpdaterFn<'submitNewComment'>>('submitNewComment')
const [deleteComment] =
useScopeValue<ReviewPanel.UpdaterFn<'deleteComment'>>('deleteComment')
const [gotoEntry] =
useScopeValue<ReviewPanel.UpdaterFn<'gotoEntry'>>('gotoEntry')
const [saveEdit] =
useScopeValue<ReviewPanel.UpdaterFn<'saveEdit'>>('saveEdit')
const [submitReplyAngular] =
useScopeValue<
(entry: { thread_id: ThreadId; replyContent: string }) => void
>('submitReply')
const [formattedProjectMembers] = useScopeValue<
ReviewPanel.Value<'formattedProjectMembers'>
>('reviewPanel.formattedProjectMembers')
const toggleReviewPanel = useCallback(() => {
if (!trackChangesVisible) {
return
}
setReviewPanelOpen(value => !value)
sendMB('rp-toggle-panel', {
value: reviewPanelOpen,
})
}, [reviewPanelOpen, setReviewPanelOpen, trackChangesVisible])
const [unresolveComment] =
useScopeValue<ReviewPanel.UpdaterFn<'unresolveComment'>>('unresolveComment')
const [deleteThread] =
useScopeValue<ReviewPanel.UpdaterFn<'deleteThread'>>('deleteThread')
const [refreshResolvedCommentsDropdown] = useScopeValue<
ReviewPanel.UpdaterFn<'refreshResolvedCommentsDropdown'>
>('refreshResolvedCommentsDropdown')
const [acceptChanges] =
useScopeValue<ReviewPanel.UpdaterFn<'acceptChanges'>>('acceptChanges')
const [rejectChanges] =
useScopeValue<ReviewPanel.UpdaterFn<'rejectChanges'>>('rejectChanges')
const [bulkAcceptActions] =
useScopeValue<ReviewPanel.UpdaterFn<'bulkAcceptActions'>>(
'bulkAcceptActions'
)
const [bulkRejectActions] =
useScopeValue<ReviewPanel.UpdaterFn<'bulkRejectActions'>>(
'bulkRejectActions'
)
const handleSetSubview = useCallback(
(subView: SubView) => {
setSubView(subView)
sendMB('rp-subview-change', { subView })
},
[setSubView]
)
const submitReply = useCallback(
(threadId: ThreadId, replyContent: string) => {
submitReplyAngular({ thread_id: threadId, replyContent })
},
[submitReplyAngular]
)
const [entryHover, setEntryHover] = useState(false)
const [isAddingComment, setIsAddingComment] = useState(false)
const [navHeight, setNavHeight] = useState(0)
const [toolbarHeight, setToolbarHeight] = useState(0)
const [layoutSuspended, setLayoutSuspended] = useState(false)
const values = useMemo<ReviewPanelStateReactIde['values']>(
() => ({
collapsed,
commentThreads,
docs,
entries,
entryHover,
isAddingComment,
loadingThreads,
nVisibleSelectedChanges,
permissions,
users,
resolvedComments,
shouldCollapse,
navHeight,
toolbarHeight,
subView,
wantTrackChanges,
loading,
openDocId,
lineHeight,
trackChangesState,
trackChangesOnForEveryone,
trackChangesOnForGuests,
trackChangesForGuestsAvailable,
formattedProjectMembers,
layoutSuspended,
}),
[
collapsed,
commentThreads,
docs,
entries,
entryHover,
isAddingComment,
loadingThreads,
nVisibleSelectedChanges,
permissions,
users,
resolvedComments,
shouldCollapse,
navHeight,
toolbarHeight,
subView,
wantTrackChanges,
loading,
openDocId,
lineHeight,
trackChangesState,
trackChangesOnForEveryone,
trackChangesOnForGuests,
trackChangesForGuestsAvailable,
formattedProjectMembers,
layoutSuspended,
]
)
const updaterFns = useMemo<ReviewPanelStateReactIde['updaterFns']>(
() => ({
handleSetSubview,
handleLayoutChange,
gotoEntry,
resolveComment,
submitReply,
acceptChanges,
rejectChanges,
toggleReviewPanel,
bulkAcceptActions,
bulkRejectActions,
saveEdit,
submitNewComment,
deleteComment,
unresolveComment,
refreshResolvedCommentsDropdown,
deleteThread,
toggleTrackChangesForEveryone,
toggleTrackChangesForUser,
toggleTrackChangesForGuests,
setEntryHover,
setCollapsed,
setShouldCollapse,
setIsAddingComment,
setNavHeight,
setToolbarHeight,
setLayoutSuspended,
}),
[
handleSetSubview,
gotoEntry,
resolveComment,
submitReply,
acceptChanges,
rejectChanges,
toggleReviewPanel,
bulkAcceptActions,
bulkRejectActions,
saveEdit,
submitNewComment,
deleteComment,
unresolveComment,
refreshResolvedCommentsDropdown,
deleteThread,
toggleTrackChangesForEveryone,
toggleTrackChangesForUser,
toggleTrackChangesForGuests,
setCollapsed,
setEntryHover,
setShouldCollapse,
setIsAddingComment,
setNavHeight,
setToolbarHeight,
setLayoutSuspended,
]
)
return { values, updaterFns }
}
export default useReviewPanelState
@@ -0,0 +1,43 @@
import { useContext, createContext } from 'react'
import useReviewPanelState from '@/features/ide-react/context/review-panel/hooks/use-review-panel-state'
import { ReviewPanelStateReactIde } from '@/features/ide-react/context/review-panel/types/review-panel-state'
export const ReviewPanelReactIdeValueContext = createContext<
ReviewPanelStateReactIde['values'] | undefined
>(undefined)
export const ReviewPanelReactIdeUpdaterFnsContext = createContext<
ReviewPanelStateReactIde['updaterFns'] | undefined
>(undefined)
export const ReviewPanelReactIdeProvider: React.FC = ({ children }) => {
const { values, updaterFns } = useReviewPanelState()
return (
<ReviewPanelReactIdeValueContext.Provider value={values}>
<ReviewPanelReactIdeUpdaterFnsContext.Provider value={updaterFns}>
{children}
</ReviewPanelReactIdeUpdaterFnsContext.Provider>
</ReviewPanelReactIdeValueContext.Provider>
)
}
export function useReviewPanelReactIdeValueContext() {
const context = useContext(ReviewPanelReactIdeValueContext)
if (!context) {
throw new Error(
'ReviewPanelReactIdeValueContext is only available inside ReviewPanelReactIdeProvider'
)
}
return context
}
export function useReviewPanelReactIdeUpdaterFnsContext() {
const context = useContext(ReviewPanelReactIdeUpdaterFnsContext)
if (!context) {
throw new Error(
'ReviewPanelReactIdeUpdaterFnsContext is only available inside ReviewPanelReactIdeProvider'
)
}
return context
}
@@ -0,0 +1,11 @@
import { ReviewPanelState } from '@/features/source-editor/context/review-panel/types/review-panel-state'
export interface ReviewPanelStateReactIde extends ReviewPanelState {}
// Getter for values
export type Value<T extends keyof ReviewPanelStateReactIde['values']> =
ReviewPanelStateReactIde['values'][T]
// Getter for stable functions
export type UpdaterFn<T extends keyof ReviewPanelStateReactIde['updaterFns']> =
ReviewPanelStateReactIde['updaterFns'][T]