From 7e05552325b3cb9c8fcc927a6df1b3b86a6024cf Mon Sep 17 00:00:00 2001 From: Zack Date: Wed, 11 Feb 2026 16:31:06 +0100 Subject: [PATCH] Refactor DisambiguatedProfile to shared-components (#31835) * Refactoring of DisambiguatedProfile into shared components * correct values and refactoring * Add username color classes to Storybook and clean up DisambiguatedProfile stories * Refactor DisambiguatedProfileView to use class component and enhance props structure * Refactor DisambiguatedProfile components to use member object and enhance props structure * Update copyright year to 2026 and adjust the tests to fit the correct memberinfro interface * Add DisambiguatedProfileViewModel class * Refactor DisambiguatedProfileViewModel to use member object and the rest of the props * Refactor SenderProfile to use DisambiguatedProfileViewModel and update DisambiguatedProfile styles * Refactor DisambiguatedProfileView to enhance interface documentation * Refactor DisambiguatedProfileView to use CSS modules for styling * Updated css + tests to fit the new changes * Update of the test snap to fit the current tests * Adjusted RoomMemberTitleView and SenderProfile to use the new viewmodel, removed the old component. * Implemented new viewmodel test for DisambiguatedProfileViewModel * Update copyright text * update css class names * update to correct snapshot after css name changes. * Apply suggestion from @florianduros Co-authored-by: Florian Duros * Moved logic to viewmodel instead of having it in the view. Removed unessecery functions and css. * removed unessecery file that I copied from root folder, this is no longed needed as I use the root file instead in the viewmodel * Better Formatting * Fix issues after merging develop * FIxed issues with eslint * Added Visible, non-interactive elements with click handlers must have at least one keyboard listener from eslint docs * Updated snapshot the fit the latest update with eslint button requirment * Update snapshot screens for new tests. * Update tests to reflect snapshots * Update snapshot due of outdated CSS module classes * Add useEffect to call setProps on the DisambiguatedProfileViewModel when props change, ensuring the view updates with the correct display name. Update LayoutSwitcher snapshot for new CSS classes. * Fix Playwright editing tests by adding exact match for Edit button selector The DisambiguatedProfile refactoring added role="button" to the component, causing the selector { name: "Edit" } to match both the user "Edith" and the actual Edit button. * Fix ForwardDialog location tests for async hook rendering The SenderProfile component now uses hooks that trigger async state updates. * Fix SenderProfile useEffect to only update changeable props * Added letter spacing * Added ClassName prop * Update snapshot * Update letter-spacing * Update snapshot screenshots * Update Snapshots * Update snapshot * Removal of letter spacing to test CI * Apply suggestion from @florianduros Co-authored-by: Florian Duros * Added closing brackets + added back letter-spacing * Update snapshots * Update snapshot * Update span to correctly apply to the CI tests, it wasn't possible to use classname as a prop * Update snapshot * Added comment to explain the span classNames * DisambiguatedProfileViewModel.setProps to runtime-changing props * replace DisambiguatedProfileViewModel setProps with explicit setters and update call sites * Update Setters * Prettier FIx * Update Setters * update DisambiguatedProfileViewModel setters and tests * Update SenderProfile to show connect display name * clone snapshot in setters to trigger reactive updates * use snapshot.merge in DisambiguatedProfileViewModel setters * emove duplicated logic in DisambiguatedProfileViewModel * Change snapshot name * Update viewmodel * Updated Tests * typo * Update src/viewmodels/profile/DisambiguatedProfileViewModel.ts Co-authored-by: Florian Duros * Removal of unused function * Update snapshots * Update tests to pass coverage * Update Eslint --------- Co-authored-by: Florian Duros --- .../shared-components/.storybook/preview.css | 26 +++ .../default-auto.png | Bin 0 -> 17352 bytes .../emphasized-auto.png | Bin 0 -> 17661 bytes .../full-example-auto.png | Bin 0 -> 18984 bytes .../with-color-class-auto.png | Bin 0 -> 17290 bytes .../with-mxid-auto.png | Bin 0 -> 19579 bytes .../with-tooltip-auto.png | Bin 0 -> 17250 bytes packages/shared-components/src/index.ts | 1 + .../DisambiguatedProfile.module.css | 27 +++ .../DisambiguatedProfile.stories.tsx | 83 +++++++ .../DisambiguatedProfile.test.tsx | 212 ++++++++++++++++++ .../DisambiguatedProfileView.tsx | 118 ++++++++++ .../DisambiguatedProfile.test.tsx.snap | 115 ++++++++++ .../profile/DisambiguatedProfile/index.tsx | 13 ++ playwright/e2e/editing/editing.spec.ts | 4 +- .../views/messages/DisambiguatedProfile.tsx | 75 ------- .../views/messages/SenderProfile.tsx | 34 ++- .../MemberList/tiles/RoomMemberTileView.tsx | 19 +- .../profile/DisambiguatedProfileViewModel.ts | 147 ++++++++++++ .../views/dialogs/ForwardDialog-test.tsx | 8 +- .../__snapshots__/ReplyChain-test.tsx.snap | 6 +- .../MemberTileView-test.tsx.snap | 12 +- .../LayoutSwitcher-test.tsx.snap | 18 +- .../AppearanceUserSettingsTab-test.tsx.snap | 18 +- .../__snapshots__/HTMLExport-test.ts.snap | 2 +- .../DisambiguatedProfileViewModel-test.tsx | 158 +++++++++++++ 26 files changed, 983 insertions(+), 113 deletions(-) create mode 100644 packages/shared-components/__vis__/linux/__baselines__/profile/DisambiguatedProfile/DisambiguatedProfile.stories.tsx/default-auto.png create mode 100644 packages/shared-components/__vis__/linux/__baselines__/profile/DisambiguatedProfile/DisambiguatedProfile.stories.tsx/emphasized-auto.png create mode 100644 packages/shared-components/__vis__/linux/__baselines__/profile/DisambiguatedProfile/DisambiguatedProfile.stories.tsx/full-example-auto.png create mode 100644 packages/shared-components/__vis__/linux/__baselines__/profile/DisambiguatedProfile/DisambiguatedProfile.stories.tsx/with-color-class-auto.png create mode 100644 packages/shared-components/__vis__/linux/__baselines__/profile/DisambiguatedProfile/DisambiguatedProfile.stories.tsx/with-mxid-auto.png create mode 100644 packages/shared-components/__vis__/linux/__baselines__/profile/DisambiguatedProfile/DisambiguatedProfile.stories.tsx/with-tooltip-auto.png create mode 100644 packages/shared-components/src/profile/DisambiguatedProfile/DisambiguatedProfile.module.css create mode 100644 packages/shared-components/src/profile/DisambiguatedProfile/DisambiguatedProfile.stories.tsx create mode 100644 packages/shared-components/src/profile/DisambiguatedProfile/DisambiguatedProfile.test.tsx create mode 100644 packages/shared-components/src/profile/DisambiguatedProfile/DisambiguatedProfileView.tsx create mode 100644 packages/shared-components/src/profile/DisambiguatedProfile/__snapshots__/DisambiguatedProfile.test.tsx.snap create mode 100644 packages/shared-components/src/profile/DisambiguatedProfile/index.tsx delete mode 100644 src/components/views/messages/DisambiguatedProfile.tsx create mode 100644 src/viewmodels/profile/DisambiguatedProfileViewModel.ts create mode 100644 test/viewmodels/profile/DisambiguatedProfileViewModel-test.tsx diff --git a/packages/shared-components/.storybook/preview.css b/packages/shared-components/.storybook/preview.css index 9f49585937..eb1772154e 100644 --- a/packages/shared-components/.storybook/preview.css +++ b/packages/shared-components/.storybook/preview.css @@ -8,3 +8,29 @@ Please see LICENSE files in the repository root for full details. .docs-story { background: var(--cpd-color-bg-canvas-default); } + +/* Username color classes - these are defined in the main app's _common.pcss + but need to be available in Storybook for components that use colorClass */ +.mx_Username_color1 { + color: var(--cpd-color-text-decorative-1); +} + +.mx_Username_color2 { + color: var(--cpd-color-text-decorative-2); +} + +.mx_Username_color3 { + color: var(--cpd-color-text-decorative-3); +} + +.mx_Username_color4 { + color: var(--cpd-color-text-decorative-4); +} + +.mx_Username_color5 { + color: var(--cpd-color-text-decorative-5); +} + +.mx_Username_color6 { + color: var(--cpd-color-text-decorative-6); +} diff --git a/packages/shared-components/__vis__/linux/__baselines__/profile/DisambiguatedProfile/DisambiguatedProfile.stories.tsx/default-auto.png b/packages/shared-components/__vis__/linux/__baselines__/profile/DisambiguatedProfile/DisambiguatedProfile.stories.tsx/default-auto.png new file mode 100644 index 0000000000000000000000000000000000000000..4f21429863fcbf1a5511b9e831c743e44e4c71bd GIT binary patch literal 17352 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 literal 0 HcmV?d00001 diff --git a/packages/shared-components/__vis__/linux/__baselines__/profile/DisambiguatedProfile/DisambiguatedProfile.stories.tsx/emphasized-auto.png b/packages/shared-components/__vis__/linux/__baselines__/profile/DisambiguatedProfile/DisambiguatedProfile.stories.tsx/emphasized-auto.png new file mode 100644 index 0000000000000000000000000000000000000000..8741845a45820fc1910b76d3f4e7ed78157eb797 GIT binary patch literal 17661 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 literal 0 HcmV?d00001 diff --git a/packages/shared-components/__vis__/linux/__baselines__/profile/DisambiguatedProfile/DisambiguatedProfile.stories.tsx/full-example-auto.png b/packages/shared-components/__vis__/linux/__baselines__/profile/DisambiguatedProfile/DisambiguatedProfile.stories.tsx/full-example-auto.png new file mode 100644 index 0000000000000000000000000000000000000000..19129fa1ac6c66aa9d9fdaa4c486937ccb0244f2 GIT binary patch literal 18984 zcmai6c|4T+_kZST)Swt4N|+MTf>w%nD$$Ch$P%rTER`+mOq&)-x82s>r2m5f;kkaCyW( zWH{SZ4)@!%OBV2d*dOL2ZqHJOb$%bi*vgh0$>qzBxxJ=dE_9Lf5Ns`~(btw?a^RTX z?^^?>g8Xk96)_vv{dBGM^^b7xIg$6k!hFCaMfFu*k4$Zs zS6&ug=3hki^9Fv&dL1}b61u^(Ca12b+fcl;M;vb9ej{-p;A5p( zk^AR?^`YO7^!qsPdVQ(Z=yS-Lo{x6dWb1F-G5u5Pb8N&J_x?-gTn+QvvOD#Qqjxk8 zd+78aEGWM!Kt3e+{VFT6A^BrAzlM3+~2)zb^{~cSW(G~Se`Qctg3zaq3tEK_{^S0OJYMUxPakY9rlr-8M9OzjQ&9w;s z@HxiAc7L&Z$nLV-BPFX|t2SOu+wq3`%?*p3bKl0* z7Mo~m-wrF*DLU5DpBL~YF-|cfKyz+{SsQR{mYJHw z_bMjzPl&jhBEB$;a08{+_@4-GfW5|nz8Pa_Ha774`BxG1TK_2foW1VUsuCRftTC(W zmrqe-UX^M~!B*e*b(;t7M70X;U5-}ls%k!#{;+-O`McAr3cFgw1-})`TVJf1pCfmp zq-wyaDKGC+aFe~vKaGzTD$a9^ls8!sS>zIV)uk^kpfjkoEG?%z?eXfG0&!(i)2xbh z-7niZJU)iJ&UN)KSpB|vnpuTUMvT7Y&!6Ra_U_Sdl(n2JKW|CAUR2OzvDH0y+h)_~ z#uL?c1D`I{rgeYTZgExnw`qTqR`7@2tKV-rakQc!q5t;I$2R->xX$hNKOIk)dx^!hwH zJmQ}~_@9!DS$WmBXS?;BD~WliuzRIxhpy4^kG^@nLA(E{xSY8CR*g&0-(q%nO!IB| z_VDy-jgHRJGX3iE&X==4<%rh|IEQo|3g{~uLOFclR8}wU(=c#np9g-KJY3ys?*FQy z(#XwSx%uaLqi=~Z!?b$V=C@~R?~4{UmaqTldt1RN;=A_4x7{D}!tV9|{7=I# zsrsTg`LmsS=n_rCyy`}!^@&&PdbxyKW_^BFwM=K)z17_Qip0zFx||Dq z^1pv`ZJc*iJEMAiZ}WmqZKP4YNlPpH`PH^huKqVXR@e5Ygh#nabk60KCh?Q;*eDAj z$7G*R|DQi|Jba7_Z@Vbp9ys->skHYd> zd;M_w>=;?;+85Qb)hlX3L_^ZCio#v@UR%H2yvA~v>VLJ9>d>mtfYA z!mj9w$rV%OYuo&j-EVy89buGwXU)71O+iL-g+UM3);?*CoN3+^TlY}U)qkb?y0*^0 z_Ihxy7IJ(Nujk1Zw{il_So@r{YwH)|#@z~i9t-|_& zu)Z@pSFdmHaVnhd7;WIxskVA`^h&3ol2M8NqpE}6xGoGTu~=2xHS0#$q5_*v`#%5p z;D|Dvrh%iYI(4ebbI;swkm>ZepZjQ3VoY~IuV(or`^as5y^qI^u5KGvsJ5=V*Cysu z2$)1cWuZ8-q481SKyS%H)jb0rn>*-e;%BVNu$!%D`L#y;w)9LvkFf36!>Ac!BTC!9 zMO<*bKKZ*(`^(w#`VW5h*hfxsi*&jFG4tNZvIpyAsbmok$fXIQKS#|*h}spq6Qpe8 zUL#P~-Wh2*Tt0`4+teSqiF{=2N2|(fkE@yM6P+={Ftq1VZl(tjg-F->Y!sLOJf*PZ zxl*ZtB=Zz}kzv<-8Q>s1`#pRuDKGnYNbf56PEaM&VM80Ay*x)WYcCPmo~*_^D3XFs z6m1KW{Y-p}MWJ)Ylk~R8azxq2=DOs6?HpMuPf$HOnTM2gwjHKKh>zhL;t|qQz(?-$ zi)Cnr1!Xd2c0hkV9L`g%Ac83IN$O^LVyNuVNAw%l_Eixs*6g&^+V^`5eJrYaK6g?0}uWl|Wh8^~Z{6I7kz#3^ znuRWe?F$#IwU&Z~#iHBB8{dcR_fMUYZs%|hF2iQ&fc|xMtX(eM4kT}KVqIbo^Q&j2 zGUDIGr(#=JrcXyt9BlS;xm>;(*7AchjB(*GzUTtTd0}St;uTl{ldAJlkaOwdaP}J| zd#QrT$nHc$pu#R&EaAsi72XXCeP_Z-8xAs^WYL}D#4TIOxQltD1*LJJ2>fk@GaJ07&dyl=v;u0 zeMVpDgG{C%lj*h=X$e_+o_|7?tG)_Dw3J`@GUV(SSF;?ggS%Mw@y-d7D(Q|s$(j0& z2dd*OOq8V#3QWfdJ&~e=*iCAPVwxy-@dDmYBx&Ex@idPF5gy87neG`E>%K>0(7LBL z9PK?xextIzA_WNnr8Qhdo7cBaW9H~2DfgJC6>PUMelE*BI3F7!W#3v2wwvr421kfh z14t7FW<|~*zw>rK98|#rcG5CRP3le{ztgKo;s9YdOP?wRl|iS+2&#+OgwA$H5XhtOCEZp-|@U5y@_U8AScJYQlU!g(w+ zWnO7KAF1M|`bz8r3aEvm6n26#m!FuOqs+u2K{d}N8RO3k1_Rr0i8JeoJCy}k9*D4?KSRp?azl{c&l~sSIg>p@Xc7Wzkl$L}cL6THuk8CX6p7N4 zApgnKNa6sj9Sxp9N;XD?%hxE*Q6=RsP30GmJFVmt~b^b`#{&2Q&96y|sqt8R~ynMW9u5s$IdY(ZU zKsDq3Y`95MWCZJFD%a^Fc~iGXGq-aOF5vw_#_m5pUWy68#Tx>4|83mWqtXN5@G+oe zjf*)e-=bZ#M7TT0P5`|V30>o<%#|kV4WZXhy)2l`nK{l=QA+hCT-TS0mB-=i6SDb< zGzp<9NU6Fe5tmYwkG9Yxa&$pTT^}-h8{g%dk(>%fK|C0>!*>NKWbAm)sRa7oa7p|s zDq1LP1-0yJ#65Zk+ut41q?zMoCGorAPJ=lhRr_x-Ok#>*jV8*T3y#lhPw;S3qr_Kx z*={}nLqdvvaPbqImy3d^lfXx!0ZwmTkseH5#*K1ibHU2Z zii1^1OpIMcyNC};uLCC6^WM^!yhVxRNw^D$?%Fv_LXEH$Z8%!H@fCG%ptfC$wX!)K z6L?5ByVY4L%4WHS1S}dhM|auMp&l1}CabS&5^R3f8X(=w=A6_i4M{@-J}U=UFf<0a z;`q{CNK2|s3{G5%tN>2<9V7Z6xq$dTO3#5DqjUFulMkhgiug!i2)Z@QO=YK%^F8K6&CL!Zl=q33E{8AI22-N@#wcr>4L+HjzrgbR>E9?C$ z#1P+ga-xvB$wC|0Y!hKa>=N8!2a*9mtO}buL#QwTy;BR^fP^8ixm#%>EnR#eUjf#+ zdm$Zus8S}8IzF3U4atZVhQw{+K9iympT^JR6zlMi$1~(lF;I$6+O?=be5m48ZW`%;<{lJsfd`i$(INTvG0J4ZO6-nRN{vjqGB8} zK?B5v2I~tv%JwiZIu}1K77R6Z)k;bH!=9nr^f8_TTof*iIZ zY1&`FZ`Gw7qw-FHBfD$~zW+5uir2>$3n)Vq^vF0u$_kk)yGG@5sx|EZ1ZQQ+tohh@ zV0-*t2R#WS0#g~sMLbPlJ9+IDDkmkh_?}&M0wQ@*S-uKMpEONDDBB^!3bFOw(8w@8 zAb68KMnSZ(yhe|vNRlYM3-&kRCK>DLo6d6qdX=wJoz5O+`gd+Nz|A3uFBt zWCC#!*fX8@1N=$S^I!K0%JQYjI85A& z`~*sxeE`$G1D6~LrnzVM+lY0{1z>V%cOauBk9&ka7hmVi0k-cPH#kel0e4Fd*5fY# zOkc`q^}#hy<7dO;h$DvB1_nHndgjt&{8h54P|v2BnVq8D8yrxY%WwY+w0lD9{1>Tw zu%3)H>dT6**xC0DawEnkMf+Hx=`*GZkePpf)TNog>$=A^^4M;VRNMH>?qDCDwVq0BZB^D=8$X4NFCH@b!48 z5|jRLX3@Uc+e0J^>rdum$gA~-!*CNN49t6#2znWtz;Ag?U+jzf18Utyl*#@DrAGU? zOSZW3=yexS)LQUcYmcs)LGnfIx8>y}vumpKt_~{8x#|;*Hy~R1F-Mr2iDxEO=t-ru z%&Wmdp8_6F<1%}TlBHE6T#b`}$H}y`E<>3lhReae03Kh4I9dq&*hx~?!h<}-v~P4H zd`H$9Oy|9s}}J*fbGv88e>T~2^X?b=2{6j>{ns;6PONL)P~-Hn_ zob`|jA9Ja)h*Q1-8<(sb=Fw~rbe~wmxm!-YG}&OoT>lDk*Uwy0Fw?-3c)6m~J{`<= zhDLfYhb}J2_1_@(@0X4?P~uIhk(9cEDL`<_wq~qKh-)8tj*QAurlL$y-uZ5O)LT&Fk2EGGC>y%ab)AM{v$XlWz)xaE1_7Z|+`j zl&&a9K+k~#I;ZFy&OV@=MK|mq^7n%r{WIQ;gU*U)j{9CDeu6 zscY+ALYw(5nLs-}_BWjH_uh)xv^ir}eulq!NB06yv7UV5fvx1nJ>U>ceJ}U7CZ=T@2?wx#^RD2>z1k zpaq!->4#y^FEOBmokQPa0~9lt@<0`1Y7oTd|Tqrp>S-E zC5lk~WF)(T@O$GpqJ9<0E&ggKw1m&f0OyxA(iSG%C-Hd9vjEz->xv{z1wiJPa;cI4 z^x8IMxE*~@aFxZM;II1zD%>^i{-C%A8Q7@6aflIbhxBk9rJX7hCnNQy^XCo93PtvC zvi@TD2HDL?02TY!H4TZdZP!E_itb=ygBKF`OFv-(2 z+4Rl-(*q_T;3)`>XAJHE6DOrkjCVq8cc9y7FGtvcz!toM?b&;CiVY+H;{V9X2kqw{ z4S6%to^qBX|EIxN&V2o;C#fgMuS7fHn(SOq4Fy^h3sP)yGl#1Vb)y#gbR?i!JViL0 zRuXiO*fq6D*N936uPCT&OC8K#E8*D!VjsLdg^}tLtc2|=bFNV#?2D2;S)-}1gzZW% z;Jt>#a5%b+u%p*t0k2_7PMh}8eS4cB_@)G;(zMUt#L!y|3W$a_|z_K zax=mDCwbH3A~wjx4)tRMPCj-9eU-2rZrzKLPlNC(Jt`_rgO;&!B~6rsz=6Bi3`yf% zlN442k%MG8U8h=WNJB!btFHrrs-Hc}XFC#^7DYmE9OOTqKShtOENHmEBWtaG0hd^; zW-q;Af@!dQT4@!y3xS19lBDrsoC5NvB;Ld27izQ8Xf^!{&g}8!T{;8{4KAYHlujpr z{1d`jDEaRy2aF_koV5q}xuwlCbB63B0_hWYIiXQ0@v1_1);)+SLM8C}O4f;lxe*6= zFB3h02Bt0#G11-1OrI0fvUCJPL3u-``O+pqC{$18NBK1<46mhqk}40EVzl7j5GB5b zel8>n41E+&j9-Jqt+ZdkSc8bL4|3w-vzL#MVMp>e>a8Q&m6gWy{hst&2VG-OM!kFz zxNhRDqf#vZmCzLo1=NRfeE|!>Y?&Vt)JvhDs*1hnPN1&Ix<{i>IJ`Y!O|~a!w6I+e-gli2 z-nK^MC(#4^!yAfVzmspbuoFgRF<*gJfNiZfQh5xaiVf-N%3tO+(Ac zfq0o$x6KK+33WS>J4Hh94pj8c+n20{tW~q9BGMZk!TeTLKw*dr4)w+w;v~UoFvZgX zUpxA`S&PQtCwhCp_RsI}`jT{X%j84x@Q@6VG1=H`ALVu6qzz~$ypEg#12~nli{1^N zIZv#S6DYvx3O6+e8Ttn_C1f)6K%1IpGVPgrc2vWkl}Jlc72UTX0Vs{Z+*tXFEH8=V zI7gTgfNQmJ4e=U9u?U)nL=Rpz>R+?3F(Uv*zib#^;|ED3g6)v7k}n&l)v}0}MS_29 z7@R%qNgR%o16nPq(;BQXq~+faL=Z7{7OkeZ$Gl*>SD6Btfwjxrr%2z0FmkUfm?{dh z=8I+!AC%q%sHWxD(NLY@6J=QgxW$(0szVfef;Tc9pcBD5(B``Lnv&)yWZti!&Q*tckIh#(XA z%Y2j!WgKTXEj|P&9(2|DEsLQl7*z^S5F}B|5>T~lu?5eJU4fE=yvLjlXvTC~w|e5c zCfZ?-sm zC7AZg*!fBlp?}LY#3BM`(15ev-;7#sj$Feb%nB%4J+x=q-)`9kJwqscGk2#SkV?%$ z?{KUtVvw<)7OPkd3Y@;2Kn?!K26zXhIU)Yx2}NKiC-w5__jLV7$}R@5d$Wz2H<9%R z?H-)KJvc?hoY4`kVyIFK@vb+8-!6NSCzRCCEK~_(R2n`XuJzZcLNj{5z!YRO{U(%y zg|Cx@bejO12{O*SXwSh(ebpE0ko$RhAmin&>Ew&k*9k)6ZIZ`@XOOWUu#;3!|2j@6 zkMD=v4vF*En?%7y+|Bu#;B)A|dOU}Neep&zv$%K@}=F0Ld-V~8q*ke0Uv(Ej#4oh+YHCkWRN`?+@j z?ce;9Hk8!kgv5K^L2%n~(bkjbBCOa@XaV~tKz!1lrngAqLW?I0r=x5K=moAicXF<@ zq%58&)I(*VZ6Z5j*%b!b#k#_T959lcZFn^8?wA5?2V0;RitWL)k%l z@K6eL3|OXuaR$c`0R&D8AxMo5Kx*`F5IF9pi4SWa4zQ0^f4H3cgg-jCey(a+M6CPjo zrc{gw`q@d#@i8Pc;OdE0CK8wg7VM-Yy!F6#ZLI;*WBSP?oxTlhcl~jsBQ)-_1exr= zENu|msC{DwIcmXrww}D`VUp(v$Uyb>F>}Jl9DqBA zI*09pXHj^wfVGbRg z_7Uv@y4WaSd(_4YM@;c;*SH{uZ?p_r4rr-%SMBr zLtK63lR~}aQFK?KADVR#FB69m%*>fD;t5`(Z9+}D8%Mh=S#YsB!=F0PIw$y93^CX? zB-q_)@SFYwNI>-GSv(5SubIHu?*IX6)p?;4 zd)pjcPY-H8HXHDmeX)#i-ZPCnsUX192RzcYHj>U;(i4sc=biKc%cY$6Olsid2{`Xp z{+H=-M7k%u37ogroHZ*Xc#u8eo#4E8C0~0$BLTf)yeB*w)Hqtv$%o-8@M)83;IF#9 z9PboJJ~*KIBq|w6>N_|~+Nr^>*D28(R=!K^pneQ=^dWIDnr7uMVFPzCm<60`k-hz{ zaxZh8HyPy4*s<;M9F`el9bT)Eq>ome3x%>QMr3#b<=?A-bQkDWkfjFcWxs;l^>duu z;Q&uJRyTdlEs#4~^ZLKI7@mQw5X#TZ0lDYcIr$Ufd8)8{Nb~*%{CykpPK%V=IEha* zg5dcbNg9X^qUCnB74^c06Bj@~a>I)R+Mjcs-9%>a<_~W>XQppuG~m=H)Ql1A0ZZ6( z;5wa{;wJx1E_5}t1l-=;4;ti9JJCmxYWyP_cMeFMKMapw7F8i`mj#*3MN9}ICZX@* z=h3&AkWUZ+*D%7%Y@64h2@{?V;N0|cn_nnvGUJdZ?f__Hkyr-?BWFqVEeHK7dG%YP zWVy~RB6_xxg>D8z-~3`N-rQr3mrMiXrd@nD5l3!{N&q$SGI0q&w6&6Y_s^CwC!NrK z@W}f|xKW3Sa`?mrfRqt2^#3-OPA3VAIS%I@-&iq|vP9t~R)I3l{wko>__b4#Oxs`P zXUeKfffl!U#C0m8#5J@6E8Gm4-dy6*Efov~OY9?Hu;gbn8==gB_@j_5;IeC`f4jDf zVf7ppBl|$aFiK1{jY&T2VP?*)G^;+h5hh)wCm)9Qsv~3awwQ22tx2mSWY`KaY*nr> z5-b(b!6Jg3k9&nLu0WkcsfBVHn&o26v^0&@c)hvIqR2 z8ds%o3hNUY4U6Ddya!CaTbvv(v?CZKd%&cled2+|;7l`mz=RAuFIEA5eHcApa@~#v z*UDIj(E}#D0_KN`#|`cQLks{wekqkc9oz#ZQHtLyD$*L<1111EfG(1$8D5{J%fJ!} zX9wsmjhwW1vkNnh!Y_@`fY)_KS9TXjGA6hj@NDlUK9BUB87E|_Zx8ZA5gJn;NwV%R`*xa8DS2ga3+<1pnJRFv=!g1YS|XQ(^~Q4!j3P=AYF@z7u}c6>5+?dd5L7 zE9N1QM#J-}8Y>c)1QGm(Vk|=G27SH0%Qp~+424@W#NLfgw7HAdVtD^b9ZXg+cn3A* ziSvdJlVF}J;Zm<0<4+t(L6^V}lbr&b8(pd!^t70&BYd+Ne9LD3eaUqIMxZConc{H~ zxqtt-DxpNmlz8z1>>bN=?{9BOpN#m+7%*LpJ+T2Ay0qscfDugrPDUL_n+G6qC>qiRn*7eE0I(;aQ&jSY#6 zi^s9r3JzPhp`P)b|1-d{~clZ4zq$sK5g|@^FnEFHRC&lBFe}v#a<0=JN4Ij)iCUTbO0XGV*?edUSYa@WF;b*%4WL^; z#XCl1ML}&J2iwQ}J%zAyb(u2S&Z*WfQK|4GlO>3x^-D6bLCKzc>QI-oeu-nT0dx{! z|I*ekX}9ET36I(OCDqrVQv*{hgId3&`ta#r(csoENdl&S69%__DH8idU%dvmehCsI zxr^r_`ZXC=3XwSQXjQ#ukUktFoG@%J^dVKzVF0(`gjHog9++{2;=IQj9yK;lI z$biA6bhN#4RF?G7nlakW95xv=+AbWy3a0}`0u+jp(ROc13m6+b+Ae7UdqY5EjJ8W! zz*9ljQ-zh1yGXTwg)p6#ujwRdw9_r%9B7Z_S^I318Veh50fVm4fW*7Fz9{!Xwt#O# zY{(nFoqWQk|E6v&?3;xK^!{s0UKR=)0f&7-L8R0(k?GWnqE8?QB6}VG{|i9b)1jYG zrQkeFiYbHd^6fQ*)9-NT=(P>4|viM6h2gcXh8UFr~q+^FUmSofh%VcNc_x)n&^PH zNb0vJA7T5)BD|0!0GeXtNf>${MCK6w4-SndIfa72coMtDFDY4CK6+;HGhl2O;198G zrpG+-qwuL<;WB_=neSlpgQ;Lm$Qw2Hnh|3#63iwES_;`UEiVVnOR>;-94l3Rc*E!8 z3{!=i|7>5n0e!q>~MWg>L&+;xYvP=>&j-3 zS^URl{EkZ~4_wP{_JWWHzX_B69xM<#BO&Z&bsQ7C>>xcPCNzWXW3J0Vw^7XbcKRoZ)Gw4I zmpML<-vT^C1VY9>9!oa0a7&BN;6oOB&>Gr`TU6wvPCouTKaNujmhgDyh+G;rd_PR2 zj0e}Jqj7L2{3j&`tjAyx?$FwMX*Fo%l2^J1OJn8l7yD8f7ySu2Jg{xk@fFNdFmlBG z&#gFmyon@0jkt#ypkgM{Az+dCh&xPMF~(A)BktHMG)(fk!x(YLQqa3}8eI&gM~}D@ z#Ry4p(1<(q9OjbH+=O&XI^vEgpv3ftfCD~_6LW#?@nDtcRlLqh0@Wn#S}D1U6$Dlu*45&$9=K2uy`p}x8joFeQPI?A! zD+oUOcGTz*zmlZ91sp@ZaXiUT`9!M)R|b!I(o!b9N?!EDZw)I*iAT)> zt4Q0*FtDzwM9%^-6mRdFj!zdkB=~-aLy613#^^i98`g@G%hO-n1%^Q=) z+x4m2Ou~H-Ms(srO}C!9?800x29NW2o_6^qx)7nP4;q9QwU48+#YRGMkc3z_fMmg7 z`I4jmGl*gZ!OCjrrR8uiS%wf-3g&vyfVtTY#IHPy^@Q~BrUAfoWrqPd^Hr=P#OGSz z{w6?ws255kIMwxUJ1jlsvIOCOw)`sY1 z(j)M*Fcql&dNu~=Q>H*(oeAK!^k-hnU%GlwoBR!A5^odEY}-iJA0#tR;YvR}y8NI2 znLkkh?o`q)Z-M7Tl>q6aL=p*a6|yVJ|qYAOvAafgvCvHQKmE99=6n&VZ11rdqMYdL%3q1Gy EAL0n5t^fc4 literal 0 HcmV?d00001 diff --git a/packages/shared-components/__vis__/linux/__baselines__/profile/DisambiguatedProfile/DisambiguatedProfile.stories.tsx/with-color-class-auto.png b/packages/shared-components/__vis__/linux/__baselines__/profile/DisambiguatedProfile/DisambiguatedProfile.stories.tsx/with-color-class-auto.png new file mode 100644 index 0000000000000000000000000000000000000000..c8cc5574eec07820843abac9bd6703e739de56a9 GIT binary patch literal 17290 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 literal 0 HcmV?d00001 diff --git a/packages/shared-components/__vis__/linux/__baselines__/profile/DisambiguatedProfile/DisambiguatedProfile.stories.tsx/with-mxid-auto.png b/packages/shared-components/__vis__/linux/__baselines__/profile/DisambiguatedProfile/DisambiguatedProfile.stories.tsx/with-mxid-auto.png new file mode 100644 index 0000000000000000000000000000000000000000..4758b37a5bf27e2f06ddd07edf809827a7db0c67 GIT binary patch literal 19579 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

j0HfaJaS!Aa4Du0P2#$>@1iLs826U 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 buu%+tXIF-Mk>5YC!dSDKw<>*w+rj?>ldS#| literal 0 HcmV?d00001 diff --git a/packages/shared-components/__vis__/linux/__baselines__/profile/DisambiguatedProfile/DisambiguatedProfile.stories.tsx/with-tooltip-auto.png b/packages/shared-components/__vis__/linux/__baselines__/profile/DisambiguatedProfile/DisambiguatedProfile.stories.tsx/with-tooltip-auto.png new file mode 100644 index 0000000000000000000000000000000000000000..d00a53f88e708f7dea0dc3632104b8a829fa7063 GIT binary patch literal 17250 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 u;~} { + const vm = useMockedViewModel(rest, { onClick }); + return ; +}; + +export default { + title: "Profile/DisambiguatedProfile", + component: DisambiguatedProfileViewWrapper, + tags: ["autodocs"], + argTypes: { + displayName: { control: "text" }, + colorClass: { control: "text" }, + className: { control: "text" }, + displayIdentifier: { control: "text" }, + title: { control: "text" }, + emphasizeDisplayName: { control: "boolean" }, + }, + args: { + displayName: "Alice", + emphasizeDisplayName: true, + onClick: fn(), + }, +} as Meta; + +const Template: StoryFn = (args) => ( + +); + +export const Default = Template.bind({}); + +export const WithMxid = Template.bind({}); +WithMxid.args = { + displayName: "Alice", + displayIdentifier: "@alice:example.org", + colorClass: "mx_Username_color1", +}; + +export const WithColorClass = Template.bind({}); +WithColorClass.args = { + displayName: "Bob", + colorClass: "mx_Username_color3", +}; + +export const Emphasized = Template.bind({}); +Emphasized.args = { + displayName: "Charlie", + emphasizeDisplayName: true, +}; + +export const WithTooltip = Template.bind({}); +WithTooltip.args = { + displayName: "Diana", + title: "Diana (@diana:example.org)", +}; + +export const FullExample = Template.bind({}); +FullExample.args = { + displayName: "Eve", + displayIdentifier: "@eve:matrix.org", + colorClass: "mx_Username_color5", + title: "Eve (@eve:matrix.org)", + emphasizeDisplayName: true, +}; diff --git a/packages/shared-components/src/profile/DisambiguatedProfile/DisambiguatedProfile.test.tsx b/packages/shared-components/src/profile/DisambiguatedProfile/DisambiguatedProfile.test.tsx new file mode 100644 index 0000000000..0b05a1e0ad --- /dev/null +++ b/packages/shared-components/src/profile/DisambiguatedProfile/DisambiguatedProfile.test.tsx @@ -0,0 +1,212 @@ +/* + * Copyright 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +import { composeStories } from "@storybook/react-vite"; +import React from "react"; +import userEvent from "@testing-library/user-event"; +import { createEvent, fireEvent } from "@testing-library/dom"; +import { afterEach, describe, expect, it, vi } from "vitest"; +import { render, screen } from "@test-utils"; + +import * as stories from "./DisambiguatedProfile.stories"; +import { + DisambiguatedProfileView, + type DisambiguatedProfileViewActions, + type DisambiguatedProfileViewSnapshot, +} from "./DisambiguatedProfileView"; +import { MockViewModel } from "../../viewmodel/MockViewModel"; + +const { Default, WithMxid, WithColorClass, Emphasized, WithTooltip, FullExample } = composeStories(stories); + +describe("DisambiguatedProfileView", () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + it("renders the default state", () => { + const { container } = render(); + expect(container).toMatchSnapshot(); + }); + + it("renders with MXID for disambiguation", () => { + const { container } = render(); + expect(container).toMatchSnapshot(); + }); + + it("renders with color class", () => { + const { container } = render(); + expect(container).toMatchSnapshot(); + }); + + it("renders with emphasized display name", () => { + const { container } = render(); + expect(container).toMatchSnapshot(); + }); + + it("renders with tooltip", () => { + const { container } = render(); + expect(container).toMatchSnapshot(); + }); + + it("renders the full example", () => { + const { container } = render(); + expect(container).toMatchSnapshot(); + }); + + class DisambiguatedProfileViewModel + extends MockViewModel + implements DisambiguatedProfileViewActions + { + public onClick?: DisambiguatedProfileViewActions["onClick"]; + + public constructor(snapshot: DisambiguatedProfileViewSnapshot, actions: DisambiguatedProfileViewActions = {}) { + super(snapshot); + this.onClick = actions.onClick; + } + } + + const getProfileContainer = (displayName: string): HTMLDivElement => { + const profileContainer = screen.getByText(displayName).closest("div"); + if (!profileContainer) { + throw new Error("Expected profile container to exist"); + } + return profileContainer; + }; + + it("should display the display name", () => { + const vm = new DisambiguatedProfileViewModel({ + displayName: "Eve", + }); + + render(); + expect(screen.getByText("Eve")).toBeInTheDocument(); + }); + + it("should display the MXID when provided", () => { + const vm = new DisambiguatedProfileViewModel({ + displayName: "Test User", + displayIdentifier: "@test:example.org", + }); + + render(); + expect(screen.getByText("@test:example.org")).toBeInTheDocument(); + }); + + it("should call onClick when clicked", async () => { + const onClick = vi.fn(); + const user = userEvent.setup(); + const vm = new DisambiguatedProfileViewModel( + { + displayName: "Clickable User", + }, + { onClick }, + ); + + render(); + await user.click(screen.getByText("Clickable User")); + expect(onClick).toHaveBeenCalled(); + }); + + it("should set button semantics when onClick is provided", () => { + const vm = new DisambiguatedProfileViewModel( + { + displayName: "Keyboard User", + }, + { onClick: vi.fn() }, + ); + + render(); + const profileContainer = getProfileContainer("Keyboard User"); + expect(profileContainer).toHaveAttribute("role", "button"); + expect(profileContainer).toHaveAttribute("tabIndex", "0"); + }); + + it("should call onClick on keyboard activation keys", () => { + const onClick = vi.fn(); + const vm = new DisambiguatedProfileViewModel( + { + displayName: "Keyboard User", + }, + { onClick }, + ); + + render(); + const profileContainer = getProfileContainer("Keyboard User"); + + const enterEvent = createEvent.keyDown(profileContainer, { key: "Enter" }); + fireEvent(profileContainer, enterEvent); + + const spaceEvent = createEvent.keyDown(profileContainer, { key: " " }); + fireEvent(profileContainer, spaceEvent); + + expect(enterEvent.defaultPrevented).toBe(true); + expect(spaceEvent.defaultPrevented).toBe(true); + expect(onClick).toHaveBeenCalledTimes(2); + }); + + it("should not call onClick for non-activation keys", () => { + const onClick = vi.fn(); + const vm = new DisambiguatedProfileViewModel( + { + displayName: "Keyboard User", + }, + { onClick }, + ); + + render(); + const profileContainer = getProfileContainer("Keyboard User"); + + fireEvent.keyDown(profileContainer, { key: "Escape" }); + expect(onClick).not.toHaveBeenCalled(); + }); + + it("should not set button semantics when onClick is not provided", () => { + const vm = new DisambiguatedProfileViewModel({ + displayName: "Static User", + }); + + render(); + const profileContainer = getProfileContainer("Static User"); + expect(profileContainer).not.toHaveAttribute("role"); + expect(profileContainer).not.toHaveAttribute("tabIndex"); + }); + + it("should display tooltip title when provided", () => { + const vm = new DisambiguatedProfileViewModel({ + displayName: "User With Tooltip", + title: "User With Tooltip (@user:example.org)", + }); + + render(); + expect(screen.getByText("User With Tooltip").closest("div")).toHaveAttribute( + "title", + "User With Tooltip (@user:example.org)", + ); + }); + + it("should apply color class when provided", () => { + const vm = new DisambiguatedProfileViewModel({ + displayName: "Colored User", + colorClass: "mx_Username_color3", + }); + + render(); + const displayNameElement = screen.getByText("Colored User"); + expect(displayNameElement).toHaveClass("mx_Username_color3"); + }); + + it("should apply emphasis styling when emphasizeDisplayName is true", () => { + const vm = new DisambiguatedProfileViewModel({ + displayName: "Emphasized User", + emphasizeDisplayName: true, + }); + + render(); + const displayNameElement = screen.getByText("Emphasized User"); + expect(displayNameElement).toHaveClass("mx_DisambiguatedProfile_displayName"); + }); +}); diff --git a/packages/shared-components/src/profile/DisambiguatedProfile/DisambiguatedProfileView.tsx b/packages/shared-components/src/profile/DisambiguatedProfile/DisambiguatedProfileView.tsx new file mode 100644 index 0000000000..df5128b2d8 --- /dev/null +++ b/packages/shared-components/src/profile/DisambiguatedProfile/DisambiguatedProfileView.tsx @@ -0,0 +1,118 @@ +/* + * Copyright 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +import React, { type JSX, type KeyboardEventHandler, type MouseEventHandler } from "react"; +import classNames from "classnames"; + +import { type ViewModel, useViewModel } from "../../viewmodel"; +import styles from "./DisambiguatedProfile.module.css"; + +/** + * The snapshot representing the current state of the DisambiguatedProfile. + */ +export interface DisambiguatedProfileViewSnapshot { + /** + * The display name to show. + */ + displayName: string; + /** + * The CSS class for coloring the display name (e.g., "mx_Username_color1"). + * Undefined if coloring is not enabled. + */ + colorClass?: string; + /** + * The CSS class name. + */ + className?: string; + /** + * The formatted user identifier to display when disambiguation is needed. + * Undefined if disambiguation is not required. + */ + displayIdentifier?: string; + /** + * The tooltip title text (pre-translated). + * Undefined if tooltip is not enabled. + */ + title?: string; + /** + * Whether to emphasize the display name with additional styling. + */ + emphasizeDisplayName?: boolean; +} + +/** + * Actions that can be performed on the DisambiguatedProfile. + */ +export interface DisambiguatedProfileViewActions { + /** + * Optional click handler for the profile. + */ + onClick?: MouseEventHandler; +} + +/** + * The view model for DisambiguatedProfileView. + */ +export type DisambiguatedProfileViewModel = ViewModel & + DisambiguatedProfileViewActions; + +interface DisambiguatedProfileViewProps { + /** + * The view model for the disambiguated profile. + */ + vm: DisambiguatedProfileViewModel; +} + +/** + * A component to display a user's profile with optional disambiguation. + * Shows the display name and optionally the MXID when disambiguation is needed + * (e.g., when multiple users have the same display name). + * + * @example + * ```tsx + * + * ``` + */ +export function DisambiguatedProfileView({ vm }: Readonly): JSX.Element { + const { displayName, colorClass, displayIdentifier, title, emphasizeDisplayName, className } = useViewModel(vm); + + const displayNameClasses = classNames(colorClass, { + [styles.disambiguatedProfile_displayName]: emphasizeDisplayName, + mx_DisambiguatedProfile_displayName: emphasizeDisplayName, + }); + + // Handle keyboard interaction for accessibility if onClick is provided + const handleKeyDown: KeyboardEventHandler | undefined = vm.onClick + ? (event) => { + if (event.key === "Enter" || event.key === " ") { + event.preventDefault(); + vm.onClick?.(event as unknown as React.MouseEvent); + } + } + : undefined; + + return ( +

+ + {displayName} + + {/* mx_DisambiguatedProfile_mxid is required for PCSS selectors like .mx_MemberTileView .mx_DisambiguatedProfile_mxid */} + {displayIdentifier && ( + + {displayIdentifier} + + )} +
+ ); +} diff --git a/packages/shared-components/src/profile/DisambiguatedProfile/__snapshots__/DisambiguatedProfile.test.tsx.snap b/packages/shared-components/src/profile/DisambiguatedProfile/__snapshots__/DisambiguatedProfile.test.tsx.snap new file mode 100644 index 0000000000..be12923128 --- /dev/null +++ b/packages/shared-components/src/profile/DisambiguatedProfile/__snapshots__/DisambiguatedProfile.test.tsx.snap @@ -0,0 +1,115 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`DisambiguatedProfileView > renders the default state 1`] = ` +
+
+ + Alice + +
+
+`; + +exports[`DisambiguatedProfileView > renders the full example 1`] = ` +
+
+ + Eve + + + @eve:matrix.org + +
+
+`; + +exports[`DisambiguatedProfileView > renders with MXID for disambiguation 1`] = ` +
+
+ + Alice + + + @alice:example.org + +
+
+`; + +exports[`DisambiguatedProfileView > renders with color class 1`] = ` +
+
+ + Bob + +
+
+`; + +exports[`DisambiguatedProfileView > renders with emphasized display name 1`] = ` +
+
+ + Charlie + +
+
+`; + +exports[`DisambiguatedProfileView > renders with tooltip 1`] = ` +
+
+ + Diana + +
+
+`; diff --git a/packages/shared-components/src/profile/DisambiguatedProfile/index.tsx b/packages/shared-components/src/profile/DisambiguatedProfile/index.tsx new file mode 100644 index 0000000000..3089ec37d4 --- /dev/null +++ b/packages/shared-components/src/profile/DisambiguatedProfile/index.tsx @@ -0,0 +1,13 @@ +/* + * Copyright 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +export { + DisambiguatedProfileView, + type DisambiguatedProfileViewModel, + type DisambiguatedProfileViewSnapshot, + type DisambiguatedProfileViewActions, +} from "./DisambiguatedProfileView"; diff --git a/playwright/e2e/editing/editing.spec.ts b/playwright/e2e/editing/editing.spec.ts index 415bcd1845..3754bcfb62 100644 --- a/playwright/e2e/editing/editing.spec.ts +++ b/playwright/e2e/editing/editing.spec.ts @@ -38,7 +38,7 @@ test.describe("Editing", () => { const editLastMessage = async (page: Page, edit: string) => { const eventTile = page.locator(".mx_RoomView_MessageList .mx_EventTile_last"); await eventTile.hover(); - await eventTile.getByRole("button", { name: "Edit" }).click(); + await eventTile.getByRole("button", { name: "Edit", exact: true }).click(); const textbox = page.getByRole("textbox", { name: "Edit message" }); await textbox.fill(edit); @@ -284,7 +284,7 @@ test.describe("Editing", () => { await expect(tile.getByText("Message", { exact: true })).toBeVisible(); const line = tile.locator(".mx_EventTile_line"); await line.hover(); - await line.getByRole("button", { name: "Edit" }).click(); + await line.getByRole("button", { name: "Edit", exact: true }).click(); await expect(axe).toHaveNoViolations(); const editComposer = page.getByRole("textbox", { name: "Edit message" }); await editComposer.pressSequentially("Foo"); diff --git a/src/components/views/messages/DisambiguatedProfile.tsx b/src/components/views/messages/DisambiguatedProfile.tsx deleted file mode 100644 index 660a832d37..0000000000 --- a/src/components/views/messages/DisambiguatedProfile.tsx +++ /dev/null @@ -1,75 +0,0 @@ -/* -Copyright 2024 New Vector Ltd. -Copyright 2022, 2023 The Matrix.org Foundation C.I.C. -Copyright 2021 Å imon Brandner - -SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE files in the repository root for full details. -*/ - -import React from "react"; -import classNames from "classnames"; - -import { _t } from "../../../languageHandler"; -import { getUserNameColorClass } from "../../../utils/FormattingUtils"; -import UserIdentifier from "../../../customisations/UserIdentifier"; - -interface MemberInfo { - userId: string; - roomId: string; - rawDisplayName?: string; - disambiguate: boolean; -} - -interface IProps { - member?: MemberInfo | null; - fallbackName: string; - onClick?(): void; - colored?: boolean; - emphasizeDisplayName?: boolean; - withTooltip?: boolean; -} - -export default class DisambiguatedProfile extends React.Component { - public render(): React.ReactNode { - const { fallbackName, member, colored, emphasizeDisplayName, withTooltip, onClick } = this.props; - const rawDisplayName = member?.rawDisplayName || fallbackName; - const mxid = member?.userId; - - let colorClass: string | undefined; - if (colored) { - colorClass = getUserNameColorClass(mxid ?? ""); - } - - let mxidElement; - let title: string | undefined; - - if (mxid) { - const identifier = - UserIdentifier.getDisplayUserIdentifier?.(mxid, { - withDisplayName: true, - roomId: member.roomId, - }) ?? mxid; - if (member?.disambiguate) { - mxidElement = {identifier}; - } - title = _t("timeline|disambiguated_profile", { - displayName: rawDisplayName, - matrixId: identifier, - }); - } - - const displayNameClasses = classNames(colorClass, { - mx_DisambiguatedProfile_displayName: emphasizeDisplayName, - }); - - return ( -
- - {rawDisplayName} - - {mxidElement} -
- ); - } -} diff --git a/src/components/views/messages/SenderProfile.tsx b/src/components/views/messages/SenderProfile.tsx index 2e51c1b50a..82b4523fb7 100644 --- a/src/components/views/messages/SenderProfile.tsx +++ b/src/components/views/messages/SenderProfile.tsx @@ -7,10 +7,11 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com Please see LICENSE files in the repository root for full details. */ -import React, { type JSX } from "react"; +import React, { type JSX, useEffect } from "react"; import { type MatrixEvent, MsgType } from "matrix-js-sdk/src/matrix"; +import { useCreateAutoDisposedViewModel, DisambiguatedProfileView } from "@element-hq/web-shared-components"; -import DisambiguatedProfile from "./DisambiguatedProfile"; +import { DisambiguatedProfileViewModel } from "../../../viewmodels/profile/DisambiguatedProfileViewModel"; import { useRoomMemberProfile } from "../../../hooks/room/useRoomMemberProfile"; interface IProps { @@ -20,20 +21,31 @@ interface IProps { } export default function SenderProfile({ mxEvent, onClick, withTooltip }: IProps): JSX.Element { + const sender = mxEvent.getSender(); + const member = useRoomMemberProfile({ - userId: mxEvent.getSender(), + userId: sender, member: mxEvent.sender, }); + const disambiguatedProfileVM = useCreateAutoDisposedViewModel( + () => + new DisambiguatedProfileViewModel({ + fallbackName: sender ?? "", + onClick, + member, + colored: true, + emphasizeDisplayName: true, + withTooltip, + className: "mx_DisambiguatedProfile", + }), + ); + + useEffect(() => { + disambiguatedProfileVM.setMember(sender ?? "", member); + }, [disambiguatedProfileVM, member, sender]); return mxEvent.getContent().msgtype !== MsgType.Emote ? ( - + ) : ( <> ); diff --git a/src/components/views/rooms/MemberList/tiles/RoomMemberTileView.tsx b/src/components/views/rooms/MemberList/tiles/RoomMemberTileView.tsx index 34c85af7b1..f8dbd02829 100644 --- a/src/components/views/rooms/MemberList/tiles/RoomMemberTileView.tsx +++ b/src/components/views/rooms/MemberList/tiles/RoomMemberTileView.tsx @@ -5,9 +5,9 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com Please see LICENSE files in the repository root for full details. */ -import React, { type JSX } from "react"; +import React, { type JSX, useEffect } from "react"; +import { useCreateAutoDisposedViewModel, DisambiguatedProfileView } from "@element-hq/web-shared-components"; -import DisambiguatedProfile from "../../../messages/DisambiguatedProfile"; import { type RoomMember } from "../../../../../models/rooms/RoomMember"; import { useMemberTileViewModel } from "../../../../viewmodels/memberlist/tiles/MemberTileViewModel"; import { E2EIconView } from "./common/E2EIconView"; @@ -17,6 +17,7 @@ import { _t } from "../../../../../languageHandler"; import { MemberTileView } from "./common/MemberTileView"; import { InvitedIconView } from "./common/InvitedIconView"; import { type MemberWithSeparator } from "../../../../viewmodels/memberlist/MemberListViewModel"; +import { DisambiguatedProfileViewModel } from "../../../../../viewmodels/profile/DisambiguatedProfileViewModel"; interface IProps { /** @@ -46,7 +47,19 @@ export function RoomMemberTileView(props: IProps): JSX.Element { /> ); const name = vm.name; - const nameJSX = ; + const disambiguatedProfileVM = useCreateAutoDisposedViewModel( + () => + new DisambiguatedProfileViewModel({ + fallbackName: name, + member, + withTooltip: true, + className: "mx_DisambiguatedProfile", + }), + ); + useEffect(() => { + disambiguatedProfileVM.setMember(name, member); + }, [disambiguatedProfileVM, member, name]); + const nameJSX = ; const presenceState = member.presenceState; let presenceJSX: JSX.Element | undefined; diff --git a/src/viewmodels/profile/DisambiguatedProfileViewModel.ts b/src/viewmodels/profile/DisambiguatedProfileViewModel.ts new file mode 100644 index 0000000000..807ae20522 --- /dev/null +++ b/src/viewmodels/profile/DisambiguatedProfileViewModel.ts @@ -0,0 +1,147 @@ +/* + * Copyright 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ +import { + BaseViewModel, + type DisambiguatedProfileViewActions, + type DisambiguatedProfileViewSnapshot, + type DisambiguatedProfileViewModel as DisambiguatedProfileViewModelInterface, +} from "@element-hq/web-shared-components"; +import { type MouseEvent } from "react"; + +import { _t } from "../../languageHandler"; +import { getUserNameColorClass } from "../../utils/FormattingUtils"; +import UserIdentifier from "../../customisations/UserIdentifier"; + +/** + * Information about a member for disambiguation purposes. + */ +interface MemberInfo { + /** + * The user's Matrix ID. + */ + userId: string; + /** + * The room ID context for disambiguation. + */ + roomId: string; + /** + * The raw display name of the user, if available. + */ + rawDisplayName?: string; + /** + * Whether the user is set to have disambiguation name. + */ + disambiguate: boolean; +} + +/** + * Props for the DisambiguatedProfileViewModel. + */ +export interface DisambiguatedProfileViewModelProps { + /** + * The member information for disambiguation. + */ + member?: MemberInfo | null; + /** + * The fallback name to use if the member's display name is not available. + */ + fallbackName: string; + /** + * Whether to apply color styling to the display name. + */ + colored?: boolean; + /** + * Whether to emphasize the display name. + */ + emphasizeDisplayName?: boolean; + /** + * Whether to show a tooltip with additional information. + */ + withTooltip?: boolean; + /** + * Optional click handler for the profile. + */ + onClick?: DisambiguatedProfileViewActions["onClick"]; + /** + * Optional CSS class name to apply to the profile. + */ + className?: string; +} + +/** + * ViewModel for the disambiguated profile, providing the current state of the component. + * It computes pre-rendered values for the View including color classes, display identifiers, and tooltips. + */ +export class DisambiguatedProfileViewModel + extends BaseViewModel + implements DisambiguatedProfileViewModelInterface +{ + private static readonly computeSnapshot = ( + props: DisambiguatedProfileViewModelProps, + ): DisambiguatedProfileViewSnapshot => { + const { member, fallbackName, colored, emphasizeDisplayName, withTooltip, className } = props; + + // Compute display name + const displayName = member?.rawDisplayName || fallbackName; + const mxid = member?.userId; + + // Compute color class if coloring is enabled + let colorClass: string | undefined; + if (colored && mxid) { + colorClass = getUserNameColorClass(mxid); + } + + // Compute display identifier for disambiguation + let displayIdentifier: string | undefined; + let title: string | undefined; + + if (mxid) { + const identifier = + UserIdentifier.getDisplayUserIdentifier?.(mxid, { + withDisplayName: true, + roomId: member?.roomId, + }) ?? mxid; + + // Only show identifier if disambiguation is needed + if (member?.disambiguate) { + displayIdentifier = identifier; + } + + // Compute tooltip title if enabled + if (withTooltip) { + title = _t("timeline|disambiguated_profile", { + displayName, + matrixId: identifier, + }); + } + } + + return { + displayName, + colorClass, + className, + displayIdentifier, + title, + emphasizeDisplayName, + }; + }; + + public constructor(props: DisambiguatedProfileViewModelProps) { + super(props, DisambiguatedProfileViewModel.computeSnapshot(props)); + } + + public setMember(fallbackName: string, member?: MemberInfo | null): void { + this.props.member = member; + this.props.fallbackName = fallbackName; + + this.snapshot.set(DisambiguatedProfileViewModel.computeSnapshot(this.props)); + } + + public onClick(evt: MouseEvent): void { + this.props.onClick?.(evt); + } +} diff --git a/test/unit-tests/components/views/dialogs/ForwardDialog-test.tsx b/test/unit-tests/components/views/dialogs/ForwardDialog-test.tsx index 683b7e1793..5bc614c12d 100644 --- a/test/unit-tests/components/views/dialogs/ForwardDialog-test.tsx +++ b/test/unit-tests/components/views/dialogs/ForwardDialog-test.tsx @@ -337,7 +337,7 @@ describe("ForwardDialog", () => { it("converts legacy location events to pin drop shares", async () => { const { container } = mountForwardDialog(legacyLocationEvent); - expect(container.querySelector(".mx_MLocationBody")).toBeTruthy(); + await waitFor(() => expect(container.querySelector(".mx_MLocationBody")).toBeTruthy()); sendToFirstRoom(container); // text and description from original event are removed @@ -364,7 +364,7 @@ describe("ForwardDialog", () => { it("removes personal information from static self location shares", async () => { const { container } = mountForwardDialog(modernLocationEvent); - expect(container.querySelector(".mx_MLocationBody")).toBeTruthy(); + await waitFor(() => expect(container.querySelector(".mx_MLocationBody")).toBeTruthy()); sendToFirstRoom(container); const timestamp = M_TIMESTAMP.findIn(modernLocationEvent.getContent())!; @@ -404,7 +404,7 @@ describe("ForwardDialog", () => { }; const { container } = mountForwardDialog(beaconEvent); - expect(container.querySelector(".mx_MLocationBody")).toBeTruthy(); + await waitFor(() => expect(container.querySelector(".mx_MLocationBody")).toBeTruthy()); sendToFirstRoom(container); @@ -414,7 +414,7 @@ describe("ForwardDialog", () => { it("forwards pin drop event", async () => { const { container } = mountForwardDialog(pinDropLocationEvent); - expect(container.querySelector(".mx_MLocationBody")).toBeTruthy(); + await waitFor(() => expect(container.querySelector(".mx_MLocationBody")).toBeTruthy()); sendToFirstRoom(container); diff --git a/test/unit-tests/components/views/elements/__snapshots__/ReplyChain-test.tsx.snap b/test/unit-tests/components/views/elements/__snapshots__/ReplyChain-test.tsx.snap index b22e49ae12..4f269d0818 100644 --- a/test/unit-tests/components/views/elements/__snapshots__/ReplyChain-test.tsx.snap +++ b/test/unit-tests/components/views/elements/__snapshots__/ReplyChain-test.tsx.snap @@ -31,10 +31,12 @@ exports[`ReplyChain should call setQuoteExpanded if chain is longer than 2 lines u
@userId:matrix.org diff --git a/test/unit-tests/components/views/rooms/memberlist/__snapshots__/MemberTileView-test.tsx.snap b/test/unit-tests/components/views/rooms/memberlist/__snapshots__/MemberTileView-test.tsx.snap index 4b5fbda763..4c5b4bcda5 100644 --- a/test/unit-tests/components/views/rooms/memberlist/__snapshots__/MemberTileView-test.tsx.snap +++ b/test/unit-tests/components/views/rooms/memberlist/__snapshots__/MemberTileView-test.tsx.snap @@ -35,7 +35,9 @@ exports[`MemberTileView RoomMemberTileView should display an verified E2EIcon wh class="mx_MemberTileView_name" >
should render 1`] = ` tabindex="-1" >
Alice @@ -210,10 +212,12 @@ exports[` should render 1`] = ` tabindex="-1" >
Alice @@ -352,10 +356,12 @@ exports[` should render 1`] = ` class="mx_MessageTimestamp" />
Alice diff --git a/test/unit-tests/components/views/settings/tabs/user/__snapshots__/AppearanceUserSettingsTab-test.tsx.snap b/test/unit-tests/components/views/settings/tabs/user/__snapshots__/AppearanceUserSettingsTab-test.tsx.snap index cb9c51ad20..f78cf65ae3 100644 --- a/test/unit-tests/components/views/settings/tabs/user/__snapshots__/AppearanceUserSettingsTab-test.tsx.snap +++ b/test/unit-tests/components/views/settings/tabs/user/__snapshots__/AppearanceUserSettingsTab-test.tsx.snap @@ -214,10 +214,12 @@ exports[`AppearanceUserSettingsTab should render 1`] = ` tabindex="-1" >
@userId:matrix.org @@ -353,10 +355,12 @@ exports[`AppearanceUserSettingsTab should render 1`] = ` tabindex="-1" >
@userId:matrix.org @@ -495,10 +499,12 @@ exports[`AppearanceUserSettingsTab should render 1`] = ` class="mx_MessageTimestamp" />
@userId:matrix.org diff --git a/test/unit-tests/utils/exportUtils/__snapshots__/HTMLExport-test.ts.snap b/test/unit-tests/utils/exportUtils/__snapshots__/HTMLExport-test.ts.snap index f0903c5b16..115385f2e4 100644 --- a/test/unit-tests/utils/exportUtils/__snapshots__/HTMLExport-test.ts.snap +++ b/test/unit-tests/utils/exportUtils/__snapshots__/HTMLExport-test.ts.snap @@ -57,7 +57,7 @@ exports[`HTMLExport should export 1`] = `

-
  • @user49:example.com
    00:00
    Message #49
  • @user48:example.com
    00:00
    Message #48
  • @user47:example.com
    00:00
    Message #47
  • @user46:example.com
    00:00
    Message #46
  • @user45:example.com
    00:00
    Message #45
  • @user44:example.com
    00:00
    Message #44
  • @user43:example.com
    00:00
    Message #43
  • @user42:example.com
    00:00
    Message #42
  • @user41:example.com
    00:00
    Message #41
  • @user40:example.com
    00:00
    Message #40
  • @user39:example.com
    00:00
    Message #39
  • @user38:example.com
    00:00
    Message #38
  • @user37:example.com
    00:00
    Message #37
  • @user36:example.com
    00:00
    Message #36
  • @user35:example.com
    00:00
    Message #35
  • @user34:example.com
    00:00
    Message #34
  • @user33:example.com
    00:00
    Message #33
  • @user32:example.com
    00:00
    Message #32
  • @user31:example.com
    00:00
    Message #31
  • @user30:example.com
    00:00
    Message #30
  • @user29:example.com
    00:00
    Message #29
  • @user28:example.com
    00:00
    Message #28
  • @user27:example.com
    00:00
    Message #27
  • @user26:example.com
    00:00
    Message #26
  • @user25:example.com
    00:00
    Message #25
  • @user24:example.com
    00:00
    Message #24
  • @user23:example.com
    00:00
    Message #23
  • @user22:example.com
    00:00
    Message #22
  • @user21:example.com
    00:00
    Message #21
  • @user20:example.com
    00:00
    Message #20
  • @user19:example.com
    00:00
    Message #19
  • @user18:example.com
    00:00
    Message #18
  • @user17:example.com
    00:00
    Message #17
  • @user16:example.com
    00:00
    Message #16
  • @user15:example.com
    00:00
    Message #15
  • @user14:example.com
    00:00
    Message #14
  • @user13:example.com
    00:00
    Message #13
  • @user12:example.com
    00:00
    Message #12
  • @user11:example.com
    00:00
    Message #11
  • @user10:example.com
    00:00
    Message #10
  • @user9:example.com
    00:00
    Message #9
  • @user8:example.com
    00:00
    Message #8
  • @user7:example.com
    00:00
    Message #7
  • @user6:example.com
    00:00
    Message #6
  • @user5:example.com
    00:00
    Message #5
  • @user4:example.com
    00:00
    Message #4
  • @user3:example.com
    00:00
    Message #3
  • @user2:example.com
    00:00
    Message #2
  • @user1:example.com
    00:00
    Message #1
  • @user0:example.com
    00:00
    Message #0
  • +
  • @user49:example.com
    00:00
    Message #49
  • @user48:example.com
    00:00
    Message #48
  • @user47:example.com
    00:00
    Message #47
  • @user46:example.com
    00:00
    Message #46
  • @user45:example.com
    00:00
    Message #45
  • @user44:example.com
    00:00
    Message #44
  • @user43:example.com
    00:00
    Message #43
  • @user42:example.com
    00:00
    Message #42
  • @user41:example.com
    00:00
    Message #41
  • @user40:example.com
    00:00
    Message #40
  • @user39:example.com
    00:00
    Message #39
  • @user38:example.com
    00:00
    Message #38
  • @user37:example.com
    00:00
    Message #37
  • @user36:example.com
    00:00
    Message #36
  • @user35:example.com
    00:00
    Message #35
  • @user34:example.com
    00:00
    Message #34
  • @user33:example.com
    00:00
    Message #33
  • @user32:example.com
    00:00
    Message #32
  • @user31:example.com
    00:00
    Message #31
  • @user30:example.com
    00:00
    Message #30
  • @user29:example.com
    00:00
    Message #29
  • @user28:example.com
    00:00
    Message #28
  • @user27:example.com
    00:00
    Message #27
  • @user26:example.com
    00:00
    Message #26
  • @user25:example.com
    00:00
    Message #25
  • @user24:example.com
    00:00
    Message #24
  • @user23:example.com
    00:00
    Message #23
  • @user22:example.com
    00:00
    Message #22
  • @user21:example.com
    00:00
    Message #21
  • @user20:example.com
    00:00
    Message #20
  • @user19:example.com
    00:00
    Message #19
  • @user18:example.com
    00:00
    Message #18
  • @user17:example.com
    00:00
    Message #17
  • @user16:example.com
    00:00
    Message #16
  • @user15:example.com
    00:00
    Message #15
  • @user14:example.com
    00:00
    Message #14
  • @user13:example.com
    00:00
    Message #13
  • @user12:example.com
    00:00
    Message #12
  • @user11:example.com
    00:00
    Message #11
  • @user10:example.com
    00:00
    Message #10
  • @user9:example.com
    00:00
    Message #9
  • @user8:example.com
    00:00
    Message #8
  • @user7:example.com
    00:00
    Message #7
  • @user6:example.com
    00:00
    Message #6
  • @user5:example.com
    00:00
    Message #5
  • @user4:example.com
    00:00
    Message #4
  • @user3:example.com
    00:00
    Message #3
  • @user2:example.com
    00:00
    Message #2
  • @user1:example.com
    00:00
    Message #1
  • @user0:example.com
    00:00
    Message #0
  • diff --git a/test/viewmodels/profile/DisambiguatedProfileViewModel-test.tsx b/test/viewmodels/profile/DisambiguatedProfileViewModel-test.tsx new file mode 100644 index 0000000000..270f3e66b4 --- /dev/null +++ b/test/viewmodels/profile/DisambiguatedProfileViewModel-test.tsx @@ -0,0 +1,158 @@ +/* + * Copyright 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +import { DisambiguatedProfileViewModel } from "../../../src/viewmodels/profile/DisambiguatedProfileViewModel"; + +describe("DisambiguatedProfileViewModel", () => { + const member = { + userId: "@alice:example.org", + roomId: "!room:example.org", + rawDisplayName: "Alice", + disambiguate: true, + }; + const nonDisambiguatedMember = { + ...member, + disambiguate: false, + }; + + it("should return the snapshot from props", () => { + const vm = new DisambiguatedProfileViewModel({ + member, + fallbackName: "Fallback", + colored: true, + emphasizeDisplayName: true, + withTooltip: true, + }); + + expect(vm.getSnapshot()).toEqual({ + displayName: "Alice", + colorClass: "mx_Username_color3", + className: undefined, + displayIdentifier: "@alice:example.org", + title: "Alice (@alice:example.org)", + emphasizeDisplayName: true, + }); + }); + + it("should default member fields when member is null", () => { + const vm = new DisambiguatedProfileViewModel({ + member: null, + fallbackName: "Fallback", + }); + + expect(vm.getSnapshot()).toMatchObject({ + displayName: "Fallback", + colorClass: undefined, + className: undefined, + displayIdentifier: undefined, + title: undefined, + emphasizeDisplayName: undefined, + }); + }); + + it("should pass through className prop", () => { + const vm = new DisambiguatedProfileViewModel({ + member, + fallbackName: "Fallback", + className: "mx_DisambiguatedProfile", + }); + + expect(vm.getSnapshot().className).toBe("mx_DisambiguatedProfile"); + }); + + it("should delegate onClick without emitting a snapshot update", () => { + const onClick = jest.fn(); + const vm = new DisambiguatedProfileViewModel({ + member, + fallbackName: "Fallback", + onClick, + }); + const prevSnapshot = vm.getSnapshot(); + const subscriber = jest.fn(); + + vm.subscribe(subscriber); + onClick({} as never); + + expect(onClick).toHaveBeenCalledTimes(1); + expect(subscriber).not.toHaveBeenCalled(); + expect(vm.getSnapshot()).toBe(prevSnapshot); + }); + + it("should emit snapshot update when fallbackName changes", () => { + const vm = new DisambiguatedProfileViewModel({ + member: null, + fallbackName: "Fallback", + }); + const subscriber = jest.fn(); + + vm.subscribe(subscriber); + vm.setMember("Updated"); + + expect(subscriber).toHaveBeenCalledTimes(1); + expect(vm.getSnapshot().displayName).toBe("Updated"); + }); + + it("should emit snapshot update when setMember is called even if fallbackName is unchanged", () => { + const vm = new DisambiguatedProfileViewModel({ + member: null, + fallbackName: "Fallback", + }); + const subscriber = jest.fn(); + + vm.subscribe(subscriber); + vm.setMember("Fallback"); + + expect(subscriber).toHaveBeenCalledTimes(1); + }); + + it("should compute tooltip title from constructor props when withTooltip is true", () => { + const vm = new DisambiguatedProfileViewModel({ + member, + fallbackName: "Fallback", + withTooltip: true, + }); + + expect(vm.getSnapshot().title).toBe("Alice (@alice:example.org)"); + }); + + it("should compute tooltip title even when disambiguation is not needed", () => { + const vm = new DisambiguatedProfileViewModel({ + member: nonDisambiguatedMember, + fallbackName: "Fallback", + withTooltip: true, + }); + + expect(vm.getSnapshot().title).toBe("Alice (@alice:example.org)"); + }); + + it("should emit snapshot update when member changes via setMember", () => { + const vm = new DisambiguatedProfileViewModel({ + member: null, + fallbackName: "Fallback", + }); + const subscriber = jest.fn(); + + vm.subscribe(subscriber); + vm.setMember("Fallback", member); + + expect(subscriber).toHaveBeenCalledTimes(1); + expect(vm.getSnapshot().displayName).toBe("Alice"); + }); + + it("should emit snapshot update when setMember is called with unchanged member", () => { + const vm = new DisambiguatedProfileViewModel({ + member, + fallbackName: "Fallback", + }); + const subscriber = jest.fn(); + + vm.subscribe(subscriber); + vm.setMember("Fallback", member); + + expect(subscriber).toHaveBeenCalledTimes(1); + }); +});