diff --git a/CHANGELOG.md b/CHANGELOG.md index ae2fe264e2..c51aa51670 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed +- Added a tag attribute for from object for typing indicator - Bumped all dependencies to the latest versions, by [@compulim](https://github.com/compulim) in PR [#4195](https://github.com/microsoft/BotFramework-WebChat/pull/4195) - Production dependencies - [`@babel/runtime@7.17.2`](https://npmjs.com/package/@babel/runtime) diff --git a/__tests__/hooks/useActiveTyping.js b/__tests__/hooks/useActiveTyping.js index 0fc1a8feea..c4ccbcf5ea 100644 --- a/__tests__/hooks/useActiveTyping.js +++ b/__tests__/hooks/useActiveTyping.js @@ -37,7 +37,8 @@ test('getter should represent bot and user typing respectively', async () => { at: 0, expireAt: 5000, name: 'Happy Web Chat user', - role: 'user' + role: 'user', + tag: null } ]); @@ -51,7 +52,8 @@ test('getter should represent bot and user typing respectively', async () => { at: 0, expireAt: 5000, name: 'bot', - role: 'bot' + role: 'bot', + tag: null } ]); @@ -64,13 +66,15 @@ test('getter should represent bot and user typing respectively', async () => { at: 0, expireAt: 5000, name: 'bot', - role: 'bot' + role: 'bot', + tag: null }, { at: 0, expireAt: 5000, name: 'Happy Web Chat user', - role: 'user' + role: 'user', + tag: null } ]); }); @@ -102,7 +106,8 @@ test('getter should filter out inactive typing', async () => { at: 0, expireAt: 5000, name: 'Happy Web Chat user', - role: 'user' + role: 'user', + tag: null } ]); @@ -121,7 +126,8 @@ test('getter should filter out inactive typing', async () => { at: 3000, expireAt: 8000, name: 'Happy Web Chat user', - role: 'user' + role: 'user', + tag: null } ]); @@ -137,7 +143,8 @@ test('getter should filter out inactive typing', async () => { at: 3000, expireAt: 13000, name: 'Happy Web Chat user', - role: 'user' + role: 'user', + tag: null } ]); }); diff --git a/docs/HOOKS.md b/docs/HOOKS.md index 856d7034f0..c6e547cdd0 100644 --- a/docs/HOOKS.md +++ b/docs/HOOKS.md @@ -137,13 +137,14 @@ interface Typing { expireAt: number; name: string; role: 'bot' | 'user'; + tag: string; } useActiveTyping(expireAfter?: number): [{ [id: string]: Typing }] ``` -This hook will return a list of participants who are actively typing, including the start typing time (`at`) and expiration time (`expireAt`), the name and the role of the participant. +This hook will return a list of participants who are actively typing, including the start typing time (`at`) and expiration time (`expireAt`), the name and the role of the participant and a (`tag`) as an additional property we wish to pass to receiver.. If the participant sends a message after the typing activity, the participant will be explicitly removed from the list. If no messages or typing activities are received, the participant is considered inactive and not listed in the result. To keep the typing indicator active, participants should continuously send the typing activity. @@ -906,6 +907,7 @@ interface Typing { expireAt: number; name: string; role: 'bot' | 'user'; + tag: string; } useRenderTypingIndicator(): diff --git a/packages/api/src/hooks/useActiveTyping.ts b/packages/api/src/hooks/useActiveTyping.ts index c1da42e957..5da73e6c25 100644 --- a/packages/api/src/hooks/useActiveTyping.ts +++ b/packages/api/src/hooks/useActiveTyping.ts @@ -10,18 +10,20 @@ function useActiveTyping(expireAfter?: number): [{ [userId: string]: Typing }] { const [{ typingAnimationDuration }] = useStyleOptions(); const forceRender = useForceRender(); - const typing: { [userId: string]: { at: number; name: string; role: string } } = useSelector(({ typing }) => typing); + const typing: { [userId: string]: { at: number; name: string; role: string; tag?: string } } = useSelector( + ({ typing }) => typing + ); if (typeof expireAfter !== 'number') { expireAfter = typingAnimationDuration; } const activeTyping: { [userId: string]: Typing } = Object.entries(typing).reduce( - (activeTyping, [id, { at, name, role }]) => { + (activeTyping, [id, { at, name, role, tag }]) => { const until = at + expireAfter; if (until > now) { - return { ...activeTyping, [id]: { at, expireAt: until, name, role } }; + return { ...activeTyping, [id]: { at, expireAt: until, name, role, tag } }; } return activeTyping; diff --git a/packages/api/src/types/Typing.ts b/packages/api/src/types/Typing.ts index 18210d7daf..d4b810610d 100644 --- a/packages/api/src/types/Typing.ts +++ b/packages/api/src/types/Typing.ts @@ -3,6 +3,7 @@ type Typing = { expireAt: number; name: string; role: 'bot' | 'user'; + tag?: string; }; export default Typing; diff --git a/packages/core/src/reducers/typing.js b/packages/core/src/reducers/typing.js index 136d3a15e6..e4e23f00f3 100644 --- a/packages/core/src/reducers/typing.js +++ b/packages/core/src/reducers/typing.js @@ -12,7 +12,7 @@ export default function lastTyping(state = DEFAULT_STATE, { payload, type }) { if (type === INCOMING_ACTIVITY || type === POST_ACTIVITY_PENDING) { const { activity: { - from: { id, name, role }, + from: { id, name, role, tag }, type: activityType } } = payload; @@ -21,7 +21,8 @@ export default function lastTyping(state = DEFAULT_STATE, { payload, type }) { state = updateIn(state, [id], () => ({ at: Date.now(), name, - role + role, + tag })); } else if (activityType === 'message') { state = updateIn(state, [id]);