From 2982283691d91f78653078b42ee5ef9639ae9b88 Mon Sep 17 00:00:00 2001 From: William Wong Date: Sun, 3 Jan 2021 23:29:46 -0800 Subject: [PATCH 1/9] Customize scroll behavior --- CHANGELOG.md | 31 ++- ...ehavior-should-scroll-correctly-1-snap.png | Bin 0 -> 20525 bytes ...ehavior-should-scroll-correctly-1-snap.png | Bin 0 -> 18817 bytes ...ehavior-should-scroll-correctly-1-snap.png | Bin 0 -> 24173 bytes ...ehavior-should-scroll-correctly-1-snap.png | Bin 0 -> 20495 bytes .../html/autoScroll.acknowledgement.html | 172 ++++++++++++ __tests__/html/autoScroll.acknowledgement.js | 7 + __tests__/html/autoScroll.snap.activity.html | 132 +++++++++ __tests__/html/autoScroll.snap.activity.js | 7 + .../html/autoScroll.snap.activityAndPage.html | 145 ++++++++++ .../html/autoScroll.snap.activityAndPage.js | 7 + __tests__/html/autoScroll.snap.default.html | 115 ++++++++ __tests__/html/autoScroll.snap.default.js | 7 + __tests__/html/autoScroll.snap.page.html | 119 ++++++++ __tests__/html/autoScroll.snap.page.js | 7 + packages/api/src/defaultStyleOptions.js | 8 +- packages/component/package-lock.json | 13 +- packages/component/package.json | 2 +- packages/component/src/BasicTranscript.js | 253 ++++++++++++++++-- packages/component/src/Composer.js | 78 ++++-- packages/component/src/Utils/findLastIndex.js | 11 + .../component/src/Utils/findLastIndex.spec.js | 29 ++ .../hooks/internal/useAcknowledgedActivity.js | 61 +++++ .../src/hooks/internal/useChanged.js | 10 + .../internal/useDispatchScrollPosition.js | 7 + .../useGetTranscriptActivityElementByID.js | 16 -- .../useGetTranscriptScrollableElement.js | 11 - .../src/hooks/internal/useRegisterScrollTo.js | 18 ++ .../hooks/internal/useRegisterScrollToEnd.js | 16 ++ .../internal/useTranscriptRootElementRef.js | 5 - .../src/hooks/useObserveScrollPosition.js | 42 +-- packages/component/src/hooks/useScrollTo.js | 44 +-- .../component/src/hooks/useScrollToEnd.js | 8 +- .../utils/createDirectLineWithTranscript.js | 21 +- 34 files changed, 1212 insertions(+), 190 deletions(-) create mode 100644 __tests__/__image_snapshots__/html/auto-scroll-snap-activity-and-page-js-auto-scroll-with-activity-and-page-snap-behavior-should-scroll-correctly-1-snap.png create mode 100644 __tests__/__image_snapshots__/html/auto-scroll-snap-activity-js-auto-scroll-with-activity-snap-behavior-should-scroll-correctly-1-snap.png create mode 100644 __tests__/__image_snapshots__/html/auto-scroll-snap-default-js-auto-scroll-with-default-snap-behavior-should-scroll-correctly-1-snap.png create mode 100644 __tests__/__image_snapshots__/html/auto-scroll-snap-page-js-auto-scroll-with-page-snap-behavior-should-scroll-correctly-1-snap.png create mode 100644 __tests__/html/autoScroll.acknowledgement.html create mode 100644 __tests__/html/autoScroll.acknowledgement.js create mode 100644 __tests__/html/autoScroll.snap.activity.html create mode 100644 __tests__/html/autoScroll.snap.activity.js create mode 100644 __tests__/html/autoScroll.snap.activityAndPage.html create mode 100644 __tests__/html/autoScroll.snap.activityAndPage.js create mode 100644 __tests__/html/autoScroll.snap.default.html create mode 100644 __tests__/html/autoScroll.snap.default.js create mode 100644 __tests__/html/autoScroll.snap.page.html create mode 100644 __tests__/html/autoScroll.snap.page.js create mode 100644 packages/component/src/Utils/findLastIndex.js create mode 100644 packages/component/src/Utils/findLastIndex.spec.js create mode 100644 packages/component/src/hooks/internal/useAcknowledgedActivity.js create mode 100644 packages/component/src/hooks/internal/useChanged.js create mode 100644 packages/component/src/hooks/internal/useDispatchScrollPosition.js delete mode 100644 packages/component/src/hooks/internal/useGetTranscriptActivityElementByID.js delete mode 100644 packages/component/src/hooks/internal/useGetTranscriptScrollableElement.js create mode 100644 packages/component/src/hooks/internal/useRegisterScrollTo.js create mode 100644 packages/component/src/hooks/internal/useRegisterScrollToEnd.js delete mode 100644 packages/component/src/hooks/internal/useTranscriptRootElementRef.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 38c68edd10..7df24785e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,24 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Added + +- Resolves [#2745](https://github.com/microsoft/BotFramework-WebChat/issues/2745). Added new `inline` layout to suggested actions, by [@compulim](https://github.com/compulim) in PR [#3641](https://github.com/microsoft/BotFramework-WebChat/pull/3641) +- Added new style options to customize auto-scroll, by [@compulim](https://github.com/compulim) in PR [#XXX](https://github.com/microsoft/BotFramework-WebChat/pull/XXX) + - Set `autoScrollSnapOnActivity` to `true` to pause auto-scroll after more than one activity is shown, or a number to pause after X number of activities + - Set `autoScrollSnapOnPage` to `true` to pause auto-scroll when a page is filled, or a number between `0` and `1` to pause after % of page is filled + - Set `autoScrollSnapOnActivityOffset` and `autoScrollSnapOnPageOffset` to a number (in pixels) to overscroll/underscroll after the pause +- Supports multiple transcripts in a single composition, by [@compulim](https://github.com/compulim) in PR [#XXX](https://github.com/microsoft/BotFramework-WebChat/pull/XXX) + +### Fixed + +- Fixes [#3278](https://github.com/microsoft/BotFramework-WebChat/issues/3278). Update `HOOKS.md` verbiage, by [@corinagum](https://github.com/corinagum) in PR [#3564](https://github.com/microsoft/BotFramework-WebChat/pull/3564) +- Fixes [#3534](https://github.com/microsoft/BotFramework-WebChat/issues/3534). Remove 2020 deprecations, by [@corinagum](https://github.com/corinagum) in PR [#3564](https://github.com/microsoft/BotFramework-WebChat/pull/3564) +- Fixes [#3561](https://github.com/microsoft/BotFramework-WebChat/issues/3561). Remove MyGet mentions from samples, by [@corinagum](https://github.com/corinagum) in PR [#3564](https://github.com/microsoft/BotFramework-WebChat/pull/3564) +- Fixes [#3537](https://github.com/microsoft/BotFramework-WebChat/issues/3537). Fix some carousels improperly using aria-roledescription, by [@corinagum](https://github.com/corinagum) in PR [#3599](https://github.com/microsoft/BotFramework-WebChat/pull/3599) +- Fixes [#3483](https://github.com/microsoft/BotFramework-WebChat/issues/3483). IE11 anchors fixed to open securely without 'noreferrer' or 'noopener', by [@corinagum](https://github.com/corinagum) in PR [#3607](https://github.com/microsoft/BotFramework-WebChat/pull/3607) +- Fixes [#3565](https://github.com/microsoft/BotFramework-WebChat/issues/3565). Allow strikethrough `` on sanitize markdown, by [@corinagum](https://github.com/corinagum) in PR [#3646](https://github.com/microsoft/BotFramework-WebChat/pull/3646) + ### Changed - Bumped all dependencies to the latest versions, by [@compulim](https://github.com/compulim) in PR [#3594](https://github.com/microsoft/BotFramework-WebChat/pull/3594) @@ -70,19 +88,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - [`whatwg-fetch@3.4.1`](https://npmjs.com/package/whatwg-fetch) - [#3392](https://github.com/microsoft/BotFramework-WebChat/issues/3392) Bumped Adaptive Cards to the 2.5.0, by [@corinagum](https://github.com/corinagum) in PR [#3630](https://github.com/microsoft/BotFramework-WebChat/pull/3630) -### Added - -- Resolves [#2745](https://github.com/microsoft/BotFramework-WebChat/issues/2745). Added new `inline` layout to suggested actions, by [@compulim](https://github.com/compulim) in PR [#3641](https://github.com/microsoft/BotFramework-WebChat/pull/3641) - -### Fixed - -- Fixes [#3278](https://github.com/microsoft/BotFramework-WebChat/issues/3278). Update `HOOKS.md` verbiage, by [@corinagum](https://github.com/corinagum) in PR [#3564](https://github.com/microsoft/BotFramework-WebChat/pull/3564) -- Fixes [#3534](https://github.com/microsoft/BotFramework-WebChat/issues/3534). Remove 2020 deprecations, by [@corinagum](https://github.com/corinagum) in PR [#3564](https://github.com/microsoft/BotFramework-WebChat/pull/3564) -- Fixes [#3561](https://github.com/microsoft/BotFramework-WebChat/issues/3561). Remove MyGet mentions from samples, by [@corinagum](https://github.com/corinagum) in PR [#3564](https://github.com/microsoft/BotFramework-WebChat/pull/3564) -- Fixes [#3537](https://github.com/microsoft/BotFramework-WebChat/issues/3537). Fix some carousels improperly using aria-roledescription, by [@corinagum](https://github.com/corinagum) in PR [#3599](https://github.com/microsoft/BotFramework-WebChat/pull/3599) -- Fixes [#3483](https://github.com/microsoft/BotFramework-WebChat/issues/3483). IE11 anchors fixed to open securely without 'noreferrer' or 'noopener', by [@corinagum](https://github.com/corinagum) in PR [#3607](https://github.com/microsoft/BotFramework-WebChat/pull/3607) -- Fixes [#3565](https://github.com/microsoft/BotFramework-WebChat/issues/3565). Allow strikethrough `` on sanitize markdown, by [@corinagum](https://github.com/corinagum) in PR [#3646](https://github.com/microsoft/BotFramework-WebChat/pull/3646) - ### Samples - Fixes [#3473](https://github.com/microsoft/BotFramework-WebChat/issues/3473). Fix samples using activityMiddleware (from 4.10.0 breaking changes), by [@corinagum](https://github.com/corinagum) in PR [#3601](https://github.com/microsoft/BotFramework-WebChat/pull/3601) diff --git a/__tests__/__image_snapshots__/html/auto-scroll-snap-activity-and-page-js-auto-scroll-with-activity-and-page-snap-behavior-should-scroll-correctly-1-snap.png b/__tests__/__image_snapshots__/html/auto-scroll-snap-activity-and-page-js-auto-scroll-with-activity-and-page-snap-behavior-should-scroll-correctly-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..a63d5b929b8be15f4dd2d1cb24511fe36844093b GIT binary patch literal 20525 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 AdH?_b literal 0 HcmV?d00001 diff --git a/__tests__/__image_snapshots__/html/auto-scroll-snap-activity-js-auto-scroll-with-activity-snap-behavior-should-scroll-correctly-1-snap.png b/__tests__/__image_snapshots__/html/auto-scroll-snap-activity-js-auto-scroll-with-activity-snap-behavior-should-scroll-correctly-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..f2a9820058bcd7ad36bb4d59dbb6bc538e9e16be GIT binary patch literal 18817 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�*st%FMsvXt?Nw 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 literal 0 HcmV?d00001 diff --git a/__tests__/__image_snapshots__/html/auto-scroll-snap-page-js-auto-scroll-with-page-snap-behavior-should-scroll-correctly-1-snap.png b/__tests__/__image_snapshots__/html/auto-scroll-snap-page-js-auto-scroll-with-page-snap-behavior-should-scroll-correctly-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..969e8410ae86dc0e84eec48d0228999d268b70b7 GIT binary patch literal 20495 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 literal 0 HcmV?d00001 diff --git a/__tests__/html/autoScroll.acknowledgement.html b/__tests__/html/autoScroll.acknowledgement.html new file mode 100644 index 0000000000..ac53b6841d --- /dev/null +++ b/__tests__/html/autoScroll.acknowledgement.html @@ -0,0 +1,172 @@ + + + + + + + + +
+
+ +
+ +
+ + + diff --git a/__tests__/html/autoScroll.acknowledgement.js b/__tests__/html/autoScroll.acknowledgement.js new file mode 100644 index 0000000000..7e1f59b13e --- /dev/null +++ b/__tests__/html/autoScroll.acknowledgement.js @@ -0,0 +1,7 @@ +/** + * @jest-environment ./__tests__/html/__jest__/WebChatEnvironment.js + */ + +describe('Auto-scroll acknowledgement logic', () => { + test('should acknowledge activities correctly', () => runHTMLTest('autoScroll.acknowledgement.html')); +}); diff --git a/__tests__/html/autoScroll.snap.activity.html b/__tests__/html/autoScroll.snap.activity.html new file mode 100644 index 0000000000..a1ab8edcd2 --- /dev/null +++ b/__tests__/html/autoScroll.snap.activity.html @@ -0,0 +1,132 @@ + + + + + + + + +
+ + + diff --git a/__tests__/html/autoScroll.snap.activity.js b/__tests__/html/autoScroll.snap.activity.js new file mode 100644 index 0000000000..34e7b0485a --- /dev/null +++ b/__tests__/html/autoScroll.snap.activity.js @@ -0,0 +1,7 @@ +/** + * @jest-environment ./__tests__/html/__jest__/WebChatEnvironment.js + */ + +describe('Auto-scroll with "activity" snap behavior', () => { + test('should scroll correctly', () => runHTMLTest('autoScroll.snap.activity.html')); +}); diff --git a/__tests__/html/autoScroll.snap.activityAndPage.html b/__tests__/html/autoScroll.snap.activityAndPage.html new file mode 100644 index 0000000000..266ce61ce0 --- /dev/null +++ b/__tests__/html/autoScroll.snap.activityAndPage.html @@ -0,0 +1,145 @@ + + + + + + + + +
+ + + diff --git a/__tests__/html/autoScroll.snap.activityAndPage.js b/__tests__/html/autoScroll.snap.activityAndPage.js new file mode 100644 index 0000000000..5642fc3dd8 --- /dev/null +++ b/__tests__/html/autoScroll.snap.activityAndPage.js @@ -0,0 +1,7 @@ +/** + * @jest-environment ./__tests__/html/__jest__/WebChatEnvironment.js + */ + +describe('Auto-scroll with "activity" and "page" snap behavior', () => { + test('should scroll correctly', () => runHTMLTest('autoScroll.snap.activityAndPage.html')); +}); diff --git a/__tests__/html/autoScroll.snap.default.html b/__tests__/html/autoScroll.snap.default.html new file mode 100644 index 0000000000..38d61cd427 --- /dev/null +++ b/__tests__/html/autoScroll.snap.default.html @@ -0,0 +1,115 @@ + + + + + + + + +
+ + + diff --git a/__tests__/html/autoScroll.snap.default.js b/__tests__/html/autoScroll.snap.default.js new file mode 100644 index 0000000000..703d7f40b6 --- /dev/null +++ b/__tests__/html/autoScroll.snap.default.js @@ -0,0 +1,7 @@ +/** + * @jest-environment ./__tests__/html/__jest__/WebChatEnvironment.js + */ + +describe('Auto-scroll with "default" snap behavior', () => { + test('should scroll correctly', () => runHTMLTest('autoScroll.snap.default.html')); +}); diff --git a/__tests__/html/autoScroll.snap.page.html b/__tests__/html/autoScroll.snap.page.html new file mode 100644 index 0000000000..c8eb933f59 --- /dev/null +++ b/__tests__/html/autoScroll.snap.page.html @@ -0,0 +1,119 @@ + + + + + + + + +
+ + + diff --git a/__tests__/html/autoScroll.snap.page.js b/__tests__/html/autoScroll.snap.page.js new file mode 100644 index 0000000000..0900ca2582 --- /dev/null +++ b/__tests__/html/autoScroll.snap.page.js @@ -0,0 +1,7 @@ +/** + * @jest-environment ./__tests__/html/__jest__/WebChatEnvironment.js + */ + +describe('Auto-scroll with "page" snap behavior', () => { + test('should scroll correctly', () => runHTMLTest('autoScroll.snap.page.html')); +}); diff --git a/packages/api/src/defaultStyleOptions.js b/packages/api/src/defaultStyleOptions.js index bcf0ce5531..29a2f6f379 100644 --- a/packages/api/src/defaultStyleOptions.js +++ b/packages/api/src/defaultStyleOptions.js @@ -200,7 +200,13 @@ const DEFAULT_OPTIONS = { toastWarnColor: '#3B3A39', // Emoji - emojiSet: true // true || false || { ':)' : '😊'} + emojiSet: true, // true || false || { ':)' : '😊'} + + // Auto-scroll behavior + autoScrollSnapOnActivity: false, // true to pause scroll after 1 activity is received, specifying a number will pause after X number of activities + autoScrollSnapOnActivityOffset: 0, // Specify number of pixels to overscroll or underscroll after pause + autoScrollSnapOnPage: false, // true to pause scroll after activities filled the page, specifying a number (0 to 1) will pause after % of page is filled + autoScrollSnapOnPageoffset: 0 // Specify number of pixels to overscroll or underscroll after pause }; export default DEFAULT_OPTIONS; diff --git a/packages/component/package-lock.json b/packages/component/package-lock.json index 8178e66801..9b6e4fef4b 100644 --- a/packages/component/package-lock.json +++ b/packages/component/package-lock.json @@ -6279,22 +6279,15 @@ } }, "react-scroll-to-bottom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/react-scroll-to-bottom/-/react-scroll-to-bottom-4.0.0.tgz", - "integrity": "sha512-7lOy14XbBdweO+8LMRp7F9nP0xWtf0mAt+I5rm1hbNZq5JcXJRn0dsZjz9ySDLleH+zMlyhPwinqFDmEEUdHtA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/react-scroll-to-bottom/-/react-scroll-to-bottom-4.1.0.tgz", + "integrity": "sha512-atWRfdhLFCG2dK4kAsCDCYvl327DDEi5BMO0kIU4D12u2o2UX+GmlKO8m7sPW86Vb3MlqL3+Gawv/79VQ90tXQ==", "requires": { "classnames": "2.2.6", "create-emotion": "10.0.27", "math-random": "2.0.1", "prop-types": "15.7.2", "simple-update-in": "2.2.0" - }, - "dependencies": { - "math-random": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/math-random/-/math-random-2.0.1.tgz", - "integrity": "sha512-oIEbWiVDxDpl5tIF4S6zYS9JExhh3bun3uLb3YAinHPTlRtW4g1S66LtJrJ4Npq8dgIa8CLK5iPVah5n4n0s2w==" - } } }, "read-pkg": { diff --git a/packages/component/package.json b/packages/component/package.json index 92a59accc4..00aceb2274 100644 --- a/packages/component/package.json +++ b/packages/component/package.json @@ -62,7 +62,7 @@ "react-film": "3.0.0", "react-redux": "7.2.2", "react-say": "2.0.2-master.ee7cd76", - "react-scroll-to-bottom": "4.0.0", + "react-scroll-to-bottom": "4.1.0", "redux": "4.0.5", "remark": "10.0.1", "sanitize-html": "1.27.5", diff --git a/packages/component/src/BasicTranscript.js b/packages/component/src/BasicTranscript.js index 11a808d5b9..49c89ac3c4 100644 --- a/packages/component/src/BasicTranscript.js +++ b/packages/component/src/BasicTranscript.js @@ -1,7 +1,15 @@ /* eslint no-magic-numbers: ["error", { "ignore": [-1, 0, 1] }] */ import { hooks } from 'botframework-webchat-api'; -import { Panel as ScrollToBottomPanel, useAnimatingToEnd, useSticky } from 'react-scroll-to-bottom'; +import { + Composer as ReactScrollToBottomComposer, + Panel as ReactScrollToBottomPanel, + useAnimatingToEnd, + useObserveScrollPosition, + useScrollTo, + useScrollToEnd, + useSticky +} from 'react-scroll-to-bottom'; import classNames from 'classnames'; import PropTypes from 'prop-types'; import React, { useCallback, useMemo, useRef } from 'react'; @@ -16,12 +24,14 @@ import removeInline from './Utils/removeInline'; import ScreenReaderActivity from './ScreenReaderActivity'; import ScrollToEndButton from './Activity/ScrollToEndButton'; import SpeakActivity from './Activity/Speak'; +import useAcknowledgedActivity from './hooks/internal/useAcknowledgedActivity'; +import useDispatchScrollPosition from './hooks/internal/useDispatchScrollPosition'; import useFocus from './hooks/useFocus'; import useMemoize from './hooks/internal/useMemoize'; +import useRegisterScrollTo from './hooks/internal/useRegisterScrollTo'; +import useRegisterScrollToEnd from './hooks/internal/useRegisterScrollToEnd'; import useStyleSet from './hooks/useStyleSet'; import useStyleToEmotionObject from './hooks/internal/useStyleToEmotionObject'; -import useTranscriptActivityElementsRef from './hooks/internal/useTranscriptActivityElementsRef'; -import useTranscriptRootElementRef from './hooks/internal/useTranscriptRootElementRef'; const { useActivities, @@ -75,16 +85,15 @@ function validateAllActivitiesTagged(activities, bins) { return activities.every(activity => bins.some(bin => bin.includes(activity))); } -const BasicTranscript = ({ className }) => { +const InternalTranscript = ({ activityElementsRef, className }) => { const [{ activity: activityStyleSet }] = useStyleSet(); const [ { bubbleFromUserNubOffset, bubbleNubOffset, groupTimestamp, internalLiveRegionFadeAfter, showAvatarInGroup } ] = useStyleOptions(); const [activities] = useActivities(); - const [activityElementsRef] = useTranscriptActivityElementsRef(); const [direction] = useDirection(); - const [rootElementRef] = useTranscriptRootElementRef(); const rootClassName = useStyleToEmotionObject()(ROOT_STYLE) + ''; + const rootElementRef = useRef(); const createActivityRenderer = useCreateActivityRenderer(); const createActivityStatusRenderer = useCreateActivityStatusRenderer(); @@ -293,6 +302,7 @@ const BasicTranscript = ({ className }) => { renderActivity, renderActivityStatus, renderAvatar, + role, // TODO: [P2] #2858 We should use core/definitions/speakingActivity for this predicate instead shouldSpeak: activity.channelData && activity.channelData.speak, @@ -306,10 +316,11 @@ const BasicTranscript = ({ className }) => { // Update activityElementRef with new sets of activity, while retaining the existing referencing element if exists. - activityElementsRef.current = renderingElements.map(({ activity: { id }, key }) => { + activityElementsRef.current = renderingElements.map(({ activity, activity: { id }, key }) => { const existingEntry = activityElements.find(entry => entry.key === key); return { + activity, activityID: id, element: existingEntry && existingEntry.element, key @@ -331,6 +342,92 @@ const BasicTranscript = ({ className }) => { const renderingActivities = useMemo(() => renderingElements.map(({ activity }) => activity), [renderingElements]); + const scrollToBottomScrollTo = useScrollTo(); + const scrollToBottomScrollToEnd = useScrollToEnd(); + + const scrollTo = useCallback( + (position, { behavior = 'auto' } = {}) => { + if (!position) { + throw new Error( + 'botframework-webchat: First argument passed to "useScrollTo" must be a ScrollPosition object.' + ); + } + + const { activityID, scrollTop } = position; + + if (typeof scrollTop !== 'undefined') { + scrollToBottomScrollTo(scrollTop, { behavior }); + } else if (typeof activityID !== 'undefined') { + const { current: rootElement } = rootElementRef; + const { element: activityElement } = + activityElementsRef.current.find(entry => entry.activityID === activityID) || {}; + + const scrollableElement = rootElement.querySelector('.webchat__basic-transcript__scrollable'); + + if (scrollableElement && activityElement) { + const [{ height: activityElementHeight, y: activityElementY }] = activityElement.getClientRects(); + const [{ height: scrollableHeight }] = scrollableElement.getClientRects(); + + const activityElementOffsetTop = activityElementY + scrollableElement.scrollTop; + + const scrollTop = Math.min( + activityElementOffsetTop, + activityElementOffsetTop - scrollableHeight + activityElementHeight + ); + + scrollToBottomScrollTo(scrollTop, { behavior }); + } + } + }, + [activityElementsRef, rootElementRef, scrollToBottomScrollTo] + ); + + useRegisterScrollTo(scrollTo); + useRegisterScrollToEnd(scrollToBottomScrollToEnd); + + const dispatchScrollPosition = useDispatchScrollPosition(); + const patchedDispatchScrollPosition = useMemo(() => { + if (!dispatchScrollPosition) { + return; + } + + return ({ scrollTop }) => { + const { current: rootElement } = rootElementRef; + + if (!rootElement) { + return; + } + + const scrollableElement = rootElement.querySelector('.webchat__basic-transcript__scrollable'); + + const [{ height: offsetHeight } = {}] = scrollableElement.getClientRects(); + + // Find the activity just above scroll view bottom. + // If the scroll view is already on top, get the first activity. + const entry = scrollableElement.scrollTop + ? [...activityElementsRef.current].reverse().find(({ element }) => { + if (!element) { + return false; + } + + const [{ y } = {}] = element.getClientRects(); + + return y < offsetHeight; + }) + : activityElementsRef.current[0]; + + const { activityID } = entry || {}; + + dispatchScrollPosition({ ...(activityID ? { activityID } : {}), scrollTop }); + }; + }, [activityElementsRef, dispatchScrollPosition, rootElementRef]); + + useObserveScrollPosition(patchedDispatchScrollPosition); + + const [lastInteractedActivity] = useAcknowledgedActivity(); + + const indexOfLastInteractedActivity = activities.indexOf(lastInteractedActivity); + return (
{ {renderingElements.map( - ({ - activity, - callbackRef, - key, - hideTimestamp, - renderActivity, - renderActivityStatus, - renderAvatar, - shouldSpeak, - showCallout - }) => ( + ( + { + activity, + callbackRef, + key, + hideTimestamp, + renderActivity, + renderActivityStatus, + renderAvatar, + role, + shouldSpeak, + showCallout + }, + index + ) => (
  • @@ -385,11 +490,14 @@ const BasicTranscript = ({ className }) => { ); }; -BasicTranscript.defaultProps = { +InternalTranscript.defaultProps = { className: '' }; -BasicTranscript.propTypes = { +InternalTranscript.propTypes = { + activityElementsRef: PropTypes.shape({ + current: PropTypes.array.isRequired + }).isRequired, className: PropTypes.string }; @@ -495,7 +603,7 @@ const InternalTranscriptScrollable = ({ activities, children }) => { }, [activities, allActivitiesRead, animatingToEnd, hideScrollToEndButton, lastReadActivityIdRef, sticky]); return ( - +
      { ))}
    - + ); }; @@ -527,4 +635,103 @@ InternalTranscriptScrollable.propTypes = { children: PropTypes.arrayOf(PropTypes.element).isRequired }; +const BasicTranscript = ({ className }) => { + const [ + { autoScrollSnapOnActivity, autoScrollSnapOnActivityOffset, autoScrollSnapOnPage, autoScrollSnapOnPageOffset } + ] = useStyleOptions(); + const [lastAcknowledgedActivity] = useAcknowledgedActivity(); + const activityElementsRef = useRef([]); + + const lastAcknowledgedActivityRef = useRef(lastAcknowledgedActivity); + + lastAcknowledgedActivityRef.current = lastAcknowledgedActivity; + + const scroller = useCallback( + ({ offsetHeight, scrollTop }) => { + const patchedAutoScrollSnapOnActivity = + typeof autoScrollSnapOnActivity === 'number' + ? Math.max(0, autoScrollSnapOnActivity) + : autoScrollSnapOnActivity + ? 1 + : 0; + const patchedAutoScrollSnapOnPage = + typeof autoScrollSnapOnPage === 'number' + ? Math.max(0, Math.min(1, autoScrollSnapOnPage)) + : autoScrollSnapOnPage + ? 1 + : 0; + const patchedAutoScrollSnapOnActivityOffset = + typeof autoScrollSnapOnActivityOffset === 'number' ? autoScrollSnapOnActivityOffset : 0; + const patchedAutoScrollSnapOnPageOffset = + typeof autoScrollSnapOnPageOffset === 'number' ? autoScrollSnapOnPageOffset : 0; + + if (patchedAutoScrollSnapOnActivity || patchedAutoScrollSnapOnPage) { + const { current: lastAcknowledgedActivity } = lastAcknowledgedActivityRef; + + const values = []; + + if (patchedAutoScrollSnapOnActivity) { + const { element: nthUnacknowledgedActivityElement } = + activityElementsRef.current[ + activityElementsRef.current.findIndex(({ activity }) => activity === lastAcknowledgedActivity) + + patchedAutoScrollSnapOnActivity + ] || {}; + + if (nthUnacknowledgedActivityElement) { + values.push( + nthUnacknowledgedActivityElement.offsetTop + + nthUnacknowledgedActivityElement.offsetHeight - + offsetHeight - + scrollTop + + patchedAutoScrollSnapOnActivityOffset + ); + } + } + + if (patchedAutoScrollSnapOnPage) { + const { element: firstUnacknowledgedActivityElement } = + activityElementsRef.current[ + activityElementsRef.current.findIndex(({ activity }) => activity === lastAcknowledgedActivity) + 1 + ] || {}; + + if (firstUnacknowledgedActivityElement) { + values.push( + firstUnacknowledgedActivityElement.offsetTop - + scrollTop - + offsetHeight * (1 - patchedAutoScrollSnapOnPage) + + patchedAutoScrollSnapOnPageOffset + ); + } + } + + return values.reduce((minValue, value) => Math.min(minValue, value), Infinity); + } else { + return Infinity; + } + }, + [ + activityElementsRef, + autoScrollSnapOnActivity, + autoScrollSnapOnActivityOffset, + autoScrollSnapOnPage, + autoScrollSnapOnPageOffset, + lastAcknowledgedActivityRef + ] + ); + + return ( + + + + ); +}; + +BasicTranscript.defaultProps = { + className: '' +}; + +BasicTranscript.propTypes = { + className: PropTypes.string +}; + export default BasicTranscript; diff --git a/packages/component/src/Composer.js b/packages/component/src/Composer.js index 5368f0693d..df24451ab0 100644 --- a/packages/component/src/Composer.js +++ b/packages/component/src/Composer.js @@ -1,6 +1,5 @@ import { Composer as APIComposer, hooks } from 'botframework-webchat-api'; import { Composer as SayComposer } from 'react-say'; -import { Composer as ScrollToBottomComposer } from 'react-scroll-to-bottom'; import createEmotion from 'create-emotion'; import createStyleSet from './Styles/createStyleSet'; import MarkdownIt from 'markdown-it'; @@ -79,9 +78,9 @@ const ComposerCore = ({ const [styleOptions] = useStyleOptions(); const internalMarkdownIt = useMemo(() => new MarkdownIt(), []); const sendBoxFocusRef = useRef(); - const transcriptActivityElementsRef = useRef([]); const transcriptFocusRef = useRef(); - const transcriptRootElementRef = useRef(); + const scrollToCallbacksRef = useRef([]); + const scrollToEndCallbacksRef = useRef([]); const dictationOnError = useCallback(err => { console.error(err); @@ -134,52 +133,77 @@ const ComposerCore = ({ }; }, [referenceGrammarID, webSpeechPonyfillFactory]); + const scrollPositionObserversRef = useRef([]); + const [numScrollPositionObservers, setNumScrollPositionObservers] = useState(0); + + const dispatchScrollPosition = useCallback( + event => scrollPositionObserversRef.current.forEach(observer => observer(event)), + [scrollPositionObserversRef] + ); + + const observeScrollPosition = useCallback( + observer => { + scrollPositionObserversRef.current = [...scrollPositionObserversRef.current, observer]; + setNumScrollPositionObservers(scrollPositionObserversRef.current.length); + + return () => { + scrollPositionObserversRef.current = scrollPositionObserversRef.current.filter(target => target !== observer); + setNumScrollPositionObservers(scrollPositionObserversRef.current.length); + }; + }, + [scrollPositionObserversRef, setNumScrollPositionObservers] + ); + const context = useMemo( () => ({ ...focusContext, dictateAbortable, + dispatchScrollPosition, internalMarkdownItState: [internalMarkdownIt], internalRenderMarkdownInline, nonce, + numScrollPositionObservers, + observeScrollPosition, renderMarkdown, + scrollToCallbacksRef, + scrollToEndCallbacksRef, sendBoxFocusRef, setDictateAbortable, styleSet: patchedStyleSet, styleToEmotionObject, suggestedActionsAccessKey, - transcriptActivityElementsRef, transcriptFocusRef, - transcriptRootElementRef, webSpeechPonyfill }), [ dictateAbortable, + dispatchScrollPosition, focusContext, internalMarkdownIt, internalRenderMarkdownInline, nonce, + numScrollPositionObservers, + observeScrollPosition, patchedStyleSet, renderMarkdown, + scrollToCallbacksRef, + scrollToEndCallbacksRef, sendBoxFocusRef, setDictateAbortable, styleToEmotionObject, suggestedActionsAccessKey, - transcriptActivityElementsRef, transcriptFocusRef, - transcriptRootElementRef, webSpeechPonyfill ] ); return ( - - - - {children} - - - - + + + {children} + + + ); }; @@ -279,19 +303,17 @@ const Composer = ({ typingIndicatorMiddleware={patchedTypingIndicatorMiddleware} {...composerProps} > - - - {children} - {onTelemetry && } - - + + {children} + {onTelemetry && } + ); diff --git a/packages/component/src/Utils/findLastIndex.js b/packages/component/src/Utils/findLastIndex.js new file mode 100644 index 0000000000..173e050d06 --- /dev/null +++ b/packages/component/src/Utils/findLastIndex.js @@ -0,0 +1,11 @@ +export default function findLastIndex(array, predicate) { + const index = [...array].reverse().findIndex(predicate); + + if (~index) { + const { length } = array || []; + + return length - index - 1; + } + + return index; +} diff --git a/packages/component/src/Utils/findLastIndex.spec.js b/packages/component/src/Utils/findLastIndex.spec.js new file mode 100644 index 0000000000..a2ac068736 --- /dev/null +++ b/packages/component/src/Utils/findLastIndex.spec.js @@ -0,0 +1,29 @@ +import findLastIndex from './findLastIndex'; + +describe('find last index', () => { + test('of an existing element should return the index of last occurrence', () => { + const actual = findLastIndex([1, 2, 3, 2, 1], value => value === 2); + + expect(actual).toBe(3); + }); + + test('of a non-existing element should return -1', () => { + const actual = findLastIndex([1, 2, 3, 2, 1], value => value === 4); + + expect(actual).toBe(-1); + }); + + test('of an empty array should return -1', () => { + const actual = findLastIndex([], value => value === 1); + + expect(actual).toBe(-1); + }); + + test('without a predicate should throw', () => { + expect(() => findLastIndex([])).toThrowError('not a function'); + }); + + test('without an array should throw', () => { + expect(() => findLastIndex(undefined, value => value === 1)).toThrowError(); + }); +}); diff --git a/packages/component/src/hooks/internal/useAcknowledgedActivity.js b/packages/component/src/hooks/internal/useAcknowledgedActivity.js new file mode 100644 index 0000000000..29b9e06b63 --- /dev/null +++ b/packages/component/src/hooks/internal/useAcknowledgedActivity.js @@ -0,0 +1,61 @@ +import { hooks } from 'botframework-webchat-api'; +import { useMemo, useRef } from 'react'; +import { useSticky } from 'react-scroll-to-bottom'; + +import findLastIndex from '../../Utils/findLastIndex'; +import getActivityUniqueId from '../../Utils/getActivityUniqueId'; +import useChanged from './useChanged'; + +const { useActivities } = hooks; + +// Acknowledged means either: +// 1. The user sent a message +// - We don't need a condition here. When Web Chat send the message, it will scroll to bottom, and it will trigger condition 2 below. +// 2. At the bottom of the transcript, scrolled from a non-bottom scroll position +// - If the transcript is already at the bottom, the user need to scroll up and then go back down +// - What happen if we are relaxing "scrolled from a non-bottom scroll position": +// 1. The condition will become solely "at the bottom of the transcript" +// 2. Auto-scroll will always scroll the transcript to the bottom +// 3. Web Chat will always acknowledge all activities as it is at the bottom +// 4. Acknowledge flag become useless + +// Note: When Web Chat is loaded, there are no activities acknowledged, we need to assume all arriving activities are acknowledged until end-user sent their first activity. +// Activities loaded initially could be from conversation history. Without assuming acknowledgement, Web Chat will not scroll initially (as everything is not acknowledged). +// Better, the chat adapter should let Web Chat know if the activity is loaded from history or not. + +// TODO: [P2] Move the "conversation history acknowledgement" logic mentioned above to polyfill of chat adapters. +// 1. Chat adapter should send "acknowledged" as part of "channelData" +// 2. If "acknowledged" is "undefined", we set it to: +// a. true, if there are no egress activities yet +// b. Otherwise, false +export default function useAcknowledgedActivity() { + const [activities] = useActivities(); + const [sticky] = useSticky(); + const lastStickyActivityIDRef = useRef(); + + const stickyChanged = useChanged(sticky); + const stickyChangedToSticky = stickyChanged && sticky; + + const lastStickyActivityID = useMemo(() => { + if (stickyChangedToSticky) { + lastStickyActivityIDRef.current = getActivityUniqueId(activities[activities.length - 1] || {}); + } + }, [activities, lastStickyActivityIDRef, stickyChangedToSticky]); + + return useMemo(() => { + const lastStickyActivityIndex = activities.findIndex( + activity => getActivityUniqueId(activity) === lastStickyActivityID + ); + + const lastEgressActivityIndex = findLastIndex(activities, ({ from: { role } = {} }) => role === 'user'); + + // As described above, if no activities were acknowledged thru egress activity, we will assume everything is acknowledged. + const lastAcknowledgedActivityIndex = !~lastEgressActivityIndex + ? activities.length - 1 + : Math.max(lastStickyActivityIndex, lastEgressActivityIndex); + + const lastAcknowledgedActivity = activities[lastAcknowledgedActivityIndex]; + + return [lastAcknowledgedActivity]; + }, [activities, lastStickyActivityID, stickyChangedToSticky]); +} diff --git a/packages/component/src/hooks/internal/useChanged.js b/packages/component/src/hooks/internal/useChanged.js new file mode 100644 index 0000000000..6b88476ab8 --- /dev/null +++ b/packages/component/src/hooks/internal/useChanged.js @@ -0,0 +1,10 @@ +import { useRef } from 'react'; + +export default function useChanged(value) { + const prevValueRef = useRef(value); + const changed = value !== prevValueRef.current; + + prevValueRef.current = value; + + return changed; +} diff --git a/packages/component/src/hooks/internal/useDispatchScrollPosition.js b/packages/component/src/hooks/internal/useDispatchScrollPosition.js new file mode 100644 index 0000000000..3cbb53fc93 --- /dev/null +++ b/packages/component/src/hooks/internal/useDispatchScrollPosition.js @@ -0,0 +1,7 @@ +import useWebChatUIContext from './useWebChatUIContext'; + +export default function useDispatchScrollPosition() { + const { dispatchScrollPosition, numScrollPositionObservers } = useWebChatUIContext(); + + return numScrollPositionObservers ? dispatchScrollPosition : undefined; +} diff --git a/packages/component/src/hooks/internal/useGetTranscriptActivityElementByID.js b/packages/component/src/hooks/internal/useGetTranscriptActivityElementByID.js deleted file mode 100644 index ed2bdfd92f..0000000000 --- a/packages/component/src/hooks/internal/useGetTranscriptActivityElementByID.js +++ /dev/null @@ -1,16 +0,0 @@ -import { useCallback } from 'react'; - -import useTranscriptActivityElementsRef from './useTranscriptActivityElementsRef'; - -export default function useGetTranscriptActivityElementByID() { - const [activityElementsRef] = useTranscriptActivityElementsRef(); - - return useCallback( - activityID => { - const { element } = activityElementsRef.current.find(entry => entry.activityID === activityID) || {}; - - return element; - }, - [activityElementsRef] - ); -} diff --git a/packages/component/src/hooks/internal/useGetTranscriptScrollableElement.js b/packages/component/src/hooks/internal/useGetTranscriptScrollableElement.js deleted file mode 100644 index 1c140aee76..0000000000 --- a/packages/component/src/hooks/internal/useGetTranscriptScrollableElement.js +++ /dev/null @@ -1,11 +0,0 @@ -import { useCallback } from 'react'; - -import useTranscriptRootElementRef from './useTranscriptRootElementRef'; - -export default function useGetTranscriptScrollableElement() { - const [rootElementRef] = useTranscriptRootElementRef(); - - return useCallback(() => rootElementRef.current.querySelector('.webchat__basic-transcript__scrollable'), [ - rootElementRef - ]); -} diff --git a/packages/component/src/hooks/internal/useRegisterScrollTo.js b/packages/component/src/hooks/internal/useRegisterScrollTo.js new file mode 100644 index 0000000000..5e8102fe9b --- /dev/null +++ b/packages/component/src/hooks/internal/useRegisterScrollTo.js @@ -0,0 +1,18 @@ +import { useEffect } from 'react'; + +import removeInline from '../../Utils/removeInline'; +import useWebChatUIContext from './useWebChatUIContext'; + +export default function useRegisterScrollTo(callback) { + const { scrollToCallbacksRef } = useWebChatUIContext(); + + useEffect(() => { + if (callback) { + const { current: scrollToCallbacks } = scrollToCallbacksRef; + + scrollToCallbacks.push(callback); + + return () => removeInline(scrollToCallbacks, callback); + } + }, [callback, scrollToCallbacksRef]); +} diff --git a/packages/component/src/hooks/internal/useRegisterScrollToEnd.js b/packages/component/src/hooks/internal/useRegisterScrollToEnd.js new file mode 100644 index 0000000000..4033ecf856 --- /dev/null +++ b/packages/component/src/hooks/internal/useRegisterScrollToEnd.js @@ -0,0 +1,16 @@ +import { useEffect } from 'react'; + +import removeInline from '../../Utils/removeInline'; +import useWebChatUIContext from './useWebChatUIContext'; + +export default function useRegisterScrollTo(callback) { + const { scrollToEndCallbacksRef } = useWebChatUIContext(); + + useEffect(() => { + const { current: scrollToEndCallbacks } = scrollToEndCallbacksRef; + + scrollToEndCallbacks.push(callback); + + return () => removeInline(scrollToEndCallbacks, callback); + }, [scrollToEndCallbacksRef]); +} diff --git a/packages/component/src/hooks/internal/useTranscriptRootElementRef.js b/packages/component/src/hooks/internal/useTranscriptRootElementRef.js deleted file mode 100644 index 828d9dc2d3..0000000000 --- a/packages/component/src/hooks/internal/useTranscriptRootElementRef.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './useWebChatUIContext'; - -export default function useTranscriptRootElementRef() { - return [useWebChatUIContext().transcriptRootElementRef]; -} diff --git a/packages/component/src/hooks/useObserveScrollPosition.js b/packages/component/src/hooks/useObserveScrollPosition.js index 9ecd586652..609cd6ef1c 100644 --- a/packages/component/src/hooks/useObserveScrollPosition.js +++ b/packages/component/src/hooks/useObserveScrollPosition.js @@ -1,13 +1,7 @@ -import { useCallback } from 'react'; -import { useObserveScrollPosition as useScrollToBottomObserveScrollPosition } from 'react-scroll-to-bottom'; - -import useGetTranscriptScrollableElement from './internal/useGetTranscriptScrollableElement'; -import useTranscriptActivityElementsRef from './internal/useTranscriptActivityElementsRef'; +import { useEffect } from 'react'; +import useWebChatUIContext from './internal/useWebChatUIContext'; export default function useObserveScrollPosition(observer, deps) { - const getTranscriptScrollableElement = useGetTranscriptScrollableElement(); - const [activityElementsRef] = useTranscriptActivityElementsRef(); - if (typeof observer !== 'function') { observer = undefined; console.warn('botframework-webchat: First argument passed to "useObserveScrollPosition" must be a function.'); @@ -17,34 +11,8 @@ export default function useObserveScrollPosition(observer, deps) { ); } - const effectCallback = useCallback( - ({ scrollTop }) => { - const scrollable = getTranscriptScrollableElement(); - const [{ height: offsetHeight } = {}] = scrollable.getClientRects(); - - // Find the activity just above scroll view bottom. - // If the scroll view is already on top, get the first activity. - const entry = scrollable.scrollTop - ? [...activityElementsRef.current].reverse().find(({ element }) => { - if (!element) { - return false; - } - - const [{ y } = {}] = element.getClientRects(); - - return y < offsetHeight; - }) - : activityElementsRef.current[0]; - - const { activityID } = entry || {}; - - observer && observer({ ...(activityID ? { activityID } : {}), scrollTop }); - }, - // This hook is very similar to useEffect, which internally use useCallback. - // The "deps" is treated as the dependencies for the useCallback. - /* eslint-disable-next-line react-hooks/exhaustive-deps */ - [activityElementsRef, getTranscriptScrollableElement, ...(deps || [])] - ); + const { observeScrollPosition } = useWebChatUIContext(); - useScrollToBottomObserveScrollPosition(effectCallback); + /* eslint-disable-next-line react-hooks/exhaustive-deps */ + useEffect(() => observer && observeScrollPosition(observer), [...(deps || []), observer, observeScrollPosition]); } diff --git a/packages/component/src/hooks/useScrollTo.js b/packages/component/src/hooks/useScrollTo.js index e2261893b7..8f7dc5f46e 100644 --- a/packages/component/src/hooks/useScrollTo.js +++ b/packages/component/src/hooks/useScrollTo.js @@ -1,45 +1,11 @@ import { useCallback } from 'react'; -import { useScrollTo as useScrollToBottomScrollTo } from 'react-scroll-to-bottom'; -import useGetTranscriptScrollableElement from './internal/useGetTranscriptScrollableElement'; -import useGetTranscriptActivityElementByID from './internal/useGetTranscriptActivityElementByID'; +import useWebChatUIContext from './internal/useWebChatUIContext'; export default function useScrollTo() { - const getActivityElementByID = useGetTranscriptActivityElementByID(); - const getScrollableElement = useGetTranscriptScrollableElement(); - const scrollTo = useScrollToBottomScrollTo(); + const { scrollToCallbacksRef } = useWebChatUIContext(); - return useCallback( - (position, { behavior = 'auto' } = {}) => { - if (!position) { - throw new Error( - 'botframework-webchat: First argument passed to "useScrollTo" must be a ScrollPosition object.' - ); - } - - const { activityID, scrollTop } = position; - - if (typeof scrollTop !== 'undefined') { - scrollTo(scrollTop, { behavior }); - } else if (typeof activityID !== 'undefined') { - const activityElement = getActivityElementByID(activityID); - - if (activityElement) { - const scrollableElement = getScrollableElement(); - const [{ height: activityElementHeight, y: activityElementY }] = activityElement.getClientRects(); - const [{ height: scrollableHeight }] = scrollableElement.getClientRects(); - - const activityElementOffsetTop = activityElementY + scrollableElement.scrollTop; - - const scrollTop = Math.min( - activityElementOffsetTop, - activityElementOffsetTop - scrollableHeight + activityElementHeight - ); - - scrollTo(scrollTop, { behavior }); - } - } - }, - [getActivityElementByID, getScrollableElement, scrollTo] - ); + return useCallback((...args) => scrollToCallbacksRef.current.forEach(callback => callback(...args)), [ + scrollToCallbacksRef + ]); } diff --git a/packages/component/src/hooks/useScrollToEnd.js b/packages/component/src/hooks/useScrollToEnd.js index 250ec50906..54c147eb9a 100644 --- a/packages/component/src/hooks/useScrollToEnd.js +++ b/packages/component/src/hooks/useScrollToEnd.js @@ -1,9 +1,11 @@ import { useCallback } from 'react'; -import { useScrollToEnd as useScrollToBottomScrollToEnd } from 'react-scroll-to-bottom'; +import useWebChatUIContext from './internal/useWebChatUIContext'; export default function useScrollToEnd() { - const scrollToEnd = useScrollToBottomScrollToEnd(); + const { scrollToEndCallbacksRef } = useWebChatUIContext(); - return useCallback(() => scrollToEnd({ behavior: 'smooth' }), [scrollToEnd]); + return useCallback(() => scrollToEndCallbacksRef.current.forEach(callback => callback({ behavior: 'smooth' })), [ + scrollToEndCallbacksRef + ]); } diff --git a/packages/testharness/src/utils/createDirectLineWithTranscript.js b/packages/testharness/src/utils/createDirectLineWithTranscript.js index 3215bd7914..1430500a53 100644 --- a/packages/testharness/src/utils/createDirectLineWithTranscript.js +++ b/packages/testharness/src/utils/createDirectLineWithTranscript.js @@ -1,3 +1,5 @@ +import Observable from 'core-js/features/observable'; + import createDeferredObservable from './createDeferredObservable'; import loadTranscriptAsset from './loadTranscriptAsset'; import shareObservable from './shareObservable'; @@ -23,7 +25,7 @@ function updateRelativeTimestamp(now, activity) { }; } -export default function createDirectLineWithTranscript(activitiesOrFilename) { +export default function createDirectLineWithTranscript(activitiesOrFilename, { echo = true } = {}) { const now = Date.now(); const patchActivity = updateRelativeTimestamp.bind(null, now); const connectionStatusDeferredObservable = createDeferredObservable(() => { @@ -31,7 +33,7 @@ export default function createDirectLineWithTranscript(activitiesOrFilename) { }); const activityDeferredObservable = createDeferredObservable(() => { - (async function() { + (async function () { connectionStatusDeferredObservable.next(1); connectionStatusDeferredObservable.next(2); @@ -58,6 +60,19 @@ export default function createDirectLineWithTranscript(activitiesOrFilename) { connectionStatus$: shareObservable(connectionStatusDeferredObservable.observable), connectionStatusDeferredObservable, end: () => {}, - postActivity: () => {} + postActivity: activity => { + const id = Math.random().toString(36).substr(2, 5); + + if (echo) { + activityDeferredObservable.next( + patchActivity({ + ...activity, + id + }) + ); + } + + return Observable.from([id]); + } }; } From 39bf5421cca8ca2bdc488bf7a8e6ee8e0f943f24 Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 4 Jan 2021 13:01:24 -0800 Subject: [PATCH 2/9] Update PR number --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7df24785e8..ef5f1c680f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,11 +25,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - Resolves [#2745](https://github.com/microsoft/BotFramework-WebChat/issues/2745). Added new `inline` layout to suggested actions, by [@compulim](https://github.com/compulim) in PR [#3641](https://github.com/microsoft/BotFramework-WebChat/pull/3641) -- Added new style options to customize auto-scroll, by [@compulim](https://github.com/compulim) in PR [#XXX](https://github.com/microsoft/BotFramework-WebChat/pull/XXX) +- Added new style options to customize auto-scroll, by [@compulim](https://github.com/compulim) in PR [#3653](https://github.com/microsoft/BotFramework-WebChat/pull/3653) - Set `autoScrollSnapOnActivity` to `true` to pause auto-scroll after more than one activity is shown, or a number to pause after X number of activities - Set `autoScrollSnapOnPage` to `true` to pause auto-scroll when a page is filled, or a number between `0` and `1` to pause after % of page is filled - Set `autoScrollSnapOnActivityOffset` and `autoScrollSnapOnPageOffset` to a number (in pixels) to overscroll/underscroll after the pause -- Supports multiple transcripts in a single composition, by [@compulim](https://github.com/compulim) in PR [#XXX](https://github.com/microsoft/BotFramework-WebChat/pull/XXX) +- Supports multiple transcripts in a single composition, by [@compulim](https://github.com/compulim) in PR [#3653](https://github.com/microsoft/BotFramework-WebChat/pull/3653) ### Fixed From 162d16a414241a32bfa22aeb28463599e8ecbc28 Mon Sep 17 00:00:00 2001 From: William Wong Date: Fri, 15 Jan 2021 11:46:38 -0800 Subject: [PATCH 3/9] Apply PR suggestions --- .../html/autoScroll.acknowledgement.html | 207 +++++++++--------- __tests__/html/autoScroll.snap.activity.html | 1 - .../html/autoScroll.snap.activityAndPage.html | 1 - __tests__/html/autoScroll.snap.default.html | 1 - __tests__/html/autoScroll.snap.page.html | 1 - .../hooks/internal/useAcknowledgedActivity.js | 2 +- .../utils/createDirectLineWithTranscript.js | 16 +- 7 files changed, 111 insertions(+), 118 deletions(-) diff --git a/__tests__/html/autoScroll.acknowledgement.html b/__tests__/html/autoScroll.acknowledgement.html index ac53b6841d..2da7d18669 100644 --- a/__tests__/html/autoScroll.acknowledgement.html +++ b/__tests__/html/autoScroll.acknowledgement.html @@ -28,145 +28,144 @@
    diff --git a/__tests__/html/autoScroll.snap.activity.html b/__tests__/html/autoScroll.snap.activity.html index a1ab8edcd2..1e54229d8c 100644 --- a/__tests__/html/autoScroll.snap.activity.html +++ b/__tests__/html/autoScroll.snap.activity.html @@ -36,7 +36,6 @@ const directLine = createDirectLineWithTranscript([createActivity(20)]); const store = createStore(); - let numActivityCreated = 0; let now = +new Date(2020, 0, 23, 12, 34); function createActivity(numLines) { diff --git a/__tests__/html/autoScroll.snap.activityAndPage.html b/__tests__/html/autoScroll.snap.activityAndPage.html index 266ce61ce0..baa15a12b0 100644 --- a/__tests__/html/autoScroll.snap.activityAndPage.html +++ b/__tests__/html/autoScroll.snap.activityAndPage.html @@ -36,7 +36,6 @@ const directLine = createDirectLineWithTranscript([createActivity(20)]); const store = createStore(); - let numActivityCreated = 0; let now = +new Date(2020, 0, 23, 12, 34); function createActivity(numLines) { diff --git a/__tests__/html/autoScroll.snap.default.html b/__tests__/html/autoScroll.snap.default.html index 38d61cd427..cf648f2ad5 100644 --- a/__tests__/html/autoScroll.snap.default.html +++ b/__tests__/html/autoScroll.snap.default.html @@ -36,7 +36,6 @@ const directLine = createDirectLineWithTranscript([createActivity(20)]); const store = createStore(); - let numActivityCreated = 0; let now = +new Date(2020, 0, 23, 12, 34); function createActivity(numLines) { diff --git a/__tests__/html/autoScroll.snap.page.html b/__tests__/html/autoScroll.snap.page.html index c8eb933f59..fb887307f6 100644 --- a/__tests__/html/autoScroll.snap.page.html +++ b/__tests__/html/autoScroll.snap.page.html @@ -36,7 +36,6 @@ const directLine = createDirectLineWithTranscript([createActivity(20)]); const store = createStore(); - let numActivityCreated = 0; let now = +new Date(2020, 0, 23, 12, 34); function createActivity(numLines) { diff --git a/packages/component/src/hooks/internal/useAcknowledgedActivity.js b/packages/component/src/hooks/internal/useAcknowledgedActivity.js index 29b9e06b63..5133487270 100644 --- a/packages/component/src/hooks/internal/useAcknowledgedActivity.js +++ b/packages/component/src/hooks/internal/useAcknowledgedActivity.js @@ -57,5 +57,5 @@ export default function useAcknowledgedActivity() { const lastAcknowledgedActivity = activities[lastAcknowledgedActivityIndex]; return [lastAcknowledgedActivity]; - }, [activities, lastStickyActivityID, stickyChangedToSticky]); + }, [activities, lastStickyActivityID]); } diff --git a/packages/testharness/src/utils/createDirectLineWithTranscript.js b/packages/testharness/src/utils/createDirectLineWithTranscript.js index 1430500a53..98685ac602 100644 --- a/packages/testharness/src/utils/createDirectLineWithTranscript.js +++ b/packages/testharness/src/utils/createDirectLineWithTranscript.js @@ -25,7 +25,7 @@ function updateRelativeTimestamp(now, activity) { }; } -export default function createDirectLineWithTranscript(activitiesOrFilename, { echo = true } = {}) { +export default function createDirectLineWithTranscript(activitiesOrFilename) { const now = Date.now(); const patchActivity = updateRelativeTimestamp.bind(null, now); const connectionStatusDeferredObservable = createDeferredObservable(() => { @@ -63,14 +63,12 @@ export default function createDirectLineWithTranscript(activitiesOrFilename, { e postActivity: activity => { const id = Math.random().toString(36).substr(2, 5); - if (echo) { - activityDeferredObservable.next( - patchActivity({ - ...activity, - id - }) - ); - } + activityDeferredObservable.next( + patchActivity({ + ...activity, + id + }) + ); return Observable.from([id]); } From 8a36838e9272502cc2a61e0da7352b06d60c3b9a Mon Sep 17 00:00:00 2001 From: William Wong Date: Fri, 15 Jan 2021 11:46:50 -0800 Subject: [PATCH 4/9] Apply suggestions from code review Co-authored-by: Corina <14900841+corinagum@users.noreply.github.com> --- packages/api/src/defaultStyleOptions.js | 4 ++-- .../src/hooks/internal/useAcknowledgedActivity.js | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/api/src/defaultStyleOptions.js b/packages/api/src/defaultStyleOptions.js index 29a2f6f379..8c63a40b0e 100644 --- a/packages/api/src/defaultStyleOptions.js +++ b/packages/api/src/defaultStyleOptions.js @@ -203,9 +203,9 @@ const DEFAULT_OPTIONS = { emojiSet: true, // true || false || { ':)' : '😊'} // Auto-scroll behavior - autoScrollSnapOnActivity: false, // true to pause scroll after 1 activity is received, specifying a number will pause after X number of activities + autoScrollSnapOnActivity: false, // true will pause scroll after 1 activity is received. Specifying a number will pause after X number of activities autoScrollSnapOnActivityOffset: 0, // Specify number of pixels to overscroll or underscroll after pause - autoScrollSnapOnPage: false, // true to pause scroll after activities filled the page, specifying a number (0 to 1) will pause after % of page is filled + autoScrollSnapOnPage: false, // true will pause scroll after activities filled the page. Specifying a number (0 to 1) will pause after % of page is filled autoScrollSnapOnPageoffset: 0 // Specify number of pixels to overscroll or underscroll after pause }; diff --git a/packages/component/src/hooks/internal/useAcknowledgedActivity.js b/packages/component/src/hooks/internal/useAcknowledgedActivity.js index 29b9e06b63..49561fbc2e 100644 --- a/packages/component/src/hooks/internal/useAcknowledgedActivity.js +++ b/packages/component/src/hooks/internal/useAcknowledgedActivity.js @@ -10,18 +10,18 @@ const { useActivities } = hooks; // Acknowledged means either: // 1. The user sent a message -// - We don't need a condition here. When Web Chat send the message, it will scroll to bottom, and it will trigger condition 2 below. +// - We don't need a condition here. When Web Chat sends the user's message, it will scroll to bottom, and it will trigger condition 2 below. // 2. At the bottom of the transcript, scrolled from a non-bottom scroll position -// - If the transcript is already at the bottom, the user need to scroll up and then go back down -// - What happen if we are relaxing "scrolled from a non-bottom scroll position": +// - If the transcript is already at the bottom, the user needs to scroll up and then go back down +// - What happens if we are relaxing "scrolled from a non-bottom scroll position": // 1. The condition will become solely "at the bottom of the transcript" // 2. Auto-scroll will always scroll the transcript to the bottom // 3. Web Chat will always acknowledge all activities as it is at the bottom // 4. Acknowledge flag become useless -// Note: When Web Chat is loaded, there are no activities acknowledged, we need to assume all arriving activities are acknowledged until end-user sent their first activity. +// Note: When Web Chat is loaded, there are no activities acknowledged. We need to assume all arriving activities are acknowledged until end-user sends their first activity. // Activities loaded initially could be from conversation history. Without assuming acknowledgement, Web Chat will not scroll initially (as everything is not acknowledged). -// Better, the chat adapter should let Web Chat know if the activity is loaded from history or not. +// It would be better if the chat adapter should let Web Chat know if the activity is loaded from history or not. // TODO: [P2] Move the "conversation history acknowledgement" logic mentioned above to polyfill of chat adapters. // 1. Chat adapter should send "acknowledged" as part of "channelData" @@ -49,7 +49,7 @@ export default function useAcknowledgedActivity() { const lastEgressActivityIndex = findLastIndex(activities, ({ from: { role } = {} }) => role === 'user'); - // As described above, if no activities were acknowledged thru egress activity, we will assume everything is acknowledged. + // As described above, if no activities were acknowledged through egress activity, we will assume everything is acknowledged. const lastAcknowledgedActivityIndex = !~lastEgressActivityIndex ? activities.length - 1 : Math.max(lastStickyActivityIndex, lastEgressActivityIndex); From 12ce434fb856c5dc0fb30914acf136b2ba4a9a96 Mon Sep 17 00:00:00 2001 From: William Wong Date: Fri, 15 Jan 2021 12:17:50 -0800 Subject: [PATCH 5/9] Apply PR suggestions --- .../component/src/hooks/internal/useAcknowledgedActivity.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/component/src/hooks/internal/useAcknowledgedActivity.js b/packages/component/src/hooks/internal/useAcknowledgedActivity.js index a3cc0a3308..7decee770b 100644 --- a/packages/component/src/hooks/internal/useAcknowledgedActivity.js +++ b/packages/component/src/hooks/internal/useAcknowledgedActivity.js @@ -11,19 +11,21 @@ const { useActivities } = hooks; // Acknowledged means either: // 1. The user sent a message // - We don't need a condition here. When Web Chat sends the user's message, it will scroll to bottom, and it will trigger condition 2 below. -// 2. At the bottom of the transcript, scrolled from a non-bottom scroll position +// 2. The user scroll to the bottom of the transcript, from a non-bottom scroll position // - If the transcript is already at the bottom, the user needs to scroll up and then go back down // - What happens if we are relaxing "scrolled from a non-bottom scroll position": // 1. The condition will become solely "at the bottom of the transcript" // 2. Auto-scroll will always scroll the transcript to the bottom // 3. Web Chat will always acknowledge all activities as it is at the bottom // 4. Acknowledge flag become useless +// 5. Therefore, even the developer set "pause after 3 activities", if activities are coming in at a slow pace (not batched in a single render) +// Web Chat will keep scrolling and not snapped/paused // Note: When Web Chat is loaded, there are no activities acknowledged. We need to assume all arriving activities are acknowledged until end-user sends their first activity. // Activities loaded initially could be from conversation history. Without assuming acknowledgement, Web Chat will not scroll initially (as everything is not acknowledged). // It would be better if the chat adapter should let Web Chat know if the activity is loaded from history or not. -// TODO: [P2] Move the "conversation history acknowledgement" logic mentioned above to polyfill of chat adapters. +// TODO: [P2] #3670 Move the "conversation history acknowledgement" logic mentioned above to polyfill of chat adapters. // 1. Chat adapter should send "acknowledged" as part of "channelData" // 2. If "acknowledged" is "undefined", we set it to: // a. true, if there are no egress activities yet From 37d1174881531bccb0289929ce0bd6365a101949 Mon Sep 17 00:00:00 2001 From: William Wong Date: Fri, 15 Jan 2021 13:14:49 -0800 Subject: [PATCH 6/9] Fix test --- .../html/autoScroll.acknowledgement.html | 207 +++++++++--------- 1 file changed, 103 insertions(+), 104 deletions(-) diff --git a/__tests__/html/autoScroll.acknowledgement.html b/__tests__/html/autoScroll.acknowledgement.html index 2da7d18669..11ca79c0b0 100644 --- a/__tests__/html/autoScroll.acknowledgement.html +++ b/__tests__/html/autoScroll.acknowledgement.html @@ -28,144 +28,143 @@
  • From c67361b2df78542ba347af5f351e1758c7314f65 Mon Sep 17 00:00:00 2001 From: William Wong Date: Fri, 15 Jan 2021 13:17:43 -0800 Subject: [PATCH 7/9] Fix test --- __tests__/html/autoScroll.acknowledgement.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/__tests__/html/autoScroll.acknowledgement.html b/__tests__/html/autoScroll.acknowledgement.html index 11ca79c0b0..9ced189f08 100644 --- a/__tests__/html/autoScroll.acknowledgement.html +++ b/__tests__/html/autoScroll.acknowledgement.html @@ -128,10 +128,11 @@ expect(numActivitiesByAcknowledgement()).toEqual({ acknowledged: 4, unacknowledged: 1 }); + addDummyActivitiesToDirectLine(10); + await new Promise(requestAnimationFrame); - addDummyActivitiesToDirectLine( - addDummyActivitiesToDirectLine(1010); + addDummyActivitiesToDirectLine(10); await pageObjects.wait(conditions.scrollStabilized(), timeouts.scrollToBottom); From caa1c85fcc37fa153f64fa3cc180ab803990b4d0 Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 20 Jan 2021 04:54:30 -0800 Subject: [PATCH 8/9] Fix tests --- ...ehavior-should-scroll-correctly-1-snap.png | Bin 20525 -> 20566 bytes ...ehavior-should-scroll-correctly-1-snap.png | Bin 18817 -> 18857 bytes ...ehavior-should-scroll-correctly-1-snap.png | Bin 24173 -> 24214 bytes ...ehavior-should-scroll-correctly-1-snap.png | Bin 20495 -> 20537 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/__tests__/__image_snapshots__/html/auto-scroll-snap-activity-and-page-js-auto-scroll-with-activity-and-page-snap-behavior-should-scroll-correctly-1-snap.png b/__tests__/__image_snapshots__/html/auto-scroll-snap-activity-and-page-js-auto-scroll-with-activity-and-page-snap-behavior-should-scroll-correctly-1-snap.png index a63d5b929b8be15f4dd2d1cb24511fe36844093b..77c30694a7b7f6134f5165fceef4385e5a048dcc 100644 GIT binary patch delta 4586 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 delta 4545 zcmbVPWmHt%yB|a;X(S~?BqUxbi6I>kq!EykkVd*>=mU~U3WEqk^CHcF^iTrQCGAKF zNH<6${x|pIU3aZ}*PU-?&Dm$~{XD;VCbIBKv+&AOWFg+a60t2v+_;GX-i-;9;l}v4 zSqVg`$TCPo5{Y`fyy6pwIfe}eq zNy6uD>!r`-Epi`a+DUSztzvc@!WoZz1~XP9R|MGxWmhC^D{zh_rcF%g8u=Hbx5Y?d zmAL6oN9)kWhGCT*mFfq6c7Fa6lK^@|Wb9bp=%!Ko%nVDZUf)Qbs`AsPcG@n23_q%7 zq07^V%}qylcXxwIn;30Vef_S5jwqkQas7JlJqz@?Kq#ft>%Qw%Mx|V$qNs}tf5m8q zY}Dk~n3jP-0ck|lhaRhiuWxD8d$~2zy7!m*-o`*NP9B+IlsPi+hgp4neYk1|{lxue zxr)`VK7H+b(4yw($gixd+>aKgC?4;X+G%{Or$?8sk)DIxnN^?FF*DNy&oCb!AK0&7 zzqE{u-f84pwuKU3CnOa2$uuhMv=XLbVEDcsNW!k5v^o|f>#ci_Ok|m``-u{ zjABSx;gRl?Gl!g9%lIEkL?rr=^<3m1MLJQXTjrunQVnvo(v`SqH%wu11AC||mG!Zi z^MRjy@sTIP<8es6@ua*`6P5 zG0XU(;^Qgvws+^-qi>6s;f_-VY|f5%=GOkuAUrAd_Vy-AR5dibd}m(a1#ryz?Z_y` zFpaNmS=rjs(9=ic=i62uE-fv={0|1iz5V>8#t*lqYDdqxLsw-J5);v6YsKx1Sc$9` zXPVH+dukdQ!$xl*Dk>_qG>Ho3CXOr)4vw{%hGX@$M9Q3VEc{>eP21H4Av-oUw%NdQ zC)h-pNmOPg8xDtyW|L#p)YJ?oXX!mV+(@6T^f|C;Yirxx-OYmjUN)XAL>bq+=XH2Z zlo+-4C$S4kO=Z$6F$ivHk>gEz7aDrq-oZgK@InFxP_32@PlAxMJ`q7d zFq^?NWo>Qh+v3jumY0_gY<);h&KOWSU-1k4V7u$9*##gI{(AI;~lLr z*7NPxuL@l1sS3Kfw-^~2y}iA6hn3i>eVPzN!>lIosN9FsGc&{X)%+${RA^`@*C9bj z_T#CI@nU*BJiIL?I29uDsLuMDQK=pc6O&3{pe%=Cv{tW!y*&><#P28!)jtFnC@d(r zBP8_fKA(WV(yyLGHMCf%$samIWQ{g0EiJAAOM@U{Pt^t|{V!HL`Um-5i-=tT|Np{~ zq8TJL9W8Bz-?6j1hldbTO#errkgTk%*i|${iSTsTf``-?@cUovbs3cE-R0mAN>TH_ zJYCtpF2NqU3IqQR_V+8~k5*XqQ0MRe{_QCl1Qs@iT*A?Q3U@#f8&ABVsCC)Ue@2K%9YM|Ux& z3IiTq-t_`5qbdO4SXP-I3&I{NgVsRF#Pj43k$=OpvhHZ>=qPJya?8lD8Y2HvX!~&qY={Oy-Q+8`imI>zuA+LK;3kl0&lR{4R}q1jxAn@s5s;i_7yJU44BK z{}WeM@1JXqbU~GpnWSHdwnWH-1J?kkeuJqW~-g3FmiiZjD>^U2wISc0@zbIA-HklwXXrPIEb8rg8Sja zq|cv)&wj7ri~3tnut67(JUvBWfVWr2UtP7cu(Sk*dp9%i?Ec!?8oxm~tYK!*HZwr+ z`Eyz~H@DwwqY;lI$SVT>_+~(tK3Br+*dTYYiw}%4no&gYzMR{_^+%5$0l9)=nI+pk z2)wA#wcqPLxwy21AWMrhEq~xoWFkaOf1Mx7mlKjf@ zvarwoFPjZ1j*^Dw@^P#(sZ~{?fL=vuVHwgs)Infx$hsa6pMYl(*WBE!_E9ic#_veb zWmXz&B?&}7icUa#u+zfALL%Tyl#rbHXD}hF-AGw&tvC=iW=VGi;?@0qcM=j3@BJQb zyzbs!i(lREfl~8q4Q9xoUvEr2)6)9#vo*xUTdLYfpwealyX|h-8U3ttsVkbXy~47K z0g?-B+#hlnD|qHO*UShV9A?_ys1Uj`CFUa$M$`djn6_@-rn~uipZlO#{~hfe92oiM>?PW4YXG%gDMx zBU5%}-SVD-Dsww?N=k~jKSu@x5*Z-l$AM)rvzMECc%|d^fF<*Q{wnfPgBG_b@JSg2 zzpMoigy5kEI+yyAPtSK++&nxyuy=~I3mHIHZ7NSwogyM4uDq9*mlt^NPZ05X8GKAk zSXPEIk?;nB-Q#0ICg*$?b@@53DJSu&Gzoj^7={`fWsBzkW^1COiF# zr9GT%ancOR!(y3$+6d11fUM%Fe!m zQi>yPFk^~~iVBK~a>~kLllb)E0$0IuXSNB0b9QwVgr~;>!x!?|x6(+HXazlZR;W8R zHukc13LQ-=g{Z`0vCpTx4}HrzgvN#q7KQdZi;9Y1Cnt+>>Afsa32?998d&ahbcMCl8qfB+dGA)%Ag(`>zBWep9zAC*R> zy@9X#-2%Q0Pu4JVu$KXP@cmj^qGDm0*`!pmjAbY9N~s}rt9k<>23O+S#jZG!mtSDO zkco+iT#c63|A~JL)->iUoYgfX#fSDZ;2xi2noL<{)3ev zLZ(Z+0$pCt>lo)rs=9%g$CDEirY?z6p}7<{>GqH|BL;Q1ii{ zR8M#J7mJE=|I>Z0Lu+emD;pbX5PX0OMUb=Hy?5_AkU)8P80eNdgcbuCAp|JOjT<){ zXRt|;kwp3TUG+s6NJ*JQBTGv7t>GWr#|m|>NFaB4!qM8=ibA2{KYZu})`O~81?m-# zM)#ra>#X7`xj{Do8#uqi6Tu*Kak2+?9x2v;KtRqM*STZ**1+}DQiPYVPK1PnfUJx% zzEwItPoEN1S66S&wPb?9g-1UoHzx;Wos*jj@)x_15ET-MY-?{PCL>z{mD-x-5a)u! znLvsGV-61=UoIFHqnRZW&bJ#Vg0de+P}9>Zfw6H8`YU4(RWpUO%KQ6E1N}caJF79E zproho8cdgx^gj{2yu6e?`59u|?4J^ITO3Gy=I)5nB~7wTKiGjM|d<}b7$9U%S*~(qNH_hE)xj3=gC>a z&EjztU}h-!8k}R}=`y-M^haM(Fue!B5YqYuDtMObtkM9AdlmCT2r0CUjr+lweRY2Pc>r{5VFo$J zdFM`0clT3WUfT2H9i>vexvItcSo$tOLw!4adCe5zFt98kApv1*oVG72<>KO^t*y-? zAn>{{4h2&1=8x(q_Q&Crw{QEkBUh>?!*0@_?6y0egx3I8~Ax7~{NJx@!R0ra!QcCe8?4fl+TjX|j zb)y0zB8iQS(lEtX<{nUIlr0Ald#GI#`PGC#$)f38O#MGh+2a4}n0*L+jbK#5-^zLh P13%>_8VY5Imv8<9h_un8 diff --git a/__tests__/__image_snapshots__/html/auto-scroll-snap-activity-js-auto-scroll-with-activity-snap-behavior-should-scroll-correctly-1-snap.png b/__tests__/__image_snapshots__/html/auto-scroll-snap-activity-js-auto-scroll-with-activity-snap-behavior-should-scroll-correctly-1-snap.png index f2a9820058bcd7ad36bb4d59dbb6bc538e9e16be..7ea7afacecb66f8eb88e1db2437fecc88f7a3b32 100644 GIT binary patch literal 18857 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 literal 18817 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�*st%FMsvXt?Nw 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 R4+TFOH?&oAu04MGzW|)EK`{UT delta 7968 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 Re};m;+c(uQnKvH4{4bdRBHjQ1 diff --git a/__tests__/__image_snapshots__/html/auto-scroll-snap-page-js-auto-scroll-with-page-snap-behavior-should-scroll-correctly-1-snap.png b/__tests__/__image_snapshots__/html/auto-scroll-snap-page-js-auto-scroll-with-page-snap-behavior-should-scroll-correctly-1-snap.png index 969e8410ae86dc0e84eec48d0228999d268b70b7..bd17d7b110162171e9bebffc78c6f7f8198d91e8 100644 GIT binary patch delta 4395 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 WmQT&Sve*dVqadRyoiAzh_J05i8nVd% delta 4352 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 z Date: Wed, 20 Jan 2021 12:20:50 -0800 Subject: [PATCH 9/9] Fix tests --- __tests__/html/timestamp.changeSendTimeout.html | 4 ++-- packages/api/src/hooks/internal/useTimePassed.js | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/__tests__/html/timestamp.changeSendTimeout.html b/__tests__/html/timestamp.changeSendTimeout.html index 3c419d8da8..ef77beee9c 100644 --- a/__tests__/html/timestamp.changeSendTimeout.html +++ b/__tests__/html/timestamp.changeSendTimeout.html @@ -9,7 +9,7 @@