Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
142 commits
Select commit Hold shift + click to select a range
5671929
Initial commit of polyMiddleware
compulim Jul 16, 2025
6e33a6e
Bump react-chain-of-responsibility and handler-chain
compulim Jul 28, 2025
10d1d42
Move middleware typing to middleware package
compulim Jul 28, 2025
ff67e17
Add useReduceMemo
compulim Jul 29, 2025
c36bed0
Update performance snapshot
compulim Jul 29, 2025
58c6f7e
Fix ESLint
compulim Jul 29, 2025
138146b
Fix test
compulim Aug 11, 2025
e1effac
Bump to latest
compulim Aug 12, 2025
f357ea5
Revert
compulim Aug 12, 2025
91d7894
Apply
compulim Aug 12, 2025
65eb765
Revert
compulim Aug 12, 2025
5cd32f0
Bump to latest
compulim Aug 12, 2025
2e03849
Fix test
compulim Aug 12, 2025
64ca8a2
Add expectation
compulim Aug 12, 2025
bebeba3
Group activities should invalidate callback on style options change
compulim Aug 12, 2025
df90db2
Add barrel file for Webpack4
compulim Aug 12, 2025
8690ee5
Rename
compulim Aug 13, 2025
c3e1f27
Better comment
compulim Aug 13, 2025
2547699
Add comment
compulim Aug 13, 2025
402454f
Convert to class component
compulim Aug 13, 2025
c1af378
Improve performance
compulim Aug 13, 2025
f972e63
Reduce one use variable
compulim Aug 13, 2025
911e472
Use internal current config
compulim Aug 13, 2025
447a112
Hide Init
compulim Aug 13, 2025
370253e
Add types="jest"
compulim Aug 13, 2025
3b1f9ec
Add comment
compulim Aug 13, 2025
d408dc3
Better comment
compulim Aug 13, 2025
e27de2f
Fix reducer immutability
compulim Aug 13, 2025
a59abaf
Import botframework-webchat-middleware
compulim Aug 13, 2025
d01d5e8
Export activity poly middleware components
compulim Aug 13, 2025
64c54e6
Add priority
compulim Aug 13, 2025
bf5a2c6
Add TODO
compulim Aug 13, 2025
182246c
Sort
compulim Aug 13, 2025
23056e3
Unify react-chain-of-responsibility version
compulim Aug 13, 2025
54ca7f7
WIP: Add test
compulim Aug 13, 2025
d65971c
Port useCreateActivityRendererInternal hook
compulim Aug 16, 2025
d24b30f
Upgrade test to html2
compulim Aug 16, 2025
843ad07
Prefix Legacy* and allow extraneous activity props
compulim Aug 16, 2025
fb50ce5
Fold unnecessary useCreateActivityRendererInternal
compulim Aug 16, 2025
11cb470
Add no import rules
compulim Aug 16, 2025
b1dfe2e
Comments
compulim Aug 16, 2025
5322961
Pass all legacy props
compulim Aug 16, 2025
e276846
Add import restriction
compulim Aug 16, 2025
7ec1bc3
Move under folder
compulim Aug 17, 2025
35ec057
Add test
compulim Aug 17, 2025
b88e124
Bump react-chain-of-responsibility
compulim Aug 17, 2025
4223d78
Add snapshot
compulim Aug 17, 2025
9af078c
Merge branch 'main' into feat-poly-middleware
compulim Aug 17, 2025
3c30ba3
Better comments
compulim Aug 17, 2025
60f272f
Add tests
compulim Aug 17, 2025
7d774c7
Update comment
compulim Aug 17, 2025
cb26a58
Rename to LegacyAttachmentMiddleware and added bf-wc-middleware/internal
compulim Aug 17, 2025
5c5ceda
Check middleware factory marker
compulim Aug 18, 2025
21f940d
Add deprecation
compulim Aug 18, 2025
f66c541
Use valibot for factory function validation
compulim Aug 18, 2025
e251389
Enhancer must be of type function
compulim Aug 18, 2025
cad87da
Check for no console.warn
compulim Aug 18, 2025
46b5db6
Add comments
compulim Aug 18, 2025
fd175bb
Add comments
compulim Aug 18, 2025
1b3a953
Rename marker to tag
compulim Aug 18, 2025
9525a4d
Bump use-reduce-memo
compulim Aug 18, 2025
25cd957
Add tests
compulim Aug 18, 2025
eaa323e
Better comments
compulim Aug 18, 2025
94ff79d
Prevent wasted rendering on unrelated middleware changes
compulim Aug 18, 2025
3536c4e
Fix exports
compulim Aug 18, 2025
fd4b288
Fix ESLint
compulim Aug 18, 2025
93d2acd
Fix tests for extractEnhancer
compulim Aug 18, 2025
156ed89
Add snapshots
compulim Aug 18, 2025
4909dd4
Add React rules
compulim Aug 18, 2025
771347e
Fix ESLint
compulim Aug 19, 2025
423735b
Better comments
compulim Aug 19, 2025
833e867
Use Object.defineProperty
compulim Aug 19, 2025
e2107f0
Remove one-use
compulim Aug 19, 2025
6e4ba44
Offload things from LegacyActivityBridge to LegacyActivityComposer
compulim Aug 20, 2025
f745492
Update snapshots
compulim Aug 22, 2025
9812ba3
Provide deprecation path for api activityMiddleware
compulim Aug 22, 2025
390ee09
Remove unnecessary declaration of activityMiddleware
compulim Aug 22, 2025
d3861bc
Simplify import
compulim Aug 22, 2025
e070746
Fix import
compulim Aug 22, 2025
c45b35f
Rename to api-middleware
compulim Aug 22, 2025
442c689
Fix npm start
compulim Aug 22, 2025
9a80912
Rename/add tests
compulim Aug 23, 2025
822eb22
Fix .eslintrc
compulim Aug 23, 2025
db3a917
Add tests
compulim Aug 23, 2025
69cacaf
Add sample
compulim Aug 23, 2025
9ddea38
Add sample
compulim Aug 23, 2025
26deb14
Clean up docs
compulim Aug 23, 2025
a9a161a
Rename PolyMiddleware to Polymiddleware
compulim Aug 23, 2025
5dcee0a
Cascade build
compulim Aug 24, 2025
0758b57
Ignore render thru error boundary
compulim Aug 24, 2025
997b41f
Add error box middleware
compulim Aug 25, 2025
d4e1a58
Fix falsy polymiddleware
compulim Aug 25, 2025
22ecad2
Allow middleware of false
compulim Aug 25, 2025
489658d
Remove unnecessary props
compulim Aug 25, 2025
9020430
Fix test
compulim Aug 25, 2025
c8f0357
Fix grouping
compulim Aug 25, 2025
6e8b890
Fix ESLint
compulim Aug 25, 2025
6fab0e7
Upgrade a test
compulim Aug 25, 2025
a3eeeef
Add trackException
compulim Aug 25, 2025
e297740
Print error once by React
compulim Aug 25, 2025
87d286d
No export Provider and extract*
compulim Aug 25, 2025
f4cbb17
Add priority
compulim Aug 25, 2025
eff52fb
Rename
compulim Aug 25, 2025
26bac86
Set TODO priority
compulim Aug 25, 2025
8ce8f4d
Reduce exports
compulim Aug 25, 2025
1f9da89
Clean up
compulim Aug 26, 2025
a7c0137
Add fallback error box
compulim Aug 26, 2025
c23a708
Clean up
compulim Aug 26, 2025
226f097
Add snapshot
compulim Aug 26, 2025
f8011c0
Add no error box test
compulim Aug 26, 2025
f0c59ac
Deconfuse render function with function component
compulim Aug 26, 2025
0c04c53
Use ErrorBoxPolymiddlewareProxy
compulim Aug 26, 2025
5469cfe
Fix homepage
compulim Aug 26, 2025
9495a18
Add new <DebugProvider>
compulim Aug 27, 2025
1b3c895
Should not depends on bundle
compulim Aug 27, 2025
5dfe961
Remove dependency to bundle
compulim Aug 27, 2025
5dd43bd
Add debug-provider package
compulim Aug 27, 2025
eb2f2ac
Add debug-theme
compulim Aug 27, 2025
389da17
Update tests
compulim Aug 27, 2025
3d5673b
Remove unnecessary expect
compulim Aug 27, 2025
dcb193c
Add new test
compulim Aug 27, 2025
f56d743
Add a red box
compulim Aug 27, 2025
033274d
Remove node_env
compulim Aug 27, 2025
84bbe87
Add date
compulim Aug 27, 2025
96dfcce
Rename
compulim Aug 27, 2025
dc8a338
Remove localDependencies
compulim Aug 27, 2025
91a0233
Fix typing
compulim Aug 27, 2025
9baa36c
Fix test
compulim Aug 27, 2025
6b53836
Fix test
compulim Aug 27, 2025
4645fe0
Merge branch 'main' into feat-poly-middleware
compulim Aug 27, 2025
0a3db13
Apply suggestion
compulim Aug 27, 2025
9b9f157
Add botframework-webchat-react-hooks package
compulim Aug 27, 2025
f270455
Use as unknown instead of as any
compulim Aug 27, 2025
1d9acb4
Add prop type
compulim Aug 27, 2025
a6855c5
Add entry
compulim Aug 27, 2025
796b75a
Add entry
compulim Aug 27, 2025
24d19e0
Fix ESLint
compulim Aug 27, 2025
e0253bb
Typos
compulim Aug 27, 2025
ff230e4
Typo
compulim Aug 28, 2025
e661cee
Test bundle content
compulim Aug 28, 2025
cc91f39
Reduce boot coed
compulim Aug 28, 2025
5ddc4ff
Add test for exports
compulim Aug 28, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
!/__tests__
/__tests__/__image_snapshots__
!/packages/bundle/dist
!/packages/debug-theme/dist
!/packages/fluent-theme/dist
!/packages/playground/build
!/packages/test/fluent-bundle/dist
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/pull-request-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ jobs:
./package.json
./__tests__/
./packages/bundle/dist/
./packages/debug-theme/dist/
./packages/fluent-theme/dist/
./packages/test/harness/
./packages/test/page-object/dist/
Expand Down
13 changes: 11 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Notes: web developers are advised to use [`~` (tilde range)](https://github.com/
- `sendBoxToolbarMiddleware`, related to PR [#5504](https://github.com/microsoft/BotFramework-WebChat/pull/5504)
- `styleOptions.hideUploadButton` is being deprecated in favor of `styleOptions.disableFileUpload`. The option will be removed on or after 2027-07-14
- `botframework-directlinespeech-sdk` no longer ponyfill `AbortController`, it is supported by modern browsers, in PR [#5530](https://github.com/microsoft/BotFramework-WebChat/pull/5530)
- `activityMiddleware` is being deprecated in favor of [`polymiddleware`](./docs/MIDDLEWARE.md). It will be removed on or after 2027-08-16, related to PR [#5515](https://github.com/microsoft/BotFramework-WebChat/pull/5515)

### Added

Expand Down Expand Up @@ -108,6 +109,13 @@ Notes: web developers are advised to use [`~` (tilde range)](https://github.com/
- Deprecated `hideUploadButton` in favor of `disableFileUpload`.
- Updated `BasicSendBoxToolbar` to rely solely on `disableFileUpload`.
- Added support for livestreaming via `entities[type="streaminfo"]` in PR [#5517](https://github.com/microsoft/BotFramework-WebChat/pull/5517) by [@kylerohn](https://github.com/kylerohn) and [@compulim](https://github.com/compulim)
- Added `polymiddleware`, a new [universal middleware for every UIs](./docs/MIDDLEWARE.md), by [@compulim](https://github.com/compulim) in PR [#5515](https://github.com/microsoft/BotFramework-WebChat/pull/5515)
- Added `polymiddleware` to `<ThemeProvider>`
- Currently supports activity middleware and the new error box middleware
- New internal packages, by [@compulim](https://github.com/compulim) in PR [#5515](https://github.com/microsoft/BotFramework-WebChat/pull/5515)
- `@msinternal/botframework-webchat-api-middleware` for middleware branch of API package
- `@msinternal/botframework-webchat-debug-theme` package for enabling debugging scenarios
- `@msinternal/botframework-webchat-react-hooks` for helpers for React hooks

### Changed

Expand Down Expand Up @@ -151,7 +159,7 @@ Notes: web developers are advised to use [`~` (tilde range)](https://github.com/
- [`[email protected]`](https://npmjs.com/package/micromark/v/4.0.2)
- [`[email protected]`](https://npmjs.com/package/microsoft-cognitiveservices-speech-sdk/v/1.45.0)
- [`[email protected]`](https://npmjs.com/package/mime/v/4.0.7)
- [`react-chain-of-responsibility@0.3.0`](https://npmjs.com/package/react-chain-of-responsibility/v/0.3.0)
- [`react-chain-of-responsibility@0.4.0-main.2a72139`](https://npmjs.com/package/react-chain-of-responsibility/v/0.4.0-main.2a72139)
- [`[email protected]`](https://npmjs.com/package/react-film/v/4.0.0)
- [`[email protected]`](https://npmjs.com/package/react-say/v/2.2.0)
- [`[email protected]`](https://npmjs.com/package/react-scroll-to-bottom/v/4.2.0)
Expand Down Expand Up @@ -277,11 +285,12 @@ Notes: web developers are advised to use [`~` (tilde range)](https://github.com/
- Fixed [#5518](https://github.com/microsoft/BotFramework-WebChat/issues/5518). Minimal bundled build should work properly, in PR [#5507](https://github.com/microsoft/BotFramework-WebChat/pull/5507), by [@compulim](https://github.com/compulim)
- Fixed [#5520](https://github.com/microsoft/BotFramework-WebChat/issues/5520). Version information should be injected when installed via npm, in PR [#5521](https://github.com/microsoft/BotFramework-WebChat/pull/5521), by [@compulim](https://github.com/compulim)

# Removed
### Removed

- Deprecating `disabled` props and `useDisabled` hook in favor of new `uiState` props and `useUIState` hook, in PR [#5276](https://github.com/microsoft/BotFramework-WebChat/pull/5276), by [@compulim](https://github.com/compulim)
- `useSuggestedActions()` hook is being deprecated in favor of the `useSuggestedActionsHooks().useSuggestedActions()` hook, in PR [#5489](https://github.com/microsoft/BotFramework-WebChat/pull/5489), by [@compulim](https://github.com/compulim)
- Fixed core internal import in legacy CommonJS environments, in [5509](https://github.com/microsoft/BotFramework-WebChat/pull/5509), by [@OEvgeny](https://github.com/OEvgeny)
- `activityMiddleware` is being deprecated in favor of [`polymiddleware`](./docs/MIDDLEWARE.md). It will be removed on or after 2027-08-16, related to PR [#5515](https://github.com/microsoft/BotFramework-WebChat/pull/5515)

### Samples

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.
27 changes: 18 additions & 9 deletions __tests__/html/focusManagement.disableHeroCard.obsolete.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en-US">
<head>
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
Expand All @@ -15,14 +15,29 @@
<script type="text/babel" data-presets="env,stage-3,react">
const {
WebChat: {
Components: { HeroCardContent }
Components: { HeroCardContent },
hooks: { useActivities }
}
} = window;

run(async function () {
const store = testHelpers.createStore();
const directLine = WebChat.createDirectLine({ token: await testHelpers.token.fetchDirectLineToken() });

const AutoDisableHeroCardContent = ({ activity, attachment }) => {
const [activities] = useActivities();
const messageActivities = activities.filter(activity => activity.type === 'message');
const isMostRecentMessageActivity = messageActivities.pop() === activity;

return (
<HeroCardContent
actionPerformedClassName="card__action--performed"
content={attachment.content}
disabled={!isMostRecentMessageActivity}
/>
);
};

WebChat.renderWebChat(
{
attachmentMiddleware:
Expand All @@ -35,13 +50,7 @@
const mostRecent = messageActivities.pop() === activity;

if (attachment.contentType === 'application/vnd.microsoft.card.hero') {
return (
<HeroCardContent
actionPerformedClassName="card__action--performed"
content={attachment.content}
disabled={!mostRecent}
/>
);
return <AutoDisableHeroCardContent activity={activity} attachment={attachment} />;
}

return next(...args);
Expand Down
5 changes: 0 additions & 5 deletions __tests__/html/hooks.useCreateActivityRenderer.js

This file was deleted.

137 changes: 78 additions & 59 deletions __tests__/html/renderActivity.performance.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,32 @@
<script type="text/babel" data-presets="env,stage-3,react">
const BATCH_SIZE = 5;

const timesActivityRendered = new Map();
const timesEnhancerCalled = new Map();
const timesHandlerCalled = new Map();

function activityRendered() {
return next => (...args) => {
const [{ activity }] = args;
const renderActivity = next(...args)
timesActivityRendered.set(activity.id, (timesActivityRendered.get(activity.id) ?? 0) + 1);
return (...args) => (
<>
{renderActivity.call ? renderActivity(...args) : renderActivity}
<small> Rendered {timesActivityRendered.get(activity.id)} times</small>
</>
)
}
return next =>
(...args) => {
const [{ activity }] = args;
const renderActivity = next(...args);

timesEnhancerCalled.set(activity.id, (timesEnhancerCalled.get(activity.id) ?? 0) + 1);

return (...args) => {
timesHandlerCalled.set(activity.id, (timesHandlerCalled.get(activity.id) ?? 0) + 1);

return (
<>
{renderActivity.call ? renderActivity(...args) : renderActivity}
<small>
{' '}
Enhancer called {timesEnhancerCalled.get(activity.id)} times and handler called{' '}
{timesHandlerCalled.get(activity.id)} times
</small>
</>
);
};
};
}

let shownCount = 0;
Expand All @@ -43,7 +55,13 @@
promises.push(
// Plain text message isolate dependencies on Markdown.
directLine.emulateIncomingActivity(
{ id: `activity-${shownCount + index}`, text: `Message ${shownCount + index}.`, textFormat: 'plain', type: 'message', timestamp },
{
id: `activity-${shownCount + index}`,
text: `Message ${shownCount + index}.`,
textFormat: 'plain',
type: 'message',
timestamp
},
{ skipWait: true }
)
);
Expand All @@ -54,53 +72,54 @@
await pageConditions.numActivitiesShown(shownCount);
}

run(
async function () {
const {
WebChat: { ReactWebChat }
} = window; // Imports in UMD fashion.

const { directLine, store } = testHelpers.createDirectLineEmulator();

WebChat.renderWebChat({ directLine, store, activityMiddleware: [activityRendered] }, document.querySelector('main'));

await pageConditions.uiConnected();
pageElements.transcript().focus();

// WHEN: Adding 10 activities.
await postMessagesBatch(directLine);
await postMessagesBatch(directLine);

// THEN: Should not re-render activity more than twice.
expect(Math.max(...timesActivityRendered.values())).toEqual(2);
expect(Math.min(...timesActivityRendered.values())).toEqual(1);

// WHEN: Scroll and clicked on the 5th activity.
const previousTimesActivityRendered = structuredClone(timesActivityRendered)
pageElements.activities()[4].scrollIntoView();
await host.clickAt(10, 10, pageElements.activities()[4]);

// THEN: Should focus on the activity.
expect(pageElements.focusedActivity()).toEqual(pageElements.activities()[4]);

// THEN: Should not re-render.
expect(timesActivityRendered).toEqual(previousTimesActivityRendered);

// WHEN: The 9th activity received an update.
const timestamp = new Date().toISOString();
const activity9Renders = timesActivityRendered.get('activity-8');
await directLine.emulateIncomingActivity(
{ id: `activity-8`, text: `Activity 8 got updated`, textFormat: 'plain', type: 'message', timestamp },
{ skipWait: true }
);
run(async function () {
const {
WebChat: { ReactWebChat }
} = window; // Imports in UMD fashion.

// THEN: Should re-render the 9th activity once.
expect(timesActivityRendered.get('activity-8')).toBe(activity9Renders + 1);
// THEN: Should render the updated 9th activity.
pageElements.focusedActivity().scrollIntoView();
await host.snapshot();
}
);
const { directLine, store } = testHelpers.createDirectLineEmulator();

WebChat.renderWebChat(
{ directLine, store, activityMiddleware: [activityRendered] },
document.querySelector('main')
);

await pageConditions.uiConnected();
pageElements.transcript().focus();

// WHEN: Adding 10 activities.
await postMessagesBatch(directLine);
await postMessagesBatch(directLine);

// THEN: Should not re-render activity more than twice.
expect(Math.max(...timesHandlerCalled.values())).toEqual(2);
expect(Math.min(...timesHandlerCalled.values())).toEqual(1);

// WHEN: Scroll and clicked on the 5th activity.
const previousTimesActivityRendered = structuredClone(timesHandlerCalled);
pageElements.activities()[4].scrollIntoView();
await host.clickAt(10, 10, pageElements.activities()[4]);

// THEN: Should focus on the activity.
expect(pageElements.focusedActivity()).toEqual(pageElements.activities()[4]);

// THEN: Should not re-render.
expect(timesHandlerCalled).toEqual(previousTimesActivityRendered);

// WHEN: The 9th activity received an update.
const timestamp = new Date().toISOString();
const activity9Renders = timesHandlerCalled.get('activity-8');
await directLine.emulateIncomingActivity(
{ id: `activity-8`, text: `Activity 8 got updated`, textFormat: 'plain', type: 'message', timestamp },
{ skipWait: true }
);

// THEN: Should re-render the 9th activity once.
expect(timesHandlerCalled.get('activity-8')).toBe(activity9Renders + 1);
// THEN: Should render the updated 9th activity.
pageElements.focusedActivity().scrollIntoView();
await host.snapshot();
});
</script>
</body>
</html>
Loading
Loading