Replace strict-event-emitter with EventTarget (#16374)

GitOrigin-RevId: 3b0afc3cd7bf3d11f35a3de23cb94061d2d6c69b
This commit is contained in:
Alf Eaton 2024-01-05 10:05:07 +00:00 committed by Copybot
parent cf0e260a36
commit 9804ebe12c
9 changed files with 64 additions and 42 deletions

14
package-lock.json generated
View file

@ -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",

View file

@ -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() {

View file

@ -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])

View file

@ -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'),

View file

@ -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)
}

View file

@ -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')

View file

@ -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()
}

View file

@ -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)
}
}
}

View file

@ -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",