diff --git a/client/contexts/AuthorizationContext.ts b/client/contexts/AuthorizationContext.ts index 8429a08d7ef40..7abb4e44e44cb 100644 --- a/client/contexts/AuthorizationContext.ts +++ b/client/contexts/AuthorizationContext.ts @@ -1,13 +1,15 @@ import { createContext, useContext, useMemo, useCallback } from 'react'; import { useSubscription, Subscription, Unsubscribe } from 'use-subscription'; -import { Emitter, Handler } from '@rocket.chat/emitter'; +import { Emitter } from '@rocket.chat/emitter'; import { IRole } from '../../definition/IUser'; type IRoles = { [_id: string]: IRole } -export class RoleStore extends Emitter { +export class RoleStore extends Emitter<{ + change: IRoles; +}> { roles: IRoles = {}; } @@ -91,7 +93,7 @@ export const useRolesDescription = (): (ids: Array) => [string] => { const subscription = useMemo( () => ({ getCurrentValue: (): IRoles => roleStore.roles, - subscribe: (callback: Handler): () => void => { + subscribe: (callback: () => void): () => void => { roleStore.on('change', callback); return (): void => { roleStore.off('change', callback); diff --git a/client/lib/banners.ts b/client/lib/banners.ts index 3ece45d2d4f4f..9067476824479 100644 --- a/client/lib/banners.ts +++ b/client/lib/banners.ts @@ -22,7 +22,10 @@ type BannerPayload = LegacyBannerPayload | UiKitBannerPayload; export const isLegacyPayload = (payload: BannerPayload): payload is LegacyBannerPayload => !('blocks' in payload); const queue: BannerPayload[] = []; -const emitter = new Emitter(); +const emitter = new Emitter<{ + update: undefined; + 'update-first': undefined; +}>(); export const firstSubscription: Subscription = { getCurrentValue: () => queue[0] ?? null, diff --git a/client/lib/createValueSubscription.ts b/client/lib/createValueSubscription.ts index b415b7f7c787f..9702f748e93a9 100644 --- a/client/lib/createValueSubscription.ts +++ b/client/lib/createValueSubscription.ts @@ -7,7 +7,9 @@ type ValueSubscription = Subscription & { export const createValueSubscription = (initialValue: T): ValueSubscription => { let value: T = initialValue; - const emitter = new Emitter(); + const emitter = new Emitter<{ + update: undefined; + }>(); return { getCurrentValue: (): T => value, diff --git a/client/lib/presence.ts b/client/lib/presence.ts index aedad7b8be75b..ec48f3f79b2a9 100644 --- a/client/lib/presence.ts +++ b/client/lib/presence.ts @@ -1,9 +1,22 @@ -import { Emitter, EventType, Handler } from '@rocket.chat/emitter'; +import { Emitter, EventHandlerOf } from '@rocket.chat/emitter'; import { APIClient } from '../../app/utils/client'; import { IUser } from '../../definition/IUser'; +import { USER_STATUS } from '../../definition/UserStatus'; -const emitter = new Emitter(); +type InternalEvents = { + remove: IUser['_id']; + reset: undefined; + restart: undefined; +}; + +type ExternalEvents = { + [key: string]: UserPresence | undefined; +}; + +type Events = InternalEvents & ExternalEvents; + +const emitter = new Emitter(); const store = new Map(); @@ -14,7 +27,7 @@ type UsersPresencePayload = { full: boolean; }; -const isUid = (eventType: EventType): eventType is UserPresence['_id'] => +const isUid = (eventType: keyof Events): eventType is UserPresence['_id'] => Boolean(eventType) && typeof eventType === 'string' && !['reset', 'restart', 'remove'].includes(eventType); const uids = new Set(); @@ -41,7 +54,7 @@ const getPresence = ((): ((uid: UserPresence['_id']) => void) => { }); currentUids.forEach((uid) => { - emitter.emit(uid, { _id: uid, status: 'offline' }); + emitter.emit(uid, { _id: uid, status: USER_STATUS.OFFLINE }); }); currentUids.clear(); @@ -68,6 +81,10 @@ const getPresence = ((): ((uid: UserPresence['_id']) => void) => { emitter.on('reset', () => { store.clear(); + emitter.events() + .filter(isUid).forEach((uid) => { + emitter.emit(uid, undefined); + }); emitter.once('restart', () => { emitter.events() .filter(isUid) @@ -78,36 +95,35 @@ const getPresence = ((): ((uid: UserPresence['_id']) => void) => { return get; })(); -const update: Handler = (update) => { +const update: EventHandlerOf = (update) => { if (update?._id) { store.set(update._id, update); uids.delete(update._id); } }; -const listen = (uid: UserPresence['_id'], handler: Handler): void => { +const listen = (uid: UserPresence['_id'], handler: EventHandlerOf | (() => void)): void => { emitter.on(uid, update); emitter.on(uid, handler); - emitter.on('reset', handler); - if (store.has(uid)) { - return handler(store.get(uid)); + const user = store.has(uid) && store.get(uid); + if (user) { + return handler(user); } getPresence(uid); }; -const stop = (uid: UserPresence['_id'], handler: Handler): void => { +const stop = (uid: UserPresence['_id'], handler: EventHandlerOf | (() => void)): void => { setTimeout(() => { emitter.off(uid, handler); emitter.off(uid, update); - emitter.off('reset', handler); emitter.emit('remove', uid); }, 5000); }; const reset = (): void => { - emitter.emit('reset', {}); + emitter.emit('reset'); store.clear(); }; @@ -126,7 +142,7 @@ const notify = (update: UserPresence): void => { }; const get = async (uid: UserPresence['_id']): Promise => new Promise((resolve) => { - const callback: Handler = (args): void => { + const callback: EventHandlerOf = (args): void => { resolve(args); stop(uid, callback); }; diff --git a/client/views/room/contexts/RoomContext.ts b/client/views/room/contexts/RoomContext.ts index a11e5faad5b66..cde7a321b762a 100644 --- a/client/views/room/contexts/RoomContext.ts +++ b/client/views/room/contexts/RoomContext.ts @@ -1,5 +1,4 @@ import { createContext } from 'react'; -// import { Handler } from '@rocket.chat/emitter'; import { IRoom } from '../../../../definition/IRoom'; diff --git a/client/views/room/lib/Toolbox/ToolboxContext.tsx b/client/views/room/lib/Toolbox/ToolboxContext.tsx index 75821941a7022..3cda75b67c3e9 100644 --- a/client/views/room/lib/Toolbox/ToolboxContext.tsx +++ b/client/views/room/lib/Toolbox/ToolboxContext.tsx @@ -1,13 +1,15 @@ import { createContext } from 'react'; -import { Handler } from '@rocket.chat/emitter'; +import { EventHandlerOf } from '@rocket.chat/emitter'; -import { actions, listen, ToolboxActionConfig, ToolboxAction } from '.'; +import { actions, listen, ToolboxActionConfig, ToolboxAction, Events } from '.'; import './defaultActions'; +export type ToolboxEventHandler = (handler: EventHandlerOf) => Function; + export type ChannelContextValue = { actions: Map; - listen: (handler: Handler) => Function; + listen: ToolboxEventHandler; tabBar?: any; context?: any; open: Function; diff --git a/client/views/room/lib/Toolbox/generator.tsx b/client/views/room/lib/Toolbox/generator.tsx index c1252e02baf95..5e22bdea9481c 100644 --- a/client/views/room/lib/Toolbox/generator.tsx +++ b/client/views/room/lib/Toolbox/generator.tsx @@ -1,18 +1,22 @@ -import { Emitter, Handler } from '@rocket.chat/emitter'; +import { Emitter, EventHandlerOf } from '@rocket.chat/emitter'; export type Store = Map; -export const generator = function generator(name?: string): -{ + +export type Events = { + change: Store; +}; + +export const generator = function generator(name?: string): ({ store: Store; add: (id: string, action: T) => Store; remove: (id: string) => boolean; - listen: (handler: Handler) => Function; + listen: (handler: EventHandlerOf, 'change'>) => Function; name: string | undefined; -} { +}) { const store: Store = new Map(); - const emitter = new Emitter(); + const emitter = new Emitter>(); const add = (id: string, action: T): Store => { store.set(id, action); @@ -26,7 +30,7 @@ export const generator = function generator(name?: string): return result; }; - const listen = (handler: Handler): Function => emitter.on('change', handler); + const listen = (handler: EventHandlerOf, 'change'>): Function => emitter.on('change', handler); return Object.freeze({ store, diff --git a/client/views/room/lib/Toolbox/index.tsx b/client/views/room/lib/Toolbox/index.tsx index 96e5cfef36f60..62ce552917add 100644 --- a/client/views/room/lib/Toolbox/index.tsx +++ b/client/views/room/lib/Toolbox/index.tsx @@ -2,7 +2,7 @@ import { FC, LazyExoticComponent, ReactNode, MouseEvent } from 'react'; import { BoxProps, OptionProps } from '@rocket.chat/fuselage'; import { IRoom } from '../../../../../definition/IRoom'; -import { generator } from './generator'; +import { generator, Events as GeneratorEvents } from './generator'; type ToolboxHook = ({ room }: { room: IRoom }) => ToolboxActionConfig | null @@ -38,4 +38,6 @@ export type ToolboxAction = ToolboxHook | ToolboxActionConfig; const { listen, add: addAction, remove: deleteAction, store: actions } = generator(); +export type Events = GeneratorEvents; + export { listen, addAction, deleteAction, actions }; diff --git a/client/views/room/providers/ToolboxProvider.tsx b/client/views/room/providers/ToolboxProvider.tsx index c07788e14e23e..a9f246f24c260 100644 --- a/client/views/room/providers/ToolboxProvider.tsx +++ b/client/views/room/providers/ToolboxProvider.tsx @@ -1,8 +1,7 @@ import React, { ReactNode, useContext, useMemo, useState, useCallback, useLayoutEffect } from 'react'; import { useDebouncedState, useMutableCallback, useSafely } from '@rocket.chat/fuselage-hooks'; -import { Handler } from '@rocket.chat/emitter'; -import { ToolboxContext } from '../lib/Toolbox/ToolboxContext'; +import { ToolboxContext, ToolboxEventHandler } from '../lib/Toolbox/ToolboxContext'; import { ToolboxAction, ToolboxActionConfig } from '../lib/Toolbox/index'; import { IRoom } from '../../../../definition/IRoom'; import { useCurrentRoute, useRoute } from '../../../contexts/RouterContext'; @@ -37,7 +36,7 @@ const VirtualAction = React.memo(({ handleChange, room, action, id }: { id: stri return null; }); -const useToolboxActions = (room: IRoom): { listen: (handler: Handler) => Function; actions: Array<[string, ToolboxAction]> } => { +const useToolboxActions = (room: IRoom): { listen: ToolboxEventHandler; actions: Array<[string, ToolboxAction]> } => { const { listen, actions } = useContext(ToolboxContext); const [state, setState] = useState>(Array.from(actions.entries())); diff --git a/package-lock.json b/package-lock.json index 8d37a6a35db52..36901f5e24945 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5920,11 +5920,12 @@ } }, "@rocket.chat/css-in-js": { - "version": "0.6.3-dev.178", - "resolved": "https://registry.npmjs.org/@rocket.chat/css-in-js/-/css-in-js-0.6.3-dev.178.tgz", - "integrity": "sha512-4cnyJx8TbZ8zKWfl1gYGfWZBtf9RWWbaDQpKClkN5myCAXE07QG/tP0z/A0nnGCiU0qSZDrsl/wcdxYwG47tEA==", + "version": "0.6.3-dev.180", + "resolved": "https://registry.npmjs.org/@rocket.chat/css-in-js/-/css-in-js-0.6.3-dev.180.tgz", + "integrity": "sha512-j34Yv+O7J0h7vG0wNe3zjteaCz3ZNJ4fyNldte5+ByiqS/LanQpQYA08+Srvtb2LCI177E9pJHQ4o0UBxIhPUg==", "requires": { "@emotion/hash": "^0.8.0", + "@rocket.chat/memo": "^0.6.3-dev.180+2425c045", "stylis": "^4.0.6" }, "dependencies": { @@ -5936,9 +5937,9 @@ } }, "@rocket.chat/emitter": { - "version": "0.6.3-dev.178", - "resolved": "https://registry.npmjs.org/@rocket.chat/emitter/-/emitter-0.6.3-dev.178.tgz", - "integrity": "sha512-wgmr7Yg6Hx7hPVpFhlOoQha8I/mLpSUb273y1MYQOItBBF58VOYwdC2r6gvBZRRbziGOZL95eOmP1N6odP4RCg==" + "version": "0.6.3-dev.185", + "resolved": "https://registry.npmjs.org/@rocket.chat/emitter/-/emitter-0.6.3-dev.185.tgz", + "integrity": "sha512-23TNzv+sS8cDT1MQl402QVsI4OEcnChtOhru6TyQqCndfpvBBObmiATgxFnClA6HQA5pXt8qMGxUl/UXDXKs0A==" }, "@rocket.chat/eslint-config": { "version": "0.3.0", @@ -6012,9 +6013,9 @@ "integrity": "sha512-gVzQHhUsZSLbIkwGi8f1KpsTepkmtwHs7hl1gGr0HrnI4eYhBWpMOEjdiH3czhPuoF/O4C8QjdpDrktIuwkVNQ==" }, "@rocket.chat/fuselage-ui-kit": { - "version": "0.6.3-dev.179", - "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-ui-kit/-/fuselage-ui-kit-0.6.3-dev.179.tgz", - "integrity": "sha512-xQpxwvpiZwTnANdNkaxRASsCZuP0yftHtz/Lq/K0CW9VQc3Ml+mkOp+FV1XImZlyv31bwfxW78SsdaQNmDkTAQ==", + "version": "0.6.3-dev.184", + "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-ui-kit/-/fuselage-ui-kit-0.6.3-dev.184.tgz", + "integrity": "sha512-xO1FuY9bCKTOKOANbRi189Uq0j6+pVSKaV3E5C3TYvWuMhwE2Lfq4gbiH/uEn5cnrVdR1HOJaaskCxkraGqTVg==", "requires": { "@rocket.chat/fuselage-polyfills": "^0.21.0" }, @@ -19928,7 +19929,7 @@ }, "chownr": { "version": "1.1.1", - "resolved": "", + "resolved": false, "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", "dev": true, "optional": true @@ -19963,7 +19964,7 @@ }, "debug": { "version": "4.1.1", - "resolved": "", + "resolved": false, "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "optional": true, @@ -19994,7 +19995,7 @@ }, "fs-minipass": { "version": "1.2.5", - "resolved": "", + "resolved": false, "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "dev": true, "optional": true, @@ -20028,7 +20029,7 @@ }, "glob": { "version": "7.1.3", - "resolved": "", + "resolved": false, "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "optional": true, @@ -20060,7 +20061,7 @@ }, "ignore-walk": { "version": "3.0.1", - "resolved": "", + "resolved": false, "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", "dev": true, "optional": true, @@ -20081,7 +20082,7 @@ }, "inherits": { "version": "2.0.3", - "resolved": "", + "resolved": false, "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true, "optional": true @@ -20129,7 +20130,7 @@ }, "minipass": { "version": "2.3.5", - "resolved": "", + "resolved": false, "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", "dev": true, "optional": true, @@ -20140,7 +20141,7 @@ }, "minizlib": { "version": "1.2.1", - "resolved": "", + "resolved": false, "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", "dev": true, "optional": true, @@ -20160,7 +20161,7 @@ }, "ms": { "version": "2.1.1", - "resolved": "", + "resolved": false, "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true, "optional": true @@ -20174,7 +20175,7 @@ }, "needle": { "version": "2.3.0", - "resolved": "", + "resolved": false, "integrity": "sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==", "dev": true, "optional": true, @@ -20186,7 +20187,7 @@ }, "node-pre-gyp": { "version": "0.12.0", - "resolved": "", + "resolved": false, "integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==", "dev": true, "optional": true, @@ -20216,14 +20217,14 @@ }, "npm-bundled": { "version": "1.0.6", - "resolved": "", + "resolved": false, "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", "dev": true, "optional": true }, "npm-packlist": { "version": "1.4.1", - "resolved": "", + "resolved": false, "integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==", "dev": true, "optional": true, @@ -20303,7 +20304,7 @@ }, "process-nextick-args": { "version": "2.0.0", - "resolved": "", + "resolved": false, "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true, "optional": true @@ -20348,7 +20349,7 @@ }, "rimraf": { "version": "2.6.3", - "resolved": "", + "resolved": false, "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "optional": true, @@ -20379,7 +20380,7 @@ }, "semver": { "version": "5.7.0", - "resolved": "", + "resolved": false, "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true, "optional": true @@ -20439,7 +20440,7 @@ }, "tar": { "version": "4.4.8", - "resolved": "", + "resolved": false, "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", "dev": true, "optional": true, @@ -20479,7 +20480,7 @@ }, "yallist": { "version": "3.0.3", - "resolved": "", + "resolved": false, "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", "dev": true, "optional": true diff --git a/package.json b/package.json index ec4a328e90ca8..5a8fecee9980b 100644 --- a/package.json +++ b/package.json @@ -135,13 +135,13 @@ "@nivo/line": "^0.61.1", "@nivo/pie": "^0.61.1", "@rocket.chat/apps-engine": "1.23.0-alpha.4655", - "@rocket.chat/css-in-js": "^0.6.3-dev.178", - "@rocket.chat/emitter": "^0.6.3-dev.178", + "@rocket.chat/css-in-js": "^0.6.3-dev.180", + "@rocket.chat/emitter": "^0.6.3-dev.185", "@rocket.chat/fuselage": "^0.6.3-dev.188", "@rocket.chat/fuselage-hooks": "^0.6.3-dev.178", "@rocket.chat/fuselage-polyfills": "^0.6.3-dev.181", "@rocket.chat/fuselage-tokens": "^0.21.0", - "@rocket.chat/fuselage-ui-kit": "^0.6.3-dev.179", + "@rocket.chat/fuselage-ui-kit": "^0.6.3-dev.184", "@rocket.chat/icons": "^0.6.3-dev.179", "@rocket.chat/mp3-encoder": "^0.6.3-dev.178", "@rocket.chat/ui-kit": "^0.6.3-dev.178",