diff --git a/CHANGELOG.md b/CHANGELOG.md
index 54534608e3..916c969ca3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Fixed
- Fixes [#2611](https://github.com/microsoft/BotFramework-WebChat/issues/2611). Fix sample 21: hooks errors, by [@corinagum](https://github.com/corinagum) in PR [#2740](https://github.com/microsoft/BotFramework-WebChat/pull/2740)
+- Fixes [#2609](https://github.com/microsoft/BotFramework-WebChat/issues/2609). Fix sample 12: minimizable button is causing another reconnect on restore, by [@compulim](https://github.com/compulim) in PR [#2758](https://github.com/microsoft/BotFramework-WebChat/pull/2758)
- Fixes [#2773](https://github.com/microsoft/BotFramework-WebChat/issues/2773). Import ES5 version of the following bundles, by [@compulim](https://github.com/compulim) in PR [#2774](https://github.com/microsoft/BotFramework-WebChat/pull/2773)
- [`abort-controller`](https://npmjs.com/package/abort-controller)
- [`event-target-shim`](https://npmjs.com/package/event-target-shim)
diff --git a/samples/12.customization-minimizable-web-chat/package.json b/samples/12.customization-minimizable-web-chat/package.json
index 085f7b34d9..9ee72b3b3c 100644
--- a/samples/12.customization-minimizable-web-chat/package.json
+++ b/samples/12.customization-minimizable-web-chat/package.json
@@ -5,7 +5,7 @@
"homepage": "https://microsoft.github.io/BotFramework-WebChat/12.customization-minimizable-web-chat/",
"dependencies": {
"botframework-webchat": "^4.7.1",
- "memoize-one": "^5.0.2",
+ "classnames": "^2.2.6",
"react": "16.12.0",
"react-dom": "16.12.0",
"react-scripts": "^3.3.0"
diff --git a/samples/12.customization-minimizable-web-chat/src/App.js b/samples/12.customization-minimizable-web-chat/src/App.js
index 188418913f..7e9318f4a1 100644
--- a/samples/12.customization-minimizable-web-chat/src/App.js
+++ b/samples/12.customization-minimizable-web-chat/src/App.js
@@ -1,18 +1,14 @@
-import React, { Component } from 'react';
-import MinimizableWebChat from './MinimizableWebChat';
+import React from 'react';
+import MinimizableWebChat from './MinimizableWebChat';
import WebPageBackground from './WebPage.jpg';
import './App.css';
-class App extends Component {
- render() {
- return (
-
-
-
-
- );
- }
-}
+const App = () => (
+
+
+
+
+);
export default App;
diff --git a/samples/12.customization-minimizable-web-chat/src/MinimizableWebChat.css b/samples/12.customization-minimizable-web-chat/src/MinimizableWebChat.css
index 4f8d74abc6..e5778b2bef 100644
--- a/samples/12.customization-minimizable-web-chat/src/MinimizableWebChat.css
+++ b/samples/12.customization-minimizable-web-chat/src/MinimizableWebChat.css
@@ -49,6 +49,10 @@
width: 30%;
}
+.minimizable-web-chat > .chat-box.hide {
+ display: none;
+}
+
.minimizable-web-chat > .chat-box.left {
left: 20px;
}
diff --git a/samples/12.customization-minimizable-web-chat/src/MinimizableWebChat.js b/samples/12.customization-minimizable-web-chat/src/MinimizableWebChat.js
index 332daf3e89..31c5a6c225 100644
--- a/samples/12.customization-minimizable-web-chat/src/MinimizableWebChat.js
+++ b/samples/12.customization-minimizable-web-chat/src/MinimizableWebChat.js
@@ -1,4 +1,5 @@
-import React from 'react';
+import classNames from 'classnames';
+import React, { useCallback, useMemo, useState } from 'react';
import { createStore, createStyleSet } from 'botframework-webchat';
import WebChat from './WebChat';
@@ -6,18 +7,11 @@ import WebChat from './WebChat';
import './fabric-icons-inline.css';
import './MinimizableWebChat.css';
-export default class extends React.Component {
- constructor(props) {
- super(props);
-
- this.handleFetchToken = this.handleFetchToken.bind(this);
- this.handleMaximizeButtonClick = this.handleMaximizeButtonClick.bind(this);
- this.handleMinimizeButtonClick = this.handleMinimizeButtonClick.bind(this);
- this.handleSwitchButtonClick = this.handleSwitchButtonClick.bind(this);
-
- const store = createStore({}, ({ dispatch }) => next => action => {
- if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
- setTimeout(() => {
+const MinimizableWebChat = () => {
+ const store = useMemo(
+ () =>
+ createStore({}, ({ dispatch }) => next => action => {
+ if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
dispatch({
type: 'WEB_CHAT/SEND_EVENT',
payload: {
@@ -27,90 +21,90 @@ export default class extends React.Component {
}
}
});
- }, 1000);
- } else if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY') {
- if (action.payload.activity.from.role === 'bot') {
- this.setState(() => ({ newMessage: true }));
+ } else if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY') {
+ if (action.payload.activity.from.role === 'bot') {
+ setNewMessage(true);
+ }
}
- }
- return next(action);
- });
+ return next(action);
+ }),
+ []
+ );
- this.state = {
- minimized: true,
- newMessage: false,
- side: 'right',
- store,
- styleSet: createStyleSet({
+ const styleSet = useMemo(
+ () =>
+ createStyleSet({
backgroundColor: 'Transparent'
}),
- token: null
- };
- }
+ []
+ );
- async handleFetchToken() {
- if (!this.state.token) {
+ const [loaded, setLoaded] = useState(false);
+ const [minimized, setMinimized] = useState(true);
+ const [newMessage, setNewMessage] = useState(false);
+ const [side, setSide] = useState('right');
+ const [token, setToken] = useState();
+
+ const handleFetchToken = useCallback(async () => {
+ if (!token) {
const res = await fetch('https://webchat-mockbot.azurewebsites.net/directline/token', { method: 'POST' });
const { token } = await res.json();
- this.setState(() => ({ token }));
+ setToken(token);
}
- }
+ }, [setToken, token]);
+
+ const handleMaximizeButtonClick = useCallback(async () => {
+ setLoaded(true);
+ setMinimized(false);
+ setNewMessage(false);
+ }, [setMinimized, setNewMessage]);
- handleMaximizeButtonClick() {
- this.setState(() => ({
- minimized: false,
- newMessage: false
- }));
- }
+ const handleMinimizeButtonClick = useCallback(() => {
+ setMinimized(true);
+ setNewMessage(false);
+ }, [setMinimized, setNewMessage]);
- handleMinimizeButtonClick() {
- this.setState(() => ({
- minimized: true,
- newMessage: false
- }));
- }
+ const handleSwitchButtonClick = useCallback(() => {
+ setSide(side === 'left' ? 'right' : 'left');
+ }, [setSide, side]);
- handleSwitchButtonClick() {
- this.setState(({ side }) => ({
- side: side === 'left' ? 'right' : 'left'
- }));
- }
+ // TODO: [P2] Currently, we cannot unmount Web Chat from DOM when it is minimized.
+ // Today, if we unmount it, Web Chat will call disconnect on DirectLineJS object.
+ // When minimized, we still want to maintain that connection while the UI is gone.
+ // This is related to https://github.com/microsoft/BotFramework-WebChat/issues/2750.
- render() {
- const {
- state: { minimized, newMessage, side, store, styleSet, token }
- } = this;
+ return (
+
+ {minimized && (
+
+ )}
+ {loaded && (
+
+ )}
+
+ );
+};
- return (
-
- {minimized ? (
-
- ) : (
-
- )}
-
- );
- }
-}
+export default MinimizableWebChat;
diff --git a/samples/12.customization-minimizable-web-chat/src/WebChat.js b/samples/12.customization-minimizable-web-chat/src/WebChat.js
index 90d39229d3..85c8834930 100644
--- a/samples/12.customization-minimizable-web-chat/src/WebChat.js
+++ b/samples/12.customization-minimizable-web-chat/src/WebChat.js
@@ -1,48 +1,35 @@
-import memoize from 'memoize-one';
-import React from 'react';
+import React, { useEffect, useMemo } from 'react';
import ReactWebChat, { createDirectLine, createStyleSet } from 'botframework-webchat';
import './WebChat.css';
-export default class extends React.Component {
- constructor(props) {
- super(props);
+const WebChat = ({ className, onFetchToken, store, token }) => {
+ const directLine = useMemo(() => createDirectLine({ token }), [token]);
- this.createDirectLine = memoize(token => createDirectLine({ token }));
-
- this.state = {
- styleSet: createStyleSet({
+ const styleSet = useMemo(
+ () =>
+ createStyleSet({
backgroundColor: 'Transparent'
- })
- };
- }
-
- componentDidMount() {
- !this.props.token && this.props.onFetchToken();
- }
+ }),
+ []
+ );
- render() {
- const {
- props: { className, store, token },
- state: { styleSet }
- } = this;
+ useEffect(() => {
+ onFetchToken();
+ }, [onFetchToken]);
- return token ? (
-
- ) : (
-
-
-
-
-
-
Please wait while we are connecting.
+ return token ? (
+
+ ) : (
+
+
+
+
+
Please wait while we are connecting.
- );
- }
-}
+
+ );
+};
+
+export default WebChat;