Upgraded Web Chat to 4.12.0 and fixed various Web Chat bugs (#2236)
* Added ability to debug shared package (redux state). * Bumped Web Chat to 4.12.0 * Integrated inspector with new WC activity focus hook * Updated fallback speech service ponyfill API * Fixed WC send box overflow visual bug * Added changelog entry
This commit is contained in:
Родитель
e16706f489
Коммит
5e2ea09c7f
|
@ -33,7 +33,7 @@
|
|||
"outputCapture": "std",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"cwd": "${workspaceFolder}/packages/app/main",
|
||||
"outFiles": [ "${workspaceRoot}/packages/app/main/app/**/*.js"]
|
||||
"outFiles": [ "${workspaceRoot}/packages/app/main/app/**/*.js", "${workspaceRoot}/packages/app/shared/**/*.js"]
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
|
|
|
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- [main] Bumped `electron` from `4.1.1` to `11.0.1` in PR [2226](https://github.com/microsoft/BotFramework-Emulator/pull/2226)
|
||||
- [main] Bumped `electron-builder` to `22.9.1` and `electron-updater` to `4.3.5` to fix the Mac build in PR [2230](https://github.com/microsoft/BotFramework-Emulator/pull/2230)
|
||||
- [client] Re-enabled the `<webview>` tag in the client so that the inspectors show again in PR [2233](https://github.com/microsoft/BotFramework-Emulator/pull/2233)
|
||||
- [client] Bumped `botframework-webchat` to v4.12.0 and fixed various Web Chat-related bugs in PR [2236](https://github.com/microsoft/BotFramework-Emulator/pull/2236)
|
||||
|
||||
## v4.11.0 - 2020 - 11 - 05
|
||||
- [client] Moved from master to main as the default branch. [2194](https://github.com/microsoft/BotFramework-Emulator/pull/2194)
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -110,8 +110,8 @@
|
|||
"base64url": "3.0.0",
|
||||
"botframework-config": "4.4.0",
|
||||
"botframework-schema": "^4.3.4",
|
||||
"botframework-webchat": "4.11.0",
|
||||
"botframework-webchat-core": "4.11.0",
|
||||
"botframework-webchat": "4.12.0",
|
||||
"botframework-webchat-core": "4.12.0",
|
||||
"core-js": "^3.6.5",
|
||||
"eslint-plugin-react": "^7.12.3",
|
||||
"markdown-it": "^8.4.2",
|
||||
|
|
|
@ -567,8 +567,7 @@ describe('The ChatSagas,', () => {
|
|||
// call createCognitiveServicesSpeechServicesPonyfillFactory
|
||||
expect(gen.next({}).value).toEqual(
|
||||
call(createCognitiveServicesSpeechServicesPonyfillFactory, {
|
||||
authorizationToken: jasmine.anything(), // any(Promise) doesn't match correctly
|
||||
region: 'westus',
|
||||
credentials: jasmine.any(Function),
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -769,8 +768,7 @@ describe('The ChatSagas,', () => {
|
|||
const existingFactory = {};
|
||||
expect(gen.next(existingFactory).value).toEqual(
|
||||
call(createCognitiveServicesSpeechServicesPonyfillFactory, {
|
||||
authorizationToken: jasmine.anything(), // .any(Promise) doesn't match correctly
|
||||
region: 'westus',
|
||||
credentials: jasmine.any(Function),
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -904,8 +902,7 @@ describe('The ChatSagas,', () => {
|
|||
const existingFactory = {};
|
||||
expect(gen.next(existingFactory).value).toEqual(
|
||||
call(createCognitiveServicesSpeechServicesPonyfillFactory, {
|
||||
authorizationToken: jasmine.anything(), // .any(Promise) doesn't match correctly
|
||||
region: 'westus',
|
||||
credentials: jasmine.any(Function),
|
||||
})
|
||||
);
|
||||
|
||||
|
|
|
@ -467,11 +467,13 @@ export class ChatSagas {
|
|||
endpointId,
|
||||
!!existingFactory
|
||||
);
|
||||
|
||||
const factory = yield call(createCognitiveServicesSpeechServicesPonyfillFactory, {
|
||||
authorizationToken: speechAuthenticationToken,
|
||||
const fetchSpeechCredentials = async () => ({
|
||||
authorizationToken: await speechAuthenticationToken,
|
||||
region: 'westus', // Currently, the prod speech service is only deployed to westus
|
||||
});
|
||||
const factory = yield call(createCognitiveServicesSpeechServicesPonyfillFactory, {
|
||||
credentials: fetchSpeechCredentials,
|
||||
});
|
||||
|
||||
yield put(webSpeechFactoryUpdated(documentId, factory)); // Provide the new factory to the store
|
||||
} catch (e) {
|
||||
|
@ -651,11 +653,13 @@ export class ChatSagas {
|
|||
botEndpoint.id,
|
||||
!!existingFactory
|
||||
);
|
||||
|
||||
const factory = yield call(createCognitiveServicesSpeechServicesPonyfillFactory, {
|
||||
authorizationToken: speechAuthenticationToken,
|
||||
const fetchSpeechCredentials = async () => ({
|
||||
authorizationToken: await speechAuthenticationToken,
|
||||
region: 'westus', // Currently, the prod speech service is only deployed to westus
|
||||
});
|
||||
const factory = yield call(createCognitiveServicesSpeechServicesPonyfillFactory, {
|
||||
credentials: fetchSpeechCredentials,
|
||||
});
|
||||
|
||||
yield put(webSpeechFactoryUpdated(documentId, factory)); // Provide the new factory to the store
|
||||
} catch (e) {
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
background-color: white;
|
||||
display: flex;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
height: calc(100% - 36px); // 36px is the height of the <header> in chatPanel.tsx
|
||||
width: 100%;
|
||||
user-select: text;
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
import * as React from 'react';
|
||||
import { mount, ReactWrapper, shallow, ShallowWrapper } from 'enzyme';
|
||||
import { Provider } from 'react-redux';
|
||||
import ReactWebChat, { createDirectLine, createStyleSet } from 'botframework-webchat';
|
||||
import { createDirectLine, createStyleSet, Components } from 'botframework-webchat';
|
||||
import { ActivityTypes } from 'botframework-schema';
|
||||
import {
|
||||
bot,
|
||||
|
@ -56,6 +56,8 @@ import webChatStyleOptions from './webChatTheme';
|
|||
import { ChatContainer } from './chatContainer';
|
||||
import { ChatProps, Chat } from './chat';
|
||||
|
||||
const { Composer } = Components;
|
||||
|
||||
jest.mock('./chat.scss', () => ({
|
||||
get bubbleContentColor() {
|
||||
return '#fff';
|
||||
|
@ -160,7 +162,7 @@ describe('<ChatContainer />', () => {
|
|||
wrapper.setProps({
|
||||
children: <ChatContainer {...updatedProps} />,
|
||||
});
|
||||
expect(wrapper.find(ReactWebChat).props().disabled).toBeTruthy();
|
||||
expect(wrapper.find(Composer).props().disabled).toBeTruthy();
|
||||
|
||||
updatedProps = {
|
||||
...props,
|
||||
|
@ -170,7 +172,7 @@ describe('<ChatContainer />', () => {
|
|||
wrapper.setProps({
|
||||
children: <ChatContainer {...updatedProps} />,
|
||||
});
|
||||
expect(wrapper.find(ReactWebChat).props().disabled).toBeFalsy();
|
||||
expect(wrapper.find(Composer).props().disabled).toBeFalsy();
|
||||
|
||||
updatedProps = {
|
||||
...props,
|
||||
|
@ -180,7 +182,7 @@ describe('<ChatContainer />', () => {
|
|||
wrapper.setProps({
|
||||
children: <ChatContainer {...updatedProps} />,
|
||||
});
|
||||
expect(wrapper.find(ReactWebChat).props().disabled).toBeFalsy();
|
||||
expect(wrapper.find(Composer).props().disabled).toBeFalsy();
|
||||
|
||||
updatedProps = {
|
||||
...props,
|
||||
|
@ -190,7 +192,7 @@ describe('<ChatContainer />', () => {
|
|||
wrapper.setProps({
|
||||
children: <ChatContainer {...updatedProps} />,
|
||||
});
|
||||
expect(wrapper.find(ReactWebChat).props().disabled).toBeFalsy();
|
||||
expect(wrapper.find(Composer).props().disabled).toBeFalsy();
|
||||
|
||||
updatedProps = {
|
||||
...props,
|
||||
|
@ -200,7 +202,7 @@ describe('<ChatContainer />', () => {
|
|||
wrapper.setProps({
|
||||
children: <ChatContainer {...updatedProps} />,
|
||||
});
|
||||
expect(wrapper.find(ReactWebChat).props().disabled).toBeFalsy();
|
||||
expect(wrapper.find(Composer).props().disabled).toBeFalsy();
|
||||
|
||||
updatedProps = {
|
||||
...props,
|
||||
|
@ -210,7 +212,7 @@ describe('<ChatContainer />', () => {
|
|||
wrapper.setProps({
|
||||
children: <ChatContainer {...updatedProps} />,
|
||||
});
|
||||
expect(wrapper.find(ReactWebChat).props().disabled).toBeTruthy();
|
||||
expect(wrapper.find(Composer).props().disabled).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('when there is no direct line client', () => {
|
||||
|
@ -223,7 +225,7 @@ describe('<ChatContainer />', () => {
|
|||
|
||||
describe('when there is a direct line client', () => {
|
||||
it('renders the WebChat component', () => {
|
||||
const webChat = wrapper.find(ReactWebChat);
|
||||
const webChat = wrapper.find(Composer);
|
||||
const styleSet = createStyleSet({ ...webChatStyleOptions });
|
||||
|
||||
styleSet.fileContent = {
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
import { ValueTypes, RestartConversationStatus } from '@bfemulator/app-shared';
|
||||
import { Activity, ActivityTypes } from 'botframework-schema';
|
||||
import ReactWebChat, { createStyleSet } from 'botframework-webchat';
|
||||
import { createStyleSet, Components } from 'botframework-webchat';
|
||||
import * as React from 'react';
|
||||
import { PureComponent, KeyboardEvent, MouseEvent, ReactNode } from 'react';
|
||||
import { EmulatorMode } from '@bfemulator/sdk-shared';
|
||||
|
@ -44,6 +44,9 @@ import * as styles from './chat.scss';
|
|||
import webChatStyleOptions from './webChatTheme';
|
||||
import { TraceActivityContainer } from './traceActivityContainer';
|
||||
import { ConnectionMessageContainer } from './connectionMessageContainer';
|
||||
import { TranscriptFocusListener } from './transcriptFocusListener';
|
||||
|
||||
const { BasicWebChat, Composer } = Components;
|
||||
|
||||
export interface ChatProps {
|
||||
botId?: string;
|
||||
|
@ -65,9 +68,11 @@ interface ChatState {
|
|||
highlightedActivities?: Activity[];
|
||||
}
|
||||
|
||||
type ActivityMap = Record<string, Activity>;
|
||||
|
||||
export class Chat extends PureComponent<ChatProps, ChatState> {
|
||||
public state = { waitForSpeechToken: false } as ChatState;
|
||||
private activityMap: { [activityId: string]: Activity } = {};
|
||||
private activityMap: ActivityMap = {};
|
||||
|
||||
public render() {
|
||||
const {
|
||||
|
@ -113,9 +118,11 @@ export class Chat extends PureComponent<ChatProps, ChatState> {
|
|||
name: 'Bot',
|
||||
};
|
||||
|
||||
const boundUpdateSelectedActivity = this.updateSelectedActivity.bind(this);
|
||||
|
||||
return (
|
||||
<div className={styles.chat}>
|
||||
<ReactWebChat
|
||||
<Composer
|
||||
store={webchatStore}
|
||||
activityMiddleware={this.createActivityMiddleware}
|
||||
cardActionMiddleware={this.cardActionMiddleware}
|
||||
|
@ -128,7 +135,10 @@ export class Chat extends PureComponent<ChatProps, ChatState> {
|
|||
userID={currentUser.id}
|
||||
username={currentUser.name || 'User'}
|
||||
webSpeechPonyfillFactory={webSpeechPonyfillFactory}
|
||||
/>
|
||||
>
|
||||
<BasicWebChat />
|
||||
<TranscriptFocusListener updateSelectedActivity={boundUpdateSelectedActivity} />
|
||||
</Composer>
|
||||
<ConnectionMessageContainer documentId={this.props.documentId} />
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
import { connect } from 'react-redux';
|
||||
import { User } from '@bfemulator/sdk-shared';
|
||||
import { Activity } from 'botframework-schema';
|
||||
import {
|
||||
executeCommand,
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
//
|
||||
// Microsoft Bot Framework: http://botframework.com
|
||||
//
|
||||
// Bot Framework Emulator Github:
|
||||
// https://github.com/Microsoft/BotFramwork-Emulator
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// MIT License:
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
import { FC, useCallback } from 'react';
|
||||
import { hooks } from 'botframework-webchat';
|
||||
import { Activity } from 'botframework-schema';
|
||||
|
||||
const { useObserveTranscriptFocus } = hooks;
|
||||
|
||||
type TranscriptFocusListenerProps = { updateSelectedActivity?: (id: string) => void };
|
||||
export const TranscriptFocusListener: FC<TranscriptFocusListenerProps> = (props: TranscriptFocusListenerProps) => {
|
||||
const onActivityFocused = useCallback(({ activity }: { activity: Activity }) => {
|
||||
if (activity) {
|
||||
props.updateSelectedActivity(activity.id);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useObserveTranscriptFocus && useObserveTranscriptFocus(onActivityFocused, [onActivityFocused]);
|
||||
|
||||
// strictly listen for and act on a new activity being selected -- do not render anything
|
||||
return null;
|
||||
};
|
|
@ -64,4 +64,6 @@ export default {
|
|||
transcriptOverlayButtonColor: 'var(--webchat-transcript-overlay-text)',
|
||||
transcriptOverlayButtonColorOnFocus: 'var(--webchat-transcript-overlay-text-focus)',
|
||||
transcriptOverlayButtonColorOnHover: 'var(--webchat-transcript-overlay-text-focus)',
|
||||
|
||||
transcriptVisualKeyboardIndicatorColor: 'var(--webchat-transcript-visual-kb-indicator-color)',
|
||||
};
|
||||
|
|
|
@ -55,6 +55,9 @@ html {
|
|||
--webchat-transcript-overlay-text: var(--neutral-1);
|
||||
--webchat-transcript-overlay-text-focus: var(--neutral-1);
|
||||
|
||||
/* The outer box that indicates the transcript is focused */
|
||||
--webchat-transcript-visual-kb-indicator-color: var(--global-focus-outline-color);
|
||||
|
||||
/* suggested actions */
|
||||
--webchat-sa-bg: var(--webchat-bubble-bg);
|
||||
--webchat-sa-border-color: var(--neutral-4);
|
||||
|
|
|
@ -54,6 +54,9 @@ html {
|
|||
--webchat-transcript-overlay-text: var(--neutral-15);
|
||||
--webchat-transcript-overlay-text-focus: var(--neutral-15);
|
||||
|
||||
/* The outer box that indicates the transcript is focused */
|
||||
--webchat-transcript-visual-kb-indicator-color: var(--global-focus-outline-color);
|
||||
|
||||
/* suggested actions */
|
||||
--webchat-sa-bg: var(--webchat-bubble-bg);
|
||||
--webchat-sa-border-color: var(--neutral-4);
|
||||
|
|
|
@ -53,6 +53,9 @@ html {
|
|||
--webchat-transcript-overlay-text: var(--neutral-1);
|
||||
--webchat-transcript-overlay-text-focus: var(--neutral-1);
|
||||
|
||||
/* The outer box that indicates the transcript is focused */
|
||||
--webchat-transcript-visual-kb-indicator-color: var(--global-focus-outline-color);
|
||||
|
||||
/* suggested actions */
|
||||
--webchat-sa-bg: var(--webchat-bubble-bg);
|
||||
--webchat-sa-border-color: transparent;
|
||||
|
|
Загрузка…
Ссылка в новой задаче