diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bbf64263e..8d0357d8fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -121,6 +121,7 @@ Notes: web developers are advised to use [`~` (tilde range)](https://github.com/ - `@msinternal/botframework-webchat-react-hooks` for helpers for React hooks - Added link sanitization and ESLint rules, in PR [#5564](https://github.com/microsoft/BotFramework-WebChat/pull/5564), by [@compulim](https://github.com/compulim) - Added blob URL sanitization and ESLint rules, in PR [#5568](https://github.com/microsoft/BotFramework-WebChat/pull/5568), by [@compulim](https://github.com/compulim) +- Added new prop `enableStreaming` to composer that activates streamed responses in PR [#5467](https://github.com/microsoft/BotFramework-WebChat/pull/5467), by [pranavjoshi001](https://github.com/pranavjoshi001) ### Changed diff --git a/packages/api/src/hooks/Composer.tsx b/packages/api/src/hooks/Composer.tsx index 81985a0ea0..85641ac527 100644 --- a/packages/api/src/hooks/Composer.tsx +++ b/packages/api/src/hooks/Composer.tsx @@ -21,6 +21,7 @@ import { sendPostBack, setDictateInterims, setDictateState, + setEnableStreaming, setLanguage, setNotification, setSendBox, @@ -111,6 +112,7 @@ const DISPATCHERS = { sendPostBack, setDictateInterims, setDictateState, + setEnableStreaming, setNotification, setSendBox, setSendBoxAttachments, @@ -232,6 +234,7 @@ type ComposerCoreProps = Readonly<{ type: string, quality: number ) => Promise; + enableStreaming?: boolean; grammars?: any; groupActivitiesMiddleware?: OneOrMany; locale?: string; @@ -277,6 +280,7 @@ const ComposerCore = ({ directLine, disabled, downscaleImageToDataURL, + enableStreaming, grammars, groupActivitiesMiddleware, locale, @@ -317,6 +321,10 @@ const ComposerCore = ({ dispatch(setSendTypingIndicator(!!sendTypingIndicator)); }, [dispatch, sendTypingIndicator]); + useEffect(() => { + dispatch(setEnableStreaming(!!enableStreaming)); + }, [dispatch, enableStreaming]); + useEffect(() => { dispatch( createConnectAction({ @@ -648,6 +656,7 @@ ComposerCore.defaultProps = { dir: 'auto', disabled: false, downscaleImageToDataURL: undefined, + enableStreaming: false, grammars: [], groupActivitiesMiddleware: undefined, locale: window.navigator.language || 'en-US', @@ -690,6 +699,7 @@ ComposerCore.propTypes = { }).isRequired, disabled: PropTypes.bool, downscaleImageToDataURL: PropTypes.func, + enableStreaming: PropTypes.bool, grammars: PropTypes.arrayOf(PropTypes.string), groupActivitiesMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), locale: PropTypes.string, diff --git a/packages/core/src/actions/setEnableStreaming.ts b/packages/core/src/actions/setEnableStreaming.ts new file mode 100644 index 0000000000..72bb95467e --- /dev/null +++ b/packages/core/src/actions/setEnableStreaming.ts @@ -0,0 +1,10 @@ +const SET_ENABLE_STREAMING = 'WEB_CHAT/SET_ENABLE_STREAMING'; + +export default function setEnableStreaming(enableStreaming: boolean) { + return { + type: SET_ENABLE_STREAMING, + payload: { enableStreaming } + }; +} + +export { SET_ENABLE_STREAMING }; diff --git a/packages/core/src/createReducer.ts b/packages/core/src/createReducer.ts index 3e9c9894b1..d6184d0783 100644 --- a/packages/core/src/createReducer.ts +++ b/packages/core/src/createReducer.ts @@ -17,6 +17,7 @@ import sendTypingIndicator from './reducers/sendTypingIndicator'; import shouldSpeakIncomingActivity from './reducers/shouldSpeakIncomingActivity'; import suggestedActions from './reducers/suggestedActions'; import suggestedActionsOriginActivity from './reducers/suggestedActionsOriginActivity'; +import enableStreaming from './reducers/enableStreaming'; import type { GlobalScopePonyfill } from './types/GlobalScopePonyfill'; @@ -26,6 +27,7 @@ export default function createReducer(ponyfill: GlobalScopePonyfill) { connectivityStatus, dictateInterims, dictateState, + enableStreaming, internal: createInternalReducer(ponyfill), language, notifications: createNotificationsReducer(ponyfill), diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index e5107f0a35..8982813742 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -18,6 +18,7 @@ import setSendBox from './actions/setSendBox'; import setSendBoxAttachments from './actions/setSendBoxAttachments'; import setSendTimeout from './actions/setSendTimeout'; import setSendTypingIndicator from './actions/setSendTypingIndicator'; +import setEnableStreaming from './actions/setEnableStreaming'; import startDictate from './actions/startDictate'; import startSpeakingActivity from './actions/startSpeakingActivity'; import stopDictate from './actions/stopDictate'; @@ -121,6 +122,7 @@ export { sendPostBack, setDictateInterims, setDictateState, + setEnableStreaming, setLanguage, setNotification, setSendBox, diff --git a/packages/core/src/reducers/enableStreaming.ts b/packages/core/src/reducers/enableStreaming.ts new file mode 100644 index 0000000000..4833759457 --- /dev/null +++ b/packages/core/src/reducers/enableStreaming.ts @@ -0,0 +1,16 @@ +import { SET_ENABLE_STREAMING } from '../actions/setEnableStreaming'; + +const DEFAULT_STATE = false; + +export default function enableStreaming(state = DEFAULT_STATE, { payload, type }) { + switch (type) { + case SET_ENABLE_STREAMING: + state = payload.enableStreaming; + break; + + default: + break; + } + + return state; +} diff --git a/packages/core/src/sagas/sendMessageToPostActivitySaga.ts b/packages/core/src/sagas/sendMessageToPostActivitySaga.ts index 9b36e09993..8427a1e271 100644 --- a/packages/core/src/sagas/sendMessageToPostActivitySaga.ts +++ b/packages/core/src/sagas/sendMessageToPostActivitySaga.ts @@ -1,12 +1,14 @@ -import { put, takeEvery } from 'redux-saga/effects'; +import { put, select, takeEvery } from 'redux-saga/effects'; import postActivity from '../actions/postActivity'; import sendMessage, { SEND_MESSAGE } from '../actions/sendMessage'; import whileConnected from './effects/whileConnected'; +import enableStreaming from '../selectors/enableStreaming'; function* postActivityWithMessage({ payload: { attachments = [], channelData, method, text } }: ReturnType) { + const isStreamingEnabled = yield select(enableStreaming); yield put( postActivity( { @@ -23,6 +25,7 @@ function* postActivityWithMessage({ ...channelData, attachmentSizes: attachments.map(({ blob: { size } }) => size) }, + ...(isStreamingEnabled && { deliveryMode: 'stream' }), text: text || undefined, textFormat: 'plain', type: 'message' diff --git a/packages/core/src/selectors/enableStreaming.ts b/packages/core/src/selectors/enableStreaming.ts new file mode 100644 index 0000000000..4d5ef980d8 --- /dev/null +++ b/packages/core/src/selectors/enableStreaming.ts @@ -0,0 +1,3 @@ +import type { ReduxState } from '../types/internal/ReduxState'; + +export default ({ enableStreaming }: ReduxState): boolean => enableStreaming; diff --git a/packages/core/src/types/internal/ReduxState.ts b/packages/core/src/types/internal/ReduxState.ts index a3c00c16d5..c32939d8d4 100644 --- a/packages/core/src/types/internal/ReduxState.ts +++ b/packages/core/src/types/internal/ReduxState.ts @@ -14,6 +14,7 @@ type ReduxState = { sendTimeout: number; sendTypingIndicator: boolean; shouldSpeakIncomingActivity: boolean; + enableStreaming: boolean; }; export type { ReduxState };