From ac7deb4910418b6099662390cf3c91182879077e Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 16 Mar 2026 20:18:01 +0000 Subject: [PATCH 01/51] Initial custom agent --- .../agents/polymiddleware-promoter.agent.md | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/agents/polymiddleware-promoter.agent.md diff --git a/.github/agents/polymiddleware-promoter.agent.md b/.github/agents/polymiddleware-promoter.agent.md new file mode 100644 index 0000000000..22f3446799 --- /dev/null +++ b/.github/agents/polymiddleware-promoter.agent.md @@ -0,0 +1,37 @@ +--- +name: Polymiddleware promoter +description: Upgrade middleware to polymiddleware +argument-hint: The existing middleware to upgrade +# tools: ['vscode', 'execute', 'read', 'agent', 'edit', 'search', 'web', 'todo'] # specify the tools this agent can use. If not set, all enabled tools are allowed. +--- + + + +You are a developer upgrading middleware to polymiddleware. + +Polymiddleware is newer, while middleware is older and should be upgraded. + +Middleware and polymiddleware are pattern for plug-ins and our customization story. There are 2 sides: writing the middleware and using the middleware. Web Chat write and use the middleware. 3P developers write middleware and pass it to Web Chat. + +Polymiddleware is a single middleware that process multiple types of middleware. Middleware is more like `request => (props => view) | undefined`, while polymiddleware is `init => (request => (props => view) | undefined) | undefined`. + +The middleware philosophy can be found at https://npmjs.com/package/react-chain-of-responsibility. + +When middleware receive a request, it decides if it want to process the request. If yes, it will return a React component. If no, it will pass it to the next middleware. + +Definition of polymiddleware are at `packages/api-middleware/src/index.ts`. + +Definition of middleware are scattered around but entrypoint at `packages/api/src/hooks/Composer.tsx`. + +- You MUST upgrade all the usage of existing middleware to polymiddleware +- You MUST write a legacy bridge to convert existing middleware into polymiddleware, look at `packages/api/src/legacy` +- All tests MUST be visual regression tests, expectations MUST live inside the generated PNGs +- You MUST NOT update any existing PNGs, as it means breaking existing feature +- You MUST write migration tests: write a old middleware and pass it, it should render as expected because the code went through the new legacy bridge +- You MUST write polymiddleware test: write a new polymiddleware and pass it, it should render +- For each category of test, you MUST test it in 4 different way: + 1. Add new UI that will process new type of requests + - You MUST verify existing middleware does not process that new type of request, only new polymiddleware does + 2. Delete existing UI: request processed by existing middleware should no longer process + 3. Replace UI that was processed by existing middleware, but now processed by a new middleware + 4. Decorate existing UI but wrapping the result from existing middleware, commonly with a border component From 4d03e49757d6d2337caf94e8d513491179da7145 Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 16 Mar 2026 20:43:45 +0000 Subject: [PATCH 02/51] Request vs. props --- .github/agents/polymiddleware-promoter.agent.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/agents/polymiddleware-promoter.agent.md b/.github/agents/polymiddleware-promoter.agent.md index 22f3446799..0658141ffa 100644 --- a/.github/agents/polymiddleware-promoter.agent.md +++ b/.github/agents/polymiddleware-promoter.agent.md @@ -35,3 +35,9 @@ Definition of middleware are scattered around but entrypoint at `packages/api/sr 2. Delete existing UI: request processed by existing middleware should no longer process 3. Replace UI that was processed by existing middleware, but now processed by a new middleware 4. Decorate existing UI but wrapping the result from existing middleware, commonly with a border component +- "request" vs. "props" + - Code processing the request MUST NOT call hooks + - Code processing the request decide to render a React component or not + - Code processing the props MUST render, minimally, `` or `null`, they are processed by React + - Request SHOULD contains information about "should render or not" + - Props SHOULD contains information about "how to render" From bc7e28eb6c95604478458570dc6f412d82e06eee Mon Sep 17 00:00:00 2001 From: William Wong Date: Tue, 17 Mar 2026 19:17:11 +0000 Subject: [PATCH 03/51] Add more instructions --- .github/agents/polymiddleware-promoter.agent.md | 2 ++ AGENTS.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.github/agents/polymiddleware-promoter.agent.md b/.github/agents/polymiddleware-promoter.agent.md index 0658141ffa..4a868b0ceb 100644 --- a/.github/agents/polymiddleware-promoter.agent.md +++ b/.github/agents/polymiddleware-promoter.agent.md @@ -41,3 +41,5 @@ Definition of middleware are scattered around but entrypoint at `packages/api/sr - Code processing the props MUST render, minimally, `` or `null`, they are processed by React - Request SHOULD contains information about "should render or not" - Props SHOULD contains information about "how to render" +- You MUST NOT remove the existing middleware from ``, however, print a deprecation warn-once, then bridge it to the polymiddleware +- You SHOULD NOT export the ``, `XXXProviderProps`, and `extractXXXEnhancer` diff --git a/AGENTS.md b/AGENTS.md index cf4fafc8de..e2eb002bbb 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -35,6 +35,7 @@ ### Typing - TypeScript is best-effort checking, use `valibot` for strict type checking +- Use TypeScript CLI instead of `tsc` - Use `valibot` for runtime type checker, never use `zod` - Assume all externally exported functions will receive unsafe/invalid input, always check with `valibot` - Avoid `any` @@ -100,6 +101,7 @@ export { MyComponentPropsSchema, type MyComponentProps }; - Use `@testduet/given-when-then` package instead of xUnit style `describe`/`before`/`test`/`after` - Prefer integration/end-to-end testing than unit testing - Use as realistic setup as possible, such as using `msw` than mocking calls +- Use `emulateIncomingActivity` and `emulateOutgoingActivity` to emulate conversation ## PR instructions From 3d2e355651147aa5f32c5e646d7402cf9f73c273 Mon Sep 17 00:00:00 2001 From: William Wong Date: Thu, 19 Mar 2026 07:56:37 +0000 Subject: [PATCH 04/51] Upgrade avatarMiddleware to polymiddleware --- .eslintrc.yml | 2 +- AGENTS.md | 6 ++ .../avatar/legacyAvatarMiddleware/addNew.html | 77 ++++++++++++++ .../addNew.html.snap-1.png | Bin 0 -> 11829 bytes .../legacyAvatarMiddleware/decorate.html | 80 ++++++++++++++ .../decorate.html.snap-1.png | Bin 0 -> 13585 bytes .../avatar/legacyAvatarMiddleware/delete.html | 53 ++++++++++ .../delete.html.snap-1.png | Bin 0 -> 9477 bytes .../legacyAvatarMiddleware/replace.html | 78 ++++++++++++++ .../replace.html.snap-1.png | Bin 0 -> 11580 bytes .../avatar/polymiddleware/addNew.html | 80 ++++++++++++++ .../polymiddleware/addNew.html.snap-1.png | Bin 0 -> 11546 bytes .../avatar/polymiddleware/decorate.html | 77 ++++++++++++++ .../polymiddleware/decorate.html.snap-1.png | Bin 0 -> 13018 bytes .../avatar/polymiddleware/delete.html | 58 ++++++++++ .../polymiddleware/delete.html.snap-1.png | Bin 0 -> 9477 bytes .../avatar/polymiddleware/replace.html | 77 ++++++++++++++ .../polymiddleware/replace.html.snap-1.png | Bin 0 -> 11555 bytes .../src/PolymiddlewareComposer.tsx | 20 +++- .../src/avatarPolymiddleware.tsx | 92 ++++++++++++++++ packages/api-middleware/src/index.ts | 15 +++ packages/api-middleware/src/legacy.ts | 2 + .../src/legacy/avatarMiddleware.ts | 19 ++++ packages/api/src/boot/internal.ts | 1 + packages/api/src/boot/middleware.ts | 16 +++ packages/api/src/hooks/Composer.tsx | 44 +++++--- .../src/hooks/internal/WebChatAPIContext.ts | 2 - .../api/src/hooks/useCreateAvatarRenderer.ts | 41 ++++--- .../createAvatarPolymiddlewareFromLegacy.tsx | 89 ++++++++++++++++ packages/bundle/src/boot/actual/middleware.ts | 18 +++- packages/component/src/Activity/Avatar.tsx | 2 +- packages/component/src/Composer.tsx | 11 +- .../src/Middleware/Avatar/DefaultAvatar.tsx | 62 +++++++++++ .../Avatar/createCoreMiddleware.tsx | 100 +++++------------- .../hooks/useRenderActivityProps.ts | 28 +++-- 35 files changed, 1027 insertions(+), 123 deletions(-) create mode 100644 __tests__/html2/middleware/avatar/legacyAvatarMiddleware/addNew.html create mode 100644 __tests__/html2/middleware/avatar/legacyAvatarMiddleware/addNew.html.snap-1.png create mode 100644 __tests__/html2/middleware/avatar/legacyAvatarMiddleware/decorate.html create mode 100644 __tests__/html2/middleware/avatar/legacyAvatarMiddleware/decorate.html.snap-1.png create mode 100644 __tests__/html2/middleware/avatar/legacyAvatarMiddleware/delete.html create mode 100644 __tests__/html2/middleware/avatar/legacyAvatarMiddleware/delete.html.snap-1.png create mode 100644 __tests__/html2/middleware/avatar/legacyAvatarMiddleware/replace.html create mode 100644 __tests__/html2/middleware/avatar/legacyAvatarMiddleware/replace.html.snap-1.png create mode 100644 __tests__/html2/middleware/avatar/polymiddleware/addNew.html create mode 100644 __tests__/html2/middleware/avatar/polymiddleware/addNew.html.snap-1.png create mode 100644 __tests__/html2/middleware/avatar/polymiddleware/decorate.html create mode 100644 __tests__/html2/middleware/avatar/polymiddleware/decorate.html.snap-1.png create mode 100644 __tests__/html2/middleware/avatar/polymiddleware/delete.html create mode 100644 __tests__/html2/middleware/avatar/polymiddleware/delete.html.snap-1.png create mode 100644 __tests__/html2/middleware/avatar/polymiddleware/replace.html create mode 100644 __tests__/html2/middleware/avatar/polymiddleware/replace.html.snap-1.png create mode 100644 packages/api-middleware/src/avatarPolymiddleware.tsx create mode 100644 packages/api-middleware/src/legacy/avatarMiddleware.ts create mode 100644 packages/api/src/legacy/createAvatarPolymiddlewareFromLegacy.tsx create mode 100644 packages/component/src/Middleware/Avatar/DefaultAvatar.tsx diff --git a/.eslintrc.yml b/.eslintrc.yml index 0ac026ba64..eb12c3c9d9 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -55,7 +55,7 @@ overrides: no-unused-vars: off '@typescript-eslint/no-unused-vars': - error - - argsIgnorePattern: ^_$ + - argsIgnorePattern: ^_ varsIgnorePattern: ^_ no-empty-function: off diff --git a/AGENTS.md b/AGENTS.md index e2eb002bbb..b469f44c1c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,6 +23,7 @@ - Prefer uppercase for acronyms instead of Pascal case, e.g. `getURL()` over `getUrl()` - The only exception is `id`, e.g. `getId()` over `getID()` - Use fewer shorthands, only allow `min`, `max`, `num` +- Prefer ternary operator over one-liner `if` statement ### Design @@ -108,3 +109,8 @@ export { MyComponentPropsSchema, type MyComponentProps }; - Run new test and all of them must be green - Run `npm run precommit` to make sure it pass all linting process - Add changelog entry to `CHANGELOG.md`, follow our existing format + +## Code review + +- Code should use as much immutable (via `Object.freeze()`) as possible, DO NOT trust `readonly` +- All inputs SHOULD be validated diff --git a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/addNew.html b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/addNew.html new file mode 100644 index 0000000000..a0d557c4da --- /dev/null +++ b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/addNew.html @@ -0,0 +1,77 @@ + + + + + + + + + + + +
+ + + diff --git a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/addNew.html.snap-1.png b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/addNew.html.snap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..c716774beed621211f6518d4c3b9d669190dab9e GIT binary patch literal 11829 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 + + + + + + + + + + +
+ + + diff --git a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/decorate.html.snap-1.png b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/decorate.html.snap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..d12ac4461a5d0c7aa0ea828d79dd20eff4a21ca7 GIT binary patch literal 13585 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 Q@E5WdN}A8$3a>)`2U~?-?f?J) literal 0 HcmV?d00001 diff --git a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/delete.html b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/delete.html new file mode 100644 index 0000000000..18229e4737 --- /dev/null +++ b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/delete.html @@ -0,0 +1,53 @@ + + + + + + + + + + + +
+ + + diff --git a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/delete.html.snap-1.png b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/delete.html.snap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..b947953c522a4fc13dbd342e41243915e0486e9f GIT binary patch literal 9477 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 literal 0 HcmV?d00001 diff --git a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/replace.html b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/replace.html new file mode 100644 index 0000000000..e71ab23198 --- /dev/null +++ b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/replace.html @@ -0,0 +1,78 @@ + + + + + + + + + + + +
+ + + diff --git a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/replace.html.snap-1.png b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/replace.html.snap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..03b6aabe9ba3e40a813509a8e8ad7e9acf766b4c GIT binary patch literal 11580 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 literal 0 HcmV?d00001 diff --git a/__tests__/html2/middleware/avatar/polymiddleware/addNew.html b/__tests__/html2/middleware/avatar/polymiddleware/addNew.html new file mode 100644 index 0000000000..431e4be5bb --- /dev/null +++ b/__tests__/html2/middleware/avatar/polymiddleware/addNew.html @@ -0,0 +1,80 @@ + + + + + + + + + + + +
+ + + diff --git a/__tests__/html2/middleware/avatar/polymiddleware/addNew.html.snap-1.png b/__tests__/html2/middleware/avatar/polymiddleware/addNew.html.snap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..b371ae90094750435bb5c7dfac31572a40edeec7 GIT binary patch literal 11546 zcmeI2WmJ@3+x9_3Q2wBZfHaDrv?4i3Bi%4`C`t`d(nGg^fD+QuHMG)0cjo}o-7(bA z@ow*T-S6}1dDeP9zH8l|STnPRxvss>eICc}IImz8C27KYl=rZ(un1*kB-OC6u+6cs zZh7P10`CaBIPPI#J;0Kc6w`1?+MdC4&@h?p*bjQ}&Di`2{%|IPvBXl2}jk0M>?%g=3D8HELenI)XAYA&<8%nPh&*etS&y5=)P2c`Jp}~ zD$0JXpFOH;dd}nL&1?JTZ(h9`!uEb!g@eW5i{nkvgx&ac9_yWyE!Im0eyliRYOG#- zA}rI}cv!Fh^YMR{-q@*j}y|;s&W+>C~ zef%P5*If3KReMnA@T=QO%-0TS1qFq81=IW6E|bLHzW>O1x)eaJAH%X+chZ~pL^sRE zXl|3Ue%<{-v;un0$?rr`s2WKbT!6 zW<@57|LS(f#z>KgJUPwIuOGaB5HU7OSmFUs_#uv;L&>VQOWyhXedBFO(<>KS&104R zoG?prEOBv_rc#@ft>HEkzA%(|?H$p6at&LDtyQI;4ioIcvzXl-tY!BNypFL#>pw4@ z-{-c7XW(?64c`x^719^?MZQF>ug}h4cPPt6@R!kFc9^8VEd@qVlY*V+`!>GpT|a4?D6)*h|cy5Qp+vk%a`?$ zoQNLN`@*O5$Kmt1y;`gkpb@Nzf9*kHHFdr#cdVZMwKzw; z`k*>Mui~ihpXu6@*+;@fpRbi9dOE)|nDxf(H{sE}*=xk%kk+lVHo$C-(tK0hxGf!W z6}{A9@Y{5^ol3pRa!o1r`2gBeV_W}sdu45o-G@rA8yh|c>6GLdl_x?giu&Nxk7pc@+8 z&pu;^K`-E;uwRTyE*9L99L``Op^#wbJti{SeWy?*fDUPffi_&wuez! zj{6|972-dSDDqiI-}@C#BS_0{EBboQb&bZ#eI#2E?tgWTvG-0E;7>xwY$9Eh_ZN#K z@W{XF{GMj7JY`Bx*FQV3ZuGY23ngCAzHUw`X5DagTy-d%lA|beb9p#!=w@YXY&>3M0E(o+v@hY+ zhxUISznmw#N%26}ooxDxyl=kUrU@=827e?+dHmA-?11Kti^@vOP=++CFd4gU=3?7) zwY^zi0;Y}J$h^PN2S?rg-KKNx_4yV8akMk#+!0P=HC2HrDn01qo13;D5UQzmJF&L1 zUuX`PEMILnTTLvkJJv0Sjh1Pz^(WK3i|x;qqwLrV2UfRC%VE}srbcL{)8vHQx2aJu*a;C8uYyi0{vL-?Mx^9Q zcTB_iCM$X!GUtY_a|T6!U*xg`lv9lWsH#y#Xupf9vSh+ou~9KMb5W|J^<Yf z9NEnFY#lP;i67p5>s53ub5B`00-6sodX<}{%b}~S3a$90!^5byW%R=P(Y;vx&%xR9 zF)Uf6Yki61CGT6TXKI+^3_Z_G`WhAjsWcX$U)XehNwQPoeN=+5haVRAlUJ>0F1{OO zIjL;8+MWH#Lxg_(#;#e5wR(xjc|_5AL3}Q0-F&<(uXr}iP~ljW;RZQ3Vj*H%{8U0H zppmhVMYBLVLyC|_E6>Ub9CXNXE$RVHu9m)CTOfUV($P!svRt^ixp^}`=$KWpSefhV zGH!@@%y5=`>?ww;u!bVGdlavz{v5{1(@G^XS>u@RS*%~Jwok0xYl$uxhE)KVbnR5)`t%tNI7KJ)^m>$cP!L5o@_{=UdYs_Gl~xe>%PL zMg!xrfU8wekg&^)KDzZKBt)&C_Ud>_)(o*1-+s{59R(4#94pxPDyZnR4oloTs8Zl} zKeZh$6!3C?!5#XDIr4}@NO#TVg#i7?@CG8&?H}i@)ySmL{!#wO>uJYWoBD%vneTH& z{zb!q{n<5VhXWK77C&+gkQITd)^(UMsfJ;(tXVl&PyUB=mX9jvSQIBwi=G{ow0CQAI=I5`92_Y zGF@Rc#m$@Nb2luLg=kpYP~w@g@L6UJ6(ydiEk#s2hL!VjYBpw^=Y*8rqirxiwZ^f<RWnk+)nH@Y>F&Jaf>JOv6nhLVUUUsiof=bXP@*#6loOD+9J3M07R0wf_u}E1z zTs!gT%74Ym#$HM!cSPoE?uC4K0p1Um2S@9#@T(1wMC zd=~w3M_OE5Twi}0>>D*l^xocHXJ_Zjz`h0Y$R_Ohh?wijQ5;dO|0c-@u(j<4-`hmx z_1|F3!>IU(JljBL8Y?omNGEXGahg|t?mvg`vQ=1lygP$b%aZFiKR?>=DfY(whV6=U z+*%c%h-8$P`@xoX`dHxeM}2*L(B_lTB+f%X=Bt79RDPP^vKY>M8%kEFUHVj5xE|vT(eh^KNqh!3lb`(-QQU|NIGx6K34vqoVBI_jr+}dx`KBZ&`kL`RT z_+UI&Rf1yK-H5_2^Iem#pwsqX*+XerRE3ou-ZGKb!2lcS3zc{Ki)~0}v?h0%&0M`? z@WVXzJii9;FZxd~9K_&`g&fug2SjcP^v(a2q#YWZur=(CD!z^Iv|Lb3VYe@za60eX z`KWppGZ&H?c^r;pL1)k9@6x=V{-i3&4GP*B8c78&&1gVe?4ybGt~ij}T%>}v7R5}r zmLEQ$px&g+B~BZ;PT;ZRHUQqQPa{|ZBfo}r_%vOmN@6zfbF?IsB|Cw`pr&k+2&TT= zm#9Td(p&!K5y|91t?OZuNU%l#W;hLw*_jyaPWv;P}Z)DE~*S^M2L;RvAXkeb6@QAU{~KEKfr$1uGf$K zzsmL)#%2G7Mg*(Pw>qtXfBgRa`}_Ag_Ku-{v`=Q7cZ2Arf3RC$I8|CD+L&g^)u(jF z7|hfZ$&$pL^Xz>(b@)_7LPbRd5UFaK;#%~-4sHAclBM$#=cwn%(fkpkDkYln^ni;k zBZGJ@j@S6%`p=n|vK5$&cse2RXU;FU&X4RQ0;`NT)yWHdac4l!(K76Ealh>1)cog? znVHMbr3sq1IO{f$MA`2wrZ8SvY=a>;auB&%=JKY*dtj`T{CNg>K}i|E+}5$bRAeL) zE7D*A)uk4d2@bUnqcjnN-8NUBOugx@y>lDy0hdyW6T4o`x_NAQS(9d=JJo&KCT#z& zO3BmdZ#e|nwCAT>_V9`5x&NU}iV=!Fv{;&a`whIly*;&7<6t+T$iPEceD@CcinsO5 zbXODyvaJI-Tj!@6IgjR^(n0cMp(My48K2G7Ki z(u_ob5x${{LUhqb5tHsyI3$KOMX$<4ey+E%&ke1(u*3oghQb#|pr_vBf|B=>3)p#b zX0_HQF`nIEJ#}6?FNHBrm)qy`M6EfCus9XzEa}aTRFzIO+*BrpQJxhoe(wz-<*>Sq z$7K%uJ-c27aG)RKxl90%U8%!Ueoa@|eK=h0t6SkIb=hD1NRT98FJ+JhI#{Iv75U57NC$0P0S zDVv5ut>T}wqN4~X(qZHC@wSdl{kaL9`<@uMg-}w~Y^kW8rx(YJDH*F0v$e2`?!@&`Wy31@Ou8)gcOL;}*=&jb|%=S8KcMLcW8{O&wg{;6N_DW2$=;`+LrOx=;! zd?Pk{@dp?1D?>v=EWXnK&+Hm*K0;kwT!0{yj~iZG9u8P8W+z&Ar-p| zo^^HG+2rU6Xgdzg{&zzPL91sW&Q?w-Is+|6&}A>Rn-$26ruz$r-P*(cY7qV>@N9*0 z)(GDrd&;`e=dTrI#U=!|#F}5|YYkiGqR-;+M$F{qsL+QH- zmeZNCVmn99_ZzX9RYOH{=1{vdyr1HJi4xBn_)D2hf?nr^8P$T6sOw+Xoy?BJ>qzUS zi3d2?uMeg{L?WmK)XW@XvoTxatZ@#L<43?S)}O6XwfQu^* z=PAFHR7^Fe)JjHz}jPI`yy2Uu)IH;KBafiPbas^Fif60sQHvs;lMSWQAhF7}7 zXiKrdl!0s3_3wI1f}fBTq)uVNRPDq#@~&qNtuGFqy8ym`Ar_ zixAqS#$l8^4!lb2{AEQDVnbLbBS5t_Qms$;#$}CLY%U{^v!H;0jZbt{S|f5njf$Kq zlKIhKds~ai|DgJSCI}Glq@Ew|Ai-7w+MR}P6*_LB_E#;v$J=ti*BQ!NEiEB05pem@t*p?d|QFmsdSH(&dwE96|{4XER@v zwq>0Wk}@?TzPJQ;vT-DuDKdD6%u+l6!HQ(%OcE=<+4qMCZhqgHYiLL`8V)$wo!L@+ z1RW8{kKrivl}DU7?QCAWvy7nSFhF?on$M$N!p}_R`dkm)O^C|*)!ZYhof3F`aVUsM zNwc(FFLo-U`j03N^Vm}g-sD9}_9gHn+vRlqlA6+p?JyxOr@1x4qWxyI5(ur`QhT0F zIujI7JSh}0&cvP=a7hX3Wl&|C z2A7?s{ug1XQc}oHz8jJ_VB%)tf}wIjq=L9>pOwOr!Kzi{a6LP?F_MF0RjQt&WHncB zVDc!|YFH?6^juc=siNkR?KPjZLi}P60ii8kyAE`6u)!DuJNe6d%o!}5_=FOO$9a(* zfV6n6CXddyisziBtU~;_e`xs`IZ8V6aTBFC`y@PvqzDoaE+TaEk~be~4wV6`1tW6k zYR&13kwoa2A1${AlTaQdA8&Q>+051=;KCpqV_7ke)A_*o+ic)iu0#laG?-gh!+tLo zmw?P%TY8BzB;t^-NCS!)H%X8Zid1cRAzQ54$3af9!K&R^W!E*=nnsruD9tYJReqAx z!(orv#6^yL#3%abFL(c6R93t8)6GG0qaYtp*^!(=0E`4O2`xe8A`a5QnVa)CF}Tyt z#&enXv-$Uca6VTikww^&OG_EWNS^w0nq#0gDToS^=StfPoTTPQ((K=5qnPrz5ZPh0 zh)8kbJ+GS+uNp0+I-$17BuH;I-mjz8q?y{_A-WPilhUS{YS#UR8@thHXqV%uVGK26 zoL3M`jQn7Ug$K5$LrQG@wiPSLZ82kt=DbMiGd#Pw}a z88l~ew-bqA)YU{h;na+sULD^V>g~oJ1u6Yjk@TOco5DRT{Rk`t{tI1{$DU7*bxUA1 zJ*TOtEmm5Zhug_!KF5Xm(#ag%cJp700f=mFP4SoC9qY3Fd17kOPJDvHI=(V@*Vyvz z82b$Ao8z>pRN7#i2N3S%QrF*Z=N7S0TCZtmSE8*B_+29U*5v{8MWoiKTnm@;DeT`! zc349siVt6hlb&LsfYgfgD*Kxv z$nZXw0|EdNe{(qAvzkXZ3`|N0DXUTR0xwz5f3G1Hu;y1h+Nm zgy0TMzPR_P`5(~H(UFlkfea)1#3;qGE0Pg3SZD?lI2^ilAG;#a^%uK>=-MbC-5{U{ zqjI(cO>`4 z-w-{jz{2{c^6zs2MDzkQYXBE7uP@Nhd#c(lbLuGxz!90dt|330RRbquZVc34%h1(? z_=cQNA0W}a*sF^ZtwLSst26-slLbZ%*FV_xl0^7nA6F5Ny{LV0WR!M7f#=caa6-@4 z;So}nfsB-!jL02YcT3!ZLXld~sQ_e@KDgY40x%tO!5|`WFX~2@VcU;Lt5I2Vmp0 z{U^;+G2kBQy+8#EFvY$ccRG9(8S&~M-XIBwfLp~Et*jrd~hi@*8{-S^3gAbQpNnJtgD)^J54^#Ejs}UX!64g3JRJ7?tzp= z<1wH0^yX+jjkkXL*kYWJn^UQA8?D#nKH%0(Q*rU;0-fJQwFh!|^n9h|{2;JaFVyAX zp-%(WM3`LYNt7vtm2933KjE5fS0#tpK)#Bh(!XDL}R+ zw_oJ8TfO!}&)N=anA`L66j=B?30q(R|H6bx-q){)+~9qXto_|f9|4i8qY)6f7>ree zEENn)wiLm1t;S(v7}%%->mMx8ZfuzW5MlBFm8B7MQi$iu0?~@r87aFi$^_Tm7L4v# z_%$Z0j)vvyB9_fM@DAlKTt~q1Kmxa4#|heSCTmfZ_?6$3HIn`5Q)A#K{xWtfy&=`J zsJjp0=%vTp=HF^$l!Y)F@A|-kwa}ptr2wuICcTMG%V$8Sd_qjy6>L-jx}+bV7-3cG!rHK{UJ z?*U?&)1AsW*xBcmZczRTLQTc>=W;!<%<8M4YpHX)5m-`KEr4rBC|Kgx0_!__2@-iX(8b^;a4Q4d$>j(ArS)W}v7qPS9E{idHp=HuV!zC=k6oS4_xkQ1a6K8{7T? zhIJU25Be0yvM6K;j1*RY({=@$Yg4=5etLQeHk(=Oh)Zem&QNIg#6(DjfREuWJO;E{ z6f!Rs1LjRzsJx7gl9Cc|Qh-55T8m;jd;S|AqTLg4vm&G5hB;x0#~bvHo`}P5|al&B}P1Q@1>#vFQW3);V;2t zQS}!xNd%F=YjqClll2~{*LlRIw#PyMc{Dv>!K}(<0GZrI*qH|T4cRSjpe*|5-lGPq zDl)`4+ROol2%oPr2wkIAElCTJo>%9V#dVqkeoE5!m}eZWMJZkx`x}~Z)*VGw5(H@c zeBnSCsRUO2x4$R+6!xf5nuKAPC0R6bZO09q^WsZ@fH}|=63v6`09tHlkmht< zC&xIG)u~1KliyCf@UB%Y&^1WKsP*S-hrtI`yLBL^EVopAQLFLp^R;O}_bP%UzdW6+ z`|4z_Sj+GF4_Jj5fE;fQdtVb$@uECQwPC{R6C>_I@^XBm6(GJVG7}w$@NIGP7ZY~u zjCX(!5)25A++P1DP1JR-32!vobGx(yRWd4~ad#N7LERr;g>Qpfi1p=yZE!#W;Eerq zFI3#v1_|)F(TprCa(G{V;s+GuM2Iq|y zhLqHCslX23+NCZ=*Rc5LtMo&>tn>(-6Z1J=~Fu!($Bq_nOPclUU;6e zyRXhHiT6G7tr=&sjG7+fGm-qiGt)eRR9)}um&vc`T;_cm4PchHv+J}Plo}vP8ciNM z<>Qgo&)OEhg+H(o%gY=Kc`7@Qd`pkrHTf(`^F?iqY$`H3Fw-(w`DQ$mFN(;~O#?ZE zK19Bilb|^SW<=k?;VAuW=u!6|o!eTnGomspER)~p)zRF|wbno!C4D#k4!qGDdv*-< zN0otN;}{xt%=EVkKj;K;)*2!x4=mV7BAe1AH3Z#(r9lkmVW%q)PG^0fpC}{xOmjz9 zA*M5vO5o-N#uQ=m>+^~n##sZZ7TbD;Ba{Dp=GVy>Wifw(!dN{`zo0i5zZznU`csOV zTw^pwH&l?KvT47*{3I*4Q%fq=iZIRv@r;k=FgUlh_$oDd`H>D6J|{%DH>f9g!ve}? znspCvwOwSQtY>One=B|4%-^g{KQ4x4Z4%@R4dUaEDt90T8s0VCf^MMbm34*p0w2C{ zJJ}tT*Y61QmFoCC`N2m$OY=yVa82D_%8z-nYVy)&44Dl@4>|g73K*%Shvm{%)%d38Vwzy%dd~QcE=d807tf%b^WnCPAv&dI)LL8WYidPU_eaL!P}5Gsqea zKhj?hsE1=o?RvWsp<_e%64fAtiA5C<|1z<_L&l9zzL-y7cwNs)cMjP3~rS-;w5dR$%X2 zQ9wgT!PUwd4vPThX`B|*ff&yY%8b@f%j7kh$aw*-8&`vU#9IjnVy#>p#9UX(O|?T( zIkbKARv7b$dQg&-m04X}-Qf6^^yn)Zni-_?xJes9lD`c zMw~~D7p-sjrfvPge}J57<4s=1+c0;V`gSJAMoTQU=P;fwZb+(vtkn{w!=POxcaGy% z$K7ciX@g?Jx-v@|3qwvRFs{z<`>mWJyh*~+ra?BeSJDH4ePl^~(`F_NqJRW~Ka~ z3Ec*DUwKRQ!wdL(+)2gk93p|BNO8`$gt!R$T=jyQS$Oa!CiQnJEQP}DLdtuGAl{*3 z->D$&9U;D@L2@YkXgzH_35E&ba86s_&iSAnkqLUbPy9@cqq^!Lcs#*2{t$TT{GlR| z!4*n5J;D{2EPe2`lifmZne*wV%eierPTSgRoKA?6mAV<$eBm-?&bVQ&xKAgG3a~ogT&Wn-|G5P)swx=)(i40q=rxYE;sTHG3yx-;gmdb`wN$TU~*Pr(#wOI@w&O1&}y%6ggR7s z0fHWF8NaJju9F<=;HxI0lZA{mgfqvfQe%1DTIEdEj4?S{AA-wH-8+> zgkfDza~)V=fR_XFVZTP0U9NEPFOfc7dabS~8m$qmy|wle#Q*rX@bL|Ju=(aD=ARaT gFj#l~A`A|efV;d%i`cO*cn3@Nt&(Js_&eYK15V7k^#A|> literal 0 HcmV?d00001 diff --git a/__tests__/html2/middleware/avatar/polymiddleware/decorate.html b/__tests__/html2/middleware/avatar/polymiddleware/decorate.html new file mode 100644 index 0000000000..0049b0fbc4 --- /dev/null +++ b/__tests__/html2/middleware/avatar/polymiddleware/decorate.html @@ -0,0 +1,77 @@ + + + + + + + + + + + +
+ + + diff --git a/__tests__/html2/middleware/avatar/polymiddleware/decorate.html.snap-1.png b/__tests__/html2/middleware/avatar/polymiddleware/decorate.html.snap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..c3ac963ce1f017bc175aec1ac9fac50f220a61f5 GIT binary patch literal 13018 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 TSBy*1o=6`^#yhR2u1Ejq*%McWNvN zCY*zfKO97B2$fi!7;zIF^IT3RwRrxVHb5KFhmscZfmeom)4H zck!b@Y|A0+RjFk0?Io~A2V=Nnu6-gja)}5(7S)HFmY7GW+S3$^|K1=yN;|wwM^{Lq zpcy7(u%cNb*SwsjPyWWR50g-0Ty|fU6H2kMdJ&k`m^%79d$U@^OLZR$vpGOD=b7t3 zJDy43VMVh3Em(S%rIObg%K8DDpb8otjU&DVouoCqHncvWgl$(vRG#6pg=9 zr#UQw^q0Z*gV0OW5S_giv6%t+VQV^ibVuDE5tJF^nNb{avXrPj4F`NvVYa#?dP{ptL2_W5?h%FOPsyXXP|#V8 zn|&(G8Sqx3p6mHD$pW9|-8u&eXS0Mg23-<4h8!~_II=P`iXPWy=Q%ro#2!4TJV)Of zsHC*;Y0=|f8mQ1{y+O&5J2?+9G$cub;-(c0`+$YSMs4Hn*sHG?y(l$gLRGwua}NGN zseZXmup)%RQ`yv*Xl;9~ZnLGP>v3GxJ?~k{6_#%RFO}kXZFtA#npI%y9>r!~^RjM*mSLR@Q#P3_=h-*;$k2Kh{Mjh7#H&n7J&d4$VjX%~% zYRnsh3Z#RB~&<7iXqV2uzsNP3x;Vm1^ zBmdS5X8s|_2v@$pQA*GO$qy|r?r~}7=Xp1T&o(gf*nOyVE`4+m>GJ!-=pknqd9!!o zT8XTA9&7Y)n*s6uLw3D79rM+q^Ffi4VkUU=Qwqcqa-mppAl!TvnDS8}UHr1&{THV> z8ch*YDcmN73m+-PJaL|LfdGba*{qwww6s`yM2`jvEg_i!v>7dx#fqFR6wAdP`CgG% zoL(5_!CUE>xt_roa}yhC%iNo=A5pX_#1wH*CBv1=jz*%4qF!YN%otYW=^xcCZDg6B zqo0zBGKai1Dk(7f_8GacG=`626%B)+O2bM*3q7mpJ=ONBZOi({zVL~A_SmDnMq?(f z2et(1v5XAuZdMII^VK+sC@>||A}_za(8a`nKMdGk{6~O@G}2Q`09h;K(F-}V;Pse2 z`7Q=<-Ov!9-@a`or)PC>0+xGhJfG5sLTX*E{6VS$*#!eL4W$&(7+$H4s{pBulHxST z$%@T3l=l3d4POND89) zZn{6^KCs4LWZaUAGJ7I&vUX>b-EJs1+!&IN`iOzBP~T5ac<(hodvO9DJP*d&{ZH$Bmgqu9u+lv;7|Wl{^x9F>kWU zLypsW;gSFRZ@)>KeO))DYvtQ5_#noBElg=j)0^UN&!Fgsw0usDYY)z(F*e!*;iVi) z-sX~>sF)kqkA+`}PGU3<@O2{eC7fkZz#cr5sMd=0_0}%V767V&e-d*^(o*PoBoJaV zfrn<9o|sW3LeNK~m}e{gVCw|5LM{o@$-A!LuoQ!PAJ(a9tMz=fidoqX%kVzK$exIhz{0D?$7q)5FN7Ti+~9 zyjsi6x8mNvze;hbv@-|a+ + + + + + + + + + + +
+ + + diff --git a/__tests__/html2/middleware/avatar/polymiddleware/delete.html.snap-1.png b/__tests__/html2/middleware/avatar/polymiddleware/delete.html.snap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..b947953c522a4fc13dbd342e41243915e0486e9f GIT binary patch literal 9477 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 literal 0 HcmV?d00001 diff --git a/__tests__/html2/middleware/avatar/polymiddleware/replace.html b/__tests__/html2/middleware/avatar/polymiddleware/replace.html new file mode 100644 index 0000000000..c937ffdb99 --- /dev/null +++ b/__tests__/html2/middleware/avatar/polymiddleware/replace.html @@ -0,0 +1,77 @@ + + + + + + + + + + + +
+ + + diff --git a/__tests__/html2/middleware/avatar/polymiddleware/replace.html.snap-1.png b/__tests__/html2/middleware/avatar/polymiddleware/replace.html.snap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..2f8f30ac89ed083cf53633377e4d8219441ff427 GIT binary patch literal 11555 zcmeHtXH*mIzHg8hQ529Sf)vpgK@gDMqzfoWl@KWb3n;xAdKE+z1f&Z{uStL?RZ0S= zfP(ZUHMCGdFQF%#$8*m9aL>JauXR4&wf2_~GFg+EdFKDC^VU#bo1Tu74g!JD-@ALq z7y_ZPgFsG&oH+$PQTFlNfIu!l?%h!{@%gwiaTZ|$&1~D$J#*>(r|>ILHy_iwKW0)> zH8P^IjkqYUBRsk&n2tb;xTx;gzf9#x)Vs*BCv!zmu>Gptd+3O5Twnx5{IB!sSNKx1 zd?lq*RpSqzOWNYH5)!tFgBC(bb&cNZCxt@IH*VZufZPn_hFoIeg8Vwe0D1NoEkrVu zI)tN{s_ESnM;8u25M<=r5*(h@Zf^zBRSuk%pI316_V)HB2`>ox zy{Esuy75!r%|=n8Z)@hM&)77Zj;WhgLufDy*dRVECu&tEC*d$RKzac05=69?a(Ihw zj_=3JMzM>mLH=T}C>7qdbgK6rCES({KnQXhMtDL_MexZni}6pM^perBC0?~Uv@4t= zP+D)usaJe*r$sJR&i~*{p*7{PLWU_qsJ`N-K9sxYh{hO-7KJUdGN@kJ5SEL{Qc^}t z8>X~nn(f?21XNNRP93muUCY(7{DNpEe14VxN?f>24nku!)cje@1;0bz56AU{gzM89 zZrE~j(Ekw&{zxwLz1;6Z*aU-xIlogI+^Xrc^y|ieZHcf5{ppC z7$7`cpTt^J+QqpLBH4r^S#L12u_Ybg5(ErzL=?J#AOuAX}bNI5SPuXAEJMlvgHuD=Q)pgK2J)8)davx8P76omKp@eyOTpm zN}RhJrLKlKFFSOu3(%ig#~rQBv_#2LcMiJqFhg%11YIY=x zcwVI$xfXldV{7hS>G2qzQW*AU&0^h-_cs|nb!1H086$sgRDY{!b84KyzWrIfmosPJ z_EFKh%z3PuUDWdTr^jKOnHSe;7c%GO&M(9c5G%2x8{pVK`H>vh)Yj^j%YOgfaqaHU zd3~OvFaKUbVq)S#rhl2w=8Q#+ONRW5`R{L8z`IiVI?v_8a}NN$sJ;iw*&S!z>hgpfNv@`iAI?v{TkbN z6~nSa5D9J|&mJi^h)tY^s-w?4iGQ;B9A8))KTgL$I)gCkT%26$FA_e-N;UcXe(~Q% zXw%Ye<)dGY@DzVCX;=(iw=-nnnsn35Shh$ny|511&H+~8Me6A1rxAVmmbD({R$tt5 zMk{7if99rN(~dEbwP{bhu{Y_D(e0GrF4fOaFgJzWRbqE8DMp!Bq3W19qQzKM>B1e$ zYPCApgiQxxI#R?MSF6Xg-d)Ohbl71{$tB6+11fYH=;Az=hmhK{As>I{w&g@VyS{hm zz*Yam+gbiIVJbBYS05B`sGX$FsPv*(BZGmgyjmn4)!|K?3*J6iDqpXM#pT3>t|!<# z3=|tR1_f53-^ElrkI6{Oi%H+1CxI0ltCd{7A)s^~{Ev;z&d!!`9^GFXERS#T?mx%c zE1Dz(HFnr{v6`&k9QT=xwsLqQ8&~OyR}REC_*Tq(t4STk-}4u}GFHCmZXyI-`V}rI zDl8UA?%NUVFDlFO+e%58c$OGCP=T<(E@m$M~JJuf`U1Wf`BuZ{#vvX z7Z;~XsdOAbVNq)HCVqGQFL=`RWtzNwznjmmlei&rRQQUlf=e;v+$xS|=H<=W6%`9R z_H9y4E@xl}ro?E>Ci00yyt9*?L5gL1$R}Gg$JK6ZxV5ySF}O6Z0=leJr>wHu$lZ}_ zwV{fRC5HI2CE^FptuI`1frp6EyxM_%L%U>AxWX#juTr!sZ!UzZ<4N&M@Z}&1df`ZR z$y)4YR3pR2>synstkysepT3WF<6k}(8o4x*cfC$@qjmC<-c=7b-GQDSG{mNB$MOtL z6&U4db*T$L$x!~YcutZZ!X|~9Gk$+QtlH^-R533dk-IKC?)I%cNjNZF#G?8>9@9wi zqn&$rvDy7WLApd8`k->2rSYUOzPbIIum*)E_ldT;aVUx>CH6rB$-ePwjh4AVTGVR> zZq$>xrkB)v>v&Ap4=mZ5FI|DH)Rh$KLN;)ryXnRV7IHi4CNZMd?!>w^e!$$ClFV3SSAV% z(K@K@h3;X-vUD8-s4w?a&CSp}i!c{aJfZuZG-ddX)5C`!=5IFkxttk#Ei}(gCgYSJxt#(SZHwh^(MPdp3!|2R*lAVAa2P^mdBBk5xIsIww%F zafyji&%3xVuX9J9kVDdCoKY~$Bp?rI>!W5`ULXG(Boo=y@!IW`kqWp2W&vzr*svHn z;mK+Ke){0RE9vkt$@~1TTvYqQ&dGJ3(dh)z7*RTlxYg_0*GBay-qY=Tt?dt}COM7$ zmwblZL-bybZmqsPJRon*hSfCAcxzvWA4oInaVwJu*JJ13+&p8nug@#o( z+U%xnVY&8KiN4z`_Z8azkp{V zw~hsBg2zd*)q`Vox3k|~<{qaybK&*W86jq=BgP7JQrW!6U{wJodWGY^IDW`dn(+Dg zMy5cT(zM6Vr+PeNiarSThI;VDBl}rS zl)2ra8kNbNO(&_NCu%K+vPS~kSK9Sn#W#k~yr=WhP22P1Y6Xy*}BkauU#)CJpX5ox697O-s#fZ025?09K_x zcW#@(gE)Zf&C@Q*&krCC!lKy4cFC6yt%D8-VT{UuSPO8F=gjxB+yV2yQURJ-nMZRg z?k@J`O*X#E6o0B^Y-~J;f^r+4Iqq`g0)qrZ0Cv>N!=wDFhC3L>?ms88Jd8msogCdE zWoKU@sYSAjDL-lo+27wEw(>89qD=u!m|PkxgC9-$uVVqn0(#8N%_RGJXMIS!X8dCa}Z%>lnk=t$|d)0L(a>ZLpINl8`S zPnB?YcUL(%uJD+y9&_o}v5j0C)YFW`InGYhdk>ddz?Q2(NL7U8GL$>+^5=@Z zz4bE@&K|Q>%VtjW*2MFcsK4UF-MT8vcx64W{Zf%D0{Dc#5ulW;pWCZ z@6LSInT8a|rHQsfxY4q5QjN?S5@vdGG$zZ1&P^V_Ib_9oAEG`^i!6%jeL2r_dp|b# zc(yA;QTp!Y(cfK{I|SVu(sgKEqa~hLqkvdI{hk)_muAX-f9A(jPmgNG8Tf9E%LIx* z97H=7=;WiU>ju=?%HZ{tZcBaqdiBLmPz0SMA>?|tvSx3tCYv}VAUWcRy0#TApjKD! zD)ccHQ4GUmcA=T{K0j$Op)&H+;5QbL%kDYzBPUWQr9H~Nzwi(L=fyf=$Rw8gK>Fq! z7R0N|UY2&K1dM8XXSfW`e)D1W*99OX90!W0J3|(azPQgSc(0YfB~;=ZiYvhR-+KJ@ zXMzA5{p2puz1R-bmTjv9A(;61eCZ;DsE09bQ9WwS`bho13iGsc68>|tmb+=sUBS@M z(nf@b)6fvQiY&f=j5>IBB8%rG2f2<%-&@dAOggje;BOn*jbjx-k(UL32QlEDC#_{+E@U^DRina(*F5=d2$*9b?F|oVPbwjDoK>mk+ z+OObmreZ}L&Ft#oZ%q)+(LX$1LR{cdRg-lXDV|HTNf8@Zx>W0AlbpUu`$$zS<-ZM7 z5o@xSzWtDnQ=k8BL+KvGg-_!Xd%PNa74@Y_{CQ!!v38(#y2S=h8l5&%mLq<%gHhTaYFy>NU`eLE0 zKsUwfhr>q+yXNex*P<5Dz4==82CG4hZAZ9zPJM@BlC(9Z7ID(ISJw!Wu0(B*70#wh z;6tWVWw@0C_9;i}7{eTOLVHrZ_d2EDK*bhE27{-7Se$akgjYEZ7mi)IapRsw4gfja zX6t41p8uB#dhrhvq@khViX{yJpV2es4Nw>0rbUB~`}TY%(8zdZlyiTk#gHXdym?={gGLUla~}_@hBbdYE;!iSU#zn!@Nyl9vgI8 zI8G+qJIi3x2Cn;PwX^^9*KqpFGR1uMYNf*R^55D|z+hMX-v;SquN5^lH3huUb-lFn z91?fV0ljzAs$qYq)B>Qky!*^|@Xj&aWugw4PfCJ;vXRq7;NFDJE6u2j_JIJ5fO{y| z(y_70pV7$a2T<(VNcQ>}&kr;da_D}V)K9bXmu^kfuj3x97}O01UBv zlVbqq!)O_Cz*hbtE6MKLv#WrWC7!mPSCaJeDbPvssQupkKb_#~y`23Q#?PQ`wnV1I zt@K`Oe~|&~qTs29?)aXhYCw%yfxD@kyKFVVz#Mtnn(7LhmFK(Yr_1OKF90VBgL$SP zxfQ(xKOjbix4wp-OA&>mK>UVId-D;e3}U8B-HzsW~Y| zam{dCE(&n&4W?0`RS64O!B%_)xcFosssq2#%f91QG&Rr%w%W>1_h1pKN7C?N=7IQtAUFF5^O$RQ?6f>LKK8kwDACy8Qgt=^PnX1E_unoF9xX}7u!>fDmBQ)KDLriIJ>jY7{Y=ShivD7QE&Mnv zG!#*_H-WY-2wN{?7tDo&tRsJ5V`3Z^SYKgC>oESsJ%WK7+`0WgkW5zEKXAnsCJ!8K zXrjum@$o(GFVq{gk`>E}Y?p^hNgkvd4a!{)I&m~v<@)lX%de)m`Dat1Y7Q_h+&4=gZy!s~wYVf(cnGyENsv6?4fxj`o`e;J3pwZWw zm2~DV9@1M12@@R6t75f;4EjDBt5Vh+qxB~OxfCa~+S(Swy?qh5)>#jW0^_7EOSuHX zv;V`&o%otUxjH>er4s-QQ8m9@Im5^ZD`_|+qU~XR83*sG4Pcoj_j1+3N)~APx&MX_ zE&lOXmbthvS2LO@3bNX1M8bd9DOzu!fb+J`r(7M%vsK&oj`Q!V#@QY@+q)fn z*G8j#h*3qBF-%-PSO8*VNxS(vMK;=0Ck#U)@eQYo9nYO`YEJ`%lJ~{5@6ak^0qAAZ-bx^R zhzyHAMC%jppv>%c=Z+7y({`YngBI46c1BR8qn)KZ8r&W&O>e zB68gm2b&;cMzB7HOKL2iK{5)jLl{N%L18Rh(vCyF?ED9>4~#-T4V0j^a)BKOQJS6% zux?~z+*bhJr4spRmGkZm_M17cG8~ej2z@ZGD7ePbZ=Nra^n7wjg4E?+i_( zN@L7vmdkSsV^CtmAYT0a9tuKL2C@rL-h=)&KDm%kmmeY;WkP9rBeo|?cfOg^cX)uV zQ*iNWyXJZ4)CFESV((iaE4X+^=NX18kcOW5@IDyfU@TlCDuTgPaXd@pEciI_?2YaD zK-aq4GT3c|%IsUf@EZ8#BW3)dZ_0DT1}&$`)I#fDv=?qs+=o?0O`>nvP z9!37cl%*Y>N$Fohy~Yg^M7Vo6n7C9`{mKs##{PY|Hrk#+v$$i<4;M z#SN>ZQ~V2!G5^|{U6G^X4$V{j*<#%WRL*nfbP~CDeYUHuh5vho{yr&TsN;3wAPj`# z7BI&Nv=OF5<+PIjnHY6}>({SKNlE?v_povh^GNdh_ZN71d3ku&PSH0TE&eSa(AL^| zou6O+c<3Ld>=b6;E+~{|CAF#kd6kyk0}vP{YWc;m_^%ZzVf=te!L$s%77ScBc zxO8ozKI^{cY_u#8EPsg2+^#2EZFJxQ&CBY5#hi%K^qh#*s$o%(&^ zrLb!);i6{PSAHp}9YAT5Snr?kQ3&LG)1T)8=&lD2Z{Y%ufDu_Zb)lImzsM^HkO2s; z^$RY9hwlXwC5`L7oSiW=G;OJp&nrK<&$cdO8m+kLL}VR@?oWFFA_J+7;PuLRV2+$e zD@W?RF}n0Ihot3t$Q?Jx5;AymF)tS79Lpj3Y-{c(K%;J(r}#z`Ox5mYUN|t5$v4gV zYF;K+X(^rK77!KHm&Mwqa9-V!3puq4zz4YA-DF_Wqu5VKEPH*}0{EEEIVL71&ZOeQ z?8hx7W)&Ybk;VnUc`b+lyK7eqEF!qXN*?1uuXK5sRzAG*R`Wh+}BPAR4;OIbFV_0LcQBg-FjMl>R&yfkt#38z^xz^OgVnq7Lx>0esG|F za$jo0AHOLHW57uk-A`ra;tBxwHw97Mnvf96X{0<>Y4;&8w4Rdk z^1eV74qFFfsSQ8;_TvJQsnnvTEQQm!F^D|d7ApXT976L;tnqke>s@J^J6Hy5hvT{z z8<=`D9>~nd4<9~&aj3W4nvMXV{*4jVfYwbB1^e)VNJs;z3hpciRW~pzASxXtpjLjN zila6=W%1)+EpgJI{OFInrfs=ayIfXpUTHTiqOGN63KCypyHJgSXdtG1Tz_^)$T#5+1)kYZ(gvIvChhF7Zmi)RSL4j9_1 z5{)I$jr<1Q2e&^HrSN9m5=9TR%o<1DuJ0MJu0gsq7dG-1I2&Zp_8qYMnO8Z;KOKCsq*$O zNuBq;+w;B_e=vBNO;w?))zM+{vaAaNNv)+9y)2hDXZ#KT-d2Y9WbbUZ9oDNC2O37Z zzWleDwD1^KnF0rj0)f3d0JU zJY9hm_H+;tY%qD`ft;XA>VyiIx@syV((?GIVosAkag+{=f?~~Y>!*Ng{i;j`>}A1P zSf*0xa78}ifpa}*tNc#y91F@dXfG~2hzPxxLW|vK5RQ&5yFiyn%Nt+_U!stY&`;6U z#mqJ!Bk=otkb32%tVwT+*~n-6{_D{?mJUU#WO2M;(=av#)GX4Ml$hw?aFs!p%^^p# z8*VKQW#)wrpCix1i=|8R*6BH=di+SM*nZ!DYp1HV@AIx;u7%%UD+N7R&6HA*(xdgl zuJjK&Pid7d;jg6tp&&d8B&1+Yet+IzMb3`Vx7~JCj#BoPmyr)RQTrZh^2^4KW5f$L zY#WkBTZUD(PLLW@bJ3=Vg5E3q37t|dgX=qXLP_caZxV0T`7No(_li;-SS2NkSU8-? zHV+B91(yVpd$wLTkRD&YM;s==R`0O=>2iydey~MpIPfWi8sEdRX~t(N(p39x)om4( z8v1y$;N5Pp*zeVS48qvE7G@B4i@oyJQy8NXUps75(=u3M{YYSWciMXxfvV7su135U zE`yyX4+oP|GQ~Yr6PXl9pbW+4AuICqEk|e3oU0=HCj&W6<@(k>c_yB7k|WozglW7j z4%!DnwMoGP+B>PldR^x$6Xl$>X)k3S@JpO||wxK5UA#-MaK>f0XfpjjBRVZrF-iUW0a+yRlI!{_18y?n; zjEdU6s=8E|qcb{tMDhA@Qp7;>zRb6-oR~BvJXur_w4ABrk9axo5IW383Wf>~K9oy{ zd2Nu5Q#5@_NfL&kbcz^!N4H+eCQZqEt$eVWakxy!S@oRM7LcN|x=7*_En0hb{Q<&_ zbP$O37C}!=k7*gy9N{0wJ<)9B!NXC3KEdoM!inq(X?4`N>DP4dNJxfB-X-!UPK%|s z;r#*teL_}5ZPVDL$YtzI?Rt?ZwjZ7P)=Kb@De>B*u$Br^Xk!vy2#z{hOHhZ_nx-f3 zo#BLzZ_fIm=5lWC<1brZrLfFCEk?1K=de9BP9wR#g_X;sJ9dW}VP1N?W!8;WEqv0q z=}Chdlffr}Ns^u-P{Cq`IcZ7?vL^VXt66^dlE56b^}d%-!uw zTsoDFRG?Rda?rQ3odfT_WEWts9IOo4CEsH#j zIeQmgJjma_5+cE$7v|Wfw)(fTK02D7=k~)=mz~94g(~wj*~mDsxG47+5T-m;FZj@Y zHI2usRy*T9f1>%yuT)8>(%{qOo}4h<(sACUm!vT?1vc_>F5he3q2Z)%gQvLw!Sk`%@1^8avPYb(PTWlfy+MVE`_-ZPtj^N%J= z9gNm{yTa^>o5bz={$`W-)1F!vx8CHe-LOCVvg>k@kFR@+dXWBa^ZM4Gll!K_SEFB5 z^_0OCTOv$RlIvUHt@a>QFfD>BZ6Nwn activityEnhancers.map(enhancer => () => enhancer), [activityEnhancers]); + const avatarEnhancers = useMemoWithPrevious>( + (prevAvatarEnhancers = []) => { + const avatarEnhancers = extractAvatarEnhancer(polymiddleware); + + // Checks for array equality, return previous version if nothing has changed. + return prevAvatarEnhancers.length === avatarEnhancers.length && + avatarEnhancers.every((middleware, index) => Object.is(middleware, prevAvatarEnhancers.at(index))) + ? prevAvatarEnhancers + : avatarEnhancers; + }, + [polymiddleware] + ); + + const avatarPolymiddleware = useMemo(() => avatarEnhancers.map(enhancer => () => enhancer), [avatarEnhancers]); + const errorBoxEnhancers = useMemoWithPrevious>( (prevErrorBoxEnhancers = []) => { const errorBoxEnhancers = extractErrorBoxEnhancer(polymiddleware); @@ -75,7 +91,9 @@ function PolymiddlewareComposer(props: PolymiddlewareComposerProps) { return ( - {children} + + {children} + ); } diff --git a/packages/api-middleware/src/avatarPolymiddleware.tsx b/packages/api-middleware/src/avatarPolymiddleware.tsx new file mode 100644 index 0000000000..d389a98366 --- /dev/null +++ b/packages/api-middleware/src/avatarPolymiddleware.tsx @@ -0,0 +1,92 @@ +import { validateProps } from '@msinternal/botframework-webchat-react-valibot'; +import { type WebChatActivity } from 'botframework-webchat-core'; +import React, { memo, useMemo } from 'react'; +import { any, boolean, custom, object, pipe, readonly, safeParse, type InferInput } from 'valibot'; + +import templatePolymiddleware, { + type InferHandler, + type InferHandlerResult, + type InferMiddleware, + type InferProps, + type InferProviderProps, + type InferRenderer, + type InferRequest +} from './private/templatePolymiddleware'; + +// This is for bridging legacy AvatarMiddleware, will be removed when AvatarMiddleware is removed. +// Customization developers should request access to styleOptions themselves someway, says, `polymiddleware={[createCustomAvatarPolymiddleware(styleOptions)]}`. +const __INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol = Symbol(); + +const { + createMiddleware: createAvatarPolymiddleware, + extractEnhancer: extractAvatarEnhancer, + Provider: AvatarPolymiddlewareProvider, + Proxy, + reactComponent: avatarComponent, + useBuildRenderCallback: useBuildRenderAvatarCallback +} = templatePolymiddleware< + { + readonly [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: any; + readonly activity: WebChatActivity; + readonly fromUser: boolean; + }, + { readonly children?: never } +>('avatar'); + +type AvatarPolymiddleware = InferMiddleware; +type AvatarPolymiddlewareHandler = InferHandler; +type AvatarPolymiddlewareHandlerResult = InferHandlerResult; +type AvatarPolymiddlewareProps = InferProps; +type AvatarPolymiddlewareRenderer = InferRenderer; +type AvatarPolymiddlewareRequest = InferRequest; +type AvatarPolymiddlewareProviderProps = InferProviderProps; + +const avatarPolymiddlewareProxyPropsSchema = pipe( + object({ + [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: any(), + activity: custom>(value => safeParse(object({}), value).success), + fromUser: boolean() + }), + readonly() +); + +type AvatarPolymiddlewareProxyProps = Readonly>; + +// A friendlier version than the organic . +const AvatarPolymiddlewareProxy = memo(function AvatarPolymiddlewareProxy(props: AvatarPolymiddlewareProxyProps) { + const { + [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: styleOptions, + activity, + fromUser + } = validateProps(avatarPolymiddlewareProxyPropsSchema, props); + + const request = useMemo( + () => + Object.freeze({ + [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: styleOptions, + activity, + fromUser + }), + [activity, fromUser, styleOptions] + ); + + return ; +}); + +export { + __INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol, + avatarComponent, + AvatarPolymiddlewareProvider, + AvatarPolymiddlewareProxy, + createAvatarPolymiddleware, + extractAvatarEnhancer, + useBuildRenderAvatarCallback, + type AvatarPolymiddleware, + type AvatarPolymiddlewareHandler, + type AvatarPolymiddlewareHandlerResult, + type AvatarPolymiddlewareProps, + type AvatarPolymiddlewareProviderProps, + type AvatarPolymiddlewareProxyProps, + type AvatarPolymiddlewareRenderer, + type AvatarPolymiddlewareRequest +}; diff --git a/packages/api-middleware/src/index.ts b/packages/api-middleware/src/index.ts index 9e0a8aeb8e..86603d221f 100644 --- a/packages/api-middleware/src/index.ts +++ b/packages/api-middleware/src/index.ts @@ -12,6 +12,21 @@ export { type ActivityPolymiddlewareRequest } from './activityPolymiddleware'; +export { + __INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol, + avatarComponent, + AvatarPolymiddlewareProxy, + createAvatarPolymiddleware, + useBuildRenderAvatarCallback, + type AvatarPolymiddleware, + type AvatarPolymiddlewareHandler, + type AvatarPolymiddlewareHandlerResult, + type AvatarPolymiddlewareProps, + type AvatarPolymiddlewareProxyProps, + type AvatarPolymiddlewareRenderer, + type AvatarPolymiddlewareRequest +} from './avatarPolymiddleware'; + export { createErrorBoxPolymiddleware, errorBoxComponent, diff --git a/packages/api-middleware/src/legacy.ts b/packages/api-middleware/src/legacy.ts index c9405239c4..db6fbf25b5 100644 --- a/packages/api-middleware/src/legacy.ts +++ b/packages/api-middleware/src/legacy.ts @@ -6,3 +6,5 @@ export { } from './legacy/activityMiddleware'; export { type LegacyAttachmentMiddleware, type LegacyRenderAttachment } from './legacy/attachmentMiddleware'; + +export { type LegacyAvatarMiddleware, type LegacyAvatarRenderer } from './legacy/avatarMiddleware'; diff --git a/packages/api-middleware/src/legacy/avatarMiddleware.ts b/packages/api-middleware/src/legacy/avatarMiddleware.ts new file mode 100644 index 0000000000..82dabcf71d --- /dev/null +++ b/packages/api-middleware/src/legacy/avatarMiddleware.ts @@ -0,0 +1,19 @@ +// TODO: This is moved from /api, need to revisit/rewrite everything in this file. +import { type WebChatActivity } from 'botframework-webchat-core'; +import { type ReactNode } from 'react'; + +type LegacyAvatarComponentFactoryArguments = { + readonly activity: WebChatActivity; + readonly fromUser: boolean; + readonly styleOptions: Readonly>; +}; + +type LegacyAvatarRenderer = false | (() => Exclude); + +type LegacyAvatarEnhancer = ( + next: (args: LegacyAvatarComponentFactoryArguments) => LegacyAvatarRenderer +) => (args: LegacyAvatarComponentFactoryArguments) => LegacyAvatarRenderer; + +type LegacyAvatarMiddleware = () => LegacyAvatarEnhancer; + +export type { LegacyAvatarMiddleware, LegacyAvatarRenderer }; diff --git a/packages/api/src/boot/internal.ts b/packages/api/src/boot/internal.ts index 1deec63da8..add882acb8 100644 --- a/packages/api/src/boot/internal.ts +++ b/packages/api/src/boot/internal.ts @@ -1,3 +1,4 @@ +export { __INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol } from '@msinternal/botframework-webchat-api-middleware'; export { default as LowPriorityDecoratorComposer } from '../decorator/internal/LowPriorityDecoratorComposer'; export { default as usePostVoiceActivity } from '../hooks/internal/usePostVoiceActivity'; export { default as useSetDictateState } from '../hooks/internal/useSetDictateState'; diff --git a/packages/api/src/boot/middleware.ts b/packages/api/src/boot/middleware.ts index 8d42eb1069..a38e239327 100644 --- a/packages/api/src/boot/middleware.ts +++ b/packages/api/src/boot/middleware.ts @@ -16,6 +16,20 @@ export { type ActivityPolymiddlewareRequest } from '@msinternal/botframework-webchat-api-middleware'; +export { + avatarComponent, + AvatarPolymiddlewareProxy, + createAvatarPolymiddleware, + useBuildRenderAvatarCallback, + type AvatarPolymiddleware, + type AvatarPolymiddlewareHandler, + type AvatarPolymiddlewareHandlerResult, + type AvatarPolymiddlewareProps, + type AvatarPolymiddlewareProxyProps, + type AvatarPolymiddlewareRenderer, + type AvatarPolymiddlewareRequest +} from '@msinternal/botframework-webchat-api-middleware'; + export { createErrorBoxPolymiddleware, errorBoxComponent, @@ -31,3 +45,5 @@ export { } from '@msinternal/botframework-webchat-api-middleware'; export { default as createActivityPolymiddlewareFromLegacy } from '../legacy/createActivityPolymiddlewareFromLegacy'; + +export { default as createAvatarPolymiddlewareFromLegacy } from '../legacy/createAvatarPolymiddlewareFromLegacy'; diff --git a/packages/api/src/hooks/Composer.tsx b/packages/api/src/hooks/Composer.tsx index 3b1794d86b..877931d423 100644 --- a/packages/api/src/hooks/Composer.tsx +++ b/packages/api/src/hooks/Composer.tsx @@ -50,6 +50,7 @@ import errorBoxTelemetryPolymiddleware from '../errorBox/errorBoxTelemetryPolymi import PrecompiledGlobalize from '../external/PrecompiledGlobalize'; import usePonyfill from '../hooks/usePonyfill'; import createActivityPolymiddlewareFromLegacy from '../legacy/createActivityPolymiddlewareFromLegacy'; +import createAvatarPolymiddlewareFromLegacy from '../legacy/createAvatarPolymiddlewareFromLegacy'; import getAllLocalizedStrings from '../localization/getAllLocalizedStrings'; import { SendBoxMiddlewareProvider, type SendBoxMiddleware } from '../middleware/SendBoxMiddleware'; import { @@ -213,12 +214,15 @@ function mergeStringsOverrides(localizedStrings, language, overrideLocalizedStri type ComposerCoreProps = Readonly<{ /** - * @deprecated The `activityMiddleware` prop is being deprecated, please use `polymiddleware` instead. This prop will be removed on or after 2027-08-21. + * @deprecated Use `polymiddleware` instead. The `activityMiddleware` prop is being deprecated, please use `polymiddleware` instead. This prop will be removed on or after 2027-08-21. */ activityMiddleware?: OneOrMany; activityStatusMiddleware?: OneOrMany; attachmentForScreenReaderMiddleware?: OneOrMany; attachmentMiddleware?: OneOrMany; + /** + * @deprecated Use `polymiddleware` instead. The `avatarMiddleware` prop is being deprecated, please use `polymiddleware` instead. This prop will be removed on or after 2028-03-16. + */ avatarMiddleware?: OneOrMany; cardActionMiddleware?: OneOrMany; children?: ReactNode | ((context: ContextOf>) => ReactNode); @@ -467,14 +471,11 @@ const ComposerCore = ({ [attachmentMiddleware] ); - const patchedAvatarRenderer = useMemo( + const polymiddlewareForLegacyAvatarMiddleware = useMemo( () => - applyMiddlewareForRenderer( - 'avatar', - { strict: false }, - ...singleToArray(avatarMiddleware), - () => () => () => false - )({}), + avatarMiddleware + ? Object.freeze([createAvatarPolymiddlewareFromLegacy(...singleToArray(avatarMiddleware))]) + : EMPTY_ARRAY, [avatarMiddleware] ); @@ -530,11 +531,32 @@ const ComposerCore = ({ // Error box telemetry polymiddleware is special and has a much higher priority. // This guarantees telemetry is always emitted for exception and no other polymiddleware can override this behavior. errorBoxTelemetryPolymiddleware, - ...(polymiddlewareFromProps || []), + + // # Why render legacy middleware before polymiddleware? + // + // - Legacy middleware should have high priority than defaults + // - Default middleware will be upgraded to polymiddleware, however, they should have lower priority + // - Default middleware are implemented in the `component` package, and passed via `polymiddleware` props + // - They are UI, cannot be implemented in `api` package + // + // We have a few way out, either one of the followings: + // + // - Add a new `lowPriorityPolymiddleware` props for default polymiddleware, so we can put them after legacy + // - We don't want any special treatments or any prioritization system + // - We put the upgrade logics inside both `api` and `component` package + // - `component` will upgrade legacy to polymiddleware and prioritize properly + // - Spaghetti code and it is difficult to test the logic in `api` package + // - We always render legacy middleware before polymiddleware + // - Default middleware are polymiddleware, has lower priority than legacy + // + // The simplest and logical move is #3: render legacy middleware before polymiddleware. + ...polymiddlewareForLegacyActivityMiddleware, + ...polymiddlewareForLegacyAvatarMiddleware, + ...(polymiddlewareFromProps || []), activityFallbackPolymiddleware ]), - [polymiddlewareForLegacyActivityMiddleware, polymiddlewareFromProps] + [polymiddlewareForLegacyActivityMiddleware, polymiddlewareForLegacyAvatarMiddleware, polymiddlewareFromProps] ); /** @@ -555,7 +577,6 @@ const ComposerCore = ({ activityStatusRenderer: patchedActivityStatusRenderer, attachmentForScreenReaderRenderer: patchedAttachmentForScreenReaderRenderer, attachmentRenderer: patchedAttachmentRenderer, - avatarRenderer: patchedAvatarRenderer, dir: patchedDir, directLine, downscaleImageToDataURL, @@ -589,7 +610,6 @@ const ComposerCore = ({ patchedActivityStatusRenderer, patchedAttachmentForScreenReaderRenderer, patchedAttachmentRenderer, - patchedAvatarRenderer, patchedDir, patchedGrammars, patchedLocalizedStrings, diff --git a/packages/api/src/hooks/internal/WebChatAPIContext.ts b/packages/api/src/hooks/internal/WebChatAPIContext.ts index a0bc434b51..f567c3dc7f 100644 --- a/packages/api/src/hooks/internal/WebChatAPIContext.ts +++ b/packages/api/src/hooks/internal/WebChatAPIContext.ts @@ -11,7 +11,6 @@ import { createContext } from 'react'; import { RenderActivityStatus } from '../../types/ActivityStatusMiddleware'; import { AttachmentForScreenReaderComponentFactory } from '../../types/AttachmentForScreenReaderMiddleware'; -import { AvatarComponentFactory } from '../../types/AvatarMiddleware'; import { PerformCardAction } from '../../types/CardActionMiddleware'; import { GroupActivities } from '../../types/GroupActivitiesMiddleware'; import LocalizedStrings from '../../types/LocalizedStrings'; @@ -25,7 +24,6 @@ export type WebChatAPIContextType = { activityStatusRenderer: RenderActivityStatus; attachmentForScreenReaderRenderer?: AttachmentForScreenReaderComponentFactory; attachmentRenderer?: LegacyRenderAttachment; - avatarRenderer: AvatarComponentFactory; clearSuggestedActions?: () => void; dir?: string; directLine?: DirectLineJSBotConnection; diff --git a/packages/api/src/hooks/useCreateAvatarRenderer.ts b/packages/api/src/hooks/useCreateAvatarRenderer.ts index 086e985e3a..61a47f69f5 100644 --- a/packages/api/src/hooks/useCreateAvatarRenderer.ts +++ b/packages/api/src/hooks/useCreateAvatarRenderer.ts @@ -1,40 +1,37 @@ -import { useMemo } from 'react'; -import useStyleOptions from './useStyleOptions'; -import useWebChatAPIContext from './internal/useWebChatAPIContext'; - -import type { AvatarComponentFactory } from '../types/AvatarMiddleware'; -import type { ReactNode } from 'react'; +import { + __INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol, + useBuildRenderAvatarCallback +} from '@msinternal/botframework-webchat-api-middleware'; import type { WebChatActivity } from 'botframework-webchat-core'; +import { useMemo, type ReactNode } from 'react'; +import useStyleOptions from './useStyleOptions'; +/** + * @deprecated Use `` or `useBuildRenderAvatarCallback` instead. This hook will be removed on or after 2028-03-16. + */ export default function useCreateAvatarRenderer(): ({ activity }: { activity: WebChatActivity; }) => false | (() => Exclude) { const [styleOptions] = useStyleOptions(); - const { avatarRenderer }: { avatarRenderer: AvatarComponentFactory } = useWebChatAPIContext(); + const buildRenderAvatar = useBuildRenderAvatarCallback(); return useMemo( () => ({ activity }) => { const { from: { role } = {} }: { from?: { role?: string } } = activity; - const result = avatarRenderer({ - activity, - fromUser: role === 'user', - styleOptions - }); - - if (result !== false && typeof result !== 'function') { - console.warn( - 'botframework-webchat: avatarMiddleware should return a function to render the avatar, or return false if avatar should be hidden. Please refer to HOOKS.md for details.' - ); - - return () => result; - } + const renderer = buildRenderAvatar( + Object.freeze({ + activity, + fromUser: role === 'user', + [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: styleOptions + }) + ); - return result; + return renderer ? (): ReactNode => renderer({}) : false; }, - [avatarRenderer, styleOptions] + [buildRenderAvatar, styleOptions] ); } diff --git a/packages/api/src/legacy/createAvatarPolymiddlewareFromLegacy.tsx b/packages/api/src/legacy/createAvatarPolymiddlewareFromLegacy.tsx new file mode 100644 index 0000000000..43343f80ff --- /dev/null +++ b/packages/api/src/legacy/createAvatarPolymiddlewareFromLegacy.tsx @@ -0,0 +1,89 @@ +import { + __INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol, + avatarComponent, + createAvatarPolymiddleware, + type AvatarPolymiddleware +} from '@msinternal/botframework-webchat-api-middleware'; +import { type LegacyAvatarMiddleware } from '@msinternal/botframework-webchat-api-middleware/legacy'; +import { composeEnhancer } from 'handler-chain'; +import React, { Fragment, memo, type ReactNode } from 'react'; +import { custom, function_, never, object, optional, pipe, readonly, safeParse, type InferInput } from 'valibot'; + +type LegacyAvatarRenderFunction = () => Exclude; + +const legacyAvatarBridgeComponentPropsSchema = pipe( + object({ + children: optional(never()), + renderFn: custom(value => safeParse(function_(), value).success) + }), + readonly() +); + +type LegacyAvatarBridgeComponentProps = Readonly< + InferInput & { children?: never } +>; + +/** + * Bridge component for the legacy avatar middleware. + * Renders the result of the legacy render function. + */ +function LegacyAvatarBridge(props: LegacyAvatarBridgeComponentProps) { + const { renderFn } = props; + + return {renderFn()}; +} + +const MemoizedLegacyAvatarBridge = memo(LegacyAvatarBridge); + +/** + * Polyfill legacy avatar middleware into a polymiddleware. + * + * @deprecated Use `polymiddleware` instead. Legacy avatar middleware is being deprecated and will be removed on or after 2027-08-16. + * @param middleware An array of legacy avatar middleware. + * @returns A polymiddleware composed by legacy avatar middleware. + */ +function createAvatarPolymiddlewareFromLegacy(...middlewares: readonly LegacyAvatarMiddleware[]): AvatarPolymiddleware { + const legacyEnhancer = composeEnhancer(...middlewares.map(middleware => middleware())); + + return createAvatarPolymiddleware(next => { + const legacyHandler = legacyEnhancer(({ activity, fromUser, styleOptions }) => { + // Pass styleOptions through the polymiddleware chain via the internal runtime extension + // so downstream handlers (e.g. core middleware) can still read it. + const handler = next( + Object.freeze({ + activity, + fromUser, + [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: styleOptions + }) + ); + + // TODO: Warn if the result is wrong. Also add tests. + // if (result !== false && typeof result !== 'function') { + // console.warn( + // 'botframework-webchat: avatarMiddleware should return a function to render the avatar, or return false if avatar should be hidden. Please refer to HOOKS.md for details.' + // ); + + // return () => result; + // } + + return !!handler && ((): Exclude => handler.render({})); + }); + + return request => { + const { + activity, + fromUser, + [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: styleOptions + } = request; + + const legacyResult = legacyHandler(Object.freeze({ activity, fromUser, styleOptions })); + + return legacyResult + ? avatarComponent(MemoizedLegacyAvatarBridge, Object.freeze({ renderFn: legacyResult })) + : undefined; + }; + }); +} + +export default createAvatarPolymiddlewareFromLegacy; +export { legacyAvatarBridgeComponentPropsSchema, type LegacyAvatarBridgeComponentProps }; diff --git a/packages/bundle/src/boot/actual/middleware.ts b/packages/bundle/src/boot/actual/middleware.ts index 9641816786..39662aec03 100644 --- a/packages/bundle/src/boot/actual/middleware.ts +++ b/packages/bundle/src/boot/actual/middleware.ts @@ -13,6 +13,8 @@ export { type Polymiddleware } from 'botframework-webchat-api/middleware'; +export { createActivityPolymiddlewareFromLegacy } from 'botframework-webchat-api/middleware'; + export { createErrorBoxPolymiddleware, errorBoxComponent, @@ -27,4 +29,18 @@ export { type ErrorBoxPolymiddlewareRequest } from 'botframework-webchat-api/middleware'; -export { createActivityPolymiddlewareFromLegacy } from 'botframework-webchat-api/middleware'; +export { + avatarComponent, + AvatarPolymiddlewareProxy, + createAvatarPolymiddleware, + useBuildRenderAvatarCallback, + type AvatarPolymiddleware, + type AvatarPolymiddlewareHandler, + type AvatarPolymiddlewareHandlerResult, + type AvatarPolymiddlewareProps, + type AvatarPolymiddlewareProxyProps, + type AvatarPolymiddlewareRenderer, + type AvatarPolymiddlewareRequest +} from 'botframework-webchat-api/middleware'; + +export { createAvatarPolymiddlewareFromLegacy } from 'botframework-webchat-api/middleware'; diff --git a/packages/component/src/Activity/Avatar.tsx b/packages/component/src/Activity/Avatar.tsx index 5bd9995f44..ba405241bb 100644 --- a/packages/component/src/Activity/Avatar.tsx +++ b/packages/component/src/Activity/Avatar.tsx @@ -2,7 +2,7 @@ import { validateProps } from '@msinternal/botframework-webchat-react-valibot'; import React, { memo } from 'react'; import { boolean, object, optional, pipe, readonly, string, type InferInput } from 'valibot'; -import { DefaultAvatar } from '../Middleware/Avatar/createCoreMiddleware'; +import DefaultAvatar from '../Middleware/Avatar/DefaultAvatar'; const avatarPropsSchema = pipe( object({ diff --git a/packages/component/src/Composer.tsx b/packages/component/src/Composer.tsx index 5b651bf1ec..04c421ef3c 100644 --- a/packages/component/src/Composer.tsx +++ b/packages/component/src/Composer.tsx @@ -400,7 +400,7 @@ const Composer = ({ ); const patchedAvatarMiddleware = useMemo( - () => [...singleToArray(avatarMiddleware), ...theme.avatarMiddleware, ...createDefaultAvatarMiddleware()], + () => [...singleToArray(avatarMiddleware), ...theme.avatarMiddleware], [avatarMiddleware, theme.avatarMiddleware] ); @@ -414,7 +414,14 @@ const Composer = ({ ); const patchedPolymiddleware = useMemo( - () => Object.freeze([...(polymiddleware || []), ...theme.polymiddleware]), + () => + Object.freeze([ + ...(polymiddleware || []), + ...theme.polymiddleware, + // Polymiddleware has lower priority than legacy middleware. + // Later, we should move default middleware to a "default theme." + ...createDefaultAvatarMiddleware() + ]), [polymiddleware, theme.polymiddleware] ); diff --git a/packages/component/src/Middleware/Avatar/DefaultAvatar.tsx b/packages/component/src/Middleware/Avatar/DefaultAvatar.tsx new file mode 100644 index 0000000000..57119de079 --- /dev/null +++ b/packages/component/src/Middleware/Avatar/DefaultAvatar.tsx @@ -0,0 +1,62 @@ +import { validateProps } from '@msinternal/botframework-webchat-react-valibot'; +import classNames from 'classnames'; +import React, { memo } from 'react'; +import { boolean, never, object, optional, pipe, readonly, string, type InferInput } from 'valibot'; + +import ImageAvatar from '../../Avatar/ImageAvatar'; +import InitialsAvatar from '../../Avatar/InitialsAvatar'; +import { useStyleToEmotionObject } from '../../hooks/internal/styleToEmotionObject'; +import useStyleSet from '../../hooks/useStyleSet'; + +const ROOT_STYLE = { + overflow: ['hidden', 'clip'], + position: 'relative', + + '> *': { + left: 0, + position: 'absolute', + top: 0 + } +}; + +const defaultAvatarPropsSchema = pipe( + object({ + 'aria-hidden': optional(boolean(), true), + children: optional(never()), + className: optional(string()), + fromUser: boolean() + }), + readonly() +); + +// eslint-disable-next-line react/require-default-props +type DefaultAvatarProps = InferInput; + +function DefaultAvatar(props: DefaultAvatarProps) { + const { 'aria-hidden': ariaHidden, className, fromUser } = validateProps(defaultAvatarPropsSchema, props, 'strict'); + + const [{ avatar: avatarStyleSet }] = useStyleSet(); + const rootClassName = useStyleToEmotionObject()(ROOT_STYLE) + ''; + + return ( +
+ + +
+ ); +} + +DefaultAvatar.displayName = 'DefaultAvatar'; + +export default memo(DefaultAvatar); + +export { defaultAvatarPropsSchema, type DefaultAvatarProps }; diff --git a/packages/component/src/Middleware/Avatar/createCoreMiddleware.tsx b/packages/component/src/Middleware/Avatar/createCoreMiddleware.tsx index 1b153d9933..dcd580fade 100644 --- a/packages/component/src/Middleware/Avatar/createCoreMiddleware.tsx +++ b/packages/component/src/Middleware/Avatar/createCoreMiddleware.tsx @@ -1,75 +1,27 @@ -import { AvatarMiddleware } from 'botframework-webchat-api'; -import { validateProps } from '@msinternal/botframework-webchat-react-valibot'; -import classNames from 'classnames'; -import React, { memo } from 'react'; -import { boolean, object, optional, pipe, readonly, string, type InferInput } from 'valibot'; - -import ImageAvatar from '../../Avatar/ImageAvatar'; -import InitialsAvatar from '../../Avatar/InitialsAvatar'; -import { useStyleToEmotionObject } from '../../hooks/internal/styleToEmotionObject'; -import useStyleSet from '../../hooks/useStyleSet'; - -const ROOT_STYLE = { - overflow: ['hidden', 'clip'], - position: 'relative', - - '> *': { - left: 0, - position: 'absolute', - top: 0 - } -}; - -const defaultAvatarPropsSchema = pipe( - object({ - 'aria-hidden': optional(boolean()), - className: optional(string()), - fromUser: boolean() - }), - readonly() -); - -type DefaultAvatarProps = InferInput; - -function DefaultAvatar(props: DefaultAvatarProps) { - const { 'aria-hidden': ariaHidden = true, className, fromUser } = validateProps(defaultAvatarPropsSchema, props); - - const [{ avatar: avatarStyleSet }] = useStyleSet(); - const rootClassName = useStyleToEmotionObject()(ROOT_STYLE) + ''; - - return ( -
- - -
- ); +import { __INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol } from 'botframework-webchat-api/internal'; +import { + avatarComponent, + createAvatarPolymiddleware, + type AvatarPolymiddleware +} from 'botframework-webchat-api/middleware'; +import DefaultAvatar from './DefaultAvatar'; + +export default function createDefaultAvatarMiddleware(): readonly AvatarPolymiddleware[] { + return Object.freeze([ + createAvatarPolymiddleware( + _next => + ({ + fromUser, + [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: { + botAvatarImage, + botAvatarInitials, + userAvatarImage, + userAvatarInitials + } + }) => + (fromUser ? userAvatarImage || userAvatarInitials : botAvatarImage || botAvatarInitials) + ? avatarComponent(DefaultAvatar, Object.freeze({ fromUser })) + : undefined + ) + ]); } - -export default function createCoreAvatarMiddleware(): AvatarMiddleware[] { - return [ - () => - () => - ({ fromUser, styleOptions }) => { - const { botAvatarImage, botAvatarInitials, userAvatarImage, userAvatarInitials } = styleOptions; - - if (fromUser ? userAvatarImage || userAvatarInitials : botAvatarImage || botAvatarInitials) { - return () => ; - } - - return false; - } - ]; -} - -const MemoizedDefaultAvatar = memo(DefaultAvatar); - -export { MemoizedDefaultAvatar as DefaultAvatar, defaultAvatarPropsSchema, type DefaultAvatarProps }; diff --git a/packages/component/src/Transcript/hooks/useRenderActivityProps.ts b/packages/component/src/Transcript/hooks/useRenderActivityProps.ts index 2d4041f03a..62070d0ee3 100644 --- a/packages/component/src/Transcript/hooks/useRenderActivityProps.ts +++ b/packages/component/src/Transcript/hooks/useRenderActivityProps.ts @@ -1,4 +1,6 @@ import { hooks } from 'botframework-webchat-api'; +import { __INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol } from 'botframework-webchat-api/internal'; +import { useBuildRenderAvatarCallback } from 'botframework-webchat-api/middleware'; import { type WebChatActivity } from 'botframework-webchat-core'; import { useMemo, type ReactNode } from 'react'; @@ -8,7 +10,7 @@ import useFirstActivityInStatusGroup from '../../Middleware/ActivityGrouping/ui/ import useLastActivityInStatusGroup from '../../Middleware/ActivityGrouping/ui/StatusGrouping/useLastActivity'; import isZeroOrPositive from '../../Utils/isZeroOrPositive'; -const { useCreateActivityStatusRenderer, useCreateAvatarRenderer, useStyleOptions } = hooks; +const { useCreateActivityStatusRenderer, useStyleOptions } = hooks; type RenderActivityProps = { hideTimestamp: boolean; @@ -18,13 +20,15 @@ type RenderActivityProps = { }; const useRenderActivityProps = (activity: WebChatActivity): RenderActivityProps => { - const [{ bubbleFromUserNubOffset, bubbleNubOffset, groupTimestamp, showAvatarInGroup }] = useStyleOptions(); + const [styleOptions] = useStyleOptions(); const [firstActivityInSenderGroup] = useFirstActivityInSenderGroup(); const [firstActivityInStatusGroup] = useFirstActivityInStatusGroup(); const [lastActivityInSenderGroup] = useLastActivityInSenderGroup(); const [lastActivityInStatusGroup] = useLastActivityInStatusGroup(); const createActivityStatusRenderer = useCreateActivityStatusRenderer(); - const renderAvatar = useCreateAvatarRenderer(); + const buildRenderAvatar = useBuildRenderAvatarCallback(); + + const { bubbleFromUserNubOffset, bubbleNubOffset, groupTimestamp, showAvatarInGroup } = styleOptions; const hideAllTimestamps = groupTimestamp === false; const isFirstInSenderGroup = @@ -36,10 +40,20 @@ const useRenderActivityProps = (activity: WebChatActivity): RenderActivityProps const isLastInStatusGroup = lastActivityInStatusGroup === activity || typeof lastActivityInStatusGroup === 'undefined'; - const renderAvatarForSenderGroup = useMemo( - () => !!renderAvatar && renderAvatar({ activity }), - [activity, renderAvatar] - ); + const renderAvatarForSenderGroup = useMemo Exclude)>(() => { + const fromUser = activity.from?.role === 'user'; + // Pass styleOptions through the runtime object (not typed in public request) for internal use + // by the core middleware and legacy bridge handlers. + const renderer = buildRenderAvatar( + Object.freeze({ + [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: styleOptions, + activity, + fromUser + }) + ); + + return renderer ? (): ReactNode => renderer({}) : false; + }, [activity, buildRenderAvatar, styleOptions]); const isTopSideBotNub = isZeroOrPositive(bubbleNubOffset); const isTopSideUserNub = isZeroOrPositive(bubbleFromUserNubOffset); From 446b23bb6f576be5551b7028f9f2839b9d4c54ab Mon Sep 17 00:00:00 2001 From: William Wong Date: Thu, 19 Mar 2026 09:07:57 +0000 Subject: [PATCH 05/51] Keep original request object --- packages/api-middleware/src/index.ts | 1 + .../src/legacy/avatarMiddleware.ts | 12 ++++- .../createAvatarPolymiddlewareFromLegacy.tsx | 53 +++++++++++-------- packages/api/src/types/AvatarMiddleware.ts | 5 ++ 4 files changed, 48 insertions(+), 23 deletions(-) diff --git a/packages/api-middleware/src/index.ts b/packages/api-middleware/src/index.ts index 86603d221f..80a766e350 100644 --- a/packages/api-middleware/src/index.ts +++ b/packages/api-middleware/src/index.ts @@ -42,5 +42,6 @@ export { } from './errorBoxPolymiddleware'; // TODO: [P0] Add tests for nesting `polymiddleware`. +export { __INTERNAL_DO_NOT_USE__legacyAvatarMiddlewareOriginalRequestSymbol } from './legacy/avatarMiddleware'; export { default as PolymiddlewareComposer } from './PolymiddlewareComposer'; export { type Polymiddleware } from './types/Polymiddleware'; diff --git a/packages/api-middleware/src/legacy/avatarMiddleware.ts b/packages/api-middleware/src/legacy/avatarMiddleware.ts index 82dabcf71d..6899783972 100644 --- a/packages/api-middleware/src/legacy/avatarMiddleware.ts +++ b/packages/api-middleware/src/legacy/avatarMiddleware.ts @@ -1,8 +1,14 @@ // TODO: This is moved from /api, need to revisit/rewrite everything in this file. import { type WebChatActivity } from 'botframework-webchat-core'; import { type ReactNode } from 'react'; +import type { AvatarPolymiddlewareRequest } from '../avatarPolymiddleware'; + +// Polymiddleware requires immutable request object. +// When bridging between legacy and polymiddlware, this symbol helps keeping the original object. +const __INTERNAL_DO_NOT_USE__legacyAvatarMiddlewareOriginalRequestSymbol = Symbol(); type LegacyAvatarComponentFactoryArguments = { + readonly [__INTERNAL_DO_NOT_USE__legacyAvatarMiddlewareOriginalRequestSymbol]: AvatarPolymiddlewareRequest; readonly activity: WebChatActivity; readonly fromUser: boolean; readonly styleOptions: Readonly>; @@ -16,4 +22,8 @@ type LegacyAvatarEnhancer = ( type LegacyAvatarMiddleware = () => LegacyAvatarEnhancer; -export type { LegacyAvatarMiddleware, LegacyAvatarRenderer }; +export { + __INTERNAL_DO_NOT_USE__legacyAvatarMiddlewareOriginalRequestSymbol, + type LegacyAvatarMiddleware, + type LegacyAvatarRenderer +}; diff --git a/packages/api/src/legacy/createAvatarPolymiddlewareFromLegacy.tsx b/packages/api/src/legacy/createAvatarPolymiddlewareFromLegacy.tsx index 43343f80ff..f1d3f3bea6 100644 --- a/packages/api/src/legacy/createAvatarPolymiddlewareFromLegacy.tsx +++ b/packages/api/src/legacy/createAvatarPolymiddlewareFromLegacy.tsx @@ -1,5 +1,6 @@ import { __INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol, + __INTERNAL_DO_NOT_USE__legacyAvatarMiddlewareOriginalRequestSymbol, avatarComponent, createAvatarPolymiddleware, type AvatarPolymiddleware @@ -46,37 +47,45 @@ function createAvatarPolymiddlewareFromLegacy(...middlewares: readonly LegacyAva const legacyEnhancer = composeEnhancer(...middlewares.map(middleware => middleware())); return createAvatarPolymiddleware(next => { - const legacyHandler = legacyEnhancer(({ activity, fromUser, styleOptions }) => { - // Pass styleOptions through the polymiddleware chain via the internal runtime extension - // so downstream handlers (e.g. core middleware) can still read it. - const handler = next( - Object.freeze({ - activity, - fromUser, - [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: styleOptions - }) - ); + const legacyHandler = legacyEnhancer( + ({ [__INTERNAL_DO_NOT_USE__legacyAvatarMiddlewareOriginalRequestSymbol]: originalRequest }) => { + if (!originalRequest) { + // TODO: Add a test + throw new Error('botframework-webchat: `avatarMiddleware` must not modify the request object'); + } + + // Pass styleOptions through the polymiddleware chain via the internal runtime extension + // so downstream handlers (e.g. core middleware) can still read it. + const handler = next(originalRequest); - // TODO: Warn if the result is wrong. Also add tests. - // if (result !== false && typeof result !== 'function') { - // console.warn( - // 'botframework-webchat: avatarMiddleware should return a function to render the avatar, or return false if avatar should be hidden. Please refer to HOOKS.md for details.' - // ); + // TODO: Warn if the result is wrong. Also add tests. + // if (result !== false && typeof result !== 'function') { + // console.warn( + // 'botframework-webchat: avatarMiddleware should return a function to render the avatar, or return false if avatar should be hidden. Please refer to HOOKS.md for details.' + // ); - // return () => result; - // } + // return () => result; + // } - return !!handler && ((): Exclude => handler.render({})); - }); + return !!handler && ((): Exclude => handler.render({})); + } + ); return request => { const { + [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: styleOptions, activity, - fromUser, - [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: styleOptions + fromUser } = request; - const legacyResult = legacyHandler(Object.freeze({ activity, fromUser, styleOptions })); + const legacyResult = legacyHandler( + Object.freeze({ + activity, + fromUser, + styleOptions, + [__INTERNAL_DO_NOT_USE__legacyAvatarMiddlewareOriginalRequestSymbol]: request + }) + ); return legacyResult ? avatarComponent(MemoizedLegacyAvatarBridge, Object.freeze({ renderFn: legacyResult })) diff --git a/packages/api/src/types/AvatarMiddleware.ts b/packages/api/src/types/AvatarMiddleware.ts index 351b11f9fa..50b3c3dd40 100644 --- a/packages/api/src/types/AvatarMiddleware.ts +++ b/packages/api/src/types/AvatarMiddleware.ts @@ -1,10 +1,15 @@ import { type WebChatActivity } from 'botframework-webchat-core'; +import type { + __INTERNAL_DO_NOT_USE__legacyAvatarMiddlewareOriginalRequestSymbol, + AvatarPolymiddlewareRequest +} from '@msinternal/botframework-webchat-api-middleware'; import { StrictStyleOptions } from '../StyleOptions'; import ComponentMiddleware, { ComponentFactory } from './ComponentMiddleware'; type AvatarComponentFactoryArguments = [ { + [__INTERNAL_DO_NOT_USE__legacyAvatarMiddlewareOriginalRequestSymbol]: AvatarPolymiddlewareRequest; activity: WebChatActivity; fromUser: boolean; styleOptions: StrictStyleOptions; From b808d04ed89d7dfa9fd8954861fc9a202e1609e3 Mon Sep 17 00:00:00 2001 From: William Wong Date: Thu, 19 Mar 2026 09:08:45 +0000 Subject: [PATCH 06/51] Fix ESLint --- packages/core-debug-api/src/RestrictedDebugAPI.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core-debug-api/src/RestrictedDebugAPI.ts b/packages/core-debug-api/src/RestrictedDebugAPI.ts index 79472fe7b1..8ef030a7ad 100644 --- a/packages/core-debug-api/src/RestrictedDebugAPI.ts +++ b/packages/core-debug-api/src/RestrictedDebugAPI.ts @@ -3,7 +3,7 @@ import DebugAPI from './private/DebugAPI'; import type { BaseContext, BreakpointObject, RestrictedDebugAPIType } from './types'; // 🔒 This function must be left empty. -// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars +// eslint-disable-next-line @typescript-eslint/no-empty-function const BREAKPOINT_FUNCTION = (__DEBUG_CONTEXT__: T) => {}; type AsGetters = { From 72443885e955858197b2ec9ef468f079176f3fb8 Mon Sep 17 00:00:00 2001 From: William Wong Date: Thu, 19 Mar 2026 09:11:45 +0000 Subject: [PATCH 07/51] Fix ESLint --- packages/component/src/Middleware/Avatar/DefaultAvatar.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/component/src/Middleware/Avatar/DefaultAvatar.tsx b/packages/component/src/Middleware/Avatar/DefaultAvatar.tsx index 57119de079..9a84697b0b 100644 --- a/packages/component/src/Middleware/Avatar/DefaultAvatar.tsx +++ b/packages/component/src/Middleware/Avatar/DefaultAvatar.tsx @@ -29,7 +29,6 @@ const defaultAvatarPropsSchema = pipe( readonly() ); -// eslint-disable-next-line react/require-default-props type DefaultAvatarProps = InferInput; function DefaultAvatar(props: DefaultAvatarProps) { From 1ee89561e7283c67ac1073ce35197354a9c75823 Mon Sep 17 00:00:00 2001 From: William Wong Date: Thu, 19 Mar 2026 09:20:12 +0000 Subject: [PATCH 08/51] Move to macOS 26 --- .github/workflows/pull-request-validation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull-request-validation.yml b/.github/workflows/pull-request-validation.yml index 5e14e26873..370f51e8ee 100644 --- a/.github/workflows/pull-request-validation.yml +++ b/.github/workflows/pull-request-validation.yml @@ -101,7 +101,7 @@ jobs: strategy: matrix: os: - - macos-latest + - macos-26 - ubuntu-latest - windows-latest runs-on: ${{ matrix.os }} From d431dd36f849d9252caddbd3e7658f5b5c182037 Mon Sep 17 00:00:00 2001 From: William Wong Date: Thu, 19 Mar 2026 09:33:50 +0000 Subject: [PATCH 09/51] Fix legacy avatar bridge --- .../createAvatarPolymiddlewareFromLegacy.tsx | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/packages/api/src/legacy/createAvatarPolymiddlewareFromLegacy.tsx b/packages/api/src/legacy/createAvatarPolymiddlewareFromLegacy.tsx index f1d3f3bea6..a547decaff 100644 --- a/packages/api/src/legacy/createAvatarPolymiddlewareFromLegacy.tsx +++ b/packages/api/src/legacy/createAvatarPolymiddlewareFromLegacy.tsx @@ -58,15 +58,6 @@ function createAvatarPolymiddlewareFromLegacy(...middlewares: readonly LegacyAva // so downstream handlers (e.g. core middleware) can still read it. const handler = next(originalRequest); - // TODO: Warn if the result is wrong. Also add tests. - // if (result !== false && typeof result !== 'function') { - // console.warn( - // 'botframework-webchat: avatarMiddleware should return a function to render the avatar, or return false if avatar should be hidden. Please refer to HOOKS.md for details.' - // ); - - // return () => result; - // } - return !!handler && ((): Exclude => handler.render({})); } ); @@ -87,9 +78,23 @@ function createAvatarPolymiddlewareFromLegacy(...middlewares: readonly LegacyAva }) ); - return legacyResult - ? avatarComponent(MemoizedLegacyAvatarBridge, Object.freeze({ renderFn: legacyResult })) - : undefined; + if (!legacyResult) { + return; + } + + let props: LegacyAvatarBridgeComponentProps; + + if (typeof legacyResult !== 'function') { + console.warn( + 'botframework-webchat: avatarMiddleware should return a function to render the avatar, or return false if avatar should be hidden. Please refer to HOOKS.md for details.' + ); + + props = Object.freeze({ renderFn: () => legacyResult }); + } else { + props = Object.freeze({ renderFn: legacyResult }); + } + + return avatarComponent(MemoizedLegacyAvatarBridge, props); }; }); } From d5c6b46436edd0f3f8694601b9f5117368afaff4 Mon Sep 17 00:00:00 2001 From: William Wong Date: Fri, 20 Mar 2026 02:19:04 +0000 Subject: [PATCH 10/51] Deprioritize default activity middleware --- .../src/private/templatePolymiddleware.tsx | 18 +++++++++++++++++- packages/api/src/hooks/Composer.tsx | 2 +- .../createActivityPolymiddlewareFromLegacy.tsx | 11 ++++++++++- packages/component/src/Composer.tsx | 5 +++-- 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/packages/api-middleware/src/private/templatePolymiddleware.tsx b/packages/api-middleware/src/private/templatePolymiddleware.tsx index 9b9cd80541..db84af06b7 100644 --- a/packages/api-middleware/src/private/templatePolymiddleware.tsx +++ b/packages/api-middleware/src/private/templatePolymiddleware.tsx @@ -19,6 +19,8 @@ const isArrayOfFunction = (middleware: unknown): middleware is InferOutput = next => request => next(request); +const DEBUG_ENHANCER_SYMBOL = Symbol('OriginalEnhancer'); +const DEBUG_NAME_SYMBOL = Symbol('MiddlewareName'); const EMPTY_ARRAY = Object.freeze([]); // Following @types/react to use {} for props. @@ -54,7 +56,21 @@ function templatePolymiddleware(name: string) { // We enforce middleware to be created using factory function. Object.defineProperty(taggedEnhancer, middlewareFactoryTag, { enumerable: false }); - return init => (init === name ? taggedEnhancer : BYPASS_ENHANCER); + const middleware: TemplatedMiddleware = init => (init === name ? taggedEnhancer : BYPASS_ENHANCER); + + Object.defineProperty(middleware, DEBUG_ENHANCER_SYMBOL, { + configurable: false, + value: enhancer, + writable: false + }); + + Object.defineProperty(middleware, DEBUG_NAME_SYMBOL, { + configurable: false, + value: name, + writable: false + }); + + return middleware; }; const warnInvalidExtraction = warnOnce(`Middleware passed for extraction of "${name}" must be an array of function`); diff --git a/packages/api/src/hooks/Composer.tsx b/packages/api/src/hooks/Composer.tsx index 877931d423..815ebc42f8 100644 --- a/packages/api/src/hooks/Composer.tsx +++ b/packages/api/src/hooks/Composer.tsx @@ -85,10 +85,10 @@ import isObject from '../utils/isObject'; import mapMap from '../utils/mapMap'; import normalizeLanguage from '../utils/normalizeLanguage'; import Tracker from './internal/Tracker'; -import useVoiceHandlers from './internal/useVoiceHandlers'; import WebChatAPIContext, { type WebChatAPIContextType } from './internal/WebChatAPIContext'; import WebChatReduxContext, { useDispatch } from './internal/WebChatReduxContext'; import defaultSelectVoice from './internal/defaultSelectVoice'; +import useVoiceHandlers from './internal/useVoiceHandlers'; import activityFallbackPolymiddleware from './middleware/activityFallbackPolymiddleware'; import applyMiddleware, { forLegacyRenderer as applyMiddlewareForLegacyRenderer, diff --git a/packages/api/src/legacy/createActivityPolymiddlewareFromLegacy.tsx b/packages/api/src/legacy/createActivityPolymiddlewareFromLegacy.tsx index 8135ee1040..a1f8c1e076 100644 --- a/packages/api/src/legacy/createActivityPolymiddlewareFromLegacy.tsx +++ b/packages/api/src/legacy/createActivityPolymiddlewareFromLegacy.tsx @@ -27,6 +27,7 @@ import { import LegacyActivityBridge from './LegacyActivityBridge'; +const DEBUG_ORIGINAL_LEGACY_MIDDLEWARE_SYMBOL = Symbol('OriginalLegacyMiddleware'); const webChatActivitySchema = custom(value => safeParse(object({}), value).success); type LegacyRenderFunction = ( @@ -87,7 +88,7 @@ function createActivityPolymiddlewareFromLegacy( ): ActivityPolymiddleware { const legacyEnhancer = composeEnhancer(...middleware.map(middleware => middleware())); - return createActivityPolymiddleware(next => { + const polymiddleware = createActivityPolymiddleware(next => { const legacyHandler = legacyEnhancer(request => { const handler = next(request); @@ -102,6 +103,14 @@ function createActivityPolymiddlewareFromLegacy( : undefined; }; }); + + Object.defineProperty(polymiddleware, DEBUG_ORIGINAL_LEGACY_MIDDLEWARE_SYMBOL, { + configurable: false, + value: Object.freeze([...middleware]), + writable: false + }); + + return polymiddleware; } export default createActivityPolymiddlewareFromLegacy; diff --git a/packages/component/src/Composer.tsx b/packages/component/src/Composer.tsx index 04c421ef3c..485ed99c1f 100644 --- a/packages/component/src/Composer.tsx +++ b/packages/component/src/Composer.tsx @@ -11,7 +11,7 @@ import { type SendBoxToolbarMiddleware } from 'botframework-webchat-api'; import { DecoratorComposer, type DecoratorMiddleware } from 'botframework-webchat-api/decorator'; -import { type Polymiddleware } from 'botframework-webchat-api/middleware'; +import { createActivityPolymiddlewareFromLegacy, type Polymiddleware } from 'botframework-webchat-api/middleware'; import { singleToArray } from 'botframework-webchat-core'; import classNames from 'classnames'; import MarkdownIt from 'markdown-it'; @@ -368,7 +368,7 @@ const Composer = ({ const theme = useTheme(); const patchedActivityMiddleware = useMemo( - () => [...singleToArray(activityMiddleware), ...theme.activityMiddleware, ...createDefaultActivityMiddleware()], + () => [...singleToArray(activityMiddleware), ...theme.activityMiddleware], [activityMiddleware, theme.activityMiddleware] ); @@ -420,6 +420,7 @@ const Composer = ({ ...theme.polymiddleware, // Polymiddleware has lower priority than legacy middleware. // Later, we should move default middleware to a "default theme." + createActivityPolymiddlewareFromLegacy(...createDefaultActivityMiddleware()), ...createDefaultAvatarMiddleware() ]), [polymiddleware, theme.polymiddleware] From 8ee929b3c07139cca679c939aec80c647831bbee Mon Sep 17 00:00:00 2001 From: William Wong Date: Fri, 20 Mar 2026 06:46:00 +0000 Subject: [PATCH 11/51] Patch attachmentLayout instead of via activityMiddleware --- .../ActivityGroupingSurface.js | 40 +++++-------------- .../createDirectLineWithTranscript.js | 7 +++- 2 files changed, 16 insertions(+), 31 deletions(-) diff --git a/packages/test/page-object/src/globals/testHelpers/activityGrouping/ActivityGroupingSurface.js b/packages/test/page-object/src/globals/testHelpers/activityGrouping/ActivityGroupingSurface.js index 97e0782380..b6093d354b 100644 --- a/packages/test/page-object/src/globals/testHelpers/activityGrouping/ActivityGroupingSurface.js +++ b/packages/test/page-object/src/globals/testHelpers/activityGrouping/ActivityGroupingSurface.js @@ -1,7 +1,7 @@ import PropTypes from 'prop-types'; -import ActivityGroupingContext from './ActivityGroupingContext'; import createDirectLineWithTranscript from '../createDirectLineWithTranscript'; +import ActivityGroupingContext from './ActivityGroupingContext'; // Use React from window (UMD) instead of import. const { React: { useEffect, useMemo, useState } = {} } = window; @@ -23,22 +23,6 @@ const URL_QUERY_MAPPING = { wd: 'hide' }; -function createCustomActivityMiddleware(attachmentLayout) { - return () => - next => - (arg0, ...args) => - next( - { - ...arg0, - activity: { - ...arg0.activity, - ...(attachmentLayout && arg0.activity.from.role === 'bot' ? { attachmentLayout } : {}) - } - }, - ...args - ); -} - function generateURL(state) { const params = {}; @@ -143,7 +127,15 @@ const ActivityGroupingSurface = ({ children }) => { let directLine; (async function () { - directLine = await createDirectLineWithTranscript(transcriptName); + directLine = await createDirectLineWithTranscript(transcriptName, { + patchActivity: activity => { + if ((attachmentLayout === 'carousel' || attachmentLayout === 'stacked') && activity.from?.role === 'bot') { + return Object.freeze({ ...activity, attachmentLayout }); + } + + return activity; + } + }); aborted || setDirectLine(directLine); })(); @@ -152,15 +144,7 @@ const ActivityGroupingSurface = ({ children }) => { aborted = true; directLine && directLine.end(); }; - }, [setDirectLine, transcriptName]); - - const activityMiddleware = useMemo( - () => - attachmentLayout === 'carousel' || attachmentLayout === 'stacked' - ? createCustomActivityMiddleware(attachmentLayout) - : undefined, - [attachmentLayout] - ); + }, [attachmentLayout, setDirectLine, transcriptName]); const styleOptions = useMemo( () => ({ @@ -223,7 +207,6 @@ const ActivityGroupingSurface = ({ children }) => { const context = useMemo( () => ({ ...contextState, - activityMiddleware, directLine, setAttachmentLayout, setBotAvatarInitials, @@ -242,7 +225,6 @@ const ActivityGroupingSurface = ({ children }) => { url }), [ - activityMiddleware, contextState, directLine, setAttachmentLayout, diff --git a/packages/test/page-object/src/globals/testHelpers/createDirectLineWithTranscript.js b/packages/test/page-object/src/globals/testHelpers/createDirectLineWithTranscript.js index c1e1fe0b72..a8218f28ce 100644 --- a/packages/test/page-object/src/globals/testHelpers/createDirectLineWithTranscript.js +++ b/packages/test/page-object/src/globals/testHelpers/createDirectLineWithTranscript.js @@ -36,10 +36,13 @@ function createUpdateRelativeTimestamp(now, { Date }) { export default function createDirectLineWithTranscript( activitiesOrFilename, - { overridePostActivity, ponyfill: { Date } = { Date: window.Date } } = {} + { overridePostActivity, patchActivity: patchActivityFromOptions, ponyfill: { Date } = { Date: window.Date } } = {} ) { const now = Date.now(); - const patchActivity = createUpdateRelativeTimestamp(now, { Date }); + const patchActivity = activity => + createUpdateRelativeTimestamp(now, { Date })( + patchActivityFromOptions ? patchActivityFromOptions(activity) : activity + ); const connectionStatusDeferredObservable = createDeferredObservable(() => { connectionStatusDeferredObservable.next(0); }); From f7675011dc77aa92cc0bf42a3ccd4a9e66d6f50a Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 23 Mar 2026 01:17:33 +0000 Subject: [PATCH 12/51] Add helper hooks --- packages/react-hooks/package.json | 9 +++++-- packages/react-hooks/src/index.ts | 2 ++ packages/react-hooks/src/useDebugDeps.ts | 26 +++++++++++++++++++++ packages/react-hooks/src/useMemoIterable.ts | 11 +++++++++ 4 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 packages/react-hooks/src/useDebugDeps.ts create mode 100644 packages/react-hooks/src/useMemoIterable.ts diff --git a/packages/react-hooks/package.json b/packages/react-hooks/package.json index 057700add4..a8ca025a54 100644 --- a/packages/react-hooks/package.json +++ b/packages/react-hooks/package.json @@ -49,10 +49,15 @@ "precommit:eslint": "../../node_modules/.bin/eslint --report-unused-disable-directives --max-warnings 0", "precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false", "preversion": "../../scripts/npm/preversion.sh", - "start": "../../scripts/npm/notify-build.sh \"src\"" + "start": "../../scripts/npm/notify-build.sh \"src\" \"../base/package.json\"" + }, + "localDependencies": { + "@msinternal/botframework-webchat-base": "development" }, - "localDependencies": {}, "peerDependencies": { "react": ">= 16.8.6" + }, + "devDependencies": { + "@msinternal/botframework-webchat-base": "0.0.0-0" } } diff --git a/packages/react-hooks/src/index.ts b/packages/react-hooks/src/index.ts index 117ee2543c..8dc71742e5 100644 --- a/packages/react-hooks/src/index.ts +++ b/packages/react-hooks/src/index.ts @@ -1 +1,3 @@ +export { default as useDebugDeps } from './useDebugDeps'; +export { default as useMemoIterable } from './useMemoIterable'; export { default as useMemoWithPrevious } from './useMemoWithPrevious'; diff --git a/packages/react-hooks/src/useDebugDeps.ts b/packages/react-hooks/src/useDebugDeps.ts new file mode 100644 index 0000000000..5793794349 --- /dev/null +++ b/packages/react-hooks/src/useDebugDeps.ts @@ -0,0 +1,26 @@ +/* eslint no-console: "off" */ + +import { useRef } from 'react'; + +export default function useDebugDeps(depsObject: Record, name: string): void { + const depsMap = Object.freeze(new Map(Object.entries(depsObject))); + const prevDepsMapRef = useRef | undefined>(); + + const { current: prevDepsMap } = prevDepsMapRef; + + // Ignores initial rendering. + if (prevDepsMap) { + const keys = new Set([...depsMap.keys(), ...prevDepsMap.keys()]); + const keysChanged = Array.from(keys).filter(key => !Object.is(depsMap.get(key), prevDepsMap.get(key))); + + if (keysChanged.length) { + console.groupCollapsed(`Changes found in ${name}`); + + keysChanged.forEach(key => console.log(key, { from: prevDepsMap.get(key), to: depsMap.get(key) })); + + console.groupEnd(); + } + } + + prevDepsMapRef.current = depsMap; +} diff --git a/packages/react-hooks/src/useMemoIterable.ts b/packages/react-hooks/src/useMemoIterable.ts new file mode 100644 index 0000000000..b9c0de884c --- /dev/null +++ b/packages/react-hooks/src/useMemoIterable.ts @@ -0,0 +1,11 @@ +import { iterateEquals } from '@msinternal/botframework-webchat-base/utils'; +import { type DependencyList } from 'react'; +import useMemoWithPrevious from './useMemoWithPrevious'; + +export default function useMemoIterable>(factory: () => T, deps: DependencyList) { + return useMemoWithPrevious(prevValue => { + const value = factory(); + + return prevValue && iterateEquals(value, prevValue) ? prevValue : value; + }, deps); +} From c0bc32a1f9287e76ef7dded9bef99f800941c28e Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 23 Mar 2026 01:18:53 +0000 Subject: [PATCH 13/51] Add iterateEquals --- packages/base/src/utils/index.ts | 1 + packages/base/src/utils/iterateEquals.spec.ts | 9 ++++++++ packages/base/src/utils/iterateEquals.ts | 22 +++++++++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 packages/base/src/utils/iterateEquals.spec.ts create mode 100644 packages/base/src/utils/iterateEquals.ts diff --git a/packages/base/src/utils/index.ts b/packages/base/src/utils/index.ts index e1caad9c14..f1681595a1 100644 --- a/packages/base/src/utils/index.ts +++ b/packages/base/src/utils/index.ts @@ -1,5 +1,6 @@ export { default as createBuildInfo, type BuildInfo, type ReadonlyBuildInfo } from './createBuildInfo'; export { default as deprecateObject } from './deprecateObject'; export { default as isForbiddenPropertyName } from './isForbiddenPropertyName'; +export { default as iterateEquals } from './iterateEquals'; export { default as warnOnce } from './warnOnce'; export { default as withResolvers, type PromiseWithResolvers } from './withResolvers'; diff --git a/packages/base/src/utils/iterateEquals.spec.ts b/packages/base/src/utils/iterateEquals.spec.ts new file mode 100644 index 0000000000..29c8f081dc --- /dev/null +++ b/packages/base/src/utils/iterateEquals.spec.ts @@ -0,0 +1,9 @@ +import { expect, test } from '@jest/globals'; +import iterateEquals from './iterateEquals'; + +test('comparing empty arrays', () => expect(iterateEquals([].values(), [].values())).toBe(true)); +test('comparing different arrays', () => expect(iterateEquals([1].values(), [2].values())).toBe(false)); +test('comparing bigger array to smaller array', () => expect(iterateEquals([1, 2].values(), [1].values())).toBe(false)); +test('comparing smaller array to bigger array', () => expect(iterateEquals([1].values(), [1, 2].values())).toBe(false)); +test('comparing non-empty array to empty array', () => expect(iterateEquals([1].values(), [].values())).toBe(false)); +test('comparing empty array to non-empty array', () => expect(iterateEquals([].values(), [1].values())).toBe(false)); diff --git a/packages/base/src/utils/iterateEquals.ts b/packages/base/src/utils/iterateEquals.ts new file mode 100644 index 0000000000..fb305fe2ab --- /dev/null +++ b/packages/base/src/utils/iterateEquals.ts @@ -0,0 +1,22 @@ +const MAX_ITERATION = 1_000_000; + +export default function iterateEquals(x: Iterable, y: Iterable): boolean { + const xIterator = x[Symbol.iterator](); + const yIterator = y[Symbol.iterator](); + + // eslint-disable-next-line no-magic-numbers + for (let count = 0; count < MAX_ITERATION; count++) { + const resultX = xIterator.next(); + const resultY = yIterator.next(); + + if (resultX.done && resultY.done) { + return true; + } + + if (!Object.is(resultX.value, resultY.value)) { + break; + } + } + + return false; +} From 5619932b0fb50e2f00ab5721afe71a29fcab4613 Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 23 Mar 2026 01:47:12 +0000 Subject: [PATCH 14/51] Use useMemoIterable and polymiddleware --- package-lock.json | 3 + .../src/PolymiddlewareComposer.tsx | 40 +- packages/api/src/hooks/Composer.tsx | 34 +- .../api/src/hooks/internal/useDebugDeps.js | 30 - packages/component/src/BasicTranscript.tsx | 640 +++++++++--------- packages/component/src/Composer.tsx | 15 +- .../Activity/createCoreMiddleware.tsx | 88 --- .../defaultActivityPolymiddleware.tsx | 87 +++ .../Avatar/createCoreMiddleware.tsx | 27 - .../Avatar/defaultAvatarPolymiddleware.tsx | 21 + 10 files changed, 471 insertions(+), 514 deletions(-) delete mode 100644 packages/api/src/hooks/internal/useDebugDeps.js delete mode 100644 packages/component/src/Middleware/Activity/createCoreMiddleware.tsx create mode 100644 packages/component/src/Middleware/Activity/defaultActivityPolymiddleware.tsx delete mode 100644 packages/component/src/Middleware/Avatar/createCoreMiddleware.tsx create mode 100644 packages/component/src/Middleware/Avatar/defaultAvatarPolymiddleware.tsx diff --git a/package-lock.json b/package-lock.json index 5b89f3716f..a7773e9765 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21734,6 +21734,9 @@ "name": "@msinternal/botframework-webchat-react-hooks", "version": "0.0.0-0", "license": "MIT", + "devDependencies": { + "@msinternal/botframework-webchat-base": "0.0.0-0" + }, "peerDependencies": { "react": ">= 16.8.6" } diff --git a/packages/api-middleware/src/PolymiddlewareComposer.tsx b/packages/api-middleware/src/PolymiddlewareComposer.tsx index db6c3e6d2e..79c6179f4f 100644 --- a/packages/api-middleware/src/PolymiddlewareComposer.tsx +++ b/packages/api-middleware/src/PolymiddlewareComposer.tsx @@ -1,4 +1,4 @@ -import { useMemoWithPrevious } from '@msinternal/botframework-webchat-react-hooks'; +import { useMemoIterable } from '@msinternal/botframework-webchat-react-hooks'; import { reactNode, validateProps } from '@msinternal/botframework-webchat-react-valibot'; import React, { memo, useMemo } from 'react'; import { @@ -35,46 +35,22 @@ type PolymiddlewareComposerProps = Readonly>( - (prevActivityEnhancers = []) => { - const activityEnhancers = extractActivityEnhancer(polymiddleware); - - // Checks for array equality, return previous version if nothing has changed. - return prevActivityEnhancers.length === activityEnhancers.length && - activityEnhancers.every((middleware, index) => Object.is(middleware, prevActivityEnhancers.at(index))) - ? prevActivityEnhancers - : activityEnhancers; - }, + const activityEnhancers = useMemoIterable>( + () => extractActivityEnhancer(polymiddleware), [polymiddleware] ); const activityPolymiddleware = useMemo(() => activityEnhancers.map(enhancer => () => enhancer), [activityEnhancers]); - const avatarEnhancers = useMemoWithPrevious>( - (prevAvatarEnhancers = []) => { - const avatarEnhancers = extractAvatarEnhancer(polymiddleware); - - // Checks for array equality, return previous version if nothing has changed. - return prevAvatarEnhancers.length === avatarEnhancers.length && - avatarEnhancers.every((middleware, index) => Object.is(middleware, prevAvatarEnhancers.at(index))) - ? prevAvatarEnhancers - : avatarEnhancers; - }, + const avatarEnhancers = useMemoIterable>( + () => extractAvatarEnhancer(polymiddleware), [polymiddleware] ); const avatarPolymiddleware = useMemo(() => avatarEnhancers.map(enhancer => () => enhancer), [avatarEnhancers]); - const errorBoxEnhancers = useMemoWithPrevious>( - (prevErrorBoxEnhancers = []) => { - const errorBoxEnhancers = extractErrorBoxEnhancer(polymiddleware); - - // Checks for array equality, return previous version if nothing has changed. - return prevErrorBoxEnhancers.length === errorBoxEnhancers.length && - errorBoxEnhancers.every((middleware, index) => Object.is(middleware, prevErrorBoxEnhancers.at(index))) - ? prevErrorBoxEnhancers - : errorBoxEnhancers; - }, + const errorBoxEnhancers = useMemoIterable>( + () => extractErrorBoxEnhancer(polymiddleware), [polymiddleware] ); @@ -98,5 +74,7 @@ function PolymiddlewareComposer(props: PolymiddlewareComposerProps) { ); } +PolymiddlewareComposer.displayName = 'PolymiddlewareComposer'; + export default memo(PolymiddlewareComposer); export { polymiddlewareComposerPropsSchema, type PolymiddlewareComposerProps }; diff --git a/packages/api/src/hooks/Composer.tsx b/packages/api/src/hooks/Composer.tsx index 815ebc42f8..ae57ce5426 100644 --- a/packages/api/src/hooks/Composer.tsx +++ b/packages/api/src/hooks/Composer.tsx @@ -4,6 +4,7 @@ import { type LegacyActivityMiddleware, type LegacyAttachmentMiddleware } from '@msinternal/botframework-webchat-api-middleware/legacy'; +import { useMemoIterable } from '@msinternal/botframework-webchat-react-hooks'; import { ReduxStoreComposer } from '@msinternal/botframework-webchat-redux-store'; import { clearSuggestedActions, @@ -240,7 +241,7 @@ type ComposerCoreProps = Readonly<{ quality: number ) => Promise; grammars?: any; - groupActivitiesMiddleware?: OneOrMany; + groupActivitiesMiddleware?: OneOrMany | undefined; locale?: string; polymiddleware?: readonly Polymiddleware[]; onTelemetry?: (event: TelemetryMeasurementEvent) => void; @@ -255,7 +256,7 @@ type ComposerCoreProps = Readonly<{ sendBoxMiddleware?: readonly SendBoxMiddleware[] | undefined; sendBoxToolbarMiddleware?: readonly SendBoxToolbarMiddleware[] | undefined; sendTypingIndicator?: boolean; - toastMiddleware?: OneOrMany; + toastMiddleware?: OneOrMany | undefined; typingIndicatorMiddleware?: OneOrMany; /** * Sets the state of the UI. @@ -284,7 +285,7 @@ const ComposerCore = ({ disabled, downscaleImageToDataURL, grammars, - groupActivitiesMiddleware, + groupActivitiesMiddleware: groupActivitiesMiddlewareFromProps, locale, onTelemetry, overrideLocalizedStrings, @@ -471,11 +472,17 @@ const ComposerCore = ({ [attachmentMiddleware] ); - const polymiddlewareForLegacyAvatarMiddleware = useMemo( + const groupActivitiesMiddleware = useMemoIterable( + () => + groupActivitiesMiddlewareFromProps ? Object.freeze(singleToArray(groupActivitiesMiddlewareFromProps)) : undefined, + [groupActivitiesMiddlewareFromProps] + ); + + const polymiddlewareForLegacyAvatarMiddleware = useMemo( () => avatarMiddleware ? Object.freeze([createAvatarPolymiddlewareFromLegacy(...singleToArray(avatarMiddleware))]) - : EMPTY_ARRAY, + : undefined, [avatarMiddleware] ); @@ -520,12 +527,15 @@ const ComposerCore = ({ [scrollToEndButtonMiddleware] ); - const polymiddlewareForLegacyActivityMiddleware = useMemo( - () => Object.freeze([createActivityPolymiddlewareFromLegacy(...singleToArray(activityMiddleware))]), + const polymiddlewareForLegacyActivityMiddleware = useMemo( + () => + activityMiddleware + ? Object.freeze([createActivityPolymiddlewareFromLegacy(...singleToArray(activityMiddleware))]) + : undefined, [activityMiddleware] ); - const polymiddleware = useMemo( + const polymiddleware = useMemoIterable( () => Object.freeze([ // Error box telemetry polymiddleware is special and has a much higher priority. @@ -551,9 +561,9 @@ const ComposerCore = ({ // // The simplest and logical move is #3: render legacy middleware before polymiddleware. - ...polymiddlewareForLegacyActivityMiddleware, - ...polymiddlewareForLegacyAvatarMiddleware, - ...(polymiddlewareFromProps || []), + ...(polymiddlewareForLegacyActivityMiddleware ?? []), + ...(polymiddlewareForLegacyAvatarMiddleware ?? []), + ...(polymiddlewareFromProps ?? []), activityFallbackPolymiddleware ]), [polymiddlewareForLegacyActivityMiddleware, polymiddlewareForLegacyAvatarMiddleware, polymiddlewareFromProps] @@ -637,7 +647,7 @@ const ComposerCore = ({ - + {typeof children === 'function' ? children(context) : children} diff --git a/packages/api/src/hooks/internal/useDebugDeps.js b/packages/api/src/hooks/internal/useDebugDeps.js deleted file mode 100644 index e749de8060..0000000000 --- a/packages/api/src/hooks/internal/useDebugDeps.js +++ /dev/null @@ -1,30 +0,0 @@ -/* eslint no-console: "off" */ - -import { isForbiddenPropertyName } from 'botframework-webchat-core'; -import { useRef } from 'react'; - -export default function useDebugDeps(depsMap, name) { - const lastDepsMapRef = useRef({}); - - const { current: lastDepsMap } = lastDepsMapRef; - const keys = new Set([...Object.keys(depsMap), ...Object.keys(lastDepsMap)]); - const keysChanged = Array.from(keys).filter( - // Mitigation through denylisting. - // eslint-disable-next-line security/detect-object-injection - key => !isForbiddenPropertyName(key) && !Object.is(depsMap[key], lastDepsMap[key]) - ); - - if (keysChanged.length) { - console.groupCollapsed(`Changes found in ${name}`); - - keysChanged.forEach(key => { - // Mitigation through denylisting. - // eslint-disable-next-line security/detect-object-injection - isForbiddenPropertyName(key) || console.log(key, { from: lastDepsMap[key], to: depsMap[key] }); - }); - - console.groupEnd(); - } - - lastDepsMapRef.current = depsMap; -} diff --git a/packages/component/src/BasicTranscript.tsx b/packages/component/src/BasicTranscript.tsx index 5b4f65647a..a80949ff6e 100644 --- a/packages/component/src/BasicTranscript.tsx +++ b/packages/component/src/BasicTranscript.tsx @@ -113,363 +113,365 @@ type ScrollToPosition = { activityID?: string; scrollTop?: number }; type InternalTranscriptProps = Readonly<{ className?: string; - terminatorRef: React.MutableRefObject; + terminatorRef: MutableRefObject; }>; // TODO: [P1] #4133 Add telemetry for computing how many re-render done so far. -const InternalTranscript = forwardRef( - ( - { className, terminatorRef }: InternalTranscriptProps, - ref: MutableRefObject | ((instance: HTMLDivElement | null) => void) - ) => { - const [activeDescendantId] = useActiveDescendantId(); - const [direction] = useDirection(); - const [focusedKey] = useFocusedKey(); - const [focusedExplicitly] = useFocusedExplicitly(); - const focusElementMapRef = useActivityElementMapRef(); - const focus = useFocus(); - const focusByActivityKey = useFocusByActivityKey(); - const focusRelativeActivity = useFocusRelativeActivity(); - const getActivityByKey = useGetActivityByKey(); - const getKeyByActivityId = useGetKeyByActivityId(); - const localize = useLocalizer(); - const rootClassName = useStyleToEmotionObject()(ROOT_STYLE) + ''; - const rootElementRef = useRef(null); - - const focusedKeyRef = useValueRef(focusedKey); - const transcriptAriaLabel = localize('TRANSCRIPT_ARIA_LABEL_ALT'); - - const callbackRef = useCallback( - (element: HTMLDivElement) => { - if (typeof ref === 'function') { - ref(element); - } else { - ref.current = element; - } +const InternalTranscript = memo( + forwardRef( + ( + { className, terminatorRef }: InternalTranscriptProps, + ref: MutableRefObject | ((instance: HTMLDivElement | null) => void) + ) => { + const [activeDescendantId] = useActiveDescendantId(); + const [direction] = useDirection(); + const [focusedKey] = useFocusedKey(); + const [focusedExplicitly] = useFocusedExplicitly(); + const focusElementMapRef = useActivityElementMapRef(); + const focus = useFocus(); + const focusByActivityKey = useFocusByActivityKey(); + const focusRelativeActivity = useFocusRelativeActivity(); + const getActivityByKey = useGetActivityByKey(); + const getKeyByActivityId = useGetKeyByActivityId(); + const localize = useLocalizer(); + const rootClassName = useStyleToEmotionObject()(ROOT_STYLE) + ''; + const rootElementRef = useRef(null); + + const focusedKeyRef = useValueRef(focusedKey); + const transcriptAriaLabel = localize('TRANSCRIPT_ARIA_LABEL_ALT'); + + const callbackRef = useCallback( + (element: HTMLDivElement) => { + if (typeof ref === 'function') { + ref(element); + } else { + ref.current = element; + } - rootElementRef.current = element; - }, - [ref, rootElementRef] - ); + rootElementRef.current = element; + }, + [ref, rootElementRef] + ); - const [numRenderingActivities] = useNumRenderingActivities(); + const [numRenderingActivities] = useNumRenderingActivities(); - const scrollToBottomScrollTo: (scrollTop: number, options?: ScrollToOptions) => void = useScrollTo(); - const scrollToBottomScrollToEnd: (options?: ScrollToOptions) => void = useScrollToEnd(); + const scrollToBottomScrollTo: (scrollTop: number, options?: ScrollToOptions) => void = useScrollTo(); + const scrollToBottomScrollToEnd: (options?: ScrollToOptions) => void = useScrollToEnd(); - const scrollTo = useCallback( - (position: ScrollToPosition, { behavior = 'auto' }: ScrollToOptions = {}) => { - if (!position) { - throw new Error( - 'botframework-webchat: First argument passed to "useScrollTo" must be a ScrollPosition object.' - ); - } + const scrollTo = useCallback( + (position: ScrollToPosition, { behavior = 'auto' }: ScrollToOptions = {}) => { + if (!position) { + throw new Error( + 'botframework-webchat: First argument passed to "useScrollTo" must be a ScrollPosition object.' + ); + } - const { activityID: activityId, scrollTop } = position; + const { activityID: activityId, scrollTop } = position; - if (typeof scrollTop !== 'undefined') { - scrollToBottomScrollTo(scrollTop, { behavior }); - } else if (typeof activityId !== 'undefined') { - const activityBoundingBoxElement = focusElementMapRef.current - .get(getKeyByActivityId(activityId)) - ?.querySelector('.webchat__basic-transcript__activity-active-descendant'); + if (typeof scrollTop !== 'undefined') { + scrollToBottomScrollTo(scrollTop, { behavior }); + } else if (typeof activityId !== 'undefined') { + const activityBoundingBoxElement = focusElementMapRef.current + .get(getKeyByActivityId(activityId)) + ?.querySelector('.webchat__basic-transcript__activity-active-descendant'); - const scrollableElement = rootElementRef.current.querySelector('.webchat__basic-transcript__scrollable'); + const scrollableElement = rootElementRef.current.querySelector('.webchat__basic-transcript__scrollable'); - if (scrollableElement && activityBoundingBoxElement) { - // ESLint conflict with TypeScript. The result of getClientRects() is not an Array but DOMRectList, and cannot be destructured. - // eslint-disable-next-line prefer-destructuring - const activityBoundingBoxElementClientRect = activityBoundingBoxElement.getClientRects()[0]; + if (scrollableElement && activityBoundingBoxElement) { + // ESLint conflict with TypeScript. The result of getClientRects() is not an Array but DOMRectList, and cannot be destructured. + // eslint-disable-next-line prefer-destructuring + const activityBoundingBoxElementClientRect = activityBoundingBoxElement.getClientRects()[0]; - // ESLint conflict with TypeScript. The result of getClientRects() is not an Array but DOMRectList, and cannot be destructured. - // eslint-disable-next-line prefer-destructuring - const scrollableElementClientRect = scrollableElement.getClientRects()[0]; + // ESLint conflict with TypeScript. The result of getClientRects() is not an Array but DOMRectList, and cannot be destructured. + // eslint-disable-next-line prefer-destructuring + const scrollableElementClientRect = scrollableElement.getClientRects()[0]; - // If either the activity or the transcript scrollable is not on DOM, we will not scroll the view. - if (activityBoundingBoxElementClientRect && scrollableElementClientRect) { - const { height: activityHeight, y: activityY } = activityBoundingBoxElementClientRect; - const { height: scrollableHeight } = scrollableElementClientRect; - const activityOffsetTop = activityY + scrollableElement.scrollTop; + // If either the activity or the transcript scrollable is not on DOM, we will not scroll the view. + if (activityBoundingBoxElementClientRect && scrollableElementClientRect) { + const { height: activityHeight, y: activityY } = activityBoundingBoxElementClientRect; + const { height: scrollableHeight } = scrollableElementClientRect; + const activityOffsetTop = activityY + scrollableElement.scrollTop; - const scrollTop = Math.min(activityOffsetTop, activityOffsetTop - scrollableHeight + activityHeight); + const scrollTop = Math.min(activityOffsetTop, activityOffsetTop - scrollableHeight + activityHeight); - scrollToBottomScrollTo(scrollTop, { behavior }); + scrollToBottomScrollTo(scrollTop, { behavior }); + } } } - } - }, - [focusElementMapRef, getKeyByActivityId, rootElementRef, scrollToBottomScrollTo] - ); + }, + [focusElementMapRef, getKeyByActivityId, rootElementRef, scrollToBottomScrollTo] + ); - const scrollToEnd = useCallback( - () => scrollToBottomScrollToEnd({ behavior: 'smooth' }), - [scrollToBottomScrollToEnd] - ); + const scrollToEnd = useCallback( + () => scrollToBottomScrollToEnd({ behavior: 'smooth' }), + [scrollToBottomScrollToEnd] + ); - const scrollRelative = useCallback( - ({ direction, displacement }: TranscriptScrollRelativeOptions) => { - const { current: rootElement } = rootElementRef; + const scrollRelative = useCallback( + ({ direction, displacement }: TranscriptScrollRelativeOptions) => { + const { current: rootElement } = rootElementRef; - if (!rootElement) { - return; - } + if (!rootElement) { + return; + } - const scrollable: HTMLElement = rootElement.querySelector('.webchat__basic-transcript__scrollable'); - let nextScrollTop: number; + const scrollable: HTMLElement = rootElement.querySelector('.webchat__basic-transcript__scrollable'); + let nextScrollTop: number; - if (typeof displacement === 'number') { - // eslint-disable-next-line no-magic-numbers - nextScrollTop = scrollable.scrollTop + (direction === 'down' ? 1 : -1) * displacement; - } else { - // eslint-disable-next-line no-magic-numbers - nextScrollTop = scrollable.scrollTop + (direction === 'down' ? 1 : -1) * scrollable.offsetHeight; - } + if (typeof displacement === 'number') { + // eslint-disable-next-line no-magic-numbers + nextScrollTop = scrollable.scrollTop + (direction === 'down' ? 1 : -1) * displacement; + } else { + // eslint-disable-next-line no-magic-numbers + nextScrollTop = scrollable.scrollTop + (direction === 'down' ? 1 : -1) * scrollable.offsetHeight; + } - scrollTo( - { - scrollTop: Math.max(0, Math.min(scrollable.scrollHeight - scrollable.offsetHeight, nextScrollTop)) - }, - { behavior: 'smooth' } - ); - }, - [rootElementRef, scrollTo] - ); - - // Since there could be multiple instances of inside the , when the developer calls `scrollXXX`, we need to call it on all instances. - // We call `useRegisterScrollXXX` to register a callback function, the `useScrollXXX` will multiplex the call into each instance of . - useRegisterScrollTo(scrollTo); - useRegisterScrollToEnd(scrollToEnd); - useRegisterScrollRelativeTranscript(scrollRelative); - - const markActivityKeyAsRead = useMarkActivityKeyAsRead(); - - const dispatchScrollPositionWithActivityId: (scrollPosition: ScrollToPosition) => void = - useDispatchScrollPosition(); - - // TODO: [P2] We should use IntersectionObserver to track what activity is in the scrollable. - // However, IntersectionObserver is not available on IE11, we need to make a limited polyfill in React style. - const handleScrollPosition = useCallback( - ({ scrollTop }: { scrollTop: number }) => { - const { current: rootElement } = rootElementRef; - - if (!rootElement) { - return; - } + scrollTo( + { + scrollTop: Math.max(0, Math.min(scrollable.scrollHeight - scrollable.offsetHeight, nextScrollTop)) + }, + { behavior: 'smooth' } + ); + }, + [rootElementRef, scrollTo] + ); - const scrollableElement = rootElement.querySelector('.webchat__basic-transcript__scrollable'); + // Since there could be multiple instances of inside the , when the developer calls `scrollXXX`, we need to call it on all instances. + // We call `useRegisterScrollXXX` to register a callback function, the `useScrollXXX` will multiplex the call into each instance of . + useRegisterScrollTo(scrollTo); + useRegisterScrollToEnd(scrollToEnd); + useRegisterScrollRelativeTranscript(scrollRelative); - // "getClientRects()" is not returning an array, thus, it is not destructurable. - // eslint-disable-next-line prefer-destructuring - const scrollableElementClientRect = scrollableElement.getClientRects()[0]; + const markActivityKeyAsRead = useMarkActivityKeyAsRead(); - // If the scrollable is not mounted, we cannot measure which activity is in view. Thus, we will not fire any events. - if (!scrollableElementClientRect) { - return; - } + const dispatchScrollPositionWithActivityId: (scrollPosition: ScrollToPosition) => void = + useDispatchScrollPosition(); - const { bottom: scrollableClientBottom } = scrollableElementClientRect; - - // Find the activity just above scroll view bottom. - // If the scroll view is already on top, get the first activity. - const activityElements = Array.from(focusElementMapRef.current.entries()); - const activityKeyJustAboveScrollBottom: string | undefined = ( - scrollableElement.scrollTop - ? activityElements - .reverse() - // Add subpixel tolerance - .find(([, element]) => { - // "getClientRects()" is not returning an array, thus, it is not destructurable. - // eslint-disable-next-line prefer-destructuring - const elementClientRect = element.getClientRects()[0]; - - // If the activity is not attached to DOM tree, we should not count it as "bottommost visible activity", as it is not visible. - return elementClientRect && elementClientRect.bottom < scrollableClientBottom + 1; - }) - : activityElements[0] - )?.[0]; - - // When the end-user slowly scrolling the view down, we will mark activity as read when the message fully appear on the screen. - activityKeyJustAboveScrollBottom && markActivityKeyAsRead(activityKeyJustAboveScrollBottom); - - if (dispatchScrollPositionWithActivityId) { - const activity = getActivityByKey(activityKeyJustAboveScrollBottom); - - dispatchScrollPositionWithActivityId({ ...(activity ? { activityID: activity.id } : {}), scrollTop }); - } - }, - [ - focusElementMapRef, - dispatchScrollPositionWithActivityId, - getActivityByKey, - markActivityKeyAsRead, - rootElementRef - ] - ); - - useObserveScrollPosition(handleScrollPosition); - - const handleTranscriptKeyDown = useCallback>( - event => { - const { target } = event; - - const fromEndOfTranscriptIndicator = target === terminatorRef.current; - const fromTranscript = target === event.currentTarget; - - if (!fromEndOfTranscriptIndicator && !fromTranscript) { - return; - } + // TODO: [P2] We should use IntersectionObserver to track what activity is in the scrollable. + // However, IntersectionObserver is not available on IE11, we need to make a limited polyfill in React style. + const handleScrollPosition = useCallback( + ({ scrollTop }: { scrollTop: number }) => { + const { current: rootElement } = rootElementRef; - let handled = true; + if (!rootElement) { + return; + } - switch (event.key) { - case 'ArrowDown': - focusRelativeActivity(fromEndOfTranscriptIndicator ? 0 : 1); - break; + const scrollableElement = rootElement.querySelector('.webchat__basic-transcript__scrollable'); - case 'ArrowUp': - // eslint-disable-next-line no-magic-numbers - focusRelativeActivity(fromEndOfTranscriptIndicator ? 0 : -1); - break; - - case 'End': - focusRelativeActivity(Infinity); - break; - - case 'Enter': - // This is capturing plain ENTER. - // When screen reader is not running, or screen reader is running outside of scan mode, the ENTER key will be captured here. - if (!fromEndOfTranscriptIndicator) { - const focusElement = focusElementMapRef.current?.get(focusedKeyRef.current); - const activityFocusTrapTarget: HTMLElement = - focusElement?.querySelector('.webchat__basic-transcript__group-focus-target') ?? - focusElement?.querySelector('.webchat__basic-transcript__activity-focus-target'); - // TODO: review focus approach: - // It is not clear how to handle focus without introducing something like context. - // Ideally we would want a way to interact with focus outside of React - // so it doesn't cause transcript re-renders while still having an ability - // to scope activity-related handlers and data in a single place. - activityFocusTrapTarget?.focus(); - } + // "getClientRects()" is not returning an array, thus, it is not destructurable. + // eslint-disable-next-line prefer-destructuring + const scrollableElementClientRect = scrollableElement.getClientRects()[0]; - break; + // If the scrollable is not mounted, we cannot measure which activity is in view. Thus, we will not fire any events. + if (!scrollableElementClientRect) { + return; + } - case 'Escape': - focus('sendBoxWithoutKeyboard'); - break; + const { bottom: scrollableClientBottom } = scrollableElementClientRect; + + // Find the activity just above scroll view bottom. + // If the scroll view is already on top, get the first activity. + const activityElements = Array.from(focusElementMapRef.current.entries()); + const activityKeyJustAboveScrollBottom: string | undefined = ( + scrollableElement.scrollTop + ? activityElements + .reverse() + // Add subpixel tolerance + .find(([, element]) => { + // "getClientRects()" is not returning an array, thus, it is not destructurable. + // eslint-disable-next-line prefer-destructuring + const elementClientRect = element.getClientRects()[0]; + + // If the activity is not attached to DOM tree, we should not count it as "bottommost visible activity", as it is not visible. + return elementClientRect && elementClientRect.bottom < scrollableClientBottom + 1; + }) + : activityElements[0] + )?.[0]; + + // When the end-user slowly scrolling the view down, we will mark activity as read when the message fully appear on the screen. + activityKeyJustAboveScrollBottom && markActivityKeyAsRead(activityKeyJustAboveScrollBottom); + + if (dispatchScrollPositionWithActivityId) { + const activity = getActivityByKey(activityKeyJustAboveScrollBottom); + + dispatchScrollPositionWithActivityId({ ...(activity ? { activityID: activity.id } : {}), scrollTop }); + } + }, + [ + focusElementMapRef, + dispatchScrollPositionWithActivityId, + getActivityByKey, + markActivityKeyAsRead, + rootElementRef + ] + ); + + useObserveScrollPosition(handleScrollPosition); + + const handleTranscriptKeyDown = useCallback>( + event => { + const { target } = event; + + const fromEndOfTranscriptIndicator = target === terminatorRef.current; + const fromTranscript = target === event.currentTarget; + + if (!fromEndOfTranscriptIndicator && !fromTranscript) { + return; + } - case 'Home': - focusRelativeActivity(-Infinity); - break; + let handled = true; - default: - handled = false; - break; - } + switch (event.key) { + case 'ArrowDown': + focusRelativeActivity(fromEndOfTranscriptIndicator ? 0 : 1); + break; - if (handled) { - event.preventDefault(); + case 'ArrowUp': + // eslint-disable-next-line no-magic-numbers + focusRelativeActivity(fromEndOfTranscriptIndicator ? 0 : -1); + break; - // If a custom HTML control wants to handle up/down arrow, we will prevent them from listening to this event to prevent bugs due to handling arrow keys twice. - event.stopPropagation(); - } - }, - [focusElementMapRef, focus, focusedKeyRef, focusRelativeActivity, terminatorRef] - ); - - const handleTranscriptKeyDownCapture = useCallback>( - event => { - const { altKey, ctrlKey, key, metaKey, target } = event; - - if ( - altKey || - (ctrlKey && key !== 'v' && key !== 'V') || - metaKey || - (!inputtableKey(key) && key !== 'Backspace') - ) { - // Ignore if one of the utility key (except SHIFT) is pressed - // E.g. CTRL-C on a link in one of the message should not jump to chat box - // E.g. "A" or "Backspace" should jump to chat box - return; - } + case 'End': + focusRelativeActivity(Infinity); + break; - // Send keystrokes to send box if we are focusing on the transcript or terminator. - if (target === event.currentTarget || target === terminatorRef.current) { - event.stopPropagation(); + case 'Enter': + // This is capturing plain ENTER. + // When screen reader is not running, or screen reader is running outside of scan mode, the ENTER key will be captured here. + if (!fromEndOfTranscriptIndicator) { + const focusElement = focusElementMapRef.current?.get(focusedKeyRef.current); + const activityFocusTrapTarget: HTMLElement = + focusElement?.querySelector('.webchat__basic-transcript__group-focus-target') ?? + focusElement?.querySelector('.webchat__basic-transcript__activity-focus-target'); + // TODO: review focus approach: + // It is not clear how to handle focus without introducing something like context. + // Ideally we would want a way to interact with focus outside of React + // so it doesn't cause transcript re-renders while still having an ability + // to scope activity-related handlers and data in a single place. + activityFocusTrapTarget?.focus(); + } - focus('sendBox'); - } - }, - [focus, terminatorRef] - ); - - useRegisterFocusTranscript(useCallback(() => focusByActivityKey(undefined), [focusByActivityKey])); - - // When the focusing activity has changed, dispatch an event to observers of "useObserveTranscriptFocus". - const dispatchTranscriptFocusByActivityKey = useDispatchTranscriptFocusByActivityKey(); - - // Dispatch a "transcript focus" event based on user selection. - // We should not dispatch "transcript focus" when a new activity come. Although the selection change, it is not initiated from the user. - useMemo( - () => dispatchTranscriptFocusByActivityKey(focusedExplicitly ? focusedKey : undefined), - [dispatchTranscriptFocusByActivityKey, focusedKey, focusedExplicitly] - ); - - // When the transcript is being focused on, we should dispatch a "transcriptfocus" event. - const handleFocus = useCallback( - // We call "focusByActivityKey" with activity key of "true". - // It means, tries to focus on anything. - ({ currentTarget, target }) => target === currentTarget && focusByActivityKey(true, false), - [focusByActivityKey] - ); - - // This is required by IE11. - // When the user clicks on and empty space (a.k.a. filler) in an empty transcript, IE11 says the focus is on the
, - // despite the fact there are no "tabIndex" attributes set on the filler. - // We need to artificially send the focus back to the transcript. - const handleFocusFiller = useCallback(() => focusByActivityKey(undefined), [focusByActivityKey]); - - // When focus into the transcript using TAB/SHIFT-TAB, scroll the focused activity into view. - useObserveFocusVisible( - rootElementRef, - useCallback(() => focusByActivityKey(undefined), [focusByActivityKey]) - ); - - const hasAnyChild = !!numRenderingActivities; - - return ( - for details. - aria-activedescendant={android ? undefined : activeDescendantId} - aria-label={transcriptAriaLabel} - className={classNames('webchat__basic-transcript', rootClassName, (className || '') + '')} - dir={direction} - onFocus={handleFocus} - onKeyDown={handleTranscriptKeyDown} - onKeyDownCapture={handleTranscriptKeyDownCapture} - ref={callbackRef} - // "aria-activedescendant" will only works with a number of roles and it must be explicitly set. - // https://www.w3.org/TR/wai-aria/#aria-activedescendant - role="group" - // For up/down arrow key navigation across activities, this component must be included in the tab sequence. - // Otherwise, "aria-activedescendant" will not be narrated when the user press up/down arrow keys. - // https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_focus_activedescendant - tabIndex={0} - > - - {hasAnyChild && } - - {hasAnyChild && } - - {hasAnyChild && ( - - - - - )} - - ); - } + break; + + case 'Escape': + focus('sendBoxWithoutKeyboard'); + break; + + case 'Home': + focusRelativeActivity(-Infinity); + break; + + default: + handled = false; + break; + } + + if (handled) { + event.preventDefault(); + + // If a custom HTML control wants to handle up/down arrow, we will prevent them from listening to this event to prevent bugs due to handling arrow keys twice. + event.stopPropagation(); + } + }, + [focusElementMapRef, focus, focusedKeyRef, focusRelativeActivity, terminatorRef] + ); + + const handleTranscriptKeyDownCapture = useCallback>( + event => { + const { altKey, ctrlKey, key, metaKey, target } = event; + + if ( + altKey || + (ctrlKey && key !== 'v' && key !== 'V') || + metaKey || + (!inputtableKey(key) && key !== 'Backspace') + ) { + // Ignore if one of the utility key (except SHIFT) is pressed + // E.g. CTRL-C on a link in one of the message should not jump to chat box + // E.g. "A" or "Backspace" should jump to chat box + return; + } + + // Send keystrokes to send box if we are focusing on the transcript or terminator. + if (target === event.currentTarget || target === terminatorRef.current) { + event.stopPropagation(); + + focus('sendBox'); + } + }, + [focus, terminatorRef] + ); + + useRegisterFocusTranscript(useCallback(() => focusByActivityKey(undefined), [focusByActivityKey])); + + // When the focusing activity has changed, dispatch an event to observers of "useObserveTranscriptFocus". + const dispatchTranscriptFocusByActivityKey = useDispatchTranscriptFocusByActivityKey(); + + // Dispatch a "transcript focus" event based on user selection. + // We should not dispatch "transcript focus" when a new activity come. Although the selection change, it is not initiated from the user. + useMemo( + () => dispatchTranscriptFocusByActivityKey(focusedExplicitly ? focusedKey : undefined), + [dispatchTranscriptFocusByActivityKey, focusedKey, focusedExplicitly] + ); + + // When the transcript is being focused on, we should dispatch a "transcriptfocus" event. + const handleFocus = useCallback( + // We call "focusByActivityKey" with activity key of "true". + // It means, tries to focus on anything. + ({ currentTarget, target }) => target === currentTarget && focusByActivityKey(true, false), + [focusByActivityKey] + ); + + // This is required by IE11. + // When the user clicks on and empty space (a.k.a. filler) in an empty transcript, IE11 says the focus is on the
, + // despite the fact there are no "tabIndex" attributes set on the filler. + // We need to artificially send the focus back to the transcript. + const handleFocusFiller = useCallback(() => focusByActivityKey(undefined), [focusByActivityKey]); + + // When focus into the transcript using TAB/SHIFT-TAB, scroll the focused activity into view. + useObserveFocusVisible( + rootElementRef, + useCallback(() => focusByActivityKey(undefined), [focusByActivityKey]) + ); + + const hasAnyChild = !!numRenderingActivities; + + return ( + for details. + aria-activedescendant={android ? undefined : activeDescendantId} + aria-label={transcriptAriaLabel} + className={classNames('webchat__basic-transcript', rootClassName, (className || '') + '')} + dir={direction} + onFocus={handleFocus} + onKeyDown={handleTranscriptKeyDown} + onKeyDownCapture={handleTranscriptKeyDownCapture} + ref={callbackRef} + // "aria-activedescendant" will only works with a number of roles and it must be explicitly set. + // https://www.w3.org/TR/wai-aria/#aria-activedescendant + role="group" + // For up/down arrow key navigation across activities, this component must be included in the tab sequence. + // Otherwise, "aria-activedescendant" will not be narrated when the user press up/down arrow keys. + // https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_focus_activedescendant + tabIndex={0} + > + + {hasAnyChild && } + + {hasAnyChild && } + + {hasAnyChild && ( + + + + + )} + + ); + } + ) ); InternalTranscript.displayName = 'InternalTranscript'; diff --git a/packages/component/src/Composer.tsx b/packages/component/src/Composer.tsx index 485ed99c1f..ff08a54691 100644 --- a/packages/component/src/Composer.tsx +++ b/packages/component/src/Composer.tsx @@ -1,5 +1,6 @@ /* eslint-disable react/require-default-props */ +import { useMemoIterable } from '@msinternal/botframework-webchat-react-hooks'; import { Composer as APIComposer, extractSendBoxMiddleware, @@ -11,15 +12,15 @@ import { type SendBoxToolbarMiddleware } from 'botframework-webchat-api'; import { DecoratorComposer, type DecoratorMiddleware } from 'botframework-webchat-api/decorator'; -import { createActivityPolymiddlewareFromLegacy, type Polymiddleware } from 'botframework-webchat-api/middleware'; +import { type Polymiddleware } from 'botframework-webchat-api/middleware'; import { singleToArray } from 'botframework-webchat-core'; +import { StoreDebugAPIRegistry, type StoreDebugAPI } from 'botframework-webchat-core/internal'; import classNames from 'classnames'; import MarkdownIt from 'markdown-it'; import PropTypes from 'prop-types'; import React, { memo, useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from 'react'; import { Composer as SayComposer } from 'react-say'; -import { StoreDebugAPIRegistry, type StoreDebugAPI } from 'botframework-webchat-core/internal'; import createDefaultAttachmentMiddleware from './Attachment/createMiddleware'; import BuiltInDecorator from './BuiltInDecorator'; import Dictation from './Dictation'; @@ -32,10 +33,10 @@ import UITracker from './hooks/internal/UITracker'; import WebChatUIContext from './hooks/internal/WebChatUIContext'; import { FocusSendBoxScope } from './hooks/sendBoxFocus'; import { ScrollRelativeTranscriptScope } from './hooks/transcriptScrollRelative'; -import createDefaultActivityMiddleware from './Middleware/Activity/createCoreMiddleware'; +import defaultActivityPolymiddleware from './Middleware/Activity/defaultActivityPolymiddleware'; import createDefaultActivityStatusMiddleware from './Middleware/ActivityStatus/createCoreMiddleware'; import createDefaultAttachmentForScreenReaderMiddleware from './Middleware/AttachmentForScreenReader/createCoreMiddleware'; -import createDefaultAvatarMiddleware from './Middleware/Avatar/createCoreMiddleware'; +import defaultAvatarPolymiddleware from './Middleware/Avatar/defaultAvatarPolymiddleware'; import createDefaultCardActionMiddleware from './Middleware/CardAction/createCoreMiddleware'; import createDefaultScrollToEndButtonMiddleware from './Middleware/ScrollToEndButton/createScrollToEndButtonMiddleware'; import createDefaultToastMiddleware from './Middleware/Toast/createCoreMiddleware'; @@ -413,15 +414,15 @@ const Composer = ({ [cardActionMiddleware, theme.cardActionMiddleware] ); - const patchedPolymiddleware = useMemo( + const patchedPolymiddleware = useMemoIterable( () => Object.freeze([ ...(polymiddleware || []), ...theme.polymiddleware, // Polymiddleware has lower priority than legacy middleware. // Later, we should move default middleware to a "default theme." - createActivityPolymiddlewareFromLegacy(...createDefaultActivityMiddleware()), - ...createDefaultAvatarMiddleware() + defaultActivityPolymiddleware, + defaultAvatarPolymiddleware ]), [polymiddleware, theme.polymiddleware] ); diff --git a/packages/component/src/Middleware/Activity/createCoreMiddleware.tsx b/packages/component/src/Middleware/Activity/createCoreMiddleware.tsx deleted file mode 100644 index e6b6434cd1..0000000000 --- a/packages/component/src/Middleware/Activity/createCoreMiddleware.tsx +++ /dev/null @@ -1,88 +0,0 @@ -/* eslint complexity: ["error", 21] */ -import { ActivityMiddleware } from 'botframework-webchat-api'; -import { - getActivityLivestreamingMetadata, - getOrgSchemaMessage, - isVoiceTranscriptActivity -} from 'botframework-webchat-core'; -import React from 'react'; - -import CarouselLayout from '../../Activity/CarouselLayout'; -import StackedLayout from '../../Activity/StackedLayout'; - -// TODO: [P4] Can we simplify these if-statement to something more readable? -function shouldFilterActivity(activity, messageThing) { - const { type } = activity; - if ( - type === 'conversationUpdate' || - (type === 'event' && !isVoiceTranscriptActivity(activity)) || - type === 'invoke' || - // Do not show content for contentless livestream interims, or finalized activity without content. - (type === 'typing' && - (getActivityLivestreamingMetadata(activity)?.type === 'contentless' || - !(activity['text'] || activity.attachments?.length > 0 || messageThing?.abstract))) || - (type === 'message' && - // Do not show postback - (activity.channelData?.postBack || - // Do not show messageBack if displayText is undefined - (activity.channelData?.messageBack && !activity.channelData.messageBack.displayText) || - // Do not show empty bubbles (no text and attachments) - !(activity.text || activity.attachments?.length || messageThing?.abstract))) - ) { - return true; - } - - return false; -} - -export default function createCoreMiddleware(): ActivityMiddleware[] { - return [ - () => - next => - (...args) => { - const [{ activity }] = args; - const isMessageOrTyping = activity.type === 'message' || activity.type === 'typing'; - - const messageThing = getOrgSchemaMessage(activity.entities); - - // Filter out activities that should not visible. - if (shouldFilterActivity(activity, messageThing)) { - return false; - } else if (isMessageOrTyping || isVoiceTranscriptActivity(activity)) { - if ( - isMessageOrTyping && - (activity.attachments?.length || 0) > 1 && - activity.attachmentLayout === 'carousel' - ) { - // The following line is not a React functional component, it's a render function called by useCreateActivityRenderer() hook. - // The function signature need to be compatible with older version of activity middleware, which was: - // - // renderActivity( - // renderAttachment: ({ activity, attachment }) => React.Element - // ) => React.Element - - return function renderCarouselLayout(renderAttachment, props) { - typeof props === 'undefined' && - console.warn( - 'botframework-webchat: One or more arguments were missing after passing through the activity middleware. Please check your custom activity middleware to make sure it passes all arguments.' - ); - - return ; - }; - } - - // The following line is not a React functional component, it's a render function called by useCreateActivityRenderer() hook. - return function renderStackedLayout(renderAttachment, props) { - typeof props === 'undefined' && - console.warn( - 'botframework-webchat: One or more arguments were missing after passing through the activity middleware. Please check your custom activity middleware to make sure it passes all arguments.' - ); - - return ; - }; - } - - return next(...args); - } - ]; -} diff --git a/packages/component/src/Middleware/Activity/defaultActivityPolymiddleware.tsx b/packages/component/src/Middleware/Activity/defaultActivityPolymiddleware.tsx new file mode 100644 index 0000000000..db55ba2243 --- /dev/null +++ b/packages/component/src/Middleware/Activity/defaultActivityPolymiddleware.tsx @@ -0,0 +1,87 @@ +/* eslint complexity: ["error", 21] */ +import { ActivityMiddleware } from 'botframework-webchat-api'; +import { + getActivityLivestreamingMetadata, + getOrgSchemaMessage, + isVoiceTranscriptActivity +} from 'botframework-webchat-core'; +import React from 'react'; + +import CarouselLayout from '../../Activity/CarouselLayout'; +import StackedLayout from '../../Activity/StackedLayout'; +import { createActivityPolymiddlewareFromLegacy, type Polymiddleware } from 'botframework-webchat-api/middleware'; + +// TODO: [P4] Can we simplify these if-statement to something more readable? +function shouldFilterActivity(activity, messageThing) { + const { type } = activity; + if ( + type === 'conversationUpdate' || + (type === 'event' && !isVoiceTranscriptActivity(activity)) || + type === 'invoke' || + // Do not show content for contentless livestream interims, or finalized activity without content. + (type === 'typing' && + (getActivityLivestreamingMetadata(activity)?.type === 'contentless' || + !(activity['text'] || activity.attachments?.length > 0 || messageThing?.abstract))) || + (type === 'message' && + // Do not show postback + (activity.channelData?.postBack || + // Do not show messageBack if displayText is undefined + (activity.channelData?.messageBack && !activity.channelData.messageBack.displayText) || + // Do not show empty bubbles (no text and attachments) + !(activity.text || activity.attachments?.length || messageThing?.abstract))) + ) { + return true; + } + + return false; +} + +function createCoreMiddleware(): ActivityMiddleware { + return () => + next => + (...args) => { + const [{ activity }] = args; + const isMessageOrTyping = activity.type === 'message' || activity.type === 'typing'; + + const messageThing = getOrgSchemaMessage(activity.entities); + + // Filter out activities that should not visible. + if (shouldFilterActivity(activity, messageThing)) { + return false; + } else if (isMessageOrTyping || isVoiceTranscriptActivity(activity)) { + if (isMessageOrTyping && (activity.attachments?.length || 0) > 1 && activity.attachmentLayout === 'carousel') { + // The following line is not a React functional component, it's a render function called by useCreateActivityRenderer() hook. + // The function signature need to be compatible with older version of activity middleware, which was: + // + // renderActivity( + // renderAttachment: ({ activity, attachment }) => React.Element + // ) => React.Element + + return function renderCarouselLayout(renderAttachment, props) { + typeof props === 'undefined' && + console.warn( + 'botframework-webchat: One or more arguments were missing after passing through the activity middleware. Please check your custom activity middleware to make sure it passes all arguments.' + ); + + return ; + }; + } + + // The following line is not a React functional component, it's a render function called by useCreateActivityRenderer() hook. + return function renderStackedLayout(renderAttachment, props) { + typeof props === 'undefined' && + console.warn( + 'botframework-webchat: One or more arguments were missing after passing through the activity middleware. Please check your custom activity middleware to make sure it passes all arguments.' + ); + + return ; + }; + } + + return next(...args); + }; +} + +const defaultActivityPolymiddleware: Polymiddleware = createActivityPolymiddlewareFromLegacy(createCoreMiddleware()); + +export default defaultActivityPolymiddleware; diff --git a/packages/component/src/Middleware/Avatar/createCoreMiddleware.tsx b/packages/component/src/Middleware/Avatar/createCoreMiddleware.tsx deleted file mode 100644 index dcd580fade..0000000000 --- a/packages/component/src/Middleware/Avatar/createCoreMiddleware.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { __INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol } from 'botframework-webchat-api/internal'; -import { - avatarComponent, - createAvatarPolymiddleware, - type AvatarPolymiddleware -} from 'botframework-webchat-api/middleware'; -import DefaultAvatar from './DefaultAvatar'; - -export default function createDefaultAvatarMiddleware(): readonly AvatarPolymiddleware[] { - return Object.freeze([ - createAvatarPolymiddleware( - _next => - ({ - fromUser, - [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: { - botAvatarImage, - botAvatarInitials, - userAvatarImage, - userAvatarInitials - } - }) => - (fromUser ? userAvatarImage || userAvatarInitials : botAvatarImage || botAvatarInitials) - ? avatarComponent(DefaultAvatar, Object.freeze({ fromUser })) - : undefined - ) - ]); -} diff --git a/packages/component/src/Middleware/Avatar/defaultAvatarPolymiddleware.tsx b/packages/component/src/Middleware/Avatar/defaultAvatarPolymiddleware.tsx new file mode 100644 index 0000000000..c35cc9ce53 --- /dev/null +++ b/packages/component/src/Middleware/Avatar/defaultAvatarPolymiddleware.tsx @@ -0,0 +1,21 @@ +import { __INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol } from 'botframework-webchat-api/internal'; +import { avatarComponent, createAvatarPolymiddleware } from 'botframework-webchat-api/middleware'; +import DefaultAvatar from './DefaultAvatar'; + +const defaultAvatarMiddleware = createAvatarPolymiddleware( + _next => + ({ + fromUser, + [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: { + botAvatarImage, + botAvatarInitials, + userAvatarImage, + userAvatarInitials + } + }) => + (fromUser ? userAvatarImage || userAvatarInitials : botAvatarImage || botAvatarInitials) + ? avatarComponent(DefaultAvatar, Object.freeze({ fromUser })) + : undefined +); + +export default defaultAvatarMiddleware; From d4c112cb951b458f77faa906980fb8acd77de3bd Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 23 Mar 2026 01:52:49 +0000 Subject: [PATCH 15/51] Add watch deps --- packages/api-middleware/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/api-middleware/package.json b/packages/api-middleware/package.json index e89165124a..9b4b1aaf94 100644 --- a/packages/api-middleware/package.json +++ b/packages/api-middleware/package.json @@ -69,7 +69,7 @@ "precommit:eslint": "../../node_modules/.bin/eslint --report-unused-disable-directives --max-warnings 0", "precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false", "preversion": "../../scripts/npm/preversion.sh", - "start": "../../scripts/npm/notify-build.sh \"src\" \"../base/package.json\" \"../react-hooks/package.json\" \"../react-valibot/package.json\"" + "start": "../../scripts/npm/notify-build.sh \"src\" \"../react-hooks/package.json\" \"../react-valibot/package.json\"" }, "pinDependencies": { "react-wrap-with": [ From 7f0f9aaf4e6cc5c8c45f91a07bb3fbd87034295d Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 23 Mar 2026 02:00:23 +0000 Subject: [PATCH 16/51] Fix signature change --- .../GroupActivitiesComposer.tsx | 4 +- .../defaultActivityPolymiddleware.tsx | 80 +++++++++++-------- packages/component/src/index.ts | 2 +- 3 files changed, 49 insertions(+), 37 deletions(-) diff --git a/packages/api/src/providers/GroupActivities/GroupActivitiesComposer.tsx b/packages/api/src/providers/GroupActivities/GroupActivitiesComposer.tsx index 8dedd511a8..a32a9ab488 100644 --- a/packages/api/src/providers/GroupActivities/GroupActivitiesComposer.tsx +++ b/packages/api/src/providers/GroupActivities/GroupActivitiesComposer.tsx @@ -13,7 +13,7 @@ import isGroupingValid from './private/isGroupingValid'; type GroupActivitiesComposerProps = Readonly<{ children?: ReactNode | undefined; - groupActivitiesMiddleware: readonly GroupActivitiesMiddleware[]; + groupActivitiesMiddleware: readonly GroupActivitiesMiddleware[] | undefined; }>; function GroupActivitiesComposer({ children, groupActivitiesMiddleware }: GroupActivitiesComposerProps) { @@ -24,7 +24,7 @@ function GroupActivitiesComposer({ children, groupActivitiesMiddleware }: GroupA () => applyMiddleware( 'group activities', - ...groupActivitiesMiddleware, + ...(groupActivitiesMiddleware ?? []), ...createDefaultGroupActivitiesMiddleware({ groupTimestamp, ponyfill }), () => () => () => ({}) ), diff --git a/packages/component/src/Middleware/Activity/defaultActivityPolymiddleware.tsx b/packages/component/src/Middleware/Activity/defaultActivityPolymiddleware.tsx index db55ba2243..d2e1529327 100644 --- a/packages/component/src/Middleware/Activity/defaultActivityPolymiddleware.tsx +++ b/packages/component/src/Middleware/Activity/defaultActivityPolymiddleware.tsx @@ -7,9 +7,9 @@ import { } from 'botframework-webchat-core'; import React from 'react'; +import { createActivityPolymiddlewareFromLegacy, type Polymiddleware } from 'botframework-webchat-api/middleware'; import CarouselLayout from '../../Activity/CarouselLayout'; import StackedLayout from '../../Activity/StackedLayout'; -import { createActivityPolymiddlewareFromLegacy, type Polymiddleware } from 'botframework-webchat-api/middleware'; // TODO: [P4] Can we simplify these if-statement to something more readable? function shouldFilterActivity(activity, messageThing) { @@ -36,52 +36,64 @@ function shouldFilterActivity(activity, messageThing) { return false; } -function createCoreMiddleware(): ActivityMiddleware { - return () => - next => - (...args) => { - const [{ activity }] = args; - const isMessageOrTyping = activity.type === 'message' || activity.type === 'typing'; +/** + * @deprecated Use `defaultActivityPolymiddleware` instead. The `createCoreActivityMiddleware` will be removed on or after 2028-03-18. + */ +function createCoreActivityMiddleware(): readonly ActivityMiddleware[] { + return Object.freeze([ + () => + next => + (...args) => { + const [{ activity }] = args; + const isMessageOrTyping = activity.type === 'message' || activity.type === 'typing'; - const messageThing = getOrgSchemaMessage(activity.entities); + const messageThing = getOrgSchemaMessage(activity.entities); - // Filter out activities that should not visible. - if (shouldFilterActivity(activity, messageThing)) { - return false; - } else if (isMessageOrTyping || isVoiceTranscriptActivity(activity)) { - if (isMessageOrTyping && (activity.attachments?.length || 0) > 1 && activity.attachmentLayout === 'carousel') { - // The following line is not a React functional component, it's a render function called by useCreateActivityRenderer() hook. - // The function signature need to be compatible with older version of activity middleware, which was: - // - // renderActivity( - // renderAttachment: ({ activity, attachment }) => React.Element - // ) => React.Element + // Filter out activities that should not visible. + if (shouldFilterActivity(activity, messageThing)) { + return false; + } else if (isMessageOrTyping || isVoiceTranscriptActivity(activity)) { + if ( + isMessageOrTyping && + (activity.attachments?.length || 0) > 1 && + activity.attachmentLayout === 'carousel' + ) { + // The following line is not a React functional component, it's a render function called by useCreateActivityRenderer() hook. + // The function signature need to be compatible with older version of activity middleware, which was: + // + // renderActivity( + // renderAttachment: ({ activity, attachment }) => React.Element + // ) => React.Element + + return function renderCarouselLayout(renderAttachment, props) { + typeof props === 'undefined' && + console.warn( + 'botframework-webchat: One or more arguments were missing after passing through the activity middleware. Please check your custom activity middleware to make sure it passes all arguments.' + ); - return function renderCarouselLayout(renderAttachment, props) { + return ; + }; + } + + // The following line is not a React functional component, it's a render function called by useCreateActivityRenderer() hook. + return function renderStackedLayout(renderAttachment, props) { typeof props === 'undefined' && console.warn( 'botframework-webchat: One or more arguments were missing after passing through the activity middleware. Please check your custom activity middleware to make sure it passes all arguments.' ); - return ; + return ; }; } - // The following line is not a React functional component, it's a render function called by useCreateActivityRenderer() hook. - return function renderStackedLayout(renderAttachment, props) { - typeof props === 'undefined' && - console.warn( - 'botframework-webchat: One or more arguments were missing after passing through the activity middleware. Please check your custom activity middleware to make sure it passes all arguments.' - ); - - return ; - }; + return next(...args); } - - return next(...args); - }; + ]); } -const defaultActivityPolymiddleware: Polymiddleware = createActivityPolymiddlewareFromLegacy(createCoreMiddleware()); +const defaultActivityPolymiddleware: Polymiddleware = createActivityPolymiddlewareFromLegacy( + ...createCoreActivityMiddleware() +); export default defaultActivityPolymiddleware; +export { createCoreActivityMiddleware }; diff --git a/packages/component/src/index.ts b/packages/component/src/index.ts index 8d4269df49..e8fd434caa 100644 --- a/packages/component/src/index.ts +++ b/packages/component/src/index.ts @@ -3,7 +3,7 @@ export { type WebChatActivity } from 'botframework-webchat-core'; export { default as createCoreAttachmentMiddleware } from './Attachment/createMiddleware'; export { default as Context } from './hooks/internal/WebChatUIContext'; -export { default as createCoreActivityMiddleware } from './Middleware/Activity/createCoreMiddleware'; +export { createCoreActivityMiddleware } from './Middleware/Activity/defaultActivityPolymiddleware'; export { default as createCoreActivityStatusMiddleware } from './Middleware/ActivityStatus/createCoreMiddleware'; export { type HTMLContentTransformEnhancer, From 8d0cf168299e620a710c3c830cab6ba9848844fe Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 23 Mar 2026 04:16:05 +0000 Subject: [PATCH 17/51] Refactor singleToArray nd OneOrMany --- packages/api/src/hooks/Composer.tsx | 3 +-- packages/base/src/utils/OneOrMany.ts | 4 ++++ packages/base/src/utils/index.ts | 2 ++ packages/base/src/utils/singleToArray.ts | 4 ++++ packages/bundle/src/AddFullBundle.tsx | 3 +-- packages/component/src/Composer.tsx | 2 +- packages/component/src/Utils/singleToArray.ts | 3 --- packages/core/src/index.ts | 15 +++++++-------- packages/core/src/types/OneOrMany.ts | 3 --- packages/core/src/utils/singleToArray.ts | 3 --- 10 files changed, 20 insertions(+), 22 deletions(-) create mode 100644 packages/base/src/utils/OneOrMany.ts create mode 100644 packages/base/src/utils/singleToArray.ts delete mode 100644 packages/component/src/Utils/singleToArray.ts delete mode 100644 packages/core/src/types/OneOrMany.ts delete mode 100644 packages/core/src/utils/singleToArray.ts diff --git a/packages/api/src/hooks/Composer.tsx b/packages/api/src/hooks/Composer.tsx index ae57ce5426..26b9b09826 100644 --- a/packages/api/src/hooks/Composer.tsx +++ b/packages/api/src/hooks/Composer.tsx @@ -4,6 +4,7 @@ import { type LegacyActivityMiddleware, type LegacyAttachmentMiddleware } from '@msinternal/botframework-webchat-api-middleware/legacy'; +import { singleToArray, type OneOrMany } from '@msinternal/botframework-webchat-base/utils'; import { useMemoIterable } from '@msinternal/botframework-webchat-react-hooks'; import { ReduxStoreComposer } from '@msinternal/botframework-webchat-redux-store'; import { @@ -28,7 +29,6 @@ import { setSendBoxAttachments, setSendTimeout, setSendTypingIndicator, - singleToArray, startDictate, startSpeakingActivity, startVoiceRecording, @@ -38,7 +38,6 @@ import { submitSendBox, type DirectLineJSBotConnection, type GlobalScopePonyfill, - type OneOrMany, type WebChatActivity } from 'botframework-webchat-core'; import PropTypes from 'prop-types'; diff --git a/packages/base/src/utils/OneOrMany.ts b/packages/base/src/utils/OneOrMany.ts new file mode 100644 index 0000000000..f518640bd1 --- /dev/null +++ b/packages/base/src/utils/OneOrMany.ts @@ -0,0 +1,4 @@ +/** @deprecated Will be removed on or after 2028-03-18. */ +type OneOrMany = T | T[]; + +export { type OneOrMany }; diff --git a/packages/base/src/utils/index.ts b/packages/base/src/utils/index.ts index f1681595a1..b8c0a3242f 100644 --- a/packages/base/src/utils/index.ts +++ b/packages/base/src/utils/index.ts @@ -2,5 +2,7 @@ export { default as createBuildInfo, type BuildInfo, type ReadonlyBuildInfo } fr export { default as deprecateObject } from './deprecateObject'; export { default as isForbiddenPropertyName } from './isForbiddenPropertyName'; export { default as iterateEquals } from './iterateEquals'; +export { type OneOrMany } from './OneOrMany'; +export { default as singleToArray } from './singleToArray'; export { default as warnOnce } from './warnOnce'; export { default as withResolvers, type PromiseWithResolvers } from './withResolvers'; diff --git a/packages/base/src/utils/singleToArray.ts b/packages/base/src/utils/singleToArray.ts new file mode 100644 index 0000000000..f823ffd5a5 --- /dev/null +++ b/packages/base/src/utils/singleToArray.ts @@ -0,0 +1,4 @@ +/** @deprecated Will be removed on or after 2028-03-18. */ +export default function singleToArray(singleOrArray: T | T[]): T[] { + return singleOrArray ? (Array.isArray(singleOrArray) ? [...singleOrArray] : [singleOrArray]) : []; +} diff --git a/packages/bundle/src/AddFullBundle.tsx b/packages/bundle/src/AddFullBundle.tsx index 370789f191..7a5ea98769 100644 --- a/packages/bundle/src/AddFullBundle.tsx +++ b/packages/bundle/src/AddFullBundle.tsx @@ -1,11 +1,10 @@ -import { warnOnce } from '@msinternal/botframework-webchat-base/utils'; +import { singleToArray, warnOnce, type OneOrMany } from '@msinternal/botframework-webchat-base/utils'; import { type AttachmentForScreenReaderMiddleware, type AttachmentMiddleware, type StyleOptions } from 'botframework-webchat-api'; import { type HTMLContentTransformMiddleware } from 'botframework-webchat-component'; -import { singleToArray, type OneOrMany } from 'botframework-webchat-core'; import React, { memo, type ReactNode } from 'react'; import AdaptiveCardsComposer from './adaptiveCards/AdaptiveCardsComposer'; diff --git a/packages/component/src/Composer.tsx b/packages/component/src/Composer.tsx index ff08a54691..039fe5883e 100644 --- a/packages/component/src/Composer.tsx +++ b/packages/component/src/Composer.tsx @@ -1,5 +1,6 @@ /* eslint-disable react/require-default-props */ +import { singleToArray } from '@msinternal/botframework-webchat-base/utils'; import { useMemoIterable } from '@msinternal/botframework-webchat-react-hooks'; import { Composer as APIComposer, @@ -13,7 +14,6 @@ import { } from 'botframework-webchat-api'; import { DecoratorComposer, type DecoratorMiddleware } from 'botframework-webchat-api/decorator'; import { type Polymiddleware } from 'botframework-webchat-api/middleware'; -import { singleToArray } from 'botframework-webchat-core'; import { StoreDebugAPIRegistry, type StoreDebugAPI } from 'botframework-webchat-core/internal'; import classNames from 'classnames'; import MarkdownIt from 'markdown-it'; diff --git a/packages/component/src/Utils/singleToArray.ts b/packages/component/src/Utils/singleToArray.ts deleted file mode 100644 index 2e59925b9b..0000000000 --- a/packages/component/src/Utils/singleToArray.ts +++ /dev/null @@ -1,3 +0,0 @@ -export default function singleToArray(singleOrArray: T | T[]): T[] { - return singleOrArray ? (Array.isArray(singleOrArray) ? singleOrArray : [singleOrArray]) : []; -} diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index c29a003704..fadb704911 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -6,6 +6,7 @@ import markActivity from './actions/markActivity'; import muteVoiceRecording from './actions/muteVoiceRecording'; import postActivity from './actions/postActivity'; import postVoiceActivity from './actions/postVoiceActivity'; +import type { VoiceHandler } from './actions/registerVoiceHandler'; import registerVoiceHandler from './actions/registerVoiceHandler'; import sendEvent from './actions/sendEvent'; import sendFiles from './actions/sendFiles'; @@ -20,6 +21,7 @@ import setSendBox from './actions/setSendBox'; import setSendBoxAttachments from './actions/setSendBoxAttachments'; import setSendTimeout from './actions/setSendTimeout'; import setSendTypingIndicator from './actions/setSendTypingIndicator'; +import type { VoiceState } from './actions/setVoiceState'; import setVoiceState from './actions/setVoiceState'; import startDictate from './actions/startDictate'; import startSpeakingActivity from './actions/startSpeakingActivity'; @@ -36,7 +38,6 @@ import createStore, { withDevTools as createStoreWithDevTools, withOptions as createStoreWithOptions } from './createStore'; -import OneOrMany from './types/OneOrMany'; import { parseAction } from './types/external/OrgSchema/Action'; import { parseClaim } from './types/external/OrgSchema/Claim'; import { parseCreativeWork } from './types/external/OrgSchema/CreativeWork'; @@ -47,13 +48,10 @@ import { parseVoteAction } from './types/external/OrgSchema/VoteAction'; import getActivityLivestreamingMetadata from './utils/getActivityLivestreamingMetadata'; import getOrgSchemaMessage from './utils/getOrgSchemaMessage'; import onErrorResumeNext from './utils/onErrorResumeNext'; -import singleToArray from './utils/singleToArray'; -import isVoiceActivity from './utils/voiceActivity/isVoiceActivity'; -import isVoiceTranscriptActivity from './utils/voiceActivity/isVoiceTranscriptActivity'; import getVoiceActivityRole from './utils/voiceActivity/getVoiceActivityRole'; import getVoiceActivityText from './utils/voiceActivity/getVoiceActivityText'; -import type { VoiceState } from './actions/setVoiceState'; -import type { VoiceHandler } from './actions/registerVoiceHandler'; +import isVoiceActivity from './utils/voiceActivity/isVoiceActivity'; +import isVoiceTranscriptActivity from './utils/voiceActivity/isVoiceTranscriptActivity'; export { isForbiddenPropertyName, @@ -100,6 +98,9 @@ import type { Project as OrgSchemaProject } from './types/external/OrgSchema/Pro import type { Thing as OrgSchemaThing } from './types/external/OrgSchema/Thing'; import type { UserReview as OrgSchemaUserReview } from './types/external/OrgSchema/UserReview'; +/** @deprecated */ +export { singleToArray, type OneOrMany } from '@msinternal/botframework-webchat-base/utils'; + const Constants = { ActivityClientState, DictateState }; export { @@ -144,7 +145,6 @@ export { setSendTimeout, setSendTypingIndicator, setVoiceState, - singleToArray, startDictate, startSpeakingActivity, startVoiceRecording, @@ -172,7 +172,6 @@ export type { DirectLineVideoCard, GlobalScopePonyfill, Observable, - OneOrMany, OrgSchemaAction, OrgSchemaClaim, OrgSchemaCreativeWork, diff --git a/packages/core/src/types/OneOrMany.ts b/packages/core/src/types/OneOrMany.ts deleted file mode 100644 index 905b1b6cee..0000000000 --- a/packages/core/src/types/OneOrMany.ts +++ /dev/null @@ -1,3 +0,0 @@ -type OneOrMany = T | T[]; - -export default OneOrMany; diff --git a/packages/core/src/utils/singleToArray.ts b/packages/core/src/utils/singleToArray.ts deleted file mode 100644 index 2e59925b9b..0000000000 --- a/packages/core/src/utils/singleToArray.ts +++ /dev/null @@ -1,3 +0,0 @@ -export default function singleToArray(singleOrArray: T | T[]): T[] { - return singleOrArray ? (Array.isArray(singleOrArray) ? singleOrArray : [singleOrArray]) : []; -} From 26a8cbe1d384fccf43a65fede07aff2b757452d4 Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 23 Mar 2026 05:01:12 +0000 Subject: [PATCH 18/51] Fix AddFullBundle rerendering --- package-lock.json | 1 + packages/bundle/package.json | 1 + packages/bundle/src/AddFullBundle.tsx | 19 +++++++++++++++---- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index a7773e9765..a43abde56b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21168,6 +21168,7 @@ "@msinternal/base64-js": "0.0.0-0", "@msinternal/botframework-directlinejs": "0.0.0-0", "@msinternal/botframework-webchat-base": "0.0.0-0", + "@msinternal/botframework-webchat-react-hooks": "0.0.0-0", "@msinternal/botframework-webchat-react-valibot": "0.0.0-0", "@msinternal/botframework-webchat-styles": "0.0.0-0", "@msinternal/botframework-webchat-tsconfig": "0.0.0-0", diff --git a/packages/bundle/package.json b/packages/bundle/package.json index ece75748b4..a5ccb07ba1 100644 --- a/packages/bundle/package.json +++ b/packages/bundle/package.json @@ -182,6 +182,7 @@ "@msinternal/base64-js": "0.0.0-0", "@msinternal/botframework-directlinejs": "0.0.0-0", "@msinternal/botframework-webchat-base": "0.0.0-0", + "@msinternal/botframework-webchat-react-hooks": "0.0.0-0", "@msinternal/botframework-webchat-react-valibot": "0.0.0-0", "@msinternal/botframework-webchat-styles": "0.0.0-0", "@msinternal/botframework-webchat-tsconfig": "0.0.0-0", diff --git a/packages/bundle/src/AddFullBundle.tsx b/packages/bundle/src/AddFullBundle.tsx index 7a5ea98769..1581051852 100644 --- a/packages/bundle/src/AddFullBundle.tsx +++ b/packages/bundle/src/AddFullBundle.tsx @@ -1,4 +1,5 @@ import { singleToArray, warnOnce, type OneOrMany } from '@msinternal/botframework-webchat-base/utils'; +import { useMemoIterable } from '@msinternal/botframework-webchat-react-hooks'; import { type AttachmentForScreenReaderMiddleware, type AttachmentMiddleware, @@ -45,8 +46,8 @@ function AddFullBundle({ adaptiveCardHostConfig, adaptiveCardsHostConfig, adaptiveCardsPackage, - attachmentForScreenReaderMiddleware, - attachmentMiddleware, + attachmentForScreenReaderMiddleware: attachmentForScreenReaderMiddlewareFromProps, + attachmentMiddleware: attachmentMiddlewareFromProps, children, htmlContentTransformMiddleware, nonce, @@ -56,9 +57,19 @@ function AddFullBundle({ }: AddFullBundleProps) { adaptiveCardHostConfig && adaptiveCardHostConfigDeprecation(); + const attachmentForScreenReaderMiddleware = useMemoIterable( + () => singleToArray(attachmentForScreenReaderMiddlewareFromProps), + [attachmentForScreenReaderMiddlewareFromProps] + ); + + const attachmentMiddleware = useMemoIterable( + () => singleToArray(attachmentMiddlewareFromProps), + [attachmentMiddlewareFromProps] + ); + const patchedProps = useComposerProps({ - attachmentForScreenReaderMiddleware: singleToArray(attachmentForScreenReaderMiddleware), - attachmentMiddleware: singleToArray(attachmentMiddleware), + attachmentForScreenReaderMiddleware, + attachmentMiddleware, htmlContentTransformMiddleware, renderMarkdown, styleOptions, From 696eb9894b95a53f200fbb2d2695e5f7f223cd6d Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 23 Mar 2026 05:01:19 +0000 Subject: [PATCH 19/51] Clean up singleToArray --- packages/api/src/boot/middleware.ts | 5 ++ packages/api/src/hooks/Composer.tsx | 18 +++---- packages/base/src/utils/OneOrMany.ts | 2 +- packages/base/src/utils/singleToArray.ts | 5 ++ packages/component/src/Composer.tsx | 61 ++++++++++++++---------- 5 files changed, 56 insertions(+), 35 deletions(-) diff --git a/packages/api/src/boot/middleware.ts b/packages/api/src/boot/middleware.ts index a38e239327..2e7611e28b 100644 --- a/packages/api/src/boot/middleware.ts +++ b/packages/api/src/boot/middleware.ts @@ -44,6 +44,11 @@ export { type ErrorBoxPolymiddlewareRequest } from '@msinternal/botframework-webchat-api-middleware'; +export { + type LegacyActivityMiddleware, + type LegacyAvatarMiddleware +} from '@msinternal/botframework-webchat-api-middleware/legacy'; + export { default as createActivityPolymiddlewareFromLegacy } from '../legacy/createActivityPolymiddlewareFromLegacy'; export { default as createAvatarPolymiddlewareFromLegacy } from '../legacy/createAvatarPolymiddlewareFromLegacy'; diff --git a/packages/api/src/hooks/Composer.tsx b/packages/api/src/hooks/Composer.tsx index 26b9b09826..a5673f0f61 100644 --- a/packages/api/src/hooks/Composer.tsx +++ b/packages/api/src/hooks/Composer.tsx @@ -216,15 +216,15 @@ type ComposerCoreProps = Readonly<{ /** * @deprecated Use `polymiddleware` instead. The `activityMiddleware` prop is being deprecated, please use `polymiddleware` instead. This prop will be removed on or after 2027-08-21. */ - activityMiddleware?: OneOrMany; - activityStatusMiddleware?: OneOrMany; - attachmentForScreenReaderMiddleware?: OneOrMany; - attachmentMiddleware?: OneOrMany; + activityMiddleware?: OneOrMany | undefined; + activityStatusMiddleware?: OneOrMany | undefined; + attachmentForScreenReaderMiddleware?: OneOrMany | undefined; + attachmentMiddleware?: OneOrMany | undefined; /** * @deprecated Use `polymiddleware` instead. The `avatarMiddleware` prop is being deprecated, please use `polymiddleware` instead. This prop will be removed on or after 2028-03-16. */ - avatarMiddleware?: OneOrMany; - cardActionMiddleware?: OneOrMany; + avatarMiddleware?: OneOrMany | undefined; + cardActionMiddleware?: OneOrMany | undefined; children?: ReactNode | ((context: ContextOf>) => ReactNode); dir?: string; directLine: DirectLineJSBotConnection; @@ -242,7 +242,7 @@ type ComposerCoreProps = Readonly<{ grammars?: any; groupActivitiesMiddleware?: OneOrMany | undefined; locale?: string; - polymiddleware?: readonly Polymiddleware[]; + polymiddleware?: readonly Polymiddleware[] | undefined; onTelemetry?: (event: TelemetryMeasurementEvent) => void; overrideLocalizedStrings?: LocalizedStrings | ((strings: LocalizedStrings, language: string) => LocalizedStrings); renderMarkdown?: ( @@ -250,13 +250,13 @@ type ComposerCoreProps = Readonly<{ newLineOptions: { markdownRespectCRLF: boolean }, linkOptions: { externalLinkAlt: string } ) => string; - scrollToEndButtonMiddleware?: OneOrMany; + scrollToEndButtonMiddleware?: OneOrMany | undefined; selectVoice?: (voices: (typeof window.SpeechSynthesisVoice)[], activity: WebChatActivity) => void; sendBoxMiddleware?: readonly SendBoxMiddleware[] | undefined; sendBoxToolbarMiddleware?: readonly SendBoxToolbarMiddleware[] | undefined; sendTypingIndicator?: boolean; toastMiddleware?: OneOrMany | undefined; - typingIndicatorMiddleware?: OneOrMany; + typingIndicatorMiddleware?: OneOrMany | undefined; /** * Sets the state of the UI. * diff --git a/packages/base/src/utils/OneOrMany.ts b/packages/base/src/utils/OneOrMany.ts index f518640bd1..b9f95411b1 100644 --- a/packages/base/src/utils/OneOrMany.ts +++ b/packages/base/src/utils/OneOrMany.ts @@ -1,4 +1,4 @@ /** @deprecated Will be removed on or after 2028-03-18. */ -type OneOrMany = T | T[]; +type OneOrMany = T | readonly T[]; export { type OneOrMany }; diff --git a/packages/base/src/utils/singleToArray.ts b/packages/base/src/utils/singleToArray.ts index f823ffd5a5..b2bcdf6d17 100644 --- a/packages/base/src/utils/singleToArray.ts +++ b/packages/base/src/utils/singleToArray.ts @@ -1,3 +1,8 @@ +/** @deprecated Will be removed on or after 2028-03-18. */ +export default function singleToArray(singleOrArray: T | T[]): T[]; +/** @deprecated Will be removed on or after 2028-03-18. */ +export default function singleToArray(singleOrArray: T | readonly T[]): readonly T[]; + /** @deprecated Will be removed on or after 2028-03-18. */ export default function singleToArray(singleOrArray: T | T[]): T[] { return singleOrArray ? (Array.isArray(singleOrArray) ? [...singleOrArray] : [singleOrArray]) : []; diff --git a/packages/component/src/Composer.tsx b/packages/component/src/Composer.tsx index 039fe5883e..ef81c8853c 100644 --- a/packages/component/src/Composer.tsx +++ b/packages/component/src/Composer.tsx @@ -9,11 +9,12 @@ import { hooks, WebSpeechPonyfillFactory, type ComposerProps as APIComposerProps, + type AvatarMiddleware, type SendBoxMiddleware, type SendBoxToolbarMiddleware } from 'botframework-webchat-api'; import { DecoratorComposer, type DecoratorMiddleware } from 'botframework-webchat-api/decorator'; -import { type Polymiddleware } from 'botframework-webchat-api/middleware'; +import { type LegacyActivityMiddleware, type Polymiddleware } from 'botframework-webchat-api/middleware'; import { StoreDebugAPIRegistry, type StoreDebugAPI } from 'botframework-webchat-core/internal'; import classNames from 'classnames'; import MarkdownIt from 'markdown-it'; @@ -368,49 +369,59 @@ const Composer = ({ const { nonce, onTelemetry } = composerProps; const theme = useTheme(); - const patchedActivityMiddleware = useMemo( - () => [...singleToArray(activityMiddleware), ...theme.activityMiddleware], + const patchedActivityMiddleware = useMemo( + () => + activityMiddleware?.length || theme?.activityMiddleware?.length + ? Object.freeze([...singleToArray(activityMiddleware ?? []), ...theme.activityMiddleware]) + : undefined, [activityMiddleware, theme.activityMiddleware] ); const patchedActivityStatusMiddleware = useMemo( - () => [ - ...singleToArray(activityStatusMiddleware), - ...theme.activityStatusMiddleware, - ...createDefaultActivityStatusMiddleware() - ], + () => + Object.freeze([ + ...singleToArray(activityStatusMiddleware ?? []), + ...theme.activityStatusMiddleware, + ...createDefaultActivityStatusMiddleware() + ]), [activityStatusMiddleware, theme.activityStatusMiddleware] ); const patchedAttachmentForScreenReaderMiddleware = useMemo( - () => [ - ...singleToArray(attachmentForScreenReaderMiddleware), - ...theme.attachmentForScreenReaderMiddleware, - ...createDefaultAttachmentForScreenReaderMiddleware() - ], + () => + Object.freeze([ + ...singleToArray(attachmentForScreenReaderMiddleware ?? []), + ...theme.attachmentForScreenReaderMiddleware, + ...createDefaultAttachmentForScreenReaderMiddleware() + ]), [attachmentForScreenReaderMiddleware, theme.attachmentForScreenReaderMiddleware] ); const patchedAttachmentMiddleware = useMemo( - () => [ - ...singleToArray(attachmentMiddleware), - ...theme.attachmentMiddleware, - ...createDefaultAttachmentMiddleware() - ], + () => + Object.freeze([ + ...singleToArray(attachmentMiddleware ?? []), + ...theme.attachmentMiddleware, + ...createDefaultAttachmentMiddleware() + ]), [attachmentMiddleware, theme.attachmentMiddleware] ); - const patchedAvatarMiddleware = useMemo( - () => [...singleToArray(avatarMiddleware), ...theme.avatarMiddleware], + const patchedAvatarMiddleware = useMemo( + () => + avatarMiddleware?.length || theme?.avatarMiddleware?.length + ? Object.freeze([...singleToArray(avatarMiddleware), ...theme.avatarMiddleware]) + : undefined, [avatarMiddleware, theme.avatarMiddleware] ); const patchedCardActionMiddleware = useMemo( - () => [ - ...singleToArray(cardActionMiddleware), - ...theme.cardActionMiddleware, - ...createDefaultCardActionMiddleware() - ], + () => + Object.freeze([ + ...singleToArray(cardActionMiddleware), + ...theme.cardActionMiddleware, + ...createDefaultCardActionMiddleware() + ]), [cardActionMiddleware, theme.cardActionMiddleware] ); From a165f97e3a2d47ab9677e068e977ffc998889ee9 Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 23 Mar 2026 05:22:24 +0000 Subject: [PATCH 20/51] Fix typings --- packages/bundle/package.json | 1 + packages/bundle/src/useComposerProps.ts | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/bundle/package.json b/packages/bundle/package.json index a5ccb07ba1..672cb8905a 100644 --- a/packages/bundle/package.json +++ b/packages/bundle/package.json @@ -153,6 +153,7 @@ "@msinternal/base64-js": "development", "@msinternal/botframework-directlinejs": "development", "@msinternal/botframework-webchat-base": "development", + "@msinternal/botframework-webchat-react-hooks": "development", "@msinternal/botframework-webchat-react-valibot": "development", "@msinternal/botframework-webchat-styles": "development", "@msinternal/botframework-webchat-tsconfig": "development", diff --git a/packages/bundle/src/useComposerProps.ts b/packages/bundle/src/useComposerProps.ts index e7eca3b7a9..f3679b054b 100644 --- a/packages/bundle/src/useComposerProps.ts +++ b/packages/bundle/src/useComposerProps.ts @@ -16,8 +16,8 @@ export default function useComposerProps({ styleOptions, styleSet }: Readonly<{ - attachmentForScreenReaderMiddleware: AttachmentForScreenReaderMiddleware[]; - attachmentMiddleware: AttachmentMiddleware[]; + attachmentForScreenReaderMiddleware: readonly AttachmentForScreenReaderMiddleware[] | undefined; + attachmentMiddleware: readonly AttachmentMiddleware[] | undefined; htmlContentTransformMiddleware: readonly HTMLContentTransformMiddleware[]; renderMarkdown?: ( markdown: string, @@ -38,12 +38,12 @@ export default function useComposerProps({ ) => string; }> { const patchedAttachmentMiddleware = useMemo( - () => [...attachmentMiddleware, createAdaptiveCardsAttachmentMiddleware()], + () => [...(attachmentMiddleware ?? []), createAdaptiveCardsAttachmentMiddleware()], [attachmentMiddleware] ); const patchedAttachmentForScreenReaderMiddleware = useMemo( - () => [...attachmentForScreenReaderMiddleware, createAdaptiveCardsAttachmentForScreenReaderMiddleware()], + () => [...(attachmentForScreenReaderMiddleware ?? []), createAdaptiveCardsAttachmentForScreenReaderMiddleware()], [attachmentForScreenReaderMiddleware] ); From 004af6c7ecce25ef243d9383726e25abdde0d740 Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 23 Mar 2026 06:42:57 +0000 Subject: [PATCH 21/51] Use undefined if array is empty --- packages/bundle/src/AddFullBundle.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/bundle/src/AddFullBundle.tsx b/packages/bundle/src/AddFullBundle.tsx index 1581051852..c920ce86f6 100644 --- a/packages/bundle/src/AddFullBundle.tsx +++ b/packages/bundle/src/AddFullBundle.tsx @@ -57,13 +57,18 @@ function AddFullBundle({ }: AddFullBundleProps) { adaptiveCardHostConfig && adaptiveCardHostConfigDeprecation(); - const attachmentForScreenReaderMiddleware = useMemoIterable( - () => singleToArray(attachmentForScreenReaderMiddlewareFromProps), + const attachmentForScreenReaderMiddleware = useMemoIterable< + readonly AttachmentForScreenReaderMiddleware[] | undefined + >( + () => + attachmentForScreenReaderMiddlewareFromProps?.length + ? singleToArray(attachmentForScreenReaderMiddlewareFromProps) + : undefined, [attachmentForScreenReaderMiddlewareFromProps] ); - const attachmentMiddleware = useMemoIterable( - () => singleToArray(attachmentMiddlewareFromProps), + const attachmentMiddleware = useMemoIterable( + () => (attachmentMiddlewareFromProps?.length ? singleToArray(attachmentMiddlewareFromProps) : undefined), [attachmentMiddlewareFromProps] ); From f8c22740b641e52f755dc49f0bc53d82be11698b Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 23 Mar 2026 06:49:44 +0000 Subject: [PATCH 22/51] Clean up polymiddleware array --- packages/api/src/hooks/Composer.tsx | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/packages/api/src/hooks/Composer.tsx b/packages/api/src/hooks/Composer.tsx index a5673f0f61..d4435f30f5 100644 --- a/packages/api/src/hooks/Composer.tsx +++ b/packages/api/src/hooks/Composer.tsx @@ -477,11 +477,8 @@ const ComposerCore = ({ [groupActivitiesMiddlewareFromProps] ); - const polymiddlewareForLegacyAvatarMiddleware = useMemo( - () => - avatarMiddleware - ? Object.freeze([createAvatarPolymiddlewareFromLegacy(...singleToArray(avatarMiddleware))]) - : undefined, + const polymiddlewareForLegacyAvatarMiddleware = useMemo( + () => (avatarMiddleware ? createAvatarPolymiddlewareFromLegacy(...singleToArray(avatarMiddleware)) : undefined), [avatarMiddleware] ); @@ -526,11 +523,9 @@ const ComposerCore = ({ [scrollToEndButtonMiddleware] ); - const polymiddlewareForLegacyActivityMiddleware = useMemo( + const polymiddlewareForLegacyActivityMiddleware = useMemo( () => - activityMiddleware - ? Object.freeze([createActivityPolymiddlewareFromLegacy(...singleToArray(activityMiddleware))]) - : undefined, + activityMiddleware ? createActivityPolymiddlewareFromLegacy(...singleToArray(activityMiddleware)) : undefined, [activityMiddleware] ); @@ -560,8 +555,8 @@ const ComposerCore = ({ // // The simplest and logical move is #3: render legacy middleware before polymiddleware. - ...(polymiddlewareForLegacyActivityMiddleware ?? []), - ...(polymiddlewareForLegacyAvatarMiddleware ?? []), + ...(polymiddlewareForLegacyActivityMiddleware ? [polymiddlewareForLegacyActivityMiddleware] : []), + ...(polymiddlewareForLegacyAvatarMiddleware ? [polymiddlewareForLegacyAvatarMiddleware] : []), ...(polymiddlewareFromProps ?? []), activityFallbackPolymiddleware ]), From d23385f6fd24b7c01e212e2a90c597eed24c8058 Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 23 Mar 2026 06:54:17 +0000 Subject: [PATCH 23/51] Fix avatarMiddleware --- packages/component/src/Composer.tsx | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/packages/component/src/Composer.tsx b/packages/component/src/Composer.tsx index ef81c8853c..0cac1e8a77 100644 --- a/packages/component/src/Composer.tsx +++ b/packages/component/src/Composer.tsx @@ -369,13 +369,11 @@ const Composer = ({ const { nonce, onTelemetry } = composerProps; const theme = useTheme(); - const patchedActivityMiddleware = useMemo( - () => - activityMiddleware?.length || theme?.activityMiddleware?.length - ? Object.freeze([...singleToArray(activityMiddleware ?? []), ...theme.activityMiddleware]) - : undefined, - [activityMiddleware, theme.activityMiddleware] - ); + const patchedActivityMiddleware = useMemo(() => { + const middleware = Object.freeze([...singleToArray(activityMiddleware ?? []), ...theme.activityMiddleware]); + + return middleware.length ? middleware : undefined; + }, [activityMiddleware, theme.activityMiddleware]); const patchedActivityStatusMiddleware = useMemo( () => @@ -407,13 +405,11 @@ const Composer = ({ [attachmentMiddleware, theme.attachmentMiddleware] ); - const patchedAvatarMiddleware = useMemo( - () => - avatarMiddleware?.length || theme?.avatarMiddleware?.length - ? Object.freeze([...singleToArray(avatarMiddleware), ...theme.avatarMiddleware]) - : undefined, - [avatarMiddleware, theme.avatarMiddleware] - ); + const patchedAvatarMiddleware = useMemo(() => { + const middleware = Object.freeze([...singleToArray(avatarMiddleware), ...theme.avatarMiddleware]); + + return middleware.length ? middleware : undefined; + }, [avatarMiddleware, theme.avatarMiddleware]); const patchedCardActionMiddleware = useMemo( () => From 5ce745c458726361b36df94c72a8e64fdd237ba2 Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 23 Mar 2026 07:33:31 +0000 Subject: [PATCH 24/51] Fix middleware.length --- packages/api/src/hooks/Composer.tsx | 25 ++++++++++++--------- packages/bundle/src/AddFullBundle.tsx | 21 +++++++++-------- packages/component/src/Composer.tsx | 10 ++++----- packages/react-hooks/src/useMemoIterable.ts | 2 +- 4 files changed, 31 insertions(+), 27 deletions(-) diff --git a/packages/api/src/hooks/Composer.tsx b/packages/api/src/hooks/Composer.tsx index d4435f30f5..0dee0db463 100644 --- a/packages/api/src/hooks/Composer.tsx +++ b/packages/api/src/hooks/Composer.tsx @@ -342,7 +342,7 @@ const ComposerCore = ({ const cardActionContext = useMemo( () => createCardActionContext({ - cardActionMiddleware: Object.freeze([...singleToArray(cardActionMiddleware)]), + cardActionMiddleware: Object.freeze([...singleToArray(cardActionMiddleware ?? [])]), continuous: !!styleOptions.speechRecognitionContinuous, directLine, dispatch, @@ -422,7 +422,7 @@ const ComposerCore = ({ applyMiddlewareForRenderer( 'activity status', { strict: false }, - ...singleToArray(activityStatusMiddleware), + ...singleToArray(activityStatusMiddleware ?? []), () => () => () => false )({}), [activityStatusMiddleware] @@ -433,7 +433,7 @@ const ComposerCore = ({ applyMiddlewareForRenderer( 'attachment for screen reader', { strict: true }, - ...singleToArray(attachmentForScreenReaderMiddleware), + ...singleToArray(attachmentForScreenReaderMiddleware ?? []), () => () => ({ attachment }) => { @@ -457,7 +457,7 @@ const ComposerCore = ({ () => applyMiddlewareForLegacyRenderer( 'attachment', - ...singleToArray(attachmentMiddleware), + ...singleToArray(attachmentMiddleware ?? []), () => () => ({ attachment }) => { @@ -473,12 +473,15 @@ const ComposerCore = ({ const groupActivitiesMiddleware = useMemoIterable( () => - groupActivitiesMiddlewareFromProps ? Object.freeze(singleToArray(groupActivitiesMiddlewareFromProps)) : undefined, + groupActivitiesMiddlewareFromProps + ? Object.freeze(singleToArray(groupActivitiesMiddlewareFromProps ?? [])) + : undefined, [groupActivitiesMiddlewareFromProps] ); const polymiddlewareForLegacyAvatarMiddleware = useMemo( - () => (avatarMiddleware ? createAvatarPolymiddlewareFromLegacy(...singleToArray(avatarMiddleware)) : undefined), + () => + avatarMiddleware ? createAvatarPolymiddlewareFromLegacy(...singleToArray(avatarMiddleware ?? [])) : undefined, [avatarMiddleware] ); @@ -487,7 +490,7 @@ const ComposerCore = ({ applyMiddlewareForRenderer( 'toast', { strict: false }, - ...singleToArray(toastMiddleware), + ...singleToArray(toastMiddleware ?? []), () => () => ({ notification }) => { @@ -506,7 +509,7 @@ const ComposerCore = ({ applyMiddlewareForRenderer( 'typing indicator', { strict: false }, - ...singleToArray(typingIndicatorMiddleware), + ...singleToArray(typingIndicatorMiddleware ?? []), () => () => () => false )({}), [typingIndicatorMiddleware] @@ -517,7 +520,7 @@ const ComposerCore = ({ applyMiddlewareForRenderer( 'scroll to end button', { strict: true }, - ...singleToArray(scrollToEndButtonMiddleware), + ...singleToArray(scrollToEndButtonMiddleware ?? []), () => () => () => false )() as any, [scrollToEndButtonMiddleware] @@ -525,7 +528,9 @@ const ComposerCore = ({ const polymiddlewareForLegacyActivityMiddleware = useMemo( () => - activityMiddleware ? createActivityPolymiddlewareFromLegacy(...singleToArray(activityMiddleware)) : undefined, + activityMiddleware + ? createActivityPolymiddlewareFromLegacy(...singleToArray(activityMiddleware ?? [])) + : undefined, [activityMiddleware] ); diff --git a/packages/bundle/src/AddFullBundle.tsx b/packages/bundle/src/AddFullBundle.tsx index c920ce86f6..b876055f5e 100644 --- a/packages/bundle/src/AddFullBundle.tsx +++ b/packages/bundle/src/AddFullBundle.tsx @@ -59,18 +59,17 @@ function AddFullBundle({ const attachmentForScreenReaderMiddleware = useMemoIterable< readonly AttachmentForScreenReaderMiddleware[] | undefined - >( - () => - attachmentForScreenReaderMiddlewareFromProps?.length - ? singleToArray(attachmentForScreenReaderMiddlewareFromProps) - : undefined, - [attachmentForScreenReaderMiddlewareFromProps] - ); + >(() => { + const middleware = singleToArray(attachmentForScreenReaderMiddlewareFromProps); - const attachmentMiddleware = useMemoIterable( - () => (attachmentMiddlewareFromProps?.length ? singleToArray(attachmentMiddlewareFromProps) : undefined), - [attachmentMiddlewareFromProps] - ); + return middleware.length ? middleware : undefined; + }, [attachmentForScreenReaderMiddlewareFromProps]); + + const attachmentMiddleware = useMemoIterable(() => { + const middleware = singleToArray(attachmentMiddlewareFromProps); + + return middleware.length ? middleware : undefined; + }, [attachmentMiddlewareFromProps]); const patchedProps = useComposerProps({ attachmentForScreenReaderMiddleware, diff --git a/packages/component/src/Composer.tsx b/packages/component/src/Composer.tsx index 0cac1e8a77..24defa72d0 100644 --- a/packages/component/src/Composer.tsx +++ b/packages/component/src/Composer.tsx @@ -406,7 +406,7 @@ const Composer = ({ ); const patchedAvatarMiddleware = useMemo(() => { - const middleware = Object.freeze([...singleToArray(avatarMiddleware), ...theme.avatarMiddleware]); + const middleware = Object.freeze([...singleToArray(avatarMiddleware ?? []), ...theme.avatarMiddleware]); return middleware.length ? middleware : undefined; }, [avatarMiddleware, theme.avatarMiddleware]); @@ -414,7 +414,7 @@ const Composer = ({ const patchedCardActionMiddleware = useMemo( () => Object.freeze([ - ...singleToArray(cardActionMiddleware), + ...singleToArray(cardActionMiddleware ?? []), ...theme.cardActionMiddleware, ...createDefaultCardActionMiddleware() ]), @@ -435,13 +435,13 @@ const Composer = ({ ); const patchedToastMiddleware = useMemo( - () => [...singleToArray(toastMiddleware), ...theme.toastMiddleware, ...createDefaultToastMiddleware()], + () => [...singleToArray(toastMiddleware ?? []), ...theme.toastMiddleware, ...createDefaultToastMiddleware()], [toastMiddleware, theme.toastMiddleware] ); const patchedTypingIndicatorMiddleware = useMemo( () => [ - ...singleToArray(typingIndicatorMiddleware), + ...singleToArray(typingIndicatorMiddleware ?? []), ...theme.typingIndicatorMiddleware, ...createDefaultTypingIndicatorMiddleware() ], @@ -452,7 +452,7 @@ const Composer = ({ const patchedScrollToEndButtonMiddleware = useMemo( () => [ - ...singleToArray(scrollToEndButtonMiddleware), + ...singleToArray(scrollToEndButtonMiddleware ?? []), ...theme.scrollToEndButtonMiddleware, ...defaultScrollToEndButtonMiddleware ], diff --git a/packages/react-hooks/src/useMemoIterable.ts b/packages/react-hooks/src/useMemoIterable.ts index b9c0de884c..87d5fb73c7 100644 --- a/packages/react-hooks/src/useMemoIterable.ts +++ b/packages/react-hooks/src/useMemoIterable.ts @@ -6,6 +6,6 @@ export default function useMemoIterable>(factory: () return useMemoWithPrevious(prevValue => { const value = factory(); - return prevValue && iterateEquals(value, prevValue) ? prevValue : value; + return typeof prevValue !== 'undefined' && iterateEquals(value, prevValue) ? prevValue : value; }, deps); } From 356004f480827da573ab4245bbcb229d3e0548f2 Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 23 Mar 2026 07:51:10 +0000 Subject: [PATCH 25/51] Fix ESLint --- packages/base/src/utils/iterateEquals.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/base/src/utils/iterateEquals.ts b/packages/base/src/utils/iterateEquals.ts index fb305fe2ab..ad57006d41 100644 --- a/packages/base/src/utils/iterateEquals.ts +++ b/packages/base/src/utils/iterateEquals.ts @@ -1,10 +1,10 @@ +// eslint-disable-next-line no-magic-numbers const MAX_ITERATION = 1_000_000; export default function iterateEquals(x: Iterable, y: Iterable): boolean { const xIterator = x[Symbol.iterator](); const yIterator = y[Symbol.iterator](); - // eslint-disable-next-line no-magic-numbers for (let count = 0; count < MAX_ITERATION; count++) { const resultX = xIterator.next(); const resultY = yIterator.next(); From bcaee945fab2a0be39f28effc07eb8786838670c Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 23 Mar 2026 07:54:58 +0000 Subject: [PATCH 26/51] Add displayName --- packages/api/src/legacy/LegacyActivityBridge.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/api/src/legacy/LegacyActivityBridge.tsx b/packages/api/src/legacy/LegacyActivityBridge.tsx index 00240ee122..a9c5d7e5fc 100644 --- a/packages/api/src/legacy/LegacyActivityBridge.tsx +++ b/packages/api/src/legacy/LegacyActivityBridge.tsx @@ -72,4 +72,6 @@ function LegacyActivityBridge(props: LegacyActivityBridgeComponentProps) { return {children}; } +LegacyActivityBridge.displayName = 'LegacyActivityBridge'; + export default memo(LegacyActivityBridge); From d6b8fe70f724f7bf80c0ca3389c459c7862a6035 Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 23 Mar 2026 08:22:30 +0000 Subject: [PATCH 27/51] Fix test --- ...acyActivityMiddleware.reactionButtons.html | 45 ++++++++++--------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/__tests__/html2/transcript/legacyActivityMiddleware.reactionButtons.html b/__tests__/html2/transcript/legacyActivityMiddleware.reactionButtons.html index fc02670349..2fffc5a2d6 100644 --- a/__tests__/html2/transcript/legacyActivityMiddleware.reactionButtons.html +++ b/__tests__/html2/transcript/legacyActivityMiddleware.reactionButtons.html @@ -1,4 +1,4 @@ - + @@ -44,7 +44,7 @@ } } = window; - const BotActivityDecorator = ({ activityID, children }) => ( + const BotActivityDecorator = ({ activityId, children }) => (
  • @@ -58,28 +58,33 @@
); - const activityMiddleware = () => next => (...args) => { - const [ - { - activity, - activity: { - from: { role } + const activityMiddleware = + () => + next => + (...args) => { + const [ + { + activity, + activity: { + from: { role } + } } - } - ] = args; + ] = args; - if (role === 'bot') { - const { id } = activity; + const handler = next(...args); - return (...renderArgs) => ( - - {next(...args)(...renderArgs)} - - ); - } + if (role === 'bot') { + const { id } = activity; + + return (...renderArgs) => ( + + {handler(...renderArgs)} + + ); + } - return next(...args); - }; + return handler; + }; run(async function () { const now = Date.now(); From 731597198f7b436209416d7bc461ef9beec6aa99 Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 23 Mar 2026 08:50:30 +0000 Subject: [PATCH 28/51] Add waitFor --- ...Button.persistWhileCallingUseScrollTo.html | 53 +++++++++++++------ 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/__tests__/html2/scrollToEndButton/scrollToEndButton.persistWhileCallingUseScrollTo.html b/__tests__/html2/scrollToEndButton/scrollToEndButton.persistWhileCallingUseScrollTo.html index b47e98155f..7d7b906a4d 100644 --- a/__tests__/html2/scrollToEndButton/scrollToEndButton.persistWhileCallingUseScrollTo.html +++ b/__tests__/html2/scrollToEndButton/scrollToEndButton.persistWhileCallingUseScrollTo.html @@ -1,22 +1,38 @@ - + - +
- From 86d6d438b03f4e024ee75a12ca65a11c2876972d Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 23 Mar 2026 09:23:13 +0000 Subject: [PATCH 29/51] Clean up useMemoIterable --- packages/api/src/hooks/Composer.tsx | 28 +++++----- packages/bundle/src/AddFullBundle.tsx | 20 +++---- packages/component/src/Composer.tsx | 76 +++++++++++++++------------ 3 files changed, 67 insertions(+), 57 deletions(-) diff --git a/packages/api/src/hooks/Composer.tsx b/packages/api/src/hooks/Composer.tsx index 0dee0db463..8744263ca2 100644 --- a/packages/api/src/hooks/Composer.tsx +++ b/packages/api/src/hooks/Composer.tsx @@ -100,6 +100,7 @@ import useStyleOptions from './useStyleOptions'; import ErrorBoundary from './utils/ErrorBoundary'; import observableToPromise from './utils/observableToPromise'; import { parseUIState } from './validation/uiState'; +import type { ActivityMiddleware } from '../../dist/botframework-webchat-api.mjs'; // List of Redux actions factory we are hoisting as Web Chat functions const DISPATCHERS = { @@ -272,11 +273,11 @@ type ComposerCoreProps = Readonly<{ }>; const ComposerCore = ({ - activityMiddleware, + activityMiddleware: activityMiddlewareFromProps, activityStatusMiddleware, attachmentForScreenReaderMiddleware, attachmentMiddleware, - avatarMiddleware, + avatarMiddleware: avatarMiddlewareFromProps, cardActionMiddleware, children, dir, @@ -472,16 +473,17 @@ const ComposerCore = ({ ); const groupActivitiesMiddleware = useMemoIterable( - () => - groupActivitiesMiddlewareFromProps - ? Object.freeze(singleToArray(groupActivitiesMiddlewareFromProps ?? [])) - : undefined, + () => Object.freeze(singleToArray(groupActivitiesMiddlewareFromProps ?? [])), [groupActivitiesMiddlewareFromProps] ); + const avatarMiddleware = useMemoIterable( + () => singleToArray(avatarMiddlewareFromProps ?? []), + [avatarMiddlewareFromProps] + ); + const polymiddlewareForLegacyAvatarMiddleware = useMemo( - () => - avatarMiddleware ? createAvatarPolymiddlewareFromLegacy(...singleToArray(avatarMiddleware ?? [])) : undefined, + () => createAvatarPolymiddlewareFromLegacy(...avatarMiddleware), [avatarMiddleware] ); @@ -526,11 +528,13 @@ const ComposerCore = ({ [scrollToEndButtonMiddleware] ); + const activityMiddleware = useMemoIterable( + () => singleToArray(activityMiddlewareFromProps ?? []), + [activityMiddlewareFromProps] + ); + const polymiddlewareForLegacyActivityMiddleware = useMemo( - () => - activityMiddleware - ? createActivityPolymiddlewareFromLegacy(...singleToArray(activityMiddleware ?? [])) - : undefined, + () => createActivityPolymiddlewareFromLegacy(...activityMiddleware), [activityMiddleware] ); diff --git a/packages/bundle/src/AddFullBundle.tsx b/packages/bundle/src/AddFullBundle.tsx index b876055f5e..20a57b2e47 100644 --- a/packages/bundle/src/AddFullBundle.tsx +++ b/packages/bundle/src/AddFullBundle.tsx @@ -57,19 +57,15 @@ function AddFullBundle({ }: AddFullBundleProps) { adaptiveCardHostConfig && adaptiveCardHostConfigDeprecation(); - const attachmentForScreenReaderMiddleware = useMemoIterable< - readonly AttachmentForScreenReaderMiddleware[] | undefined - >(() => { - const middleware = singleToArray(attachmentForScreenReaderMiddlewareFromProps); - - return middleware.length ? middleware : undefined; - }, [attachmentForScreenReaderMiddlewareFromProps]); - - const attachmentMiddleware = useMemoIterable(() => { - const middleware = singleToArray(attachmentMiddlewareFromProps); + const attachmentForScreenReaderMiddleware = useMemoIterable( + () => singleToArray(attachmentForScreenReaderMiddlewareFromProps), + [attachmentForScreenReaderMiddlewareFromProps] + ); - return middleware.length ? middleware : undefined; - }, [attachmentMiddlewareFromProps]); + const attachmentMiddleware = useMemoIterable( + () => singleToArray(attachmentMiddlewareFromProps), + [attachmentMiddlewareFromProps] + ); const patchedProps = useComposerProps({ attachmentForScreenReaderMiddleware, diff --git a/packages/component/src/Composer.tsx b/packages/component/src/Composer.tsx index 24defa72d0..2cc9ca2ccd 100644 --- a/packages/component/src/Composer.tsx +++ b/packages/component/src/Composer.tsx @@ -4,14 +4,21 @@ import { singleToArray } from '@msinternal/botframework-webchat-base/utils'; import { useMemoIterable } from '@msinternal/botframework-webchat-react-hooks'; import { Composer as APIComposer, + AttachmentForScreenReaderMiddleware, extractSendBoxMiddleware, extractSendBoxToolbarMiddleware, hooks, WebSpeechPonyfillFactory, + type ActivityStatusMiddleware, type ComposerProps as APIComposerProps, + type AttachmentMiddleware, type AvatarMiddleware, + type CardActionMiddleware, + type ScrollToEndButtonMiddleware, type SendBoxMiddleware, - type SendBoxToolbarMiddleware + type SendBoxToolbarMiddleware, + type ToastMiddleware, + type TypingIndicatorMiddleware } from 'botframework-webchat-api'; import { DecoratorComposer, type DecoratorMiddleware } from 'botframework-webchat-api/decorator'; import { type LegacyActivityMiddleware, type Polymiddleware } from 'botframework-webchat-api/middleware'; @@ -369,13 +376,12 @@ const Composer = ({ const { nonce, onTelemetry } = composerProps; const theme = useTheme(); - const patchedActivityMiddleware = useMemo(() => { - const middleware = Object.freeze([...singleToArray(activityMiddleware ?? []), ...theme.activityMiddleware]); - - return middleware.length ? middleware : undefined; - }, [activityMiddleware, theme.activityMiddleware]); + const patchedActivityMiddleware = useMemo( + () => Object.freeze([...singleToArray(activityMiddleware ?? []), ...theme.activityMiddleware]), + [activityMiddleware, theme.activityMiddleware] + ); - const patchedActivityStatusMiddleware = useMemo( + const patchedActivityStatusMiddleware = useMemoIterable( () => Object.freeze([ ...singleToArray(activityStatusMiddleware ?? []), @@ -385,7 +391,7 @@ const Composer = ({ [activityStatusMiddleware, theme.activityStatusMiddleware] ); - const patchedAttachmentForScreenReaderMiddleware = useMemo( + const patchedAttachmentForScreenReaderMiddleware = useMemoIterable( () => Object.freeze([ ...singleToArray(attachmentForScreenReaderMiddleware ?? []), @@ -395,7 +401,7 @@ const Composer = ({ [attachmentForScreenReaderMiddleware, theme.attachmentForScreenReaderMiddleware] ); - const patchedAttachmentMiddleware = useMemo( + const patchedAttachmentMiddleware = useMemoIterable( () => Object.freeze([ ...singleToArray(attachmentMiddleware ?? []), @@ -405,13 +411,12 @@ const Composer = ({ [attachmentMiddleware, theme.attachmentMiddleware] ); - const patchedAvatarMiddleware = useMemo(() => { - const middleware = Object.freeze([...singleToArray(avatarMiddleware ?? []), ...theme.avatarMiddleware]); - - return middleware.length ? middleware : undefined; - }, [avatarMiddleware, theme.avatarMiddleware]); + const patchedAvatarMiddleware = useMemoIterable( + () => Object.freeze([...singleToArray(avatarMiddleware ?? []), ...theme.avatarMiddleware]), + [avatarMiddleware, theme.avatarMiddleware] + ); - const patchedCardActionMiddleware = useMemo( + const patchedCardActionMiddleware = useMemoIterable( () => Object.freeze([ ...singleToArray(cardActionMiddleware ?? []), @@ -434,32 +439,37 @@ const Composer = ({ [polymiddleware, theme.polymiddleware] ); - const patchedToastMiddleware = useMemo( - () => [...singleToArray(toastMiddleware ?? []), ...theme.toastMiddleware, ...createDefaultToastMiddleware()], + const patchedToastMiddleware = useMemoIterable( + () => + Object.freeze([ + ...singleToArray(toastMiddleware ?? []), + ...theme.toastMiddleware, + ...createDefaultToastMiddleware() + ]), [toastMiddleware, theme.toastMiddleware] ); - const patchedTypingIndicatorMiddleware = useMemo( - () => [ - ...singleToArray(typingIndicatorMiddleware ?? []), - ...theme.typingIndicatorMiddleware, - ...createDefaultTypingIndicatorMiddleware() - ], + const patchedTypingIndicatorMiddleware = useMemoIterable( + () => + Object.freeze([ + ...singleToArray(typingIndicatorMiddleware ?? []), + ...theme.typingIndicatorMiddleware, + ...createDefaultTypingIndicatorMiddleware() + ]), [typingIndicatorMiddleware, theme.typingIndicatorMiddleware] ); - const defaultScrollToEndButtonMiddleware = useMemo(() => createDefaultScrollToEndButtonMiddleware(), []); - - const patchedScrollToEndButtonMiddleware = useMemo( - () => [ - ...singleToArray(scrollToEndButtonMiddleware ?? []), - ...theme.scrollToEndButtonMiddleware, - ...defaultScrollToEndButtonMiddleware - ], - [defaultScrollToEndButtonMiddleware, scrollToEndButtonMiddleware, theme.scrollToEndButtonMiddleware] + const patchedScrollToEndButtonMiddleware = useMemoIterable( + () => + Object.freeze([ + ...singleToArray(scrollToEndButtonMiddleware ?? []), + ...theme.scrollToEndButtonMiddleware, + ...createDefaultScrollToEndButtonMiddleware() + ]), + [scrollToEndButtonMiddleware, theme.scrollToEndButtonMiddleware] ); - const sendBoxMiddleware = useMemo( + const sendBoxMiddleware = useMemoIterable( () => Object.freeze([ ...extractSendBoxMiddleware(sendBoxMiddlewareFromProps), From 37bd3f63bb15b1b43e35b0f0c1093110c985cc09 Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 23 Mar 2026 09:58:50 +0000 Subject: [PATCH 30/51] Fix import --- packages/api/src/hooks/Composer.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/api/src/hooks/Composer.tsx b/packages/api/src/hooks/Composer.tsx index 8744263ca2..98a74c9ce5 100644 --- a/packages/api/src/hooks/Composer.tsx +++ b/packages/api/src/hooks/Composer.tsx @@ -100,7 +100,6 @@ import useStyleOptions from './useStyleOptions'; import ErrorBoundary from './utils/ErrorBoundary'; import observableToPromise from './utils/observableToPromise'; import { parseUIState } from './validation/uiState'; -import type { ActivityMiddleware } from '../../dist/botframework-webchat-api.mjs'; // List of Redux actions factory we are hoisting as Web Chat functions const DISPATCHERS = { @@ -528,7 +527,7 @@ const ComposerCore = ({ [scrollToEndButtonMiddleware] ); - const activityMiddleware = useMemoIterable( + const activityMiddleware = useMemoIterable( () => singleToArray(activityMiddlewareFromProps ?? []), [activityMiddlewareFromProps] ); From 89644bc455fec101b60891f3878096456fef63c4 Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 23 Mar 2026 10:43:09 +0000 Subject: [PATCH 31/51] Remove no-magic-numbers --- packages/base/src/utils/iterateEquals.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/base/src/utils/iterateEquals.ts b/packages/base/src/utils/iterateEquals.ts index ad57006d41..bb9ad460e8 100644 --- a/packages/base/src/utils/iterateEquals.ts +++ b/packages/base/src/utils/iterateEquals.ts @@ -1,4 +1,3 @@ -// eslint-disable-next-line no-magic-numbers const MAX_ITERATION = 1_000_000; export default function iterateEquals(x: Iterable, y: Iterable): boolean { From 94649accb5b48a738e8a251ad325b2536ff0e413 Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 23 Mar 2026 11:07:51 +0000 Subject: [PATCH 32/51] Should only show 1 message --- __tests__/html2/timestamp/attachmentSendTimeout.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/__tests__/html2/timestamp/attachmentSendTimeout.html b/__tests__/html2/timestamp/attachmentSendTimeout.html index 04064bdbc0..ae0564f207 100644 --- a/__tests__/html2/timestamp/attachmentSendTimeout.html +++ b/__tests__/html2/timestamp/attachmentSendTimeout.html @@ -5,6 +5,7 @@ + @@ -91,6 +92,7 @@ updateProps(props => updateIn(props, ['styleOptions', 'sendTimeoutForAttachments'], () => 130000)); // THEN: It should revive the message and show "Sending" again. + expect(pageElements.activities()).toHaveProperty('length', 1); await expect(pageElements.activityStatuses()[1].innerText).toBe('Sending'); await host.snapshot('local'); }, From 10b6ffc6e2f63ff7a2528ca7ad9029b75f8b7489 Mon Sep 17 00:00:00 2001 From: William Wong Date: Tue, 24 Mar 2026 01:56:12 +0000 Subject: [PATCH 33/51] Fix runHook twice --- __tests__/html2/timestamp/attachmentSendTimeout.html | 7 +++++-- .../testHelpers/createRunHookActivityMiddleware.js | 12 ++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/__tests__/html2/timestamp/attachmentSendTimeout.html b/__tests__/html2/timestamp/attachmentSendTimeout.html index ae0564f207..f228c59b65 100644 --- a/__tests__/html2/timestamp/attachmentSendTimeout.html +++ b/__tests__/html2/timestamp/attachmentSendTimeout.html @@ -65,7 +65,11 @@ fileBlob.name = 'empty.zip'; // WHEN: Sending out the file. - await pageObjects.runHook(({ useSendFiles }) => useSendFiles()([fileBlob])); + await pageObjects.runHook(({ useSendFiles }, numCalled) => { + const sendFiles = useSendFiles(); + + numCalled || sendFiles([fileBlob]); + }); await pageConditions.numActivitiesShown(2); // THEN: It should show "Sending". @@ -92,7 +96,6 @@ updateProps(props => updateIn(props, ['styleOptions', 'sendTimeoutForAttachments'], () => 130000)); // THEN: It should revive the message and show "Sending" again. - expect(pageElements.activities()).toHaveProperty('length', 1); await expect(pageElements.activityStatuses()[1].innerText).toBe('Sending'); await host.snapshot('local'); }, diff --git a/packages/test/page-object/src/globals/testHelpers/createRunHookActivityMiddleware.js b/packages/test/page-object/src/globals/testHelpers/createRunHookActivityMiddleware.js index 3ecac51882..a071587d91 100644 --- a/packages/test/page-object/src/globals/testHelpers/createRunHookActivityMiddleware.js +++ b/packages/test/page-object/src/globals/testHelpers/createRunHookActivityMiddleware.js @@ -1,15 +1,19 @@ -const RunHook = ({ fn, resolve }) => { - resolve(fn(window.WebChat.hooks)); +const { createElement, memo, useRef } = React; + +const RunHook = memo(({ fn, resolve }) => { + const numCalledRef = useRef(0); + + resolve(fn(window.WebChat.hooks, numCalledRef.current++)); return false; -}; +}); function createRunHookActivityMiddleware() { return () => next => ({ activity, ...others }) => { if (activity.type === 'event' && activity.name === '__RUN_HOOK') { - return () => !activity.ref.count++ && window.React.createElement(RunHook, activity.value); + return () => !activity.ref.count++ && createElement(RunHook, activity.value); } return next({ activity, ...others }); From 4add0902b5262ef2ffb0bdbe6217aa9363e5e06e Mon Sep 17 00:00:00 2001 From: William Wong Date: Tue, 24 Mar 2026 02:21:52 +0000 Subject: [PATCH 34/51] Fix window.React --- .../testHelpers/createRunHookActivityMiddleware.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/test/page-object/src/globals/testHelpers/createRunHookActivityMiddleware.js b/packages/test/page-object/src/globals/testHelpers/createRunHookActivityMiddleware.js index a071587d91..eda97b3ad2 100644 --- a/packages/test/page-object/src/globals/testHelpers/createRunHookActivityMiddleware.js +++ b/packages/test/page-object/src/globals/testHelpers/createRunHookActivityMiddleware.js @@ -1,19 +1,17 @@ -const { createElement, memo, useRef } = React; - -const RunHook = memo(({ fn, resolve }) => { - const numCalledRef = useRef(0); +const RunHook = ({ fn, resolve }) => { + const numCalledRef = window.React.useRef(0); resolve(fn(window.WebChat.hooks, numCalledRef.current++)); return false; -}); +}; function createRunHookActivityMiddleware() { return () => next => ({ activity, ...others }) => { if (activity.type === 'event' && activity.name === '__RUN_HOOK') { - return () => !activity.ref.count++ && createElement(RunHook, activity.value); + return () => !activity.ref.count++ && window.React.createElement(RunHook, activity.value); } return next({ activity, ...others }); From 494b95b2977fd49839aa362471aa29130e3f80b3 Mon Sep 17 00:00:00 2001 From: William Wong Date: Tue, 24 Mar 2026 07:22:22 +0000 Subject: [PATCH 35/51] Clean up --- .../src/avatarPolymiddleware.tsx | 18 +++----- .../api/src/hooks/useCreateAvatarRenderer.ts | 45 ++++++++++--------- .../createAvatarPolymiddlewareFromLegacy.tsx | 13 +++--- .../Avatar/defaultAvatarPolymiddleware.tsx | 11 +++-- 4 files changed, 43 insertions(+), 44 deletions(-) diff --git a/packages/api-middleware/src/avatarPolymiddleware.tsx b/packages/api-middleware/src/avatarPolymiddleware.tsx index d389a98366..92ace268fa 100644 --- a/packages/api-middleware/src/avatarPolymiddleware.tsx +++ b/packages/api-middleware/src/avatarPolymiddleware.tsx @@ -1,7 +1,7 @@ import { validateProps } from '@msinternal/botframework-webchat-react-valibot'; import { type WebChatActivity } from 'botframework-webchat-core'; import React, { memo, useMemo } from 'react'; -import { any, boolean, custom, object, pipe, readonly, safeParse, type InferInput } from 'valibot'; +import { any, custom, object, pipe, readonly, safeParse, type InferInput } from 'valibot'; import templatePolymiddleware, { type InferHandler, @@ -28,7 +28,6 @@ const { { readonly [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: any; readonly activity: WebChatActivity; - readonly fromUser: boolean; }, { readonly children?: never } >('avatar'); @@ -44,8 +43,7 @@ type AvatarPolymiddlewareProviderProps = InferProviderProps>(value => safeParse(object({}), value).success), - fromUser: boolean() + activity: custom>(value => safeParse(object({}), value).success) }), readonly() ); @@ -54,20 +52,16 @@ type AvatarPolymiddlewareProxyProps = Readonly. const AvatarPolymiddlewareProxy = memo(function AvatarPolymiddlewareProxy(props: AvatarPolymiddlewareProxyProps) { - const { - [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: styleOptions, - activity, - fromUser - } = validateProps(avatarPolymiddlewareProxyPropsSchema, props); + const { [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: styleOptions, activity } = + validateProps(avatarPolymiddlewareProxyPropsSchema, props); const request = useMemo( () => Object.freeze({ [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: styleOptions, - activity, - fromUser + activity }), - [activity, fromUser, styleOptions] + [activity, styleOptions] ); return ; diff --git a/packages/api/src/hooks/useCreateAvatarRenderer.ts b/packages/api/src/hooks/useCreateAvatarRenderer.ts index 61a47f69f5..7fb65cc08d 100644 --- a/packages/api/src/hooks/useCreateAvatarRenderer.ts +++ b/packages/api/src/hooks/useCreateAvatarRenderer.ts @@ -3,35 +3,38 @@ import { useBuildRenderAvatarCallback } from '@msinternal/botframework-webchat-api-middleware'; import type { WebChatActivity } from 'botframework-webchat-core'; -import { useMemo, type ReactNode } from 'react'; +import { useCallback, type ReactNode } from 'react'; +import { useRefFrom } from 'use-ref-from'; import useStyleOptions from './useStyleOptions'; -/** - * @deprecated Use `` or `useBuildRenderAvatarCallback` instead. This hook will be removed on or after 2028-03-16. - */ -export default function useCreateAvatarRenderer(): ({ +type CreateAvatarRendererCallback = ({ activity }: { activity: WebChatActivity; -}) => false | (() => Exclude) { +}) => false | (() => Exclude); + +/** + * @deprecated Use `` or `useBuildRenderAvatarCallback` instead. This hook will be removed on or after 2028-03-16. + */ +export default function useCreateAvatarRenderer(): CreateAvatarRendererCallback { const [styleOptions] = useStyleOptions(); + const styleOptionsRef = useRefFrom(styleOptions); const buildRenderAvatar = useBuildRenderAvatarCallback(); - return useMemo( - () => - ({ activity }) => { - const { from: { role } = {} }: { from?: { role?: string } } = activity; - - const renderer = buildRenderAvatar( - Object.freeze({ - activity, - fromUser: role === 'user', - [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: styleOptions - }) - ); + // TODO: [P1] We should move this function into `api-middleware`. + // However, it use `useStyleOptions` which is from `api` package. + // In order to do that, we need to build a new `api-style-options` package first. + return useCallback( + ({ activity }) => { + const renderer = buildRenderAvatar( + Object.freeze({ + activity, + [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: styleOptionsRef.current + }) + ); - return renderer ? (): ReactNode => renderer({}) : false; - }, - [buildRenderAvatar, styleOptions] + return renderer ? (): ReactNode => renderer({}) : false; + }, + [buildRenderAvatar, styleOptionsRef] ); } diff --git a/packages/api/src/legacy/createAvatarPolymiddlewareFromLegacy.tsx b/packages/api/src/legacy/createAvatarPolymiddlewareFromLegacy.tsx index a547decaff..e186fee70d 100644 --- a/packages/api/src/legacy/createAvatarPolymiddlewareFromLegacy.tsx +++ b/packages/api/src/legacy/createAvatarPolymiddlewareFromLegacy.tsx @@ -51,7 +51,9 @@ function createAvatarPolymiddlewareFromLegacy(...middlewares: readonly LegacyAva ({ [__INTERNAL_DO_NOT_USE__legacyAvatarMiddlewareOriginalRequestSymbol]: originalRequest }) => { if (!originalRequest) { // TODO: Add a test - throw new Error('botframework-webchat: `avatarMiddleware` must not modify the request object'); + throw new Error( + 'botframework-webchat: `avatarMiddleware` must pass the whole request object to downstreamers' + ); } // Pass styleOptions through the polymiddleware chain via the internal runtime extension @@ -63,16 +65,13 @@ function createAvatarPolymiddlewareFromLegacy(...middlewares: readonly LegacyAva ); return request => { - const { - [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: styleOptions, - activity, - fromUser - } = request; + const { [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: styleOptions, activity } = + request; const legacyResult = legacyHandler( Object.freeze({ activity, - fromUser, + fromUser: activity.from?.role === 'user', styleOptions, [__INTERNAL_DO_NOT_USE__legacyAvatarMiddlewareOriginalRequestSymbol]: request }) diff --git a/packages/component/src/Middleware/Avatar/defaultAvatarPolymiddleware.tsx b/packages/component/src/Middleware/Avatar/defaultAvatarPolymiddleware.tsx index c35cc9ce53..b7d6adf48d 100644 --- a/packages/component/src/Middleware/Avatar/defaultAvatarPolymiddleware.tsx +++ b/packages/component/src/Middleware/Avatar/defaultAvatarPolymiddleware.tsx @@ -5,17 +5,20 @@ import DefaultAvatar from './DefaultAvatar'; const defaultAvatarMiddleware = createAvatarPolymiddleware( _next => ({ - fromUser, + activity, [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: { botAvatarImage, botAvatarInitials, userAvatarImage, userAvatarInitials } - }) => - (fromUser ? userAvatarImage || userAvatarInitials : botAvatarImage || botAvatarInitials) + }) => { + const fromUser = activity.from?.role === 'user'; + + return (fromUser ? userAvatarImage || userAvatarInitials : botAvatarImage || botAvatarInitials) ? avatarComponent(DefaultAvatar, Object.freeze({ fromUser })) - : undefined + : undefined; + } ); export default defaultAvatarMiddleware; From 22403b7f4268cef046238249c4d8b4cf80ec63e4 Mon Sep 17 00:00:00 2001 From: William Wong Date: Tue, 24 Mar 2026 08:46:21 +0000 Subject: [PATCH 36/51] Add test --- .../avatar/backwardCompatibility.html | 127 ++++++++++++++++++ .../backwardCompatibility.html.snap-1.png | Bin 0 -> 12142 bytes 2 files changed, 127 insertions(+) create mode 100644 __tests__/html2/middleware/avatar/backwardCompatibility.html create mode 100644 __tests__/html2/middleware/avatar/backwardCompatibility.html.snap-1.png diff --git a/__tests__/html2/middleware/avatar/backwardCompatibility.html b/__tests__/html2/middleware/avatar/backwardCompatibility.html new file mode 100644 index 0000000000..4d58b562d0 --- /dev/null +++ b/__tests__/html2/middleware/avatar/backwardCompatibility.html @@ -0,0 +1,127 @@ + + + + + + +
+ + + + diff --git a/__tests__/html2/middleware/avatar/backwardCompatibility.html.snap-1.png b/__tests__/html2/middleware/avatar/backwardCompatibility.html.snap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..0c5e4883e6c9f6ece7e8cdf01d4ba600cf1b0889 GIT binary patch literal 12142 zcmeHtS5#A77$sH|en6#)1XM&ongXF0{gE!6(3_&tqzM7(Dgx4_1e7X0gc3kH2@$0z zy(C0J?+{9W5IV_R*UY@k!>l!rv(|r~?z-*Vd+t8_+k2lAZK$uw#K6r!M@Pq`t@YTL zj_!;z9o^Ztm(Bu5RNg?h=;*G{X+M5s`X+0Al0J)#a!T7KrH!xoe+TI`e>J^&MHDX0 z`0=Xx18&A!pDmspI*O`V=XZvM-oDGNuGj9M9rr%M!ssgdV?(wprk`$i4=K{)dp4=l z-wHBg&rWF$oX7_#^QrWY0o#w>pw{UDe?J+X#4Zq>#Rm`_*Hs?6-b>7MFVEA{NxeV! z_Ilfy?{PD94jNu`_xa`MKL2<6zi#;t4*v~<|JdO_R{XCT{Qp@biFf6?%X*wRdX;Jx zlbTAKs99^p_Wm^b{f1tbvD+=`u~{7Mug7^Nk5*Wjm2PoeQlO(u>@y^QTSk@82dj9q z);+(r@$Lj+C%x-aE{$R46CJT4vFRSR2-=B!cj}Kd2GH9hQVV^T=k(D=ejw2rNxEPkE4dgB-S8mGFZZ#+tf;+3KiZOj`Uw!FSpNo?`Kc!Q$x}* zuLBZaD)$ouM}tb^=TeTX4#Ql(PjFt)T#@b&~gQy6Mz22 zMRo}mWoPH_7f?5n04BMM~$HY=jDH}BDsCOSXv$fsWLPz|ZMWIj*p9rk~{L}W}l)UOV zeO)nRVRv$3KT5SR)8lo+^kziIpX$w{waJ6+&7Gdfcl6CLkx2xk(pJ&4x<)cRZD}{| z-CN0(Sr)!l=u*X6?C7%70_Kn`%i{9-V_CMCb^UWErxF*)!BlroPi#yKw`}pirEmhT z6IFqPRO98_>E!f$@>zAZ$I|tg(tcLZ!d1^^y&L$_6tZlquDG`wzByLHuc&Afy^oT2 zjkF1=YuPoH0AqK54fqeJBGY;zqHG%%h6TdMS^A&+#va6$f$P9p@y+=L$@MqNU2$`U zt~NV60vV0#TRl{zg@L?>zcP<^dNu`Bw{NR4F+^yIjW-*pZiF70?2~g_H2EkVo%2SV zSpH+^d-52 z8Km+8nPQ#$=EWX8U#MwgNYD#Q7gsBSiz-Ov<-uDCl3nYBTc-4@mCiVCO`h4%Jt?R5 zNV|purKc3Jw!EQHJC;2w)Qjy7v;?*1ci8sJQkI>Wa1Sh8LQxnTY*pnw(e8w?IMO~G z#YMd67;=Wx)<~L}C9!K?_FpjsG1e;|R2?I!FEWdn&_y`?)xowkl&IZ0*!r3bnNEGPi-Y6TiQz-l%;=#E1rd=^ zkEZ=tO*%7qw6L^Gj1wgY~2OY$5O+$uF$@U^9~ za>-N@`lw&Cm_sx`Rlo{eK0}T{I743G68fyq3Ab55Ynu_bdE+}AaY=p^U}tMktgDg$ zckCi~b*DGiJ{|FccRXu-a2 zdh;!{iP@-@xw+@AsW5Z9pyh%N-Q`Y^9>;16Cg-GorX!qZF&fiu-IK5GF{R|+!LA?v{(3wg_ui+aNvZvuAFulj==Y3* z{$Y+U?6p=UO*ee2L8){w$-ZH|T-LCTqVz|vs$ZDJYC)Qk^KNs*ibxonnBcT8pFcab zKX$g?b1*d>27{$toD)}+65;Y^e`n!0l;F16Od5I5R2dc)-`^~tYg6w}g=;v`*Mh!c zxsLlS=pAxvk7xc^ptig5mFr}~TnS8majSMu+Ga(=ggWOTW2%{%EtI6zXL7HH?eZe~ zz31)EjKJb3Ffr^M(yXvqeL|NNYO&kU*l4j|dM5em6aO#olJ$DR0yp{u7Gax(DJb5- zlS7ZaSIR5(?;2J~oDueSFqh6bLoJ`hzLbNI`56Tj)U%YKQYzeesX>b2TImGT0xXMN%{Dd|IsSKcjcX)WTqV5F=8^f zBGkO2vcU{pRB);d(%3s5V_v*?GxpgXGY%$o+n6+6J+XVj%n?5kVa{*O^jM1e1^kunli!U` zs8VO+`_KMa-YD*P0PQek=RB$>W~OA2U$~nTRBenO?@#UY>fYis(2ZUwd2!LP+EB+r zel{P5uqnL9jFt6%*FG2%QxN#-Np_l{+~;cy>749Nn!{@BL+fwkDsFR+L#~x4ltvhX z5;rVV!urzwl>p}ibjI^;KohPld45LbS?*_N1uT7ua{FgR6;19}WT?L`^>Y2Rnnh{r ztqzL1dxoCJ>v*G~g|rZP!{b+Puj!bayyl1%`EWVc-ltlVFT@l{95GOZ)|rvnL;F5I za15jn7Y$f=mC5wu^ zy-_nku|$N+m{!zW^KV6T&Cbp))>r+>P49$AYVn7ku9_dP#7h_Eygl_@tz6}}Ch9%r zzyC~-D})}echB^h+m-Q@3P~hhu#G4SJfO%=v7)vk{r^QE3i~G?94Ab%1{&DhAHrF8 z@r4DuxRegxlV9Fwm^L$OEt2$M${4G(ZRyWeY-uj;cf9j&_9dvNY@4_9h#HAI7#}b> zK=u%|SxFNkyYgJ#Z{2OqVB0pV(w4hcfe<$@%a{E6_M@qJXMVMp5Z6cb`5^{Qq}jQ4 zMHoM?sXCY~?)+^8w6Lg4YC3znO&x=}BT`}+s59e{TK?+eO^<=&N`OQ9EPf{L5e=>8v@5Vm|I@4Wbr4`*vTz3fZ2- zl@G!3r{?5PJ2>sx*x3HzlHM8!YsDZ?g+Ajbn$%95TfaO;Gc-SP7=!UwPkh_}e`IxT z{~Uc+2G}ihCna}bd0EzTD)?Y))|#Tf?|QhiNZ2@C1aG&|^R0&jQ0`(a;n#Vjocc{O zcGt(G#%!(XUwu*e^eFt|p{#xA;Ua&clBA+yOUUtFfkwP>`vDo}c+_K0eZ5hKmvJ8a zTD7IBA3t()|KnADZkbnd4&UDj=Df*Y5(v1&eDcuMd&$`@$89d&8$}yyPBm;wzA44l zo6rH2rV}z4%UfBA5Em9V65;>!iOX6$>ulPAftm;*IQ*8Ujf|}9^0xsMw}6Ku11i?v zJSfemazo$oNXJ0F*SN80wasRz{wZymYL?PhlhM?EU0^dRPrtpoi?=NQ=lctczPQe6NWdJ?oQj)zSk(QPw<30Bny(DZ>{5%B8oI^_1 z6(34QqW1{E`zpGPimDszh=;5n;k_T)j_Y~Fg*dH?NqLke2#9YcXRg_jJeT$LRLE1e zPjPZ?9vW7z>P<4wz_P97Cj!?V8(r0ohNtJxUQ^dpN&@A5y6A*Ex^&PmGCYj0u*NqB z*hy#9c#!KW6zl8Ud<@GGZ%&t|y3r%Xd|?wUI}WzzqpZ%qqZKNv29VTPlnX@~NIt@9A01gff}?(}dV%uJHH;Tbm4hH)RSXTAGma6C+O+j#%qHX~cx3WwLx zaf4Lk#fTcUzAIrXR+ooM404rs+H!|f)cKC@*Jk+q=$D2x(}0jG$cmwwBHChV zU&OfW93t;asY_nWJ*e_rv`?>E^gZ~d_O9W3BK!k-&Ur%da<7}`8^$}tVk7qvMZZ_( zUX9KjZS+vPCRf`#4Ue>?Evi-uKC13~`m&mxs}NA5YcpLNmPyrYP$7hv$AmXfQ~Xd1 zXoBGJ-bUuhYx7JQcLl%o&l9>Bm+iR@bkM$8-w(`Kt;-0&DTspVef(g7W@2ajjbk)B z#bh_`$O~I*^fCngX!EfM|CoW%Yswm4;?QC-mfU)0cafwU?DI*>tkR|wqjQ~BY!=%4 zpz97v@9$V2?+aj6z>>=Ul&Yck*K|b8PL2~CL^INojd+~7o`^+1X7EqrY_TYi1`WL* zcdUlr%NIASh|~}*6xX$~ag^A$xLw zWaeu0YCGxebg%DZMHY58tV@|lI>lwow$g)F>4WR)C8jsRc*~%*EGNgi2NF)3F7DR# zuUyDDs9G?w{*K#~An##qL19Uo{Eoaw&(be}A~JGpkzOOkdZ8~&i(>NgZ^Q1pR!$2v zYf<&UYOPJLF|4U6DJfY6&op0WaMOq0Y+*@wF`gzYr?3RwZ7s@w2McF@eR!DnnbF)F z6yltSV80N-ZUh$2_cpg>uef9egP9-T&LC6fvNE`ExFJIX*}q4PWn-$yvj3{)zU?;` z@}4d1+si&1lV$2+<|CRV*(wq`%kGJkp(PNe7v8%*ZJ&GhH39l!aVq@S;=Rf`RI3ty&awkd+;X6{db7)tF`8X|@jNAdw5}wz;ro^eCGw-Gbbl@2yvfj1=r>rPIF#Og{<2#8j zQ#cEKCL6`CD#zhrvoa|+cL~{)^r!B~mw1Kw;yvBi8w)Ql{F@ikeGhUUy8?&rd|~=#EB6~py0QdP z=mduhEmDb%ydTL7LM;7W87hFLPZbQ$&PMS~ZJdKVf!u}<<$coGgQaqE|1)|ey3;L1 z7a^zMPN)sqY|`9dhCHPZq*uziHWzK37p;D}H%u14vtSam_wHZ^lhC`vx=0K)kRDq% zdA`e_g}U3%x~YUFuTC*t=-L7PomsYG6TZ#m%b43}aMHEQ>S}E}JKYb3%8fX{;27N= z6XPE-EOp>#(T~Prc4D;d;P}37ggWojd$jKIu~4`3eKdVv;hP_YXC)h&-4|4ySb4h} zsdpCEArX8q^pziTbgMB(`E+Pnx5SRHNEMe54Qe~R?|XuOSgvtf`mDm6tr1PvZI$FZM0ou`RygqQb>Z(;E7BwQI$lrXQ_lVzjrW5q|ke~C9FCtyXrWb<88s5 zBf3_NUU^mw^PTY~j~?^i-5eLHN>CsQF?H8F&(;yd8)x1xe63N?%nja&K1a0L5C_4B z!xd;C1sjFg+(~0y>xdeT;N8_7irc;LO6|bPvbfM@7x$m*>qHA*&8K-8yyJ}i=YQla zSq3Qf#0*QRohtY#Eedw=VT;VQT`2WpYdnWV1Kxz$zP%(Y-?pMf`u|IboPVjKeo<_i_*(h8wtAl5`2yMd) zP}8nHo83@C$&gbI7oHS4X|9(yc;z8+*@A8KZ% z9FgHpKhssgVee>uuEkP{bj&~G9Q883dzb|-YKhyPN%(U8x~@4=M^{_hKu<(MBL2n8 zLrACdT%hXpHV5?=mO3}5^3-FsD3%bgw#*b7yp^vPi}Dd+V3=t1rbYyZDxb82 z-icBMZoGV{{{EezQcfDeRU?Lh$If2$5qO9rAfThDV>QXE2Nld&#vH{j&Knmb7_R<4 z&+8W>GpA0x=$MV)@YnVMQKf^g7unI%0SxDtDl?BKhL^GbmTI=0SvTL~;*k&wb0KuQ z;Po*5Emxx(<$X~0ua3v3cYLIxa=|F2tf_ME`K-8J4W=8;TL$mGMruH%iRp{dM}tC& ziXtLD%LyCuE-r_M0Ss{ug;u~)?;m-d2yo;6^mIz%i`2#=$F6(KJtmF&o*o|?{EfQY zj_iEKzmA`5gXoSklrMI{G;PPEzm+!sBgKgNc3FCJIa~cGjD{2uULBNFEpYkP8+mxh zBxzngRrRc|e)l0n{e@8-@kX^5Dj)IG>P{bwZ@SFsXVyeSPkNnakb~T3-hYbD{}A6i zO*g*krPwX4KZNl1m}84%)%OZHdV^OmFtl}?xIFJ6w|DWcGw+)DrPqhvNNT<@X1VX2j`bdY~fafgSkKipgVAP?+1L#<%CH z3<%@!?xHAr0#XkH1e{qahr7;7#O#rz^kv(YM!g%dA%SZznRwCrN1G)%O|?pfS3KAm z3OPJ2(^IaRA@7J>^Z0YW;gQ))rBQM_#BB5@iBGwMIvLLA6y4sh?^EPC>A(zg~7?S)Y`H=6M zsSqX1`v_4sfec-2J<7*Vu%rhcY)*)ER2R!{>$_*lcKp+&Zc`D%j!+3Iz`~kM8S;C3{*KAIsMR166tJP%DJU1{bCfRSPUxQd z$X$uMg{TSZhiXzlJgUaL&5*CIt`l#e#2v<*Gn;kV{prNgo=aYyM~o1f;RMK#dA9{kO3J9DL5_Y!S^kTkZ(&a~_K zY-hv;M+RxT`PP*G6*HHzhm$IRKpPGh3fSQLD%0CGYvMW~L#}_InV`LSLbEzTHZV?Y zrcP`7oX{kVC0lvgp_?qWMx@XwPq_R!)J=?u=A^*y&dLwLU>tadz;l|wl>uLh{;3spxnc$ z?w7|b9o7K4x3*Of80Y$B#MnIs+A>-pV%6Y>CuHo~5tfIOq7v4pi!n7n&%l?7r|Hm4IvaYrVK1;o&CTK?5Ki4G-mq>XbWryTt|FzLRnt&$V^dn^z`>HS+ z)qlcUv!z}A?GwA8jk=f^2Kt#6hRL}wiPotMSx>vr(AK$mz`_DwmPzC91x(duj|66- z#h(NdF>gJXizT7=r+!2*_Vn~v*SUgSh6^E=nYg8Y_4JUHP_S$ajN)fUNB3fM^#vp%Wimi3qb1ZT4!B^32~u00xu!%-9O zpH&T1-Qn)il|cIfH@ZzHbUcgsr=#thrsPwzNxunsy7aOkNp7<6Uu z>A@B{girQR`Sjtr^Yc->a(R%c$=J$u3fh!m~zfxxJd^Vnjlz{CupYMaTQI{T`#?YtrUk+HM(YEz zv&VLB83|s`k0~wA1iKa2hZETH47IMBWV!_i-K~8|!xzFHBYqsMdTq7QuLa-=w6(R3 zEj?PkQq<@BPyf}>hz#Td1{}8cCyS~LMOPrg!*6x?1z>f%KbjaQ zQ-D<6X!cuGRh3?*4E54S>Qu=7WJ%WR7~YzFL1QLLX-N*ZYUs&QUnV;fb;s2k?u@{H zbwSfDngXIyt*+^p;+A6@o_OZ7cenii%aRn1sj8>p=ja$)L5$zyDjEK-w=T^9eNF)& zSQ~nJq!G^z3RN>gnA?H3mZAfm100Be-+!8QSB3bx0iN927hXaW!N6roY094k2qz`D0IOdcq zCN6FkH8ZHj()atfHO=@HCXl6bgqA&P2~HBTN)5z$0-IX0gEv6lk?l-H>af@5vK!q{zk&h zTAX%op1$sPOjNE1E(h4;#2<5<9T{Z$(X!4JHe3OCOs6bwjh8Qr(@GJD49OSWG3+8b zy1MMzB{_kvKpNM}3 zfFAVV*<&$Ph4paX_Kk@qayLvwqIo5sKS3@Zg$n+iETD76y%RislK{`ku8?b%7+k8X z04mlmOle;rkemX*9QM7>l_lk*-{3J>31ogr{F;cQy$PRz!&qe?`07a$Qv{Gx30TaH z8$hu3r#0jlKUxklb{i4Q%qmzFw{3Qg!aLHa`xuduFhFPLgi#Nz$nDXr7)sH-w@dxm z)|Qr~oGBR@M|CYWw-G=T`JoKiYGnjJ7{S2za3V;Q@#UQp^1!iff0n!nnf+m)D+OO0 z6m~EhB|h{NJJ>i{@JPJFSwo|TH%+XTNobs9qLJ%LQ}9AhHpy0 zFI?+mfb~HH&D_+*Qor>p=vs$Qt>-MQ-2#w~21@8LWvyfx;!t|{)xdyE5f+{_9ryTC zm8WthM1_Hw#y+}J@UvArir)PVHR-Ol=A{eW1Hfc3xJWaRw<5BF`UrM&e<}zmQ*U)w z>vRpVGE=^80eJ2}0r4Rr!ywTyMlBgq(O+J9y8B4T7kXl<+n$SbDf;eF)fDq>U zhyD=F4syY2kM%qwHV~(MZQtwMB1ET(Dg>@RtSO1Y_K*-f0SigQvv7{Dvc--|0Gnl_ zblu|@YB7|xt+La{>=QRU8uONP{H%F~dGorgb4|p%OjVo*Bd22#|{BloDhW zOJ`Jkmo%)hRp+v?Kwzr$~ZM~JDFR- zV>ed4sLa6xmy%N2PTwJSmbo@0o4JlLmF-^ailfmDrv`EzMJTc#5FgJ)T)GlKq34Ar zu@GR1%0iP`9c`tGW%z-CrkVTY-*X{)t_`7pQc!q^KqBU22p9wmA%RMd)G!V?^(#L* z`Q|iW2GeKS$yhuWCe+ptdK&0HN04QcCgkFHb$Rbm9%67?danJ>_tizrGgZd|@wG(I z?-#q?Ey!l|81_^09g^|JPgRLZeIbcj88ChFBolix+nGRP%Cp^2e9|B*TUYKfXyzbIkV_=lu@b!YJ z*vMObpzBX{J}Wp|X$<5iM5}Pb;{l)xmqyhY&Lccdm4~Y*e z?tamrPZbWbYPtxj&BgY*Y&e?Rct`9t10s`HT32$2=8~U}ldAPexFM?_@^8`S?%UkF zeo)Q$CjzN^e}1P3mIWg4GS7cqNrxxrgdVLDXp~kg-Vmu5jy$~Fl8ualbL}3jA*Z2u z+wQXz%T#WlknLvsPX+XW@y>CUkZM)xb|S;$_&n#II`x@P_&|Fg9R~LpZU)mwhEWz! zbX~M-(4diF-2ln&NF#ZJ{)=zzcCLk58~2q_N2uu0DJcx;u3s0Zo__2(G-PmGW%v6* z7f(u7K#y1h93C(iE!a$2&I#HyDzNn&+>lMJ=kDItZBpQv^zH&Ne9XudBZBH0a|4OO z=|X;ps>R$*h`GHLAbot^=RAE=a{fE$E3g? z8C>@r-p;8>;XeD**oh@T71oRQtNV_T$vRYapJ?1p(&Qa7GIx*9SPnl~DJ4^4?N8=@ z3+9>zH@4s01|}A{d@4x&3Tx$jm2vI>={nO&R8O^)gF&AlnK*B4dLc>*q`8HND07vH zIX9#E{iI+7QS&52T04qAe!B6oj}{~lGU=K#d1G-vUP)R z9Dk7KLqC?e&>eWs`$PV(>kE&=fW`7Onh1A546t+YuPr`Dm-g9SZ-xHh3UGu@TV4Ng J<-ZQ^{|C_SH?05w literal 0 HcmV?d00001 From 97775f4bbc2b68b60e52b5205b4e6e04cdba918c Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 25 Mar 2026 02:40:24 +0000 Subject: [PATCH 37/51] Clean up tests --- .../avatar/backwardCompatibility.html | 45 ++++--- .../backwardCompatibility.html.snap-1.png | Bin 12142 -> 18874 bytes .../avatar/legacyAvatarMiddleware/addNew.html | 77 ------------ .../addNew.html.snap-1.png | Bin 11829 -> 0 bytes .../legacyAvatarMiddleware/addOrReplace.html | 107 +++++++++++++++++ .../addOrReplace.html.snap-1.png | Bin 0 -> 19583 bytes .../legacyAvatarMiddleware/decorate.html | 113 +++++++++++------- .../decorate.html.snap-1.png | Bin 13585 -> 19583 bytes .../avatar/legacyAvatarMiddleware/delete.html | 73 +++++++---- .../delete.html.snap-1.png | Bin 9477 -> 12834 bytes .../legacyAvatarMiddleware/replace.html | 78 ------------ .../replace.html.snap-1.png | Bin 11580 -> 0 bytes .../avatar/polymiddleware/addNew.html | 80 ------------- .../polymiddleware/addNew.html.snap-1.png | Bin 11546 -> 0 bytes .../avatar/polymiddleware/addOrReplace.html | 106 ++++++++++++++++ .../addOrReplace.html.snap-1.png | Bin 0 -> 14393 bytes .../avatar/polymiddleware/decorate.html | 105 +++++++++------- .../polymiddleware/decorate.html.snap-1.png | Bin 13018 -> 19056 bytes .../avatar/polymiddleware/delete.html | 78 ++++++++---- .../polymiddleware/delete.html.snap-1.png | Bin 9477 -> 12834 bytes .../avatar/polymiddleware/replace.html | 77 ------------ .../polymiddleware/replace.html.snap-1.png | Bin 11555 -> 0 bytes 22 files changed, 481 insertions(+), 458 deletions(-) delete mode 100644 __tests__/html2/middleware/avatar/legacyAvatarMiddleware/addNew.html delete mode 100644 __tests__/html2/middleware/avatar/legacyAvatarMiddleware/addNew.html.snap-1.png create mode 100644 __tests__/html2/middleware/avatar/legacyAvatarMiddleware/addOrReplace.html create mode 100644 __tests__/html2/middleware/avatar/legacyAvatarMiddleware/addOrReplace.html.snap-1.png delete mode 100644 __tests__/html2/middleware/avatar/legacyAvatarMiddleware/replace.html delete mode 100644 __tests__/html2/middleware/avatar/legacyAvatarMiddleware/replace.html.snap-1.png delete mode 100644 __tests__/html2/middleware/avatar/polymiddleware/addNew.html delete mode 100644 __tests__/html2/middleware/avatar/polymiddleware/addNew.html.snap-1.png create mode 100644 __tests__/html2/middleware/avatar/polymiddleware/addOrReplace.html create mode 100644 __tests__/html2/middleware/avatar/polymiddleware/addOrReplace.html.snap-1.png delete mode 100644 __tests__/html2/middleware/avatar/polymiddleware/replace.html delete mode 100644 __tests__/html2/middleware/avatar/polymiddleware/replace.html.snap-1.png diff --git a/__tests__/html2/middleware/avatar/backwardCompatibility.html b/__tests__/html2/middleware/avatar/backwardCompatibility.html index 4d58b562d0..dc68db8921 100644 --- a/__tests__/html2/middleware/avatar/backwardCompatibility.html +++ b/__tests__/html2/middleware/avatar/backwardCompatibility.html @@ -35,44 +35,42 @@ run(async function () { const { directLine, store } = createDirectLineEmulator(); - const MiddlewareAvatar = ({ activity, children }) => { - expect(activity).toHaveProperty('text', 'Hello, World!'); - - return createElement( + const MiddlewareAvatar = ({ activity, children, fromUser }) => + createElement( 'div', { style: { borderRadius: 40, height: 40, - outline: 'dashed 2px green', + outlineColor: 'green', outlineOffset: 2, + outlineStyle: fromUser ? 'dotted' : 'dashed', + outlineWidth: 2, overflow: 'hidden', width: 40 } }, children ); - }; - - const PolymiddlewareAvatar = ({ activity, children }) => { - expect(activity).toHaveProperty('text', 'Hello, World!'); - return createElement( + const PolymiddlewareAvatar = ({ activity, children }) => + createElement( 'div', { style: { borderRadius: 32, height: 32, margin: 4, - outline: 'dotted 2px red', + outlineColor: 'red', outlineOffset: 2, + outlineStyle: activity.from?.role === 'user' ? 'dotted' : 'dashed', + outlineWidth: 2, overflow: 'hidden', width: 32 } }, children ); - }; renderWebChat( { @@ -81,11 +79,14 @@ const children = next(request); expect(Object.getOwnPropertyNames(request)).toEqual(['activity', 'fromUser', 'styleOptions']); - expect(request.activity).toHaveProperty('text', 'Hello, World!'); - expect(request).toHaveProperty('fromUser', false); expect(request.styleOptions).toHaveProperty('botAvatarInitials', 'WC'); - return (...args) => createElement(MiddlewareAvatar, { activity: request.activity }, children(...args)); + return (...args) => + createElement( + MiddlewareAvatar, + { activity: request.activity, fromUser: request.fromUser }, + children(...args) + ); } ], directLine, @@ -93,7 +94,6 @@ createAvatarPolymiddleware(next => request => { expect('styleOptions' in request).toBe(false); expect(Object.getOwnPropertyNames(request)).toEqual(['activity']); - expect(request.activity).toHaveProperty('text', 'Hello, World!'); const children = next(request)?.render(); @@ -102,8 +102,9 @@ ]), store, styleOptions: { - botAvatarInitials: 'WC', botAvatarImage: '/assets/bot-avatar.jpg', + botAvatarInitials: 'WC', + userAvatarImage: '/assets/user-avatar.jpg', userAvatarInitials: 'WW' } }, @@ -112,12 +113,20 @@ await pageConditions.uiConnected(); - directLine.emulateIncomingActivity({ + await directLine.emulateIncomingActivity({ from: { role: 'bot' }, + id: 'a-00001', text: 'Hello, World!', type: 'message' }); + await directLine.emulateIncomingActivity({ + from: { role: 'user' }, + id: 'a-00002', + text: 'Aloha!', + type: 'message' + }); + // THEN: Should show an image with a green outside border with a red inside border. // Legacy middleware has higher priority than polymiddleware. await host.snapshot('local'); diff --git a/__tests__/html2/middleware/avatar/backwardCompatibility.html.snap-1.png b/__tests__/html2/middleware/avatar/backwardCompatibility.html.snap-1.png index 0c5e4883e6c9f6ece7e8cdf01d4ba600cf1b0889..b353219fa9fa5976711c0430355e9b2556ef4a39 100644 GIT binary patch literal 18874 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 Z!WIfW|9Ar5%=GG&w4{PWxtLMF{{vkD(-r^# literal 12142 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 J<-ZQ^{|C_SH?05w diff --git a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/addNew.html b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/addNew.html deleted file mode 100644 index a0d557c4da..0000000000 --- a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/addNew.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - -
- - - diff --git a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/addNew.html.snap-1.png b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/addNew.html.snap-1.png deleted file mode 100644 index c716774beed621211f6518d4c3b9d669190dab9e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11829 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 + + + + + +
+ + + + diff --git a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/addOrReplace.html.snap-1.png b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/addOrReplace.html.snap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..b8ebe9c68e59554b16f6f594fb921bcd8d4fe104 GIT binary patch literal 19583 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 aU}nhX+0@h~b;b@T!r - + + +
- - - - - -
diff --git a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/decorate.html.snap-1.png b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/decorate.html.snap-1.png index d12ac4461a5d0c7aa0ea828d79dd20eff4a21ca7..b8ebe9c68e59554b16f6f594fb921bcd8d4fe104 100644 GIT binary patch literal 19583 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 Q@E5WdN}A8$3a>)`2U~?-?f?J) diff --git a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/delete.html b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/delete.html index 18229e4737..b69192cbbc 100644 --- a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/delete.html +++ b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/delete.html @@ -1,39 +1,60 @@ - + + +
- - - - - -
diff --git a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/delete.html.snap-1.png b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/delete.html.snap-1.png index b947953c522a4fc13dbd342e41243915e0486e9f..2410f6bf15574b4c5c17dff81a4c09beaca8eaba 100644 GIT binary patch literal 12834 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 literal 9477 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 diff --git a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/replace.html b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/replace.html deleted file mode 100644 index e71ab23198..0000000000 --- a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/replace.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - -
- - - diff --git a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/replace.html.snap-1.png b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/replace.html.snap-1.png deleted file mode 100644 index 03b6aabe9ba3e40a813509a8e8ad7e9acf766b4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11580 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 diff --git a/__tests__/html2/middleware/avatar/polymiddleware/addNew.html b/__tests__/html2/middleware/avatar/polymiddleware/addNew.html deleted file mode 100644 index 431e4be5bb..0000000000 --- a/__tests__/html2/middleware/avatar/polymiddleware/addNew.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - -
- - - diff --git a/__tests__/html2/middleware/avatar/polymiddleware/addNew.html.snap-1.png b/__tests__/html2/middleware/avatar/polymiddleware/addNew.html.snap-1.png deleted file mode 100644 index b371ae90094750435bb5c7dfac31572a40edeec7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11546 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 diff --git a/__tests__/html2/middleware/avatar/polymiddleware/addOrReplace.html b/__tests__/html2/middleware/avatar/polymiddleware/addOrReplace.html new file mode 100644 index 0000000000..1f9619e39e --- /dev/null +++ b/__tests__/html2/middleware/avatar/polymiddleware/addOrReplace.html @@ -0,0 +1,106 @@ + + + + + + +
+ + + + diff --git a/__tests__/html2/middleware/avatar/polymiddleware/addOrReplace.html.snap-1.png b/__tests__/html2/middleware/avatar/polymiddleware/addOrReplace.html.snap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..5b6eb0a9b3628faed436d0bd29365df02cc06998 GIT binary patch literal 14393 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 bryzUG_4TA`D98%9LiSSSm2#Eh>xlmYd9X<0 literal 0 HcmV?d00001 diff --git a/__tests__/html2/middleware/avatar/polymiddleware/decorate.html b/__tests__/html2/middleware/avatar/polymiddleware/decorate.html index 0049b0fbc4..4fe1d7b380 100644 --- a/__tests__/html2/middleware/avatar/polymiddleware/decorate.html +++ b/__tests__/html2/middleware/avatar/polymiddleware/decorate.html @@ -1,63 +1,76 @@ - + + +

- - - - - -
diff --git a/__tests__/html2/middleware/avatar/polymiddleware/decorate.html.snap-1.png b/__tests__/html2/middleware/avatar/polymiddleware/decorate.html.snap-1.png index c3ac963ce1f017bc175aec1ac9fac50f220a61f5..db7331c81c8e1c3411c43cf54fe68e79eb702f5c 100644 GIT binary patch literal 19056 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 literal 13018 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 TSBy*1o=6`^#yhR2u1Ejq*%McWNvN zCY*zfKO97B2$fi!7;zIF^IT3RwRrxVHb5KFhmscZfmeom)4H zck!b@Y|A0+RjFk0?Io~A2V=Nnu6-gja)}5(7S)HFmY7GW+S3$^|K1=yN;|wwM^{Lq zpcy7(u%cNb*SwsjPyWWR50g-0Ty|fU6H2kMdJ&k`m^%79d$U@^OLZR$vpGOD=b7t3 zJDy43VMVh3Em(S%rIObg%K8DDpb8otjU&DVouoCqHncvWgl$(vRG#6pg=9 zr#UQw^q0Z*gV0OW5S_giv6%t+VQV^ibVuDE5tJF^nNb{avXrPj4F`NvVYa#?dP{ptL2_W5?h%FOPsyXXP|#V8 zn|&(G8Sqx3p6mHD$pW9|-8u&eXS0Mg23-<4h8!~_II=P`iXPWy=Q%ro#2!4TJV)Of zsHC*;Y0=|f8mQ1{y+O&5J2?+9G$cub;-(c0`+$YSMs4Hn*sHG?y(l$gLRGwua}NGN zseZXmup)%RQ`yv*Xl;9~ZnLGP>v3GxJ?~k{6_#%RFO}kXZFtA#npI%y9>r!~^RjM*mSLR@Q#P3_=h-*;$k2Kh{Mjh7#H&n7J&d4$VjX%~% zYRnsh3Z#RB~&<7iXqV2uzsNP3x;Vm1^ zBmdS5X8s|_2v@$pQA*GO$qy|r?r~}7=Xp1T&o(gf*nOyVE`4+m>GJ!-=pknqd9!!o zT8XTA9&7Y)n*s6uLw3D79rM+q^Ffi4VkUU=Qwqcqa-mppAl!TvnDS8}UHr1&{THV> z8ch*YDcmN73m+-PJaL|LfdGba*{qwww6s`yM2`jvEg_i!v>7dx#fqFR6wAdP`CgG% zoL(5_!CUE>xt_roa}yhC%iNo=A5pX_#1wH*CBv1=jz*%4qF!YN%otYW=^xcCZDg6B zqo0zBGKai1Dk(7f_8GacG=`626%B)+O2bM*3q7mpJ=ONBZOi({zVL~A_SmDnMq?(f z2et(1v5XAuZdMII^VK+sC@>||A}_za(8a`nKMdGk{6~O@G}2Q`09h;K(F-}V;Pse2 z`7Q=<-Ov!9-@a`or)PC>0+xGhJfG5sLTX*E{6VS$*#!eL4W$&(7+$H4s{pBulHxST z$%@T3l=l3d4POND89) zZn{6^KCs4LWZaUAGJ7I&vUX>b-EJs1+!&IN`iOzBP~T5ac<(hodvO9DJP*d&{ZH$Bmgqu9u+lv;7|Wl{^x9F>kWU zLypsW;gSFRZ@)>KeO))DYvtQ5_#noBElg=j)0^UN&!Fgsw0usDYY)z(F*e!*;iVi) z-sX~>sF)kqkA+`}PGU3<@O2{eC7fkZz#cr5sMd=0_0}%V767V&e-d*^(o*PoBoJaV zfrn<9o|sW3LeNK~m}e{gVCw|5LM{o@$-A!LuoQ!PAJ(a9tMz=fidoqX%kVzK$exIhz{0D?$7q)5FN7Ti+~9 zyjsi6x8mNvze;hbv@-|a+ - + + +
- - - - - -
diff --git a/__tests__/html2/middleware/avatar/polymiddleware/delete.html.snap-1.png b/__tests__/html2/middleware/avatar/polymiddleware/delete.html.snap-1.png index b947953c522a4fc13dbd342e41243915e0486e9f..2410f6bf15574b4c5c17dff81a4c09beaca8eaba 100644 GIT binary patch literal 12834 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 literal 9477 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 diff --git a/__tests__/html2/middleware/avatar/polymiddleware/replace.html b/__tests__/html2/middleware/avatar/polymiddleware/replace.html deleted file mode 100644 index c937ffdb99..0000000000 --- a/__tests__/html2/middleware/avatar/polymiddleware/replace.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - -
- - - diff --git a/__tests__/html2/middleware/avatar/polymiddleware/replace.html.snap-1.png b/__tests__/html2/middleware/avatar/polymiddleware/replace.html.snap-1.png deleted file mode 100644 index 2f8f30ac89ed083cf53633377e4d8219441ff427..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11555 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 Date: Wed, 25 Mar 2026 02:58:31 +0000 Subject: [PATCH 38/51] Skip test --- ...ouping.legacyActivityMiddleware.skip.html} | 125 ++++++++++-------- ...cyActivityMiddleware.skip.html.snap-1.png} | Bin 2 files changed, 72 insertions(+), 53 deletions(-) rename __tests__/html2/activityGrouping/{activityGrouping.legacyActivityMiddleware.html => activityGrouping.legacyActivityMiddleware.skip.html} (59%) rename __tests__/html2/activityGrouping/{activityGrouping.legacyActivityMiddleware.html.snap-1.png => activityGrouping.legacyActivityMiddleware.skip.html.snap-1.png} (100%) diff --git a/__tests__/html2/activityGrouping/activityGrouping.legacyActivityMiddleware.html b/__tests__/html2/activityGrouping/activityGrouping.legacyActivityMiddleware.skip.html similarity index 59% rename from __tests__/html2/activityGrouping/activityGrouping.legacyActivityMiddleware.html rename to __tests__/html2/activityGrouping/activityGrouping.legacyActivityMiddleware.skip.html index 60b506fd2b..f5bfc7ecc3 100644 --- a/__tests__/html2/activityGrouping/activityGrouping.legacyActivityMiddleware.html +++ b/__tests__/html2/activityGrouping/activityGrouping.legacyActivityMiddleware.skip.html @@ -1,4 +1,19 @@ - + + @@ -32,57 +47,63 @@ run(async function () { await host.windowSize(undefined, 1280, document.getElementById('webchat')); - const activityMiddleware = () => next => (...renderActivityArgs) => { - const [{ activity }] = renderActivityArgs; + const activityMiddleware = + () => + next => + (...renderActivityArgs) => { + const [{ activity }] = renderActivityArgs; - const renderActivity = next(...renderActivityArgs); + const renderActivity = next(...renderActivityArgs); - if (/^1/.test(activity.id)) { - return (children, ...renderAttachmentArgs) => ( -
- {renderActivity( - (...renderAttachmentArgs) => ( -
{children(...renderAttachmentArgs)}
- ), + if (/^1/.test(activity.id)) { + return (children, ...renderAttachmentArgs) => ( +
+ {renderActivity( + (...renderAttachmentArgs) => ( +
{children(...renderAttachmentArgs)}
+ ), + ...renderActivityArgs + )} +
+ ); + } else if (/^2/.test(activity.id)) { + return (children, ...renderAttachmentArgs) => + renderActivity( + (...renderAttachmentArgs) => { + const [firstArg] = renderAttachmentArgs; + const { + attachment, + attachment: { contentType } + } = firstArg; + + if (/^image\//.test(contentType)) { + return ( +
+ {children(...renderAttachmentArgs)} +
+ {children( + { + ...firstArg, + attachment: { + ...attachment, + contentType: 'application/octet-stream' + } + }, + ...renderAttachmentArgs + )} +
+
+ ); + } + + return children(...renderAttachmentArgs); + }, ...renderActivityArgs - )} -
- ); - } else if (/^2/.test(activity.id)) { - return (children, ...renderAttachmentArgs) => - renderActivity((...renderAttachmentArgs) => { - const [firstArg] = renderAttachmentArgs; - const { - attachment, - attachment: { contentType } - } = firstArg; - - if (/^image\//.test(contentType)) { - return ( -
- {children(...renderAttachmentArgs)} -
- {children( - { - ...firstArg, - attachment: { - ...attachment, - contentType: 'application/octet-stream' - } - }, - ...renderAttachmentArgs - )} -
-
- ); - } - - return children(...renderAttachmentArgs); - }, ...renderActivityArgs); - } - - return renderActivity; - }; + ); + } + + return renderActivity; + }; WebChat.renderWebChat( { @@ -106,8 +127,7 @@ role: 'bot' }, id: '1.0', - text: - 'Decorating activity of **carousel layout**. Also decorate attachment without using attachment middleware.', + text: 'Decorating activity of **carousel layout**. Also decorate attachment without using attachment middleware.', timestamp: 0, type: 'message' }, @@ -123,8 +143,7 @@ role: 'bot' }, id: '1.1', - text: - 'Decorating activity of **stacked layout**. Also decorate attachment without using attachment middleware.', + text: 'Decorating activity of **stacked layout**. Also decorate attachment without using attachment middleware.', timestamp: 0, type: 'message' }, diff --git a/__tests__/html2/activityGrouping/activityGrouping.legacyActivityMiddleware.html.snap-1.png b/__tests__/html2/activityGrouping/activityGrouping.legacyActivityMiddleware.skip.html.snap-1.png similarity index 100% rename from __tests__/html2/activityGrouping/activityGrouping.legacyActivityMiddleware.html.snap-1.png rename to __tests__/html2/activityGrouping/activityGrouping.legacyActivityMiddleware.skip.html.snap-1.png From 173be9013f5e19b7da03016d71d99e94c7190975 Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 25 Mar 2026 07:39:19 +0000 Subject: [PATCH 39/51] Use styleOptions at init --- packages/component/src/Composer.tsx | 6 +++-- .../createDefaultAvatarPolymiddleware.tsx | 17 +++++++++++++ .../Avatar/defaultAvatarPolymiddleware.tsx | 24 ------------------- 3 files changed, 21 insertions(+), 26 deletions(-) create mode 100644 packages/component/src/Middleware/Avatar/createDefaultAvatarPolymiddleware.tsx delete mode 100644 packages/component/src/Middleware/Avatar/defaultAvatarPolymiddleware.tsx diff --git a/packages/component/src/Composer.tsx b/packages/component/src/Composer.tsx index 2cc9ca2ccd..7624bbcce7 100644 --- a/packages/component/src/Composer.tsx +++ b/packages/component/src/Composer.tsx @@ -44,7 +44,7 @@ import { ScrollRelativeTranscriptScope } from './hooks/transcriptScrollRelative' import defaultActivityPolymiddleware from './Middleware/Activity/defaultActivityPolymiddleware'; import createDefaultActivityStatusMiddleware from './Middleware/ActivityStatus/createCoreMiddleware'; import createDefaultAttachmentForScreenReaderMiddleware from './Middleware/AttachmentForScreenReader/createCoreMiddleware'; -import defaultAvatarPolymiddleware from './Middleware/Avatar/defaultAvatarPolymiddleware'; +import createDefaultAvatarMiddleware from './Middleware/Avatar/createDefaultAvatarPolymiddleware'; import createDefaultCardActionMiddleware from './Middleware/CardAction/createCoreMiddleware'; import createDefaultScrollToEndButtonMiddleware from './Middleware/ScrollToEndButton/createScrollToEndButtonMiddleware'; import createDefaultToastMiddleware from './Middleware/Toast/createCoreMiddleware'; @@ -426,6 +426,8 @@ const Composer = ({ [cardActionMiddleware, theme.cardActionMiddleware] ); + const defaultAvatarPolymiddleware = useMemo(() => createDefaultAvatarMiddleware(styleOptions), [styleOptions]); + const patchedPolymiddleware = useMemoIterable( () => Object.freeze([ @@ -436,7 +438,7 @@ const Composer = ({ defaultActivityPolymiddleware, defaultAvatarPolymiddleware ]), - [polymiddleware, theme.polymiddleware] + [defaultAvatarPolymiddleware, polymiddleware, theme.polymiddleware] ); const patchedToastMiddleware = useMemoIterable( diff --git a/packages/component/src/Middleware/Avatar/createDefaultAvatarPolymiddleware.tsx b/packages/component/src/Middleware/Avatar/createDefaultAvatarPolymiddleware.tsx new file mode 100644 index 0000000000..9d8669f8cc --- /dev/null +++ b/packages/component/src/Middleware/Avatar/createDefaultAvatarPolymiddleware.tsx @@ -0,0 +1,17 @@ +import type { StyleOptions } from 'botframework-webchat-api'; +import { avatarComponent, createAvatarPolymiddleware } from 'botframework-webchat-api/middleware'; +import DefaultAvatar from './DefaultAvatar'; + +function createDefaultAvatarMiddleware(styleOptions: StyleOptions | undefined) { + const { botAvatarImage, botAvatarInitials, userAvatarImage, userAvatarInitials } = styleOptions ?? {}; + + return createAvatarPolymiddleware(_next => ({ activity }) => { + const fromUser = activity.from?.role === 'user'; + + return (fromUser ? userAvatarImage || userAvatarInitials : botAvatarImage || botAvatarInitials) + ? avatarComponent(DefaultAvatar, Object.freeze({ fromUser })) + : undefined; + }); +} + +export default createDefaultAvatarMiddleware; diff --git a/packages/component/src/Middleware/Avatar/defaultAvatarPolymiddleware.tsx b/packages/component/src/Middleware/Avatar/defaultAvatarPolymiddleware.tsx deleted file mode 100644 index b7d6adf48d..0000000000 --- a/packages/component/src/Middleware/Avatar/defaultAvatarPolymiddleware.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { __INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol } from 'botframework-webchat-api/internal'; -import { avatarComponent, createAvatarPolymiddleware } from 'botframework-webchat-api/middleware'; -import DefaultAvatar from './DefaultAvatar'; - -const defaultAvatarMiddleware = createAvatarPolymiddleware( - _next => - ({ - activity, - [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: { - botAvatarImage, - botAvatarInitials, - userAvatarImage, - userAvatarInitials - } - }) => { - const fromUser = activity.from?.role === 'user'; - - return (fromUser ? userAvatarImage || userAvatarInitials : botAvatarImage || botAvatarInitials) - ? avatarComponent(DefaultAvatar, Object.freeze({ fromUser })) - : undefined; - } -); - -export default defaultAvatarMiddleware; From 5326629358f3d6d47c207f87e3bc8abc8f7e1247 Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 25 Mar 2026 07:47:29 +0000 Subject: [PATCH 40/51] Add changing middleware tests --- .../legacyAvatarMiddleware/changing.html | 117 ++++++++++++++++++ .../changing.html.snap-1.png | Bin 0 -> 16819 bytes .../changing.html.snap-2.png | Bin 0 -> 19583 bytes .../avatar/polymiddleware/changing.html | 113 +++++++++++++++++ .../polymiddleware/changing.html.snap-1.png | Bin 0 -> 16819 bytes .../polymiddleware/changing.html.snap-2.png | Bin 0 -> 15997 bytes 6 files changed, 230 insertions(+) create mode 100644 __tests__/html2/middleware/avatar/legacyAvatarMiddleware/changing.html create mode 100644 __tests__/html2/middleware/avatar/legacyAvatarMiddleware/changing.html.snap-1.png create mode 100644 __tests__/html2/middleware/avatar/legacyAvatarMiddleware/changing.html.snap-2.png create mode 100644 __tests__/html2/middleware/avatar/polymiddleware/changing.html create mode 100644 __tests__/html2/middleware/avatar/polymiddleware/changing.html.snap-1.png create mode 100644 __tests__/html2/middleware/avatar/polymiddleware/changing.html.snap-2.png diff --git a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/changing.html b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/changing.html new file mode 100644 index 0000000000..cd931bb706 --- /dev/null +++ b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/changing.html @@ -0,0 +1,117 @@ + + + + + + +
+ + + + diff --git a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/changing.html.snap-1.png b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/changing.html.snap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..15faa46ff77cce90334467153b5ac20a388d9ab5 GIT binary patch literal 16819 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 MTtTe-i$TEu0{FU8>Hq)$ literal 0 HcmV?d00001 diff --git a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/changing.html.snap-2.png b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/changing.html.snap-2.png new file mode 100644 index 0000000000000000000000000000000000000000..b8ebe9c68e59554b16f6f594fb921bcd8d4fe104 GIT binary patch literal 19583 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 aU}nhX+0@h~b;b@T!r + + + + + +
+ + + + diff --git a/__tests__/html2/middleware/avatar/polymiddleware/changing.html.snap-1.png b/__tests__/html2/middleware/avatar/polymiddleware/changing.html.snap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..15faa46ff77cce90334467153b5ac20a388d9ab5 GIT binary patch literal 16819 zcmeIaRa9GHyDr+67ARUMPLSfoDeknmYmnmZR@@7;xD+q$7TkhEf#ObZcMI;$o?U0H z%YDun`*M#zS94^HOnLJ@-}gR}geoaWqN5O@ym;{fU0O;^<;9Da7B61B`i}exct^bYScQ2&HKC8K>9V{WGscp3ioxlo4ZB|STlT5V+D8zpi7`==P$uatDbUPbapjl3| zA-@hD-+V7?WE4PTY|l2^aP=yO93|&s+0ZNb5N57$E6nb6Z1P<6hhf)r?Y3uhdnlRR zd<4xYIV%L)>|WocQLGpNLX);|8wx4BK)Tl{)2-5px{3!_zw#H z??yo-0v<@)`hlgjeRnXSgxK1;({|WXqvkQB1H!%l?;jo
nuKOHie`fG04JAQxCd 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 MTtTe-i$TEu0{FU8>Hq)$ literal 0 HcmV?d00001 diff --git a/__tests__/html2/middleware/avatar/polymiddleware/changing.html.snap-2.png b/__tests__/html2/middleware/avatar/polymiddleware/changing.html.snap-2.png new file mode 100644 index 0000000000000000000000000000000000000000..a05e2fe13b388c267232bced2749b41de426fafd GIT binary patch literal 15997 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 z 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 bhKMirM`a5+JY4;ND=$9Es>swxnS}g50bzfa literal 0 HcmV?d00001 From f6f835b25cb4b6b25e0b44a109989fec8025ac0b Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 25 Mar 2026 16:47:50 +0000 Subject: [PATCH 41/51] Add tests --- .../legacyAvatarMiddleware/styleOptions.html | 120 ++++++++++++++++++ .../styleOptions.html.snap-1.png | Bin 0 -> 19583 bytes .../styleOptions.html.snap-2.png | Bin 0 -> 19378 bytes .../defaultAvatar.styleOptions.html | 102 +++++++++++++++ ...defaultAvatar.styleOptions.html.snap-1.png | Bin 0 -> 11689 bytes ...defaultAvatar.styleOptions.html.snap-2.png | Bin 0 -> 10863 bytes 6 files changed, 222 insertions(+) create mode 100644 __tests__/html2/middleware/avatar/legacyAvatarMiddleware/styleOptions.html create mode 100644 __tests__/html2/middleware/avatar/legacyAvatarMiddleware/styleOptions.html.snap-1.png create mode 100644 __tests__/html2/middleware/avatar/legacyAvatarMiddleware/styleOptions.html.snap-2.png create mode 100644 __tests__/html2/middleware/avatar/polymiddleware/defaultAvatar.styleOptions.html create mode 100644 __tests__/html2/middleware/avatar/polymiddleware/defaultAvatar.styleOptions.html.snap-1.png create mode 100644 __tests__/html2/middleware/avatar/polymiddleware/defaultAvatar.styleOptions.html.snap-2.png diff --git a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/styleOptions.html b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/styleOptions.html new file mode 100644 index 0000000000..8bc9afd476 --- /dev/null +++ b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/styleOptions.html @@ -0,0 +1,120 @@ + + + + + + +
+ + + + diff --git a/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/styleOptions.html.snap-1.png b/__tests__/html2/middleware/avatar/legacyAvatarMiddleware/styleOptions.html.snap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..b8ebe9c68e59554b16f6f594fb921bcd8d4fe104 GIT binary patch literal 19583 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 aU}nhX+0@h~b;b@T!rP<#CeZ0h{lofc^3^b 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 literal 0 HcmV?d00001 diff --git a/__tests__/html2/middleware/avatar/polymiddleware/defaultAvatar.styleOptions.html b/__tests__/html2/middleware/avatar/polymiddleware/defaultAvatar.styleOptions.html new file mode 100644 index 0000000000..ccc94f8126 --- /dev/null +++ b/__tests__/html2/middleware/avatar/polymiddleware/defaultAvatar.styleOptions.html @@ -0,0 +1,102 @@ + + + + + + +
+ + + + diff --git a/__tests__/html2/middleware/avatar/polymiddleware/defaultAvatar.styleOptions.html.snap-1.png b/__tests__/html2/middleware/avatar/polymiddleware/defaultAvatar.styleOptions.html.snap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..f3a4c6837f2953f1e4177636570b1a2d5bce36d6 GIT binary patch literal 11689 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 literal 0 HcmV?d00001 diff --git a/__tests__/html2/middleware/avatar/polymiddleware/defaultAvatar.styleOptions.html.snap-2.png b/__tests__/html2/middleware/avatar/polymiddleware/defaultAvatar.styleOptions.html.snap-2.png new file mode 100644 index 0000000000000000000000000000000000000000..01dc08b0d023ecd96a046543a94dcfd76eff635e GIT binary patch literal 10863 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 Date: Wed, 25 Mar 2026 17:10:02 +0000 Subject: [PATCH 42/51] Fix type portability --- packages/api/src/boot/middleware.ts | 2 ++ .../Middleware/Avatar/createDefaultAvatarPolymiddleware.tsx | 6 +++++- packages/component/src/boot/internal.ts | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/api/src/boot/middleware.ts b/packages/api/src/boot/middleware.ts index 2e7611e28b..9d2dca6850 100644 --- a/packages/api/src/boot/middleware.ts +++ b/packages/api/src/boot/middleware.ts @@ -35,6 +35,8 @@ export { errorBoxComponent, ErrorBoxPolymiddlewareProxy, useBuildRenderErrorBoxCallback, + // For type portability only. + type __INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol, type ErrorBoxPolymiddleware, type ErrorBoxPolymiddlewareHandler, type ErrorBoxPolymiddlewareHandlerResult, diff --git a/packages/component/src/Middleware/Avatar/createDefaultAvatarPolymiddleware.tsx b/packages/component/src/Middleware/Avatar/createDefaultAvatarPolymiddleware.tsx index 9d8669f8cc..fff1d127df 100644 --- a/packages/component/src/Middleware/Avatar/createDefaultAvatarPolymiddleware.tsx +++ b/packages/component/src/Middleware/Avatar/createDefaultAvatarPolymiddleware.tsx @@ -1,5 +1,9 @@ import type { StyleOptions } from 'botframework-webchat-api'; -import { avatarComponent, createAvatarPolymiddleware } from 'botframework-webchat-api/middleware'; +import { + avatarComponent, + createAvatarPolymiddleware, + type __INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol +} from 'botframework-webchat-api/middleware'; import DefaultAvatar from './DefaultAvatar'; function createDefaultAvatarMiddleware(styleOptions: StyleOptions | undefined) { diff --git a/packages/component/src/boot/internal.ts b/packages/component/src/boot/internal.ts index 9064f4abf0..f49f3b5469 100644 --- a/packages/component/src/boot/internal.ts +++ b/packages/component/src/boot/internal.ts @@ -10,3 +10,6 @@ export { default as ScreenReaderText } from '../ScreenReaderText'; export { default as createIconComponent } from '../Utils/createIconComponent'; export { default as parseDocumentFragmentFromString } from '../Utils/parseDocumentFragmentFromString'; export { default as serializeDocumentFragmentIntoString } from '../Utils/serializeDocumentFragmentIntoString'; + +// For type portability +export { __INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol } from 'botframework-webchat-api/internal'; From 7fcdd2b3de0e6ba12b7b4b4fd5227105d6ced146 Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 25 Mar 2026 18:19:26 +0000 Subject: [PATCH 43/51] Add AvatarPolymiddlewareProxy --- .../html2/middleware/avatar/renderProxy.html | 138 ++++++++++++++++++ .../avatar/renderProxy.html.snap-1.png | Bin 0 -> 7105 bytes .../src/avatarPolymiddleware.tsx | 1 + packages/api/src/boot/middleware.ts | 7 +- .../middleware/AvatarPolymiddlewareProxy.tsx | 46 ++++++ 5 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 __tests__/html2/middleware/avatar/renderProxy.html create mode 100644 __tests__/html2/middleware/avatar/renderProxy.html.snap-1.png create mode 100644 packages/api/src/middleware/AvatarPolymiddlewareProxy.tsx diff --git a/__tests__/html2/middleware/avatar/renderProxy.html b/__tests__/html2/middleware/avatar/renderProxy.html new file mode 100644 index 0000000000..3a65c0257e --- /dev/null +++ b/__tests__/html2/middleware/avatar/renderProxy.html @@ -0,0 +1,138 @@ + + + + + + +
+ + + + diff --git a/__tests__/html2/middleware/avatar/renderProxy.html.snap-1.png b/__tests__/html2/middleware/avatar/renderProxy.html.snap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..6321eb2b6a2aa78ce4a86659748f5eb046ea0e3d GIT binary patch literal 7105 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 O0E-(?lhSMVqy7(A0*w6t literal 0 HcmV?d00001 diff --git a/packages/api-middleware/src/avatarPolymiddleware.tsx b/packages/api-middleware/src/avatarPolymiddleware.tsx index 92ace268fa..5dd8a7ce81 100644 --- a/packages/api-middleware/src/avatarPolymiddleware.tsx +++ b/packages/api-middleware/src/avatarPolymiddleware.tsx @@ -26,6 +26,7 @@ const { useBuildRenderCallback: useBuildRenderAvatarCallback } = templatePolymiddleware< { + // TODO: The `styleOptions` is only for legacy middleware. readonly [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: any; readonly activity: WebChatActivity; }, diff --git a/packages/api/src/boot/middleware.ts b/packages/api/src/boot/middleware.ts index 9d2dca6850..edd046e29c 100644 --- a/packages/api/src/boot/middleware.ts +++ b/packages/api/src/boot/middleware.ts @@ -18,18 +18,21 @@ export { export { avatarComponent, - AvatarPolymiddlewareProxy, createAvatarPolymiddleware, useBuildRenderAvatarCallback, type AvatarPolymiddleware, type AvatarPolymiddlewareHandler, type AvatarPolymiddlewareHandlerResult, type AvatarPolymiddlewareProps, - type AvatarPolymiddlewareProxyProps, type AvatarPolymiddlewareRenderer, type AvatarPolymiddlewareRequest } from '@msinternal/botframework-webchat-api-middleware'; +export { + default as AvatarPolymiddlewareProxy, + AvatarPolymiddlewareProxyProps +} from '../middleware/AvatarPolymiddlewareProxy'; + export { createErrorBoxPolymiddleware, errorBoxComponent, diff --git a/packages/api/src/middleware/AvatarPolymiddlewareProxy.tsx b/packages/api/src/middleware/AvatarPolymiddlewareProxy.tsx new file mode 100644 index 0000000000..3d9908b205 --- /dev/null +++ b/packages/api/src/middleware/AvatarPolymiddlewareProxy.tsx @@ -0,0 +1,46 @@ +// We need to patch from `api-middleware`. +// +// - Props of should not need `styleOptions` +// - We should call `useStyleOptions()` to get style options +// - However, `api-middleware` is before `api`, so it do not have access to `useStyleOptions` +// +// Until we have `api-style-options`, we have to patch inside `api`. + +import { + __INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol, + AvatarPolymiddlewareProxy as RawAvatarPolymiddlewareProxy +} from '@msinternal/botframework-webchat-api-middleware'; +import { validateProps } from '@msinternal/botframework-webchat-react-valibot'; +import type { WebChatActivity } from 'botframework-webchat-core'; +import React, { memo, useMemo } from 'react'; +import { custom, object, pipe, readonly, safeParse, type InferInput } from 'valibot'; +import { useStyleOptions } from '../hooks'; + +const avatarPolymiddlewareProxyPropsSchema = pipe( + object({ + activity: custom>(value => safeParse(object({}), value).success) + }), + readonly() +); + +type AvatarPolymiddlewareProxyProps = Readonly>; + +const AvatarPolymiddlewareProxy = memo((props: AvatarPolymiddlewareProxyProps) => { + const { activity } = validateProps(avatarPolymiddlewareProxyPropsSchema, props); + + const [styleOptions] = useStyleOptions(); + + const rawProps = useMemo( + () => ({ + [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: styleOptions + }), + [styleOptions] + ); + + return ; +}); + +AvatarPolymiddlewareProxy.displayName = 'AvatarPolymiddlewareProxy'; + +export default AvatarPolymiddlewareProxy; +export { avatarPolymiddlewareProxyPropsSchema, type AvatarPolymiddlewareProxyProps }; From 5d3bb3e1c3766a247779c39d81da6fcae355c8cc Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 25 Mar 2026 18:19:34 +0000 Subject: [PATCH 44/51] Clean up --- __tests__/html2/timestamp/attachmentSendTimeout.html | 1 - 1 file changed, 1 deletion(-) diff --git a/__tests__/html2/timestamp/attachmentSendTimeout.html b/__tests__/html2/timestamp/attachmentSendTimeout.html index f228c59b65..523dca36b2 100644 --- a/__tests__/html2/timestamp/attachmentSendTimeout.html +++ b/__tests__/html2/timestamp/attachmentSendTimeout.html @@ -5,7 +5,6 @@ - From 3bb3b7128bb710529d641e4ff69a886579d937ef Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 25 Mar 2026 18:30:40 +0000 Subject: [PATCH 45/51] Add useBuildRenderAvatarCallback test --- .../avatar/useBuildRenderAvatarCallback.html | 146 ++++++++++++++++++ ...eBuildRenderAvatarCallback.html.snap-1.png | Bin 0 -> 7105 bytes .../src/avatarPolymiddleware.tsx | 3 + 3 files changed, 149 insertions(+) create mode 100644 __tests__/html2/middleware/avatar/useBuildRenderAvatarCallback.html create mode 100644 __tests__/html2/middleware/avatar/useBuildRenderAvatarCallback.html.snap-1.png diff --git a/__tests__/html2/middleware/avatar/useBuildRenderAvatarCallback.html b/__tests__/html2/middleware/avatar/useBuildRenderAvatarCallback.html new file mode 100644 index 0000000000..9a704b4bf8 --- /dev/null +++ b/__tests__/html2/middleware/avatar/useBuildRenderAvatarCallback.html @@ -0,0 +1,146 @@ + + + + + + +
+ + + + diff --git a/__tests__/html2/middleware/avatar/useBuildRenderAvatarCallback.html.snap-1.png b/__tests__/html2/middleware/avatar/useBuildRenderAvatarCallback.html.snap-1.png new file mode 100644 index 0000000000000000000000000000000000000000..6321eb2b6a2aa78ce4a86659748f5eb046ea0e3d GIT binary patch literal 7105 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 O0E-(?lhSMVqy7(A0*w6t literal 0 HcmV?d00001 diff --git a/packages/api-middleware/src/avatarPolymiddleware.tsx b/packages/api-middleware/src/avatarPolymiddleware.tsx index 5dd8a7ce81..d57e789425 100644 --- a/packages/api-middleware/src/avatarPolymiddleware.tsx +++ b/packages/api-middleware/src/avatarPolymiddleware.tsx @@ -53,6 +53,9 @@ type AvatarPolymiddlewareProxyProps = Readonly. const AvatarPolymiddlewareProxy = memo(function AvatarPolymiddlewareProxy(props: AvatarPolymiddlewareProxyProps) { + // TODO: [P1] Proxy should not require `styleOptions`, it should read from `useStyleOptions`. + // However the `useStyleOptions` hook is in `api` which is not available in `api-middleware`. + // We should refactor `useStyleOptions` into `api-style-options` so we can make the hook available here. const { [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: styleOptions, activity } = validateProps(avatarPolymiddlewareProxyPropsSchema, props); From 63655d49073ea1227282a3bbf5fffb8ddf6b2e44 Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 25 Mar 2026 18:43:28 +0000 Subject: [PATCH 46/51] Clean up --- packages/api/src/hooks/useCreateAvatarRenderer.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/api/src/hooks/useCreateAvatarRenderer.ts b/packages/api/src/hooks/useCreateAvatarRenderer.ts index 7fb65cc08d..5884260a99 100644 --- a/packages/api/src/hooks/useCreateAvatarRenderer.ts +++ b/packages/api/src/hooks/useCreateAvatarRenderer.ts @@ -18,9 +18,10 @@ type CreateAvatarRendererCallback = ({ */ export default function useCreateAvatarRenderer(): CreateAvatarRendererCallback { const [styleOptions] = useStyleOptions(); - const styleOptionsRef = useRefFrom(styleOptions); const buildRenderAvatar = useBuildRenderAvatarCallback(); + const styleOptionsRef = useRefFrom(styleOptions); + // TODO: [P1] We should move this function into `api-middleware`. // However, it use `useStyleOptions` which is from `api` package. // In order to do that, we need to build a new `api-style-options` package first. From 8e1ce638d8db7db2c6e10d7c008acd282647292c Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 25 Mar 2026 18:53:42 +0000 Subject: [PATCH 47/51] Clean up --- packages/api/src/types/AvatarMiddleware.ts | 2 ++ packages/component/src/Composer.tsx | 4 ++-- .../Middleware/Activity/defaultActivityPolymiddleware.tsx | 7 +++++-- .../Avatar/createDefaultAvatarPolymiddleware.tsx | 1 + packages/component/src/boot/internal.ts | 2 +- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/api/src/types/AvatarMiddleware.ts b/packages/api/src/types/AvatarMiddleware.ts index 50b3c3dd40..3e3c2fb0c1 100644 --- a/packages/api/src/types/AvatarMiddleware.ts +++ b/packages/api/src/types/AvatarMiddleware.ts @@ -9,6 +9,8 @@ import ComponentMiddleware, { ComponentFactory } from './ComponentMiddleware'; type AvatarComponentFactoryArguments = [ { + // We need to keep the original polymiddleweare request while running inside legacy middleware. + // When we transit from legacy middleware back to polymiddleware, we can restore the request object. [__INTERNAL_DO_NOT_USE__legacyAvatarMiddlewareOriginalRequestSymbol]: AvatarPolymiddlewareRequest; activity: WebChatActivity; fromUser: boolean; diff --git a/packages/component/src/Composer.tsx b/packages/component/src/Composer.tsx index 7624bbcce7..e8fb5b4419 100644 --- a/packages/component/src/Composer.tsx +++ b/packages/component/src/Composer.tsx @@ -376,7 +376,7 @@ const Composer = ({ const { nonce, onTelemetry } = composerProps; const theme = useTheme(); - const patchedActivityMiddleware = useMemo( + const patchedActivityMiddleware = useMemoIterable( () => Object.freeze([...singleToArray(activityMiddleware ?? []), ...theme.activityMiddleware]), [activityMiddleware, theme.activityMiddleware] ); @@ -481,7 +481,7 @@ const Composer = ({ [sendBoxMiddlewareFromProps, theme.sendBoxMiddleware] ); - const sendBoxToolbarMiddleware = useMemo( + const sendBoxToolbarMiddleware = useMemoIterable( () => Object.freeze([ ...extractSendBoxToolbarMiddleware(sendBoxToolbarMiddlewareFromProps), diff --git a/packages/component/src/Middleware/Activity/defaultActivityPolymiddleware.tsx b/packages/component/src/Middleware/Activity/defaultActivityPolymiddleware.tsx index d2e1529327..b76c939fd0 100644 --- a/packages/component/src/Middleware/Activity/defaultActivityPolymiddleware.tsx +++ b/packages/component/src/Middleware/Activity/defaultActivityPolymiddleware.tsx @@ -1,5 +1,6 @@ /* eslint complexity: ["error", 21] */ import { ActivityMiddleware } from 'botframework-webchat-api'; +import { createActivityPolymiddlewareFromLegacy, type Polymiddleware } from 'botframework-webchat-api/middleware'; import { getActivityLivestreamingMetadata, getOrgSchemaMessage, @@ -7,7 +8,6 @@ import { } from 'botframework-webchat-core'; import React from 'react'; -import { createActivityPolymiddlewareFromLegacy, type Polymiddleware } from 'botframework-webchat-api/middleware'; import CarouselLayout from '../../Activity/CarouselLayout'; import StackedLayout from '../../Activity/StackedLayout'; @@ -96,4 +96,7 @@ const defaultActivityPolymiddleware: Polymiddleware = createActivityPolymiddlewa ); export default defaultActivityPolymiddleware; -export { createCoreActivityMiddleware }; +export { + // Exporting `createCoreActivityMiddleware()` for backward compatibility. + createCoreActivityMiddleware +}; diff --git a/packages/component/src/Middleware/Avatar/createDefaultAvatarPolymiddleware.tsx b/packages/component/src/Middleware/Avatar/createDefaultAvatarPolymiddleware.tsx index fff1d127df..c1d7a42329 100644 --- a/packages/component/src/Middleware/Avatar/createDefaultAvatarPolymiddleware.tsx +++ b/packages/component/src/Middleware/Avatar/createDefaultAvatarPolymiddleware.tsx @@ -2,6 +2,7 @@ import type { StyleOptions } from 'botframework-webchat-api'; import { avatarComponent, createAvatarPolymiddleware, + // For type portability. type __INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol } from 'botframework-webchat-api/middleware'; import DefaultAvatar from './DefaultAvatar'; diff --git a/packages/component/src/boot/internal.ts b/packages/component/src/boot/internal.ts index f49f3b5469..1dc92dd9f6 100644 --- a/packages/component/src/boot/internal.ts +++ b/packages/component/src/boot/internal.ts @@ -12,4 +12,4 @@ export { default as parseDocumentFragmentFromString } from '../Utils/parseDocume export { default as serializeDocumentFragmentIntoString } from '../Utils/serializeDocumentFragmentIntoString'; // For type portability -export { __INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol } from 'botframework-webchat-api/internal'; +export { type __INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol } from 'botframework-webchat-api/internal'; From 68ed0a90cc87d05ea19d1f97f9bd5b64d4c37dc8 Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 25 Mar 2026 19:57:28 +0000 Subject: [PATCH 48/51] Update doc --- CHANGELOG.md | 4 ++++ docs/MIDDLEWARE.md | 12 +++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d964ae03c1..5601c56193 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ Breaking changes in this release: - 💥 Root-level (unconnected) `Claim` entity is being deprecated, in PR [#5564](https://github.com/microsoft/BotFramework-WebChat/pull/5564), by [@compulim](https://github.com/compulim). It will be removed on or after 2027-08-29 - Use `entities[@id=""][@type="Message"].citation[@type="Claim"]` instead - 💥 `activityStatusMiddleware.nextVisibleActivity` and `activityStatusMiddleware.sameTimestampGroup` is removed after deprecation, in PR [#5565](https://github.com/microsoft/BotFramework-WebChat/issues/5565), by [@compulim](https://github.com/compulim) +- 💥 `avatarMiddleware` is being deprecated in favor of [`polymiddleware`](./docs/MIDDLEWARE.md). It will be removed on or after 2028-03-18, related to PR [#5779](https://github.com/microsoft/BotFramework-WebChat/pull/5779) ### Added @@ -108,8 +109,10 @@ Breaking changes in this release: - 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) and [#5566](https://github.com/microsoft/BotFramework-WebChat/pull/5566) + - Legacy middleware is prioritized over polymiddleware - Added `polymiddleware` to `` - Currently supports activity middleware and the new error box middleware + - Supports avatar middleware, by [@compulim](https://github.com/compulim) in PR [#5779](https://github.com/microsoft/BotFramework-WebChat/pull/5779) - 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 @@ -348,6 +351,7 @@ Breaking changes in this release: - Removed legacy test harness, in PR [#5655](https://github.com/microsoft/BotFramework-WebChat/issues/5655), by [@compulim](https://github.com/compulim) - All tests are now either using `html2` test harness or simple unit tests - Legacy and `html` (html1) test harness are all migrated to `html2` +- `avatarMiddleware` is being deprecated in favor of [`polymiddleware`](./docs/MIDDLEWARE.md). It will be removed on or after 2028-03-18, related to PR [#5779](https://github.com/microsoft/BotFramework-WebChat/pull/5779) ### Fixed diff --git a/docs/MIDDLEWARE.md b/docs/MIDDLEWARE.md index 41de6d8727..12c5eed04c 100644 --- a/docs/MIDDLEWARE.md +++ b/docs/MIDDLEWARE.md @@ -52,6 +52,8 @@ function MyChatUI() { The following are supported polymiddleware types: - Activity (PR [#5515](https://github.com/microsoft/BotFramework-WebChat/pull/5515)) +- Avatar (PR [#5779](https://github.com/microsoft/BotFramework-WebChat/pull/5779)) + - [Sample code](__tests__/html2/middleware/avatar/polymiddleware/decorate.html) - Error box (PR [#5515](https://github.com/microsoft/BotFramework-WebChat/pull/5515)) ## Recipes @@ -284,7 +286,7 @@ Over the past 7.5 years of journey, we learnt a lot. Polymiddleware combined all ### Polyfilling legacy middleware -Legacy middleware passed to deprecating props such as `activityMiddleware` will be upgraded to polymiddleware automatically and placed after other polymiddleware passed via the `polymiddleware` prop. In other words, legacy middleware has lower priority than polymiddleware. +Legacy middleware passed to deprecating props such as `activityMiddleware` will be upgraded to polymiddleware automatically and placed before other polymiddleware passed via the `polymiddleware` prop. In other words, legacy middleware has higher priority than polymiddleware. Special polymiddleware factory functions such as `createActivityPolymiddlewareFromLegacy()` allow input of legacy middleware and output as polymiddleware. This helps the transition period. However, these special factory functions is also marked as deprecated. @@ -296,7 +298,7 @@ When multiple legacy middleware are passed as an array to `createActivityPolymid ### When to use `useBuildRenderXXXCallback()` vs. ``? -The main differences are: +We recommend the proxy component if you do not care about empty rendering or element count. For example, empty `` will be emitted by proxy but not rendered by `useBuildRenderXXXCallback()`. - `useBuildRenderXXXCallback()` allows precise render control - Developers can control how the render function is being used and what to do if the polymiddleware decided not to render the activity @@ -314,8 +316,8 @@ The following table shows how polymiddleware are prioritized. | Priority | Type | Description | | -------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Highest | Error boundary |

All polymiddleware has an error boundary wrapper to control error propagation.

Error will be rendered using the `ErrorBox` polymiddleware and reported via `onTelemetry` prop.

| -| Normal | Polymiddleware | Polymiddleware passed to the `polymiddleware` prop. | -| Low | Legacy middleware | Legacy middleware passed to their corresponding prop (such as `activityMiddleware`) and upgraded automatically. | +| Normal | Legacy middleware | Legacy middleware passed to their corresponding prop (such as `activityMiddleware`) and upgraded automatically. | +| Low | Polymiddleware | Polymiddleware passed to the `polymiddleware` prop. | | Lowest | Catch-all as error | Requests not handled by any polymiddleware in the chain will be thrown as an error. | ## Deprecation dates @@ -328,7 +330,7 @@ We introduced polymiddleware in 2025-08-16. Based on our 2-year deprecation rule | Activity status | | (TBD) | | Attachment | | (TBD) | | Attachment for screen reader | | (TBD) | -| Avatar | | (TBD) | +| Avatar | PR [#5779](https://github.com/microsoft/BotFramework-WebChat/pull/5779) | 2028-03-18 | | Card action | | (TBD) | | Group activities | | (TBD) | | Scroll to end button | | (TBD) | From ae15b969ff233b8ed3f2d44465b48121b775a949 Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 25 Mar 2026 21:13:09 +0000 Subject: [PATCH 49/51] Centralize useBuildRenderCallback patch --- packages/api/src/boot/middleware.ts | 3 +- .../api/src/hooks/useCreateAvatarRenderer.ts | 25 +++---------- .../useBuildRenderAvatarCallback.ts | 37 +++++++++++++++++++ .../hooks/useRenderActivityProps.ts | 11 +----- 4 files changed, 46 insertions(+), 30 deletions(-) create mode 100644 packages/api/src/middleware/useBuildRenderAvatarCallback.ts diff --git a/packages/api/src/boot/middleware.ts b/packages/api/src/boot/middleware.ts index edd046e29c..cc9f351676 100644 --- a/packages/api/src/boot/middleware.ts +++ b/packages/api/src/boot/middleware.ts @@ -19,7 +19,6 @@ export { export { avatarComponent, createAvatarPolymiddleware, - useBuildRenderAvatarCallback, type AvatarPolymiddleware, type AvatarPolymiddlewareHandler, type AvatarPolymiddlewareHandlerResult, @@ -33,6 +32,8 @@ export { AvatarPolymiddlewareProxyProps } from '../middleware/AvatarPolymiddlewareProxy'; +export { default as useBuildRenderAvatarCallback } from '../middleware/useBuildRenderAvatarCallback'; + export { createErrorBoxPolymiddleware, errorBoxComponent, diff --git a/packages/api/src/hooks/useCreateAvatarRenderer.ts b/packages/api/src/hooks/useCreateAvatarRenderer.ts index 5884260a99..83671f28e6 100644 --- a/packages/api/src/hooks/useCreateAvatarRenderer.ts +++ b/packages/api/src/hooks/useCreateAvatarRenderer.ts @@ -1,41 +1,26 @@ -import { - __INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol, - useBuildRenderAvatarCallback -} from '@msinternal/botframework-webchat-api-middleware'; import type { WebChatActivity } from 'botframework-webchat-core'; import { useCallback, type ReactNode } from 'react'; -import { useRefFrom } from 'use-ref-from'; -import useStyleOptions from './useStyleOptions'; +import useBuildRenderAvatarCallback from '../middleware/useBuildRenderAvatarCallback'; -type CreateAvatarRendererCallback = ({ - activity -}: { - activity: WebChatActivity; +type CreateAvatarRendererCallback = (request: { + readonly activity: WebChatActivity; }) => false | (() => Exclude); /** * @deprecated Use `` or `useBuildRenderAvatarCallback` instead. This hook will be removed on or after 2028-03-16. */ export default function useCreateAvatarRenderer(): CreateAvatarRendererCallback { - const [styleOptions] = useStyleOptions(); const buildRenderAvatar = useBuildRenderAvatarCallback(); - const styleOptionsRef = useRefFrom(styleOptions); - // TODO: [P1] We should move this function into `api-middleware`. // However, it use `useStyleOptions` which is from `api` package. // In order to do that, we need to build a new `api-style-options` package first. return useCallback( ({ activity }) => { - const renderer = buildRenderAvatar( - Object.freeze({ - activity, - [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: styleOptionsRef.current - }) - ); + const renderer = buildRenderAvatar(Object.freeze({ activity })); return renderer ? (): ReactNode => renderer({}) : false; }, - [buildRenderAvatar, styleOptionsRef] + [buildRenderAvatar] ); } diff --git a/packages/api/src/middleware/useBuildRenderAvatarCallback.ts b/packages/api/src/middleware/useBuildRenderAvatarCallback.ts new file mode 100644 index 0000000000..caf58372d5 --- /dev/null +++ b/packages/api/src/middleware/useBuildRenderAvatarCallback.ts @@ -0,0 +1,37 @@ +// We need to patch `useBuildRenderAvatarCallback()` from `api-middleware`. +// +// - Request of `useBuildRenderAvatarCallback()` should not need `styleOptions` +// - We should call `useStyleOptions()` to get style options +// - However, `api-middleware` is before `api`, so it do not have access to `useStyleOptions` +// +// Until we have `api-style-options`, we have to patch `useBuildRenderAvatarCallback()` inside `api`. + +import { + __INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol, + useBuildRenderAvatarCallback as useBuildRenderAvatarCallbackRaw +} from '@msinternal/botframework-webchat-api-middleware'; +import type { WebChatActivity } from 'botframework-webchat-core'; +import { useCallback } from 'react'; +import type { ComponentRenderer } from 'react-chain-of-responsibility/preview'; +import { useRefFrom } from 'use-ref-from'; +import { useStyleOptions } from '../hooks'; + +export default function useBuildRenderAvatarCallback(): (request: { + readonly activity: WebChatActivity; +}) => ComponentRenderer<{ children?: never }> { + const [styleOptions] = useStyleOptions(); + + const renderAvatar = useBuildRenderAvatarCallbackRaw(); + const styleOptionsRef = useRefFrom(styleOptions); + + return useCallback<(request: { readonly activity: WebChatActivity }) => ReturnType>( + request => + renderAvatar( + Object.freeze({ + activity: request.activity, + [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: styleOptionsRef.current + }) + ), + [renderAvatar, styleOptionsRef] + ); +} diff --git a/packages/component/src/Transcript/hooks/useRenderActivityProps.ts b/packages/component/src/Transcript/hooks/useRenderActivityProps.ts index 62070d0ee3..4467295396 100644 --- a/packages/component/src/Transcript/hooks/useRenderActivityProps.ts +++ b/packages/component/src/Transcript/hooks/useRenderActivityProps.ts @@ -41,19 +41,12 @@ const useRenderActivityProps = (activity: WebChatActivity): RenderActivityProps lastActivityInStatusGroup === activity || typeof lastActivityInStatusGroup === 'undefined'; const renderAvatarForSenderGroup = useMemo Exclude)>(() => { - const fromUser = activity.from?.role === 'user'; // Pass styleOptions through the runtime object (not typed in public request) for internal use // by the core middleware and legacy bridge handlers. - const renderer = buildRenderAvatar( - Object.freeze({ - [__INTERNAL_DO_NOT_USE__avatarPolymiddlewareRequestStyleOptionsSymbol]: styleOptions, - activity, - fromUser - }) - ); + const renderer = buildRenderAvatar(Object.freeze({ activity })); return renderer ? (): ReactNode => renderer({}) : false; - }, [activity, buildRenderAvatar, styleOptions]); + }, [activity, buildRenderAvatar]); const isTopSideBotNub = isZeroOrPositive(bubbleNubOffset); const isTopSideUserNub = isZeroOrPositive(bubbleFromUserNubOffset); From 196fba014412f6035803f0f4f733505d724cd913 Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 25 Mar 2026 21:13:13 +0000 Subject: [PATCH 50/51] Add entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5601c56193..d7475e0a62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -406,6 +406,7 @@ Breaking changes in this release: - Fixed compatibility with `create-react-app` by adding file extension to `core-js` imports, by [@compulim](https://github.com/compulim) in PR [#5680](https://github.com/microsoft/BotFramework-WebChat/pull/5680) - Fixed virtual keyboard should be collapsed after being suppressed, in iOS 26.3, by [@compulim](https://github.com/compulim) in PR [#5757](https://github.com/microsoft/BotFramework-WebChat/pull/5757) - Fixed Fluent/Copilot typing indicator animation background color, in PR [#5770](https://github.com/microsoft/BotFramework-WebChat/pull/5770), by [@OEvgeny](https://github.com/OEvgeny) +- Fixed `` should not re-render when `attachment[ForScreenReader]Middleware` is updated without noticeable different (`iterateEquals`), by [@compulim](https://github.com/compulim), in PR [#5799](https://github.com/microsoft/BotFramework-WebChat/pull/5779) ## [4.18.0] - 2024-07-10 From d1dd577efa59fc17868a96c9defcf91d96d5bfb9 Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 25 Mar 2026 21:13:40 +0000 Subject: [PATCH 51/51] Fix PR number --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7475e0a62..99741da629 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -406,7 +406,7 @@ Breaking changes in this release: - Fixed compatibility with `create-react-app` by adding file extension to `core-js` imports, by [@compulim](https://github.com/compulim) in PR [#5680](https://github.com/microsoft/BotFramework-WebChat/pull/5680) - Fixed virtual keyboard should be collapsed after being suppressed, in iOS 26.3, by [@compulim](https://github.com/compulim) in PR [#5757](https://github.com/microsoft/BotFramework-WebChat/pull/5757) - Fixed Fluent/Copilot typing indicator animation background color, in PR [#5770](https://github.com/microsoft/BotFramework-WebChat/pull/5770), by [@OEvgeny](https://github.com/OEvgeny) -- Fixed `` should not re-render when `attachment[ForScreenReader]Middleware` is updated without noticeable different (`iterateEquals`), by [@compulim](https://github.com/compulim), in PR [#5799](https://github.com/microsoft/BotFramework-WebChat/pull/5779) +- Fixed `` should not re-render when `attachment[ForScreenReader]Middleware` is updated without noticeable different (`iterateEquals`), by [@compulim](https://github.com/compulim), in PR [#5779](https://github.com/microsoft/BotFramework-WebChat/pull/5779) ## [4.18.0] - 2024-07-10