mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-06-08 00:29:04 +02:00
Add full project search UI (#22671)
GitOrigin-RevId: f40c85f40f4c16b4b3c26a197924cd9ac9b3db1f
This commit is contained in:
@@ -333,6 +333,7 @@ const _ProjectController = {
|
||||
const splitTests = [
|
||||
!anonymous && 'bib-file-tpr-prompt',
|
||||
'compile-log-events',
|
||||
'full-project-search',
|
||||
'math-preview',
|
||||
'null-test-share-modal',
|
||||
'paywall-cta',
|
||||
|
||||
@@ -983,6 +983,8 @@ module.exports = {
|
||||
autoCompleteExtensions: [],
|
||||
sectionTitleGenerators: [],
|
||||
toastGenerators: [],
|
||||
editorSidebarComponents: [],
|
||||
fileTreeToolbarComponents: [],
|
||||
},
|
||||
|
||||
moduleImportSequence: [
|
||||
|
||||
@@ -7,6 +7,12 @@ import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import OLButtonToolbar from '@/features/ui/components/ol/ol-button-toolbar'
|
||||
import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
|
||||
import React, { ElementType } from 'react'
|
||||
|
||||
const fileTreeToolbarComponents = importOverleafModules(
|
||||
'fileTreeToolbarComponents'
|
||||
) as { import: { default: ElementType }; path: string }[]
|
||||
|
||||
function FileTreeToolbar() {
|
||||
const { fileTreeReadOnly } = useFileTreeData()
|
||||
@@ -105,12 +111,14 @@ function FileTreeToolbarRight() {
|
||||
const { canRename, canDelete, startRenaming, startDeleting } =
|
||||
useFileTreeActionable()
|
||||
|
||||
if (!canRename && !canDelete) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="toolbar-right">
|
||||
{fileTreeToolbarComponents.map(
|
||||
({ import: { default: Component }, path }) => (
|
||||
<Component key={path} />
|
||||
)
|
||||
)}
|
||||
|
||||
{canRename ? (
|
||||
<OLTooltip
|
||||
id="rename"
|
||||
@@ -127,6 +135,7 @@ function FileTreeToolbarRight() {
|
||||
</button>
|
||||
</OLTooltip>
|
||||
) : null}
|
||||
|
||||
{canDelete ? (
|
||||
<OLTooltip
|
||||
id="delete"
|
||||
|
||||
@@ -5,6 +5,12 @@ import classNames from 'classnames'
|
||||
import { useLayoutContext } from '@/shared/context/layout-context'
|
||||
import { OutlineContainer } from '@/features/outline/components/outline-container'
|
||||
import { useOutlinePane } from '@/features/ide-react/hooks/use-outline-pane'
|
||||
import React, { ElementType } from 'react'
|
||||
import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
|
||||
|
||||
const editorSidebarComponents = importOverleafModules(
|
||||
'editorSidebarComponents'
|
||||
) as { import: { default: ElementType }; path: string }[]
|
||||
|
||||
export default function EditorSidebar() {
|
||||
const { view } = useLayoutContext()
|
||||
@@ -17,6 +23,11 @@ export default function EditorSidebar() {
|
||||
hidden: view === 'history',
|
||||
})}
|
||||
>
|
||||
{editorSidebarComponents.map(
|
||||
({ import: { default: Component }, path }) => (
|
||||
<Component key={path} />
|
||||
)
|
||||
)}
|
||||
<PanelGroup autoSaveId="ide-editor-sidebar-layout" direction="vertical">
|
||||
<Panel
|
||||
defaultSize={50}
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
Dispatch,
|
||||
SetStateAction,
|
||||
FC,
|
||||
useState,
|
||||
} from 'react'
|
||||
import useScopeValue from '../hooks/use-scope-value'
|
||||
import useDetachLayout from '../hooks/use-detach-layout'
|
||||
@@ -17,6 +18,7 @@ import { debugConsole } from '@/utils/debugging'
|
||||
import { BinaryFile } from '@/features/file-view/types/binary-file'
|
||||
import useScopeEventEmitter from '@/shared/hooks/use-scope-event-emitter'
|
||||
import useEventListener from '@/shared/hooks/use-event-listener'
|
||||
import { isSplitTestEnabled } from '@/utils/splitTestUtils'
|
||||
|
||||
export type IdeLayout = 'sideBySide' | 'flat'
|
||||
export type IdeView = 'editor' | 'file' | 'pdf' | 'history'
|
||||
@@ -49,8 +51,12 @@ type LayoutContextValue = {
|
||||
>
|
||||
pdfLayout: IdeLayout
|
||||
pdfPreviewOpen: boolean
|
||||
projectSearchIsOpen: boolean
|
||||
setProjectSearchIsOpen: Dispatch<SetStateAction<boolean>>
|
||||
}
|
||||
|
||||
const isMac = /Mac/.test(window.navigator?.platform)
|
||||
|
||||
const debugPdfDetach = getMeta('ol-debugPdfDetach')
|
||||
|
||||
export const LayoutContext = createContext<LayoutContextValue | undefined>(
|
||||
@@ -107,6 +113,9 @@ export const LayoutProvider: FC = ({ children }) => {
|
||||
const [leftMenuShown, setLeftMenuShown] =
|
||||
useScopeValue<boolean>('ui.leftMenuShown')
|
||||
|
||||
// whether the project search is open
|
||||
const [projectSearchIsOpen, setProjectSearchIsOpen] = useState(false)
|
||||
|
||||
useEventListener(
|
||||
'ui.toggle-left-menu',
|
||||
useCallback(
|
||||
@@ -124,6 +133,21 @@ export const LayoutProvider: FC = ({ children }) => {
|
||||
}, [setReviewPanelOpen])
|
||||
)
|
||||
|
||||
useEventListener(
|
||||
'keydown',
|
||||
useCallback((event: KeyboardEvent) => {
|
||||
if (
|
||||
(isMac ? event.metaKey : event.ctrlKey) &&
|
||||
event.shiftKey &&
|
||||
event.key === 'f'
|
||||
) {
|
||||
if (isSplitTestEnabled('full-project-search')) {
|
||||
setProjectSearchIsOpen(true)
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
)
|
||||
|
||||
// whether to display the editor and preview side-by-side or full-width ("flat")
|
||||
const [pdfLayout, setPdfLayout] = useScopeValue<IdeLayout>('ui.pdfLayout')
|
||||
|
||||
@@ -194,6 +218,8 @@ export const LayoutProvider: FC = ({ children }) => {
|
||||
leftMenuShown,
|
||||
pdfLayout,
|
||||
pdfPreviewOpen,
|
||||
projectSearchIsOpen,
|
||||
setProjectSearchIsOpen,
|
||||
reviewPanelOpen,
|
||||
miniReviewPanelVisible,
|
||||
loadingStyleSheet,
|
||||
@@ -216,6 +242,8 @@ export const LayoutProvider: FC = ({ children }) => {
|
||||
leftMenuShown,
|
||||
pdfLayout,
|
||||
pdfPreviewOpen,
|
||||
projectSearchIsOpen,
|
||||
setProjectSearchIsOpen,
|
||||
reviewPanelOpen,
|
||||
miniReviewPanelVisible,
|
||||
loadingStyleSheet,
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { FC, createContext, useContext, useMemo } from 'react'
|
||||
import { FC, createContext, useContext, useMemo, useState } from 'react'
|
||||
import useScopeValue from '../hooks/use-scope-value'
|
||||
import getMeta from '@/utils/meta'
|
||||
import { ProjectContextValue } from './types/project-context'
|
||||
import { ProjectSnapshot } from '@/infrastructure/project-snapshot'
|
||||
|
||||
const ProjectContext = createContext<ProjectContextValue | undefined>(undefined)
|
||||
|
||||
@@ -43,6 +44,8 @@ export const ProjectProvider: FC = ({ children }) => {
|
||||
mainBibliographyDoc_id: mainBibliographyDocId,
|
||||
} = project || projectFallback
|
||||
|
||||
const [projectSnapshot] = useState(() => new ProjectSnapshot(_id))
|
||||
|
||||
const tags = useMemo(
|
||||
() =>
|
||||
(getMeta('ol-projectTags') || [])
|
||||
@@ -65,6 +68,7 @@ export const ProjectProvider: FC = ({ children }) => {
|
||||
tags,
|
||||
trackChangesState,
|
||||
mainBibliographyDocId,
|
||||
projectSnapshot,
|
||||
}
|
||||
}, [
|
||||
_id,
|
||||
@@ -79,6 +83,7 @@ export const ProjectProvider: FC = ({ children }) => {
|
||||
tags,
|
||||
trackChangesState,
|
||||
mainBibliographyDocId,
|
||||
projectSnapshot,
|
||||
])
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { UserId } from '../../../../../types/user'
|
||||
import { PublicAccessLevel } from '../../../../../types/public-access-level'
|
||||
import { ProjectSnapshot } from '@/infrastructure/project-snapshot'
|
||||
|
||||
export type ProjectContextMember = {
|
||||
_id: UserId
|
||||
@@ -46,6 +47,7 @@ export type ProjectContextValue = {
|
||||
color?: string
|
||||
}[]
|
||||
trackChangesState: boolean | Record<UserId | '__guests__', boolean>
|
||||
projectSnapshot: ProjectSnapshot
|
||||
}
|
||||
|
||||
export type ProjectContextUpdateValue = Partial<ProjectContextValue>
|
||||
|
||||
@@ -51,12 +51,12 @@
|
||||
|
||||
// Enable ::before and ::after pseudo-elements to position themselves correctly
|
||||
position: relative;
|
||||
|
||||
background-color: @editor-resizer-bg-color;
|
||||
|
||||
.custom-toggler {
|
||||
padding: 0;
|
||||
border-width: 0;
|
||||
|
||||
// Override react-resizable-panels which sets a global * { cursor: ew-resize }
|
||||
cursor: pointer !important;
|
||||
}
|
||||
@@ -74,9 +74,11 @@
|
||||
width: 7px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
&::before {
|
||||
top: 25%;
|
||||
}
|
||||
|
||||
&::after {
|
||||
top: 75%;
|
||||
}
|
||||
@@ -89,6 +91,7 @@
|
||||
.synctex-controls {
|
||||
left: -8px;
|
||||
margin: 0;
|
||||
|
||||
// Ensure that SyncTex controls appear in front of PDF viewer controls and logs pane
|
||||
z-index: 12;
|
||||
|
||||
@@ -128,6 +131,7 @@
|
||||
height: 100%;
|
||||
background-color: @file-tree-bg;
|
||||
color: var(--neutral-20);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ide-react-symbol-palette {
|
||||
|
||||
@@ -60,6 +60,7 @@ $editor-toggler-bg-dark-color: color.adjust(
|
||||
background-color: var(--file-tree-bg);
|
||||
height: 100%;
|
||||
color: var(--content-secondary-dark);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ide-react-body {
|
||||
|
||||
Reference in New Issue
Block a user