Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Customize scroll behavior #3653

Merged
merged 13 commits into from
Jan 20, 2021
31 changes: 18 additions & 13 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 [#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 [#3653](https://github.com/microsoft/BotFramework-WebChat/pull/3653)

### 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 `<s>` 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)
Expand Down Expand Up @@ -70,19 +88,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- [`[email protected]`](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 `<s>` 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)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
171 changes: 171 additions & 0 deletions __tests__/html/autoScroll.acknowledgement.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<script crossorigin="anonymous" src="/__dist__/testharness.js"></script>
<script crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
<style type="text/css">
.button-bar {
position: fixed;
right: 10px;
text-align: right;
top: 10px;
}

.webchat__basic-transcript__activity.webchat__basic-transcript__activity--acknowledged {
background-color: Cyan;
}

.webchat__basic-transcript__activity:not(.webchat__basic-transcript__activity--acknowledged) {
background-color: Orange;
}
</style>
</head>
<body>
<div id="webchat"></div>
<div class="button-bar">
<button class="add-activity-button">Add activity with 10 lines</button>
<br />
<button class="add-3-activities-button">Add 3 activities with 10 lines each</button>
</div>
<script type="text/babel" data-presets="env,stage-3,react">
const {
conditions,
createDirectLineWithTranscript,
createStore,
elements,
expect,
host,
pageObjects,
shareObservable,
timeouts,
token
} = window.WebChatTest;

const {
Components: { AdaptiveCardContent }
} = window.WebChat;

const directLine = createDirectLineWithTranscript([createActivity(20)]);
const store = createStore();

let now = +new Date(2020, 0, 23, 12, 34);

function createActivity(numLines) {
return {
from: { role: 'bot' },
id: Math.random().toString(36).substr(2, 5),
text: new Array(numLines)
.fill()
.map((_, index) => `Line ${index + 1}`)
.join('\n\n'),
timestamp: new Date().toISOString(),
type: 'message'
};
}

function addDummyActivitiesToDirectLine(numLines) {
directLine.activityDeferredObservable.next(createActivity(numLines));
}

function numActivitiesByAcknowledgement() {
const { length: numActivities } = document.querySelectorAll('.webchat__basic-transcript__activity');

const { length: numAcknowledged } = document.querySelectorAll(
'.webchat__basic-transcript__activity--acknowledged'
);

return {
acknowledged: numAcknowledged,
unacknowledged: numActivities - numAcknowledged
};
}

document.querySelector('.add-activity-button').addEventListener('click', () => {
addDummyActivitiesToDirectLine(10);
});

document.querySelector('.add-3-activities-button').addEventListener('click', () => {
addDummyActivitiesToDirectLine(10);
addDummyActivitiesToDirectLine(10);
addDummyActivitiesToDirectLine(10);
});

(async function () {
const webChatElement = document.getElementById('webchat');

window.WebChat.renderWebChat(
{
directLine,
store,
styleOptions: { autoScrollSnapOnPage: true }
},
webChatElement
);

await pageObjects.wait(conditions.uiConnected(), timeouts.directLine);

addDummyActivitiesToDirectLine(10);

await pageObjects.wait(conditions.minNumActivitiesShown(2), timeouts.directLine);
await pageObjects.wait(conditions.scrollStabilized(), timeouts.scrollToBottom);

expect(numActivitiesByAcknowledgement()).toEqual({ acknowledged: 2, unacknowledged: 0 });

addDummyActivitiesToDirectLine(10);

await pageObjects.wait(conditions.scrollStabilized(), timeouts.scrollToBottom);

expect(numActivitiesByAcknowledgement()).toEqual({ acknowledged: 3, unacknowledged: 0 });

await pageObjects.sendMessageViaSendBox('Hello, World!');
await pageObjects.wait(conditions.scrollStabilized(), timeouts.scrollToBottom);

expect(numActivitiesByAcknowledgement()).toEqual({ acknowledged: 4, unacknowledged: 0 });

addDummyActivitiesToDirectLine(10);

await pageObjects.wait(conditions.scrollStabilized(), timeouts.scrollToBottom);

expect(numActivitiesByAcknowledgement()).toEqual({ acknowledged: 4, unacknowledged: 1 });
);

await new Promise(requestAnimationFrame);

addDummyActivitiesToDirectLine(
addDummyActivitiesToDirectLine(1010);

await pageObjects.wait(conditions.scrollStabilized(), timeouts.scrollToBottom);

expect(numActivitiesByAcknowledgement()).toEqual({ acknowledged: 4, unacknowledged: 3 });

const activityElementAtTopOfView = document.querySelectorAll('.webchat__basic-transcript__activity')[4];
const scrollable = document.querySelector('.webchat__basic-transcript__scrollable');

expect(scrollable.scrollTop).toBe(activityElementAtTopOfView.offsetTop);

await pageObjects.sendMessageViaSendBox('Aloha!');

await pageObjects.wait(conditions.scrollToBottomCompleted(), timeouts.scrollToBottom);
expect(numActivitiesByAcknowledgement()).toEqual({ acknowledged: 8, unacknowledged: 0 });

// Scroll to top and lose the stickiness.
scrollable.scrollTop = 0;

// Wait for scroll-to-bottom to detect it is no longer sticky.
await new Promise(resolve => setTimeout(resolve, 1000));

addDummyActivitiesToDirectLine(10);
await pageObjects.wait(conditions.minNumActivitiesShown(9), timeouts.directLine);

expect(scrollable.scrollTop).toBe(0);
expect(numActivitiesByAcknowledgement()).toEqual({ acknowledged: 8, unacknowledged: 1 });

await host.done();
})().catch(async err => {
console.error(err);

await host.error(err);
});
</script>
</body>
</html>
7 changes: 7 additions & 0 deletions __tests__/html/autoScroll.acknowledgement.js
Original file line number Diff line number Diff line change
@@ -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'));
});
131 changes: 131 additions & 0 deletions __tests__/html/autoScroll.snap.activity.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<script crossorigin="anonymous" src="/__dist__/testharness.js"></script>
<script crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
<style type="text/css">
.webchat__basic-transcript__activity.webchat__basic-transcript__activity--acknowledged {
background-color: Cyan;
}

