mirror of
https://github.com/overleaf/overleaf.git
synced 2025-04-12 05:36:40 +00:00
Replace strict-event-emitter with EventTarget (#16374)
GitOrigin-RevId: 3b0afc3cd7bf3d11f35a3de23cb94061d2d6c69b
This commit is contained in:
parent
cf0e260a36
commit
9804ebe12c
9 changed files with 64 additions and 42 deletions
14
package-lock.json
generated
14
package-lock.json
generated
|
@ -39473,12 +39473,6 @@
|
|||
"queue-tick": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/strict-event-emitter": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz",
|
||||
"integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/strict-uri-encode": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
|
||||
|
@ -46658,7 +46652,6 @@
|
|||
"sinon-mongoose": "^2.3.0",
|
||||
"socket.io-mock": "^1.3.1",
|
||||
"storybook": "^7.4.0",
|
||||
"strict-event-emitter": "^0.5.1",
|
||||
"terser-webpack-plugin": "^5.3.9",
|
||||
"thread-loader": "^4.0.2",
|
||||
"timekeeper": "^2.2.0",
|
||||
|
@ -55432,7 +55425,6 @@
|
|||
"sinon-mongoose": "^2.3.0",
|
||||
"socket.io-mock": "^1.3.1",
|
||||
"storybook": "^7.4.0",
|
||||
"strict-event-emitter": "^0.5.1",
|
||||
"terser-webpack-plugin": "^5.3.9",
|
||||
"thread-loader": "^4.0.2",
|
||||
"timekeeper": "^2.2.0",
|
||||
|
@ -80671,12 +80663,6 @@
|
|||
"queue-tick": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"strict-event-emitter": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz",
|
||||
"integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==",
|
||||
"dev": true
|
||||
},
|
||||
"strict-uri-encode": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { ConnectionError, ConnectionState } from './types/connection-state'
|
||||
import SocketIoShim from '../../../ide/connection/SocketIoShim'
|
||||
import getMeta from '../../../utils/meta'
|
||||
import { Emitter } from 'strict-event-emitter'
|
||||
import { Socket } from '@/features/ide-react/connection/types/socket'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
|
||||
|
@ -29,11 +28,12 @@ const initialState: ConnectionState = {
|
|||
error: '',
|
||||
}
|
||||
|
||||
type Events = {
|
||||
statechange: [{ state: ConnectionState; previousState: ConnectionState }]
|
||||
}
|
||||
export class StateChangeEvent extends CustomEvent<{
|
||||
state: ConnectionState
|
||||
previousState: ConnectionState
|
||||
}> {}
|
||||
|
||||
export class ConnectionManager extends Emitter<Events> {
|
||||
export class ConnectionManager extends EventTarget {
|
||||
state: ConnectionState = initialState
|
||||
private connectionAttempt: number | null = null
|
||||
private gracefullyReconnectUntil = 0
|
||||
|
@ -113,7 +113,9 @@ export class ConnectionManager extends Emitter<Events> {
|
|||
previousState,
|
||||
state,
|
||||
})
|
||||
this.emit('statechange', { state, previousState })
|
||||
this.dispatchEvent(
|
||||
new StateChangeEvent('statechange', { detail: { state, previousState } })
|
||||
)
|
||||
}
|
||||
|
||||
private onOnline() {
|
||||
|
|
|
@ -8,7 +8,10 @@ import {
|
|||
useMemo,
|
||||
} from 'react'
|
||||
import { ConnectionState } from '../connection/types/connection-state'
|
||||
import { ConnectionManager } from '@/features/ide-react/connection/connection-manager'
|
||||
import {
|
||||
ConnectionManager,
|
||||
StateChangeEvent,
|
||||
} from '@/features/ide-react/connection/connection-manager'
|
||||
import { Socket } from '@/features/ide-react/connection/types/socket'
|
||||
import { secondsUntil } from '@/features/ide-react/connection/utils'
|
||||
import { useLocation } from '@/shared/hooks/use-location'
|
||||
|
@ -37,13 +40,13 @@ export const ConnectionProvider: FC = ({ children }) => {
|
|||
)
|
||||
|
||||
useEffect(() => {
|
||||
function handleStateChange(event: { state: ConnectionState }) {
|
||||
setConnectionState(event.state)
|
||||
}
|
||||
connectionManager.on('statechange', handleStateChange)
|
||||
const handleStateChange = ((event: StateChangeEvent) => {
|
||||
setConnectionState(event.detail.state)
|
||||
}) as EventListener
|
||||
connectionManager.addEventListener('statechange', handleStateChange)
|
||||
|
||||
return () => {
|
||||
connectionManager.off('statechange', handleStateChange)
|
||||
connectionManager.removeEventListener('statechange', handleStateChange)
|
||||
}
|
||||
}, [connectionManager])
|
||||
|
||||
|
|
|
@ -18,11 +18,10 @@ import { useEditorContext } from '@/shared/context/editor-context'
|
|||
import { useIdeContext } from '@/shared/context/ide-context'
|
||||
import useSocketListener from '@/features/ide-react/hooks/use-socket-listener'
|
||||
import useEventListener from '@/shared/hooks/use-event-listener'
|
||||
import { FileTreeFindResult } from '@/features/ide-react/types/file-tree'
|
||||
import { Project } from '../../../../../types/project'
|
||||
import { useModalsContext } from '@/features/ide-react/context/modals-context'
|
||||
import { usePermissionsContext } from '@/features/ide-react/context/permissions-context'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { IdeEvents } from '@/features/ide-react/create-ide-event-emitter'
|
||||
|
||||
type DocumentMetadata = {
|
||||
labels: string[]
|
||||
|
@ -63,7 +62,9 @@ export const MetadataProvider: FC = ({ children }) => {
|
|||
const debouncerRef = useRef<Map<string, number>>(new Map()) // DocId => Timeout
|
||||
|
||||
useEffect(() => {
|
||||
const handleEntityDeleted = (entity: FileTreeFindResult) => {
|
||||
const handleEntityDeleted = ({
|
||||
detail: [entity],
|
||||
}: CustomEvent<IdeEvents['entity:deleted']>) => {
|
||||
if (entity.type === 'doc') {
|
||||
setDocuments(documents => {
|
||||
return _.omit(documents, entity.entity._id)
|
||||
|
@ -184,7 +185,9 @@ export const MetadataProvider: FC = ({ children }) => {
|
|||
useEventListener('editor:metadata-outdated', handleMetadataOutdated)
|
||||
|
||||
useEffect(() => {
|
||||
const handleProjectJoined = ({ project }: { project: Project }) => {
|
||||
const handleProjectJoined = ({
|
||||
detail: [{ project }],
|
||||
}: CustomEvent<IdeEvents['project:joined']>) => {
|
||||
if (project.deletedByExternalDataSource) {
|
||||
showGenericMessageModal(
|
||||
t('project_renamed_or_deleted'),
|
||||
|
|
|
@ -19,6 +19,7 @@ import { useFileTreeData } from '@/shared/context/file-tree-data-context'
|
|||
import { findDocEntityById } from '@/features/ide-react/util/find-doc-entity-by-id'
|
||||
import useSocketListener from '@/features/ide-react/hooks/use-socket-listener'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import { IdeEvents } from '@/features/ide-react/create-ide-event-emitter'
|
||||
|
||||
type OnlineUser = {
|
||||
id: string
|
||||
|
@ -213,7 +214,9 @@ export const OnlineUsersProvider: FC = ({ children }) => {
|
|||
|
||||
// Track the position of the main cursor
|
||||
useEffect(() => {
|
||||
const handleCursorUpdate = (position: CursorPosition | null) => {
|
||||
const handleCursorUpdate = ({
|
||||
detail: [position],
|
||||
}: CustomEvent<IdeEvents['cursor:editor:update']>) => {
|
||||
if (position) {
|
||||
setCurrentPosition(position)
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import useScopeValue from '@/shared/hooks/use-scope-value'
|
|||
import { ReactScopeValueStore } from '@/features/ide-react/scope-value-store/react-scope-value-store'
|
||||
import { useFileTreeData } from '@/shared/context/file-tree-data-context'
|
||||
import { findDocEntityById } from '@/features/ide-react/util/find-doc-entity-by-id'
|
||||
import { IdeEvents } from '@/features/ide-react/create-ide-event-emitter'
|
||||
|
||||
type References = {
|
||||
keys: string[]
|
||||
|
@ -108,7 +109,9 @@ export const ReferencesProvider: FC = ({ children }) => {
|
|||
)
|
||||
|
||||
useEffect(() => {
|
||||
const handleDocClosed = (doc: ShareJsDoc) => {
|
||||
const handleDocClosed = ({
|
||||
detail: [doc],
|
||||
}: CustomEvent<IdeEvents['document:closed']>) => {
|
||||
if (
|
||||
doc.doc_id &&
|
||||
findDocEntityById(fileTreeData, doc.doc_id)?.name?.endsWith('.bib')
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { Emitter } from 'strict-event-emitter'
|
||||
import { Project } from '../../../../types/project'
|
||||
import { PermissionsLevel } from '@/features/ide-react/types/permissions'
|
||||
import { ShareJsDoc } from '@/features/ide-react/editor/share-js-doc'
|
||||
|
@ -26,8 +25,33 @@ export type IdeEvents = {
|
|||
'entity:deleted': [entity: FileTreeFindResult]
|
||||
}
|
||||
|
||||
export type IdeEventEmitter = Emitter<IdeEvents>
|
||||
export class IdeEventEmitter extends EventTarget {
|
||||
emit<T extends keyof IdeEvents>(eventName: T, ...detail: IdeEvents[T]) {
|
||||
this.dispatchEvent(new CustomEvent<IdeEvents[T]>(eventName, { detail }))
|
||||
}
|
||||
|
||||
export function createIdeEventEmitter(): IdeEventEmitter {
|
||||
return new Emitter<IdeEvents>()
|
||||
on<T extends keyof IdeEvents>(
|
||||
eventName: T,
|
||||
listener: (event: CustomEvent<IdeEvents[T]>) => void
|
||||
) {
|
||||
this.addEventListener(eventName, listener as EventListener)
|
||||
}
|
||||
|
||||
once<T extends keyof IdeEvents>(
|
||||
eventName: T,
|
||||
listener: (event: CustomEvent<IdeEvents[T]>) => void
|
||||
) {
|
||||
this.addEventListener(eventName, listener as EventListener, { once: true })
|
||||
}
|
||||
|
||||
off<T extends keyof IdeEvents>(
|
||||
eventName: T,
|
||||
listener: (event: CustomEvent<IdeEvents[T]>) => void
|
||||
) {
|
||||
this.removeEventListener(eventName, listener as EventListener)
|
||||
}
|
||||
}
|
||||
|
||||
export function createIdeEventEmitter() {
|
||||
return new IdeEventEmitter()
|
||||
}
|
||||
|
|
|
@ -2,14 +2,13 @@ import {
|
|||
ScopeEventEmitter,
|
||||
ScopeEventName,
|
||||
} from '../../../../../types/ide/scope-event-emitter'
|
||||
import EventEmitter from 'events'
|
||||
|
||||
export class ReactScopeEventEmitter implements ScopeEventEmitter {
|
||||
// eslint-disable-next-line no-useless-constructor
|
||||
constructor(private readonly eventEmitter: EventEmitter) {}
|
||||
constructor(private readonly eventEmitter: EventTarget) {}
|
||||
|
||||
emit(eventName: ScopeEventName, broadcast: boolean, ...detail: unknown[]) {
|
||||
this.eventEmitter.emit(eventName, ...detail)
|
||||
this.eventEmitter.dispatchEvent(new CustomEvent(eventName, { detail }))
|
||||
}
|
||||
|
||||
on(eventName: ScopeEventName, listener: (...args: unknown[]) => void) {
|
||||
|
@ -18,9 +17,9 @@ export class ReactScopeEventEmitter implements ScopeEventEmitter {
|
|||
const wrappedListener = (...detail: unknown[]) => {
|
||||
listener({}, ...detail)
|
||||
}
|
||||
this.eventEmitter.on(eventName, wrappedListener)
|
||||
this.eventEmitter.addEventListener(eventName, wrappedListener)
|
||||
return () => {
|
||||
this.eventEmitter.off(eventName, wrappedListener)
|
||||
this.eventEmitter.removeEventListener(eventName, wrappedListener)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -344,7 +344,6 @@
|
|||
"sinon-mongoose": "^2.3.0",
|
||||
"socket.io-mock": "^1.3.1",
|
||||
"storybook": "^7.4.0",
|
||||
"strict-event-emitter": "^0.5.1",
|
||||
"terser-webpack-plugin": "^5.3.9",
|
||||
"thread-loader": "^4.0.2",
|
||||
"timekeeper": "^2.2.0",
|
||||
|
|
Loading…
Add table
Reference in a new issue