mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-23 09:09:36 +02:00
Merge pull request #23284 from overleaf/ae-scope-event-types
Improve scope event types GitOrigin-RevId: 5327c56a14244a2513748d3bcbac04413d104e12
This commit is contained in:
@@ -33,7 +33,7 @@ import { Update } from '@/features/history/services/types/update'
|
||||
import { useDebugDiffTracker } from '../hooks/use-debug-diff-tracker'
|
||||
import { useEditorContext } from '@/shared/context/editor-context'
|
||||
|
||||
interface GotoOffsetOptions {
|
||||
export interface GotoOffsetOptions {
|
||||
gotoOffset: number
|
||||
}
|
||||
|
||||
@@ -243,12 +243,7 @@ export const EditorManagerProvider: FC = ({ children }) => {
|
||||
|
||||
const jumpToLine = useCallback(
|
||||
(options: GotoLineOptions) => {
|
||||
goToLineEmitter(
|
||||
options.gotoLine,
|
||||
options.gotoColumn ?? 0,
|
||||
options.syncToPdf ?? false,
|
||||
options.selectionLength
|
||||
)
|
||||
goToLineEmitter(options)
|
||||
},
|
||||
[goToLineEmitter]
|
||||
)
|
||||
@@ -460,7 +455,7 @@ export const EditorManagerProvider: FC = ({ children }) => {
|
||||
}
|
||||
} else if (hasGotoOffset(options)) {
|
||||
window.setTimeout(() => {
|
||||
eventEmitter.emit('editor:gotoOffset', options.gotoOffset)
|
||||
eventEmitter.emit('editor:gotoOffset', options)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,11 @@ export const OutlineProvider: FC = ({ children }) => {
|
||||
const jumpToLine = useCallback(
|
||||
(lineNumber: number, syncToPdf: boolean) => {
|
||||
setIgnoreNextScroll(true)
|
||||
goToLineEmitter(lineNumber, 0, syncToPdf)
|
||||
goToLineEmitter({
|
||||
gotoLine: lineNumber,
|
||||
gotoColumn: 0,
|
||||
syncToPdf,
|
||||
})
|
||||
eventTracking.sendMB('outline-jump-to-line')
|
||||
},
|
||||
[goToLineEmitter]
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Project } from '../../../../types/project'
|
||||
import { PermissionsLevel } from '@/features/ide-react/types/permissions'
|
||||
import { ShareJsDoc } from '@/features/ide-react/editor/share-js-doc'
|
||||
import { GotoLineOptions } from '@/features/ide-react/types/goto-line-options'
|
||||
import { GotoOffsetOptions } from '@/features/ide-react/context/editor-manager-context'
|
||||
import { CursorPosition } from '@/features/ide-react/types/cursor-position'
|
||||
import { FileTreeFindResult } from '@/features/ide-react/types/file-tree'
|
||||
|
||||
@@ -13,12 +14,12 @@ export type IdeEvents = {
|
||||
'doc:opened': []
|
||||
'ide:opAcknowledged': [{ doc_id: string; op: any }]
|
||||
'store-doc-position': []
|
||||
'editor:gotoOffset': [gotoOffset: number]
|
||||
'editor:gotoOffset': [options: GotoOffsetOptions]
|
||||
'editor:gotoLine': [options: GotoLineOptions]
|
||||
'cursor:editor:update': [position: CursorPosition]
|
||||
'outline-toggled': [isOpen: boolean]
|
||||
'cursor:editor:syncToPdf': []
|
||||
'scroll:editor:update': []
|
||||
'scroll:editor:update': [middleVisibleLine?: number]
|
||||
'comment:start_adding': []
|
||||
'history:toggle': []
|
||||
'entity:deleted': [entity: FileTreeFindResult]
|
||||
|
||||
@@ -2,20 +2,26 @@ import {
|
||||
ScopeEventEmitter,
|
||||
ScopeEventName,
|
||||
} from '../../../../../types/ide/scope-event-emitter'
|
||||
import { IdeEvents } from '@/features/ide-react/create-ide-event-emitter'
|
||||
|
||||
export class ReactScopeEventEmitter implements ScopeEventEmitter {
|
||||
// eslint-disable-next-line no-useless-constructor
|
||||
constructor(private readonly eventEmitter: EventTarget) {}
|
||||
|
||||
emit(eventName: ScopeEventName, broadcast: boolean, ...detail: unknown[]) {
|
||||
emit<T extends ScopeEventName>(
|
||||
eventName: T,
|
||||
broadcast: boolean,
|
||||
...detail: IdeEvents[T]
|
||||
) {
|
||||
this.eventEmitter.dispatchEvent(new CustomEvent(eventName, { detail }))
|
||||
}
|
||||
|
||||
on(eventName: ScopeEventName, listener: (...args: unknown[]) => void) {
|
||||
// A listener attached via useScopeEventListener expects an event as the
|
||||
// first parameter. We don't have one, so just provide an empty object
|
||||
const wrappedListener = (event: CustomEvent<unknown[]>) => {
|
||||
listener({}, ...event.detail)
|
||||
on<T extends ScopeEventName>(
|
||||
eventName: T,
|
||||
listener: (event: Event, ...args: IdeEvents[T]) => void
|
||||
) {
|
||||
const wrappedListener = (event: CustomEvent<IdeEvents[T]>) => {
|
||||
listener(event, ...event.detail)
|
||||
}
|
||||
this.eventEmitter.addEventListener(
|
||||
eventName,
|
||||
|
||||
@@ -309,11 +309,12 @@ function PdfSynctexControls() {
|
||||
cursorPositionRef.current = cursorPosition
|
||||
}, [cursorPosition])
|
||||
|
||||
const handleSyncToPdf = useCallback(() => {
|
||||
syncToPdf(cursorPositionRef.current)
|
||||
}, [syncToPdf])
|
||||
|
||||
useScopeEventListener('cursor:editor:syncToPdf', handleSyncToPdf)
|
||||
useScopeEventListener(
|
||||
'cursor:editor:syncToPdf',
|
||||
useCallback(() => {
|
||||
syncToPdf(cursorPositionRef.current)
|
||||
}, [syncToPdf])
|
||||
)
|
||||
|
||||
const _syncToCode = useCallback(
|
||||
(position, visualOffset = 0) => {
|
||||
|
||||
@@ -467,28 +467,35 @@ function useCodeMirrorScope(view: EditorView) {
|
||||
|
||||
const emitSyncToPdf = useScopeEventEmitter('cursor:editor:syncToPdf')
|
||||
|
||||
const handleGoToLine = useCallback(
|
||||
(event, lineNumber, columnNumber, syncToPdf, selectionLength) => {
|
||||
setCursorLineAndScroll(view, lineNumber, columnNumber, selectionLength)
|
||||
if (syncToPdf) {
|
||||
emitSyncToPdf()
|
||||
}
|
||||
},
|
||||
[emitSyncToPdf, view]
|
||||
)
|
||||
|
||||
// select and scroll to position on editor:gotoLine event (from synctex)
|
||||
useScopeEventListener('editor:gotoLine', handleGoToLine)
|
||||
|
||||
const handleGoToOffset = useCallback(
|
||||
(event, offset) => {
|
||||
setCursorPositionAndScroll(view, offset)
|
||||
},
|
||||
[view]
|
||||
useScopeEventListener(
|
||||
'editor:gotoLine',
|
||||
useCallback(
|
||||
(_event, options) => {
|
||||
setCursorLineAndScroll(
|
||||
view,
|
||||
options.gotoLine,
|
||||
options.gotoColumn,
|
||||
options.selectionLength
|
||||
)
|
||||
if (options.syncToPdf) {
|
||||
emitSyncToPdf()
|
||||
}
|
||||
},
|
||||
[emitSyncToPdf, view]
|
||||
)
|
||||
)
|
||||
|
||||
// select and scroll to position on editor:gotoOffset event (from review panel)
|
||||
useScopeEventListener('editor:gotoOffset', handleGoToOffset)
|
||||
useScopeEventListener(
|
||||
'editor:gotoOffset',
|
||||
useCallback(
|
||||
(_event, options) => {
|
||||
setCursorPositionAndScroll(view, options.gotoOffset)
|
||||
},
|
||||
[view]
|
||||
)
|
||||
)
|
||||
|
||||
// dispatch 'cursor:editor:update' to Angular scope (for synctex and realtime)
|
||||
const dispatchCursorUpdate = useScopeEventEmitter('cursor:editor:update')
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import { useCallback } from 'react'
|
||||
import { useIdeContext } from '../context/ide-context'
|
||||
import { ScopeEventName } from '../../../../types/ide/scope-event-emitter'
|
||||
import { IdeEvents } from '@/features/ide-react/create-ide-event-emitter'
|
||||
|
||||
export default function useScopeEventEmitter(
|
||||
eventName: ScopeEventName,
|
||||
export default function useScopeEventEmitter<T extends ScopeEventName>(
|
||||
eventName: T,
|
||||
broadcast = true
|
||||
) {
|
||||
const { scopeEventEmitter } = useIdeContext()
|
||||
|
||||
return useCallback(
|
||||
(...detail: unknown[]) => {
|
||||
(...detail: IdeEvents[T]) => {
|
||||
scopeEventEmitter.emit(eventName, broadcast, ...detail)
|
||||
},
|
||||
[scopeEventEmitter, eventName, broadcast]
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { useEffect } from 'react'
|
||||
import { useIdeContext } from '../context/ide-context'
|
||||
import { ScopeEventName } from '../../../../types/ide/scope-event-emitter'
|
||||
import { IdeEvents } from '@/features/ide-react/create-ide-event-emitter'
|
||||
|
||||
export default function useScopeEventListener(
|
||||
eventName: ScopeEventName,
|
||||
listener: (...args: unknown[]) => void
|
||||
export default function useScopeEventListener<T extends ScopeEventName>(
|
||||
eventName: T,
|
||||
listener: (event: Event, ...args: IdeEvents[T]) => void
|
||||
) {
|
||||
const { scopeEventEmitter } = useIdeContext()
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@ import { IdeEvents } from '@/features/ide-react/create-ide-event-emitter'
|
||||
export type ScopeEventName = keyof IdeEvents
|
||||
|
||||
export interface ScopeEventEmitter {
|
||||
emit: (
|
||||
eventName: ScopeEventName,
|
||||
emit: <T extends ScopeEventName>(
|
||||
eventName: T,
|
||||
broadcast: boolean,
|
||||
...detail: unknown[]
|
||||
...detail: IdeEvents[T]
|
||||
) => void
|
||||
on: (
|
||||
eventName: ScopeEventName,
|
||||
listener: (...args: unknown[]) => void
|
||||
on: <T extends ScopeEventName>(
|
||||
eventName: T,
|
||||
listener: (event: Event, ...args: IdeEvents[T]) => void
|
||||
) => () => void
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user