.webchat__basic-transcript__activity:not(.webchat__basic-transcript__activity--acknowledged) {
background-color: Orange;
}
</style>
</head>
<body>
<div id="webchat"></div>
<script type="text/babel" data-presets="env,stage-3,react">
const {
conditions,
createDirectLineWithTranscript,
createStore,
elements,
expect,
host,
pageObjects,
shareObservable,
timeouts,
token
} = window.WebChatTest;

const {
Components: { AdaptiveCardContent }
} = window.WebChat;

const directLine = createDirectLineWithTranscript([createActivity(20)]);
const store = createStore();

let now = +new Date(2020, 0, 23, 12, 34);

function createActivity(numLines) {
return {
from: { role: 'bot' },
id: Math.random().toString(36).substr(2, 5),
text: new Array(numLines)
.fill()
.map((_, index) => `Line ${index + 1}`)
.join('\n\n'),
timestamp: new Date().toISOString(),
type: 'message'
};
}

function addDummyActivitiesToDirectLine(numLines) {
directLine.activityDeferredObservable.next(createActivity(numLines));
}

function numActivitiesByAcknowledgement() {
const { length: numActivities } = document.querySelectorAll('.webchat__basic-transcript__activity');

const { length: numAcknowledged } = document.querySelectorAll(
'.webchat__basic-transcript__activity--acknowledged'
);

return {
acknowledged: numAcknowledged,
unacknowledged: numActivities - numAcknowledged
};
}

(async function () {
const webChatElement = document.getElementById('webchat');

window.WebChat.renderWebChat(
{
directLine,
store,
styleOptions: {
autoScrollSnapOnActivity: 2,
autoScrollSnapOnActivityOffset: 100
}
},
webChatElement
);

await pageObjects.wait(conditions.uiConnected(), timeouts.directLine);

addDummyActivitiesToDirectLine(10);

await pageObjects.wait(conditions.minNumActivitiesShown(2), timeouts.directLine);
await pageObjects.wait(conditions.scrollStabilized(), timeouts.scrollToBottom);

await pageObjects.sendMessageViaSendBox('Hello, World!');

await pageObjects.wait(conditions.minNumActivitiesShown(3), timeouts.directLine);
await pageObjects.wait(conditions.scrollStabilized(), timeouts.scrollToBottom);

const scrollable = document.querySelector('.webchat__basic-transcript__scrollable');

expect(scrollable.scrollTop).toBe(
scrollable.scrollHeight - scrollable.offsetHeight,
'scrollable should be at bottom'
);

addDummyActivitiesToDirectLine(10);
addDummyActivitiesToDirectLine(10);
addDummyActivitiesToDirectLine(10);

await pageObjects.wait(conditions.minNumActivitiesShown(6), timeouts.directLine);
await pageObjects.wait(conditions.scrollStabilized(), timeouts.scrollToBottom);

const activityElementAtBottomOfView = document.querySelectorAll('.webchat__basic-transcript__activity')[4];

expect(scrollable.scrollTop).toBe(
activityElementAtBottomOfView.offsetTop +
activityElementAtBottomOfView.offsetHeight +
100 -
scrollable.offsetHeight,
'scrollable should be at 2 activities + 100px'
);

await host.snapshot();
await host.done();
})().catch(async err => {
console.error(err);

await host.error(err);
});
</script>
</body>
</html>
7 changes: 7 additions & 0 deletions __tests__/html/autoScroll.snap.activity.js
Original file line number Diff line number Diff line change
@@ -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'));
});
Loading