From 6173c1224b54ad475873bb5f3f8f357aa7d4faf6 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Wed, 26 Feb 2025 06:23:19 +0000 Subject: [PATCH 001/458] [create-pull-request] automated change (#29364) Co-authored-by: t3chguy <2403652+t3chguy@users.noreply.github.com> --- src/i18n/strings/fr.json | 6 ++++++ src/i18n/strings/nb_NO.json | 33 ++++++++++++++++++++------------- src/i18n/strings/uk.json | 5 +++++ 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index ab4c75ceaa..fd21ce2232 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -1245,6 +1245,7 @@ "change": "Changer le serveur d’identité", "change_prompt": "Se déconnecter du serveur d’identité et se connecter à à la place ?", "change_server_prompt": "Si vous ne voulez pas utiliser pour découvrir et être découvrable par les contacts que vous connaissez, saisissez un autre serveur d’identité ci-dessous.", + "changed": "Votre serveur d’identité a été changé", "checking": "Vérification du serveur", "description_connected": "Vous utilisez actuellement pour découvrir et être découvert par des contacts existants que vous connaissez. Vous pouvez changer votre serveur d’identité ci-dessous.", "description_disconnected": "Vous n’utilisez actuellement aucun serveur d’identité. Pour découvrir et être découvert par les contacts existants que vous connaissez, ajoutez-en un ci-dessous.", @@ -2096,6 +2097,7 @@ "other": "Vous êtes en train de rejoindre %(count)s salons" }, "notification_options": "Paramètres de notifications", + "open_space_menu": "Ouvrir le menu de l’espace", "redacting_messages_status": { "one": "Actuellement en train de supprimer les messages dans %(count)s salon", "other": "Actuellement en train de supprimer les messages dans %(count)s salons" @@ -2110,6 +2112,10 @@ "sort_by_activity": "Activité", "sort_by_alphabet": "A-Z", "sort_unread_first": "Afficher les salons non lus en premier", + "space_menu": { + "home": "Accueil de l’espace", + "space_settings": "Paramètres de l'espace" + }, "space_menu_label": "Menu %(spaceName)s", "sublist_options": "Options de liste", "suggested_rooms_heading": "Salons recommandés" diff --git a/src/i18n/strings/nb_NO.json b/src/i18n/strings/nb_NO.json index f20b4e1af6..6404721caa 100644 --- a/src/i18n/strings/nb_NO.json +++ b/src/i18n/strings/nb_NO.json @@ -4,12 +4,12 @@ "jump_first_invite": "Hopp til den første invitasjonen.", "message_composer": "Meldingsfelt", "n_unread_messages": { - "1 ulest melding.": "one", - "%(count)s uleste meldinger.": "other" + "one": "1 ulest melding.", + "other": "%(count)s uleste meldinger." }, "n_unread_messages_mentions": { - "1 ulest nevnelse.": "one", - "%(count)s uleste meldinger inkludert der du nevnes.": "other" + "one": "1 ulest omtale.", + "other": "%(count)s uleste meldinger, inkludert omtaler." }, "recent_rooms": "Nylige rom", "room_name": "Rom %(name)s", @@ -509,11 +509,12 @@ "modern": "Moderne", "mute": "Demp", "n_members": { - "%(count)s medlem": "one", - "%(count)s medlemmer": "other" + "one": "%(count)s medlem", + "other": "%(count)s medlemmer" }, "n_rooms": { - "%(count)s rom": "one" + "one": "%(count)s rom", + "other": "%(count)s rom" }, "name": "Navn", "no_results": "Ingen treff", @@ -942,7 +943,7 @@ "title": "Ny gjenopprettingsmetode", "warning": "Hvis du ikke har angitt den nye gjenopprettingsmetoden, kan det hende at en hacker prøver å få tilgang til kontoen din. Du må øyeblikkelig endre passordet for kontoen din og angi en ny gjenopprettingsmetode i Innstillinger." }, - "not_supported": "", + "not_supported": "", "pinned_identity_changed": "%(displayName)ss (%(userId)s) identitet ser ut til å ha endret seg. Finn ut mer", "pinned_identity_changed_no_displayname": "%(userId)ss identitet ser ut til å ha endret seg. Finn ut mer", "recovery_method_removed": { @@ -2097,19 +2098,25 @@ "other": "Blir for øyeblikket med i %(count)s rom" }, "notification_options": "Varselsinnstillinger", + "open_space_menu": "Åpne Område-meny", "redacting_messages_status": { "one": "Fjerner for øyeblikket meldinger i %(count)s rom", "other": "Fjerner for øyeblikket meldinger i %(count)s rom" }, "show_less": "Vis mindre", "show_n_more": { - "Vis %(count)s til": "one" + "one": "Vis %(count)s mer", + "other": "Vis %(count)s mer" }, "show_previews": "Vis forhåndsvisninger av meldinger", "sort_by": "Sorter etter", "sort_by_activity": "Aktivitet", "sort_by_alphabet": "A-Å", "sort_unread_first": "Vis rom med uleste meldinger først", + "space_menu": { + "home": "Område hjem", + "space_settings": "Område innstillinger" + }, "space_menu_label": "", "sublist_options": "Liste alternativer", "suggested_rooms_heading": "Foreslåtte rom" @@ -3771,8 +3778,8 @@ "title_progress": "Last opp filer (%(current)s av %(total)s)", "upload_all_button": "Last opp alle", "upload_n_others_button": { - "Last opp %(count)s andre filer": "other", - "Last opp %(count)s annen fil": "one" + "one": "Last opp %(count)s en annen fil", + "other": "Last opp %(count)s andre filer" } }, "user_info": { @@ -3812,8 +3819,8 @@ "promote_warning": "Du vil ikke kunne angre denne endringen ettersom du promoterer brukeren til å ha samme tilgangsnivå som deg selv.", "redact": { "confirm_button": { - "Slett %(count)s meldinger": "other", - "Slett 1 melding": "one" + "one": "Fjern 1 melding", + "other": "Fjern %(count)s meldinger" }, "confirm_description_1": { "one": "Du er i ferd med å fjerne %(count)s melding fra %(user)s. Dette vil fjerne dem permanent for alle i samtalen. Ønsker du å fortsette?", diff --git a/src/i18n/strings/uk.json b/src/i18n/strings/uk.json index 33bd47ea3c..bd7bc660ac 100644 --- a/src/i18n/strings/uk.json +++ b/src/i18n/strings/uk.json @@ -2102,6 +2102,7 @@ "other": "Приєднання до %(count)s кімнат" }, "notification_options": "Параметри сповіщень", + "open_space_menu": "Відкрити меню простору", "redacting_messages_status": { "one": "Триває видалення повідомлень в %(count)s кімнаті", "other": "Триває видалення повідомлень у %(count)s кімнатах" @@ -2116,6 +2117,10 @@ "sort_by_activity": "Активністю", "sort_by_alphabet": "А-Я", "sort_unread_first": "Спочатку показувати кімнати з непрочитаними повідомленнями", + "space_menu": { + "home": "Домівка простору", + "space_settings": "Налаштування простору" + }, "space_menu_label": "%(spaceName)s — меню", "sublist_options": "Параметри переліку", "suggested_rooms_heading": "Пропоновані кімнати" From 0997e0a747f7cb957eaf4dda6277d35763a024d9 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Wed, 26 Feb 2025 12:14:04 +0100 Subject: [PATCH 002/458] refactor: rename `RoomListView` as `RoomListPanel` (#29361) --- .../room-list-header.spec.ts | 0 .../room-list-panel.spec.ts} | 8 ++++---- .../room-list-search.spec.ts | 0 .../room-list-header-compose-menu-linux.png | Bin 0 -> 4815 bytes .../room-list-header-linux.png | Bin 0 -> 1765 bytes .../room-list-header-space-menu-linux.png | Bin .../room-list-space-header-linux.png | Bin .../room-list-panel-linux.png | Bin 0 -> 7985 bytes .../search-section-linux.png | Bin 0 -> 3993 bytes .../room-list-header-compose-menu-linux.png | Bin 4816 -> 0 bytes .../room-list-header-linux.png | Bin 1758 -> 0 bytes .../search-section-linux.png | Bin 3970 -> 0 bytes .../room-list-view-linux.png | Bin 7975 -> 0 bytes res/css/_components.pcss | 6 +++--- .../_RoomListHeaderView.pcss | 0 .../_RoomListPanel.pcss} | 2 +- .../_RoomListSearch.pcss | 0 src/components/structures/LeftPanel.tsx | 4 ++-- .../RoomListHeaderView.tsx | 0 .../RoomListPanel.tsx} | 8 ++++---- .../RoomListSearch.tsx | 0 .../{RoomListView => RoomListPanel}/index.ts | 2 +- .../RoomListHeaderView-test.tsx | 2 +- .../RoomListPanel-test.tsx} | 6 +++--- .../RoomListSearch-test.tsx | 2 +- .../RoomListHeaderView-test.tsx.snap | 0 .../__snapshots__/RoomListPanel-test.tsx.snap} | 12 ++++++------ .../__snapshots__/RoomListSearch-test.tsx.snap | 0 28 files changed, 26 insertions(+), 26 deletions(-) rename playwright/e2e/left-panel/{room-list-view => room-list-panel}/room-list-header.spec.ts (100%) rename playwright/e2e/left-panel/{room-list-view/room-list-view.spec.ts => room-list-panel/room-list-panel.spec.ts} (78%) rename playwright/e2e/left-panel/{room-list-view => room-list-panel}/room-list-search.spec.ts (100%) create mode 100644 playwright/snapshots/left-panel/room-list-panel/room-list-header.spec.ts/room-list-header-compose-menu-linux.png create mode 100644 playwright/snapshots/left-panel/room-list-panel/room-list-header.spec.ts/room-list-header-linux.png rename playwright/snapshots/left-panel/{room-list-view => room-list-panel}/room-list-header.spec.ts/room-list-header-space-menu-linux.png (100%) rename playwright/snapshots/left-panel/{room-list-view => room-list-panel}/room-list-header.spec.ts/room-list-space-header-linux.png (100%) create mode 100644 playwright/snapshots/left-panel/room-list-panel/room-list-panel.spec.ts/room-list-panel-linux.png create mode 100644 playwright/snapshots/left-panel/room-list-panel/room-list-search.spec.ts/search-section-linux.png delete mode 100644 playwright/snapshots/left-panel/room-list-view/room-list-header.spec.ts/room-list-header-compose-menu-linux.png delete mode 100644 playwright/snapshots/left-panel/room-list-view/room-list-header.spec.ts/room-list-header-linux.png delete mode 100644 playwright/snapshots/left-panel/room-list-view/room-list-search.spec.ts/search-section-linux.png delete mode 100644 playwright/snapshots/left-panel/room-list-view/room-list-view.spec.ts/room-list-view-linux.png rename res/css/views/rooms/{RoomListView => RoomListPanel}/_RoomListHeaderView.pcss (100%) rename res/css/views/rooms/{RoomListView/_RoomListView.pcss => RoomListPanel/_RoomListPanel.pcss} (94%) rename res/css/views/rooms/{RoomListView => RoomListPanel}/_RoomListSearch.pcss (100%) rename src/components/views/rooms/{RoomListView => RoomListPanel}/RoomListHeaderView.tsx (100%) rename src/components/views/rooms/{RoomListView/RoomListView.tsx => RoomListPanel/RoomListPanel.tsx} (79%) rename src/components/views/rooms/{RoomListView => RoomListPanel}/RoomListSearch.tsx (100%) rename src/components/views/rooms/{RoomListView => RoomListPanel}/index.ts (80%) rename test/unit-tests/components/views/rooms/{RoomListView => RoomListPanel}/RoomListHeaderView-test.tsx (99%) rename test/unit-tests/components/views/rooms/{RoomListView/RoomListView-test.tsx => RoomListPanel/RoomListPanel-test.tsx} (88%) rename test/unit-tests/components/views/rooms/{RoomListView => RoomListPanel}/RoomListSearch-test.tsx (99%) rename test/unit-tests/components/views/rooms/{RoomListView => RoomListPanel}/__snapshots__/RoomListHeaderView-test.tsx.snap (100%) rename test/unit-tests/components/views/rooms/{RoomListView/__snapshots__/RoomListView-test.tsx.snap => RoomListPanel/__snapshots__/RoomListPanel-test.tsx.snap} (92%) rename test/unit-tests/components/views/rooms/{RoomListView => RoomListPanel}/__snapshots__/RoomListSearch-test.tsx.snap (100%) diff --git a/playwright/e2e/left-panel/room-list-view/room-list-header.spec.ts b/playwright/e2e/left-panel/room-list-panel/room-list-header.spec.ts similarity index 100% rename from playwright/e2e/left-panel/room-list-view/room-list-header.spec.ts rename to playwright/e2e/left-panel/room-list-panel/room-list-header.spec.ts diff --git a/playwright/e2e/left-panel/room-list-view/room-list-view.spec.ts b/playwright/e2e/left-panel/room-list-panel/room-list-panel.spec.ts similarity index 78% rename from playwright/e2e/left-panel/room-list-view/room-list-view.spec.ts rename to playwright/e2e/left-panel/room-list-panel/room-list-panel.spec.ts index 7cd5122e8a..53795773ed 100644 --- a/playwright/e2e/left-panel/room-list-view/room-list-view.spec.ts +++ b/playwright/e2e/left-panel/room-list-panel/room-list-panel.spec.ts @@ -9,7 +9,7 @@ import { type Page } from "@playwright/test"; import { test, expect } from "../../../element-web-test"; -test.describe("Search section of the room list", () => { +test.describe("Room list panel", () => { test.use({ labsFlags: ["feature_new_room_list"], }); @@ -19,7 +19,7 @@ test.describe("Search section of the room list", () => { * @param page */ function getRoomListView(page: Page) { - return page.getByTestId("room-list-view"); + return page.getByTestId("room-list-panel"); } test.beforeEach(async ({ page, app, user }) => { @@ -27,8 +27,8 @@ test.describe("Search section of the room list", () => { await app.closeNotificationToast(); }); - test("should render the room list view", { tag: "@screenshot" }, async ({ page, app, user }) => { + test("should render the room list panel", { tag: "@screenshot" }, async ({ page, app, user }) => { const roomListView = getRoomListView(page); - await expect(roomListView).toMatchScreenshot("room-list-view.png"); + await expect(roomListView).toMatchScreenshot("room-list-panel.png"); }); }); diff --git a/playwright/e2e/left-panel/room-list-view/room-list-search.spec.ts b/playwright/e2e/left-panel/room-list-panel/room-list-search.spec.ts similarity index 100% rename from playwright/e2e/left-panel/room-list-view/room-list-search.spec.ts rename to playwright/e2e/left-panel/room-list-panel/room-list-search.spec.ts diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-header.spec.ts/room-list-header-compose-menu-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-header.spec.ts/room-list-header-compose-menu-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..8382d3b1844c7a990f767a573987ba05b8a20a84 GIT binary patch literal 4815 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 literal 0 HcmV?d00001 diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-header.spec.ts/room-list-header-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-header.spec.ts/room-list-header-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..6c871b6b9c74f31fb628fc45e178e212d3fef21e GIT binary patch literal 1765 zcmb_d`#;l*AO7H|<5n%&v>dcEs*_9ZxfJHJT#k~<+>3K0!dym-##$kl;kceJCSPAP z5<^FrQ9`Q`FCjK}HH*1VuC*QKZ#dsyp6C5MKRnNG?xTP zDW_U`8qZ#Ysd}N_CzH|ZM(nvPS@%XXR8G%C2kzmn>!-^j7o4m<)_K)cP5KrG-c$k) zYK#B_*y_x&vwh)Je8-tB>pQiplx&Ir^{t*kdat%$j`?Ga8%qm2_2jIy7?7yAU9SxQ z%EoUc0pHUw;C_-f06=kKfcw8NPOSfvdBvVK;N}$;Bf?$6PA#$Dz%ZjyUAzu)v%SRg zq2p|s65^!qmU#_vzNC^ZT<+))Zu}A)?A0bJTWE62^+~XuT)2=0C`v5xRv^-#e(1zZ zX*f}2!8K~C#V*4$i~pp6;9Y7zoruN6&<|6rZ8GQjD2;}5xAQ4gZ!>r(CL^QLgMCjD z;WyZ@_~3^Ox{TO;(fk745-feD-NO6w>XilNeX37gx(CuV8ELfBogUqQLcIOw|;bf>Z05p%ioGjJ{K7<;N%uPyeCQfQXk^^-4%zTSQ_cYb{1Xb8a5kUf(y+$2vjzbn9})aR^$ykgU_$u5%?^Z#MTz5P+Y^!n7c27W3}pk z?TrL=-|0fKk(^>A0<_aj_QbPFRc3G~6zaX9?_$-Lv|s15mV4=vE(9_lD0>tk-=qY|*061~k2!(APGTWb zHMQ1#%5#wSQtJug$`Y^hgFCTkM?yyj^)dNo_H*BFJL|%dgRP|+<8_w@ba-?3`$iYIqY*JX|xi# z(PUUnZRj8QjipGji)vZ)E&;nw=6s4pV48oF$VXeQ;d8|WM`_eSq1B_Uq>3M`WQ!#6 zX5sSco7>w1DWxWUdoEphEwj_teaQr^z^H1EbJ;KUl-J)Tqp%LMESFl|qm7dBr)Wf) z{ebPr9hZ4jeWM@$ks9Yll6n`IQi$69S=eA@>Z&wkA&6x;M1rNtWNuznbP3zYo^yJN>h_-ObS9YDfgI({DSI^%+EpCsUG6KuF+ou_2K={pPS=<%_s_;cdEi8F$O=W}1X z_ZQQ)mG#T~{glii@A{xZ`q1q6JiyOlk71m9My^aPv&igR{FKrN)#@bxXl%*=uTWY5 mAk%svK8pkOfBYW|q1d$xp#f5icCmxq0&LOOz&e!ggTDdx7fu5J literal 0 HcmV?d00001 diff --git a/playwright/snapshots/left-panel/room-list-view/room-list-header.spec.ts/room-list-header-space-menu-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-header.spec.ts/room-list-header-space-menu-linux.png similarity index 100% rename from playwright/snapshots/left-panel/room-list-view/room-list-header.spec.ts/room-list-header-space-menu-linux.png rename to playwright/snapshots/left-panel/room-list-panel/room-list-header.spec.ts/room-list-header-space-menu-linux.png diff --git a/playwright/snapshots/left-panel/room-list-view/room-list-header.spec.ts/room-list-space-header-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-header.spec.ts/room-list-space-header-linux.png similarity index 100% rename from playwright/snapshots/left-panel/room-list-view/room-list-header.spec.ts/room-list-space-header-linux.png rename to playwright/snapshots/left-panel/room-list-panel/room-list-header.spec.ts/room-list-space-header-linux.png diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-panel.spec.ts/room-list-panel-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-panel.spec.ts/room-list-panel-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..d03dbf992b02661f4589e7e124671d058574e4d1 GIT binary patch literal 7985 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 Q2F`c)mdVZH8&6*U7pzRP8UO$Q literal 0 HcmV?d00001 diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-search.spec.ts/search-section-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-search.spec.ts/search-section-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..123cf3758623f9e70cbbb90dd4e66959b4ffa002 GIT binary patch literal 3993 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 Zx0?H@H+7pFQm$DWpsA`0sRY}+{|_K)xvBsF literal 0 HcmV?d00001 diff --git a/playwright/snapshots/left-panel/room-list-view/room-list-header.spec.ts/room-list-header-compose-menu-linux.png b/playwright/snapshots/left-panel/room-list-view/room-list-header.spec.ts/room-list-header-compose-menu-linux.png deleted file mode 100644 index 8f53c47d53c0252f104e995e574fd3314a50d948..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4816 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 diff --git a/playwright/snapshots/left-panel/room-list-view/room-list-header.spec.ts/room-list-header-linux.png b/playwright/snapshots/left-panel/room-list-view/room-list-header.spec.ts/room-list-header-linux.png deleted file mode 100644 index 82636daa73d7d0c9482979a8a708aeeb424e843b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1758 zcmbuAX*k=77RLWfQwA+5AyerTMJaJhYoush@)uia?X`?VXIf3wT1%z2TBBMKBP6z4 z%TQ7}4Q&n8C{xB(Aw`i!E+J!yYJ*tQoB4jf&6jh|bI$X;Uw-fNo}9~W4u=$uDgXd* z$jK4(005aErL(oXth73tOX$)jbKAqg4rqFZSOkEBR435Z>rR=F6LC>B1R=MEg}qvZ zc*_Z6TDI!iG+L2G_HS%t7#g@AywvU8-8B&3<=?_Q$U0XJe`st>Go{_exKMql?+^W9 zQ=N~GV#K|BZbB|NM^`#ru4az7Nnnk37~qm(FnLF=CEI9M#t(n|bhsc{WG%LC92AJ4 zz`s+W!#f87-tXyw0H7W%16=tN0^qbYfYi)?u+aWnQ|m@sTl=N)_vfCPpB$u_qQzN! zOS8mJMxCPJ&vop?)x=$))u80t5?|lCx*cqM{9UDe|dIL7Q`-;Xjqw`8tHPK)#TTteT95oRa&dI;=$S?5WICIv!j=T7} z{a1FH^P&n;zl#9d_U3vxH-2x?lu7-%&=#9byfB@=`@!ewOM&Ct`r3u@Vm@bS-HT$z z5s3Dqx#8Qws<Xayx(svT;cEEMO?Ouav-HGzr&gpQNh?=h3QIxR?IM%3o1U3d+a$md&BLT&}%Z5!KHtcIxIi zkHS(FTQF}HnHk&EiH2kwT^9roKlYb9?+qW9`Bn3%U{KfJWk4t~ zY8`BkgCjsSGPSwAfg4V@32a3bJRV?#W@eFOK= z^VUeaw)P1*KkF^2m;FLii3Y~{esxPT^ijQKod=2SJk(wLD_onA`pc(a9o-6UZ=xhK z&X9?hF7-Sjc*I^u=ibv$6(VtKPV>x@Bt4KU$RXYlc;CxcT(fJ%F+m9|$E-oJC}6Qv zNWJtNL@~K&Ryk8ji*|9G$;UrBNL9QP$mE@Dvy@6@+ClHYE&ThS(3~`_`|FqQ)s6Ym z4oDixQ);|bKnrNmrA|ej*yiXCcHn0-Qm@r2g$Too&}j6&Rq3{7dj0V|iEN$H9Fcgy zRvxjId(4DPBzmrID%SW`ysG`O8)ka{5eL~B`F=dv3O8U8^s7JRb)*;8Kq+WVUdd!R@Q4+GdH*i-+g$$aT*K}DJm7bx|BTsuk4Ep{I zAv|!fhs0p`)J0WeAkUK5b`_&z_tIKV-*!Ej67y39!+w5uX zUACbLW{`%40`-N_Th@A=r}I%E3m;6s`RhnF>DVu*kXrsgB@+OQ*Z*N!|KG&lSIoS6 VJ*l3Yf|5Qgz{%bXY_h|p{SPy}O@aUb diff --git a/playwright/snapshots/left-panel/room-list-view/room-list-search.spec.ts/search-section-linux.png b/playwright/snapshots/left-panel/room-list-view/room-list-search.spec.ts/search-section-linux.png deleted file mode 100644 index 6c2684e84964c41f2614af19fe003ca9c2518f73..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3970 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 { return (
- +
); diff --git a/src/components/views/rooms/RoomListView/RoomListHeaderView.tsx b/src/components/views/rooms/RoomListPanel/RoomListHeaderView.tsx similarity index 100% rename from src/components/views/rooms/RoomListView/RoomListHeaderView.tsx rename to src/components/views/rooms/RoomListPanel/RoomListHeaderView.tsx diff --git a/src/components/views/rooms/RoomListView/RoomListView.tsx b/src/components/views/rooms/RoomListPanel/RoomListPanel.tsx similarity index 79% rename from src/components/views/rooms/RoomListView/RoomListView.tsx rename to src/components/views/rooms/RoomListPanel/RoomListPanel.tsx index 2aa11269ff..e5c1cbfa30 100644 --- a/src/components/views/rooms/RoomListView/RoomListView.tsx +++ b/src/components/views/rooms/RoomListPanel/RoomListPanel.tsx @@ -12,7 +12,7 @@ import { UIComponent } from "../../../../settings/UIFeature"; import { RoomListSearch } from "./RoomListSearch"; import { RoomListHeaderView } from "./RoomListHeaderView"; -type RoomListViewProps = { +type RoomListPanelProps = { /** * Current active space * See {@link RoomListSearch} @@ -21,13 +21,13 @@ type RoomListViewProps = { }; /** - * A view component for the room list. + * The panel of the room list */ -export const RoomListView: React.FC = ({ activeSpace }) => { +export const RoomListPanel: React.FC = ({ activeSpace }) => { const displayRoomSearch = shouldShowComponent(UIComponent.FilterContainer); return ( -
+
{displayRoomSearch && }
diff --git a/src/components/views/rooms/RoomListView/RoomListSearch.tsx b/src/components/views/rooms/RoomListPanel/RoomListSearch.tsx similarity index 100% rename from src/components/views/rooms/RoomListView/RoomListSearch.tsx rename to src/components/views/rooms/RoomListPanel/RoomListSearch.tsx diff --git a/src/components/views/rooms/RoomListView/index.ts b/src/components/views/rooms/RoomListPanel/index.ts similarity index 80% rename from src/components/views/rooms/RoomListView/index.ts rename to src/components/views/rooms/RoomListPanel/index.ts index 4fa7c095df..4356a51e26 100644 --- a/src/components/views/rooms/RoomListView/index.ts +++ b/src/components/views/rooms/RoomListPanel/index.ts @@ -5,4 +5,4 @@ * Please see LICENSE files in the repository root for full details. */ -export { RoomListView } from "./RoomListView"; +export { RoomListPanel } from "./RoomListPanel"; diff --git a/test/unit-tests/components/views/rooms/RoomListView/RoomListHeaderView-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListHeaderView-test.tsx similarity index 99% rename from test/unit-tests/components/views/rooms/RoomListView/RoomListHeaderView-test.tsx rename to test/unit-tests/components/views/rooms/RoomListPanel/RoomListHeaderView-test.tsx index 97195556c3..3a7e189d91 100644 --- a/test/unit-tests/components/views/rooms/RoomListView/RoomListHeaderView-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListHeaderView-test.tsx @@ -14,7 +14,7 @@ import { type RoomListHeaderViewState, useRoomListHeaderViewModel, } from "../../../../../../src/components/viewmodels/roomlist/RoomListHeaderViewModel"; -import { RoomListHeaderView } from "../../../../../../src/components/views/rooms/RoomListView/RoomListHeaderView"; +import { RoomListHeaderView } from "../../../../../../src/components/views/rooms/RoomListPanel/RoomListHeaderView"; jest.mock("../../../../../../src/components/viewmodels/roomlist/RoomListHeaderViewModel", () => ({ useRoomListHeaderViewModel: jest.fn(), diff --git a/test/unit-tests/components/views/rooms/RoomListView/RoomListView-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPanel-test.tsx similarity index 88% rename from test/unit-tests/components/views/rooms/RoomListView/RoomListView-test.tsx rename to test/unit-tests/components/views/rooms/RoomListPanel/RoomListPanel-test.tsx index fecdabbae9..525a17e1ac 100644 --- a/test/unit-tests/components/views/rooms/RoomListView/RoomListView-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPanel-test.tsx @@ -9,7 +9,7 @@ import React from "react"; import { render, screen } from "jest-matrix-react"; import { mocked } from "jest-mock"; -import { RoomListView } from "../../../../../../src/components/views/rooms/RoomListView"; +import { RoomListPanel } from "../../../../../../src/components/views/rooms/RoomListPanel"; import { shouldShowComponent } from "../../../../../../src/customisations/helpers/UIComponents"; import { MetaSpace } from "../../../../../../src/stores/spaces"; @@ -17,9 +17,9 @@ jest.mock("../../../../../../src/customisations/helpers/UIComponents", () => ({ shouldShowComponent: jest.fn(), })); -describe("", () => { +describe("", () => { function renderComponent() { - return render(); + return render(); } beforeEach(() => { diff --git a/test/unit-tests/components/views/rooms/RoomListView/RoomListSearch-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListSearch-test.tsx similarity index 99% rename from test/unit-tests/components/views/rooms/RoomListView/RoomListSearch-test.tsx rename to test/unit-tests/components/views/rooms/RoomListPanel/RoomListSearch-test.tsx index ead58cc039..47ecc69cc3 100644 --- a/test/unit-tests/components/views/rooms/RoomListView/RoomListSearch-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListSearch-test.tsx @@ -10,7 +10,7 @@ import { render, screen } from "jest-matrix-react"; import { mocked } from "jest-mock"; import userEvent from "@testing-library/user-event"; -import { RoomListSearch } from "../../../../../../src/components/views/rooms/RoomListView/RoomListSearch"; +import { RoomListSearch } from "../../../../../../src/components/views/rooms/RoomListPanel/RoomListSearch"; import { MetaSpace } from "../../../../../../src/stores/spaces"; import { shouldShowComponent } from "../../../../../../src/customisations/helpers/UIComponents"; import defaultDispatcher from "../../../../../../src/dispatcher/dispatcher"; diff --git a/test/unit-tests/components/views/rooms/RoomListView/__snapshots__/RoomListHeaderView-test.tsx.snap b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListHeaderView-test.tsx.snap similarity index 100% rename from test/unit-tests/components/views/rooms/RoomListView/__snapshots__/RoomListHeaderView-test.tsx.snap rename to test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListHeaderView-test.tsx.snap diff --git a/test/unit-tests/components/views/rooms/RoomListView/__snapshots__/RoomListView-test.tsx.snap b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListPanel-test.tsx.snap similarity index 92% rename from test/unit-tests/components/views/rooms/RoomListView/__snapshots__/RoomListView-test.tsx.snap rename to test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListPanel-test.tsx.snap index 90e1454f50..d261fb9582 100644 --- a/test/unit-tests/components/views/rooms/RoomListView/__snapshots__/RoomListView-test.tsx.snap +++ b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListPanel-test.tsx.snap @@ -1,10 +1,10 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` should not render the RoomListSearch component when UIComponent.FilterContainer is at false 1`] = ` +exports[` should not render the RoomListSearch component when UIComponent.FilterContainer is at false 1`] = `
should not render the RoomListSearch component when UI `; -exports[` should render the RoomListSearch component when UIComponent.FilterContainer is at true 1`] = ` +exports[` should render the RoomListSearch component when UIComponent.FilterContainer is at true 1`] = `
Date: Thu, 27 Feb 2025 14:13:23 +0200 Subject: [PATCH 003/458] fix: /tmp/element-web-config may already exist preventing the container from booting up (#29372) * fix: /tmp/element-web-config may already exist preventing the container from booting up * Update docker/docker-entrypoint.d/18-load-element-modules.sh Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --------- Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --- docker/docker-entrypoint.d/18-load-element-modules.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/docker-entrypoint.d/18-load-element-modules.sh b/docker/docker-entrypoint.d/18-load-element-modules.sh index 15c0cb6086..14a3b53531 100755 --- a/docker/docker-entrypoint.d/18-load-element-modules.sh +++ b/docker/docker-entrypoint.d/18-load-element-modules.sh @@ -11,7 +11,7 @@ entrypoint_log() { } # Copy these config files as a base -mkdir /tmp/element-web-config +mkdir -p /tmp/element-web-config cp /app/config*.json /tmp/element-web-config/ # If there are modules to be loaded From 808412c6be7a950c565c2f0ce64f47d3dc7ea7a1 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Thu, 27 Feb 2025 12:41:59 +0000 Subject: [PATCH 004/458] fix: /tmp/element-web-config may already exist preventing the container from booting up (#29372) (#29377) * fix: /tmp/element-web-config may already exist preventing the container from booting up * Update docker/docker-entrypoint.d/18-load-element-modules.sh Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --------- Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> (cherry picked from commit 45497905bed955c68e191a9ed45ddaf2a0bbae36) Co-authored-by: Itay Grudev --- docker/docker-entrypoint.d/18-load-element-modules.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/docker-entrypoint.d/18-load-element-modules.sh b/docker/docker-entrypoint.d/18-load-element-modules.sh index 15c0cb6086..14a3b53531 100755 --- a/docker/docker-entrypoint.d/18-load-element-modules.sh +++ b/docker/docker-entrypoint.d/18-load-element-modules.sh @@ -11,7 +11,7 @@ entrypoint_log() { } # Copy these config files as a base -mkdir /tmp/element-web-config +mkdir -p /tmp/element-web-config cp /app/config*.json /tmp/element-web-config/ # If there are modules to be loaded From 7a513a2dc24efb223855adaa8bcdd567aa6684bc Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Thu, 27 Feb 2025 13:16:17 +0000 Subject: [PATCH 005/458] v1.11.94 --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 324c7f7ad8..792fdd876c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +Changes in [1.11.94](https://github.com/element-hq/element-web/releases/tag/v1.11.94) (2025-02-27) +================================================================================================== +## 🐛 Bug Fixes + +* [Backport staging] fix: /tmp/element-web-config may already exist preventing the container from booting up ([#29377](https://github.com/element-hq/element-web/pull/29377)). Contributed by @RiotRobot. + + Changes in [1.11.93](https://github.com/element-hq/element-web/releases/tag/v1.11.93) (2025-02-25) ================================================================================================== ## ✨ Features diff --git a/package.json b/package.json index c47ea4f5d0..63904b4228 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "element-web", - "version": "1.11.93", + "version": "1.11.94", "description": "Element: the future of secure communication", "author": "New Vector Ltd.", "repository": { From e749b017c925c0f77ca532487f1f8c21bfbc1ba9 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Thu, 27 Feb 2025 14:34:54 +0100 Subject: [PATCH 006/458] refactor: rename `mx_RoomList` as `mx_LegacyRoomList` (#29362) --- playwright/e2e/crypto/crypto.spec.ts | 2 +- playwright/e2e/invite/invite-dialog.spec.ts | 2 +- res/css/_components.pcss | 2 +- .../{_RoomList.pcss => _LegacyRoomList.pcss} | 18 ++++++++--------- src/components/structures/SpaceRoomView.tsx | 8 ++++---- src/components/views/rooms/LegacyRoomList.tsx | 20 +++++++++---------- 6 files changed, 26 insertions(+), 26 deletions(-) rename res/css/views/rooms/{_RoomList.pcss => _LegacyRoomList.pcss} (71%) diff --git a/playwright/e2e/crypto/crypto.spec.ts b/playwright/e2e/crypto/crypto.spec.ts index ace1b74c74..2d294ff7c2 100644 --- a/playwright/e2e/crypto/crypto.spec.ts +++ b/playwright/e2e/crypto/crypto.spec.ts @@ -28,7 +28,7 @@ const checkDMRoom = async (page: Page) => { }; const startDMWithBob = async (page: Page, bob: Bot) => { - await page.locator(".mx_RoomList").getByRole("button", { name: "Start chat" }).click(); + await page.locator(".mx_LegacyRoomList").getByRole("button", { name: "Start chat" }).click(); await page.getByTestId("invite-dialog-input").fill(bob.credentials.userId); await page.locator(".mx_InviteDialog_tile_nameStack_name").getByText("Bob").click(); await expect( diff --git a/playwright/e2e/invite/invite-dialog.spec.ts b/playwright/e2e/invite/invite-dialog.spec.ts index 73238f8c3d..8d64e6e047 100644 --- a/playwright/e2e/invite/invite-dialog.spec.ts +++ b/playwright/e2e/invite/invite-dialog.spec.ts @@ -77,7 +77,7 @@ test.describe("Invite dialog", function () { "should support inviting a user to Direct Messages", { tag: "@screenshot" }, async ({ page, app, user, bot }) => { - await page.locator(".mx_RoomList").getByRole("button", { name: "Start chat" }).click(); + await page.locator(".mx_LegacyRoomList").getByRole("button", { name: "Start chat" }).click(); const other = page.locator(".mx_InviteDialog_other"); // Assert that the header is rendered diff --git a/res/css/_components.pcss b/res/css/_components.pcss index c14bb40db7..9012960195 100644 --- a/res/css/_components.pcss +++ b/res/css/_components.pcss @@ -289,6 +289,7 @@ @import "./views/rooms/_IRCLayout.pcss"; @import "./views/rooms/_InvitedIconView.pcss"; @import "./views/rooms/_JumpToBottomButton.pcss"; +@import "./views/rooms/_LegacyRoomList.pcss"; @import "./views/rooms/_LegacyRoomListHeader.pcss"; @import "./views/rooms/_LinkPreviewGroup.pcss"; @import "./views/rooms/_LinkPreviewWidget.pcss"; @@ -313,7 +314,6 @@ @import "./views/rooms/_RoomHeader.pcss"; @import "./views/rooms/_RoomInfoLine.pcss"; @import "./views/rooms/_RoomKnocksBar.pcss"; -@import "./views/rooms/_RoomList.pcss"; @import "./views/rooms/_RoomPreviewBar.pcss"; @import "./views/rooms/_RoomPreviewCard.pcss"; @import "./views/rooms/_RoomSearchAuxPanel.pcss"; diff --git a/res/css/views/rooms/_RoomList.pcss b/res/css/views/rooms/_LegacyRoomList.pcss similarity index 71% rename from res/css/views/rooms/_RoomList.pcss rename to res/css/views/rooms/_LegacyRoomList.pcss index 74e2e86ed1..acf162b7a2 100644 --- a/res/css/views/rooms/_RoomList.pcss +++ b/res/css/views/rooms/_LegacyRoomList.pcss @@ -6,31 +6,31 @@ 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. */ -.mx_RoomList { +.mx_LegacyRoomList { padding-right: 7px; /* width of the scrollbar, to line things up */ } -.mx_RoomList_iconPlus::before { +.mx_LegacyRoomList_iconPlus::before { mask-image: url("$(res)/img/element-icons/roomlist/plus-circle.svg"); } -.mx_RoomList_iconNewRoom::before { +.mx_LegacyRoomList_iconNewRoom::before { mask-image: url("$(res)/img/element-icons/roomlist/hash-plus.svg"); } -.mx_RoomList_iconNewVideoRoom::before { +.mx_LegacyRoomList_iconNewVideoRoom::before { mask-image: url("$(res)/img/element-icons/roomlist/hash-video.svg"); } -.mx_RoomList_iconAddExistingRoom::before { +.mx_LegacyRoomList_iconAddExistingRoom::before { mask-image: url("$(res)/img/element-icons/roomlist/hash.svg"); } -.mx_RoomList_iconExplore::before { +.mx_LegacyRoomList_iconExplore::before { mask-image: url("$(res)/img/element-icons/roomlist/hash-search.svg"); } -.mx_RoomList_iconDialpad::before { +.mx_LegacyRoomList_iconDialpad::before { mask-image: url("$(res)/img/element-icons/roomlist/dialpad.svg"); } -.mx_RoomList_iconStartChat::before { +.mx_LegacyRoomList_iconStartChat::before { mask-image: url("@vector-im/compound-design-tokens/icons/user-add-solid.svg"); } -.mx_RoomList_iconInvite::before { +.mx_LegacyRoomList_iconInvite::before { mask-image: url("$(res)/img/element-icons/room/share.svg"); } diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index 170cb4615d..bb4fe19520 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -117,7 +117,7 @@ const SpaceLandingAddButton: React.FC<{ space: Room }> = ({ space }) => { <> => { e.preventDefault(); e.stopPropagation(); @@ -132,7 +132,7 @@ const SpaceLandingAddButton: React.FC<{ space: Room }> = ({ space }) => { {videoRoomsEnabled && ( => { e.preventDefault(); e.stopPropagation(); @@ -157,7 +157,7 @@ const SpaceLandingAddButton: React.FC<{ space: Room }> = ({ space }) => { )} { e.preventDefault(); e.stopPropagation(); @@ -168,7 +168,7 @@ const SpaceLandingAddButton: React.FC<{ space: Room }> = ({ space }) => { {canCreateSpace && ( { e.preventDefault(); e.stopPropagation(); diff --git a/src/components/views/rooms/LegacyRoomList.tsx b/src/components/views/rooms/LegacyRoomList.tsx index 2894255c04..a940484b16 100644 --- a/src/components/views/rooms/LegacyRoomList.tsx +++ b/src/components/views/rooms/LegacyRoomList.tsx @@ -142,7 +142,7 @@ const DmAuxButton: React.FC = ({ tabIndex, dispatcher = default {showCreateRooms && ( { e.preventDefault(); e.stopPropagation(); @@ -158,7 +158,7 @@ const DmAuxButton: React.FC = ({ tabIndex, dispatcher = default {showInviteUsers && ( { e.preventDefault(); e.stopPropagation(); @@ -230,7 +230,7 @@ const UntaggedAuxButton: React.FC = ({ tabIndex }) => { { e.preventDefault(); e.stopPropagation(); @@ -247,7 +247,7 @@ const UntaggedAuxButton: React.FC = ({ tabIndex }) => { <> { e.preventDefault(); e.stopPropagation(); @@ -261,7 +261,7 @@ const UntaggedAuxButton: React.FC = ({ tabIndex }) => { {videoRoomsEnabled && ( { e.preventDefault(); e.stopPropagation(); @@ -279,7 +279,7 @@ const UntaggedAuxButton: React.FC = ({ tabIndex }) => { )} { e.preventDefault(); e.stopPropagation(); @@ -300,7 +300,7 @@ const UntaggedAuxButton: React.FC = ({ tabIndex }) => { <> { e.preventDefault(); e.stopPropagation(); @@ -312,7 +312,7 @@ const UntaggedAuxButton: React.FC = ({ tabIndex }) => { {videoRoomsEnabled && ( { e.preventDefault(); e.stopPropagation(); @@ -333,7 +333,7 @@ const UntaggedAuxButton: React.FC = ({ tabIndex }) => { {showExploreRooms ? ( { e.preventDefault(); e.stopPropagation(); @@ -678,7 +678,7 @@ export default class LegacyRoomList extends React.PureComponent } onKeyDownHandler(ev); }} - className="mx_RoomList" + className="mx_LegacyRoomList" role="tree" aria-label={_t("common|rooms")} ref={this.treeRef} From c6b3bf962a16a9695046b293b34ccae8f57953df Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 27 Feb 2025 14:20:01 +0000 Subject: [PATCH 007/458] Enable babel plugins to enable js-sdk to use decorators (#29376) * Enable @babel/plugin-proposal-decorators Only needed because we consume js-sdk code directly so its own transpiling isn't in play This should separately be fixed, we should not need to have a superset of js-sdk's babel plugins Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- babel.config.js | 2 ++ package.json | 2 ++ yarn.lock | 20 ++++++++++++++++++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/babel.config.js b/babel.config.js index b63a90e5ff..58df067b79 100644 --- a/babel.config.js +++ b/babel.config.js @@ -31,5 +31,7 @@ module.exports = { "@babel/plugin-syntax-dynamic-import", "@babel/plugin-transform-runtime", + ["@babel/plugin-proposal-decorators", { version: "2023-11" }], // only needed by the js-sdk + "@babel/plugin-transform-class-static-block", // only needed by the js-sdk for decorators ], }; diff --git a/package.json b/package.json index 8be3299d4b..a0fb4a8216 100644 --- a/package.json +++ b/package.json @@ -162,9 +162,11 @@ "@babel/core": "^7.12.10", "@babel/eslint-parser": "^7.12.10", "@babel/eslint-plugin": "^7.12.10", + "@babel/plugin-proposal-decorators": "^7.25.9", "@babel/plugin-proposal-export-default-from": "^7.12.1", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-transform-class-properties": "^7.12.1", + "@babel/plugin-transform-class-static-block": "^7.26.0", "@babel/plugin-transform-logical-assignment-operators": "^7.20.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.12.1", "@babel/plugin-transform-numeric-separator": "^7.12.7", diff --git a/yarn.lock b/yarn.lock index f226827c41..22ce4d7bf5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -343,6 +343,15 @@ "@babel/helper-plugin-utils" "^7.25.9" "@babel/traverse" "^7.25.9" +"@babel/plugin-proposal-decorators@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.25.9.tgz#8680707f943d1a3da2cd66b948179920f097e254" + integrity sha512-smkNLL/O1ezy9Nhy4CNosc4Va+1wo5w4gzSZeLe6y6dM4mmHfYOCPolXQPHQxonZCF+ZyebxN9vqOolkYrSn5g== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/plugin-syntax-decorators" "^7.25.9" + "@babel/plugin-proposal-export-default-from@^7.12.1": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.25.9.tgz#52702be6ef8367fc8f18b8438278332beeb8f87c" @@ -383,6 +392,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-syntax-decorators@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.25.9.tgz#986b4ca8b7b5df3f67cee889cedeffc2e2bf14b3" + integrity sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/plugin-syntax-dynamic-import@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" @@ -3529,7 +3545,7 @@ classnames "^2.5.1" vaul "^1.0.0" -"@vector-im/matrix-wysiwyg-wasm@link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.0-af862ffd231dc0a6b8d6f2cb3601e68456c0ff24-integrity/node_modules/bindings/wysiwyg-wasm": +"@vector-im/matrix-wysiwyg-wasm@link:../../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.0-af862ffd231dc0a6b8d6f2cb3601e68456c0ff24-integrity/node_modules/bindings/wysiwyg-wasm": version "0.0.0" uid "" @@ -3538,7 +3554,7 @@ resolved "https://registry.yarnpkg.com/@vector-im/matrix-wysiwyg/-/matrix-wysiwyg-2.38.0.tgz#af862ffd231dc0a6b8d6f2cb3601e68456c0ff24" integrity sha512-cMEVicFYVzFxuSyWON0aVGjAJMcgJZ+LxuLTEp8EGuu8cRacuh0RN5rapb11YVZygzFvE7X1cMedJ/fKd5vRLA== dependencies: - "@vector-im/matrix-wysiwyg-wasm" "link:../../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.0-af862ffd231dc0a6b8d6f2cb3601e68456c0ff24-integrity/node_modules/bindings/wysiwyg-wasm" + "@vector-im/matrix-wysiwyg-wasm" "link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.0-af862ffd231dc0a6b8d6f2cb3601e68456c0ff24-integrity/node_modules/bindings/wysiwyg-wasm" "@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1": version "1.14.1" From 1ad1387e05f20719eb455662db6eabb9ff4d9529 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Fri, 28 Feb 2025 06:21:55 +0000 Subject: [PATCH 008/458] [create-pull-request] automated change (#29389) Co-authored-by: t3chguy <2403652+t3chguy@users.noreply.github.com> --- src/i18n/strings/cs.json | 12 +++++- src/i18n/strings/cy.json | 86 ++++++++++++++++++++++------------------ 2 files changed, 59 insertions(+), 39 deletions(-) diff --git a/src/i18n/strings/cs.json b/src/i18n/strings/cs.json index 157b7e5762..b4df045a29 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -80,12 +80,14 @@ "maximise": "Maximalizovat", "mention": "Zmínit", "minimise": "Minimalizovat", + "new_message": "Nová zpráva", "new_room": "Nová místnost", "new_video_room": "Nová video místnost", "next": "Další", "no": "Ne", "ok": "OK", "open": "Otevřít", + "open_menu": "Otevřít nabídku", "pause": "Pozastavit", "pin": "Připnout", "play": "Přehrát", @@ -1244,6 +1246,7 @@ "change": "Změnit server identit", "change_prompt": "Odpojit se ze serveru a připojit na ?", "change_server_prompt": "Pokud nechcete na hledání existujících kontaktů používat server , zvolte si jiný server.", + "changed": "Váš server identit byl změněn", "checking": "Kontrolování serveru", "description_connected": "Pro hledání existujících kontaktů používáte server identit . Níže ho můžete změnit.", "description_disconnected": "Pro hledání existujících kontaktů nepoužíváte žádný server identit . Abyste mohli hledat kontakty, nějaký níže nastavte.", @@ -1286,7 +1289,9 @@ "title": "Nepodporovaný prohlížeč", "use_desktop_heading": "Místo toho použijte %(brand)s Desktop", "use_mobile_heading": "Místo toho použijte %(brand)s na mobilu", - "use_mobile_heading_after_desktop": "Nebo použijte naši mobilní aplikaci" + "use_mobile_heading_after_desktop": "Nebo použijte naši mobilní aplikaci", + "windows_64bit": "Windows (64-bit)", + "windows_arm_64bit": "Windows (ARM 64-bit)" }, "info_tooltip_title": "Informace", "integration_manager": { @@ -2098,6 +2103,7 @@ "other": "Momentálně se připojuje %(count)s místností" }, "notification_options": "Možnosti oznámení", + "open_space_menu": "Otevřít nabídku prostoru", "redacting_messages_status": { "one": "Momentálně se odstraňují zprávy v %(count)s místnosti", "other": "Momentálně se odstraňují zprávy v %(count)s místnostech" @@ -2112,6 +2118,10 @@ "sort_by_activity": "Aktivity", "sort_by_alphabet": "A–Z", "sort_unread_first": "Zobrazovat místnosti s nepřečtenými zprávami jako první", + "space_menu": { + "home": "Domov prostoru", + "space_settings": "Nastavení prostoru" + }, "space_menu_label": "Nabídka pro %(spaceName)s", "sublist_options": "Možnosti seznamu", "suggested_rooms_heading": "Doporučené místnosti" diff --git a/src/i18n/strings/cy.json b/src/i18n/strings/cy.json index 475a73bce3..dbe5b8bb62 100644 --- a/src/i18n/strings/cy.json +++ b/src/i18n/strings/cy.json @@ -72,12 +72,14 @@ "maximise": "Mwyhau", "mention": "Crybwyll", "minimise": "Lleihau", + "new_message": "Neges newydd", "new_room": "Ystafell newydd", "new_video_room": "Ystafell fideo newydd", "next": "Nesaf", "no": "Na", "ok": "Iawn", "open": "Agor", + "open_menu": "Agor dewislen", "pause": "Oedi", "pin": "Pinio", "play": "Chwarae", @@ -322,11 +324,11 @@ "server_picker_title_default": "Opsiynau Gweinydd", "server_picker_title_registration": "Cyfrif gwesteiwr ymlaen", "session_logged_out_description": "Er diogelwch, mae'r sesiwn hon wedi'i hallgofnodi. Mewngofnodwch eto.", - "session_logged_out_title": "Wedi Arwyddo Allan", + "session_logged_out_title": "Wedi Allgofnodi", "set_email": { - "description": "Bydd hyn yn caniatáu ichi ailosod eich cyfrinair a derbyn hysbysiadau.", + "description": "Bydd hyn yn caniatáu i chi ailosod eich cyfrinair a derbyn hysbysiadau.", "verification_pending_description": "Gwiriwch eich e-bost a chliciwch ar y ddolen sydd ynddo. Unwaith y gwneir hyn, cliciwch parhau.", - "verification_pending_title": "Dilysu yn yr Arfaeth" + "verification_pending_title": "Yn Aros i Wirio" }, "set_email_prompt": "Ydych chi am osod cyfeiriad e-bost?", "sign_in_description": "Defnyddiwch eich cyfrif i barhau.", @@ -335,7 +337,7 @@ "sign_in_or_register": "Mewngofnodi neu Creu Cyfrif", "sign_in_or_register_description": "Defnyddiwch eich cyfrif neu crëwch un newydd i barhau.", "sign_in_prompt": "Oes gennych chi gyfrif? Mewngofnodwch", - "sign_in_with_sso": "Mewngofnodwch gyda mewngofnodi sengl", + "sign_in_with_sso": "Mewngofnodwch gyda mewngofnod sengl", "signing_in": "Wrthi'n mewngofnodi…", "soft_logout": { "clear_data_button": "Clirio'r holl ddata", @@ -348,9 +350,9 @@ "soft_logout_intro_unsupported_auth": "Ni allwch fewngofnodi i'ch cyfrif. Cysylltwch â gweinyddwr eich gweinydd cartref am ragor o wybodaeth.", "soft_logout_subheading": "Clirio data personol", "soft_logout_warning": "Rhybudd: mae eich data personol (gan gynnwys allweddi amgryptio) yn dal i gael ei storio yn y sesiwn hon. Cliriwch ef os ydych wedi gorffen defnyddio'r sesiwn hon, neu eisiau mewngofnodi i gyfrif arall.", - "sso": "Arwyddo Sengl", + "sso": "Mewngofnod Sengl", "sso_complete_in_browser_dialog_title": "Ewch i'ch porwr i gwblhau Mewngofnodi", - "sso_failed_missing_storage": "Gofynnom i'r porwr gofio pa weinydd cartref rydych chi'n ei ddefnyddio i'ch galluogi i fewngofnodi, ond yn anffodus mae eich porwr wedi anghofio hynny. Ewch i'r dudalen mewngofnodi a cheisiwch eto.", + "sso_failed_missing_storage": "Rydym wedi gofyn i'r porwr gofio pa weinydd cartref rydych chi'n ei ddefnyddio i'ch galluogi i fewngofnodi, ond yn anffodus mae eich porwr wedi anghofio hynny. Ewch i'r dudalen mewngofnodi a cheisiwch eto.", "sso_or_username_password": "%(ssoButtons)s Neu %(usernamePassword)s", "sync_footer_subtitle": "Os ydych chi wedi ymuno â llawer o ystafelloedd, gallai hyn gymryd peth amser", "syncing": "Cydweddu…", @@ -367,17 +369,17 @@ "msisdn_token_incorrect": "Tocyn yn anghywir", "msisdn_token_prompt": "Rhowch y cod sydd ynddo:", "password_prompt": "Cadarnhewch eich hunaniaeth trwy nodi cyfrinair eich cyfrif isod.", - "recaptcha_missing_params": "Allwedd gyhoeddus captcha ar goll yng nghyfluniad y gweinydd cartref. Rhowch wybod i'ch gweinyddwr gweinyddwr am hyn.", + "recaptcha_missing_params": "Mae allwedd gyhoeddus captcha ar goll yn ffurfweddiad y gweinydd cartref. Rhowch wybod i'ch gweinyddwr gweinyddwr am hyn.", "registration_token_label": "Tocyn cofrestru", "registration_token_prompt": "Rhowch docyn cofrestru a ddarparwyd gan weinyddwr y gweinydd cartref.", "sso_body": "Cadarnhewch ychwanegu'r cyfeiriad e-bost hwn trwy ddefnyddio Single Sign On i brofi pwy ydych.", - "sso_failed": "Aeth rhywbeth o'i le wrth gadarnhau pwy ydych chi. Canslo a cheisio eto.", + "sso_failed": "Aeth rhywbeth o'i le wrth gadarnhau pwy ydych chi. Diddymu a cheisio eto.", "sso_postauth_body": "Cliciwch ar y botwm isod i gadarnhau pwy ydych chi.", "sso_postauth_title": "Cadarnhau i barhau", - "sso_preauth_body": "I barhau, defnyddiwch Arwyddo Sengl i brofi pwy ydych.", - "sso_title": "Defnyddiwch Arwyddo Sengl i barhau", - "terms": "Adolygwch a derbyniwch bolisïau'r gweinydd cartref hwn:", - "terms_invalid": "Adolygwch a derbyniwch holl bolisïau'r gweinydd cartref" + "sso_preauth_body": "I barhau, defnyddiwch Mewngofnod Sengl i brofi pwy ydych.", + "sso_title": "Defnyddiwch Mewngofnod Sengl i barhau", + "terms": "Darllenwch a derbyniwch bolisïau'r gweinydd cartref hwn:", + "terms_invalid": "Darllenwch a derbyniwch bolisïau'r gweinydd cartref hwn" }, "unsupported_auth": "Nid yw'r gweinydd cartref hwn yn cynnig unrhyw lifau mewngofnodi a gefnogir gan y cleient hwn.", "unsupported_auth_email": "Nid yw'r gweinydd cartref hwn yn cefnogi mewngofnodi gan ddefnyddio cyfeiriad e-bost.", @@ -389,13 +391,13 @@ }, "bug_reporting": { "additional_context": "Os oes cyd-destun ychwanegol a fyddai'n helpu i ddadansoddi'r mater, megis yr hyn yr oeddech yn ei wneud ar y pryd, IDau ystafelloedd, IDau defnyddiwr, ac ati, cynhwyswch y pethau hynny yma.", - "before_submitting": "Rydym yn argymell creu rhifyn GitHub i sicrhau bod eich adroddiad yn cael ei adolygu.", + "before_submitting": "Rydym yn argymell creu mater GitHub i sicrhau bod eich adroddiad yn cael ei ddarllen.", "collecting_information": "Casglu gwybodaeth fersiwn ap", - "collecting_logs": "Casglu boncyffion", - "create_new_issue": "Os gwelwch yn dda creu rhifyn newydd ar GitHub fel y gallwn ymchwilio i'r byg hwn.", - "description": "Mae logiau dadfygio yn cynnwys data defnydd cymhwysiad gan gynnwys eich enw defnyddiwr, IDau neu arallenwau'r ystafelloedd yr ydych wedi ymweld â nhw, pa elfennau UI y gwnaethoch ryngweithio â nhw ddiwethaf, ac enwau defnyddwyr defnyddwyr eraill. Nid ydynt yn cynnwys negeseuon.", - "download_logs": "Lawrlwythwch logiau", - "downloading_logs": "Wrthi'n llwytho i lawr logiau", + "collecting_logs": "Casglu cofnodion", + "create_new_issue": "Os gwelwch yn dda crewch fater newydd ar GitHub fel y gallwn ymchwilio i'r byg hwn.", + "description": "Mae cofnodion dadfygio yn cynnwys data defnydd cymhwysiad gan gynnwys eich enw defnyddiwr, IDau neu arallenwau'r ystafelloedd yr ydych wedi ymweld â nhw, pa elfennau UI y gwnaethoch ryngweithio â nhw ddiwethaf, ac enwau defnyddwyr defnyddwyr eraill. Nid ydynt yn cynnwys negeseuon.", + "download_logs": "Llwytho logiau i lawr", + "downloading_logs": "Wrthi'n llwytho logiau i lawr", "error_empty": "Dywedwch wrthym beth aeth o'i le neu, yn well, crëwch fater GitHub sy'n disgrifio'r broblem.", "failed_send_logs": "Wedi methu ag anfon logiau: ", "github_issue": "Mater GitHub", @@ -507,7 +509,7 @@ "people": "Pobl", "preferences": "Dewisiadau", "presence": "Presenoldeb", - "preview_message": "Hei chi. Ti yw'r gorau!", + "preview_message": "Hei ti. Ti yw'r gorau!", "privacy": "Preifatrwydd", "private": "Preifat", "private_room": "Ystafell breifat", @@ -531,7 +533,7 @@ "select_all": "Dewis y cyfan", "server": "Gweinydd", "settings": "Gosodiadau", - "setup_secure_messages": "Sefydlu Negeseuon Diogel", + "setup_secure_messages": "Gosod Negeseuon Diogel", "show_more": "Dangos mwy", "someone": "Rhywun", "space": "Bwlch", @@ -543,12 +545,12 @@ "support": "Cymorth", "system_alerts": "Rhybuddion System", "theme": "Thema", - "thread": "Edau", + "thread": "Edefyn", "threads": "Edau", "timeline": "Llinell Amser", "unavailable": "ddim ar gael", "unencrypted": "Heb ei amgryptio", - "unmute": "Dad-ddistewi", + "unmute": "Dad-dewi", "unnamed_room": "Ystafell Ddienw", "unnamed_space": "Gofod Dienw", "unverified": "Heb ei wirio", @@ -556,7 +558,7 @@ "user": "Defnyddwyr", "user_avatar": "Llun proffil", "username": "Enw defnyddiwr", - "verification_cancelled": "Dilysiad wedi'i ganslo", + "verification_cancelled": "Dilysiad wedi'i ddiddymu", "verified": "Gwiriwyd", "version": "Fersiwn", "video": "Fideo", @@ -567,22 +569,22 @@ "composer": { "autocomplete": { "@room_description": "Rhowch wybod i'r ystafell gyfan", - "command_a11y": "Command Autocomplete", + "command_a11y": "Awtogwblhau Gorchymyn", "command_description": "Gorchmynion", - "emoji_a11y": "Autocomplete Emoji", - "notification_a11y": "Hysbysiad yn Awtolenwi", + "emoji_a11y": "Awtogwblhau Emoji", + "notification_a11y": "Awtogwblhau Hysbysiad", "notification_description": "Hysbysiad Ystafell", - "room_a11y": "Ystafell Awtogwblhau", - "space_a11y": "Gofod Autocomplete", - "user_a11y": "Defnyddiwr yn Awtolenwi", + "room_a11y": "Awtogwblhau Ystafell", + "space_a11y": "Awtogwblhau Gofod", + "user_a11y": "Awtogwblhau Defnyddiwr", "user_description": "Defnyddwyr" }, "close_sticker_picker": "Cuddio sticeri", "edit_composer_label": "Golygu neges", "format_bold": "Trwm", "format_code_block": "Bloc cod", - "format_decrease_indent": "Gostyngiad mewnoliad", - "format_increase_indent": "Cynnydd mewnoliad", + "format_decrease_indent": "Lleihau mewnoliad", + "format_increase_indent": "Cynnyddu mewnoliad", "format_inline_code": "Cod", "format_insert_link": "Mewnosod dolen", "format_italic": "Italig", @@ -604,7 +606,7 @@ "no_perms_notice": "Nid oes gennych ganiatâd i bostio i'r ystafell hon", "placeholder": "Anfon neges…", "placeholder_encrypted": "Anfon neges wedi'i hamgryptio…", - "placeholder_reply": "Anfonwch ateb…", + "placeholder_reply": "Anfon ateb…", "placeholder_reply_encrypted": "Anfon ateb wedi'i amgryptio…", "placeholder_thread": "Ateb i edefyn…", "placeholder_thread_encrypted": "Ymateb i edefyn wedi'i amgryptio…", @@ -620,17 +622,17 @@ "stop_voice_message": "Stopio recordio", "voice_message_button": "Neges Llais" }, - "console_dev_note": "Os ydych chi'n gwybod beth rydych chi'n ei wneud, mae Element yn ffynhonnell agored, gwnewch yn siŵr eich bod chi'n edrych ar ein GitHub ( https://github.com/vector-im/element-web/ ) a chyfrannu!", + "console_dev_note": "Os ydych chi'n gwybod beth rydych chi'n ei wneud, mae Element yn raglen cod agored, gwnewch yn siŵr eich bod chi'n edrych ar ein GitHub ( https://github.com/vector-im/element-web/ ) a chyfrannu!", "console_scam_warning": "Os dywedodd rhywun wrthych am gopïo/gludo rhywbeth yma, mae'n debygol iawn eich bod yn cael eich twyllo!", "console_wait": "Arhoswch!", "create_room": { "action_create_room": "Creu ystafell", "action_create_video_room": "Creu ystafell fideo", - "encrypted_video_room_warning": "Ni allwch analluogi hyn yn nes ymlaen. Bydd yr ystafell yn cael ei hamgryptio ond ni fydd yr alwad wedi'i mewnosod.", - "encrypted_warning": "Ni allwch analluogi hyn yn nes ymlaen. Ni fydd pontydd a'r mwyafrif o bots yn gweithio eto.", + "encrypted_video_room_warning": "Allwch chi ddim analluogi hyn yn nes ymlaen. Bydd yr ystafell yn cael ei hamgryptio ond ni fydd yr alwad wedi'i mewnosod.", + "encrypted_warning": "Allwch chi ddim analluogi hyn yn nes ymlaen. Ni fydd pontydd a'r mwyafrif o fotiau'n gweithio eto.", "encryption_forced": "Mae angen amgryptio ar eich gweinydd er mwyn ei alluogi mewn ystafelloedd preifat.", "encryption_label": "Galluogi amgryptio o'r dechrau i'r diwedd", - "error_title": "Methiant i greu ystafell", + "error_title": "Methu creu ystafell", "generic_error": "Mae'n bosibl nad yw'r gweinydd ar gael, wedi'i orlwytho, neu eich bod yn taro byg.", "join_rule_change_notice": "Gallwch newid hwn unrhyw bryd o osodiadau ystafell.", "join_rule_invite": "Ystafell breifat (gwahoddiad yn unig)", @@ -647,7 +649,7 @@ "title_video_room": "Creu ystafell fideo", "topic_label": "Pwnc (dewisol)", "unfederated": "Rhwystro unrhyw un nad yw'n rhan o %(serverName)s rhag ymuno â'r ystafell hon byth.", - "unfederated_label_default_off": "Efallai y byddwch yn galluogi hyn os mai dim ond ar gyfer cydweithio â thimau mewnol ar eich gweinydd cartref y bydd yr ystafell yn cael ei defnyddio. Ni ellir newid hyn yn ddiweddarach.", + "unfederated_label_default_off": "Efallai y byddwch yn galluogi hyn os mai dim ond ar gyfer cydweithio â thimau mewnol ar eich gweinydd cartref y bydd yr ystafell yn cael ei defnyddio. Nid oes modd newid hyn yn ddiweddarach.", "unfederated_label_default_on": "Efallai y byddwch yn analluogi hyn os bydd yr ystafell yn cael ei defnyddio ar gyfer cydweithio â thimau allanol sydd â'u gweinydd cartref eu hunain. Ni ellir newid hyn yn ddiweddarach.", "unsupported_version": "Nid yw'r gweinydd yn cefnogi'r fersiwn ystafell a nodwyd." }, @@ -1199,6 +1201,7 @@ "change": "Newid gweinydd hunaniaeth", "change_prompt": "Datgysylltwch o'r gweinydd hunaniaeth a chysylltu â yn lle hynny?", "change_server_prompt": "Os nad ydych am ddefnyddio i ddarganfod a bod yn ddarganfyddadwy gan gysylltiadau presennol yr ydych yn gwybod, rhowch weinydd hunaniaeth arall isod.", + "changed": "Mae eich gweinydd hunaniaeth wedi'i newid", "checking": "Gwirio gweinydd", "description_connected": "Rydych chi'n defnyddio ar hyn o bryd i ddarganfod a bod yn ddarganfyddadwy gan gysylltiadau presennol rydych chi'n eu hadnabod. Gallwch newid eich gweinydd hunaniaeth isod.", "description_disconnected": "Nid ydych yn defnyddio gweinydd adnabod ar hyn o bryd. I ddarganfod a chael eich darganfod gan gysylltiadau presennol rydych chi'n eu hadnabod, ychwanegwch un isod.", @@ -1237,7 +1240,9 @@ "title": "Nid yw %(brand)s yn cefnogi'r porwr hwn", "use_desktop_heading": "Defnyddiwch %(brand)s Penbwrdd yn lle hynny", "use_mobile_heading": "Defnyddiwch %(brand)s ar ffôn symudol yn lle hynny", - "use_mobile_heading_after_desktop": "Neu defnyddiwch ein app symudol" + "use_mobile_heading_after_desktop": "Neu defnyddiwch ein app symudol", + "windows_64bit": "Windows (64-did)", + "windows_arm_64bit": "Windows (ARM 64-did)" }, "info_tooltip_title": "Gwybodaeth", "integration_manager": { @@ -1977,12 +1982,17 @@ "home_menu_label": "Opsiynau cartref", "join_public_room_label": "Ymunwch â'r ystafell gyhoeddus", "notification_options": "Opsiynau hysbysu", + "open_space_menu": "Agor dewislen gofod", "show_less": "Dangos llai", "show_previews": "Dangos rhagolwg o negeseuon", "sort_by": "Trefnu yn ôl", "sort_by_activity": "Gweithgaredd", "sort_by_alphabet": "A-Z", "sort_unread_first": "Dangos ystafelloedd gyda negeseuon heb eu darllen yn gyntaf", + "space_menu": { + "home": "Cartref gofod", + "space_settings": "Gosodiadau Gofod" + }, "space_menu_label": "Dewislen %(spaceName)s", "sublist_options": "Rhestrwch opsiynau", "suggested_rooms_heading": "Ystafelloedd a Awgrymir" From 7db909a47d345aff9b4041d4a7ba26d5cc41a22a Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Fri, 28 Feb 2025 09:34:06 +0100 Subject: [PATCH 009/458] new room list: keep space name in one line in header (#29369) * fix(new room list): keep space name in one line in header * test(new room list): update tests --- .../RoomListPanel/_RoomListHeaderView.pcss | 13 +++++++--- .../RoomListPanel/RoomListHeaderView.tsx | 4 ++-- .../RoomListHeaderView-test.tsx.snap | 24 ++++++++++++------- .../__snapshots__/RoomListPanel-test.tsx.snap | 12 ++++++---- 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/res/css/views/rooms/RoomListPanel/_RoomListHeaderView.pcss b/res/css/views/rooms/RoomListPanel/_RoomListHeaderView.pcss index 6a88e61332..8ce4655e58 100644 --- a/res/css/views/rooms/RoomListPanel/_RoomListHeaderView.pcss +++ b/res/css/views/rooms/RoomListPanel/_RoomListHeaderView.pcss @@ -9,9 +9,16 @@ height: 60px; padding: 0 var(--cpd-space-3x); - h1 { - all: unset; - font: var(--cpd-font-heading-sm-semibold); + .mx_RoomListHeaderView_title { + min-width: 0; + + h1 { + all: unset; + font: var(--cpd-font-heading-sm-semibold); + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } } button { diff --git a/src/components/views/rooms/RoomListPanel/RoomListHeaderView.tsx b/src/components/views/rooms/RoomListPanel/RoomListHeaderView.tsx index 7c82dabc2a..e8cc5dccb3 100644 --- a/src/components/views/rooms/RoomListPanel/RoomListHeaderView.tsx +++ b/src/components/views/rooms/RoomListPanel/RoomListHeaderView.tsx @@ -38,8 +38,8 @@ export function RoomListHeaderView(): JSX.Element { align="center" data-testid="room-list-header" > - -

{vm.title}

+ +

{vm.title}

{vm.displaySpaceMenu && }
{vm.displayComposeMenu && } diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListHeaderView-test.tsx.snap b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListHeaderView-test.tsx.snap index eee7df2dd7..6e571117fd 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListHeaderView-test.tsx.snap +++ b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListHeaderView-test.tsx.snap @@ -9,10 +9,12 @@ exports[` compose menu should display the compose menu 1`] style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: 0;" >
-

+

title

+
+
+
+
+
+
+
+
+
`; @@ -141,6 +167,32 @@ exports[` should render the RoomListSearch component when UICom +
+
+
+
+
+
+
+
+
`; diff --git a/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts b/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts new file mode 100644 index 0000000000..cd37b04e34 --- /dev/null +++ b/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts @@ -0,0 +1,53 @@ +/* +Copyright 2025 New Vector 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 type { MatrixDispatcher } from "../../../../src/dispatcher/dispatcher"; +import { RoomListStoreV3Class } from "../../../../src/stores/room-list-v3/RoomListStoreV3"; +import { AsyncStoreWithClient } from "../../../../src/stores/AsyncStoreWithClient"; +import { RecencySorter } from "../../../../src/stores/room-list-v3/skip-list/sorters/RecencySorter"; +import { stubClient } from "../../../test-utils"; +import { getMockedRooms } from "./skip-list/getMockedRooms"; +import { AlphabeticSorter } from "../../../../src/stores/room-list-v3/skip-list/sorters/AlphabeticSorter"; + +describe("RoomListStoreV3", () => { + async function getRoomListStore() { + const client = stubClient(); + const rooms = getMockedRooms(client); + client.getVisibleRooms = jest.fn().mockReturnValue(rooms); + jest.spyOn(AsyncStoreWithClient.prototype, "matrixClient", "get").mockReturnValue(client); + const fakeDispatcher = { register: jest.fn() } as unknown as MatrixDispatcher; + const store = new RoomListStoreV3Class(fakeDispatcher); + store.start(); + return { client, rooms, store }; + } + + it("Provides an unsorted list of rooms", async () => { + const { store, rooms } = await getRoomListStore(); + expect(store.getRooms()).toEqual(rooms); + }); + + it("Provides a sorted list of rooms", async () => { + const { store, rooms, client } = await getRoomListStore(); + const sorter = new RecencySorter(client.getSafeUserId()); + const sortedRooms = sorter.sort(rooms); + expect(store.getSortedRooms()).toEqual(sortedRooms); + }); + + it("Provides a way to resort", async () => { + const { store, rooms, client } = await getRoomListStore(); + + // List is sorted by recency, sort by alphabetical now + store.useAlphabeticSorting(); + let sortedRooms = new AlphabeticSorter().sort(rooms); + expect(store.getSortedRooms()).toEqual(sortedRooms); + + // Go back to recency sorting + store.useRecencySorting(); + sortedRooms = new RecencySorter(client.getSafeUserId()).sort(rooms); + expect(store.getSortedRooms()).toEqual(sortedRooms); + }); +}); diff --git a/test/unit-tests/stores/room-list-v3/skip-list/RoomSkipList-test.ts b/test/unit-tests/stores/room-list-v3/skip-list/RoomSkipList-test.ts index 3172307a81..b644aa30e9 100644 --- a/test/unit-tests/stores/room-list-v3/skip-list/RoomSkipList-test.ts +++ b/test/unit-tests/stores/room-list-v3/skip-list/RoomSkipList-test.ts @@ -7,26 +7,15 @@ Please see LICENSE files in the repository root for full details. import { shuffle } from "lodash"; -import type { MatrixClient, Room } from "matrix-js-sdk/src/matrix"; +import type { Room } from "matrix-js-sdk/src/matrix"; import type { Sorter } from "../../../../../src/stores/room-list-v3/skip-list/sorters"; -import { mkMessage, mkStubRoom, stubClient } from "../../../../test-utils"; +import { mkMessage, stubClient } from "../../../../test-utils"; import { RoomSkipList } from "../../../../../src/stores/room-list-v3/skip-list/RoomSkipList"; import { RecencySorter } from "../../../../../src/stores/room-list-v3/skip-list/sorters/RecencySorter"; import { AlphabeticSorter } from "../../../../../src/stores/room-list-v3/skip-list/sorters/AlphabeticSorter"; +import { getMockedRooms } from "./getMockedRooms"; describe("RoomSkipList", () => { - function getMockedRooms(client: MatrixClient, roomCount: number = 100): Room[] { - const rooms: Room[] = []; - for (let i = 0; i < roomCount; ++i) { - const roomId = `!foo${i}:matrix.org`; - const room = mkStubRoom(roomId, `Foo Room ${i}`, client); - const event = mkMessage({ room: roomId, user: `@foo${i}:matrix.org`, ts: i + 1, event: true }); - room.timeline.push(event); - rooms.push(room); - } - return rooms; - } - function generateSkipList(roomCount?: number): { skipList: RoomSkipList; rooms: Room[]; diff --git a/test/unit-tests/stores/room-list-v3/skip-list/getMockedRooms.ts b/test/unit-tests/stores/room-list-v3/skip-list/getMockedRooms.ts new file mode 100644 index 0000000000..d895ba944b --- /dev/null +++ b/test/unit-tests/stores/room-list-v3/skip-list/getMockedRooms.ts @@ -0,0 +1,21 @@ +/* +Copyright 2025 New Vector 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 type { MatrixClient, Room } from "matrix-js-sdk/src/matrix"; +import { mkMessage, mkStubRoom } from "../../../../test-utils"; + +export function getMockedRooms(client: MatrixClient, roomCount: number = 100): Room[] { + const rooms: Room[] = []; + for (let i = 0; i < roomCount; ++i) { + const roomId = `!foo${i}:matrix.org`; + const room = mkStubRoom(roomId, `Foo Room ${i}`, client); + const event = mkMessage({ room: roomId, user: `@foo${i}:matrix.org`, ts: i + 1, event: true }); + room.timeline.push(event); + rooms.push(room); + } + return rooms; +} From bf48100d31f8dac186a43eb48ff8b3402a360baa Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Mon, 3 Mar 2025 20:38:14 +0530 Subject: [PATCH 014/458] Room List - Update the room list store on actions from the dispatcher (#29397) * Update the store on action * Add more tests * Add newlines between case blocks * Make code more readable - Make if/else more consistent - Add comment on findAndAddRoom() * Add more tests * Remove redundant code On a timeline action, we return early if payload.room is falsy. So then why do we need to retry fetching the room? I think this can be removed but will ask others if there's some conext I'm missing. * Fix test * Remove more redundant code * Add more tests * Explain intention in comment * Emit only once even when adding multiple rooms * Add missing tsdoc --- src/stores/room-list-v3/RoomListStoreV3.ts | 102 +++++++- .../room-list-v3/RoomListStoreV3-test.ts | 225 +++++++++++++++++- 2 files changed, 320 insertions(+), 7 deletions(-) diff --git a/src/stores/room-list-v3/RoomListStoreV3.ts b/src/stores/room-list-v3/RoomListStoreV3.ts index 2904680ea8..0e70409761 100644 --- a/src/stores/room-list-v3/RoomListStoreV3.ts +++ b/src/stores/room-list-v3/RoomListStoreV3.ts @@ -5,7 +5,10 @@ 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 type { EmptyObject, Room } from "matrix-js-sdk/src/matrix"; +import { logger } from "matrix-js-sdk/src/logger"; +import { EventType } from "matrix-js-sdk/src/matrix"; + +import type { EmptyObject, Room, RoomState } from "matrix-js-sdk/src/matrix"; import type { MatrixDispatcher } from "../../dispatcher/dispatcher"; import type { ActionPayload } from "../../dispatcher/payloads"; import { AsyncStoreWithClient } from "../AsyncStoreWithClient"; @@ -16,6 +19,8 @@ import { LISTS_UPDATE_EVENT } from "../room-list/RoomListStore"; import { RoomSkipList } from "./skip-list/RoomSkipList"; import { RecencySorter } from "./skip-list/sorters/RecencySorter"; import { AlphabeticSorter } from "./skip-list/sorters/AlphabeticSorter"; +import { readReceiptChangeIsFor } from "../../utils/read-receipts"; +import { EffectiveMembership, getEffectiveMembership, getEffectiveMembershipTag } from "../../utils/membership"; /** * This store allows for fast retrieval of the room list in a sorted and filtered manner. @@ -78,7 +83,100 @@ export class RoomListStoreV3Class extends AsyncStoreWithClient { } protected async onAction(payload: ActionPayload): Promise { - return; + if (!this.matrixClient || !this.roomSkipList?.initialized) return; + + /** + * For the kind of updates that we care about (represented by the cases below), + * we try to find the associated room and simply re-insert it into the + * skiplist. If the position of said room in the sorted list changed, re-inserting + * would put it in the correct place. + */ + switch (payload.action) { + case "MatrixActions.Room.receipt": { + if (readReceiptChangeIsFor(payload.event, this.matrixClient)) { + const room = payload.room; + if (!room) { + logger.warn(`Own read receipt was in unknown room ${room.roomId}`); + return; + } + this.addRoomAndEmit(room); + } + break; + } + + case "MatrixActions.Room.tags": { + const room = payload.room; + this.addRoomAndEmit(room); + break; + } + + case "MatrixActions.Event.decrypted": { + const roomId = payload.event.getRoomId(); + if (!roomId) return; + const room = this.matrixClient.getRoom(roomId); + if (!room) { + logger.warn(`Event ${payload.event.getId()} was decrypted in an unknown room ${roomId}`); + return; + } + this.addRoomAndEmit(room); + break; + } + + case "MatrixActions.accountData": { + if (payload.event_type !== EventType.Direct) return; + const dmMap = payload.event.getContent(); + let needsEmit = false; + for (const userId of Object.keys(dmMap)) { + const roomIds = dmMap[userId]; + for (const roomId of roomIds) { + const room = this.matrixClient.getRoom(roomId); + if (!room) { + logger.warn(`${roomId} was found in DMs but the room is not in the store`); + continue; + } + this.roomSkipList.addRoom(room); + needsEmit = true; + } + } + if (needsEmit) this.emit(LISTS_UPDATE_EVENT); + break; + } + + case "MatrixActions.Room.timeline": { + // Ignore non-live events (backfill) and notification timeline set events (without a room) + if (!payload.isLiveEvent || !payload.isLiveUnfilteredRoomTimelineEvent || !payload.room) return; + this.addRoomAndEmit(payload.room); + break; + } + + case "MatrixActions.Room.myMembership": { + const oldMembership = getEffectiveMembership(payload.oldMembership); + const newMembership = getEffectiveMembershipTag(payload.room, payload.membership); + if (oldMembership !== EffectiveMembership.Join && newMembership === EffectiveMembership.Join) { + // If we're joining an upgraded room, we'll want to make sure we don't proliferate + // the dead room in the list. + const roomState: RoomState = payload.room.currentState; + const predecessor = roomState.findPredecessor(this.msc3946ProcessDynamicPredecessor); + if (predecessor) { + const prevRoom = this.matrixClient?.getRoom(predecessor.roomId); + if (prevRoom) this.roomSkipList.removeRoom(prevRoom); + else logger.warn(`Unable to find predecessor room with id ${predecessor.roomId}`); + } + } + this.addRoomAndEmit(payload.room); + break; + } + } + } + + /** + * Add a room to the skiplist and emit an update. + * @param room The room to add to the skiplist + */ + private addRoomAndEmit(room: Room): void { + if (!this.roomSkipList) throw new Error("roomSkipList hasn't been created yet!"); + this.roomSkipList.addRoom(room); + this.emit(LISTS_UPDATE_EVENT); } } diff --git a/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts b/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts index cd37b04e34..ad3ccdcfd9 100644 --- a/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts +++ b/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts @@ -5,13 +5,17 @@ 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 type { MatrixDispatcher } from "../../../../src/dispatcher/dispatcher"; +import { EventType, KnownMembership, MatrixEvent, Room } from "matrix-js-sdk/src/matrix"; +import { logger } from "matrix-js-sdk/src/logger"; + import { RoomListStoreV3Class } from "../../../../src/stores/room-list-v3/RoomListStoreV3"; import { AsyncStoreWithClient } from "../../../../src/stores/AsyncStoreWithClient"; import { RecencySorter } from "../../../../src/stores/room-list-v3/skip-list/sorters/RecencySorter"; -import { stubClient } from "../../../test-utils"; +import { mkEvent, mkMessage, stubClient, upsertRoomStateEvents } from "../../../test-utils"; import { getMockedRooms } from "./skip-list/getMockedRooms"; import { AlphabeticSorter } from "../../../../src/stores/room-list-v3/skip-list/sorters/AlphabeticSorter"; +import { LISTS_UPDATE_EVENT } from "../../../../src/stores/room-list/RoomListStore"; +import dispatcher from "../../../../src/dispatcher/dispatcher"; describe("RoomListStoreV3", () => { async function getRoomListStore() { @@ -19,10 +23,9 @@ describe("RoomListStoreV3", () => { const rooms = getMockedRooms(client); client.getVisibleRooms = jest.fn().mockReturnValue(rooms); jest.spyOn(AsyncStoreWithClient.prototype, "matrixClient", "get").mockReturnValue(client); - const fakeDispatcher = { register: jest.fn() } as unknown as MatrixDispatcher; - const store = new RoomListStoreV3Class(fakeDispatcher); + const store = new RoomListStoreV3Class(dispatcher); store.start(); - return { client, rooms, store }; + return { client, rooms, store, dispatcher }; } it("Provides an unsorted list of rooms", async () => { @@ -50,4 +53,216 @@ describe("RoomListStoreV3", () => { sortedRooms = new RecencySorter(client.getSafeUserId()).sort(rooms); expect(store.getSortedRooms()).toEqual(sortedRooms); }); + + describe("Updates", () => { + it("Room is re-inserted on timeline event", async () => { + const { store, rooms, dispatcher } = await getRoomListStore(); + + // Let's pretend like a new timeline event came on the room in 37th index. + const room = rooms[37]; + const event = mkMessage({ room: room.roomId, user: `@foo${3}:matrix.org`, ts: 1000, event: true }); + room.timeline.push(event); + + const payload = { + action: "MatrixActions.Room.timeline", + event, + isLiveEvent: true, + isLiveUnfilteredRoomTimelineEvent: true, + room, + }; + + const fn = jest.fn(); + store.on(LISTS_UPDATE_EVENT, fn); + dispatcher.dispatch(payload, true); + + expect(fn).toHaveBeenCalled(); + expect(store.getSortedRooms()[0].roomId).toEqual(room.roomId); + }); + + it("Predecessor room is removed on room upgrade", async () => { + const { store, rooms, client, dispatcher } = await getRoomListStore(); + // Let's say that !foo32:matrix.org is being upgraded + const oldRoom = rooms[32]; + // Create a new room with a predecessor event that points to oldRoom + const newRoom = new Room("!foonew:matrix.org", client, client.getSafeUserId(), {}); + const createWithPredecessor = new MatrixEvent({ + type: EventType.RoomCreate, + sender: "@foo:foo.org", + room_id: newRoom.roomId, + content: { + predecessor: { room_id: oldRoom.roomId, event_id: "tombstone_event_id" }, + }, + event_id: "$create", + state_key: "", + }); + upsertRoomStateEvents(newRoom, [createWithPredecessor]); + + const fn = jest.fn(); + store.on(LISTS_UPDATE_EVENT, fn); + dispatcher.dispatch( + { + action: "MatrixActions.Room.myMembership", + oldMembership: KnownMembership.Invite, + membership: KnownMembership.Join, + room: newRoom, + }, + true, + ); + + expect(fn).toHaveBeenCalled(); + const roomIds = store.getSortedRooms().map((r) => r.roomId); + expect(roomIds).not.toContain(oldRoom.roomId); + expect(roomIds).toContain(newRoom.roomId); + }); + + it("Rooms are inserted on m.direct event", async () => { + const { store, dispatcher } = await getRoomListStore(); + + // Let's create a m.direct event that we can dispatch + const content = { + "@bar1:matrix.org": ["!newroom1:matrix.org", "!newroom2:matrix.org"], + "@bar2:matrix.org": ["!newroom3:matrix.org", "!newroom4:matrix.org"], + "@bar3:matrix.org": ["!newroom5:matrix.org"], + }; + const event = mkEvent({ + event: true, + content, + user: "@foo:matrix.org", + type: EventType.Direct, + }); + + const fn = jest.fn(); + store.on(LISTS_UPDATE_EVENT, fn); + dispatcher.dispatch( + { + action: "MatrixActions.accountData", + event_type: EventType.Direct, + event, + }, + true, + ); + + // Ensure only one emit occurs + expect(fn).toHaveBeenCalledTimes(1); + + // Each of these rooms should now appear in the store + // We don't need to mock the rooms themselves since our mocked + // client will create the rooms on getRoom() call. + const roomIds = store.getSortedRooms().map((r) => r.roomId); + [ + "!newroom1:matrix.org", + "!newroom2:matrix.org", + "!newroom3:matrix.org", + "!newroom4:matrix.org", + "!newroom5:matrix.org", + ].forEach((id) => expect(roomIds).toContain(id)); + }); + + it("Room is re-inserted on tag change", async () => { + const { store, rooms, dispatcher } = await getRoomListStore(); + const fn = jest.fn(); + store.on(LISTS_UPDATE_EVENT, fn); + dispatcher.dispatch( + { + action: "MatrixActions.Room.tags", + room: rooms[10], + }, + true, + ); + expect(fn).toHaveBeenCalled(); + }); + + it("Room is re-inserted on decryption", async () => { + const { store, rooms, client, dispatcher } = await getRoomListStore(); + jest.spyOn(client, "getRoom").mockImplementation(() => rooms[10]); + + const fn = jest.fn(); + store.on(LISTS_UPDATE_EVENT, fn); + dispatcher.dispatch( + { + action: "MatrixActions.Event.decrypted", + event: { getRoomId: () => rooms[10].roomId }, + }, + true, + ); + expect(fn).toHaveBeenCalled(); + }); + + it("Logs a warning if room couldn't be found from room-id on decryption action", async () => { + const { store, client, dispatcher } = await getRoomListStore(); + jest.spyOn(client, "getRoom").mockImplementation(() => null); + const warnSpy = jest.spyOn(logger, "warn"); + + const fn = jest.fn(); + store.on(LISTS_UPDATE_EVENT, fn); + + // Dispatch a decrypted action but the room does not exist. + dispatcher.dispatch( + { + action: "MatrixActions.Event.decrypted", + event: { + getRoomId: () => "!doesnotexist:matrix.org", + getId: () => "some-id", + }, + }, + true, + ); + + expect(warnSpy).toHaveBeenCalled(); + expect(fn).not.toHaveBeenCalled(); + }); + + describe("Update from read receipt", () => { + function getReadReceiptEvent(userId: string) { + const content = { + some_id: { + "m.read": { + [userId]: { + ts: 5000, + }, + }, + }, + }; + const event = mkEvent({ + event: true, + content, + user: "@foo:matrix.org", + type: EventType.Receipt, + }); + return event; + } + + it("Room is re-inserted on read receipt from our user", async () => { + const { store, rooms, client, dispatcher } = await getRoomListStore(); + const event = getReadReceiptEvent(client.getSafeUserId()); + const fn = jest.fn(); + store.on(LISTS_UPDATE_EVENT, fn); + dispatcher.dispatch( + { + action: "MatrixActions.Room.receipt", + room: rooms[10], + event, + }, + true, + ); + expect(fn).toHaveBeenCalled(); + }); + + it("Read receipt from other users do not cause room to be re-inserted", async () => { + const { store, rooms, dispatcher } = await getRoomListStore(); + const event = getReadReceiptEvent("@foobar:matrix.org"); + const fn = jest.fn(); + store.on(LISTS_UPDATE_EVENT, fn); + dispatcher.dispatch( + { + action: "MatrixActions.Room.receipt", + room: rooms[10], + event, + }, + true, + ); + expect(fn).not.toHaveBeenCalled(); + }); + }); + }); }); From 4b025204534f9f447aaedcffe02ece721135d3ea Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Mon, 3 Mar 2025 15:28:46 +0000 Subject: [PATCH 015/458] Remove redundant `UserIdentityWarning` test (#29403) * Remove redundant `UserIdentityWarning` test Since the refactoring in https://github.com/element-hq/element-web/pull/29067, this test is redundant. It is also flaky and hard to understand. Time for it to die. * delint --- .../views/rooms/UserIdentityWarning-test.tsx | 47 +------------------ 1 file changed, 1 insertion(+), 46 deletions(-) diff --git a/test/unit-tests/components/views/rooms/UserIdentityWarning-test.tsx b/test/unit-tests/components/views/rooms/UserIdentityWarning-test.tsx index e1fa041747..7aad13643e 100644 --- a/test/unit-tests/components/views/rooms/UserIdentityWarning-test.tsx +++ b/test/unit-tests/components/views/rooms/UserIdentityWarning-test.tsx @@ -6,7 +6,7 @@ Please see LICENSE files in the repository root for full details. */ import React from "react"; -import { sleep, defer } from "matrix-js-sdk/src/utils"; +import { sleep } from "matrix-js-sdk/src/utils"; import { EventType, type MatrixClient, @@ -579,49 +579,4 @@ describe("UserIdentityWarning", () => { expect(getWarningByText("@bob:example.org's identity appears to have changed.")).toBeInTheDocument(), ); }); - - // If we get an update for a user's verification status while we're fetching - // that user's verification status, we should display based on the updated - // value. - describe("handles races between fetching verification status and receiving updates", () => { - // First case: check that if the update says that the user identity - // needs approval, but the fetch says it doesn't, we show the warning. - it("update says identity needs approval", async () => { - jest.spyOn(room, "getEncryptionTargetMembers").mockResolvedValue([ - mockRoomMember("@alice:example.org", "Alice"), - ]); - jest.spyOn(room, "getMember").mockReturnValue(mockRoomMember("@alice:example.org", "Alice")); - const crypto = client.getCrypto()!; - - const firstStatusPromise = defer(); - let callNumber = 0; - jest.spyOn(crypto, "getUserVerificationStatus").mockImplementation(async () => { - await firstStatusPromise.promise; - callNumber++; - if (callNumber == 1) { - await sleep(40); - return new UserVerificationStatus(false, false, false, false); - } else { - return new UserVerificationStatus(false, false, false, true); - } - }); - - renderComponent(client, room); - await sleep(10); // give it some time to finish initialising - - act(() => { - client.emit( - CryptoEvent.UserTrustStatusChanged, - "@alice:example.org", - new UserVerificationStatus(false, false, false, true), - ); - firstStatusPromise.resolve(undefined); - }); - await waitFor(() => - expect( - getWarningByText("Alice's (@alice:example.org) identity appears to have changed."), - ).toBeInTheDocument(), - ); - }); - }); }); From 072ee0cf3644bc94d81279938168e92b59a300bd Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Tue, 4 Mar 2025 09:26:49 +0000 Subject: [PATCH 016/458] [create-pull-request] automated change (#29405) Co-authored-by: t3chguy <2403652+t3chguy@users.noreply.github.com> --- playwright/testcontainers/synapse.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright/testcontainers/synapse.ts b/playwright/testcontainers/synapse.ts index 68c249a424..ef1328779c 100644 --- a/playwright/testcontainers/synapse.ts +++ b/playwright/testcontainers/synapse.ts @@ -25,7 +25,7 @@ import { type HomeserverContainer, type StartedHomeserverContainer } from "./Hom import { type StartedMatrixAuthenticationServiceContainer } from "./mas.ts"; import { Api, ClientServerApi, type Verb } from "../plugins/utils/api.ts"; -const TAG = "develop@sha256:3c22173f9e2c28af991b918a1a097d8bf05dd9bdd4afd89d142c65004a59322d"; +const TAG = "develop@sha256:edf6d9f7fa0b5cbc7f68a5e87ad8ba7289f941473d1e1a440e61dbccde9636ff"; const DEFAULT_CONFIG = { server_name: "localhost", From ffa8971195c407ba917c08c87caaf2aba3ddb484 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Tue, 4 Mar 2025 10:41:16 +0000 Subject: [PATCH 017/458] Device dehydration: remove .well-known check (#29404) * Device dehydrateion: remove .well-known check Per https://github.com/element-hq/element-web/issues/29387, this is redundant * Update src/utils/device/dehydration.ts Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --------- Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --- playwright/e2e/crypto/dehydration.spec.ts | 12 --------- src/utils/device/dehydration.ts | 32 ++++------------------- 2 files changed, 5 insertions(+), 39 deletions(-) diff --git a/playwright/e2e/crypto/dehydration.spec.ts b/playwright/e2e/crypto/dehydration.spec.ts index 35b5fae1ad..89ee854c91 100644 --- a/playwright/e2e/crypto/dehydration.spec.ts +++ b/playwright/e2e/crypto/dehydration.spec.ts @@ -22,18 +22,6 @@ test.use({ msc3814_enabled: true, }, }, - config: async ({ config, context }, use) => { - const wellKnown = { - ...config.default_server_config, - "org.matrix.msc3814": true, - }; - - await context.route("https://localhost/.well-known/matrix/client", async (route) => { - await route.fulfill({ json: wellKnown }); - }); - - await use(config); - }, }); test.describe("Dehydration", () => { diff --git a/src/utils/device/dehydration.ts b/src/utils/device/dehydration.ts index 031a3f362d..5dbec29739 100644 --- a/src/utils/device/dehydration.ts +++ b/src/utils/device/dehydration.ts @@ -7,34 +7,12 @@ Please see LICENSE files in the repository root for full details. */ import { logger } from "matrix-js-sdk/src/logger"; -import { type CryptoApi, type StartDehydrationOpts } from "matrix-js-sdk/src/crypto-api"; +import { type StartDehydrationOpts } from "matrix-js-sdk/src/crypto-api"; import type { MatrixClient } from "matrix-js-sdk/src/matrix"; /** - * Check if device dehydration is enabled. - * - * Note that this doesn't necessarily mean that device dehydration has been initialised - * (yet) on this client; rather, it means that the server supports it, the crypto backend - * supports it, and the application configuration suggests that it *should* be - * initialised on this device. - * - * Dehydration can currently only be enabled by setting a flag in the .well-known file. - */ -async function deviceDehydrationEnabled(client: MatrixClient, crypto: CryptoApi | undefined): Promise { - if (!crypto) { - return false; - } - if (!(await crypto.isDehydrationSupported())) { - return false; - } - const wellknown = await client.waitForClientWellKnown(); - return !!wellknown?.["org.matrix.msc3814"]; -} - -/** - * If dehydration is enabled (i.e., it is supported by the server and enabled in - * the configuration), rehydrate a device (if available) and create + * If dehydration is supported by the server, rehydrate a device (if available) and create * a new dehydrated device. * * @param client - MatrixClient to use for the operation @@ -45,8 +23,8 @@ export async function initialiseDehydrationIfEnabled( opts: StartDehydrationOpts = {}, ): Promise { const crypto = client.getCrypto(); - if (await deviceDehydrationEnabled(client, crypto)) { - logger.log("Device dehydration enabled"); - await crypto!.startDehydration(opts); + if (crypto && (await crypto.isDehydrationSupported())) { + logger.debug("Starting device dehydration"); + await crypto.startDehydration(opts); } } From 21e9d93e69e37b2696f4df885344dee5e4992840 Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Tue, 4 Mar 2025 16:57:41 +0530 Subject: [PATCH 018/458] Room List Store: Filter rooms by active space (#29399) * Add method to await space store setup Otherwise, the room list store will get incorrect information about spaces and thus will produce an incorrect roomlist. * Implement a way to filter by active space Implement a way to filter by active space * Fix broken jest tests * Fix typo * Rename `isReady` to `storeReadyPromise` * Fix mock in test --- src/stores/room-list-v3/RoomListStoreV3.ts | 21 +++++++ src/stores/room-list-v3/skip-list/RoomNode.ts | 22 ++++++++ .../room-list-v3/skip-list/RoomSkipList.ts | 38 +++++++++++++ src/stores/spaces/SpaceStore.ts | 11 ++++ .../room-list-v3/RoomListStoreV3-test.ts | 55 ++++++++++++++++++- .../skip-list/RoomSkipList-test.ts | 8 +++ 6 files changed, 153 insertions(+), 2 deletions(-) diff --git a/src/stores/room-list-v3/RoomListStoreV3.ts b/src/stores/room-list-v3/RoomListStoreV3.ts index 0e70409761..36a05f8357 100644 --- a/src/stores/room-list-v3/RoomListStoreV3.ts +++ b/src/stores/room-list-v3/RoomListStoreV3.ts @@ -21,6 +21,8 @@ import { RecencySorter } from "./skip-list/sorters/RecencySorter"; import { AlphabeticSorter } from "./skip-list/sorters/AlphabeticSorter"; import { readReceiptChangeIsFor } from "../../utils/read-receipts"; import { EffectiveMembership, getEffectiveMembership, getEffectiveMembershipTag } from "../../utils/membership"; +import SpaceStore from "../spaces/SpaceStore"; +import { UPDATE_HOME_BEHAVIOUR, UPDATE_SELECTED_SPACE } from "../spaces"; /** * This store allows for fast retrieval of the room list in a sorted and filtered manner. @@ -34,6 +36,10 @@ export class RoomListStoreV3Class extends AsyncStoreWithClient { public constructor(dispatcher: MatrixDispatcher) { super(dispatcher); this.msc3946ProcessDynamicPredecessor = SettingsStore.getValue("feature_dynamic_room_predecessors"); + SpaceStore.instance.on(UPDATE_SELECTED_SPACE, () => { + this.onActiveSpaceChanged(); + }); + SpaceStore.instance.on(UPDATE_HOME_BEHAVIOUR, () => this.onActiveSpaceChanged()); } /** @@ -53,6 +59,14 @@ export class RoomListStoreV3Class extends AsyncStoreWithClient { else return []; } + /** + * Get a list of sorted rooms that belong to the currently active space. + */ + public getSortedRoomsInActiveSpace(): Room[] { + if (this.roomSkipList?.initialized) return Array.from(this.roomSkipList.getRoomsInActiveSpace()); + else return []; + } + /** * Re-sort the list of rooms by alphabetic order. */ @@ -78,6 +92,7 @@ export class RoomListStoreV3Class extends AsyncStoreWithClient { const sorter = new RecencySorter(this.matrixClient.getSafeUserId()); this.roomSkipList = new RoomSkipList(sorter); const rooms = this.getRooms(); + await SpaceStore.instance.storeReadyPromise; this.roomSkipList.seed(rooms); this.emit(LISTS_UPDATE_EVENT); } @@ -178,6 +193,12 @@ export class RoomListStoreV3Class extends AsyncStoreWithClient { this.roomSkipList.addRoom(room); this.emit(LISTS_UPDATE_EVENT); } + + private onActiveSpaceChanged(): void { + if (!this.roomSkipList) return; + this.roomSkipList.calculateActiveSpaceForNodes(); + this.emit(LISTS_UPDATE_EVENT); + } } export default class RoomListStoreV3 { diff --git a/src/stores/room-list-v3/skip-list/RoomNode.ts b/src/stores/room-list-v3/skip-list/RoomNode.ts index cbc2a3346f..af792aa757 100644 --- a/src/stores/room-list-v3/skip-list/RoomNode.ts +++ b/src/stores/room-list-v3/skip-list/RoomNode.ts @@ -6,6 +6,7 @@ Please see LICENSE files in the repository root for full details. */ import type { Room } from "matrix-js-sdk/src/matrix"; +import SpaceStore from "../../spaces/SpaceStore"; /** * Room skip list stores room nodes. @@ -13,6 +14,8 @@ import type { Room } from "matrix-js-sdk/src/matrix"; * in different levels. */ export class RoomNode { + private _isInActiveSpace: boolean = false; + public constructor(public readonly room: Room) {} /** @@ -26,4 +29,23 @@ export class RoomNode { * eg: previous[i] gives the previous room node from this room node in level i. */ public previous: RoomNode[] = []; + + /** + * Whether the room associated with this room node belongs to + * the currently active space. + * @see {@link SpaceStoreClass#activeSpace} to understand what active + * space means. + */ + public get isInActiveSpace(): boolean { + return this._isInActiveSpace; + } + + /** + * Check if this room belongs to the active space and store the result + * in {@link RoomNode#isInActiveSpace}. + */ + public checkIfRoomBelongsToActiveSpace(): void { + const activeSpace = SpaceStore.instance.activeSpace; + this._isInActiveSpace = SpaceStore.instance.isRoomInSpace(activeSpace, this.room.roomId); + } } diff --git a/src/stores/room-list-v3/skip-list/RoomSkipList.ts b/src/stores/room-list-v3/skip-list/RoomSkipList.ts index 260786594f..323b4c8fcb 100644 --- a/src/stores/room-list-v3/skip-list/RoomSkipList.ts +++ b/src/stores/room-list-v3/skip-list/RoomSkipList.ts @@ -44,9 +44,22 @@ export class RoomSkipList implements Iterable { this.levels[currentLevel.level] = currentLevel; currentLevel = currentLevel.generateNextLevel(); } while (currentLevel.size > 1); + + // 3. Go through the list of rooms and mark nodes in active space + this.calculateActiveSpaceForNodes(); + this.initialized = true; } + /** + * Go through all the room nodes and check if they belong to the active space. + */ + public calculateActiveSpaceForNodes(): void { + for (const node of this.roomNodeMap.values()) { + node.checkIfRoomBelongsToActiveSpace(); + } + } + /** * Change the sorting algorithm used by the skip list. * This will reset the list and will rebuild from scratch. @@ -81,6 +94,7 @@ export class RoomSkipList implements Iterable { this.removeRoom(room); const newNode = new RoomNode(room); + newNode.checkIfRoomBelongsToActiveSpace(); this.roomNodeMap.set(room.roomId, newNode); /** @@ -159,6 +173,10 @@ export class RoomSkipList implements Iterable { return new SortedRoomIterator(this.levels[0].head!); } + public getRoomsInActiveSpace(): SortedSpaceFilteredIterator { + return new SortedSpaceFilteredIterator(this.levels[0].head!); + } + /** * The number of rooms currently in the skip list. */ @@ -179,3 +197,23 @@ class SortedRoomIterator implements Iterator { }; } } + +class SortedSpaceFilteredIterator implements Iterator { + public constructor(private current: RoomNode) {} + + public [Symbol.iterator](): SortedSpaceFilteredIterator { + return this; + } + + public next(): IteratorResult { + let current = this.current; + while (current && !current.isInActiveSpace) { + current = current.next[0]; + } + if (!current) return { value: undefined, done: true }; + this.current = current.next[0]; + return { + value: current.room, + }; + } +} diff --git a/src/stores/spaces/SpaceStore.ts b/src/stores/spaces/SpaceStore.ts index 8e8b4cc273..690beaa0b7 100644 --- a/src/stores/spaces/SpaceStore.ts +++ b/src/stores/spaces/SpaceStore.ts @@ -21,6 +21,7 @@ import { } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; +import { defer } from "matrix-js-sdk/src/utils"; import { AsyncStoreWithClient } from "../AsyncStoreWithClient"; import defaultDispatcher from "../../dispatcher/dispatcher"; @@ -152,6 +153,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { private _enabledMetaSpaces: MetaSpace[] = []; /** Whether the feature flag is set for MSC3946 */ private _msc3946ProcessDynamicPredecessor: boolean = SettingsStore.getValue("feature_dynamic_room_predecessors"); + private _storeReadyDeferred = defer(); public constructor() { super(defaultDispatcher, {}); @@ -162,6 +164,14 @@ export class SpaceStoreClass extends AsyncStoreWithClient { SettingsStore.monitorSetting("feature_dynamic_room_predecessors", null); } + /** + * A promise that resolves when the space store is ready. + * This happens after an initial hierarchy of spaces and rooms has been computed. + */ + public get storeReadyPromise(): Promise { + return this._storeReadyDeferred.promise; + } + /** * Get the order of meta spaces to display in the space panel. * @@ -1201,6 +1211,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { } else { this.switchSpaceIfNeeded(); } + this._storeReadyDeferred.resolve(); } private sendUserProperties(): void { diff --git a/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts b/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts index ad3ccdcfd9..c91606034e 100644 --- a/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts +++ b/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts @@ -11,11 +11,13 @@ import { logger } from "matrix-js-sdk/src/logger"; import { RoomListStoreV3Class } from "../../../../src/stores/room-list-v3/RoomListStoreV3"; import { AsyncStoreWithClient } from "../../../../src/stores/AsyncStoreWithClient"; import { RecencySorter } from "../../../../src/stores/room-list-v3/skip-list/sorters/RecencySorter"; -import { mkEvent, mkMessage, stubClient, upsertRoomStateEvents } from "../../../test-utils"; +import { mkEvent, mkMessage, mkSpace, stubClient, upsertRoomStateEvents } from "../../../test-utils"; import { getMockedRooms } from "./skip-list/getMockedRooms"; import { AlphabeticSorter } from "../../../../src/stores/room-list-v3/skip-list/sorters/AlphabeticSorter"; import { LISTS_UPDATE_EVENT } from "../../../../src/stores/room-list/RoomListStore"; import dispatcher from "../../../../src/dispatcher/dispatcher"; +import SpaceStore from "../../../../src/stores/spaces/SpaceStore"; +import { MetaSpace, UPDATE_SELECTED_SPACE } from "../../../../src/stores/spaces"; describe("RoomListStoreV3", () => { async function getRoomListStore() { @@ -24,10 +26,16 @@ describe("RoomListStoreV3", () => { client.getVisibleRooms = jest.fn().mockReturnValue(rooms); jest.spyOn(AsyncStoreWithClient.prototype, "matrixClient", "get").mockReturnValue(client); const store = new RoomListStoreV3Class(dispatcher); - store.start(); + await store.start(); return { client, rooms, store, dispatcher }; } + beforeEach(() => { + jest.spyOn(SpaceStore.instance, "isRoomInSpace").mockImplementation((space) => space === MetaSpace.Home); + jest.spyOn(SpaceStore.instance, "activeSpace", "get").mockImplementation(() => MetaSpace.Home); + jest.spyOn(SpaceStore.instance, "storeReadyPromise", "get").mockImplementation(() => Promise.resolve()); + }); + it("Provides an unsorted list of rooms", async () => { const { store, rooms } = await getRoomListStore(); expect(store.getRooms()).toEqual(rooms); @@ -264,5 +272,48 @@ describe("RoomListStoreV3", () => { expect(fn).not.toHaveBeenCalled(); }); }); + + describe("Spaces", () => { + it("Filtering by spaces work", async () => { + const client = stubClient(); + const rooms = getMockedRooms(client); + + // Let's choose 5 rooms to put in space + const indexes = [6, 8, 13, 27, 75]; + const roomIds = indexes.map((i) => rooms[i].roomId); + const spaceRoom = mkSpace(client, "!space1:matrix.org", [], roomIds); + rooms.push(spaceRoom); + + client.getVisibleRooms = jest.fn().mockReturnValue(rooms); + jest.spyOn(AsyncStoreWithClient.prototype, "matrixClient", "get").mockReturnValue(client); + + // Mock the space store + jest.spyOn(SpaceStore.instance, "isRoomInSpace").mockImplementation((space, id) => { + if (space === MetaSpace.Home && !roomIds.includes(id)) return true; + if (space === spaceRoom.roomId && roomIds.includes(id)) return true; + return false; + }); + + const store = new RoomListStoreV3Class(dispatcher); + await store.start(); + const fn = jest.fn(); + store.on(LISTS_UPDATE_EVENT, fn); + + // The rooms which belong to the space should not be shown + const result = store.getSortedRoomsInActiveSpace().map((r) => r.roomId); + for (const id of roomIds) { + expect(result).not.toContain(id); + } + + // Lets switch to the space + jest.spyOn(SpaceStore.instance, "activeSpace", "get").mockImplementation(() => spaceRoom.roomId); + SpaceStore.instance.emit(UPDATE_SELECTED_SPACE); + expect(fn).toHaveBeenCalled(); + const result2 = store.getSortedRoomsInActiveSpace().map((r) => r.roomId); + for (const id of roomIds) { + expect(result2).toContain(id); + } + }); + }); }); }); diff --git a/test/unit-tests/stores/room-list-v3/skip-list/RoomSkipList-test.ts b/test/unit-tests/stores/room-list-v3/skip-list/RoomSkipList-test.ts index b644aa30e9..1d091350b1 100644 --- a/test/unit-tests/stores/room-list-v3/skip-list/RoomSkipList-test.ts +++ b/test/unit-tests/stores/room-list-v3/skip-list/RoomSkipList-test.ts @@ -14,6 +14,8 @@ import { RoomSkipList } from "../../../../../src/stores/room-list-v3/skip-list/R import { RecencySorter } from "../../../../../src/stores/room-list-v3/skip-list/sorters/RecencySorter"; import { AlphabeticSorter } from "../../../../../src/stores/room-list-v3/skip-list/sorters/AlphabeticSorter"; import { getMockedRooms } from "./getMockedRooms"; +import SpaceStore from "../../../../../src/stores/spaces/SpaceStore"; +import { MetaSpace } from "../../../../../src/stores/spaces"; describe("RoomSkipList", () => { function generateSkipList(roomCount?: number): { @@ -30,6 +32,12 @@ describe("RoomSkipList", () => { return { skipList, rooms, totalRooms: rooms.length, sorter }; } + beforeEach(() => { + jest.spyOn(SpaceStore.instance, "isRoomInSpace").mockImplementation((space) => space === MetaSpace.Home); + jest.spyOn(SpaceStore.instance, "activeSpace", "get").mockImplementation(() => MetaSpace.Home); + jest.spyOn(SpaceStore.instance, "storeReadyPromise", "get").mockImplementation(() => Promise.resolve()); + }); + it("Rooms are in sorted order after initial seed", () => { const { skipList, totalRooms } = generateSkipList(); expect(skipList.size).toEqual(totalRooms); From ed35a7cba4c14e0847d5e566dccf81b6632f89f9 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 4 Mar 2025 12:46:15 +0000 Subject: [PATCH 019/458] Upgrade dependency to matrix-js-sdk@37.1.0-rc.0 --- package.json | 2 +- yarn.lock | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index a0fb4a8216..30eb7dbb44 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,7 @@ "maplibre-gl": "^5.0.0", "matrix-encrypt-attachment": "^1.0.3", "matrix-events-sdk": "0.0.1", - "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", + "matrix-js-sdk": "37.1.0-rc.0", "matrix-widget-api": "^1.10.0", "memoize-one": "^6.0.0", "mime": "^4.0.4", diff --git a/yarn.lock b/yarn.lock index 22ce4d7bf5..4d048814a3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3545,7 +3545,7 @@ classnames "^2.5.1" vaul "^1.0.0" -"@vector-im/matrix-wysiwyg-wasm@link:../../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.0-af862ffd231dc0a6b8d6f2cb3601e68456c0ff24-integrity/node_modules/bindings/wysiwyg-wasm": +"@vector-im/matrix-wysiwyg-wasm@link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.0-af862ffd231dc0a6b8d6f2cb3601e68456c0ff24-integrity/node_modules/bindings/wysiwyg-wasm": version "0.0.0" uid "" @@ -3554,7 +3554,7 @@ resolved "https://registry.yarnpkg.com/@vector-im/matrix-wysiwyg/-/matrix-wysiwyg-2.38.0.tgz#af862ffd231dc0a6b8d6f2cb3601e68456c0ff24" integrity sha512-cMEVicFYVzFxuSyWON0aVGjAJMcgJZ+LxuLTEp8EGuu8cRacuh0RN5rapb11YVZygzFvE7X1cMedJ/fKd5vRLA== dependencies: - "@vector-im/matrix-wysiwyg-wasm" "link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.0-af862ffd231dc0a6b8d6f2cb3601e68456c0ff24-integrity/node_modules/bindings/wysiwyg-wasm" + "@vector-im/matrix-wysiwyg-wasm" "link:../../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.0-af862ffd231dc0a6b8d6f2cb3601e68456c0ff24-integrity/node_modules/bindings/wysiwyg-wasm" "@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1": version "1.14.1" @@ -8751,9 +8751,10 @@ matrix-events-sdk@0.0.1: resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1.tgz#c8c38911e2cb29023b0bbac8d6f32e0de2c957dd" integrity sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA== -"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop": - version "37.0.0" - resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/d81929de4c9526e7d68ab7226804726cdef6387f" +matrix-js-sdk@37.1.0-rc.0: + version "37.1.0-rc.0" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-37.1.0-rc.0.tgz#e5667ea22519a18247dc9b3d2dc992afd03b599d" + integrity sha512-VQmfzeJ9HiYQ9+EyaH1ku+u7e56/4+W6eHAxLMXzSXjOxw2XcGMfLZ6quH356/b4QYkoOw2un8EgHIBiQN5ZQQ== dependencies: "@babel/runtime" "^7.12.5" "@matrix-org/matrix-sdk-crypto-wasm" "^14.0.1" From c0d14daa17efed6097bf7601953fda4136f5698e Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 4 Mar 2025 12:51:06 +0000 Subject: [PATCH 020/458] v1.11.95-rc.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 30eb7dbb44..58491a66aa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "element-web", - "version": "1.11.94", + "version": "1.11.95-rc.0", "description": "Element: the future of secure communication", "author": "New Vector Ltd.", "repository": { From 31af8b07dd54598d95d97f999e500d82064bda36 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 4 Mar 2025 13:24:38 +0000 Subject: [PATCH 021/458] Remove buggy tooltip on room intro & homepage (#29406) * Remove buggy tooltip on room intro & homepage Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Add knip ignore Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- knip.ts | 1 + .../views/elements/MiniAvatarUploader.tsx | 45 +++++++------------ .../elements/MiniAvatarUploader-test.tsx | 4 +- 3 files changed, 19 insertions(+), 31 deletions(-) diff --git a/knip.ts b/knip.ts index 17ad531332..0188e096e5 100644 --- a/knip.ts +++ b/knip.ts @@ -19,6 +19,7 @@ export default { ignore: [ // Keep for now "src/hooks/useLocalStorageState.ts", + "src/hooks/useTimeout.ts", "src/components/views/elements/InfoTooltip.tsx", "src/components/views/elements/StyledCheckbox.tsx", ], diff --git a/src/components/views/elements/MiniAvatarUploader.tsx b/src/components/views/elements/MiniAvatarUploader.tsx index a6328816ed..49a908d854 100644 --- a/src/components/views/elements/MiniAvatarUploader.tsx +++ b/src/components/views/elements/MiniAvatarUploader.tsx @@ -9,10 +9,8 @@ Please see LICENSE files in the repository root for full details. import classNames from "classnames"; import { EventType } from "matrix-js-sdk/src/matrix"; import React, { useContext, useRef, useState, type MouseEvent, type ReactNode } from "react"; -import { Tooltip } from "@vector-im/compound-web"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; -import { useTimeout } from "../../../hooks/useTimeout"; import { chromeFileInputFix } from "../../../utils/BrowserWorkarounds"; import AccessibleButton from "./AccessibleButton"; import Spinner from "./Spinner"; @@ -42,15 +40,6 @@ const MiniAvatarUploader: React.FC = ({ }) => { const cli = useContext(MatrixClientContext); const [busy, setBusy] = useState(false); - const [hover, setHover] = useState(false); - const [show, setShow] = useState(false); - - useTimeout(() => { - setShow(true); - }, 3000); // show after 3 seconds - useTimeout(() => { - setShow(false); - }, 13000); // hide after being shown for 10 seconds const uploadRef = useRef(null); @@ -61,7 +50,6 @@ const MiniAvatarUploader: React.FC = ({ isUserAvatar || room?.currentState?.maySendStateEvent(EventType.RoomAvatar, cli.getSafeUserId()); if (!canSetAvatar) return {children}; - const visible = !!label && (hover || show); return ( = ({ accept="image/*" /> - - { - uploadRef.current?.click(); - }} - > - {children} + { + uploadRef.current?.click(); + }} + aria-label={label} + > + {children} -
- {busy ? :
} -
- - +
+ {busy ? :
} +
+ ); }; diff --git a/test/unit-tests/components/views/elements/MiniAvatarUploader-test.tsx b/test/unit-tests/components/views/elements/MiniAvatarUploader-test.tsx index 5b451c44b4..f6d2c07bc9 100644 --- a/test/unit-tests/components/views/elements/MiniAvatarUploader-test.tsx +++ b/test/unit-tests/components/views/elements/MiniAvatarUploader-test.tsx @@ -26,12 +26,12 @@ describe("", () => { const setAvatarUrl = jest.fn(); const user = userEvent.setup(); - const { container, findByText } = render( + const { container, findByLabelText } = render( , withClientContextRenderOptions(cli), ); - await findByText("Upload"); + await findByLabelText("Upload"); await user.upload(container.querySelector("input")!, AVATAR_FILE); expect(cli.uploadContent).toHaveBeenCalledWith(AVATAR_FILE); From 59c26fc3addcc5e089eb0cb22db4254f9111c657 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 14:43:55 +0000 Subject: [PATCH 022/458] Update docker (#29408) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/docker.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index d0c447f8c6..6352ce3bc4 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -29,10 +29,10 @@ jobs: if: github.event_name != 'pull_request' - name: Set up QEMU - uses: docker/setup-qemu-action@4574d27a4764455b42196d70a065bc6853246a25 # v3 + uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@f7ce87c1d6bead3e36075b2ce75da1f6cc28aaca # v3 + uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3 with: install: true @@ -53,7 +53,7 @@ jobs: - name: Build and load id: test-build - uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6 + uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6 with: context: . load: true @@ -93,7 +93,7 @@ jobs: - name: Docker meta id: meta - uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96 # v5 + uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5 if: github.event_name != 'pull_request' with: images: | @@ -107,7 +107,7 @@ jobs: - name: Build and push id: build-and-push - uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6 + uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6 if: github.event_name != 'pull_request' with: context: . From cef25c2cab9fec1dc3b96c5770e315841a048797 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 14:44:45 +0000 Subject: [PATCH 023/458] Update sigstore/cosign-installer digest to d7d6bc7 (#29411) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/docker.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index 6352ce3bc4..12ebaddf5b 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -25,7 +25,7 @@ jobs: fetch-depth: 0 # needed for docker-package to be able to calculate the version - name: Install Cosign - uses: sigstore/cosign-installer@c56c2d3e59e4281cc41dea2217323ba5694b171e # v3 + uses: sigstore/cosign-installer@d7d6bc7722e3daa8354c50bcb52f4837da5e9b6a # v3 if: github.event_name != 'pull_request' - name: Set up QEMU From 54e015706c30bf7833995b17cd9cfbfac27e36fa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 14:45:16 +0000 Subject: [PATCH 024/458] Update peter-evans/create-pull-request digest to 271a8d0 (#29410) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/playwright-image-updates.yaml | 2 +- .github/workflows/update-jitsi.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/playwright-image-updates.yaml b/.github/workflows/playwright-image-updates.yaml index e5e2f739c0..7681600dde 100644 --- a/.github/workflows/playwright-image-updates.yaml +++ b/.github/workflows/playwright-image-updates.yaml @@ -23,7 +23,7 @@ jobs: - name: Create Pull Request id: cpr - uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7 + uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7 with: token: ${{ secrets.ELEMENT_BOT_TOKEN }} branch: actions/playwright-image-updates diff --git a/.github/workflows/update-jitsi.yml b/.github/workflows/update-jitsi.yml index a3abcb002f..f4fd13892b 100644 --- a/.github/workflows/update-jitsi.yml +++ b/.github/workflows/update-jitsi.yml @@ -23,7 +23,7 @@ jobs: run: "yarn update:jitsi" - name: Create Pull Request - uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7 + uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7 with: token: ${{ secrets.ELEMENT_BOT_TOKEN }} branch: actions/jitsi-update From e1d76e77a5c8fbd4a49020c279f1a147431784b1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 14:45:39 +0000 Subject: [PATCH 025/458] Update definitelyTyped (#29412) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index 22ce4d7bf5..48e8721b78 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3116,9 +3116,9 @@ integrity sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ== "@types/lodash@^4.14.168": - version "4.17.15" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.15.tgz#12d4af0ed17cc7600ce1f9980cec48fc17ad1e89" - integrity sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw== + version "4.17.16" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.16.tgz#94ae78fab4a38d73086e962d0b65c30d816bfb0a" + integrity sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g== "@types/mapbox__point-geometry@*", "@types/mapbox__point-geometry@^0.1.4": version "0.1.4" @@ -3172,9 +3172,9 @@ undici-types "~6.20.0" "@types/node@18", "@types/node@^18.11.18": - version "18.19.76" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.76.tgz#7991658e0ba41ad30cc8be01c9bbe580d58f2112" - integrity sha512-yvR7Q9LdPz2vGpmpJX5LolrgRdWvB67MJKDPSgIIzpFbaf9a1j/f5DnLp5VDyHGMR0QZHlTr1afsD87QCXFHKw== + version "18.19.79" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.79.tgz#82fde7ac17809f4738a494b22273f0f7e6754f6e" + integrity sha512-90K8Oayimbctc5zTPHPfZloc/lGVs7f3phUAAMcTgEPtg8kKquGZDERC8K4vkBYkQQh48msiYUslYtxTWvqcAg== dependencies: undici-types "~5.26.4" @@ -3545,9 +3545,8 @@ classnames "^2.5.1" vaul "^1.0.0" -"@vector-im/matrix-wysiwyg-wasm@link:../../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.0-af862ffd231dc0a6b8d6f2cb3601e68456c0ff24-integrity/node_modules/bindings/wysiwyg-wasm": +"@vector-im/matrix-wysiwyg-wasm@link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.0-af862ffd231dc0a6b8d6f2cb3601e68456c0ff24-integrity/node_modules/bindings/wysiwyg-wasm": version "0.0.0" - uid "" "@vector-im/matrix-wysiwyg@2.38.0": version "2.38.0" From 81c12db5eebd88c0f9f3d75b773f1ef22ccb7281 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 14:45:44 +0000 Subject: [PATCH 026/458] Update dependency @sentry/browser to v9.3.0 (#29416) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 68 +++++++++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/yarn.lock b/yarn.lock index 48e8721b78..e63d0933e4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2470,35 +2470,35 @@ resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g== -"@sentry-internal/browser-utils@9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-9.1.0.tgz#0f67de865d4e1b3a60cd618cdda8431d383e6b71" - integrity sha512-S1uT+kkFlstWpwnaBTIJSwwAID8PS3aA0fIidOjNezeoUE5gOvpsjDATo9q+sl6FbGWynxMz6EnYSrq/5tuaBQ== +"@sentry-internal/browser-utils@9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-9.3.0.tgz#345fa61da239186fa0ad6c7194d4a1f7df7646c7" + integrity sha512-G3z4HCUyb5nJe03EPUhWjnaHqMDt4mOTFJDNha3DGoB51lMYojpQI1Qo1u6bY4qkWVSO1c+HqOU0RVsXoAchtQ== dependencies: - "@sentry/core" "9.1.0" + "@sentry/core" "9.3.0" -"@sentry-internal/feedback@9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-9.1.0.tgz#e96edd4e46c8ab19f00855f60fa3bed01106bb5b" - integrity sha512-jTDCqkqH3QDC8m9WO4mB06hqnBRsl3p7ozoh0E774UvNB6blOEZjShhSGMMEy5jbbJajPWsOivCofUtFAwbfGw== +"@sentry-internal/feedback@9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-9.3.0.tgz#d60bcedd01907478b286512ce54f59682b2910e0" + integrity sha512-LQmIbQaATlN5QEwCD2Xt+7VKfwfR5W3dbn0jdF1x4hQFE/srdnOj60xMz/mj3tP5BxV552xJniGsyZ8lXHDb2A== dependencies: - "@sentry/core" "9.1.0" + "@sentry/core" "9.3.0" -"@sentry-internal/replay-canvas@9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-9.1.0.tgz#20be6ac4b722078ebdbc760aada02858ecbffe7e" - integrity sha512-gxredVe+mOgfNqDJ3dTLiRON3FK1rZ8d0LHp7TICK/umLkWFkuso0DbNeyKU+3XCEjCr9VM7ZRqTDMzmY6zyVg== +"@sentry-internal/replay-canvas@9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-9.3.0.tgz#b9432ab65152304b5f86f99efdeffcd92091f733" + integrity sha512-MhDMJeRGa55a0D541+OzTFMWwbabthhDGbAL90/NpappfyeBbAiktmCNl0BFTZuRbCGrC2m1LLCqHegCVKW4fQ== dependencies: - "@sentry-internal/replay" "9.1.0" - "@sentry/core" "9.1.0" + "@sentry-internal/replay" "9.3.0" + "@sentry/core" "9.3.0" -"@sentry-internal/replay@9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-9.1.0.tgz#b423edf4dabaea0b7ba689a87b19cf3ea87075f0" - integrity sha512-E2xrUoms90qvm0BVOuaZ8QfkMoTUEgoIW/35uOeaqNcL7uOIj8c5cSEQQKit2Dr7CL6W+Ci5c6Khdyd5C0NL5w== +"@sentry-internal/replay@9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-9.3.0.tgz#c846cf77cd8deefda84316f1a938bbeae5861564" + integrity sha512-ZkH+Gahn89JygpuiFn26ZgAqJXHtnr+HjfQ2ONOFoWQHNH6X5wk75UTma55aYk1d8VcBPFoU6WjFhZoQ55SV1g== dependencies: - "@sentry-internal/browser-utils" "9.1.0" - "@sentry/core" "9.1.0" + "@sentry-internal/browser-utils" "9.3.0" + "@sentry/core" "9.3.0" "@sentry/babel-plugin-component-annotate@3.1.2": version "3.1.2" @@ -2506,15 +2506,15 @@ integrity sha512-5h2WXRJ6swKA0TwxHHryC8M2QyOfS9QhTAL6ElPfkEYe9HhJieXmxsDpyspbqAa26ccnCUcmwE5vL34jAjt4sQ== "@sentry/browser@^9.0.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-9.1.0.tgz#7798a930562b3b403611e1f201fb8e50e59da472" - integrity sha512-G55e5j77DqRW3LkalJLAjRRfuyKrjHaKTnwIYXa6ycO+Q1+l14pEUxu+eK5Abu2rtSdViwRSb5/G6a/miSUlYA== + version "9.3.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-9.3.0.tgz#270e93c0f1bc10abb6651255bcaa30ba21c4928a" + integrity sha512-yPwWWQo/hpN63p0NGmk/Dd1Fx5CQRWNMfuV7dtfPBtg3vRjDecA9OLyK29AqK5h3Fl8FuJOyOqB87CvtXUqh5g== dependencies: - "@sentry-internal/browser-utils" "9.1.0" - "@sentry-internal/feedback" "9.1.0" - "@sentry-internal/replay" "9.1.0" - "@sentry-internal/replay-canvas" "9.1.0" - "@sentry/core" "9.1.0" + "@sentry-internal/browser-utils" "9.3.0" + "@sentry-internal/feedback" "9.3.0" + "@sentry-internal/replay" "9.3.0" + "@sentry-internal/replay-canvas" "9.3.0" + "@sentry/core" "9.3.0" "@sentry/bundler-plugin-core@3.1.2": version "3.1.2" @@ -2584,10 +2584,10 @@ "@sentry/cli-win32-i686" "2.41.1" "@sentry/cli-win32-x64" "2.41.1" -"@sentry/core@9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-9.1.0.tgz#db7438d144b7ea405260c33082971eedab48d7f3" - integrity sha512-djWEzSBpMgqdF3GQuxO+kXCUX+Mgq42G4Uah/HSUBvPDHKipMmyWlutGRoFyVPPOnCDgpHu3wCt83wbpEyVmDw== +"@sentry/core@9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-9.3.0.tgz#d5a1ab7deecd95f86316e658129d3874557cbfd9" + integrity sha512-SxQ4z7wTkfguvYb2ctNEMU9kVAbhl9ymfjhLnrvtygTwL5soLqAKdco/lX/4P9K9Osgb2Dl6urQWRl+AhzKVbQ== "@sentry/webpack-plugin@^3.0.0": version "3.1.2" From 3d705b1895c41881479a6a91586419523445303c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 14:45:47 +0000 Subject: [PATCH 027/458] Update dependency caniuse-lite to v1.0.30001701 (#29414) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index a0fb4a8216..2584b34f2f 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "@types/react-dom": "18.3.5", "oidc-client-ts": "3.1.0", "jwt-decode": "4.0.0", - "caniuse-lite": "1.0.30001699", + "caniuse-lite": "1.0.30001701", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0", "wrap-ansi": "npm:wrap-ansi@^7.0.0" }, diff --git a/yarn.lock b/yarn.lock index e63d0933e4..83dbdc77b0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4585,10 +4585,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@1.0.30001699, caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001646, caniuse-lite@^1.0.30001688: - version "1.0.30001699" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001699.tgz#a102cf330d153bf8c92bfb5be3cd44c0a89c8c12" - integrity sha512-b+uH5BakXZ9Do9iK+CkDmctUSEqZl+SP056vc5usa0PL+ev5OHw003rZXcnjNDv3L8P5j6rwT6C0BPKSikW08w== +caniuse-lite@1.0.30001701, caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001646, caniuse-lite@^1.0.30001688: + version "1.0.30001701" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001701.tgz#ad9c90301f7153cf6b3314d16cc30757285bf9e7" + integrity sha512-faRs/AW3jA9nTwmJBSO1PQ6L/EOgsB5HMQQq4iCu5zhPgVVgO/pZRHlmatwijZKetFw8/Pr4q6dEN8sJuq8qTw== chalk@5.2.0: version "5.2.0" From b82c8554e3e8b954c303444740736d38f2cd9848 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 14:46:12 +0000 Subject: [PATCH 028/458] Update fontsource monorepo to v5.2.5 (#29418) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index 83dbdc77b0..695b725dc4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1637,14 +1637,14 @@ integrity sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig== "@fontsource/inconsolata@^5": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@fontsource/inconsolata/-/inconsolata-5.1.1.tgz#bc5cc74d04dee8b2cb4e706cc33ac3dc50100191" - integrity sha512-jLLMagEJURTae5J30gehIsXRv96vjQ0XlALGxZC7DERWPqsJTa0oSsZR8k6IJfizU4ZeRl/aKWpZca2Lo3TvSg== + version "5.2.5" + resolved "https://registry.yarnpkg.com/@fontsource/inconsolata/-/inconsolata-5.2.5.tgz#8f220d83567dc27b7b54fd583044cb2ebbbd2759" + integrity sha512-OvzkZY5qYghv/jEV6cfGZzFhdFTvSnU+ExPC7WcZ7w8PdRhtiu/SpcBWOBt+3LXgS0n9qyepgq4zZmxlDTlGGQ== "@fontsource/inter@^5": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@fontsource/inter/-/inter-5.1.1.tgz#401803b6ac4c877f5be94088aa89147ed5a2bd85" - integrity sha512-weN3E+rq0Xb3Z93VHJ+Rc7WOQX9ETJPTAJ+gDcaMHtjft67L58sfS65rAjC5tZUXQ2FdZ/V1/sSzCwZ6v05kJw== + version "5.2.5" + resolved "https://registry.yarnpkg.com/@fontsource/inter/-/inter-5.2.5.tgz#69efffe6ccfae138cbe1806f41daa39cef986b59" + integrity sha512-kbsPKj0S4p44JdYRFiW78Td8Ge2sBVxi/PIBwmih+RpSXUdvS9nbs1HIiuUSPtRMi14CqLEZ/fbk7dj7vni1Sg== "@formatjs/ecma402-abstract@2.3.3": version "2.3.3" From fbc6f12408f84734fb438b35bd8c82fd0682a271 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 14:46:13 +0000 Subject: [PATCH 029/458] Update dependency @types/react-virtualized to v9.22.2 (#29413) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index 695b725dc4..03138dd059 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3199,9 +3199,9 @@ integrity sha512-z6djfFIbrrddtunoMJBOPlyZrnmeuG1kkvHUNi2QfpOb+JMMLuLliHHTmMyRi7k7LiTAut0HbdGCF6ibDtQAHQ== "@types/prop-types@*": - version "15.7.13" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.13.tgz#2af91918ee12d9d32914feb13f5326658461b451" - integrity sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA== + version "15.7.14" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.14.tgz#1433419d73b2a7ebfc6918dcefd2ec0d5cd698f2" + integrity sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ== "@types/qrcode@^1.3.5": version "1.5.5" @@ -3248,9 +3248,9 @@ integrity sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w== "@types/react-virtualized@^9.21.30": - version "9.22.0" - resolved "https://registry.yarnpkg.com/@types/react-virtualized/-/react-virtualized-9.22.0.tgz#2ff9b3692fa04a429df24ffc7d181d9f33b3831d" - integrity sha512-JL/YCCFZ123za//cj10Apk54F0UGFMrjOE0QHTuXt1KBMFrzLOGv9/x6Uc/pZ0Gaf4o6w61Fostvlw0DwuPXig== + version "9.22.2" + resolved "https://registry.yarnpkg.com/@types/react-virtualized/-/react-virtualized-9.22.2.tgz#97674f050a85d0f7aab827b3d894f3f1b237922a" + integrity sha512-0Eg/ME3OHYWGxs+/n4VelfYrhXssireZaa1Uqj5SEkTpSaBu5ctFGOCVxcOqpGXRiEdrk/7uho9tlZaryCIjHA== dependencies: "@types/prop-types" "*" "@types/react" "*" From 8c42b0bed89031d347c58b4c3fa537920509a25c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 14:46:16 +0000 Subject: [PATCH 030/458] Update stylelint (#29419) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 131 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 73 insertions(+), 58 deletions(-) diff --git a/yarn.lock b/yarn.lock index 03138dd059..dc84033b50 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1986,10 +1986,10 @@ resolved "https://registry.yarnpkg.com/@jsonjoy.com/util/-/util-1.5.0.tgz#6008e35b9d9d8ee27bc4bfaa70c8cbf33a537b4c" integrity sha512-ojoNsrIuPI9g6o8UxhraZQSyF2ByJanAY4cTFbc8Mf2AXEF4aQRGY1dJxyJpuyav8r9FGflEt/Ff3u5Nt6YMPA== -"@keyv/serialize@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@keyv/serialize/-/serialize-1.0.2.tgz#72507c4be94d8914434a4aa80661f8ac6131967f" - integrity sha512-+E/LyaAeuABniD/RvUezWVXKpeuvwLEA9//nE9952zBaOdBd2mQ3pPoM8cUe2X6IcMByfuSLzmYqnYshG60+HQ== +"@keyv/serialize@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@keyv/serialize/-/serialize-1.0.3.tgz#e0fe3710e2a379cb0490cd41e5a5ffa2bab58bf6" + integrity sha512-qnEovoOp5Np2JDGonIDL6Ayihw0RhnRh6vxPuHo4RDn1UOzwEo4AeIfpL6UGIrsceWrCMiVPgwRjbHu4vYFc3g== dependencies: buffer "^6.0.3" @@ -4513,13 +4513,13 @@ bytes@3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -cacheable@^1.8.8: - version "1.8.8" - resolved "https://registry.yarnpkg.com/cacheable/-/cacheable-1.8.8.tgz#d105f6de41811e42acfa1327718f955794f879a6" - integrity sha512-OE1/jlarWxROUIpd0qGBSKFLkNsotY8pt4GeiVErUYh/NUeTNrT+SBksUgllQv4m6a0W/VZsLuiHb88maavqEw== +cacheable@^1.8.9: + version "1.8.9" + resolved "https://registry.yarnpkg.com/cacheable/-/cacheable-1.8.9.tgz#f5498999567ae1015761d805bd8bbecd8393fbd4" + integrity sha512-FicwAUyWnrtnd4QqYAoRlNs44/a1jTL7XDKqm5gJ90wz1DQPlC7U2Rd1Tydpv+E7WAr4sQHuw8Q8M3nZMAyecQ== dependencies: - hookified "^1.7.0" - keyv "^5.2.3" + hookified "^1.7.1" + keyv "^5.3.1" call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1: version "1.0.1" @@ -6410,13 +6410,20 @@ fastest-levenshtein@1.0.16, fastest-levenshtein@^1.0.12, fastest-levenshtein@^1. resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== -fastq@^1.15.0, fastq@^1.6.0: +fastq@^1.15.0: version "1.19.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.0.tgz#a82c6b7c2bb4e44766d865f07997785fecfdcb89" integrity sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA== dependencies: reusify "^1.0.4" +fastq@^1.6.0: + version "1.19.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" + integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== + dependencies: + reusify "^1.0.4" + faye-websocket@^0.11.3: version "0.11.4" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" @@ -6464,12 +6471,12 @@ fflate@^0.4.8: resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.4.8.tgz#f90b82aefbd8ac174213abb338bd7ef848f0f5ae" integrity sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA== -file-entry-cache@^10.0.5: - version "10.0.6" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-10.0.6.tgz#1fc49c38231b56e792c65222c0aa519d40b5db55" - integrity sha512-0wvv16mVo9nN0Md3k7DMjgAPKG/TY4F/gYMBVb/wMThFRJvzrpaqBFqF6km9wf8QfYTN+mNg5aeaBLfy8k35uA== +file-entry-cache@^10.0.6: + version "10.0.7" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-10.0.7.tgz#e0ac34d4b8c44bea8a0a27ceb4dae982f2d32749" + integrity sha512-txsf5fu3anp2ff3+gOJJzRImtrtm/oa9tYLN0iTuINZ++EyVR/nRrg2fKYwvG/pXDofcrvvb0scEbX3NyW/COw== dependencies: - flat-cache "^6.1.6" + flat-cache "^6.1.7" file-entry-cache@^6.0.1: version "6.0.1" @@ -6569,14 +6576,14 @@ flat-cache@^3.0.4: keyv "^4.5.3" rimraf "^3.0.2" -flat-cache@^6.1.6: - version "6.1.6" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-6.1.6.tgz#62a94ba475297ec742d6c3a2be6516a96d311c9e" - integrity sha512-F+CKgSwp0pzLx67u+Zy1aCueVWFAHWbXepvXlZ+bWVTaASbm5SyCnSJ80Fp1ePEmS57wU+Bf6cx6525qtMZ4lQ== +flat-cache@^6.1.7: + version "6.1.7" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-6.1.7.tgz#c04b08316739ad7ef997e1b9ea363443fc2fcb38" + integrity sha512-qwZ4xf1v1m7Rc9XiORly31YaChvKt6oNVHuqqZcoED/7O+ToyNVGobKsIAopY9ODcWpEDKEBAbrSOCBHtNQvew== dependencies: - cacheable "^1.8.8" - flatted "^3.3.2" - hookified "^1.7.0" + cacheable "^1.8.9" + flatted "^3.3.3" + hookified "^1.7.1" flat@^5.0.2: version "5.0.2" @@ -6588,10 +6595,10 @@ flatted@^3.2.9: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== -flatted@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.2.tgz#adba1448a9841bec72b42c532ea23dbbedef1a27" - integrity sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA== +flatted@^3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" + integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== focus-lock@^1.3.6: version "1.3.6" @@ -7032,10 +7039,10 @@ hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: dependencies: react-is "^16.7.0" -hookified@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/hookified/-/hookified-1.7.0.tgz#d1eb2a1d099fd4eeb3c43e5f75f3fe2ae82aae13" - integrity sha512-XQdMjqC1AyeOzfs+17cnIk7Wdfu1hh2JtcyNfBf5u9jHrT3iZUlGHxLTntFBuk5lwkqJ6l3+daeQdHK5yByHVA== +hookified@^1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/hookified/-/hookified-1.7.1.tgz#b08228173e06e9e8767bae1dffb216b8c6171b41" + integrity sha512-OXcdHsXeOiD7OJ5zvWj8Oy/6RCdLwntAX+wUrfemNcMGn6sux4xbEHi2QXwqePYhjQ/yvxxq2MvCRirdlHscBw== hosted-git-info@^2.1.4: version "2.8.9" @@ -8361,12 +8368,12 @@ keyv@^4.5.3: dependencies: json-buffer "3.0.1" -keyv@^5.2.3: - version "5.2.3" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-5.2.3.tgz#32db1a4aa8d05e2b8ab82688a57ddc5d2184a25c" - integrity sha512-AGKecUfzrowabUv0bH1RIR5Vf7w+l4S3xtQAypKaUpTdIR1EbrAcTxHCrpo9Q+IWeUlFE2palRtgIQcgm+PQJw== +keyv@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-5.3.1.tgz#d3acebeecedafd4bf2b929e8866bcd79db071f1e" + integrity sha512-13hQT2q2VIwOoaJdJa7nY3J8UVbYtMTJFHnwm9LI+SaQRfUiM6Em9KZeOVTCKbMnGcRIL3NSUFpAdjZCq24nLQ== dependencies: - "@keyv/serialize" "^1.0.2" + "@keyv/serialize" "^1.0.3" kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" @@ -8805,9 +8812,9 @@ mdn-data@2.12.2: integrity sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA== mdn-data@^2.15.0: - version "2.15.0" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.15.0.tgz#8d8bc0d9a463edf4296c418a8b49d3a8b2c686fb" - integrity sha512-KIrS0lFPOqA4DgeO16vI5fkAsy8p++WBlbXtB5P1EQs8ubBgguAInNd1DnrCeTRfGchY0kgThgDOOIPyOLH2dQ== + version "2.17.0" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.17.0.tgz#6978ea53c38228a6cb2dae71bff652bc02ce5585" + integrity sha512-VT5LJBdLRI+cc3DPXJD89PGwI8yXuciE5gZJoSPnH4yeGzMPqxwkZv3BjFSoaWpmOlJNBhVT6HKeQPcZKlNEvA== mdurl@^1.0.1, mdurl@~1.0.1: version "1.0.1" @@ -10183,6 +10190,14 @@ postcss-selector-parser@^7.0.0: cssesc "^3.0.0" util-deprecate "^1.0.2" +postcss-selector-parser@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz#4d6af97eba65d73bc4d84bcb343e865d7dd16262" + integrity sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + postcss-simple-vars@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/postcss-simple-vars/-/postcss-simple-vars-7.0.1.tgz#836b3097a54dcd13dbd3c36a5dbdd512fad2954c" @@ -10226,10 +10241,10 @@ postcss@^8.3.11, postcss@^8.4.33, postcss@^8.4.38: picocolors "^1.1.0" source-map-js "^1.2.1" -postcss@^8.5.1: - version "8.5.1" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.1.tgz#e2272a1f8a807fafa413218245630b5db10a3214" - integrity sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ== +postcss@^8.5.3: + version "8.5.3" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.3.tgz#1463b6f1c7fb16fe258736cba29a2de35237eafb" + integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A== dependencies: nanoid "^3.3.8" picocolors "^1.1.1" @@ -10920,9 +10935,9 @@ retry@^0.13.1: integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + version "1.1.0" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" + integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== rfc4648@^1.4.0: version "1.5.4" @@ -11705,9 +11720,9 @@ stylelint-config-standard@^37.0.0: stylelint-config-recommended "^15.0.0" stylelint-scss@^6.0.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-6.11.0.tgz#ec842bf3c5fe7c726c924f6c6ffe27e662c38c48" - integrity sha512-AvJ6LVzz2iXHxPlPTR9WVy73FC/vmohH54VySNlCKX1NIXNAeuzy/VbIkMJLMyw/xKYqkgY4kAgB+qy5BfCaCg== + version "6.11.1" + resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-6.11.1.tgz#03860aab250112825b2deb77ca7ff1e2ba3a5414" + integrity sha512-e4rYo0UY+BIMtGeGanghrvHTjcryxgZbyFxUedp8dLFqC4P70aawNdYjRrQxbnKhu3BNr4+lt5e/53tcKXiwFA== dependencies: css-tree "^3.0.1" is-plain-object "^5.0.0" @@ -11715,7 +11730,7 @@ stylelint-scss@^6.0.0: mdn-data "^2.15.0" postcss-media-query-parser "^0.2.3" postcss-resolve-nested-selector "^0.1.6" - postcss-selector-parser "^7.0.0" + postcss-selector-parser "^7.1.0" postcss-value-parser "^4.2.0" stylelint-value-no-unknown-custom-properties@^6.0.1: @@ -11727,9 +11742,9 @@ stylelint-value-no-unknown-custom-properties@^6.0.1: resolve "^1.22.8" stylelint@^16.13.0: - version "16.14.1" - resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-16.14.1.tgz#32d3df8c5ce7ba0275ce6a4a966b6099d7a828e3" - integrity sha512-oqCL7AC3786oTax35T/nuLL8p2C3k/8rHKAooezrPGRvUX0wX+qqs5kMWh5YYT4PHQgVDobHT4tw55WgpYG6Sw== + version "16.15.0" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-16.15.0.tgz#a561cd50ad468cc4898f5c57cc1f223287fdea59" + integrity sha512-OK6Rs7EPdcdmjqiDycadZY4fw3f5/TC1X6/tGjnF3OosbwCeNs7nG+79MCAtjEg7ckwqTJTsku08e0Rmaz5nUw== dependencies: "@csstools/css-parser-algorithms" "^3.0.4" "@csstools/css-tokenizer" "^3.0.3" @@ -11744,7 +11759,7 @@ stylelint@^16.13.0: debug "^4.3.7" fast-glob "^3.3.3" fastest-levenshtein "^1.0.16" - file-entry-cache "^10.0.5" + file-entry-cache "^10.0.6" global-modules "^2.0.0" globby "^11.1.0" globjoin "^0.1.4" @@ -11758,14 +11773,14 @@ stylelint@^16.13.0: micromatch "^4.0.8" normalize-path "^3.0.0" picocolors "^1.1.1" - postcss "^8.5.1" + postcss "^8.5.3" postcss-resolve-nested-selector "^0.1.6" postcss-safe-parser "^7.0.1" - postcss-selector-parser "^7.0.0" + postcss-selector-parser "^7.1.0" postcss-value-parser "^4.2.0" resolve-from "^5.0.0" string-width "^4.2.3" - supports-hyperlinks "^3.1.0" + supports-hyperlinks "^3.2.0" svg-tags "^1.0.0" table "^6.9.0" write-file-atomic "^5.0.1" @@ -11808,7 +11823,7 @@ supports-color@^8.0.0, supports-color@^8.1.1: dependencies: has-flag "^4.0.0" -supports-hyperlinks@^3.1.0: +supports-hyperlinks@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz#b8e485b179681dea496a1e7abdf8985bd3145461" integrity sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig== From 20ac69f3794f34981e3d25009b1b7dce1d1d07d2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 14:48:00 +0000 Subject: [PATCH 031/458] Update guibranco/github-status-action-v2 digest to 5ef6e17 (#29409) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8109500ea6..710e996b39 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -104,7 +104,7 @@ jobs: - name: Skip SonarCloud in merge queue if: github.event_name == 'merge_group' || inputs.disable_coverage == 'true' - uses: guibranco/github-status-action-v2@7ca807c2ba3401be532d29a876b93262108099fb + uses: guibranco/github-status-action-v2@5ef6e175c333bc629f3718b083c8a2ff6e0bbfbc with: authToken: ${{ secrets.GITHUB_TOKEN }} state: success From 4776a9971d0df544b67b92e6e3ce8716552f910e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 14:48:06 +0000 Subject: [PATCH 032/458] Update typescript-eslint monorepo to v8.25.0 (#29420) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 99 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 72 insertions(+), 27 deletions(-) diff --git a/yarn.lock b/yarn.lock index dc84033b50..19101056a7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3395,29 +3395,29 @@ "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@^8.19.0": - version "8.24.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.24.1.tgz#d104c2a6212304c649105b18af2c110b4a1dd4ae" - integrity sha512-ll1StnKtBigWIGqvYDVuDmXJHVH4zLVot1yQ4fJtLpL7qacwkxJc1T0bptqw+miBQ/QfUbhl1TcQ4accW5KUyA== + version "8.26.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.0.tgz#7e880faf91f89471c30c141951e15f0eb3a0599e" + integrity sha512-cLr1J6pe56zjKYajK6SSSre6nl1Gj6xDp1TY0trpgPzjVbgDwd09v2Ws37LABxzkicmUjhEeg/fAUjPJJB1v5Q== dependencies: "@eslint-community/regexpp" "^4.10.0" - "@typescript-eslint/scope-manager" "8.24.1" - "@typescript-eslint/type-utils" "8.24.1" - "@typescript-eslint/utils" "8.24.1" - "@typescript-eslint/visitor-keys" "8.24.1" + "@typescript-eslint/scope-manager" "8.26.0" + "@typescript-eslint/type-utils" "8.26.0" + "@typescript-eslint/utils" "8.26.0" + "@typescript-eslint/visitor-keys" "8.26.0" graphemer "^1.4.0" ignore "^5.3.1" natural-compare "^1.4.0" ts-api-utils "^2.0.1" "@typescript-eslint/parser@^8.19.0": - version "8.24.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.24.1.tgz#67965c2d2ddd7eadb2f094c395695db8334ef9a2" - integrity sha512-Tqoa05bu+t5s8CTZFaGpCH2ub3QeT9YDkXbPd3uQ4SfsLoh1/vv2GEYAioPoxCWJJNsenXlC88tRjwoHNts1oQ== + version "8.26.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.26.0.tgz#9b4d2198e89f64fb81e83167eedd89a827d843a9" + integrity sha512-mNtXP9LTVBy14ZF3o7JG69gRPBK/2QWtQd0j0oH26HcY/foyJJau6pNUez7QrM5UHnSvwlQcJXKsk0I99B9pOA== dependencies: - "@typescript-eslint/scope-manager" "8.24.1" - "@typescript-eslint/types" "8.24.1" - "@typescript-eslint/typescript-estree" "8.24.1" - "@typescript-eslint/visitor-keys" "8.24.1" + "@typescript-eslint/scope-manager" "8.26.0" + "@typescript-eslint/types" "8.26.0" + "@typescript-eslint/typescript-estree" "8.26.0" + "@typescript-eslint/visitor-keys" "8.26.0" debug "^4.3.4" "@typescript-eslint/scope-manager@8.23.0": @@ -3436,13 +3436,21 @@ "@typescript-eslint/types" "8.24.1" "@typescript-eslint/visitor-keys" "8.24.1" -"@typescript-eslint/type-utils@8.24.1": - version "8.24.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.24.1.tgz#99113e1df63d1571309d87eef68967344c78dd65" - integrity sha512-/Do9fmNgCsQ+K4rCz0STI7lYB4phTtEXqqCAs3gZW0pnK7lWNkvWd5iW545GSmApm4AzmQXmSqXPO565B4WVrw== +"@typescript-eslint/scope-manager@8.26.0": + version "8.26.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.26.0.tgz#b06623fad54a3a77fadab5f652ef75ed3780b545" + integrity sha512-E0ntLvsfPqnPwng8b8y4OGuzh/iIOm2z8U3S9zic2TeMLW61u5IH2Q1wu0oSTkfrSzwbDJIB/Lm8O3//8BWMPA== dependencies: - "@typescript-eslint/typescript-estree" "8.24.1" - "@typescript-eslint/utils" "8.24.1" + "@typescript-eslint/types" "8.26.0" + "@typescript-eslint/visitor-keys" "8.26.0" + +"@typescript-eslint/type-utils@8.26.0": + version "8.26.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.26.0.tgz#9ee8cc98184b5f66326578de9c097edc89da6f68" + integrity sha512-ruk0RNChLKz3zKGn2LwXuVoeBcUMh+jaqzN461uMMdxy5H9epZqIBtYj7UiPXRuOpaALXGbmRuZQhmwHhaS04Q== + dependencies: + "@typescript-eslint/typescript-estree" "8.26.0" + "@typescript-eslint/utils" "8.26.0" debug "^4.3.4" ts-api-utils "^2.0.1" @@ -3456,6 +3464,11 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.24.1.tgz#8777a024f3afc4ace5e48f9a804309c6dd38f95a" integrity sha512-9kqJ+2DkUXiuhoiYIUvIYjGcwle8pcPpdlfkemGvTObzgmYfJ5d0Qm6jwb4NBXP9W1I5tss0VIAnWFumz3mC5A== +"@typescript-eslint/types@8.26.0": + version "8.26.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.26.0.tgz#c4e93a8faf3a38a8d8adb007dc7834f1c89ee7bf" + integrity sha512-89B1eP3tnpr9A8L6PZlSjBvnJhWXtYfZhECqlBl1D9Lme9mHO6iWlsprBtVenQvY1HMhax1mWOjhtL3fh/u+pA== + "@typescript-eslint/typescript-estree@8.23.0": version "8.23.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.23.0.tgz#f633ef08efa656e386bc44b045ffcf9537cc6924" @@ -3484,15 +3497,29 @@ semver "^7.6.0" ts-api-utils "^2.0.1" -"@typescript-eslint/utils@8.24.1", "@typescript-eslint/utils@^8.13.0": - version "8.24.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.24.1.tgz#08d14eac33cfb3456feeee5a275b8ad3349e52ed" - integrity sha512-OOcg3PMMQx9EXspId5iktsI3eMaXVwlhC8BvNnX6B5w9a4dVgpkQZuU8Hy67TolKcl+iFWq0XX+jbDGN4xWxjQ== +"@typescript-eslint/typescript-estree@8.26.0": + version "8.26.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.26.0.tgz#128972172005a7376e34ed2ecba4e29363b0cad1" + integrity sha512-tiJ1Hvy/V/oMVRTbEOIeemA2XoylimlDQ03CgPPNaHYZbpsc78Hmngnt+WXZfJX1pjQ711V7g0H7cSJThGYfPQ== + dependencies: + "@typescript-eslint/types" "8.26.0" + "@typescript-eslint/visitor-keys" "8.26.0" + debug "^4.3.4" + fast-glob "^3.3.2" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^2.0.1" + +"@typescript-eslint/utils@8.26.0": + version "8.26.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.26.0.tgz#845d20ed8378a5594e6445f54e53b972aee7b3e6" + integrity sha512-2L2tU3FVwhvU14LndnQCA2frYC8JnPDVKyQtWFPf8IYFMt/ykEN1bPolNhNbCVgOmdzTlWdusCTKA/9nKrf8Ig== dependencies: "@eslint-community/eslint-utils" "^4.4.0" - "@typescript-eslint/scope-manager" "8.24.1" - "@typescript-eslint/types" "8.24.1" - "@typescript-eslint/typescript-estree" "8.24.1" + "@typescript-eslint/scope-manager" "8.26.0" + "@typescript-eslint/types" "8.26.0" + "@typescript-eslint/typescript-estree" "8.26.0" "@typescript-eslint/utils@^6.0.0 || ^7.0.0 || ^8.0.0": version "8.23.0" @@ -3504,6 +3531,16 @@ "@typescript-eslint/types" "8.23.0" "@typescript-eslint/typescript-estree" "8.23.0" +"@typescript-eslint/utils@^8.13.0": + version "8.24.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.24.1.tgz#08d14eac33cfb3456feeee5a275b8ad3349e52ed" + integrity sha512-OOcg3PMMQx9EXspId5iktsI3eMaXVwlhC8BvNnX6B5w9a4dVgpkQZuU8Hy67TolKcl+iFWq0XX+jbDGN4xWxjQ== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@typescript-eslint/scope-manager" "8.24.1" + "@typescript-eslint/types" "8.24.1" + "@typescript-eslint/typescript-estree" "8.24.1" + "@typescript-eslint/visitor-keys@8.23.0": version "8.23.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.23.0.tgz#40405fd26a61d23f5f4c2ed0f016a47074781df8" @@ -3520,6 +3557,14 @@ "@typescript-eslint/types" "8.24.1" eslint-visitor-keys "^4.2.0" +"@typescript-eslint/visitor-keys@8.26.0": + version "8.26.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.26.0.tgz#a4876216756c69130ea958df3b77222c2ad95290" + integrity sha512-2z8JQJWAzPdDd51dRQ/oqIJxe99/hoLIqmf8RMCAJQtYDc535W/Jt2+RTP4bP0aKeBG1F65yjIZuczOXCmbWwg== + dependencies: + "@typescript-eslint/types" "8.26.0" + eslint-visitor-keys "^4.2.0" + "@ungap/structured-clone@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" From f1ebd85af1c1a9528a3c3653bc2aa720c9e8c356 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 14:48:57 +0000 Subject: [PATCH 033/458] Update dependency babel-loader to v10 (#29422) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 70 ++++------------------------------------------------ 2 files changed, 6 insertions(+), 66 deletions(-) diff --git a/package.json b/package.json index 2584b34f2f..918a4c6e85 100644 --- a/package.json +++ b/package.json @@ -220,7 +220,7 @@ "@typescript-eslint/eslint-plugin": "^8.19.0", "@typescript-eslint/parser": "^8.19.0", "babel-jest": "^29.0.0", - "babel-loader": "^9.0.0", + "babel-loader": "^10.0.0", "babel-plugin-jsx-remove-data-test-id": "^3.0.0", "blob-polyfill": "^9.0.0", "chokidar": "^4.0.0", diff --git a/yarn.lock b/yarn.lock index 19101056a7..d3ee1370f7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4220,13 +4220,12 @@ babel-jest@^29.0.0, babel-jest@^29.7.0: graceful-fs "^4.2.9" slash "^3.0.0" -babel-loader@^9.0.0: - version "9.2.1" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-9.2.1.tgz#04c7835db16c246dd19ba0914418f3937797587b" - integrity sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA== +babel-loader@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-10.0.0.tgz#b9743714c0e1e084b3e4adef3cd5faee33089977" + integrity sha512-z8jt+EdS61AMw22nSfoNJAZ0vrtmhPRVi6ghL3rCeRZI8cdNYFiV5xeV3HbE7rlZZNmGH8BVccwWt8/ED0QOHA== dependencies: - find-cache-dir "^4.0.0" - schema-utils "^4.0.0" + find-up "^5.0.0" babel-plugin-istanbul@^6.1.1: version "6.1.1" @@ -4879,11 +4878,6 @@ commander@^8.3.0: resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== -common-path-prefix@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" - integrity sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w== - commonmark@^0.31.0: version "0.31.2" resolved "https://registry.yarnpkg.com/commonmark/-/commonmark-0.31.2.tgz#9d8d5439c82c9a235154d858a53e1a7965d573a5" @@ -6580,14 +6574,6 @@ finalhandler@1.3.1: statuses "2.0.1" unpipe "~1.0.0" -find-cache-dir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-4.0.0.tgz#a30ee0448f81a3990708f6453633c733e2f6eec2" - integrity sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg== - dependencies: - common-path-prefix "^3.0.0" - pkg-dir "^7.0.0" - find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" @@ -6604,14 +6590,6 @@ find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" -find-up@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-6.3.0.tgz#2abab3d3280b2dc7ac10199ef324c4e002c8c790" - integrity sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw== - dependencies: - locate-path "^7.1.0" - path-exists "^5.0.0" - flat-cache@^3.0.4: version "3.2.0" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" @@ -8602,13 +8580,6 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -locate-path@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-7.2.0.tgz#69cb1779bd90b35ab1e771e1f2f89a202c2a8a8a" - integrity sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA== - dependencies: - p-locate "^6.0.0" - lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" @@ -9386,13 +9357,6 @@ p-limit@^3.0.2, p-limit@^3.1.0: dependencies: yocto-queue "^0.1.0" -p-limit@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-4.0.0.tgz#914af6544ed32bfa54670b061cafcbd04984b644" - integrity sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ== - dependencies: - yocto-queue "^1.0.0" - p-locate@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" @@ -9407,13 +9371,6 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" -p-locate@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-6.0.0.tgz#3da9a49d4934b901089dca3302fa65dc5a05c04f" - integrity sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw== - dependencies: - p-limit "^4.0.0" - p-map@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" @@ -9518,11 +9475,6 @@ path-exists@^4.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== -path-exists@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-5.0.0.tgz#a6aad9489200b21fab31e49cf09277e5116fb9e7" - integrity sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ== - path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -9624,13 +9576,6 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -pkg-dir@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-7.0.0.tgz#8f0c08d6df4476756c5ff29b3282d0bab7517d11" - integrity sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA== - dependencies: - find-up "^6.3.0" - playwright-core@1.50.1, playwright-core@^1.45.1: version "1.50.1" resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.50.1.tgz#6a0484f1f1c939168f40f0ab3828c4a1592c4504" @@ -13064,11 +13009,6 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -yocto-queue@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.1.1.tgz#fef65ce3ac9f8a32ceac5a634f74e17e5b232110" - integrity sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g== - zip-stream@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-6.0.1.tgz#e141b930ed60ccaf5d7fa9c8260e0d1748a2bbfb" From dfdac8ef63f32128cb046ab31a7590634257698e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 14:51:37 +0000 Subject: [PATCH 034/458] Update dependency copy-webpack-plugin to v13 (#29423) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 58 +++++++++++++++++----------------------------------- 2 files changed, 20 insertions(+), 40 deletions(-) diff --git a/package.json b/package.json index 918a4c6e85..6f9e810cc9 100644 --- a/package.json +++ b/package.json @@ -225,7 +225,7 @@ "blob-polyfill": "^9.0.0", "chokidar": "^4.0.0", "concurrently": "^9.0.0", - "copy-webpack-plugin": "^12.0.0", + "copy-webpack-plugin": "^13.0.0", "core-js": "^3.38.1", "cronstrue": "^2.41.0", "css-loader": "^7.0.0", diff --git a/yarn.lock b/yarn.lock index d3ee1370f7..5a848238f6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2603,11 +2603,6 @@ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== -"@sindresorhus/merge-streams@^2.1.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz#719df7fb41766bc143369eaa0dd56d8dc87c9958" - integrity sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg== - "@sinonjs/commons@^3.0.0": version "3.0.1" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" @@ -4968,17 +4963,16 @@ cookie@0.7.1: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9" integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w== -copy-webpack-plugin@^12.0.0: - version "12.0.2" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-12.0.2.tgz#935e57b8e6183c82f95bd937df658a59f6a2da28" - integrity sha512-SNwdBeHyII+rWvee/bTnAYyO8vfVdcSTud4EIb6jcZ8inLeWucJE0DnxXQBjlQ5zlteuuvooGQy3LIyGxhvlOA== +copy-webpack-plugin@^13.0.0: + version "13.0.0" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-13.0.0.tgz#793342576eed76fdbc7936b873eae17aa7a7d9a3" + integrity sha512-FgR/h5a6hzJqATDGd9YG41SeDViH+0bkHn6WNXCi5zKAZkeESeSxLySSsFLHqLEVCh0E+rITmCf0dusXWYukeQ== dependencies: - fast-glob "^3.3.2" glob-parent "^6.0.1" - globby "^14.0.0" normalize-path "^3.0.0" schema-utils "^4.2.0" serialize-javascript "^6.0.2" + tinyglobby "^0.2.12" core-js-compat@^3.38.0, core-js-compat@^3.38.1, core-js-compat@^3.40.0: version "3.40.0" @@ -6482,6 +6476,11 @@ fdir@^6.4.0: resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.2.tgz#ddaa7ce1831b161bc3657bb99cb36e1622702689" integrity sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ== +fdir@^6.4.3: + version "6.4.3" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.3.tgz#011cdacf837eca9b811c89dbb902df714273db72" + integrity sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw== + fetch-mock-jest@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/fetch-mock-jest/-/fetch-mock-jest-1.5.1.tgz#0e13df990d286d9239e284f12b279ed509bf53cd" @@ -6941,18 +6940,6 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -globby@^14.0.0: - version "14.0.2" - resolved "https://registry.yarnpkg.com/globby/-/globby-14.0.2.tgz#06554a54ccfe9264e5a9ff8eded46aa1e306482f" - integrity sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw== - dependencies: - "@sindresorhus/merge-streams" "^2.1.0" - fast-glob "^3.3.2" - ignore "^5.2.4" - path-type "^5.0.0" - slash "^5.1.0" - unicorn-magic "^0.1.0" - globjoin@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43" @@ -7260,7 +7247,7 @@ ieee754@^1.1.12, ieee754@^1.1.13, ieee754@^1.2.1: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ignore@^5.1.8, ignore@^5.2.0, ignore@^5.2.4, ignore@^5.3.1: +ignore@^5.1.8, ignore@^5.2.0, ignore@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== @@ -9526,11 +9513,6 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -path-type@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-5.0.0.tgz#14b01ed7aea7ddf9c7c3f46181d4d04f9c785bb8" - integrity sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg== - pbf@^3.2.1, pbf@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/pbf/-/pbf-3.3.0.tgz#1790f3d99118333cc7f498de816028a346ef367f" @@ -11304,11 +11286,6 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slash@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-5.1.0.tgz#be3adddcdf09ac38eebe8dcdc7b1a57a75b095ce" - integrity sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg== - slice-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" @@ -12021,6 +11998,14 @@ tiny-invariant@^1.0.6: resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127" integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg== +tinyglobby@^0.2.12: + version "0.2.12" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.12.tgz#ac941a42e0c5773bd0b5d08f32de82e74a1a61b5" + integrity sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww== + dependencies: + fdir "^6.4.3" + picomatch "^4.0.2" + tinyglobby@^0.2.7: version "0.2.9" resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.9.tgz#6baddd1b0fe416403efb0dd40442c7d7c03c1c66" @@ -12321,11 +12306,6 @@ unicode-property-aliases-ecmascript@^2.0.0: resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== -unicorn-magic@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/unicorn-magic/-/unicorn-magic-0.1.0.tgz#1bb9a51c823aaf9d73a8bfcd3d1a23dde94b0ce4" - integrity sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ== - universalify@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" From 1770b94ed3f05cdd5543129e0c568408411df078 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 15:01:20 +0000 Subject: [PATCH 035/458] Update dependency typescript to v5.8.2 (#29417) * Update dependency typescript to v5.8.2 * Fix types Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --- package.json | 2 +- src/utils/location/locationEventGeoUri.ts | 2 +- .../views/settings/tabs/user/SessionManagerTab-test.tsx | 1 + test/unit-tests/utils/oidc/authorize-test.ts | 1 + yarn.lock | 8 ++++---- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 6f9e810cc9..0ec4002e84 100644 --- a/package.json +++ b/package.json @@ -290,7 +290,7 @@ "terser-webpack-plugin": "^5.3.9", "testcontainers": "^10.16.0", "ts-node": "^10.9.1", - "typescript": "5.7.3", + "typescript": "5.8.2", "util": "^0.12.5", "web-streams-polyfill": "^4.0.0", "webpack": "^5.89.0", diff --git a/src/utils/location/locationEventGeoUri.ts b/src/utils/location/locationEventGeoUri.ts index 54b463da3c..7648120102 100644 --- a/src/utils/location/locationEventGeoUri.ts +++ b/src/utils/location/locationEventGeoUri.ts @@ -18,5 +18,5 @@ export const locationEventGeoUri = (mxEvent: MatrixEvent): string => { // https://github.com/matrix-org/matrix-doc/issues/3516 const content = mxEvent.getContent(); const loc = M_LOCATION.findIn(content) as { uri?: string }; - return loc ? loc.uri : content["geo_uri"]; + return loc?.uri ?? content["geo_uri"]; }; diff --git a/test/unit-tests/components/views/settings/tabs/user/SessionManagerTab-test.tsx b/test/unit-tests/components/views/settings/tabs/user/SessionManagerTab-test.tsx index 625aafe731..171fa4b827 100644 --- a/test/unit-tests/components/views/settings/tabs/user/SessionManagerTab-test.tsx +++ b/test/unit-tests/components/views/settings/tabs/user/SessionManagerTab-test.tsx @@ -263,6 +263,7 @@ describe("", () => { }); afterAll(() => { + // @ts-expect-error window.location = realWindowLocation; }); diff --git a/test/unit-tests/utils/oidc/authorize-test.ts b/test/unit-tests/utils/oidc/authorize-test.ts index cade0c42ca..3ccc77e633 100644 --- a/test/unit-tests/utils/oidc/authorize-test.ts +++ b/test/unit-tests/utils/oidc/authorize-test.ts @@ -65,6 +65,7 @@ describe("OIDC authorization", () => { }); afterAll(() => { + // @ts-expect-error window.location = realWindowLocation; }); diff --git a/yarn.lock b/yarn.lock index 5a848238f6..a3679463b5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12231,10 +12231,10 @@ typed-array-length@^1.0.7: possible-typed-array-names "^1.0.0" reflect.getprototypeof "^1.0.6" -typescript@5.7.3: - version "5.7.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.3.tgz#919b44a7dbb8583a9b856d162be24a54bf80073e" - integrity sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw== +typescript@5.8.2: + version "5.8.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.2.tgz#8170b3702f74b79db2e5a96207c15e65807999e4" + integrity sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ== ua-parser-js@^1.0.2: version "1.0.40" From 9d8efacede71e3057383684446df3bde21e7bb1a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 15:36:57 +0000 Subject: [PATCH 036/458] Update dependency @vector-im/matrix-wysiwyg to v2.38.2 (#28708) * Update dependency @vector-im/matrix-wysiwyg to v2.38.2 * Fix types Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --- package.json | 2 +- .../rooms/wysiwyg_composer/components/Editor.tsx | 2 +- .../wysiwyg_composer/hooks/useSetCursorPosition.ts | 2 +- yarn.lock | 12 ++++++------ 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 0ec4002e84..666760d407 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "@types/react-virtualized": "^9.21.30", "@vector-im/compound-design-tokens": "^4.0.0", "@vector-im/compound-web": "^7.6.4", - "@vector-im/matrix-wysiwyg": "2.38.0", + "@vector-im/matrix-wysiwyg": "2.38.2", "@zxcvbn-ts/core": "^3.0.4", "@zxcvbn-ts/language-common": "^3.0.4", "@zxcvbn-ts/language-en": "^3.0.2", diff --git a/src/components/views/rooms/wysiwyg_composer/components/Editor.tsx b/src/components/views/rooms/wysiwyg_composer/components/Editor.tsx index e65bf278b6..1d9c332899 100644 --- a/src/components/views/rooms/wysiwyg_composer/components/Editor.tsx +++ b/src/components/views/rooms/wysiwyg_composer/components/Editor.tsx @@ -22,7 +22,7 @@ interface EditorProps { } export const Editor = memo( - forwardRef(function Editor( + forwardRef(function Editor( { disabled, placeholder, leftComponent, rightComponent }: EditorProps, ref, ) { diff --git a/src/components/views/rooms/wysiwyg_composer/hooks/useSetCursorPosition.ts b/src/components/views/rooms/wysiwyg_composer/hooks/useSetCursorPosition.ts index 5b164051eb..408c24ea7c 100644 --- a/src/components/views/rooms/wysiwyg_composer/hooks/useSetCursorPosition.ts +++ b/src/components/views/rooms/wysiwyg_composer/hooks/useSetCursorPosition.ts @@ -10,7 +10,7 @@ import { type RefObject, useEffect } from "react"; import { setCursorPositionAtTheEnd } from "./utils"; -export function useSetCursorPosition(disabled: boolean, ref: RefObject): void { +export function useSetCursorPosition(disabled: boolean, ref: RefObject): void { useEffect(() => { if (ref.current && !disabled) { setCursorPositionAtTheEnd(ref.current); diff --git a/yarn.lock b/yarn.lock index a3679463b5..063b68e02a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3585,15 +3585,15 @@ classnames "^2.5.1" vaul "^1.0.0" -"@vector-im/matrix-wysiwyg-wasm@link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.0-af862ffd231dc0a6b8d6f2cb3601e68456c0ff24-integrity/node_modules/bindings/wysiwyg-wasm": +"@vector-im/matrix-wysiwyg-wasm@link:../../bindings/wysiwyg-wasm": version "0.0.0" -"@vector-im/matrix-wysiwyg@2.38.0": - version "2.38.0" - resolved "https://registry.yarnpkg.com/@vector-im/matrix-wysiwyg/-/matrix-wysiwyg-2.38.0.tgz#af862ffd231dc0a6b8d6f2cb3601e68456c0ff24" - integrity sha512-cMEVicFYVzFxuSyWON0aVGjAJMcgJZ+LxuLTEp8EGuu8cRacuh0RN5rapb11YVZygzFvE7X1cMedJ/fKd5vRLA== +"@vector-im/matrix-wysiwyg@2.38.2": + version "2.38.2" + resolved "https://registry.yarnpkg.com/@vector-im/matrix-wysiwyg/-/matrix-wysiwyg-2.38.2.tgz#3fa19a2a17fd12d955ef1e14fd63aecbcf3b95e8" + integrity sha512-TUnLPgZ8/zGUccQZxjIP3MVHjqybgV4u0r6kXibs35wlXgomXjwcN5gchl3FpgGkiHbi8g3D2ao0oHaqi2GaIw== dependencies: - "@vector-im/matrix-wysiwyg-wasm" "link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.0-af862ffd231dc0a6b8d6f2cb3601e68456c0ff24-integrity/node_modules/bindings/wysiwyg-wasm" + "@vector-im/matrix-wysiwyg-wasm" "link:../../bindings/wysiwyg-wasm" "@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1": version "1.14.1" From 56c7fc1948923b4b3f3507799e725ac16bcf8018 Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Tue, 4 Mar 2025 11:40:35 -0500 Subject: [PATCH 037/458] Prevent user from accidentally triggering multiple identity resets (#29388) * prevent user from accidentally triggering multiple identity resets * apply changes from review and update to latest design * Use a CSS class and compound variable * update snapshot * Update test/unit-tests/components/views/settings/encryption/ResetIdentityPanel-test.tsx --------- Co-authored-by: Richard van der Hoff Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- res/css/_components.pcss | 1 + .../encryption/_ResetIdentityPanel.pcss | 11 + .../encryption/ResetIdentityPanel.tsx | 32 ++- src/i18n/strings/en_EN.json | 2 + .../encryption/ResetIdentityPanel-test.tsx | 13 +- .../ResetIdentityPanel-test.tsx.snap | 203 ++++++++++++++++++ .../EncryptionUserSettingsTab-test.tsx.snap | 1 + 7 files changed, 256 insertions(+), 7 deletions(-) create mode 100644 res/css/views/settings/encryption/_ResetIdentityPanel.pcss diff --git a/res/css/_components.pcss b/res/css/_components.pcss index 9012960195..cd260ca3aa 100644 --- a/res/css/_components.pcss +++ b/res/css/_components.pcss @@ -362,6 +362,7 @@ @import "./views/settings/encryption/_EncryptionCard.pcss"; @import "./views/settings/encryption/_EncryptionCardEmphasisedContent.pcss"; @import "./views/settings/encryption/_RecoveryPanelOutOfSync.pcss"; +@import "./views/settings/encryption/_ResetIdentityPanel.pcss"; @import "./views/settings/tabs/_SettingsBanner.pcss"; @import "./views/settings/tabs/_SettingsIndent.pcss"; @import "./views/settings/tabs/_SettingsSection.pcss"; diff --git a/res/css/views/settings/encryption/_ResetIdentityPanel.pcss b/res/css/views/settings/encryption/_ResetIdentityPanel.pcss new file mode 100644 index 0000000000..8318d6d91c --- /dev/null +++ b/res/css/views/settings/encryption/_ResetIdentityPanel.pcss @@ -0,0 +1,11 @@ +/* + * Copyright 2024 New Vector 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. + */ + +// Red text for the "Do not close this window" warning +.mx_ResetIdentityPanel_warning { + color: var(--cpd-color-text-critical-primary); +} diff --git a/src/components/views/settings/encryption/ResetIdentityPanel.tsx b/src/components/views/settings/encryption/ResetIdentityPanel.tsx index 747b22fd59..6c25985a22 100644 --- a/src/components/views/settings/encryption/ResetIdentityPanel.tsx +++ b/src/components/views/settings/encryption/ResetIdentityPanel.tsx @@ -5,11 +5,11 @@ * Please see LICENSE files in the repository root for full details. */ -import { Breadcrumb, Button, VisualList, VisualListItem } from "@vector-im/compound-web"; +import { Breadcrumb, Button, InlineSpinner, VisualList, VisualListItem } from "@vector-im/compound-web"; import CheckIcon from "@vector-im/compound-design-tokens/assets/web/icons/check"; import InfoIcon from "@vector-im/compound-design-tokens/assets/web/icons/info"; import ErrorIcon from "@vector-im/compound-design-tokens/assets/web/icons/error-solid"; -import React, { type MouseEventHandler } from "react"; +import React, { useState, type MouseEventHandler } from "react"; import { _t } from "../../../../languageHandler"; import { EncryptionCard } from "./EncryptionCard"; @@ -44,6 +44,10 @@ interface ResetIdentityPanelProps { export function ResetIdentityPanel({ onCancelClick, onFinish, variant }: ResetIdentityPanelProps): JSX.Element { const matrixClient = useMatrixClientContext(); + // After the user clicks "Continue", we disable the button so it can't be + // clicked again, and warn the user not to close the window. + const [inProgress, setInProgress] = useState(false); + return ( <> - + {inProgress ? ( + + + {_t("settings|encryption|advanced|do_not_close_warning")} + + + ) : ( + + )} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 624beab0b8..03626aab4e 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2479,12 +2479,14 @@ "breadcrumb_title_forgot": "Forgot your recovery key? You’ll need to reset your identity.", "breadcrumb_warning": "Only do this if you believe your account has been compromised.", "details_title": "Encryption details", + "do_not_close_warning": "Do not close this window until the reset is finished", "export_keys": "Export keys", "import_keys": "Import keys", "other_people_device_description": "By default in encrypted rooms, do not send encrypted messages to anyone until you’ve verified them", "other_people_device_label": "Never send encrypted messages to unverified devices", "other_people_device_title": "Other people’s devices", "reset_identity": "Reset cryptographic identity", + "reset_in_progress": "Reset in progress...", "session_id": "Session ID:", "session_key": "Session key:", "title": "Advanced" diff --git a/test/unit-tests/components/views/settings/encryption/ResetIdentityPanel-test.tsx b/test/unit-tests/components/views/settings/encryption/ResetIdentityPanel-test.tsx index 7b3095b5b4..e331e59824 100644 --- a/test/unit-tests/components/views/settings/encryption/ResetIdentityPanel-test.tsx +++ b/test/unit-tests/components/views/settings/encryption/ResetIdentityPanel-test.tsx @@ -7,6 +7,7 @@ import React from "react"; import { type MatrixClient } from "matrix-js-sdk/src/matrix"; +import { sleep, defer } from "matrix-js-sdk/src/utils"; import { render, screen } from "jest-matrix-react"; import userEvent from "@testing-library/user-event"; @@ -30,7 +31,17 @@ describe("", () => { ); expect(asFragment()).toMatchSnapshot(); - await user.click(screen.getByRole("button", { name: "Continue" })); + // We need to pause the reset so that we can check that it's providing + // feedback to the user that something is happening. + const { promise: resetEncryptionPromise, resolve: resolveResetEncryption } = defer(); + jest.spyOn(matrixClient.getCrypto()!, "resetEncryption").mockReturnValue(resetEncryptionPromise); + + const continueButton = screen.getByRole("button", { name: "Continue" }); + await user.click(continueButton); + expect(asFragment()).toMatchSnapshot(); + resolveResetEncryption!(); + await sleep(0); + expect(matrixClient.getCrypto()!.resetEncryption).toHaveBeenCalled(); expect(onFinish).toHaveBeenCalled(); }); diff --git a/test/unit-tests/components/views/settings/encryption/__snapshots__/ResetIdentityPanel-test.tsx.snap b/test/unit-tests/components/views/settings/encryption/__snapshots__/ResetIdentityPanel-test.tsx.snap index ce4f8b16ab..bd872eec87 100644 --- a/test/unit-tests/components/views/settings/encryption/__snapshots__/ResetIdentityPanel-test.tsx.snap +++ b/test/unit-tests/components/views/settings/encryption/__snapshots__/ResetIdentityPanel-test.tsx.snap @@ -159,6 +159,7 @@ exports[` should display the 'forgot recovery key' variant class="mx_EncryptionCard_buttons" >
`; + +exports[` should reset the encryption when the continue button is clicked 2`] = ` + + +
+
+
+ + + +
+

+ Are you sure you want to reset your identity? +

+
+
+
    +
  • + + Your account details, contacts, preferences, and chat list will be kept +
  • +
  • + + You will lose any message history that’s stored only on the server +
  • +
  • + + You will need to verify all your existing devices and contacts again +
  • +
+ + Only do this if you believe your account has been compromised. + +
+
+ +
+ + Do not close this window until the reset is finished + +
+
+
+
+`; diff --git a/test/unit-tests/components/views/settings/tabs/user/__snapshots__/EncryptionUserSettingsTab-test.tsx.snap b/test/unit-tests/components/views/settings/tabs/user/__snapshots__/EncryptionUserSettingsTab-test.tsx.snap index 5268748d66..c8e6701e0d 100644 --- a/test/unit-tests/components/views/settings/tabs/user/__snapshots__/EncryptionUserSettingsTab-test.tsx.snap +++ b/test/unit-tests/components/views/settings/tabs/user/__snapshots__/EncryptionUserSettingsTab-test.tsx.snap @@ -333,6 +333,7 @@ exports[` should display the reset identity panel w class="mx_EncryptionCard_buttons" >
+
+
+
+
+
+
+ Loading… +
+   +
+
+
+
+
+
{ }); it("opens the room summary", async () => { + const user = userEvent.setup(); const { container } = render(, getWrapper()); - fireEvent.click(getByText(container, ROOM_ID)); + await user.click(getByText(container, ROOM_ID)); expect(setCardSpy).toHaveBeenCalledWith({ phase: RightPanelPhases.RoomSummary }); }); it("shows a face pile for rooms", async () => { + const user = userEvent.setup(); const members = [ { userId: "@me:example.org", @@ -161,33 +164,36 @@ describe("RoomHeader", () => { const facePile = getByLabelText(document.body, "4 members"); expect(facePile).toHaveTextContent("4"); - fireEvent.click(facePile); + await user.click(facePile); expect(setCardSpy).toHaveBeenCalledWith({ phase: RightPanelPhases.MemberList }); }); it("has room info icon that opens the room info panel", async () => { + const user = userEvent.setup(); const { getAllByRole } = render(, getWrapper()); const infoButton = getAllByRole("button", { name: "Room info" })[1]; - fireEvent.click(infoButton); + await user.click(infoButton); expect(setCardSpy).toHaveBeenCalledWith({ phase: RightPanelPhases.RoomSummary }); }); it("opens the thread panel", async () => { + const user = userEvent.setup(); render(, getWrapper()); - fireEvent.click(getByLabelText(document.body, "Threads")); + await user.click(getByLabelText(document.body, "Threads")); expect(setCardSpy).toHaveBeenCalledWith({ phase: RightPanelPhases.ThreadPanel }); }); it("opens the notifications panel", async () => { + const user = userEvent.setup(); jest.spyOn(SettingsStore, "getValue").mockImplementation((name: string): any => { if (name === "feature_notifications") return true; }); render(, getWrapper()); - fireEvent.click(getByLabelText(document.body, "Notifications")); + await user.click(getByLabelText(document.body, "Notifications")); expect(setCardSpy).toHaveBeenCalledWith({ phase: RightPanelPhases.NotificationPanel }); }); @@ -274,6 +280,7 @@ describe("RoomHeader", () => { }); it("you can call when you're two in the room", async () => { + const user = userEvent.setup(); mockRoomMembers(room, 2); render(, getWrapper()); @@ -284,10 +291,10 @@ describe("RoomHeader", () => { const placeCallSpy = jest.spyOn(LegacyCallHandler.instance, "placeCall"); - fireEvent.click(voiceButton); + await user.click(voiceButton); expect(placeCallSpy).toHaveBeenLastCalledWith(room.roomId, CallType.Voice); - fireEvent.click(videoButton); + await user.click(videoButton); expect(placeCallSpy).toHaveBeenLastCalledWith(room.roomId, CallType.Video); }); @@ -332,6 +339,7 @@ describe("RoomHeader", () => { }); it("renders only the video call element", async () => { + const user = userEvent.setup(); mockRoomMembers(room, 3); jest.spyOn(SdkConfig, "get").mockReturnValue({ use_exclusively: true }); // allow element calls @@ -344,9 +352,9 @@ describe("RoomHeader", () => { const videoCallButton = screen.getByRole("button", { name: "Video call" }); expect(videoCallButton).not.toHaveAttribute("aria-disabled", "true"); - const dispatcherSpy = jest.spyOn(dispatcher, "dispatch"); + const dispatcherSpy = jest.spyOn(dispatcher, "dispatch").mockImplementation(); - fireEvent.click(videoCallButton); + await user.click(videoCallButton); expect(dispatcherSpy).toHaveBeenCalledWith(expect.objectContaining({ view_call: true })); }); @@ -366,7 +374,8 @@ describe("RoomHeader", () => { expect(screen.getByRole("button", { name: "Ongoing call" })).toHaveAttribute("aria-disabled", "true"); }); - it("clicking on ongoing (unpinned) call re-pins it", () => { + it("clicking on ongoing (unpinned) call re-pins it", async () => { + const user = userEvent.setup(); mockRoomMembers(room, 3); jest.spyOn(SettingsStore, "getValue").mockImplementation((feature) => feature == UIFeature.Widgets); // allow calls @@ -386,7 +395,7 @@ describe("RoomHeader", () => { const videoButton = screen.getByRole("button", { name: "Video call" }); expect(videoButton).not.toHaveAttribute("aria-disabled", "true"); - fireEvent.click(videoButton); + await user.click(videoButton); expect(spy).toHaveBeenCalledWith(room, widget, Container.Top); }); @@ -463,6 +472,7 @@ describe("RoomHeader", () => { }); it("calls using legacy or jitsi", async () => { + const user = userEvent.setup(); mockRoomMembers(room, 2); jest.spyOn(room.currentState, "mayClientSendStateEvent").mockImplementation((key) => { if (key === "im.vector.modular.widgets") return true; @@ -476,14 +486,15 @@ describe("RoomHeader", () => { expect(videoButton).not.toHaveAttribute("aria-disabled", "true"); const placeCallSpy = jest.spyOn(LegacyCallHandler.instance, "placeCall"); - fireEvent.click(voiceButton); + await user.click(voiceButton); expect(placeCallSpy).toHaveBeenLastCalledWith(room.roomId, CallType.Voice); - fireEvent.click(videoButton); + await user.click(videoButton); expect(placeCallSpy).toHaveBeenLastCalledWith(room.roomId, CallType.Video); }); it("calls using legacy or jitsi for large rooms", async () => { + const user = userEvent.setup(); mockRoomMembers(room, 3); jest.spyOn(room.currentState, "mayClientSendStateEvent").mockImplementation((key) => { @@ -497,11 +508,12 @@ describe("RoomHeader", () => { expect(videoButton).not.toHaveAttribute("aria-disabled", "true"); const placeCallSpy = jest.spyOn(LegacyCallHandler.instance, "placeCall"); - fireEvent.click(videoButton); + await user.click(videoButton); expect(placeCallSpy).toHaveBeenLastCalledWith(room.roomId, CallType.Video); }); it("calls using element call for large rooms", async () => { + const user = userEvent.setup(); mockRoomMembers(room, 3); jest.spyOn(room.currentState, "mayClientSendStateEvent").mockImplementation((key) => { @@ -514,8 +526,8 @@ describe("RoomHeader", () => { const videoButton = screen.getByRole("button", { name: "Video call" }); expect(videoButton).not.toHaveAttribute("aria-disabled", "true"); - const dispatcherSpy = jest.spyOn(dispatcher, "dispatch"); - fireEvent.click(videoButton); + const dispatcherSpy = jest.spyOn(dispatcher, "dispatch").mockImplementation(); + await user.click(videoButton); expect(dispatcherSpy).toHaveBeenCalledWith(expect.objectContaining({ view_call: true })); }); @@ -750,10 +762,11 @@ describe("RoomHeader", () => { }); it("should open room settings when clicking the room avatar", async () => { + const user = userEvent.setup(); render(, getWrapper()); const dispatcherSpy = jest.spyOn(dispatcher, "dispatch"); - fireEvent.click(getByLabelText(document.body, "Open room settings")); + await user.click(getByLabelText(document.body, "Open room settings")); expect(dispatcherSpy).toHaveBeenCalledWith(expect.objectContaining({ action: "open_room_settings" })); }); }); diff --git a/test/unit-tests/components/views/rooms/RoomHeader/__snapshots__/RoomHeader-test.tsx.snap b/test/unit-tests/components/views/rooms/RoomHeader/__snapshots__/RoomHeader-test.tsx.snap index c2a339457a..3ac64ce10e 100644 --- a/test/unit-tests/components/views/rooms/RoomHeader/__snapshots__/RoomHeader-test.tsx.snap +++ b/test/unit-tests/components/views/rooms/RoomHeader/__snapshots__/RoomHeader-test.tsx.snap @@ -43,7 +43,8 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
+ ); +} diff --git a/src/components/views/rooms/RoomListPanel/RoomListPanel.tsx b/src/components/views/rooms/RoomListPanel/RoomListPanel.tsx index a52b619651..291794399f 100644 --- a/src/components/views/rooms/RoomListPanel/RoomListPanel.tsx +++ b/src/components/views/rooms/RoomListPanel/RoomListPanel.tsx @@ -6,14 +6,13 @@ Please see LICENSE files in the repository root for full details. */ import React from "react"; -import { AutoSizer, List } from "react-virtualized"; -import type { ListRowProps } from "react-virtualized"; import { shouldShowComponent } from "../../../../customisations/helpers/UIComponents"; import { UIComponent } from "../../../../settings/UIFeature"; import { RoomListSearch } from "./RoomListSearch"; import { RoomListHeaderView } from "./RoomListHeaderView"; -import { useRoomListViewModel } from "../../../viewmodels/roomlist/RoomListViewModel"; +import { RoomListView } from "./RoomListView"; +import { Flex } from "../../../utils/Flex"; type RoomListPanelProps = { /** @@ -28,31 +27,18 @@ type RoomListPanelProps = { */ export const RoomListPanel: React.FC = ({ activeSpace }) => { const displayRoomSearch = shouldShowComponent(UIComponent.FilterContainer); - const { rooms } = useRoomListViewModel(); - - const rowRenderer = ({ key, index, style }: ListRowProps): React.JSX.Element => { - return ( -
- {rooms[index].name} -
- ); - }; return ( -
+ {displayRoomSearch && } - - {({ height, width }) => ( - - )} - -
+ + ); }; diff --git a/src/components/views/rooms/RoomListPanel/RoomListView.tsx b/src/components/views/rooms/RoomListPanel/RoomListView.tsx new file mode 100644 index 0000000000..14b456852c --- /dev/null +++ b/src/components/views/rooms/RoomListPanel/RoomListView.tsx @@ -0,0 +1,20 @@ +/* + * Copyright 2025 New Vector 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 } from "react"; + +import { useRoomListViewModel } from "../../../viewmodels/roomlist/RoomListViewModel"; +import { RoomList } from "./RoomList"; + +/** + * Host the room list and the (future) room filters + */ +export function RoomListView(): JSX.Element { + const vm = useRoomListViewModel(); + // Room filters will be added soon + return ; +} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 64200527c1..c3dd76a5a2 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2104,12 +2104,16 @@ "one": "Currently joining %(count)s room", "other": "Currently joining %(count)s rooms" }, + "list_title": "Room list", "notification_options": "Notification options", "open_space_menu": "Open space menu", "redacting_messages_status": { "one": "Currently removing messages in %(count)s room", "other": "Currently removing messages in %(count)s rooms" }, + "room": { + "open_room": "Open room %(roomName)s" + }, "show_less": "Show less", "show_n_more": { "one": "Show %(count)s more", diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx new file mode 100644 index 0000000000..bbf0edbf5e --- /dev/null +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx @@ -0,0 +1,52 @@ +/* + * Copyright 2025 New Vector 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 from "react"; +import { type MatrixClient } from "matrix-js-sdk/src/matrix"; +import { render, screen, waitFor } from "jest-matrix-react"; +import userEvent from "@testing-library/user-event"; + +import { mkRoom, stubClient } from "../../../../../test-utils"; +import { type RoomListViewState } from "../../../../../../src/components/viewmodels/roomlist/RoomListViewModel"; +import { RoomList } from "../../../../../../src/components/views/rooms/RoomListPanel/RoomList"; +import DMRoomMap from "../../../../../../src/utils/DMRoomMap"; + +describe("", () => { + let matrixClient: MatrixClient; + let vm: RoomListViewState; + + beforeEach(() => { + // Needed to render the virtualized list in rtl tests + // https://github.com/bvaughn/react-virtualized/issues/493#issuecomment-640084107 + jest.spyOn(HTMLElement.prototype, "offsetHeight", "get").mockReturnValue(1500); + jest.spyOn(HTMLElement.prototype, "offsetWidth", "get").mockReturnValue(1500); + + matrixClient = stubClient(); + const rooms = Array.from({ length: 10 }, (_, i) => mkRoom(matrixClient, `room${i}`)); + vm = { rooms, openRoom: jest.fn() }; + + // Needed to render a room list cell + DMRoomMap.makeShared(matrixClient); + jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(null); + }); + + it("should render a room list", () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); + + it("should open the room", async () => { + const user = userEvent.setup(); + + render(); + await waitFor(async () => { + expect(screen.getByRole("gridcell", { name: "Open room room9" })).toBeVisible(); + await user.click(screen.getByRole("gridcell", { name: "Open room room9" })); + }); + expect(vm.openRoom).toHaveBeenCalledWith(vm.rooms[9].roomId); + }); +}); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListCell-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListCell-test.tsx new file mode 100644 index 0000000000..3bbde9fb92 --- /dev/null +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListCell-test.tsx @@ -0,0 +1,44 @@ +/* + * Copyright 2025 New Vector 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 from "react"; +import { type MatrixClient, type Room } from "matrix-js-sdk/src/matrix"; +import { render, screen } from "jest-matrix-react"; +import userEvent from "@testing-library/user-event"; + +import { mkRoom, stubClient } from "../../../../../test-utils"; +import { RoomListCell } from "../../../../../../src/components/views/rooms/RoomListPanel/RoomListCell"; +import DMRoomMap from "../../../../../../src/utils/DMRoomMap"; + +describe("", () => { + let matrixClient: MatrixClient; + let room: Room; + + beforeEach(() => { + matrixClient = stubClient(); + room = mkRoom(matrixClient, "room1"); + + DMRoomMap.makeShared(matrixClient); + jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(null); + }); + + test("should render a room cell", () => { + const onClick = jest.fn(); + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); + + test("should call onClick when clicked", async () => { + const user = userEvent.setup(); + + const onClick = jest.fn(); + render(); + + await user.click(screen.getByRole("button", { name: `Open room ${room.name}` })); + expect(onClick).toHaveBeenCalled(); + }); +}); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomList-test.tsx.snap b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomList-test.tsx.snap new file mode 100644 index 0000000000..54919fb980 --- /dev/null +++ b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomList-test.tsx.snap @@ -0,0 +1,504 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` should render a room list 1`] = ` + +
+
+
+
+ + + + + + + + + + +
+
+
+
+
+
+
+
+
+
+ +`; diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListCell-test.tsx.snap b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListCell-test.tsx.snap new file mode 100644 index 0000000000..cf7c8b854a --- /dev/null +++ b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListCell-test.tsx.snap @@ -0,0 +1,50 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` should render a room cell 1`] = ` + + + +`; diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListPanel-test.tsx.snap b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListPanel-test.tsx.snap index 35643e394f..cd1fafd224 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListPanel-test.tsx.snap +++ b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListPanel-test.tsx.snap @@ -3,8 +3,9 @@ exports[` should not render the RoomListSearch component when UIComponent.FilterContainer is at false 1`] = `
should not render the RoomListSearch component when U
-
-
-
+ class="resize-triggers" + > +
+
+
+
+
@@ -56,8 +62,9 @@ exports[` should not render the RoomListSearch component when U exports[` should render the RoomListSearch component when UIComponent.FilterContainer is at true 1`] = `
should render the RoomListSearch component when UICom
-
-
-
+ class="resize-triggers" + > +
+
+
+
+
From 8d891cde539d0c1e749c982f66ae13294139b7e3 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Thu, 6 Mar 2025 11:55:41 +0000 Subject: [PATCH 047/458] Move toggle switch for integration manager for a11y (#29436) * Move toggle switch for integration manager for a11y * Update test * add toggle_label * lint --- .../security-user-settings-tab.spec.ts | 6 +- .../settings/_SetIntegrationManager.pcss | 20 +++---- .../views/settings/SetIntegrationManager.tsx | 33 ++++++----- src/i18n/strings/en_EN.json | 1 + .../SetIntegrationManager-test.tsx.snap | 52 ++++++++++++----- .../SecurityUserSettingsTab-test.tsx.snap | 57 +++++++++++++------ 6 files changed, 109 insertions(+), 60 deletions(-) diff --git a/playwright/e2e/settings/security-user-settings-tab.spec.ts b/playwright/e2e/settings/security-user-settings-tab.spec.ts index 9a5616ef59..25bf1a9dbe 100644 --- a/playwright/e2e/settings/security-user-settings-tab.spec.ts +++ b/playwright/e2e/settings/security-user-settings-tab.spec.ts @@ -91,7 +91,7 @@ test.describe("Security user settings tab", () => { await expect(tab.getByText(`Identity server (identity.example.org)`, { exact: true })).toBeVisible(); }); - test("should enable show integrations as enabled", async ({ app, page, user }) => { + test("should show integrations as enabled", async ({ app, page, user }) => { const tab = await app.settings.openUserSettings("Security"); const setIntegrationManager = tab.locator(".mx_SetIntegrationManager"); @@ -102,7 +102,9 @@ test.describe("Security user settings tab", () => { }), ).toBeVisible(); // Make sure integration manager's toggle switch is enabled - await expect(setIntegrationManager.locator(".mx_ToggleSwitch_enabled")).toBeVisible(); + const toggleswitch = setIntegrationManager.getByLabel("Enable the integration manager"); + await expect(toggleswitch).toBeVisible(); + await expect(toggleswitch).toBeChecked(); await expect(setIntegrationManager.locator(".mx_SetIntegrationManager_heading_manager")).toHaveText( "Manage integrations(scalar.vector.im)", ); diff --git a/res/css/views/settings/_SetIntegrationManager.pcss b/res/css/views/settings/_SetIntegrationManager.pcss index a046ce0fff..f370d06e5e 100644 --- a/res/css/views/settings/_SetIntegrationManager.pcss +++ b/res/css/views/settings/_SetIntegrationManager.pcss @@ -7,19 +7,13 @@ Please see LICENSE files in the repository root for full details. */ .mx_SetIntegrationManager { - .mx_SettingsFlag { + .mx_SetIntegrationManager_heading_manager { + display: flex; align-items: center; - - .mx_SetIntegrationManager_heading_manager { - display: flex; - align-items: center; - flex-wrap: wrap; - column-gap: $spacing-4; - } - - .mx_ToggleSwitch { - align-self: flex-start; - min-width: var(--ToggleSwitch-min-width); /* avoid compression */ - } + flex-wrap: wrap; + column-gap: $spacing-4; + } + form { + margin-top: var(--cpd-space-3x); } } diff --git a/src/components/views/settings/SetIntegrationManager.tsx b/src/components/views/settings/SetIntegrationManager.tsx index 8721ddcd4b..98066bc0a4 100644 --- a/src/components/views/settings/SetIntegrationManager.tsx +++ b/src/components/views/settings/SetIntegrationManager.tsx @@ -9,13 +9,13 @@ Please see LICENSE files in the repository root for full details. import React from "react"; import { logger } from "matrix-js-sdk/src/logger"; import { type EmptyObject } from "matrix-js-sdk/src/matrix"; +import { Root, InlineField, Label, ToggleInput } from "@vector-im/compound-web"; import { _t } from "../../../languageHandler"; import { IntegrationManagers } from "../../../integrations/IntegrationManagers"; import { type IntegrationManagerInstance } from "../../../integrations/IntegrationManagerInstance"; import SettingsStore from "../../../settings/SettingsStore"; import { SettingLevel } from "../../../settings/SettingLevel"; -import ToggleSwitch from "../elements/ToggleSwitch"; import Heading from "../typography/Heading"; import { SettingsSubsectionText } from "./shared/SettingsSubsection"; import { UIFeature } from "../../../settings/UIFeature"; @@ -66,26 +66,33 @@ export default class SetIntegrationManager extends React.Component +
{_t("integration_manager|manage_title")} {managerName}
-
{bodyText} {_t("integration_manager|explainer")} - + + + } + > + + + +
); } } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index c3dd76a5a2..bd577e7418 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1306,6 +1306,7 @@ "error_connecting_heading": "Cannot connect to integration manager", "explainer": "Integration managers receive configuration data, and can modify widgets, send room invites, and set power levels on your behalf.", "manage_title": "Manage integrations", + "toggle_label": "Enable the integration manager", "use_im": "Use an integration manager to manage bots, widgets, and sticker packs.", "use_im_default": "Use an integration manager (%(serverName)s) to manage bots, widgets, and sticker packs." }, diff --git a/test/unit-tests/components/views/settings/__snapshots__/SetIntegrationManager-test.tsx.snap b/test/unit-tests/components/views/settings/__snapshots__/SetIntegrationManager-test.tsx.snap index 9dab61f8b2..025afc3c97 100644 --- a/test/unit-tests/components/views/settings/__snapshots__/SetIntegrationManager-test.tsx.snap +++ b/test/unit-tests/components/views/settings/__snapshots__/SetIntegrationManager-test.tsx.snap @@ -1,10 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`SetIntegrationManager should render manage integrations sections 1`] = ` - +
+
+
+
+ +
+
+
+
+ +
+
+ +
`; diff --git a/test/unit-tests/components/views/settings/tabs/user/__snapshots__/SecurityUserSettingsTab-test.tsx.snap b/test/unit-tests/components/views/settings/tabs/user/__snapshots__/SecurityUserSettingsTab-test.tsx.snap index 2a2cf63451..92a9a53276 100644 --- a/test/unit-tests/components/views/settings/tabs/user/__snapshots__/SecurityUserSettingsTab-test.tsx.snap +++ b/test/unit-tests/components/views/settings/tabs/user/__snapshots__/SecurityUserSettingsTab-test.tsx.snap @@ -8,10 +8,9 @@ exports[` renders security section 1`] = `
- +
+
+
+
+ +
+
+
+
+ +
+
+ +
@@ -445,7 +468,7 @@ exports[` renders security section 1`] = ` > @@ -454,7 +477,7 @@ exports[` renders security section 1`] = ` > Date: Thu, 6 Mar 2025 18:13:25 +0530 Subject: [PATCH 048/458] Room List Store: Support filters by implementing just the favourite filter (#29433) * Implement the favourite filter * Make the room node capable of dealing with filters - Holds data to indicate which filters apply - Provides method to check if a given set of filters apply to this node - Provides a method to recalculate which filters apply * Wire up the filtering mechanism in skip list * Use filters in the store * Remove else * Use a set instead of map --- src/stores/room-list-v3/RoomListStoreV3.ts | 12 +- src/stores/room-list-v3/skip-list/RoomNode.ts | 28 +++++ .../room-list-v3/skip-list/RoomSkipList.ts | 60 ++++------ .../skip-list/filters/FavouriteFilter.ts | 20 ++++ .../room-list-v3/skip-list/filters/index.ts | 24 ++++ .../room-list-v3/skip-list/iterators.ts | 47 ++++++++ .../room-list-v3/RoomListStoreV3-test.ts | 103 ++++++++++++++++-- 7 files changed, 245 insertions(+), 49 deletions(-) create mode 100644 src/stores/room-list-v3/skip-list/filters/FavouriteFilter.ts create mode 100644 src/stores/room-list-v3/skip-list/filters/index.ts create mode 100644 src/stores/room-list-v3/skip-list/iterators.ts diff --git a/src/stores/room-list-v3/RoomListStoreV3.ts b/src/stores/room-list-v3/RoomListStoreV3.ts index 36a05f8357..83e73e1b7f 100644 --- a/src/stores/room-list-v3/RoomListStoreV3.ts +++ b/src/stores/room-list-v3/RoomListStoreV3.ts @@ -11,6 +11,7 @@ import { EventType } from "matrix-js-sdk/src/matrix"; import type { EmptyObject, Room, RoomState } from "matrix-js-sdk/src/matrix"; import type { MatrixDispatcher } from "../../dispatcher/dispatcher"; import type { ActionPayload } from "../../dispatcher/payloads"; +import type { FilterKey } from "./skip-list/filters"; import { AsyncStoreWithClient } from "../AsyncStoreWithClient"; import SettingsStore from "../../settings/SettingsStore"; import { VisibilityProvider } from "../room-list/filters/VisibilityProvider"; @@ -23,6 +24,7 @@ import { readReceiptChangeIsFor } from "../../utils/read-receipts"; import { EffectiveMembership, getEffectiveMembership, getEffectiveMembershipTag } from "../../utils/membership"; import SpaceStore from "../spaces/SpaceStore"; import { UPDATE_HOME_BEHAVIOUR, UPDATE_SELECTED_SPACE } from "../spaces"; +import { FavouriteFilter } from "./skip-list/filters/FavouriteFilter"; /** * This store allows for fast retrieval of the room list in a sorted and filtered manner. @@ -61,9 +63,13 @@ export class RoomListStoreV3Class extends AsyncStoreWithClient { /** * Get a list of sorted rooms that belong to the currently active space. + * If filterKeys is passed, only the rooms that match the given filters are + * returned. + + * @param filterKeys Optional array of filters that the rooms must match against. */ - public getSortedRoomsInActiveSpace(): Room[] { - if (this.roomSkipList?.initialized) return Array.from(this.roomSkipList.getRoomsInActiveSpace()); + public getSortedRoomsInActiveSpace(filterKeys?: FilterKey[]): Room[] { + if (this.roomSkipList?.initialized) return Array.from(this.roomSkipList.getRoomsInActiveSpace(filterKeys)); else return []; } @@ -90,7 +96,7 @@ export class RoomListStoreV3Class extends AsyncStoreWithClient { protected async onReady(): Promise { if (this.roomSkipList?.initialized || !this.matrixClient) return; const sorter = new RecencySorter(this.matrixClient.getSafeUserId()); - this.roomSkipList = new RoomSkipList(sorter); + this.roomSkipList = new RoomSkipList(sorter, [new FavouriteFilter()]); const rooms = this.getRooms(); await SpaceStore.instance.storeReadyPromise; this.roomSkipList.seed(rooms); diff --git a/src/stores/room-list-v3/skip-list/RoomNode.ts b/src/stores/room-list-v3/skip-list/RoomNode.ts index af792aa757..6fbcb65588 100644 --- a/src/stores/room-list-v3/skip-list/RoomNode.ts +++ b/src/stores/room-list-v3/skip-list/RoomNode.ts @@ -6,6 +6,7 @@ Please see LICENSE files in the repository root for full details. */ import type { Room } from "matrix-js-sdk/src/matrix"; +import type { Filter, FilterKey } from "./filters"; import SpaceStore from "../../spaces/SpaceStore"; /** @@ -48,4 +49,31 @@ export class RoomNode { const activeSpace = SpaceStore.instance.activeSpace; this._isInActiveSpace = SpaceStore.instance.isRoomInSpace(activeSpace, this.room.roomId); } + + /** + * Aggregates all the filter keys that apply to this room. + * eg: if filterKeysSet.has(Filter.FavouriteFilter) is true, then this room is a favourite room. + */ + private filterKeysSet: Set = new Set(); + + /** + * Returns true if the associated room matches all the provided filters. + * Returns false otherwise. + * @param filterKeys An array of filter keys to check against. + */ + public doesRoomMatchFilters(filterKeys: FilterKey[]): boolean { + return !filterKeys.some((key) => !this.filterKeysSet.has(key)); + } + + /** + * Populates {@link RoomNode#filterKeysSet} by checking if the associated room + * satisfies the given filters. + * @param filters A list of filters + */ + public applyFilters(filters: Filter[]): void { + this.filterKeysSet = new Set(); + for (const filter of filters) { + if (filter.matches(this.room)) this.filterKeysSet.add(filter.key); + } + } } diff --git a/src/stores/room-list-v3/skip-list/RoomSkipList.ts b/src/stores/room-list-v3/skip-list/RoomSkipList.ts index 323b4c8fcb..1653d8068d 100644 --- a/src/stores/room-list-v3/skip-list/RoomSkipList.ts +++ b/src/stores/room-list-v3/skip-list/RoomSkipList.ts @@ -7,9 +7,11 @@ Please see LICENSE files in the repository root for full details. import type { Room } from "matrix-js-sdk/src/matrix"; import type { Sorter } from "./sorters"; +import type { Filter, FilterKey } from "./filters"; import { RoomNode } from "./RoomNode"; import { shouldPromote } from "./utils"; import { Level } from "./Level"; +import { SortedRoomIterator, SortedSpaceFilteredIterator } from "./iterators"; /** * Implements a skip list that stores rooms using a given sorting algorithm. @@ -20,7 +22,10 @@ export class RoomSkipList implements Iterable { private roomNodeMap: Map = new Map(); public initialized: boolean = false; - public constructor(private sorter: Sorter) {} + public constructor( + private sorter: Sorter, + private filters: Filter[] = [], + ) {} private reset(): void { this.levels = [new Level(0)]; @@ -35,6 +40,7 @@ export class RoomSkipList implements Iterable { const sortedRoomNodes = this.sorter.sort(rooms).map((room) => new RoomNode(room)); let currentLevel = this.levels[0]; for (const node of sortedRoomNodes) { + node.applyFilters(this.filters); currentLevel.setNext(node); this.roomNodeMap.set(node.room.roomId, node); } @@ -95,6 +101,7 @@ export class RoomSkipList implements Iterable { const newNode = new RoomNode(room); newNode.checkIfRoomBelongsToActiveSpace(); + newNode.applyFilters(this.filters); this.roomNodeMap.set(room.roomId, newNode); /** @@ -173,8 +180,22 @@ export class RoomSkipList implements Iterable { return new SortedRoomIterator(this.levels[0].head!); } - public getRoomsInActiveSpace(): SortedSpaceFilteredIterator { - return new SortedSpaceFilteredIterator(this.levels[0].head!); + /** + * Returns an iterator that can be used to generate a list of sorted rooms that belong + * to the currently active space. Passing filterKeys will further filter the list such + * that only rooms that match the filters are returned. + * + * @example To get an array of rooms: + * Array.from(RLS.getRoomsInActiveSpace()); + * + * @example Use a for ... of loop to iterate over rooms: + * for(const room of RLS.getRoomsInActiveSpace()) { something(room); } + * + * @example Additional filtering: + * Array.from(RLS.getRoomsInActiveSpace([FilterKeys.Favourite])); + */ + public getRoomsInActiveSpace(filterKeys: FilterKey[] = []): SortedSpaceFilteredIterator { + return new SortedSpaceFilteredIterator(this.levels[0].head!, filterKeys); } /** @@ -184,36 +205,3 @@ export class RoomSkipList implements Iterable { return this.levels[0].size; } } - -class SortedRoomIterator implements Iterator { - public constructor(private current: RoomNode) {} - - public next(): IteratorResult { - const current = this.current; - if (!current) return { value: undefined, done: true }; - this.current = current.next[0]; - return { - value: current.room, - }; - } -} - -class SortedSpaceFilteredIterator implements Iterator { - public constructor(private current: RoomNode) {} - - public [Symbol.iterator](): SortedSpaceFilteredIterator { - return this; - } - - public next(): IteratorResult { - let current = this.current; - while (current && !current.isInActiveSpace) { - current = current.next[0]; - } - if (!current) return { value: undefined, done: true }; - this.current = current.next[0]; - return { - value: current.room, - }; - } -} diff --git a/src/stores/room-list-v3/skip-list/filters/FavouriteFilter.ts b/src/stores/room-list-v3/skip-list/filters/FavouriteFilter.ts new file mode 100644 index 0000000000..6af657b81e --- /dev/null +++ b/src/stores/room-list-v3/skip-list/filters/FavouriteFilter.ts @@ -0,0 +1,20 @@ +/* +Copyright 2025 New Vector 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 type { Room } from "matrix-js-sdk/src/matrix"; +import type { Filter } from "."; +import { FilterKey } from "."; +import { DefaultTagID } from "../../../room-list/models"; + +export class FavouriteFilter implements Filter { + public matches(room: Room): boolean { + return !!room.tags[DefaultTagID.Favourite]; + } + + public get key(): FilterKey.FavouriteFilter { + return FilterKey.FavouriteFilter; + } +} diff --git a/src/stores/room-list-v3/skip-list/filters/index.ts b/src/stores/room-list-v3/skip-list/filters/index.ts new file mode 100644 index 0000000000..0580c95764 --- /dev/null +++ b/src/stores/room-list-v3/skip-list/filters/index.ts @@ -0,0 +1,24 @@ +/* +Copyright 2025 New Vector 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 type { Room } from "matrix-js-sdk/src/matrix"; + +export const enum FilterKey { + FavouriteFilter, +} + +export interface Filter { + /** + * Boolean return value indicates whether this room satisfies + * the filter condition. + */ + matches(room: Room): boolean; + + /** + * Used to identify this particular filter. + */ + key: FilterKey; +} diff --git a/src/stores/room-list-v3/skip-list/iterators.ts b/src/stores/room-list-v3/skip-list/iterators.ts new file mode 100644 index 0000000000..a992c79aef --- /dev/null +++ b/src/stores/room-list-v3/skip-list/iterators.ts @@ -0,0 +1,47 @@ +/* +Copyright 2025 New Vector 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 type { Room } from "matrix-js-sdk/src/matrix"; +import type { RoomNode } from "./RoomNode"; +import type { FilterKey } from "./filters"; + +export class SortedRoomIterator implements Iterator { + public constructor(private current: RoomNode) {} + + public next(): IteratorResult { + const current = this.current; + if (!current) return { value: undefined, done: true }; + this.current = current.next[0]; + return { + value: current.room, + }; + } +} + +export class SortedSpaceFilteredIterator implements Iterator { + public constructor( + private current: RoomNode, + private readonly filters: FilterKey[], + ) {} + + public [Symbol.iterator](): SortedSpaceFilteredIterator { + return this; + } + + public next(): IteratorResult { + let current = this.current; + while (current) { + if (current.isInActiveSpace && current.doesRoomMatchFilters(this.filters)) break; + current = current.next[0]; + } + if (!current) return { value: undefined, done: true }; + this.current = current.next[0]; + return { + value: current.room, + }; + } +} diff --git a/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts b/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts index c91606034e..7edd5b3ef9 100644 --- a/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts +++ b/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts @@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details. import { EventType, KnownMembership, MatrixEvent, Room } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; +import type { MatrixClient } from "matrix-js-sdk/src/matrix"; import { RoomListStoreV3Class } from "../../../../src/stores/room-list-v3/RoomListStoreV3"; import { AsyncStoreWithClient } from "../../../../src/stores/AsyncStoreWithClient"; import { RecencySorter } from "../../../../src/stores/room-list-v3/skip-list/sorters/RecencySorter"; @@ -18,6 +19,8 @@ import { LISTS_UPDATE_EVENT } from "../../../../src/stores/room-list/RoomListSto import dispatcher from "../../../../src/dispatcher/dispatcher"; import SpaceStore from "../../../../src/stores/spaces/SpaceStore"; import { MetaSpace, UPDATE_SELECTED_SPACE } from "../../../../src/stores/spaces"; +import { DefaultTagID } from "../../../../src/stores/room-list/models"; +import { FilterKey } from "../../../../src/stores/room-list-v3/skip-list/filters"; describe("RoomListStoreV3", () => { async function getRoomListStore() { @@ -273,19 +276,40 @@ describe("RoomListStoreV3", () => { }); }); + /** + * Create a space and add it to rooms + * @param rooms An array of rooms to which the new space is added. + * @param inSpaceIndices A list of indices from which rooms are added to the space. + */ + function createSpace(rooms: Room[], inSpaceIndices: number[], client: MatrixClient) { + const roomIds = inSpaceIndices.map((i) => rooms[i].roomId); + const spaceRoom = mkSpace(client, "!space1:matrix.org", [], roomIds); + rooms.push(spaceRoom); + return { spaceRoom, roomIds }; + } + + function setupMocks(spaceRoom: Room, roomIds: string[]) { + jest.spyOn(SpaceStore.instance, "isRoomInSpace").mockImplementation((space, id) => { + if (space === MetaSpace.Home && !roomIds.includes(id)) return true; + if (space === spaceRoom.roomId && roomIds.includes(id)) return true; + return false; + }); + jest.spyOn(SpaceStore.instance, "activeSpace", "get").mockImplementation(() => spaceRoom.roomId); + } + + function getClientAndRooms() { + const client = stubClient(); + const rooms = getMockedRooms(client); + client.getVisibleRooms = jest.fn().mockReturnValue(rooms); + jest.spyOn(AsyncStoreWithClient.prototype, "matrixClient", "get").mockReturnValue(client); + return { client, rooms }; + } + describe("Spaces", () => { it("Filtering by spaces work", async () => { - const client = stubClient(); - const rooms = getMockedRooms(client); - + const { client, rooms } = getClientAndRooms(); // Let's choose 5 rooms to put in space - const indexes = [6, 8, 13, 27, 75]; - const roomIds = indexes.map((i) => rooms[i].roomId); - const spaceRoom = mkSpace(client, "!space1:matrix.org", [], roomIds); - rooms.push(spaceRoom); - - client.getVisibleRooms = jest.fn().mockReturnValue(rooms); - jest.spyOn(AsyncStoreWithClient.prototype, "matrixClient", "get").mockReturnValue(client); + const { spaceRoom, roomIds } = createSpace(rooms, [6, 8, 13, 27, 75], client); // Mock the space store jest.spyOn(SpaceStore.instance, "isRoomInSpace").mockImplementation((space, id) => { @@ -315,5 +339,64 @@ describe("RoomListStoreV3", () => { } }); }); + + describe("Filters", () => { + it("filters by both space and favourite", async () => { + const { client, rooms } = getClientAndRooms(); + // Let's choose 5 rooms to put in space + const { spaceRoom, roomIds } = createSpace(rooms, [6, 8, 13, 27, 75], client); + + // Let's say that 8, 27 an 75 are favourite rooms + [8, 27, 75].forEach((i) => { + rooms[i].tags[DefaultTagID.Favourite] = {}; + }); + + setupMocks(spaceRoom, roomIds); + const store = new RoomListStoreV3Class(dispatcher); + await store.start(); + + // Sorted, filtered rooms should be 8, 27 and 75 + const result = store.getSortedRoomsInActiveSpace([FilterKey.FavouriteFilter]); + expect(result).toHaveLength(3); + for (const i of [8, 27, 75]) { + expect(result).toContain(rooms[i]); + } + }); + + it("filters are recalculated on room update", async () => { + const { client, rooms } = getClientAndRooms(); + // Let's choose 5 rooms to put in space + const { spaceRoom, roomIds } = createSpace(rooms, [6, 8, 13, 27, 75], client); + + // Let's say that 8, 27 an 75 are favourite rooms + [8, 27, 75].forEach((i) => { + rooms[i].tags[DefaultTagID.Favourite] = {}; + }); + + setupMocks(spaceRoom, roomIds); + const store = new RoomListStoreV3Class(dispatcher); + await store.start(); + + // Let's say 27 got unfavourited + const fn = jest.fn(); + store.on(LISTS_UPDATE_EVENT, fn); + rooms[27].tags = {}; + dispatcher.dispatch( + { + action: "MatrixActions.Room.tags", + room: rooms[27], + }, + true, + ); + expect(fn).toHaveBeenCalled(); + + // Sorted, filtered rooms should be 27 and 75 + const result = store.getSortedRoomsInActiveSpace([FilterKey.FavouriteFilter]); + expect(result).toHaveLength(2); + for (const i of [8, 75]) { + expect(result).toContain(rooms[i]); + } + }); + }); }); }); From 27c1b38dab72b3c1d938b9a2b91839aff8aeb884 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Fri, 7 Mar 2025 06:20:44 +0000 Subject: [PATCH 049/458] [create-pull-request] automated change (#29443) Co-authored-by: t3chguy <2403652+t3chguy@users.noreply.github.com> --- src/i18n/strings/cs.json | 3 --- src/i18n/strings/cy.json | 3 --- src/i18n/strings/de_DE.json | 11 +++++------ src/i18n/strings/el.json | 2 -- src/i18n/strings/eo.json | 2 -- src/i18n/strings/es.json | 2 -- src/i18n/strings/et.json | 3 --- src/i18n/strings/fa.json | 2 -- src/i18n/strings/fi.json | 3 --- src/i18n/strings/fr.json | 16 +++++++++++++--- src/i18n/strings/gl.json | 2 -- src/i18n/strings/he.json | 2 -- src/i18n/strings/hu.json | 3 --- src/i18n/strings/id.json | 2 -- src/i18n/strings/is.json | 2 -- src/i18n/strings/it.json | 3 --- src/i18n/strings/ja.json | 2 -- src/i18n/strings/ka.json | 2 -- src/i18n/strings/lo.json | 2 -- src/i18n/strings/lt.json | 2 -- src/i18n/strings/lv.json | 3 --- src/i18n/strings/mg_MG.json | 3 --- src/i18n/strings/nb_NO.json | 3 --- src/i18n/strings/nl.json | 2 -- src/i18n/strings/pl.json | 3 --- src/i18n/strings/pt.json | 3 --- src/i18n/strings/pt_BR.json | 2 -- src/i18n/strings/ru.json | 2 -- src/i18n/strings/sk.json | 2 -- src/i18n/strings/sq.json | 2 -- src/i18n/strings/sv.json | 3 --- src/i18n/strings/tr.json | 3 --- src/i18n/strings/uk.json | 3 --- src/i18n/strings/vi.json | 2 -- src/i18n/strings/zh_Hans.json | 2 -- src/i18n/strings/zh_Hant.json | 2 -- 36 files changed, 18 insertions(+), 91 deletions(-) diff --git a/src/i18n/strings/cs.json b/src/i18n/strings/cs.json index a6318b896d..ac99222c79 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -407,7 +407,6 @@ "download_logs": "Stáhnout záznamy", "downloading_logs": "Stahování záznamů", "error_empty": "Dejte nám vědět, prosím, co se pokazilo nebo vytvořte issue na GitHubu, kde problém popište.", - "failed_send_logs": "Nepodařilo se odeslat záznamy: ", "github_issue": "issue na GitHubu", "introduction": "Pokud jste odeslali chybu prostřednictvím GitHubu, ladící protokoly nám mohou pomoci problém vysledovat. ", "log_request": "Abychom tomu mohli pro příště předejít, pošlete nám prosím záznamy.", @@ -497,7 +496,6 @@ "legal": "Právní informace", "light": "Světlý", "loading": "Načítání…", - "lobby": "Předsálí", "location": "Poloha", "low_priority": "Nízká priorita", "matrix": "Matrix", @@ -3914,7 +3912,6 @@ "input_devices": "Vstupní zařízení", "jitsi_call": "Jitsi konference", "join_button_tooltip_call_full": "Omlouváme se — tento hovor je v současné době plný", - "join_button_tooltip_connecting": "Spojování", "legacy_call": "Zastaralý způsob hovoru", "maximise": "Vyplnit obrazovku", "maximise_call": "Maximalizovat hovor", diff --git a/src/i18n/strings/cy.json b/src/i18n/strings/cy.json index f8db1668ea..d4c6089a55 100644 --- a/src/i18n/strings/cy.json +++ b/src/i18n/strings/cy.json @@ -399,7 +399,6 @@ "download_logs": "Llwytho logiau i lawr", "downloading_logs": "Wrthi'n llwytho logiau i lawr", "error_empty": "Dywedwch wrthym beth aeth o'i le neu, yn well, crëwch fater GitHub sy'n disgrifio'r broblem.", - "failed_send_logs": "Wedi methu ag anfon logiau: ", "github_issue": "Mater GitHub", "introduction": "Os ydych chi wedi cyflwyno byg trwy GitHub, gall logiau dadfygio ein helpu i ddod o hyd i'r broblem. ", "log_request": "Er mwyn ein helpu i atal hyn yn y dyfodol, anfonwch logiau atom .", @@ -485,7 +484,6 @@ "legal": "Cyfreithiol", "light": "Golau", "loading": "Llwytho…", - "lobby": "Cyntedd", "location": "Lleoliad", "low_priority": "Blaenoriaeth isel", "matrix": "Matrics", @@ -3546,7 +3544,6 @@ "input_devices": "Dyfeisiau mewnbwn", "jitsi_call": "Cynhadledd Jitsi", "join_button_tooltip_call_full": "Mae'n ddrwg gennym - mae'r alwad hon yn llawn ar hyn o bryd", - "join_button_tooltip_connecting": "Yn cysylltu", "legacy_call": "Galwad Etifeddiaeth", "maximise": "Llanw'r Sgrin", "maximise_call": "Mwyhau galwad", diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 1f539a4aa2..00e76092e8 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -1,6 +1,6 @@ { "a11y": { - "emoji_picker": "Emoji-Auswahl", + "emoji_picker": "Emoji-Picker", "jump_first_invite": "Zur ersten Einladung springen.", "message_composer": "Nachrichteneingabe-Feld", "n_unread_messages": { @@ -407,7 +407,6 @@ "download_logs": "Protokolle herunterladen", "downloading_logs": "Lade Protokolle herunter", "error_empty": "Bitte teile uns mit, was schief lief - oder besser, beschreibe das Problem auf GitHub in einem \"Issue\".", - "failed_send_logs": "Senden von Protokolldateien fehlgeschlagen: ", "github_issue": "GitHub-Problem", "introduction": "Wenn du uns einen Bug auf GitHub gemeldet hast, können uns Debug-Logs helfen, das Problem zu finden. ", "log_request": "Um uns zu helfen, dies in Zukunft zu vermeiden, sende uns bitte die Protokolldateien.", @@ -497,7 +496,6 @@ "legal": "Rechtliches", "light": "Hell", "loading": "Lade …", - "lobby": "Lobby", "location": "Standort", "low_priority": "Niedrige Priorität", "matrix": "Matrix", @@ -1019,8 +1017,8 @@ "sas_description": "Vergleiche eine einmalige Reihe von Emojis, sofern du an keinem Gerät eine Kamera hast", "sas_emoji_caption_self": "Bestätige, dass die folgenden Emoji auf beiden Geräten in der gleichen Reihenfolge angezeigt werden:", "sas_emoji_caption_user": "Verifiziere diesen Nutzer, indem du bestätigst, dass folgende Emojis auf dessen Bildschirm erscheinen.", - "sas_match": "Sie passen zueinander", - "sas_no_match": "Sie passen nicht zueinander", + "sas_match": "Sie stimmen überein", + "sas_no_match": "Sie stimmen nicht überein", "sas_prompt": "Vergleiche einzigartige Emojis", "scan_qr": "Verifizierung durch Scannen eines QR-Codes", "scan_qr_explainer": "Bitte %(displayName)s, deinen Code zu scannen:", @@ -2478,12 +2476,14 @@ "breadcrumb_title_forgot": "Haben Sie Ihren Wiederherstellungsschlüssel vergessen? Sie müssen Ihre Identität zurücksetzen.", "breadcrumb_warning": "Tun Sie dies nur, wenn Sie glauben, dass Ihr Konto kompromittiert wurde.", "details_title": "Angaben zur Verschlüsselung", + "do_not_close_warning": "Schließen Sie dieses Fenster nicht, bis der Reset abgeschlossen ist", "export_keys": "Schlüssel exportieren", "import_keys": "Schlüssel importieren", "other_people_device_description": "Senden Sie in verschlüsselten Räumen standardmäßig keine verschlüsselten Nachrichten an Dritte, bis Sie diese verifiziert haben", "other_people_device_label": "Senden Sie niemals verschlüsselte Nachrichten an nicht verifizierte Geräte", "other_people_device_title": "Geräte anderer Personen", "reset_identity": "Kryptografische Identität zurücksetzen", + "reset_in_progress": "Der Reset wird ausgeführt", "session_id": "Sitzungs-ID:", "session_key": "Sitzungsschlüssel:", "title": "Advanced" @@ -3906,7 +3906,6 @@ "input_devices": "Eingabegeräte", "jitsi_call": "Jitsi-Konferenz", "join_button_tooltip_call_full": "Entschuldigung — dieser Anruf ist aktuell besetzt", - "join_button_tooltip_connecting": "Verbinden", "legacy_call": "Legacy-Anruf", "maximise": "Bildschirm füllen", "maximise_call": "Anruf maximieren", diff --git a/src/i18n/strings/el.json b/src/i18n/strings/el.json index 0f3ed2c5d4..19ebbed984 100644 --- a/src/i18n/strings/el.json +++ b/src/i18n/strings/el.json @@ -316,7 +316,6 @@ "download_logs": "Λήψη αρχείων καταγραφής", "downloading_logs": "Λήψη αρχείων καταγραφής", "error_empty": "Πείτε μας τι πήγε στραβά ή, καλύτερα, δημιουργήστε ένα ζήτημα στο GitHub που να περιγράφει το πρόβλημα.", - "failed_send_logs": "Αποτυχία αποστολής αρχείων καταγραφής: ", "github_issue": "Ζήτημα GitHub", "introduction": "Εάν έχετε υποβάλει ένα σφάλμα μέσω του GitHub, τα αρχεία καταγραφής εντοπισμού σφαλμάτων μπορούν να μας βοηθήσουν να εντοπίσουμε το πρόβλημα. ", "log_request": "Για να μας βοηθήσετε να το αποτρέψουμε αυτό στο μέλλον, στείλτε μας τα αρχεία καταγραφής.", @@ -3137,7 +3136,6 @@ "hangup": "Κλείσιμο", "hide_sidebar_button": "Απόκρυψη πλαϊνής μπάρας", "input_devices": "Συσκευές εισόδου", - "join_button_tooltip_connecting": "Συνδέεται", "maximise": "Γέμισμα οθόνης", "misconfigured_server": "Η κλήση απέτυχε λόγω της λανθασμένης διάρθρωσης του διακομιστή", "misconfigured_server_description": "Παρακαλείστε να ρωτήσετε τον διαχειριστή του κεντρικού διακομιστή σας (%(homeserverDomain)s) να ρυθμίσουν έναν διακομιστή πρωτοκόλλου TURN ώστε οι κλήσεις να λειτουργούν απρόσκοπτα.", diff --git a/src/i18n/strings/eo.json b/src/i18n/strings/eo.json index a87dce68d2..2c68437086 100644 --- a/src/i18n/strings/eo.json +++ b/src/i18n/strings/eo.json @@ -301,7 +301,6 @@ "download_logs": "Elŝuti protokolon", "downloading_logs": "Elŝutante protokolon", "error_empty": "Bonvolu diri al ni kio misokazis, aŭ pli bone raporti problemon per GitHub.", - "failed_send_logs": "Malsukcesis sendi protokolon: ", "github_issue": "Problemo per GitHub", "log_request": "Por malhelpi tion ose, bonvolu sendi al ni protokolon.", "logs_sent": "Protokolo sendiĝis", @@ -2620,7 +2619,6 @@ "expand": "Reveni al voko", "hangup": "Fini vokon", "hide_sidebar_button": "Kaŝi flankan breton", - "join_button_tooltip_connecting": "Konektante", "misconfigured_server": "Voko malsukcesis pro misagordita servilo", "misconfigured_server_description": "Bonvolu peti la administranton de via hejmservilo (%(homeserverDomain)s) agordi TURN-servilon, por ke vokoj funkciu dependeble.", "more_button": "Pli", diff --git a/src/i18n/strings/es.json b/src/i18n/strings/es.json index 3b1e1e11ef..60aa278469 100644 --- a/src/i18n/strings/es.json +++ b/src/i18n/strings/es.json @@ -349,7 +349,6 @@ "download_logs": "Descargar registros", "downloading_logs": "Descargando registros", "error_empty": "Por favor, cuéntanos qué ha fallado o, mejor aún, crea una incidencia en GitHub describiendo el problema.", - "failed_send_logs": "Error al enviar registros: ", "github_issue": "Incidencia de GitHub", "introduction": "Si ya has informado de un fallo a través de GitHub, los registros de depuración nos pueden ayudar a investigar mejor el problema. ", "log_request": "Para ayudarnos a prevenir esto en el futuro, por favor, envíanos logs.", @@ -3314,7 +3313,6 @@ "hide_sidebar_button": "Ocultar menú lateral", "input_devices": "Dispositivos de entrada", "join_button_tooltip_call_full": "Lo sentimos — la llamada está llena", - "join_button_tooltip_connecting": "Conectando", "maximise": "Llenar la pantalla", "misconfigured_server": "La llamada ha fallado debido a una mala configuración del servidor", "misconfigured_server_description": "Por favor, pídele al administrador de tu servidor base (%(homeserverDomain)s) que configure un servidor TURN para que las llamadas funcionen correctamente.", diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 36c9fb95c8..0ec47dc662 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -405,7 +405,6 @@ "download_logs": "Laadi logikirjed alla", "downloading_logs": "Laadin logisid alla", "error_empty": "Palun kirjelda seda, mis läks valesti ja loo GitHub'is veateade.", - "failed_send_logs": "Logikirjete saatmine ei õnnestunud: ", "github_issue": "Veateade GitHub'is", "introduction": "Kui sa oled GitHub'is teinud meile veateate, siis silumislogid võivad aidata vea lahendamisel. ", "log_request": "Tagamaks et sama ei juhtuks tulevikus, palun saada meile salvestatud logid.", @@ -495,7 +494,6 @@ "legal": "Juriidiline teave", "light": "Hele", "loading": "Laadime…", - "lobby": "Ooteruum", "location": "Asukoht", "low_priority": "Vähetähtis", "matrix": "Matrix", @@ -3880,7 +3878,6 @@ "input_devices": "Sisendseadmed", "jitsi_call": "Jitsi-põhine kõne", "join_button_tooltip_call_full": "Vabandust, selles kõnes ei saa rohkem osalejaid olla", - "join_button_tooltip_connecting": "Kõne on ühendamisel", "legacy_call": "Vana lahendusega kõne", "maximise": "Täida ekraan", "maximise_call": "Tee kõneaken suureks", diff --git a/src/i18n/strings/fa.json b/src/i18n/strings/fa.json index 27ca4e8259..6d8d71fcff 100644 --- a/src/i18n/strings/fa.json +++ b/src/i18n/strings/fa.json @@ -287,7 +287,6 @@ "download_logs": "دانلود گزارش‌ها", "downloading_logs": "در حال دریافت لاگ‌ها", "error_empty": "لطفاً به ما بگویید چه مشکلی پیش آمد و یا اینکه لطف کنید و یک مسئله GitHub ایجاد کنید که مشکل را توصیف کند.", - "failed_send_logs": "ارسال گزارش با خطا مواجه شد: ", "github_issue": "مسئله GitHub", "log_request": "برای کمک به ما در جلوگیری از این امر در آینده ، لطفا لاگ‌ها را برای ما ارسال کنید.", "logs_sent": "گزارش‌های مربوط ارسال شد", @@ -2307,7 +2306,6 @@ "expand": "بازگشت به تماس", "hangup": "قطع", "hide_sidebar_button": "پنهان سازی نوار کناری", - "join_button_tooltip_connecting": "در حال اتصال", "misconfigured_server": "تماس به دلیل پیکربندی نادرست سرور موفقیت‌آمیز نبود", "misconfigured_server_description": "لطفا برای برقراری تماس، از مدیر %(homeserverDomain)s بخواهید سرور TURN را پیکربندی نماید.", "misconfigured_server_fallback": "از طرف دیگر، می‌توانید سعی کنید از سرور عمومی در استفاده کنید، اما این به آن اندازه قابل اعتماد نخواهد بود و آدرس IP شما را با آن سرور به اشتراک می‌گذارد. شما همچنین می توانید این قابلیت را در تنظیمات مدیریت کنید.", diff --git a/src/i18n/strings/fi.json b/src/i18n/strings/fi.json index 148ea72b0f..d6f80c03d0 100644 --- a/src/i18n/strings/fi.json +++ b/src/i18n/strings/fi.json @@ -394,7 +394,6 @@ "download_logs": "Lataa lokit", "downloading_logs": "Ladataan lokeja", "error_empty": "Kerro mikä meni pieleen, tai, mikä parempaa, luo GitHub-issue joka kuvailee ongelman.", - "failed_send_logs": "Lokien lähettäminen epäonnistui: ", "github_issue": "GitHub-issue", "introduction": "Jos olet tehnyt ilmoituksen ohjelmistovirheestä GitHubiin, vianjäljityslokit voivat auttaa ongelman selvittämisessä. ", "log_request": "Voit auttaa meitä estämään tämän toistumisen lähettämällä meille lokeja.", @@ -481,7 +480,6 @@ "legal": "Lakitekstit", "light": "Vaalea", "loading": "Ladataan…", - "lobby": "Aula", "location": "Sijainti", "low_priority": "Matala prioriteetti", "matrix": "Matrix", @@ -3420,7 +3418,6 @@ "input_devices": "Sisääntulolaitteet", "jitsi_call": "Jitsi-konferenssi", "join_button_tooltip_call_full": "Pahoittelut — tämä puhelu on täynnä", - "join_button_tooltip_connecting": "Yhdistetään", "maximise_call": "Suurenna puhelu", "metaspace_video_rooms": { "conference_room_section": "Konferenssit" diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index fd8c4b472e..ba7762b4a1 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -407,7 +407,15 @@ "download_logs": "Télécharger les journaux", "downloading_logs": "Téléchargement des journaux", "error_empty": "Dites-nous ce qui s’est mal passé ou, encore mieux, créez un rapport d’erreur sur GitHub qui décrit le problème.", - "failed_send_logs": "Échec lors de l’envoi des journaux : ", + "failed_download_logs": "Impossible de télécharger les journaux de débogage : ", + "failed_send_logs_causes": { + "disallowed_app": "Votre rapport de bogue a été rejeté. Le serveur Rageshake ne prend pas en charge cette application.", + "rejected_generic": "Votre rapport de bogue a été rejeté. Le serveur rageshake a rejeté le contenu du rapport en raison de règles internes.", + "rejected_recovery_key": "Votre rapport de bogue a été rejeté pour des raisons de sécurité, car il contenait une clé de récupération.", + "rejected_version": "Votre rapport de bogue a été rejeté car la version que vous utilisez est trop ancienne.", + "server_unknown_error": "Le serveur rageshake a rencontré une erreur inconnue et n'a pas pu gérer le rapport.", + "unknown_error": "Impossible d'envoyer les journaux de débogages." + }, "github_issue": "Rapport GitHub", "introduction": "Si vous avez soumis une anomalie via GitHub, les journaux de débogage peuvent nous aider à cibler le problème. ", "log_request": "Pour nous aider à éviter cela dans le futur, veuillez nous envoyer les journaux.", @@ -497,7 +505,6 @@ "legal": "Légal", "light": "Clair", "loading": "Chargement…", - "lobby": "Salle d'attente", "location": "Position", "low_priority": "Priorité basse", "matrix": "Matrix", @@ -2096,12 +2103,16 @@ "one": "Vous êtes en train de rejoindre %(count)s salon", "other": "Vous êtes en train de rejoindre %(count)s salons" }, + "list_title": "Liste de salons", "notification_options": "Paramètres de notifications", "open_space_menu": "Ouvrir le menu de l’espace", "redacting_messages_status": { "one": "Actuellement en train de supprimer les messages dans %(count)s salon", "other": "Actuellement en train de supprimer les messages dans %(count)s salons" }, + "room": { + "open_room": "Ouvrir salon %(roomName)s" + }, "show_less": "En voir moins", "show_n_more": { "other": "En afficher %(count)s de plus", @@ -3908,7 +3919,6 @@ "input_devices": "Périphériques d’entrée", "jitsi_call": "Conférence Jitsi", "join_button_tooltip_call_full": "Désolé — Cet appel est actuellement complet", - "join_button_tooltip_connecting": "Connexion", "legacy_call": "Appel vidéo", "maximise": "Remplir l’écran", "maximise_call": "Plein écran", diff --git a/src/i18n/strings/gl.json b/src/i18n/strings/gl.json index 1a1596ab37..f399214511 100644 --- a/src/i18n/strings/gl.json +++ b/src/i18n/strings/gl.json @@ -318,7 +318,6 @@ "download_logs": "Descargar rexistro", "downloading_logs": "Descargando o rexistro", "error_empty": "Cóntanos o que fallou ou, mellor aínda, abre un informe en GitHub que describa o problema.", - "failed_send_logs": "Fallo ao enviar os informes: ", "github_issue": "Informe en GitHub", "introduction": "Se informaches do fallo en GitHub, os rexistros poden ser útiles para arranxar o problema. ", "log_request": "Para axudarnos a evitar esto no futuro, envíanos o rexistro.", @@ -3057,7 +3056,6 @@ "hangup": "Quedada", "hide_sidebar_button": "Agochar barra lateral", "input_devices": "Dispositivos de entrada", - "join_button_tooltip_connecting": "Conectando", "misconfigured_server": "Fallou a chamada porque o servidor está mal configurado", "misconfigured_server_description": "Contacta coa administración do teu servidor (%(homeserverDomain)s) para configurar un servidor TURN para que as chamadas funcionen de xeito fiable.", "more_button": "Máis", diff --git a/src/i18n/strings/he.json b/src/i18n/strings/he.json index d2c668f5c3..1be8d900f5 100644 --- a/src/i18n/strings/he.json +++ b/src/i18n/strings/he.json @@ -289,7 +289,6 @@ "download_logs": "הורד יומנים", "downloading_logs": "מוריד לוגים", "error_empty": "אנא ספר לנו מה השתבש או, יותר טוב, צור בעיה של GitHub המתארת את הבעיה.", - "failed_send_logs": "כשל במשלוח יומנים: ", "github_issue": "סוגיית GitHub", "introduction": "אם שלחתם באג דרך GitHub, שליחת לוגים יכולה לעזור לנו לאתר את הבעיה. ", "log_request": "כדי לעזור לנו למנוע זאת בעתיד, אנא שלחו לנו יומנים .", @@ -2486,7 +2485,6 @@ "expand": "חזור לשיחה", "hangup": "ניתוק", "hide_sidebar_button": "הסתר סרגל צד", - "join_button_tooltip_connecting": "מקשר", "misconfigured_server": "השיחה נכשלה בגלל הגדרות שרת שגויות", "misconfigured_server_description": "אנא בקשו ממנהל השרת (%(homeserverDomain)s) לסדר את הגדרות שרת TURN על מנת שהשיחות יפעלו בעקביות.", "more_button": "יותר", diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index c2a5f2e868..d07513949e 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -405,7 +405,6 @@ "download_logs": "Naplók letöltése", "downloading_logs": "Naplók letöltése folyamatban", "error_empty": "Mondja el nekünk, hogy mi az, ami nem működött, vagy még jobb, ha egy GitHub-jegyben írja le a problémát.", - "failed_send_logs": "Hiba a naplók elküldése során: ", "github_issue": "GitHub-jegy", "introduction": "Ha a GitHubon keresztül küldött be hibajegyet, akkor a hibakeresési naplók segítenek nekünk felderíteni a problémát. ", "log_request": "Segítsen abban, hogy ez később ne fordulhasson elő, küldje el nekünk a naplókat.", @@ -495,7 +494,6 @@ "legal": "Jogi feltételek", "light": "Világos", "loading": "Betöltés…", - "lobby": "Váróterem", "location": "Földrajzi helyzet", "low_priority": "Alacsony prioritás", "matrix": "Matrix", @@ -3867,7 +3865,6 @@ "input_devices": "Beviteli eszközök", "jitsi_call": "Jitsi konferencia", "join_button_tooltip_call_full": "Bocsánat — ez a hívás betelt", - "join_button_tooltip_connecting": "Kapcsolódás", "legacy_call": "Örökölt hívás", "maximise": "Képernyő kitöltése", "maximise_call": "Maximalizálja a hívást", diff --git a/src/i18n/strings/id.json b/src/i18n/strings/id.json index ba4f84c79f..c591a11e65 100644 --- a/src/i18n/strings/id.json +++ b/src/i18n/strings/id.json @@ -365,7 +365,6 @@ "download_logs": "Unduh catatan", "downloading_logs": "Mengunduh catatan", "error_empty": "Mohon beri tahu kami apa saja yang salah atau, lebih baik, buat sebuah issue GitHub yang menjelaskan masalahnya.", - "failed_send_logs": "Gagal untuk mengirimkan catatan: ", "github_issue": "Masalah GitHub", "introduction": "Jika Anda mengirim sebuah kutu via GitHub, catatan pengawakutu dapat membantu kami melacak masalahnya. ", "log_request": "Untuk membantu kami mencegahnya di masa mendatang, silakan kirimkan kami catatan.", @@ -3529,7 +3528,6 @@ "hide_sidebar_button": "Sembunyikan sisi bilah", "input_devices": "Perangkat masukan", "join_button_tooltip_call_full": "Maaf — panggilan ini saat ini penuh", - "join_button_tooltip_connecting": "Menghubungkan", "maximise": "Penuhi layar", "misconfigured_server": "Panggilan gagal karena servernya tidak dikonfigurasi dengan benar", "misconfigured_server_description": "Mohon tanyakan ke administrator homeserver Anda (%(homeserverDomain)s) untuk mengkonfigurasikan server TURN supaya panggilan dapat bekerja dengan benar.", diff --git a/src/i18n/strings/is.json b/src/i18n/strings/is.json index 5de21e263c..179961871d 100644 --- a/src/i18n/strings/is.json +++ b/src/i18n/strings/is.json @@ -316,7 +316,6 @@ "description": "Atvikaskrár innihalda gögn varðandi virkni hugbúnaðarins en líka notandanafn þitt, auðkenni eða samnefni spjallrása sem þú hefur skoðað, hvaða viðmótshluta þú hefur átt við, auk notendanafna annarra notenda. Atvikaskrár innihalda ekki skilaboð.", "download_logs": "Niðurhal atvikaskrá", "downloading_logs": "Sæki atvikaskrá", - "failed_send_logs": "Mistókst að senda atvikaskrár: ", "github_issue": "Villutilkynning á GitHub", "introduction": "Ef þú hefur tilkynnt vandamál í gegnum GitHub, þá geta atvikaskrár hjálpað okkur við að finna ástæður vandamálanna. ", "logs_sent": "Sendi atvikaskrár", @@ -2953,7 +2952,6 @@ "hide_sidebar_button": "Fela hliðarspjald", "input_devices": "Inntakstæki", "join_button_tooltip_call_full": "Því miður - þetta símtal er fullt í augnablikinu", - "join_button_tooltip_connecting": "Tengist", "maximise": "Fylla skjá", "misconfigured_server": "Símtal mistókst vegna vanstillingar netþjóns", "misconfigured_server_description": "Spurðu kerfisstjóra (%(homeserverDomain)s) heimaþjónsins þíns um að setja upp TURN-þjón til að tryggja að símtöl virki eðlilega.", diff --git a/src/i18n/strings/it.json b/src/i18n/strings/it.json index e3c38a579f..5e240b68c3 100644 --- a/src/i18n/strings/it.json +++ b/src/i18n/strings/it.json @@ -372,7 +372,6 @@ "download_logs": "Scarica i log", "downloading_logs": "Scaricamento dei log", "error_empty": "Per favore dicci cos'è andato storto, o meglio, crea una segnalazione su GitHub che descriva il problema.", - "failed_send_logs": "Invio dei log fallito: ", "github_issue": "Segnalazione GitHub", "introduction": "Se hai inviato un errore via GitHub, i log di debug possono aiutarci ad individuare il problema. ", "log_request": "Per aiutarci a prevenire questa cosa in futuro, inviaci i log.", @@ -461,7 +460,6 @@ "legal": "Informazioni legali", "light": "Chiaro", "loading": "Caricamento…", - "lobby": "Sala d’attesa", "location": "Posizione", "low_priority": "Bassa priorità", "matrix": "Matrix", @@ -3580,7 +3578,6 @@ "input_devices": "Dispositivi di input", "jitsi_call": "Conferenza Jitsi", "join_button_tooltip_call_full": "Spiacenti — questa chiamata è piena", - "join_button_tooltip_connecting": "In connessione", "legacy_call": "Chiamata legacy", "maximise": "Riempi schermo", "maximise_call": "Massimizza la chiamata", diff --git a/src/i18n/strings/ja.json b/src/i18n/strings/ja.json index f49db86f20..ee9172d575 100644 --- a/src/i18n/strings/ja.json +++ b/src/i18n/strings/ja.json @@ -355,7 +355,6 @@ "download_logs": "ログのダウンロード", "downloading_logs": "ログをダウンロードしています", "error_empty": "発生した問題を教えてください。または、問題を説明するGitHub issueを作成してください。", - "failed_send_logs": "ログの送信に失敗しました: ", "introduction": "もしGitHubで不具合を報告した場合は、デバッグログが問題の解決に役立ちます。 ", "log_request": "今後これが起こらないようにするために、ログを送信してください。", "logs_sent": "ログが送信されました", @@ -3294,7 +3293,6 @@ "hide_sidebar_button": "サイドバーを表示しない", "input_devices": "入力装置", "join_button_tooltip_call_full": "すみません ― この通話は現在満員です", - "join_button_tooltip_connecting": "接続しています", "maximise": "全画面", "misconfigured_server": "サーバーの不正な設定のため通話に失敗しました", "misconfigured_server_description": "安定した通話のために、ホームサーバー(%(homeserverDomain)s)の管理者にTURNサーバーの設定を依頼してください。", diff --git a/src/i18n/strings/ka.json b/src/i18n/strings/ka.json index 8b83f48166..2f5610c106 100644 --- a/src/i18n/strings/ka.json +++ b/src/i18n/strings/ka.json @@ -348,7 +348,6 @@ "download_logs": "ჩამოტვირთეთ ჟურნალები", "downloading_logs": "ლოგების ჩამოტვირთვა", "error_empty": "გთხოვთ, გვითხრათ, რა მოხდა არასწორედ, ან, უკეთესი, შექმენით GitHub პრობლემა, რომელიც აღწერს პრობლემას.", - "failed_send_logs": "ჟურნალის გაგზავნა ვერ მოხერხდა: ", "github_issue": "GitHub-ის პრობლემა", "introduction": "თუ თქვენ წარადგინეთ ხარვეზი GitHub-ის მეშვეობით, გამართვის ჟურნალები დაგვეხმარება პრობლემის გარკვევაში. ", "log_request": "მომავალში ამის თავიდან ასაცილებლად, გთხოვთ გამოგვიგზავნეთ ჟურნალები .", @@ -2824,7 +2823,6 @@ "hide_sidebar_button": "გვერდითი ზოლის დამალვა", "input_devices": "შეყვანის მოწყობილობები", "join_button_tooltip_call_full": "უკაცრავად - ეს ზარი ამჟამად სავსეა", - "join_button_tooltip_connecting": "დაკავშირება", "maximise": "ეკრანის შევსება", "misconfigured_server": "ზარი ვერ მოხერხდა სერვერის არასწორი კონფიგურაციის გამო", "misconfigured_server_description": "გთხოვთ, ჰკითხოთ თქვენი სახლის სერვერის ადმინისტრატორს (%(homeserverDomain)s ) TURN სერვერის კონფიგურაცია, რათა ზარებმა საიმედოდ იმუშაოს.", diff --git a/src/i18n/strings/lo.json b/src/i18n/strings/lo.json index 142bbc5a5b..eeb3bb883f 100644 --- a/src/i18n/strings/lo.json +++ b/src/i18n/strings/lo.json @@ -315,7 +315,6 @@ "download_logs": "ບັນທຶກການດາວໂຫຼດ", "downloading_logs": "ບັນທຶກການດາວໂຫຼດ", "error_empty": "ກະລຸນາບອກພວກເຮົາວ່າມີຫຍັງຜິດພາດ ຫຼື, ດີກວ່າ, ສ້າງບັນຫາ GitHub ເພື່ອອະທິບາຍບັນຫາ.", - "failed_send_logs": "ສົ່ງບັນທຶກບໍ່ສຳເລັດ: ", "github_issue": "ບັນຫາ GitHub", "introduction": "ຖ້າທ່ານໄດ້ສົ່ງຂໍ້ບົກພ່ອງຜ່ານ GitHub, ບັນທຶກການຂໍ້ຜິດພາດສາມາດຊ່ວຍພວກເຮົາຕິດຕາມບັນຫາໄດ້. ", "log_request": "ເພື່ອຊ່ວຍພວກເຮົາປ້ອງກັນສິ່ງນີ້ໃນອະນາຄົດ, ກະລຸນາ ສົ່ງບັນທຶກໃຫ້ພວກເຮົາ.", @@ -2959,7 +2958,6 @@ "hangup": "ວາງສາຍ", "hide_sidebar_button": "ເຊື່ອງແຖບດ້ານຂ້າງ", "input_devices": "ອຸປະກອນຂາເຂົ້າ", - "join_button_tooltip_connecting": "ກຳລັງເຊື່ອມຕໍ່", "misconfigured_server": "ການໂທບໍ່ສຳເລັດເນື່ອງຈາກເຊີບເວີຕັ້ງຄ່າຜິດພາດ", "misconfigured_server_description": "ກະລຸນາຕິດຕໍ່ຜູ້ຄຸ້ມຄອງສະຖານີຂອງທ່ານ (%(homeserverDomain)s) ເພື່ອກໍານົດຄ່າຂອງ TURN Server ເພື່ອໃຫ້ການໂທເຮັດວຽກໄດ້ຢ່າງສະຖຽນ.", "more_button": "ເພີ່ມເຕີມ", diff --git a/src/i18n/strings/lt.json b/src/i18n/strings/lt.json index 74a77142e7..2c2a0361dd 100644 --- a/src/i18n/strings/lt.json +++ b/src/i18n/strings/lt.json @@ -253,7 +253,6 @@ "download_logs": "Parsisiųsti žurnalus", "downloading_logs": "Parsiunčiami žurnalai", "error_empty": "Pasakyite mums kas nutiko, arba, dar geriau, sukurkite GitHub problemą su jos apibūdinimu.", - "failed_send_logs": "Nepavyko išsiųsti žurnalų: ", "github_issue": "GitHub problema", "introduction": "Jei per GitHub pateikėte klaidą, derinimo žurnalai gali padėti mums nustatyti problemą. ", "log_request": "Norėdami padėti mums išvengti to ateityje, atsiųskite mums žurnalus.", @@ -2355,7 +2354,6 @@ "expand": "Grįžti prie skambučio", "hangup": "Padėti ragelį", "hide_sidebar_button": "Slėpti šoninę juostą", - "join_button_tooltip_connecting": "Jungiamasi", "misconfigured_server": "Skambutis nepavyko dėl neteisingai sukonfigūruoto serverio", "misconfigured_server_description": "Paprašykite savo serverio administratoriaus (%(homeserverDomain)s) sukonfiguruoti TURN serverį, kad skambučiai veiktų patikimai.", "more_button": "Daugiau", diff --git a/src/i18n/strings/lv.json b/src/i18n/strings/lv.json index cfb087c075..97f28fc1de 100644 --- a/src/i18n/strings/lv.json +++ b/src/i18n/strings/lv.json @@ -404,7 +404,6 @@ "download_logs": "Lejupielādēt žurnālus", "downloading_logs": "Žurnālu lejupielāde", "error_empty": "Lūdzu, pastāstiet mums, kas nogāja greizi, vai reģistrējiet GitHub problēmu ar tās detalizētu aprakstu.", - "failed_send_logs": "Neizdevās nosūtīt logfailus: ", "github_issue": "GitHub problēma", "introduction": "Ja esat iesniedzis kļūdu, izmantojot GitHub, atkļūdošanas žurnāli var mums palīdzēt izsekot problēmai. ", "log_request": "Lai palīdzētu mums to novērst nākotnē, lūdzu, nosūtiet mums žurnālus.", @@ -494,7 +493,6 @@ "legal": "Juridiskā informācija", "light": "Gaiša", "loading": "Notiek ielāde…", - "lobby": "Vestibils", "location": "Atrašanās vieta", "low_priority": "Zems svarīgums", "matrix": "Matrix", @@ -3522,7 +3520,6 @@ "hide_sidebar_button": "Paslēpt sānjoslu", "input_devices": "Ievades ierīces", "join_button_tooltip_call_full": "Atvainojiet, šis zvans pašlaik ir pilns", - "join_button_tooltip_connecting": "Savieno", "maximise": "Aizpildīt ekrānu", "metaspace_video_rooms": { "conference_room_section": "Konferences" diff --git a/src/i18n/strings/mg_MG.json b/src/i18n/strings/mg_MG.json index 7497294194..f566a109b7 100644 --- a/src/i18n/strings/mg_MG.json +++ b/src/i18n/strings/mg_MG.json @@ -369,7 +369,6 @@ "download_logs": "Haka vaovao", "downloading_logs": "Misintona hazo", "error_empty": "Mba lazao anay izay tsy nety na, tsara kokoa, mamorona olana GitHub izay mamaritra ny olana.", - "failed_send_logs": "Tsy tontonsa ny fandefasana rakitra: ", "github_issue": "Olana GitHub", "introduction": "Raha nandefa bibikely taminy alàlan'ny GitHub ianao, dia afaka manampy antsika hanara-maso ilay olana ny log debug.", "log_request": "Mba ho fanampiana atsika hisoroka izany amin'ny ho avy, azafady andefaso hazo izahay .", @@ -458,7 +457,6 @@ "legal": "Mitovy", "light": "Fahazavana", "loading": "Manatontonsa", - "lobby": "Fandraisana", "location": "Toerana isihany", "low_priority": "Laharam-pahamehana ambany", "matrix": "Matrix", @@ -3562,7 +3560,6 @@ "input_devices": "Fampidirana fitaovana", "jitsi_call": "Fihaonambe Jitsi", "join_button_tooltip_call_full": "Miala tsiny — feno ity antso ity amin'izao fotoana izao", - "join_button_tooltip_connecting": "Mampifandray", "legacy_call": "Antso", "maximise": "Ameno ny efijery", "maximise_call": "Ampitomboy ny antso", diff --git a/src/i18n/strings/nb_NO.json b/src/i18n/strings/nb_NO.json index 26a46d268f..f871244d7b 100644 --- a/src/i18n/strings/nb_NO.json +++ b/src/i18n/strings/nb_NO.json @@ -407,7 +407,6 @@ "download_logs": "Last ned logger", "downloading_logs": "Laster ned logger", "error_empty": "Fortell oss hva som gikk galt, eller bedre, opprett et GitHub-problem som beskriver problemet.", - "failed_send_logs": "Mislyktes i å sende loggbøker: ", "github_issue": "Github-saksrapport", "introduction": "Hvis du har sendt inn en feil via GitHub, kan feilsøkingslogger hjelpe oss med å spore opp problemet. ", "log_request": "For å hjelpe oss med å forhindre dette i fremtiden, vennligst send oss loggfiler.", @@ -497,7 +496,6 @@ "legal": "Juridisk", "light": "Lys", "loading": "Laster inn …", - "lobby": "Lobby", "location": "Lokasjon", "low_priority": "Lavprioritet", "matrix": "Matrix", @@ -3906,7 +3904,6 @@ "input_devices": "Inndataenheter", "jitsi_call": "Jitsi Conference", "join_button_tooltip_call_full": "Beklager - denne samtalen er for øyeblikket full", - "join_button_tooltip_connecting": "Kobler til", "legacy_call": "Eldre samtale", "maximise": "Fyll skjermen", "maximise_call": "Maksimer samtalen", diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index 9e8e3bbff6..ff287e80e1 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -336,7 +336,6 @@ "download_logs": "Logs downloaden", "downloading_logs": "Logs downloaden", "error_empty": "Laat ons weten wat er verkeerd is gegaan, of nog beter, maak een foutrapport aan op GitHub, waarin je het probleem beschrijft.", - "failed_send_logs": "Versturen van logs mislukt: ", "github_issue": "GitHub-melding", "introduction": "Als je een bug via GitHub hebt ingediend, kunnen foutopsporingslogboeken ons helpen het probleem op te sporen. ", "log_request": "Stuur ons jouw logs om dit in de toekomst te helpen voorkomen.", @@ -3114,7 +3113,6 @@ "hide_sidebar_button": "Zijbalk verbergen", "input_devices": "Invoer apparaten", "join_button_tooltip_call_full": "Sorry — dit gesprek is momenteel vol", - "join_button_tooltip_connecting": "Verbinden", "maximise": "Scherm vullen", "misconfigured_server": "Oproep mislukt door verkeerd geconfigureerde server", "misconfigured_server_description": "Vraag je homeserver-beheerder (%(homeserverDomain)s) een TURN-server te configureren voor de betrouwbaarheid van de oproepen.", diff --git a/src/i18n/strings/pl.json b/src/i18n/strings/pl.json index 24b026098b..8795a74b8e 100644 --- a/src/i18n/strings/pl.json +++ b/src/i18n/strings/pl.json @@ -407,7 +407,6 @@ "download_logs": "Pobierz dzienniki", "downloading_logs": "Pobieranie logów", "error_empty": "Powiedz nam, co poszło nie tak, lub nawet lepiej - utwórz zgłoszenie na platformie GitHub, które opisuje problem.", - "failed_send_logs": "Nie udało się wysłać dzienników: ", "github_issue": "Zgłoszenie GitHub", "introduction": "Jeśli zgłosiłeś błąd za pomocą serwisu GitHub, dzienniki debugowania mogą pomóc nam w namierzeniu problemu. ", "log_request": "Aby uniknąć tego problemu w przyszłości, wyślij nam dzienniki.", @@ -498,7 +497,6 @@ "legal": "Zasoby prawne", "light": "Jasny", "loading": "Wczytywanie…", - "lobby": "Poczekalnia", "location": "Lokalizacja", "low_priority": "Niski priorytet", "matrix": "Matrix", @@ -3918,7 +3916,6 @@ "input_devices": "Urządzenia wejściowe", "jitsi_call": "Konferencja Jitsi", "join_button_tooltip_call_full": "Przepraszamy — to połączenie jest już zapełnione", - "join_button_tooltip_connecting": "Łączenie", "legacy_call": "Połączenie Legacy", "maximise": "Wypełnij ekran", "maximise_call": "Maksymalizuj połączenie", diff --git a/src/i18n/strings/pt.json b/src/i18n/strings/pt.json index 0fd31452a2..7f348223e9 100644 --- a/src/i18n/strings/pt.json +++ b/src/i18n/strings/pt.json @@ -405,7 +405,6 @@ "download_logs": "Descarrega os registos", "downloading_logs": "Descarregando registos", "error_empty": "Diz-nos o que correu mal ou, melhor ainda, cria uma questão no GitHub que descreva o problema.", - "failed_send_logs": "Falha ao enviar registos: ", "github_issue": "Problema no GitHub", "introduction": "Se submeteste um erro através do GitHub, os registos de depuração podem ajudar-nos a localizar o problema. ", "log_request": "Para nos ajudar a evitar esta situação no futuro, envia-nos os registos para .", @@ -495,7 +494,6 @@ "legal": "Legal", "light": "Claro", "loading": "A carregar…", - "lobby": "Átrio", "location": "Localização", "low_priority": "Baixa prioridade", "matrix": "Matrix", @@ -3897,7 +3895,6 @@ "input_devices": "Dispositivos de entrada", "jitsi_call": "Conferência Jitsi", "join_button_tooltip_call_full": "Desculpa, neste momento, esta chamada está cheia", - "join_button_tooltip_connecting": "A conectar...", "legacy_call": "Chamada Legacy", "maximise": "Preenche o ecrã", "maximise_call": "Maximiza a chamada", diff --git a/src/i18n/strings/pt_BR.json b/src/i18n/strings/pt_BR.json index 02fb06c0a6..d2cd4fe848 100644 --- a/src/i18n/strings/pt_BR.json +++ b/src/i18n/strings/pt_BR.json @@ -376,7 +376,6 @@ "download_logs": "Baixar relatórios", "downloading_logs": "Baixando relatórios", "error_empty": "Por favor, diga-nos o que aconteceu de errado ou, ainda melhor, crie um bilhete de erro no GitHub que descreva o problema.", - "failed_send_logs": "Falha ao enviar os relatórios:· ", "github_issue": "Bilhete de erro no GitHub", "introduction": "Se você enviou um bug pelo GitHub, os logs de depuração podem nos ajudar a rastrear o problema. ", "log_request": "Para nos ajudar a evitar isso no futuro, envie-nos os relatórios.", @@ -3166,7 +3165,6 @@ "hide_sidebar_button": "Esconder a barra lateral", "input_devices": "Dispositivos de entrada", "join_button_tooltip_call_full": "Desculpe, esta chamada está lotada no momento", - "join_button_tooltip_connecting": "Conectando", "maximise": "Preencher tela", "misconfigured_server": "A chamada falhou por conta de má configuração no servidor", "misconfigured_server_description": "Por favor, peça ao administrador do seu servidor (%(homeserverDomain)s) para configurar um servidor TURN, de modo que as chamadas funcionem de maneira estável.", diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index d91a348e60..190dbe30a1 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -366,7 +366,6 @@ "download_logs": "Скачать журналы", "downloading_logs": "Скачивание журналов", "error_empty": "Пожалуйста, расскажите нам что пошло не так, либо, ещё лучше, создайте отчёт в GitHub с описанием проблемы.", - "failed_send_logs": "Не удалось отправить журналы: ", "github_issue": "GitHub вопрос", "introduction": "Если вы отправили ошибку через GitHub, журналы отладки могут помочь нам отследить проблему. ", "log_request": "Чтобы помочь нам предотвратить это в будущем, пожалуйста, отправьте нам логи.", @@ -3562,7 +3561,6 @@ "hide_sidebar_button": "Скрыть боковую панель", "input_devices": "Устройства ввода", "join_button_tooltip_call_full": "Извините — этот вызов в настоящее время заполнен", - "join_button_tooltip_connecting": "Подключение", "maximise": "Заполнить экран", "misconfigured_server": "Вызов не состоялся из-за неправильно настроенного сервера", "misconfigured_server_description": "Попросите администратора вашего домашнего сервера (%(homeserverDomain)s) настроить сервер TURN для надежной работы звонков.", diff --git a/src/i18n/strings/sk.json b/src/i18n/strings/sk.json index c8a373fb3c..b5528cb237 100644 --- a/src/i18n/strings/sk.json +++ b/src/i18n/strings/sk.json @@ -366,7 +366,6 @@ "download_logs": "Stiahnuť záznamy", "downloading_logs": "Sťahovanie záznamov", "error_empty": "Povedzte nám prosím, čo sa pokazilo, alebo radšej vytvorte príspevok v službe GitHub, v ktorom problém popíšete.", - "failed_send_logs": "Nepodarilo sa odoslať záznamy: ", "github_issue": "Správa o probléme na GitHub", "introduction": "Ak ste odoslali chybu prostredníctvom služby GitHub, záznamy o ladení nám môžu pomôcť nájsť problém. ", "log_request": "Aby ste nám pomohli tomuto v budúcnosti zabrániť, pošlite nám prosím záznamy o chybe.", @@ -3590,7 +3589,6 @@ "hide_sidebar_button": "Skryť bočný panel", "input_devices": "Vstupné zariadenia", "join_button_tooltip_call_full": "Prepáčte — tento hovor je momentálne obsadený", - "join_button_tooltip_connecting": "Pripájanie", "maximise": "Vyplniť obrazovku", "misconfigured_server": "Hovor zlyhal z dôvodu nesprávne nastaveného servera", "misconfigured_server_description": "Prosím, požiadajte správcu vášho domovského servera (%(homeserverDomain)s) aby nakonfiguroval Turn server, čo zlepší spoľahlivosť audio / video hovorov.", diff --git a/src/i18n/strings/sq.json b/src/i18n/strings/sq.json index cdbffbc51e..bcd804bf15 100644 --- a/src/i18n/strings/sq.json +++ b/src/i18n/strings/sq.json @@ -357,7 +357,6 @@ "download_logs": "Shkarko regjistra", "downloading_logs": "Po shkarkohen regjistra", "error_empty": "Ju lutemi, na tregoni ç’shkoi keq ose, akoma më mirë, krijoni në GitHub një çështje që përshkruan problemin.", - "failed_send_logs": "S’u arrit të dërgoheshin regjistra: ", "github_issue": "Çështje në GitHub", "introduction": "Nëse keni parashtruar një të metë përmes GitHub-i, regjistrat e diagnostikimit na ndihmojnë të kapim problemin. ", "log_request": "Për të na ndihmuar ta parandalojmë këtë në të ardhmen, ju lutemi, dërgonani regjistra.", @@ -3359,7 +3358,6 @@ "hide_sidebar_button": "Fshihe anështyllën", "input_devices": "Pajisje input-i", "join_button_tooltip_call_full": "Na ndjeni — aktualisht kjo thirrje është plot", - "join_button_tooltip_connecting": "Po lidhet", "maximise": "Mbushe ekranin", "misconfigured_server": "Thirrja dështoi për shkak shërbyesi të keqformësuar", "misconfigured_server_description": "Që thirrjet të funksionojnë pa probleme, ju lutemi, kërkojini përgjegjësit të shërbyesit tuaj Home (%(homeserverDomain)s) të formësojë një shërbyes TURN.", diff --git a/src/i18n/strings/sv.json b/src/i18n/strings/sv.json index 46b7fc196f..a2f58e0049 100644 --- a/src/i18n/strings/sv.json +++ b/src/i18n/strings/sv.json @@ -405,7 +405,6 @@ "download_logs": "Ladda ner loggar", "downloading_logs": "Laddar ner loggar", "error_empty": "Berätta vad som gick fel, eller skapa ännu hellre ett GitHub-ärende som beskriver problemet.", - "failed_send_logs": "Misslyckades att skicka loggar: ", "github_issue": "GitHub-ärende", "introduction": "Om du har rapporterat en bugg via GitHub så kan felsökningsloggar hjälpa oss att hitta problemet. ", "log_request": "För att hjälpa oss att förhindra detta i framtiden, vänligen skicka oss loggar.", @@ -495,7 +494,6 @@ "legal": "Juridiskt", "light": "Ljust", "loading": "Laddar …", - "lobby": "Lobby", "location": "Plats", "low_priority": "Låg prioritet", "matrix": "Matrix", @@ -3786,7 +3784,6 @@ "input_devices": "Ingångsenheter", "jitsi_call": "Jitsi-gruppsamtal", "join_button_tooltip_call_full": "Tyvärr - det här samtalet är för närvarande fullt", - "join_button_tooltip_connecting": "Ansluter", "legacy_call": "Standardsamtal", "maximise": "Fyll skärmen", "maximise_call": "Maximera samtal", diff --git a/src/i18n/strings/tr.json b/src/i18n/strings/tr.json index 8be7a15f8d..9c1ad1b6fe 100644 --- a/src/i18n/strings/tr.json +++ b/src/i18n/strings/tr.json @@ -405,7 +405,6 @@ "download_logs": "Günlükleri indir", "downloading_logs": "Günlükler indiriliyor", "error_empty": "Lütfen neyin yanlış gittiğini bize bildirin ya da en güzeli problemi tanımlayan bir GitHub talebi oluşturun.", - "failed_send_logs": "Logların gönderilmesi başarısız: ", "github_issue": "GitHub sorunu", "introduction": "GitHub aracılığıyla bir hata bildirdiyseniz, hata ayıklama günlükleri sorunu bulmamızda yardımcı olabilir. ", "log_request": "Bunun gelecekte de olmasının önüne geçmek için lütfen günceleri bize gönderin.", @@ -495,7 +494,6 @@ "legal": "Yasal", "light": "Aydınlık", "loading": "Yükleniyor...", - "lobby": "Lobi", "location": "Konum", "low_priority": "Düşük öncelik", "matrix": "Matrix", @@ -3890,7 +3888,6 @@ "input_devices": "Giriş aygıtları", "jitsi_call": "Jitsi Konferansı", "join_button_tooltip_call_full": "Üzgünüz - bu çağrı şu anda dolu", - "join_button_tooltip_connecting": "Bağlanıyor", "legacy_call": "Eski Tip Çağrı", "maximise": "Ekranı kapla", "maximise_call": "Arama ekranı kapla", diff --git a/src/i18n/strings/uk.json b/src/i18n/strings/uk.json index bd7bc660ac..52fd2b6604 100644 --- a/src/i18n/strings/uk.json +++ b/src/i18n/strings/uk.json @@ -407,7 +407,6 @@ "download_logs": "Завантажити журнали", "downloading_logs": "Завантаження журналів", "error_empty": "Будь ласка, повідомте нам, що пішло не так; а ще краще створіть обговорення на GitHub із описом проблеми.", - "failed_send_logs": "Не вдалося надіслати журнали: ", "github_issue": "Обговорення на GitHub", "introduction": "Якщо ви надіслали звіт про ваду на GitHub, журнали зневадження можуть допомогти нам визначити проблему. ", "log_request": "Щоб уникнути цього в майбутньому просимо надіслати нам журнал.", @@ -497,7 +496,6 @@ "legal": "Правові положення", "light": "Світла", "loading": "Завантаження…", - "lobby": "Зона очікування", "location": "Місцеперебування", "low_priority": "Неважливі", "matrix": "Matrix", @@ -3911,7 +3909,6 @@ "input_devices": "Пристрої вводу", "jitsi_call": "Конференція Jitsi", "join_button_tooltip_call_full": "Перепрошуємо, цей виклик заповнено", - "join_button_tooltip_connecting": "З'єднання", "legacy_call": "Застарілий спосіб виклику", "maximise": "Заповнити екран", "maximise_call": "Розгорнути виклик", diff --git a/src/i18n/strings/vi.json b/src/i18n/strings/vi.json index 57c0fb4108..dd2e6fecf3 100644 --- a/src/i18n/strings/vi.json +++ b/src/i18n/strings/vi.json @@ -332,7 +332,6 @@ "download_logs": "Tải xuống nhật ký", "downloading_logs": "Đang tải nhật ký xuống", "error_empty": "Vui lòng cho chúng tôi biết điều gì đã xảy ra hoặc tốt hơn là tạo sự cố trên GitHub để mô tả vấn đề.", - "failed_send_logs": "Không gửi được nhật ký: ", "github_issue": "Sự cố GitHub", "introduction": "Nếu bạn đã báo cáo lỗi qua GitHub, nhật ký gỡ lỗi có thể giúp chúng tôi theo dõi vấn đề. ", "log_request": "Để giúp chúng tôi ngăn chặn điều này trong tương lai, vui lòng gửi nhật ký cho chúng tôi send us logs.", @@ -3237,7 +3236,6 @@ "hide_sidebar_button": "Ẩn thanh bên", "input_devices": "Thiết bị đầu vào", "join_button_tooltip_call_full": "Xin lỗi — cuộc gọi này đang đầy", - "join_button_tooltip_connecting": "Đang kết nối", "maximise": "Vừa màn hình", "misconfigured_server": "Thực hiện cuộc gọi thất bại do thiết lập máy chủ sai", "misconfigured_server_description": "Vui lòng yêu cầu quản trị viên máy chủ của bạn (%(homeserverDomain)s) thiết lập máy chủ TURN để cuộc gọi hoạt động ổn định.", diff --git a/src/i18n/strings/zh_Hans.json b/src/i18n/strings/zh_Hans.json index f9c4122b21..e42bb2160a 100644 --- a/src/i18n/strings/zh_Hans.json +++ b/src/i18n/strings/zh_Hans.json @@ -349,7 +349,6 @@ "download_logs": "下载日志", "downloading_logs": "正在下载日志", "error_empty": "请告诉我们哪里出错了,或最好创建一个 GitHub issue 来描述此问题。", - "failed_send_logs": "无法发送日志: ", "github_issue": "GitHub 上的 issue", "introduction": "若你通过GitHub提交bug,则调试日志能帮助我们追踪问题。 ", "log_request": "要帮助我们防止其以后发生,请给我们发送日志。", @@ -3215,7 +3214,6 @@ "hide_sidebar_button": "隐藏侧边栏", "input_devices": "输入设备", "join_button_tooltip_call_full": "抱歉——目前线路拥挤", - "join_button_tooltip_connecting": "连接中", "maximise": "填满屏幕", "misconfigured_server": "服务器配置错误导致通话失败", "misconfigured_server_description": "请联系你的家服务器(%(homeserverDomain)s)的管理员配置 TURN 服务器,以确保通话过程稳定。", diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index ecffe184e9..f670086a7c 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -364,7 +364,6 @@ "download_logs": "下載紀錄檔", "downloading_logs": "正在下載紀錄檔", "error_empty": "請告訴我們發生了什麼錯誤,或更好的是,在 GitHub 上建立描述問題的議題。", - "failed_send_logs": "無法傳送除錯訊息: ", "github_issue": "GitHub 議題", "introduction": "若您透過 GitHub 遞交錯誤,除錯紀錄檔可以協助我們追蹤問題。 ", "log_request": "要協助我們讓這個問題不再發生,請將紀錄檔傳送給我們。", @@ -3482,7 +3481,6 @@ "hide_sidebar_button": "隱藏側邊欄", "input_devices": "輸入裝置", "join_button_tooltip_call_full": "抱歉 — 此通話目前已滿", - "join_button_tooltip_connecting": "連線中", "maximise": "填滿螢幕", "misconfigured_server": "由於伺服器設定錯誤,無法通話", "misconfigured_server_description": "請聯繫您家伺服器(%(homeserverDomain)s)的管理員建立一套 TURN 伺服器,使通話能更穩定運作。", From 82957507d078a9fcb26001792cb703c4ec6bedb4 Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Fri, 7 Mar 2025 16:29:39 +0530 Subject: [PATCH 050/458] Room List Store: Implement rest of the primary filters (#29444) * Implement rest of the primary filters * Support the new filters in the store --- src/stores/room-list-v3/RoomListStoreV3.ts | 10 +- .../skip-list/filters/PeopleFilter.ts | 21 ++++ .../skip-list/filters/RoomsFilter.ts | 21 ++++ .../skip-list/filters/UnreadFilter.ts | 20 ++++ .../room-list-v3/skip-list/filters/index.ts | 3 + .../room-list-v3/RoomListStoreV3-test.ts | 97 +++++++++++++++++++ 6 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 src/stores/room-list-v3/skip-list/filters/PeopleFilter.ts create mode 100644 src/stores/room-list-v3/skip-list/filters/RoomsFilter.ts create mode 100644 src/stores/room-list-v3/skip-list/filters/UnreadFilter.ts diff --git a/src/stores/room-list-v3/RoomListStoreV3.ts b/src/stores/room-list-v3/RoomListStoreV3.ts index 83e73e1b7f..df7246e95c 100644 --- a/src/stores/room-list-v3/RoomListStoreV3.ts +++ b/src/stores/room-list-v3/RoomListStoreV3.ts @@ -25,6 +25,14 @@ import { EffectiveMembership, getEffectiveMembership, getEffectiveMembershipTag import SpaceStore from "../spaces/SpaceStore"; import { UPDATE_HOME_BEHAVIOUR, UPDATE_SELECTED_SPACE } from "../spaces"; import { FavouriteFilter } from "./skip-list/filters/FavouriteFilter"; +import { UnreadFilter } from "./skip-list/filters/UnreadFilter"; +import { PeopleFilter } from "./skip-list/filters/PeopleFilter"; +import { RoomsFilter } from "./skip-list/filters/RoomsFilter"; + +/** + * These are the filters passed to the room skip list. + */ +const FILTERS = [new FavouriteFilter(), new UnreadFilter(), new PeopleFilter(), new RoomsFilter()]; /** * This store allows for fast retrieval of the room list in a sorted and filtered manner. @@ -96,7 +104,7 @@ export class RoomListStoreV3Class extends AsyncStoreWithClient { protected async onReady(): Promise { if (this.roomSkipList?.initialized || !this.matrixClient) return; const sorter = new RecencySorter(this.matrixClient.getSafeUserId()); - this.roomSkipList = new RoomSkipList(sorter, [new FavouriteFilter()]); + this.roomSkipList = new RoomSkipList(sorter, FILTERS); const rooms = this.getRooms(); await SpaceStore.instance.storeReadyPromise; this.roomSkipList.seed(rooms); diff --git a/src/stores/room-list-v3/skip-list/filters/PeopleFilter.ts b/src/stores/room-list-v3/skip-list/filters/PeopleFilter.ts new file mode 100644 index 0000000000..742eb40abe --- /dev/null +++ b/src/stores/room-list-v3/skip-list/filters/PeopleFilter.ts @@ -0,0 +1,21 @@ +/* +Copyright 2025 New Vector 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 type { Room } from "matrix-js-sdk/src/matrix"; +import type { Filter } from "."; +import { FilterKey } from "."; +import DMRoomMap from "../../../../utils/DMRoomMap"; + +export class PeopleFilter implements Filter { + public matches(room: Room): boolean { + // Match rooms that are DMs + return !!DMRoomMap.shared().getUserIdForRoomId(room.roomId); + } + + public get key(): FilterKey.PeopleFilter { + return FilterKey.PeopleFilter; + } +} diff --git a/src/stores/room-list-v3/skip-list/filters/RoomsFilter.ts b/src/stores/room-list-v3/skip-list/filters/RoomsFilter.ts new file mode 100644 index 0000000000..58349dcea2 --- /dev/null +++ b/src/stores/room-list-v3/skip-list/filters/RoomsFilter.ts @@ -0,0 +1,21 @@ +/* +Copyright 2025 New Vector 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 type { Room } from "matrix-js-sdk/src/matrix"; +import type { Filter } from "."; +import { FilterKey } from "."; +import DMRoomMap from "../../../../utils/DMRoomMap"; + +export class RoomsFilter implements Filter { + public matches(room: Room): boolean { + // This should filter rooms that are not DMs + return !DMRoomMap.shared().getUserIdForRoomId(room.roomId); + } + + public get key(): FilterKey.RoomsFilter { + return FilterKey.RoomsFilter; + } +} diff --git a/src/stores/room-list-v3/skip-list/filters/UnreadFilter.ts b/src/stores/room-list-v3/skip-list/filters/UnreadFilter.ts new file mode 100644 index 0000000000..c830f1d55b --- /dev/null +++ b/src/stores/room-list-v3/skip-list/filters/UnreadFilter.ts @@ -0,0 +1,20 @@ +/* +Copyright 2025 New Vector 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 type { Room } from "matrix-js-sdk/src/matrix"; +import type { Filter } from "."; +import { FilterKey } from "."; +import { RoomNotificationStateStore } from "../../../notifications/RoomNotificationStateStore"; + +export class UnreadFilter implements Filter { + public matches(room: Room): boolean { + return RoomNotificationStateStore.instance.getRoomState(room).isUnread; + } + + public get key(): FilterKey.UnreadFilter { + return FilterKey.UnreadFilter; + } +} diff --git a/src/stores/room-list-v3/skip-list/filters/index.ts b/src/stores/room-list-v3/skip-list/filters/index.ts index 0580c95764..29bcabb27e 100644 --- a/src/stores/room-list-v3/skip-list/filters/index.ts +++ b/src/stores/room-list-v3/skip-list/filters/index.ts @@ -8,6 +8,9 @@ import type { Room } from "matrix-js-sdk/src/matrix"; export const enum FilterKey { FavouriteFilter, + UnreadFilter, + PeopleFilter, + RoomsFilter, } export interface Filter { diff --git a/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts b/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts index 7edd5b3ef9..6d4b81239e 100644 --- a/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts +++ b/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts @@ -9,6 +9,7 @@ import { EventType, KnownMembership, MatrixEvent, Room } from "matrix-js-sdk/src import { logger } from "matrix-js-sdk/src/logger"; import type { MatrixClient } from "matrix-js-sdk/src/matrix"; +import type { RoomNotificationState } from "../../../../src/stores/notifications/RoomNotificationState"; import { RoomListStoreV3Class } from "../../../../src/stores/room-list-v3/RoomListStoreV3"; import { AsyncStoreWithClient } from "../../../../src/stores/AsyncStoreWithClient"; import { RecencySorter } from "../../../../src/stores/room-list-v3/skip-list/sorters/RecencySorter"; @@ -21,6 +22,8 @@ import SpaceStore from "../../../../src/stores/spaces/SpaceStore"; import { MetaSpace, UPDATE_SELECTED_SPACE } from "../../../../src/stores/spaces"; import { DefaultTagID } from "../../../../src/stores/room-list/models"; import { FilterKey } from "../../../../src/stores/room-list-v3/skip-list/filters"; +import { RoomNotificationStateStore } from "../../../../src/stores/notifications/RoomNotificationStateStore"; +import DMRoomMap from "../../../../src/utils/DMRoomMap"; describe("RoomListStoreV3", () => { async function getRoomListStore() { @@ -37,6 +40,17 @@ describe("RoomListStoreV3", () => { jest.spyOn(SpaceStore.instance, "isRoomInSpace").mockImplementation((space) => space === MetaSpace.Home); jest.spyOn(SpaceStore.instance, "activeSpace", "get").mockImplementation(() => MetaSpace.Home); jest.spyOn(SpaceStore.instance, "storeReadyPromise", "get").mockImplementation(() => Promise.resolve()); + jest.spyOn(RoomNotificationStateStore.instance, "getRoomState").mockImplementation((room) => { + const state = { + isUnread: false, + } as unknown as RoomNotificationState; + return state; + }); + jest.spyOn(DMRoomMap, "shared").mockImplementation((() => { + return { + getUserIdForRoomId: (id) => "", + }; + }) as () => DMRoomMap); }); it("Provides an unsorted list of rooms", async () => { @@ -397,6 +411,89 @@ describe("RoomListStoreV3", () => { expect(result).toContain(rooms[i]); } }); + + it("supports filtering unread rooms", async () => { + const { client, rooms } = getClientAndRooms(); + // Let's choose 5 rooms to put in space + const { spaceRoom, roomIds } = createSpace(rooms, [6, 8, 13, 27, 75], client); + + // Let's say 8, 27 are unread + jest.spyOn(RoomNotificationStateStore.instance, "getRoomState").mockImplementation((room) => { + const state = { + isUnread: [rooms[8], rooms[27]].includes(room), + } as unknown as RoomNotificationState; + return state; + }); + + setupMocks(spaceRoom, roomIds); + const store = new RoomListStoreV3Class(dispatcher); + await store.start(); + + // Should only give us rooms at index 8 and 27 + const result = store.getSortedRoomsInActiveSpace([FilterKey.UnreadFilter]); + expect(result).toHaveLength(2); + for (const i of [8, 27]) { + expect(result).toContain(rooms[i]); + } + }); + + it("supports filtering by people and rooms", async () => { + const { client, rooms } = getClientAndRooms(); + // Let's choose 5 rooms to put in space + const { spaceRoom, roomIds } = createSpace(rooms, [6, 8, 13, 27, 75], client); + + // Let's say 8, 27 are dms + const ids = [8, 27].map((i) => rooms[i].roomId); + jest.spyOn(DMRoomMap, "shared").mockImplementation((() => { + return { + getUserIdForRoomId: (id) => (ids.includes(id) ? "@myuser:matrix.org" : ""), + }; + }) as () => DMRoomMap); + + setupMocks(spaceRoom, roomIds); + const store = new RoomListStoreV3Class(dispatcher); + await store.start(); + + // Should only give us rooms at index 8 and 27 + const peopleRooms = store.getSortedRoomsInActiveSpace([FilterKey.PeopleFilter]); + expect(peopleRooms).toHaveLength(2); + for (const i of [8, 27]) { + expect(peopleRooms).toContain(rooms[i]); + } + + // Rest are normal rooms + const nonDms = store.getSortedRoomsInActiveSpace([FilterKey.RoomsFilter]); + expect(nonDms).toHaveLength(3); + for (const i of [6, 13, 75]) { + expect(nonDms).toContain(rooms[i]); + } + }); + + it("supports multiple filters", async () => { + const { client, rooms } = getClientAndRooms(); + // Let's choose 5 rooms to put in space + const { spaceRoom, roomIds } = createSpace(rooms, [6, 8, 13, 27, 75], client); + + // Let's say that 8 is a favourite room + rooms[8].tags[DefaultTagID.Favourite] = {}; + + // Let's say 8, 27 are unread + jest.spyOn(RoomNotificationStateStore.instance, "getRoomState").mockImplementation((room) => { + const state = { + isUnread: [rooms[8], rooms[27]].includes(room), + } as unknown as RoomNotificationState; + return state; + }); + + setupMocks(spaceRoom, roomIds); + const store = new RoomListStoreV3Class(dispatcher); + await store.start(); + + // Should give us only room at 8 since that's the only room which matches both filters + const result = store.getSortedRoomsInActiveSpace([FilterKey.UnreadFilter, FilterKey.FavouriteFilter]); + expect(result).toHaveLength(1); + expect(result).toContain(rooms[8]); + }); }); }); }); From 179b36880921d3d8cf28e4451cc64cd07b919c4b Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Sat, 8 Mar 2025 06:14:47 +0000 Subject: [PATCH 051/458] [create-pull-request] automated change (#29447) Co-authored-by: t3chguy <2403652+t3chguy@users.noreply.github.com> --- playwright/testcontainers/synapse.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright/testcontainers/synapse.ts b/playwright/testcontainers/synapse.ts index a6b78bc8f6..1a78cfc927 100644 --- a/playwright/testcontainers/synapse.ts +++ b/playwright/testcontainers/synapse.ts @@ -25,7 +25,7 @@ import { type HomeserverContainer, type StartedHomeserverContainer } from "./Hom import { type StartedMatrixAuthenticationServiceContainer } from "./mas.ts"; import { Api, ClientServerApi, type Verb } from "../plugins/utils/api.ts"; -const TAG = "develop@sha256:8d0049e8e0524ad6817cf7737453fe47de1ed3b8d04704f0c2fd6c136414c9d7"; +const TAG = "develop@sha256:12dcb34f71bb5619dba100e526a6c515fb4456d614310b5482852c7ca6f5adb9"; const DEFAULT_CONFIG = { server_name: "localhost", From 53065f9437cb1b698f0995da7690430b93a03191 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Mon, 10 Mar 2025 09:12:38 +0000 Subject: [PATCH 052/458] Add E2E test for quick settings dialog (#29441) * Update quick settings menu to use a11y roles. * Add e2e test to test quick menu rendering * Use a testid for now. * lint lint * Revert aria changes * revert managed * write screenshot --- .../e2e/settings/quick-settings-menu.spec.ts | 18 ++++++++++++++++++ .../quick-settings-linux.png | Bin 0 -> 16542 bytes .../views/spaces/QuickSettingsButton.tsx | 2 ++ 3 files changed, 20 insertions(+) create mode 100644 playwright/e2e/settings/quick-settings-menu.spec.ts create mode 100644 playwright/snapshots/settings/quick-settings-menu.spec.ts/quick-settings-linux.png diff --git a/playwright/e2e/settings/quick-settings-menu.spec.ts b/playwright/e2e/settings/quick-settings-menu.spec.ts new file mode 100644 index 0000000000..e58d523c21 --- /dev/null +++ b/playwright/e2e/settings/quick-settings-menu.spec.ts @@ -0,0 +1,18 @@ +/* +Copyright 2025 New Vector 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 { test, expect } from "../../element-web-test"; + +test.describe("Quick settings menu", () => { + test("should be rendered properly", { tag: "@screenshot" }, async ({ app, page, user }) => { + await page.getByRole("button", { name: "Quick settings" }).click(); + // Assert that the top heading is renderedc + const settings = page.getByTestId("quick-settings-menu"); + await expect(settings).toBeVisible(); + await expect(settings).toMatchScreenshot("quick-settings.png"); + }); +}); diff --git a/playwright/snapshots/settings/quick-settings-menu.spec.ts/quick-settings-linux.png b/playwright/snapshots/settings/quick-settings-menu.spec.ts/quick-settings-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..135c669fb028816b4d57d3b6b5f4ce7c3041ee5e GIT binary patch literal 16542 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 R47e9aPD)v_T--S5{{T#)Dd+$I literal 0 HcmV?d00001 diff --git a/src/components/views/spaces/QuickSettingsButton.tsx b/src/components/views/spaces/QuickSettingsButton.tsx index 7e365a5c24..12a351b93e 100644 --- a/src/components/views/spaces/QuickSettingsButton.tsx +++ b/src/components/views/spaces/QuickSettingsButton.tsx @@ -51,6 +51,8 @@ const QuickSettingsButton: React.FC<{ wrapperClassName={classNames("mx_QuickSettingsButton_ContextMenuWrapper", { mx_QuickSettingsButton_ContextMenuWrapper_new_room_list: newRoomListEnabled, })} + // Eventually replace with a properly aria-labelled menu + data-testid="quick-settings-menu" onFinished={closeMenu} managed={false} focusLock={true} From 47976447b5bf9a1f8a464b6ce1c223175c059390 Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Mon, 10 Mar 2025 17:07:37 +0530 Subject: [PATCH 053/458] Room List Store: Implement secondary filters (#29458) * Implement the secondary filters * Use the new filters in the store * Write tests --- src/stores/room-list-v3/RoomListStoreV3.ts | 13 +++- .../skip-list/filters/InvitesFilter.ts | 20 ++++++ .../skip-list/filters/LowPriorityFilter.ts | 20 ++++++ .../skip-list/filters/MentionsFilter.ts | 20 ++++++ .../room-list-v3/skip-list/filters/index.ts | 3 + .../room-list-v3/RoomListStoreV3-test.ts | 71 +++++++++++++++++++ 6 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 src/stores/room-list-v3/skip-list/filters/InvitesFilter.ts create mode 100644 src/stores/room-list-v3/skip-list/filters/LowPriorityFilter.ts create mode 100644 src/stores/room-list-v3/skip-list/filters/MentionsFilter.ts diff --git a/src/stores/room-list-v3/RoomListStoreV3.ts b/src/stores/room-list-v3/RoomListStoreV3.ts index df7246e95c..15521ddd3f 100644 --- a/src/stores/room-list-v3/RoomListStoreV3.ts +++ b/src/stores/room-list-v3/RoomListStoreV3.ts @@ -28,11 +28,22 @@ import { FavouriteFilter } from "./skip-list/filters/FavouriteFilter"; import { UnreadFilter } from "./skip-list/filters/UnreadFilter"; import { PeopleFilter } from "./skip-list/filters/PeopleFilter"; import { RoomsFilter } from "./skip-list/filters/RoomsFilter"; +import { InvitesFilter } from "./skip-list/filters/InvitesFilter"; +import { MentionsFilter } from "./skip-list/filters/MentionsFilter"; +import { LowPriorityFilter } from "./skip-list/filters/LowPriorityFilter"; /** * These are the filters passed to the room skip list. */ -const FILTERS = [new FavouriteFilter(), new UnreadFilter(), new PeopleFilter(), new RoomsFilter()]; +const FILTERS = [ + new FavouriteFilter(), + new UnreadFilter(), + new PeopleFilter(), + new RoomsFilter(), + new InvitesFilter(), + new MentionsFilter(), + new LowPriorityFilter(), +]; /** * This store allows for fast retrieval of the room list in a sorted and filtered manner. diff --git a/src/stores/room-list-v3/skip-list/filters/InvitesFilter.ts b/src/stores/room-list-v3/skip-list/filters/InvitesFilter.ts new file mode 100644 index 0000000000..fb9fff9b44 --- /dev/null +++ b/src/stores/room-list-v3/skip-list/filters/InvitesFilter.ts @@ -0,0 +1,20 @@ +/* +Copyright 2025 New Vector 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 { type Room, KnownMembership } from "matrix-js-sdk/src/matrix"; + +import type { Filter } from "."; +import { FilterKey } from "."; + +export class InvitesFilter implements Filter { + public matches(room: Room): boolean { + return room.getMyMembership() === KnownMembership.Invite; + } + + public get key(): FilterKey.InvitesFilter { + return FilterKey.InvitesFilter; + } +} diff --git a/src/stores/room-list-v3/skip-list/filters/LowPriorityFilter.ts b/src/stores/room-list-v3/skip-list/filters/LowPriorityFilter.ts new file mode 100644 index 0000000000..da47761d6e --- /dev/null +++ b/src/stores/room-list-v3/skip-list/filters/LowPriorityFilter.ts @@ -0,0 +1,20 @@ +/* +Copyright 2025 New Vector 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 type { Room } from "matrix-js-sdk/src/matrix"; +import type { Filter } from "."; +import { FilterKey } from "."; +import { DefaultTagID } from "../../../room-list/models"; + +export class LowPriorityFilter implements Filter { + public matches(room: Room): boolean { + return !!room.tags[DefaultTagID.LowPriority]; + } + + public get key(): FilterKey.LowPriorityFilter { + return FilterKey.LowPriorityFilter; + } +} diff --git a/src/stores/room-list-v3/skip-list/filters/MentionsFilter.ts b/src/stores/room-list-v3/skip-list/filters/MentionsFilter.ts new file mode 100644 index 0000000000..8897e766d4 --- /dev/null +++ b/src/stores/room-list-v3/skip-list/filters/MentionsFilter.ts @@ -0,0 +1,20 @@ +/* +Copyright 2025 New Vector 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 type { Room } from "matrix-js-sdk/src/matrix"; +import type { Filter } from "."; +import { FilterKey } from "."; +import { RoomNotificationStateStore } from "../../../notifications/RoomNotificationStateStore"; + +export class MentionsFilter implements Filter { + public matches(room: Room): boolean { + return RoomNotificationStateStore.instance.getRoomState(room).hasMentions; + } + + public get key(): FilterKey.MentionsFilter { + return FilterKey.MentionsFilter; + } +} diff --git a/src/stores/room-list-v3/skip-list/filters/index.ts b/src/stores/room-list-v3/skip-list/filters/index.ts index 29bcabb27e..e4c65167b3 100644 --- a/src/stores/room-list-v3/skip-list/filters/index.ts +++ b/src/stores/room-list-v3/skip-list/filters/index.ts @@ -11,6 +11,9 @@ export const enum FilterKey { UnreadFilter, PeopleFilter, RoomsFilter, + LowPriorityFilter, + MentionsFilter, + InvitesFilter, } export interface Filter { diff --git a/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts b/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts index 6d4b81239e..ac9f820439 100644 --- a/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts +++ b/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts @@ -469,6 +469,77 @@ describe("RoomListStoreV3", () => { } }); + it("supports filtering invited rooms", async () => { + const { client, rooms } = getClientAndRooms(); + + // Let's add 5 rooms that we are invited to + const invitedRooms = getMockedRooms(client, 5); + for (const room of invitedRooms) { + room.getMyMembership = jest.fn().mockReturnValue(KnownMembership.Invite); + } + + rooms.push(...invitedRooms); + + // Let's choose 5 rooms to put in space + const { spaceRoom, roomIds } = createSpace(rooms, [6, 8, 100, 101, 102, 103, 104], client); + setupMocks(spaceRoom, roomIds); + const store = new RoomListStoreV3Class(dispatcher); + await store.start(); + + const result = store.getSortedRoomsInActiveSpace([FilterKey.InvitesFilter]); + expect(result).toHaveLength(5); + for (const room of invitedRooms) { + expect(result).toContain(room); + } + }); + + it("supports filtering by mentions", async () => { + const { client, rooms } = getClientAndRooms(); + // Let's choose 5 rooms to put in space + const { spaceRoom, roomIds } = createSpace(rooms, [6, 8, 13, 27, 75], client); + + // Let's say 8, 27 have mentions + jest.spyOn(RoomNotificationStateStore.instance, "getRoomState").mockImplementation((room) => { + const state = { + hasMentions: [rooms[8], rooms[27]].includes(room), + } as unknown as RoomNotificationState; + return state; + }); + + setupMocks(spaceRoom, roomIds); + const store = new RoomListStoreV3Class(dispatcher); + await store.start(); + + // Should only give us rooms at index 8 and 27 + const result = store.getSortedRoomsInActiveSpace([FilterKey.MentionsFilter]); + expect(result).toHaveLength(2); + for (const i of [8, 27]) { + expect(result).toContain(rooms[i]); + } + }); + + it("supports filtering low priority rooms", async () => { + const { client, rooms } = getClientAndRooms(); + // Let's choose 5 rooms to put in space + const { spaceRoom, roomIds } = createSpace(rooms, [6, 8, 13, 27, 75], client); + + // Let's say that 8, 27 an 75 are low priority rooms + [8, 27, 75].forEach((i) => { + rooms[i].tags[DefaultTagID.LowPriority] = {}; + }); + + setupMocks(spaceRoom, roomIds); + const store = new RoomListStoreV3Class(dispatcher); + await store.start(); + + // Sorted, filtered rooms should be 8, 27 and 75 + const result = store.getSortedRoomsInActiveSpace([FilterKey.LowPriorityFilter]); + expect(result).toHaveLength(3); + for (const i of [8, 27, 75]) { + expect(result).toContain(rooms[i]); + } + }); + it("supports multiple filters", async () => { const { client, rooms } = getClientAndRooms(); // Let's choose 5 rooms to put in space From da87bbe854808fac65339b4254c5096c6959f0a4 Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Mon, 10 Mar 2025 17:28:12 +0530 Subject: [PATCH 054/458] Room List Store: Fix bug where left rooms appear in room list (#29452) * Write failing test * Remove room when membership changes from JOIN to LEAVE --- src/stores/room-list-v3/RoomListStoreV3.ts | 5 +++++ .../room-list-v3/RoomListStoreV3-test.ts | 21 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/stores/room-list-v3/RoomListStoreV3.ts b/src/stores/room-list-v3/RoomListStoreV3.ts index 15521ddd3f..21bbe3140d 100644 --- a/src/stores/room-list-v3/RoomListStoreV3.ts +++ b/src/stores/room-list-v3/RoomListStoreV3.ts @@ -192,6 +192,11 @@ export class RoomListStoreV3Class extends AsyncStoreWithClient { case "MatrixActions.Room.myMembership": { const oldMembership = getEffectiveMembership(payload.oldMembership); const newMembership = getEffectiveMembershipTag(payload.room, payload.membership); + if (oldMembership === EffectiveMembership.Join && newMembership === EffectiveMembership.Leave) { + this.roomSkipList.removeRoom(payload.room); + this.emit(LISTS_UPDATE_EVENT); + return; + } if (oldMembership !== EffectiveMembership.Join && newMembership === EffectiveMembership.Join) { // If we're joining an upgraded room, we'll want to make sure we don't proliferate // the dead room in the list. diff --git a/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts b/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts index ac9f820439..ec27049c89 100644 --- a/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts +++ b/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts @@ -104,6 +104,27 @@ describe("RoomListStoreV3", () => { expect(store.getSortedRooms()[0].roomId).toEqual(room.roomId); }); + it("Room is removed when membership changes from join to leave", async () => { + const { store, rooms, dispatcher } = await getRoomListStore(); + + // Let's say the user leaves room at index 37 + const room = rooms[37]; + + const payload = { + action: "MatrixActions.Room.myMembership", + oldMembership: KnownMembership.Join, + membership: KnownMembership.Leave, + room, + }; + + const fn = jest.fn(); + store.on(LISTS_UPDATE_EVENT, fn); + dispatcher.dispatch(payload, true); + + expect(fn).toHaveBeenCalled(); + expect(store.getSortedRooms()).not.toContain(room); + }); + it("Predecessor room is removed on room upgrade", async () => { const { store, rooms, client, dispatcher } = await getRoomListStore(); // Let's say that !foo32:matrix.org is being upgraded From af476905b69c8434fedce1116fab6bfb50d83ecc Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Mon, 10 Mar 2025 18:03:06 +0530 Subject: [PATCH 055/458] Room List Store: Fetch rooms after space store is ready + attach store to window (#29453) * Attach the new store to window * Fetch rooms after space store is ready If we fetch a list of rooms and then wait for the space store to be ready, we will need some way of handling the onAction calls we get while we wait. These calls are dropped now. --- src/@types/global.d.ts | 2 ++ src/stores/room-list-v3/RoomListStoreV3.ts | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index 1df84ad344..3bbeda067b 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -47,6 +47,7 @@ import { type DeepReadonly } from "./common"; import type MatrixChat from "../components/structures/MatrixChat"; import { type InitialCryptoSetupStore } from "../stores/InitialCryptoSetupStore"; import { type ModuleApiType } from "../modules/Api.ts"; +import type { RoomListStoreV3Class } from "../stores/room-list-v3/RoomListStoreV3.ts"; /* eslint-disable @typescript-eslint/naming-convention */ @@ -99,6 +100,7 @@ declare global { mxToastStore: ToastStore; mxDeviceListener: DeviceListener; mxRoomListStore: RoomListStore; + mxRoomListStoreV3: RoomListStoreV3Class; mxRoomListLayoutStore: RoomListLayoutStore; mxPlatformPeg: PlatformPeg; mxIntegrationManagers: typeof IntegrationManagers; diff --git a/src/stores/room-list-v3/RoomListStoreV3.ts b/src/stores/room-list-v3/RoomListStoreV3.ts index 21bbe3140d..8d1bf8331f 100644 --- a/src/stores/room-list-v3/RoomListStoreV3.ts +++ b/src/stores/room-list-v3/RoomListStoreV3.ts @@ -116,8 +116,8 @@ export class RoomListStoreV3Class extends AsyncStoreWithClient { if (this.roomSkipList?.initialized || !this.matrixClient) return; const sorter = new RecencySorter(this.matrixClient.getSafeUserId()); this.roomSkipList = new RoomSkipList(sorter, FILTERS); - const rooms = this.getRooms(); await SpaceStore.instance.storeReadyPromise; + const rooms = this.getRooms(); this.roomSkipList.seed(rooms); this.emit(LISTS_UPDATE_EVENT); } @@ -244,3 +244,5 @@ export default class RoomListStoreV3 { return this.internalInstance; } } + +window.mxRoomListStoreV3 = RoomListStoreV3.instance; From fd91e7815247ad4d00a846bb0347e80f4c8529d7 Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Mon, 10 Mar 2025 18:53:38 +0530 Subject: [PATCH 056/458] RoomListViewModel: Support primary filters in the view model (#29454) * Track available filters and expose this info from the vm - Adds a separate hook that tracks the filtered rooms and the available filters. - When secondary filters are added, some of the primary filters will be selectively hidden. So track this info in the vm. * Write tests * Fix typescript error * Fix translation * Explain what a primary filter is --- .../viewmodels/roomlist/RoomListViewModel.tsx | 92 +++++++++++++++++-- src/i18n/strings/en_EN.json | 6 ++ .../roomlist/RoomListViewModel-test.tsx | 59 +++++++++++- .../rooms/RoomListPanel/RoomList-test.tsx | 2 +- 4 files changed, 145 insertions(+), 14 deletions(-) diff --git a/src/components/viewmodels/roomlist/RoomListViewModel.tsx b/src/components/viewmodels/roomlist/RoomListViewModel.tsx index d1c1d994e0..2a7dac04d3 100644 --- a/src/components/viewmodels/roomlist/RoomListViewModel.tsx +++ b/src/components/viewmodels/roomlist/RoomListViewModel.tsx @@ -5,15 +5,18 @@ 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 { useCallback, useState } from "react"; +import { useCallback, useMemo, useState } from "react"; import type { Room } from "matrix-js-sdk/src/matrix"; import type { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; +import type { TranslationKey } from "../../../languageHandler"; import RoomListStoreV3 from "../../../stores/room-list-v3/RoomListStoreV3"; import { useEventEmitter } from "../../../hooks/useEventEmitter"; import { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore"; import dispatcher from "../../../dispatcher/dispatcher"; import { Action } from "../../../dispatcher/actions"; +import { FilterKey } from "../../../stores/room-list-v3/skip-list/filters"; +import { _t, _td } from "../../../languageHandler"; export interface RoomListViewState { /** @@ -25,6 +28,12 @@ export interface RoomListViewState { * Open the room having given roomId. */ openRoom: (roomId: string) => void; + + /** + * A list of objects that provide the view enough information + * to render primary room filters. + */ + primaryFilters: PrimaryFilter[]; } /** @@ -32,12 +41,7 @@ export interface RoomListViewState { * @see {@link RoomListViewState} for more information about what this view model returns. */ export function useRoomListViewModel(): RoomListViewState { - const [rooms, setRooms] = useState(RoomListStoreV3.instance.getSortedRoomsInActiveSpace()); - - useEventEmitter(RoomListStoreV3.instance, LISTS_UPDATE_EVENT, () => { - const newRooms = RoomListStoreV3.instance.getSortedRoomsInActiveSpace(); - setRooms(newRooms); - }); + const { primaryFilters, rooms } = useFilteredRooms(); const openRoom = useCallback((roomId: string): void => { dispatcher.dispatch({ @@ -47,5 +51,77 @@ export function useRoomListViewModel(): RoomListViewState { }); }, []); - return { rooms, openRoom }; + return { + rooms, + openRoom, + primaryFilters, + }; +} + +/** + * Provides information about a primary filter. + * A primary filter is a commonly used filter that is given + * more precedence in the UI. For eg, primary filters may be + * rendered as pills above the room list. + */ +interface PrimaryFilter { + // A function to toggle this filter on and off. + toggle: () => void; + // Whether this filter is currently applied + active: boolean; + // Text that can be used in the UI to represent this filter. + name: string; +} + +interface FilteredRooms { + primaryFilters: PrimaryFilter[]; + rooms: Room[]; +} + +const filterKeyToNameMap: Map = new Map([ + [FilterKey.UnreadFilter, _td("room_list|filters|unread")], + [FilterKey.FavouriteFilter, _td("room_list|filters|favourite")], + [FilterKey.PeopleFilter, _td("room_list|filters|people")], + [FilterKey.RoomsFilter, _td("room_list|filters|rooms")], +]); + +/** + * Track available filters and provide a filtered list of rooms. + */ +function useFilteredRooms(): FilteredRooms { + const [primaryFilter, setPrimaryFilter] = useState(); + const [rooms, setRooms] = useState(() => RoomListStoreV3.instance.getSortedRoomsInActiveSpace()); + + const updateRoomsFromStore = useCallback((filter?: FilterKey): void => { + const filters = filter !== undefined ? [filter] : []; + const newRooms = RoomListStoreV3.instance.getSortedRoomsInActiveSpace(filters); + setRooms(newRooms); + }, []); + + useEventEmitter(RoomListStoreV3.instance, LISTS_UPDATE_EVENT, () => { + updateRoomsFromStore(primaryFilter); + }); + + const primaryFilters = useMemo(() => { + const createPrimaryFilter = (key: FilterKey, name: string): PrimaryFilter => { + return { + toggle: () => { + setPrimaryFilter((currentFilter) => { + const filter = currentFilter === key ? undefined : key; + updateRoomsFromStore(filter); + return filter; + }); + }, + active: primaryFilter === key, + name, + }; + }; + const filters: PrimaryFilter[] = []; + for (const [key, name] of filterKeyToNameMap.entries()) { + filters.push(createPrimaryFilter(key, _t(name))); + } + return filters; + }, [primaryFilter, updateRoomsFromStore]); + + return { primaryFilters, rooms }; } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index bd577e7418..133ab7360b 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2099,6 +2099,12 @@ "failed_add_tag": "Failed to add tag %(tagName)s to room", "failed_remove_tag": "Failed to remove tag %(tagName)s from room", "failed_set_dm_tag": "Failed to set direct message tag", + "filters": { + "favourite": "Favourites", + "people": "People", + "rooms": "Rooms", + "unread": "Unread" + }, "home_menu_label": "Home options", "join_public_room_label": "Join public room", "joining_rooms_status": { diff --git a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx index b1da67ac18..9babc6cf24 100644 --- a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx +++ b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx @@ -14,16 +14,19 @@ import { LISTS_UPDATE_EVENT } from "../../../../../src/stores/room-list/SlidingR import { useRoomListViewModel } from "../../../../../src/components/viewmodels/roomlist/RoomListViewModel"; import dispatcher from "../../../../../src/dispatcher/dispatcher"; import { Action } from "../../../../../src/dispatcher/actions"; +import { FilterKey } from "../../../../../src/stores/room-list-v3/skip-list/filters"; describe("RoomListViewModel", () => { function mockAndCreateRooms() { const rooms = range(10).map((i) => mkStubRoom(`foo${i}:matrix.org`, `Foo ${i}`, undefined)); - jest.spyOn(RoomListStoreV3.instance, "getSortedRoomsInActiveSpace").mockImplementation(() => [...rooms]); - return rooms; + const fn = jest + .spyOn(RoomListStoreV3.instance, "getSortedRoomsInActiveSpace") + .mockImplementation(() => [...rooms]); + return { rooms, fn }; } it("should return a list of rooms", async () => { - const rooms = mockAndCreateRooms(); + const { rooms } = mockAndCreateRooms(); const { result: vm } = renderHook(() => useRoomListViewModel()); expect(vm.current.rooms).toHaveLength(10); @@ -33,7 +36,7 @@ describe("RoomListViewModel", () => { }); it("should update list of rooms on event from room list store", async () => { - const rooms = mockAndCreateRooms(); + const { rooms } = mockAndCreateRooms(); const { result: vm } = renderHook(() => useRoomListViewModel()); const newRoom = mkStubRoom("bar:matrix.org", "Bar", undefined); @@ -46,7 +49,7 @@ describe("RoomListViewModel", () => { }); it("should dispatch view room action on openRoom", async () => { - const rooms = mockAndCreateRooms(); + const { rooms } = mockAndCreateRooms(); const { result: vm } = renderHook(() => useRoomListViewModel()); const fn = jest.spyOn(dispatcher, "dispatch"); @@ -59,4 +62,50 @@ describe("RoomListViewModel", () => { }), ); }); + + describe("Filters", () => { + it("should provide list of available filters", () => { + mockAndCreateRooms(); + const { result: vm } = renderHook(() => useRoomListViewModel()); + // should have 4 filters + expect(vm.current.primaryFilters).toHaveLength(4); + // check the order + for (const [i, name] of ["Unread", "Favourites", "People", "Rooms"].entries()) { + expect(vm.current.primaryFilters[i].name).toEqual(name); + expect(vm.current.primaryFilters[i].active).toEqual(false); + } + }); + + it("should get filtered rooms from RLS on toggle", () => { + const { fn } = mockAndCreateRooms(); + const { result: vm } = renderHook(() => useRoomListViewModel()); + // Let's say we toggle the People toggle + const i = vm.current.primaryFilters.findIndex((f) => f.name === "People"); + act(() => { + vm.current.primaryFilters[i].toggle(); + }); + expect(fn).toHaveBeenCalledWith([FilterKey.PeopleFilter]); + expect(vm.current.primaryFilters[i].active).toEqual(true); + }); + + it("should change active property on toggle", () => { + mockAndCreateRooms(); + const { result: vm } = renderHook(() => useRoomListViewModel()); + // Let's say we toggle the People filter + const i = vm.current.primaryFilters.findIndex((f) => f.name === "People"); + expect(vm.current.primaryFilters[i].active).toEqual(false); + act(() => { + vm.current.primaryFilters[i].toggle(); + }); + expect(vm.current.primaryFilters[i].active).toEqual(true); + + // Let's say that we toggle the Favourite filter + const j = vm.current.primaryFilters.findIndex((f) => f.name === "Favourites"); + act(() => { + vm.current.primaryFilters[j].toggle(); + }); + expect(vm.current.primaryFilters[i].active).toEqual(false); + expect(vm.current.primaryFilters[j].active).toEqual(true); + }); + }); }); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx index bbf0edbf5e..53a721a13a 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx @@ -27,7 +27,7 @@ describe("", () => { matrixClient = stubClient(); const rooms = Array.from({ length: 10 }, (_, i) => mkRoom(matrixClient, `room${i}`)); - vm = { rooms, openRoom: jest.fn() }; + vm = { rooms, openRoom: jest.fn(), primaryFilters: [] }; // Needed to render a room list cell DMRoomMap.makeShared(matrixClient); From 26a17f93147172e0cd3bee4f117729385e85a149 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Tue, 11 Mar 2025 10:34:05 +0000 Subject: [PATCH 057/458] [create-pull-request] automated change (#29455) Co-authored-by: t3chguy <2403652+t3chguy@users.noreply.github.com> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --- src/i18n/strings/uk.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/i18n/strings/uk.json b/src/i18n/strings/uk.json index 52fd2b6604..c30ee6b7ae 100644 --- a/src/i18n/strings/uk.json +++ b/src/i18n/strings/uk.json @@ -407,6 +407,15 @@ "download_logs": "Завантажити журнали", "downloading_logs": "Завантаження журналів", "error_empty": "Будь ласка, повідомте нам, що пішло не так; а ще краще створіть обговорення на GitHub із описом проблеми.", + "failed_download_logs": "Не вдалося завантажити журнали налагодження: ", + "failed_send_logs_causes": { + "disallowed_app": "Ваш звіт про помилку було відхилено. Сервер rageshake не підтримує цей застосунок.", + "rejected_generic": "Ваш звіт про помилку було відхилено. Сервер rageshake відхилив вміст звіту через політику.", + "rejected_recovery_key": "Ваш звіт про помилку було відхилено з міркувань безпеки, оскільки він містив ключ відновлення.", + "rejected_version": "Ваш звіт про помилку було відхилено, оскільки версія, яку ви використовуєте, надто стара.", + "server_unknown_error": "Сервер rageshake зіткнувся з невідомою помилкою і не зміг обробити звіт.", + "unknown_error": "Не вдалося надіслати журнали." + }, "github_issue": "Обговорення на GitHub", "introduction": "Якщо ви надіслали звіт про ваду на GitHub, журнали зневадження можуть допомогти нам визначити проблему. ", "log_request": "Щоб уникнути цього в майбутньому просимо надіслати нам журнал.", @@ -1298,6 +1307,7 @@ "error_connecting_heading": "Не вдалося з'єднатися з менеджером інтеграцій", "explainer": "Менеджери інтеграцій отримують дані конфігурації та можуть змінювати віджети, надсилати запрошення у кімнати й установлювати рівні повноважень від вашого імені.", "manage_title": "Керування інтеграціями", + "toggle_label": "Увімкнути менеджер інтеграції", "use_im": "Використовувати менеджер інтеграцій для керування ботами, віджетами й пакунками наліпок.", "use_im_default": "Використовувати менеджер інтеграцій %(serverName)s для керування ботами, віджетами й пакунками наліпок." }, @@ -2099,12 +2109,16 @@ "one": "Приєднання до %(count)s кімнати", "other": "Приєднання до %(count)s кімнат" }, + "list_title": "Список кімнат", "notification_options": "Параметри сповіщень", "open_space_menu": "Відкрити меню простору", "redacting_messages_status": { "one": "Триває видалення повідомлень в %(count)s кімнаті", "other": "Триває видалення повідомлень у %(count)s кімнатах" }, + "room": { + "open_room": "Відкрити кімнату %(roomName)s" + }, "show_less": "Згорнути", "show_n_more": { "other": "Показати ще %(count)s", @@ -2481,12 +2495,14 @@ "breadcrumb_title_forgot": "Забули ключ відновлення? Вам потрібно скинути свою особистість.", "breadcrumb_warning": "Робіть це, лише якщо ви впевнені, що ваш обліковий запис скомпрометований.", "details_title": "Подробиці шифрування", + "do_not_close_warning": "Не закривайте це вікно, поки не завершиться скидання", "export_keys": "Експорт ключів", "import_keys": "Імпорт ключів", "other_people_device_description": "Усталено, в кімнатах з шифруванням, зашифровані повідомлення не надсилаються, поки є не верифіковані учасники", "other_people_device_label": "Ніколи не надсилати зашифровані повідомлення на неверифіковані пристрої", "other_people_device_title": "Пристрої інших людей", "reset_identity": "Скинути криптографічну ідентичність", + "reset_in_progress": "Виконується скидання...", "session_id": "ID сеансу:", "session_key": "Ключ сеансу:", "title": "Додатково" From 3f3fba99eb1c0dea1aa83a315f8064ea7d4d3844 Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Tue, 11 Mar 2025 18:59:55 +0530 Subject: [PATCH 058/458] RoomListViewModel: Support secondary filters in the view model (#29465) * Support secondary filters in the view model * Write view model tests * Fix RoomList test * Add more comments --- .../viewmodels/roomlist/RoomListViewModel.tsx | 91 ++------- .../viewmodels/roomlist/useFilteredRooms.tsx | 188 ++++++++++++++++++ .../roomlist/RoomListViewModel-test.tsx | 96 +++++++++ .../rooms/RoomListPanel/RoomList-test.tsx | 9 +- 4 files changed, 307 insertions(+), 77 deletions(-) create mode 100644 src/components/viewmodels/roomlist/useFilteredRooms.tsx diff --git a/src/components/viewmodels/roomlist/RoomListViewModel.tsx b/src/components/viewmodels/roomlist/RoomListViewModel.tsx index 2a7dac04d3..fb827c4889 100644 --- a/src/components/viewmodels/roomlist/RoomListViewModel.tsx +++ b/src/components/viewmodels/roomlist/RoomListViewModel.tsx @@ -5,18 +5,13 @@ 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 { useCallback, useMemo, useState } from "react"; +import { useCallback } from "react"; import type { Room } from "matrix-js-sdk/src/matrix"; import type { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; -import type { TranslationKey } from "../../../languageHandler"; -import RoomListStoreV3 from "../../../stores/room-list-v3/RoomListStoreV3"; -import { useEventEmitter } from "../../../hooks/useEventEmitter"; -import { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore"; import dispatcher from "../../../dispatcher/dispatcher"; import { Action } from "../../../dispatcher/actions"; -import { FilterKey } from "../../../stores/room-list-v3/skip-list/filters"; -import { _t, _td } from "../../../languageHandler"; +import { type PrimaryFilter, type SecondaryFilters, useFilteredRooms } from "./useFilteredRooms"; export interface RoomListViewState { /** @@ -34,6 +29,16 @@ export interface RoomListViewState { * to render primary room filters. */ primaryFilters: PrimaryFilter[]; + + /** + * A function to activate a given secondary filter. + */ + activateSecondaryFilter: (filter: SecondaryFilters) => void; + + /** + * The currently active secondary filter. + */ + activeSecondaryFilter: SecondaryFilters; } /** @@ -41,7 +46,7 @@ export interface RoomListViewState { * @see {@link RoomListViewState} for more information about what this view model returns. */ export function useRoomListViewModel(): RoomListViewState { - const { primaryFilters, rooms } = useFilteredRooms(); + const { primaryFilters, rooms, activateSecondaryFilter, activeSecondaryFilter } = useFilteredRooms(); const openRoom = useCallback((roomId: string): void => { dispatcher.dispatch({ @@ -55,73 +60,7 @@ export function useRoomListViewModel(): RoomListViewState { rooms, openRoom, primaryFilters, + activateSecondaryFilter, + activeSecondaryFilter, }; } - -/** - * Provides information about a primary filter. - * A primary filter is a commonly used filter that is given - * more precedence in the UI. For eg, primary filters may be - * rendered as pills above the room list. - */ -interface PrimaryFilter { - // A function to toggle this filter on and off. - toggle: () => void; - // Whether this filter is currently applied - active: boolean; - // Text that can be used in the UI to represent this filter. - name: string; -} - -interface FilteredRooms { - primaryFilters: PrimaryFilter[]; - rooms: Room[]; -} - -const filterKeyToNameMap: Map = new Map([ - [FilterKey.UnreadFilter, _td("room_list|filters|unread")], - [FilterKey.FavouriteFilter, _td("room_list|filters|favourite")], - [FilterKey.PeopleFilter, _td("room_list|filters|people")], - [FilterKey.RoomsFilter, _td("room_list|filters|rooms")], -]); - -/** - * Track available filters and provide a filtered list of rooms. - */ -function useFilteredRooms(): FilteredRooms { - const [primaryFilter, setPrimaryFilter] = useState(); - const [rooms, setRooms] = useState(() => RoomListStoreV3.instance.getSortedRoomsInActiveSpace()); - - const updateRoomsFromStore = useCallback((filter?: FilterKey): void => { - const filters = filter !== undefined ? [filter] : []; - const newRooms = RoomListStoreV3.instance.getSortedRoomsInActiveSpace(filters); - setRooms(newRooms); - }, []); - - useEventEmitter(RoomListStoreV3.instance, LISTS_UPDATE_EVENT, () => { - updateRoomsFromStore(primaryFilter); - }); - - const primaryFilters = useMemo(() => { - const createPrimaryFilter = (key: FilterKey, name: string): PrimaryFilter => { - return { - toggle: () => { - setPrimaryFilter((currentFilter) => { - const filter = currentFilter === key ? undefined : key; - updateRoomsFromStore(filter); - return filter; - }); - }, - active: primaryFilter === key, - name, - }; - }; - const filters: PrimaryFilter[] = []; - for (const [key, name] of filterKeyToNameMap.entries()) { - filters.push(createPrimaryFilter(key, _t(name))); - } - return filters; - }, [primaryFilter, updateRoomsFromStore]); - - return { primaryFilters, rooms }; -} diff --git a/src/components/viewmodels/roomlist/useFilteredRooms.tsx b/src/components/viewmodels/roomlist/useFilteredRooms.tsx new file mode 100644 index 0000000000..a21918e5fa --- /dev/null +++ b/src/components/viewmodels/roomlist/useFilteredRooms.tsx @@ -0,0 +1,188 @@ +/* +Copyright 2025 New Vector 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 { useCallback, useMemo, useState } from "react"; + +import type { Room } from "matrix-js-sdk/src/matrix"; +import { FilterKey } from "../../../stores/room-list-v3/skip-list/filters"; +import { _t, _td, type TranslationKey } from "../../../languageHandler"; +import RoomListStoreV3 from "../../../stores/room-list-v3/RoomListStoreV3"; +import { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore"; +import { useEventEmitter } from "../../../hooks/useEventEmitter"; + +/** + * Provides information about a primary filter. + * A primary filter is a commonly used filter that is given + * more precedence in the UI. For eg, primary filters may be + * rendered as pills above the room list. + */ +export interface PrimaryFilter { + // A function to toggle this filter on and off. + toggle: () => void; + // Whether this filter is currently applied + active: boolean; + // Text that can be used in the UI to represent this filter. + name: string; +} + +interface FilteredRooms { + primaryFilters: PrimaryFilter[]; + rooms: Room[]; + activateSecondaryFilter: (filter: SecondaryFilters) => void; + activeSecondaryFilter: SecondaryFilters; +} + +const filterKeyToNameMap: Map = new Map([ + [FilterKey.UnreadFilter, _td("room_list|filters|unread")], + [FilterKey.FavouriteFilter, _td("room_list|filters|favourite")], + [FilterKey.PeopleFilter, _td("room_list|filters|people")], + [FilterKey.RoomsFilter, _td("room_list|filters|rooms")], +]); + +/** + * These are the secondary filters which are not prominently shown + * in the UI. + */ +export const enum SecondaryFilters { + AllActivity, + MentionsOnly, + InvitesOnly, + LowPriority, +} + +/** + * A map from {@link SecondaryFilters} which the UI understands to + * {@link FilterKey} which the store understands. + */ +const secondaryFiltersToFilterKeyMap = new Map([ + [SecondaryFilters.AllActivity, undefined], + [SecondaryFilters.MentionsOnly, FilterKey.MentionsFilter], + [SecondaryFilters.InvitesOnly, FilterKey.InvitesFilter], + [SecondaryFilters.LowPriority, FilterKey.LowPriorityFilter], +]); + +/** + * Use this function to determine if a given primary filter is compatible with + * a given secondary filter. Practically, this determines whether it makes sense + * to expose two filters together in the UI - for eg, it does not make sense to show the + * favourite primary filter if the active secondary filter is low priority. + * @param primary Primary filter key + * @param secondary Secondary filter key + * @returns true if compatible, false otherwise + */ +function isPrimaryFilterCompatible(primary: FilterKey, secondary: FilterKey): boolean { + if (secondary === FilterKey.MentionsFilter) { + if (primary === FilterKey.UnreadFilter) return false; + } else if (secondary === FilterKey.InvitesFilter) { + if (primary === FilterKey.UnreadFilter || primary === FilterKey.FavouriteFilter) return false; + } else if (secondary === FilterKey.LowPriorityFilter) { + if (primary === FilterKey.FavouriteFilter) return false; + } + return true; +} + +/** + * Track available filters and provide a filtered list of rooms. + */ +export function useFilteredRooms(): FilteredRooms { + /** + * Primary filter refers to the pill based filters + * rendered above the room list. + */ + const [primaryFilter, setPrimaryFilter] = useState(); + /** + * Secondary filters are also filters but they are hidden + * away in a popup menu. + */ + const [activeSecondaryFilter, setActiveSecondaryFilter] = useState(SecondaryFilters.AllActivity); + + const secondaryFilter = useMemo( + () => secondaryFiltersToFilterKeyMap.get(activeSecondaryFilter), + [activeSecondaryFilter], + ); + + const [rooms, setRooms] = useState(() => RoomListStoreV3.instance.getSortedRoomsInActiveSpace()); + + const updateRoomsFromStore = useCallback((filters: FilterKey[] = []): void => { + const newRooms = RoomListStoreV3.instance.getSortedRoomsInActiveSpace(filters); + setRooms(newRooms); + }, []); + + const filterUndefined = (array: (FilterKey | undefined)[]): FilterKey[] => + array.filter((f) => f !== undefined) as FilterKey[]; + + const getAppliedFilters = (): FilterKey[] => { + return filterUndefined([primaryFilter, secondaryFilter]); + }; + + useEventEmitter(RoomListStoreV3.instance, LISTS_UPDATE_EVENT, () => { + const filters = getAppliedFilters(); + updateRoomsFromStore(filters); + }); + + /** + * Secondary filters are activated using this function. + * This is different to how primary filters work because the secondary + * filters are static i.e they are always available and don't need to be + * hidden. + */ + const activateSecondaryFilter = useCallback( + (filter: SecondaryFilters): void => { + // If the filter is already active, just return. + if (filter === activeSecondaryFilter) return; + + // SecondaryFilter is an enum for the UI, let's convert it to something + // that the store will understand. + const secondary = secondaryFiltersToFilterKeyMap.get(filter); + + // Active primary filter may need to be toggled off when applying this secondary filer. + let primary = primaryFilter; + if ( + primaryFilter !== undefined && + secondary !== undefined && + !isPrimaryFilterCompatible(primaryFilter, secondary) + ) { + primary = undefined; + } + + setActiveSecondaryFilter(filter); + setPrimaryFilter(primary); + updateRoomsFromStore(filterUndefined([primary, secondary])); + }, + [activeSecondaryFilter, primaryFilter, updateRoomsFromStore], + ); + + /** + * This tells the view which primary filters are available, how to toggle them + * and whether a given primary filter is active. @see {@link PrimaryFilter} + */ + const primaryFilters = useMemo(() => { + const createPrimaryFilter = (key: FilterKey, name: string): PrimaryFilter => { + return { + toggle: () => { + setPrimaryFilter((currentFilter) => { + const filter = currentFilter === key ? undefined : key; + updateRoomsFromStore(filterUndefined([filter, secondaryFilter])); + return filter; + }); + }, + active: primaryFilter === key, + name, + }; + }; + const filters: PrimaryFilter[] = []; + for (const [key, name] of filterKeyToNameMap.entries()) { + if (secondaryFilter && !isPrimaryFilterCompatible(key, secondaryFilter)) { + continue; + } + filters.push(createPrimaryFilter(key, _t(name))); + } + return filters; + }, [primaryFilter, updateRoomsFromStore, secondaryFilter]); + + return { primaryFilters, rooms, activateSecondaryFilter, activeSecondaryFilter }; +} diff --git a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx index 9babc6cf24..055feb84e6 100644 --- a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx +++ b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx @@ -15,6 +15,7 @@ import { useRoomListViewModel } from "../../../../../src/components/viewmodels/r import dispatcher from "../../../../../src/dispatcher/dispatcher"; import { Action } from "../../../../../src/dispatcher/actions"; import { FilterKey } from "../../../../../src/stores/room-list-v3/skip-list/filters"; +import { SecondaryFilters } from "../../../../../src/components/viewmodels/roomlist/useFilteredRooms"; describe("RoomListViewModel", () => { function mockAndCreateRooms() { @@ -107,5 +108,100 @@ describe("RoomListViewModel", () => { expect(vm.current.primaryFilters[i].active).toEqual(false); expect(vm.current.primaryFilters[j].active).toEqual(true); }); + + it("should select all activity as default secondary filter", () => { + mockAndCreateRooms(); + const { result: vm } = renderHook(() => useRoomListViewModel()); + + // By default, all activity should be the active secondary filter + expect(vm.current.activeSecondaryFilter).toEqual(SecondaryFilters.AllActivity); + }); + + it("should be able to filter using secondary filters", () => { + const { fn } = mockAndCreateRooms(); + const { result: vm } = renderHook(() => useRoomListViewModel()); + + // Let's say we toggle the mentions secondary filter + act(() => { + vm.current.activateSecondaryFilter(SecondaryFilters.MentionsOnly); + }); + expect(fn).toHaveBeenCalledWith([FilterKey.MentionsFilter]); + }); + + it("primary filters are applied on top of secondary filers", () => { + const { fn } = mockAndCreateRooms(); + const { result: vm } = renderHook(() => useRoomListViewModel()); + + // Let's say we toggle the mentions secondary filter + act(() => { + vm.current.activateSecondaryFilter(SecondaryFilters.MentionsOnly); + }); + + // Let's say we toggle the People filter + const i = vm.current.primaryFilters.findIndex((f) => f.name === "People"); + act(() => { + vm.current.primaryFilters[i].toggle(); + }); + + // RLS call must include both these filters + expect(fn).toHaveBeenLastCalledWith( + expect.arrayContaining([FilterKey.PeopleFilter, FilterKey.MentionsFilter]), + ); + }); + + const testcases: Array<[string, { secondary: SecondaryFilters; filterKey: FilterKey }, string]> = [ + [ + "Mentions only", + { secondary: SecondaryFilters.MentionsOnly, filterKey: FilterKey.MentionsFilter }, + "Unread", + ], + ["Invites only", { secondary: SecondaryFilters.InvitesOnly, filterKey: FilterKey.InvitesFilter }, "Unread"], + [ + "Invites only", + { secondary: SecondaryFilters.InvitesOnly, filterKey: FilterKey.InvitesFilter }, + "Favourites", + ], + [ + "Low priority", + { secondary: SecondaryFilters.LowPriority, filterKey: FilterKey.LowPriorityFilter }, + "Favourites", + ], + ]; + + describe.each(testcases)("For secondary filter: %s", (secondaryFilterName, secondary, primaryFilterName) => { + it(`should unapply incompatible primary filter that is already active: ${primaryFilterName}`, () => { + const { fn } = mockAndCreateRooms(); + const { result: vm } = renderHook(() => useRoomListViewModel()); + + // Apply the primary filter + const i = vm.current.primaryFilters.findIndex((f) => f.name === primaryFilterName); + act(() => { + vm.current.primaryFilters[i].toggle(); + }); + + // Apply the secondary filter + act(() => { + vm.current.activateSecondaryFilter(secondary.secondary); + }); + + // RLS call should only include the secondary filter + expect(fn).toHaveBeenLastCalledWith([secondary.filterKey]); + // Primary filter should have been unapplied + expect(vm.current.primaryFilters[i].active).toEqual(false); + }); + + it(`should hide incompatible primary filter: ${primaryFilterName}`, () => { + mockAndCreateRooms(); + const { result: vm } = renderHook(() => useRoomListViewModel()); + + // Apply the secondary filter + act(() => { + vm.current.activateSecondaryFilter(secondary.secondary); + }); + + // Incompatible primary filter must be hidden + expect(vm.current.primaryFilters.find((f) => f.name === primaryFilterName)).toBeUndefined(); + }); + }); }); }); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx index 53a721a13a..e720798f04 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx @@ -14,6 +14,7 @@ import { mkRoom, stubClient } from "../../../../../test-utils"; import { type RoomListViewState } from "../../../../../../src/components/viewmodels/roomlist/RoomListViewModel"; import { RoomList } from "../../../../../../src/components/views/rooms/RoomListPanel/RoomList"; import DMRoomMap from "../../../../../../src/utils/DMRoomMap"; +import { SecondaryFilters } from "../../../../../../src/components/viewmodels/roomlist/useFilteredRooms"; describe("", () => { let matrixClient: MatrixClient; @@ -27,7 +28,13 @@ describe("", () => { matrixClient = stubClient(); const rooms = Array.from({ length: 10 }, (_, i) => mkRoom(matrixClient, `room${i}`)); - vm = { rooms, openRoom: jest.fn(), primaryFilters: [] }; + vm = { + rooms, + openRoom: jest.fn(), + primaryFilters: [], + activateSecondaryFilter: () => {}, + activeSecondaryFilter: SecondaryFilters.AllActivity, + }; // Needed to render a room list cell DMRoomMap.makeShared(matrixClient); From bc4bc6c25ef4d2f759c949c430e57812184f9c72 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 11 Mar 2025 14:36:16 +0000 Subject: [PATCH 059/458] Upgrade dependency to matrix-js-sdk@37.1.0 --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 58491a66aa..56f6b1ba2b 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,7 @@ "maplibre-gl": "^5.0.0", "matrix-encrypt-attachment": "^1.0.3", "matrix-events-sdk": "0.0.1", - "matrix-js-sdk": "37.1.0-rc.0", + "matrix-js-sdk": "37.1.0", "matrix-widget-api": "^1.10.0", "memoize-one": "^6.0.0", "mime": "^4.0.4", diff --git a/yarn.lock b/yarn.lock index 4d048814a3..1717e4bd47 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3545,7 +3545,7 @@ classnames "^2.5.1" vaul "^1.0.0" -"@vector-im/matrix-wysiwyg-wasm@link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.0-af862ffd231dc0a6b8d6f2cb3601e68456c0ff24-integrity/node_modules/bindings/wysiwyg-wasm": +"@vector-im/matrix-wysiwyg-wasm@link:../../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.0-af862ffd231dc0a6b8d6f2cb3601e68456c0ff24-integrity/node_modules/bindings/wysiwyg-wasm": version "0.0.0" uid "" @@ -8751,10 +8751,10 @@ matrix-events-sdk@0.0.1: resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1.tgz#c8c38911e2cb29023b0bbac8d6f32e0de2c957dd" integrity sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA== -matrix-js-sdk@37.1.0-rc.0: - version "37.1.0-rc.0" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-37.1.0-rc.0.tgz#e5667ea22519a18247dc9b3d2dc992afd03b599d" - integrity sha512-VQmfzeJ9HiYQ9+EyaH1ku+u7e56/4+W6eHAxLMXzSXjOxw2XcGMfLZ6quH356/b4QYkoOw2un8EgHIBiQN5ZQQ== +matrix-js-sdk@37.1.0: + version "37.1.0" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-37.1.0.tgz#e5234da2f954a6fda442830b52e1fca68a3697bb" + integrity sha512-MRhXSM+MV21B8qg76KFtqLeD5kjEcaKAvHrB7XS8fT9TdZQlmWBtkE6K2JaYaOkd3QDITNZLymSeap4Q2Gh9RA== dependencies: "@babel/runtime" "^7.12.5" "@matrix-org/matrix-sdk-crypto-wasm" "^14.0.1" From 324dd5a858a80af89a84a74b2fe4ed1d4dd5c132 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 11 Mar 2025 14:40:55 +0000 Subject: [PATCH 060/458] v1.11.95 --- CHANGELOG.md | 25 +++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 792fdd876c..5b458cd6bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,28 @@ +Changes in [1.11.95](https://github.com/element-hq/element-web/releases/tag/v1.11.95) (2025-03-11) +================================================================================================== +## ✨ Features + +* Room List Store: Filter rooms by active space ([#29399](https://github.com/element-hq/element-web/pull/29399)). Contributed by @MidhunSureshR. +* Room List - Update the room list store on actions from the dispatcher ([#29397](https://github.com/element-hq/element-web/pull/29397)). Contributed by @MidhunSureshR. +* Room List - Implement a minimal view model ([#29357](https://github.com/element-hq/element-web/pull/29357)). Contributed by @MidhunSureshR. +* New room list: add space menu in room header ([#29352](https://github.com/element-hq/element-web/pull/29352)). Contributed by @florianduros. +* Room List - Store sorted rooms in skip list ([#29345](https://github.com/element-hq/element-web/pull/29345)). Contributed by @MidhunSureshR. +* New room list: add dial to search section ([#29359](https://github.com/element-hq/element-web/pull/29359)). Contributed by @florianduros. +* New room list: add compose menu for spaces in header ([#29347](https://github.com/element-hq/element-web/pull/29347)). Contributed by @florianduros. +* Use EditInPlace control for Identity Server picker to improve a11y ([#29280](https://github.com/element-hq/element-web/pull/29280)). Contributed by @Half-Shot. +* First step to add header to new room list ([#29320](https://github.com/element-hq/element-web/pull/29320)). Contributed by @florianduros. +* Add Windows 64-bit arm link and remove 32-bit link on compatibility page ([#29312](https://github.com/element-hq/element-web/pull/29312)). Contributed by @t3chguy. +* Honour the backup disable flag from Element X ([#29290](https://github.com/element-hq/element-web/pull/29290)). Contributed by @dbkr. + +## 🐛 Bug Fixes + +* Fix edited code block width ([#29394](https://github.com/element-hq/element-web/pull/29394)). Contributed by @florianduros. +* new room list: keep space name in one line in header ([#29369](https://github.com/element-hq/element-web/pull/29369)). Contributed by @florianduros. +* Dismiss "Key storage out of sync" toast when secrets received ([#29348](https://github.com/element-hq/element-web/pull/29348)). Contributed by @richvdh. +* Minor CSS fixes for the new room list ([#29334](https://github.com/element-hq/element-web/pull/29334)). Contributed by @florianduros. +* Add padding to room header icon ([#29271](https://github.com/element-hq/element-web/pull/29271)). Contributed by @langleyd. + + Changes in [1.11.94](https://github.com/element-hq/element-web/releases/tag/v1.11.94) (2025-02-27) ================================================================================================== ## 🐛 Bug Fixes diff --git a/package.json b/package.json index 56f6b1ba2b..4a44c636fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "element-web", - "version": "1.11.95-rc.0", + "version": "1.11.95", "description": "Element: the future of secure communication", "author": "New Vector Ltd.", "repository": { From 4e696d2dc67d58d72698d60397ca7616e6e236ba Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 11 Mar 2025 14:44:08 +0000 Subject: [PATCH 061/458] Reset matrix-js-sdk back to develop branch --- package.json | 2 +- yarn.lock | 15 ++++----------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 30bfafcd37..974be1666e 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,7 @@ "maplibre-gl": "^5.0.0", "matrix-encrypt-attachment": "^1.0.3", "matrix-events-sdk": "0.0.1", - "matrix-js-sdk": "37.1.0", + "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", "matrix-widget-api": "^1.10.0", "memoize-one": "^6.0.0", "mime": "^4.0.4", diff --git a/yarn.lock b/yarn.lock index 62e13096fb..0eabcd5e26 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3587,13 +3587,14 @@ "@vector-im/matrix-wysiwyg-wasm@link:../../bindings/wysiwyg-wasm": version "0.0.0" + uid "" "@vector-im/matrix-wysiwyg@2.38.2": version "2.38.2" resolved "https://registry.yarnpkg.com/@vector-im/matrix-wysiwyg/-/matrix-wysiwyg-2.38.2.tgz#3fa19a2a17fd12d955ef1e14fd63aecbcf3b95e8" integrity sha512-TUnLPgZ8/zGUccQZxjIP3MVHjqybgV4u0r6kXibs35wlXgomXjwcN5gchl3FpgGkiHbi8g3D2ao0oHaqi2GaIw== dependencies: - "@vector-im/matrix-wysiwyg-wasm" "link:../../bindings/wysiwyg-wasm" + "@vector-im/matrix-wysiwyg-wasm" "link:../../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.2-3fa19a2a17fd12d955ef1e14fd63aecbcf3b95e8-integrity/node_modules/bindings/wysiwyg-wasm" "@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1": version "1.14.1" @@ -6450,13 +6451,6 @@ fastq@^1.15.0, fastq@^1.6.0: dependencies: reusify "^1.0.4" -fastq@^1.6.0: - version "1.19.1" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" - integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== - dependencies: - reusify "^1.0.4" - faye-websocket@^0.11.3: version "0.11.4" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" @@ -8761,10 +8755,9 @@ matrix-events-sdk@0.0.1: resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1.tgz#c8c38911e2cb29023b0bbac8d6f32e0de2c957dd" integrity sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA== -matrix-js-sdk@37.1.0: +"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop": version "37.1.0" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-37.1.0.tgz#e5234da2f954a6fda442830b52e1fca68a3697bb" - integrity sha512-MRhXSM+MV21B8qg76KFtqLeD5kjEcaKAvHrB7XS8fT9TdZQlmWBtkE6K2JaYaOkd3QDITNZLymSeap4Q2Gh9RA== + resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/f552370c2625e20a921a5dbf5284491bb6c22861" dependencies: "@babel/runtime" "^7.12.5" "@matrix-org/matrix-sdk-crypto-wasm" "^14.0.1" From cc95d154fb4723dafd80187884c40581b72fbe4a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Mar 2025 15:03:42 +0000 Subject: [PATCH 062/458] Bump axios from 1.8.1 to 1.8.2 (#29468) Bumps [axios](https://github.com/axios/axios) from 1.8.1 to 1.8.2. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](https://github.com/axios/axios/compare/v1.8.1...v1.8.2) --- updated-dependencies: - dependency-name: axios dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index 0eabcd5e26..dbc924a9f9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3585,9 +3585,8 @@ classnames "^2.5.1" vaul "^1.0.0" -"@vector-im/matrix-wysiwyg-wasm@link:../../bindings/wysiwyg-wasm": +"@vector-im/matrix-wysiwyg-wasm@link:../../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.2-3fa19a2a17fd12d955ef1e14fd63aecbcf3b95e8-integrity/node_modules/bindings/wysiwyg-wasm": version "0.0.0" - uid "" "@vector-im/matrix-wysiwyg@2.38.2": version "2.38.2" @@ -4185,9 +4184,9 @@ axe-core@^4.10.0, axe-core@~4.10.2: integrity sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w== axios@^1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.8.1.tgz#7c118d2146e9ebac512b7d1128771cdd738d11e3" - integrity sha512-NN+fvwH/kV01dYUQ3PTOZns4LWtWhOFCAhQ/pHb88WQ1hNe5V/dvFwc4VJcDL11LT9xSX0QtsR8sWUuyOuOq7g== + version "1.8.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.8.2.tgz#fabe06e241dfe83071d4edfbcaa7b1c3a40f7979" + integrity sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg== dependencies: follow-redirects "^1.15.6" form-data "^4.0.0" From 2052080d7d8a213064910cac491ec5cf9057610e Mon Sep 17 00:00:00 2001 From: Ben Banfield-Zanin Date: Tue, 11 Mar 2025 18:04:33 +0000 Subject: [PATCH 063/458] Fix Docker Healthcheck (#29471) * Correct test for docker container being healthy * Correct docker healthcheck for busybox wget * Repeatedly check the health state of the docker container * Use until loop & rely on timeout-minutes * Fix check to look at healthy state --------- Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --- .github/workflows/docker.yaml | 5 ++++- Dockerfile | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index 12ebaddf5b..7e5da929d4 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -61,6 +61,7 @@ jobs: - name: Test the image env: IMAGEID: ${{ steps.test-build.outputs.imageid }} + timeout-minutes: 2 run: | set -x @@ -86,7 +87,9 @@ jobs: test "$MODULE_0" = "/${MODULE_PATH}" # Check healthcheck - test "$(docker inspect -f {{.State.Running}} $CONTAINER_ID)" == "true" + until test "$(docker inspect -f {{.State.Health.Status}} $CONTAINER_ID)" == "healthy"; do + sleep 1 + done # Clean up docker stop "$CONTAINER_ID" diff --git a/Dockerfile b/Dockerfile index ed1312101e..cd1766347a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,4 +47,4 @@ USER nginx # HTTP listen port ENV ELEMENT_WEB_PORT=80 -HEALTHCHECK --start-period=5s CMD wget --retry-connrefused --tries=5 -q --wait=3 --spider http://localhost:$ELEMENT_WEB_PORT/config.json +HEALTHCHECK --start-period=5s CMD wget -q --spider http://localhost:$ELEMENT_WEB_PORT/config.json From 3ab3041c45d8c28ee5f2581f43e5f60ae25a25a6 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Wed, 12 Mar 2025 06:14:50 +0000 Subject: [PATCH 064/458] [create-pull-request] automated change (#29475) Co-authored-by: t3chguy <2403652+t3chguy@users.noreply.github.com> --- playwright/testcontainers/synapse.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright/testcontainers/synapse.ts b/playwright/testcontainers/synapse.ts index 1a78cfc927..d3f661ecc6 100644 --- a/playwright/testcontainers/synapse.ts +++ b/playwright/testcontainers/synapse.ts @@ -25,7 +25,7 @@ import { type HomeserverContainer, type StartedHomeserverContainer } from "./Hom import { type StartedMatrixAuthenticationServiceContainer } from "./mas.ts"; import { Api, ClientServerApi, type Verb } from "../plugins/utils/api.ts"; -const TAG = "develop@sha256:12dcb34f71bb5619dba100e526a6c515fb4456d614310b5482852c7ca6f5adb9"; +const TAG = "develop@sha256:26e0d9c5ca96218243432d48a9f8596e4c1bc10b748f0a1bddf9916b914d1216"; const DEFAULT_CONFIG = { server_name: "localhost", From 273cdf41e9291ff52a0da08306f0d902454e3916 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Wed, 12 Mar 2025 06:20:02 +0000 Subject: [PATCH 065/458] [create-pull-request] automated change (#29476) Co-authored-by: t3chguy <2403652+t3chguy@users.noreply.github.com> --- src/i18n/strings/cs.json | 14 ++++++++++++++ src/i18n/strings/fr.json | 7 +++++++ src/i18n/strings/hu.json | 12 +++++++++++- src/i18n/strings/nb_NO.json | 1 + src/i18n/strings/uk.json | 6 ++++++ 5 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/cs.json b/src/i18n/strings/cs.json index ac99222c79..762e2e1868 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -407,6 +407,15 @@ "download_logs": "Stáhnout záznamy", "downloading_logs": "Stahování záznamů", "error_empty": "Dejte nám vědět, prosím, co se pokazilo nebo vytvořte issue na GitHubu, kde problém popište.", + "failed_download_logs": "Stažení ladících protokolů se nezdařilo: ", + "failed_send_logs_causes": { + "disallowed_app": "Vaše hlášení o chybě bylo zamítnuto. Rageshake server tuto aplikaci nepodporuje.", + "rejected_generic": "Vaše hlášení o chybě bylo zamítnuto. Rageshake server odmítl obsah zprávy kvůli zásadám.", + "rejected_recovery_key": "Vaše hlášení o chybě bylo z bezpečnostních důvodů odmítnuto, protože obsahovalo klíč pro obnovení.", + "rejected_version": "Vaše hlášení o chybě bylo zamítnuto, protože verze, kterou používáte, je příliš stará.", + "server_unknown_error": "Rageshake server narazil na neznámou chybu a nemohl zpracovat zprávu.", + "unknown_error": "Odeslání protokolů se nezdařilo." + }, "github_issue": "issue na GitHubu", "introduction": "Pokud jste odeslali chybu prostřednictvím GitHubu, ladící protokoly nám mohou pomoci problém vysledovat. ", "log_request": "Abychom tomu mohli pro příště předejít, pošlete nám prosím záznamy.", @@ -1298,6 +1307,7 @@ "error_connecting_heading": "Nepovedlo se připojení ke správci integrací", "explainer": "Správci integrace přijímají konfigurační data a mohou vaším jménem upravovat widgety, odesílat pozvánky do místností a nastavovat úrovně oprávnění.", "manage_title": "Správa integrací", + "toggle_label": "Povolit správce integrací", "use_im": "Použít správce integrací na správu botů, widgetů a nálepek.", "use_im_default": "Použít správce integrací (%(serverName)s) na správu botů, widgetů a nálepek." }, @@ -2100,12 +2110,16 @@ "one": "Momentálně se připojuje %(count)s místnost", "other": "Momentálně se připojuje %(count)s místností" }, + "list_title": "Seznam místností", "notification_options": "Možnosti oznámení", "open_space_menu": "Otevřít nabídku prostoru", "redacting_messages_status": { "one": "Momentálně se odstraňují zprávy v %(count)s místnosti", "other": "Momentálně se odstraňují zprávy v %(count)s místnostech" }, + "room": { + "open_room": "Otevřít místnost %(roomName)s" + }, "show_less": "Zobrazit méně", "show_n_more": { "other": "Zobrazit %(count)s dalších", diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index ba7762b4a1..e3722da0a5 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -1306,6 +1306,7 @@ "error_connecting_heading": "Impossible de se connecter au gestionnaire d’intégrations", "explainer": "Les gestionnaires d’intégrations reçoivent les données de configuration et peuvent modifier les widgets, envoyer des invitations aux salons et définir les rangs à votre place.", "manage_title": "Gérer les intégrations", + "toggle_label": "Activer le gestionnaire d'intégration", "use_im": "Utilisez un gestionnaire d’intégrations pour gérer les robots, les widgets et les jeux d’autocollants.", "use_im_default": "Utilisez un gestionnaire d’intégrations (%(serverName)s) pour gérer les robots, les widgets et les jeux d’autocollants." }, @@ -2097,6 +2098,12 @@ "failed_add_tag": "Échec de l’ajout de l’étiquette %(tagName)s au salon", "failed_remove_tag": "Échec de la suppression de l’étiquette %(tagName)s du salon", "failed_set_dm_tag": "Échec de l’ajout de l’étiquette de conversation privée", + "filters": { + "favourite": "Favoris", + "people": "Personnes", + "rooms": "Salons", + "unread": "Non lu" + }, "home_menu_label": "Options de l’accueil", "join_public_room_label": "Rejoindre le salon public", "joining_rooms_status": { diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index d07513949e..6b569ad870 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -80,12 +80,14 @@ "maximise": "Teljes méret", "mention": "Megemlítés", "minimise": "Lecsukás", + "new_message": "Új üzenet", "new_room": "Új szoba", "new_video_room": "Új videószoba", "next": "Következő", "no": "Nem", "ok": "Rendben", "open": "Megnyitás", + "open_menu": "Menü megnyitása", "pause": "Szünet", "pin": "Kitűzés", "play": "Lejátszás", @@ -1275,7 +1277,9 @@ "title": "Nem támogatott böngésző", "use_desktop_heading": "Használjon inkább %(brand)s asztali alkalmazást", "use_mobile_heading": "%(brand)s mobil alkalmazás használata", - "use_mobile_heading_after_desktop": "Vagy használja mobilalkalmazásunkat" + "use_mobile_heading_after_desktop": "Vagy használja mobilalkalmazásunkat", + "windows_64bit": "Windows (64 bites)", + "windows_arm_64bit": "Windows (64 bites ARM)" }, "info_tooltip_title": "Információ", "integration_manager": { @@ -2068,6 +2072,12 @@ "failed_add_tag": "Nem sikerült hozzáadni a szobához ezt: %(tagName)s", "failed_remove_tag": "Nem sikerült a szobáról eltávolítani ezt: %(tagName)s", "failed_set_dm_tag": "Nem sikerült a közvetlen beszélgetés címkét beállítani", + "filters": { + "favourite": "Kedvencek", + "people": "Emberek", + "rooms": "Szobák", + "unread": "Olvasatlan" + }, "home_menu_label": "Kezdőlap beállítások", "join_public_room_label": "Belépés nyilvános szobába", "joining_rooms_status": { diff --git a/src/i18n/strings/nb_NO.json b/src/i18n/strings/nb_NO.json index f871244d7b..45f6ea8ebe 100644 --- a/src/i18n/strings/nb_NO.json +++ b/src/i18n/strings/nb_NO.json @@ -407,6 +407,7 @@ "download_logs": "Last ned logger", "downloading_logs": "Laster ned logger", "error_empty": "Fortell oss hva som gikk galt, eller bedre, opprett et GitHub-problem som beskriver problemet.", + "failed_download_logs": "Kunne ikke laste ned feilsøkingslogger: ", "github_issue": "Github-saksrapport", "introduction": "Hvis du har sendt inn en feil via GitHub, kan feilsøkingslogger hjelpe oss med å spore opp problemet. ", "log_request": "For å hjelpe oss med å forhindre dette i fremtiden, vennligst send oss loggfiler.", diff --git a/src/i18n/strings/uk.json b/src/i18n/strings/uk.json index c30ee6b7ae..4996466148 100644 --- a/src/i18n/strings/uk.json +++ b/src/i18n/strings/uk.json @@ -2103,6 +2103,12 @@ "failed_add_tag": "Не вдалось додати до кімнати мітку %(tagName)s", "failed_remove_tag": "Не вдалося прибрати з кімнати мітку %(tagName)s", "failed_set_dm_tag": "Не вдалося встановити мітку особистого повідомлення", + "filters": { + "favourite": "Обрані", + "people": "Люди", + "rooms": "Кімнати", + "unread": "Непрочитані" + }, "home_menu_label": "Параметри домівки", "join_public_room_label": "Приєднатись до загальнодоступної кімнати", "joining_rooms_status": { From bf6ae73d39f95de81414a5bffd15f8c92b594384 Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Wed, 12 Mar 2025 08:04:17 +0000 Subject: [PATCH 066/458] White background for 'They do not match' button (#29470) --- src/components/views/verification/VerificationShowSas.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/views/verification/VerificationShowSas.tsx b/src/components/views/verification/VerificationShowSas.tsx index d2d53164d3..2292aad090 100644 --- a/src/components/views/verification/VerificationShowSas.tsx +++ b/src/components/views/verification/VerificationShowSas.tsx @@ -165,12 +165,12 @@ export default class VerificationShowSas extends React.Component } else { confirm = (
- - {_t("encryption|verification|sas_no_match")} - {_t("encryption|verification|sas_match")} + + {_t("encryption|verification|sas_no_match")} +
); } From a058d85c2196b5bd110611e34ebc1b66fe00a7df Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Mar 2025 11:50:10 +0000 Subject: [PATCH 067/458] Update playwright to v1.51.0 (#29469) * Update playwright to v1.51.0 * Update screenshots Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --- playwright/Dockerfile | 2 +- .../invite-dialog-dm-with-user-pill-linux.png | Bin 60445 -> 60456 bytes .../invite-dialog-dm-without-user-linux.png | Bin 51656 -> 51670 bytes .../account-linux.png | Bin 65929 -> 65882 bytes .../account-smallscreen-linux.png | Bin 35568 -> 36546 bytes yarn.lock | 26 +++++++++--------- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/playwright/Dockerfile b/playwright/Dockerfile index 26ab7e5603..6d812037de 100644 --- a/playwright/Dockerfile +++ b/playwright/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/playwright:v1.50.1-noble +FROM mcr.microsoft.com/playwright:v1.51.0-noble WORKDIR /work diff --git a/playwright/snapshots/invite/invite-dialog.spec.ts/invite-dialog-dm-with-user-pill-linux.png b/playwright/snapshots/invite/invite-dialog.spec.ts/invite-dialog-dm-with-user-pill-linux.png index 7e3b73aaeea8d1ccfcacedac3c1c8f1a5237e6f6..95b10570a08aa1d6ddf87d4181547119e5926383 100644 GIT binary patch delta 24180 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

}C)stu&+apCywiMGoaPb9?efK+ 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 diff --git a/playwright/snapshots/invite/invite-dialog.spec.ts/invite-dialog-dm-without-user-linux.png b/playwright/snapshots/invite/invite-dialog.spec.ts/invite-dialog-dm-without-user-linux.png index e8fbfdce043738b3de18f8b4dc0148f44b7ca7c9..8f2a488c00b36366504ff03a58317d89661ec14e 100644 GIT binary patch delta 14458 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

@FYw{1?i}DjfA=@E7*MYCkk|g9`e5#P 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%0DJ}8so8_X&YGTP_KOW4i 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

AH% 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

`xamFQonUKpc`9Y8I;@zq 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 literal 35568 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 diff --git a/yarn.lock b/yarn.lock index dbc924a9f9..deb6d393bd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2168,11 +2168,11 @@ integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== "@playwright/test@^1.40.1": - version "1.50.1" - resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.50.1.tgz#027d00ca77ec79688764eb765cfe9a688807bf0b" - integrity sha512-Jii3aBg+CEDpgnuDxEp/h7BimHcUTDlpEtce89xEumlJ5ef2hqepZ+PWp1DDpYC/VO9fmWVI1IlEaoI5fK9FXQ== + version "1.51.0" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.51.0.tgz#8d5c8400b465a0bfdbcf993e390ceecb903ea6d2" + integrity sha512-dJ0dMbZeHhI+wb77+ljx/FeC8VBP6j/rj9OAojO08JI80wTZy6vRk9KvHKiDCUh4iMpEiseMgqRBIeW+eKX6RA== dependencies: - playwright "1.50.1" + playwright "1.51.0" "@polka/url@^1.0.0-next.24": version "1.0.0-next.28" @@ -9552,17 +9552,17 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -playwright-core@1.50.1, playwright-core@^1.45.1: - version "1.50.1" - resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.50.1.tgz#6a0484f1f1c939168f40f0ab3828c4a1592c4504" - integrity sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ== +playwright-core@1.51.0, playwright-core@^1.45.1: + version "1.51.0" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.51.0.tgz#bb23ea6bb6298242d088ae5e966ffcf8dc9827e8" + integrity sha512-x47yPE3Zwhlil7wlNU/iktF7t2r/URR3VLbH6EknJd/04Qc/PSJ0EY3CMXipmglLG+zyRxW6HNo2EGbKLHPWMg== -playwright@1.50.1: - version "1.50.1" - resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.50.1.tgz#2f93216511d65404f676395bfb97b41aa052b180" - integrity sha512-G8rwsOQJ63XG6BbKj2w5rHeavFjy5zynBA9zsJMMtBoe/Uf757oG12NXz6e6OirF7RCrTVAKFXbLmn1RbL7Qaw== +playwright@1.51.0: + version "1.51.0" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.51.0.tgz#9ba154497ba62bc6dc199c58ee19295eb35a4707" + integrity sha512-442pTfGM0xxfCYxuBa/Pu6B2OqxqqaYq39JS8QDMGThUvIOCd6s0ANDog3uwA0cHavVlnTQzGCN7Id2YekDSXA== dependencies: - playwright-core "1.50.1" + playwright-core "1.51.0" optionalDependencies: fsevents "2.3.2" From cd6737942fe63b6956d762968dfbfbd90da369e9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Mar 2025 12:45:21 +0000 Subject: [PATCH 068/458] Update dependency @babel/runtime to v7.26.10 [SECURITY] (#29478) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index deb6d393bd..9f7a27a82d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1100,9 +1100,9 @@ "@babel/plugin-transform-typescript" "^7.25.9" "@babel/runtime@^7.0.0", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.17.9", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.9.tgz#aa4c6facc65b9cb3f87d75125ffd47781b475433" - integrity sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg== + version "7.26.10" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.10.tgz#a07b4d8fa27af131a633d7b3524db803eb4764c2" + integrity sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw== dependencies: regenerator-runtime "^0.14.0" From cb7d77de4537b1cc7c379c8838f9c8089fc94cfd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Mar 2025 12:45:21 +0000 Subject: [PATCH 069/458] Update dependency @babel/runtime to v7.26.10 [SECURITY] (#29478) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> From e44ca88a7edc4d047ea625d30d47bf911961dc71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Gy=C3=B6ngy=C3=B6si?= Date: Thu, 13 Mar 2025 10:46:29 +0100 Subject: [PATCH 070/458] Change ToggleHiddenEventVisibility & GoToHome KeyBindingActions (#29374) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current keyboard shortcuts for GoToHome and ToggleHiddenEventVisibility are: | | other | macOS | |----------------------------- |-------------- |-------------- | | GoToHome | Ctrl–Alt–H | Ctrl–Shift–H | | ToggleHiddenEventVisibility | Ctrl–Shift–H | Cmd–Shift–H | This removes both distinctions for macOS in order ToggleHiddenEventVisibility not to conflict with... 1. the built-in Safari keyboard shortcut for opening the Home page (Cmd–Shift–H) 2. the KeyBindingAction for GoToHome. Co-authored-by: Florian Duros --- src/accessibility/KeyboardShortcuts.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/accessibility/KeyboardShortcuts.ts b/src/accessibility/KeyboardShortcuts.ts index d5c32d6d8d..da0097f4b2 100644 --- a/src/accessibility/KeyboardShortcuts.ts +++ b/src/accessibility/KeyboardShortcuts.ts @@ -521,8 +521,7 @@ export const KEYBOARD_SHORTCUTS: IKeyboardShortcuts = { [KeyBindingAction.GoToHome]: { default: { ctrlKey: true, - altKey: !IS_MAC, - shiftKey: IS_MAC, + altKey: true, key: Key.H, }, displayName: _td("keyboard|go_home_view"), @@ -585,7 +584,7 @@ export const KEYBOARD_SHORTCUTS: IKeyboardShortcuts = { }, [KeyBindingAction.ToggleHiddenEventVisibility]: { default: { - ctrlOrCmdKey: true, + ctrlKey: true, shiftKey: true, key: Key.H, }, From 917d53a56fd6de290fdf2269a330d62fe6464907 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Thu, 13 Mar 2025 14:32:48 +0100 Subject: [PATCH 071/458] Add wrap props to flex component (#29480) * feat(flex): add wrap props to flex component * test: update snapshot --- res/css/components/views/utils/_Flex.pcss | 1 + src/components/utils/Flex.tsx | 9 ++++- .../__snapshots__/ErrorView-test.tsx.snap | 6 +-- .../__snapshots__/FilePanel-test.tsx.snap | 2 +- .../__snapshots__/RoomView-test.tsx.snap | 14 +++---- ...teractiveAuthEntryComponents-test.tsx.snap | 2 +- .../ExtensionsCard-test.tsx.snap | 2 +- .../PinnedMessagesCard-test.tsx.snap | 2 +- .../RoomSummaryCard-test.tsx.snap | 12 +++--- .../__snapshots__/UserInfo-test.tsx.snap | 30 +++++++------- .../__snapshots__/RoomHeader-test.tsx.snap | 2 +- .../__snapshots__/RoomList-test.tsx.snap | 40 +++++++++---------- .../__snapshots__/RoomListCell-test.tsx.snap | 4 +- .../RoomListHeaderView-test.tsx.snap | 16 ++++---- .../__snapshots__/RoomListPanel-test.tsx.snap | 16 ++++---- .../RoomListSearch-test.tsx.snap | 16 ++++---- .../ThirdPartyMemberInfo-test.tsx.snap | 8 ++-- .../MemberTileView-test.tsx.snap | 2 +- .../ResetIdentityPanel-test.tsx.snap | 8 ++-- .../EncryptionUserSettingsTab-test.tsx.snap | 2 +- .../vector/__snapshots__/init-test.ts.snap | 6 +-- 21 files changed, 104 insertions(+), 96 deletions(-) diff --git a/res/css/components/views/utils/_Flex.pcss b/res/css/components/views/utils/_Flex.pcss index a7f3688466..9cfa6424f0 100644 --- a/res/css/components/views/utils/_Flex.pcss +++ b/res/css/components/views/utils/_Flex.pcss @@ -12,4 +12,5 @@ Please see LICENSE files in the repository root for full details. align-items: var(--mx-flex-align, unset); justify-content: var(--mx-flex-justify, unset); gap: var(--mx-flex-gap, unset); + flex-wrap: var(--mx-flex-wrap, unset); } diff --git a/src/components/utils/Flex.tsx b/src/components/utils/Flex.tsx index ca085a0a52..c4e2f90066 100644 --- a/src/components/utils/Flex.tsx +++ b/src/components/utils/Flex.tsx @@ -39,6 +39,11 @@ type FlexProps should match snapshot 1`] = `

should show the empty state when there are no pi >
has button to edit topic 1`] = ` />
has button to edit topic 1`] = `
renders the room summary 1`] = ` />
renders the room summary 1`] = `
renders the room topic in the summary 1`] = ` />
renders the room topic in the summary 1`] = `
with crypto enabled renders 1`] = ` >

with crypto enabled renders 1`] = ` >
@user:example.com
@@ -113,7 +113,7 @@ exports[` with crypto enabled renders 1`] = `

with crypto enabled should render a deactivate button for >

with crypto enabled should render a deactivate button for >
@user:example.com
@@ -399,7 +399,7 @@ exports[` with crypto enabled should render a deactivate button for

renders verification unavailable message 1`] = ` >

renders verification unavailable message 1`] = ` >
@user:example.com
@@ -689,7 +689,7 @@ exports[` renders verification unavailable message 1`] = `

renders verified badge when user is verified 1`] = ` >

renders verified badge when user is verified 1`] = ` >
@user:example.com
@@ -771,7 +771,7 @@ exports[` renders verified badge when user is verified 1`] = `

renders verify button 1`] = ` >

renders verify button 1`] = ` >
@user:example.com
@@ -868,7 +868,7 @@ exports[` renders verify button 1`] = `

should display the reset identity panel w
+
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
should render the RoomListSearch component when UICom
+
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
should render primary filters 1`] = ` + +
    +
  • + +
  • +
  • + +
  • +
+
+`; From 973d639d01cd690d18cc02daa7f6ee72326baae6 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Fri, 14 Mar 2025 06:15:40 +0000 Subject: [PATCH 076/458] [create-pull-request] automated change (#29494) Co-authored-by: t3chguy <2403652+t3chguy@users.noreply.github.com> --- playwright/testcontainers/synapse.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright/testcontainers/synapse.ts b/playwright/testcontainers/synapse.ts index d3f661ecc6..47c2e708e2 100644 --- a/playwright/testcontainers/synapse.ts +++ b/playwright/testcontainers/synapse.ts @@ -25,7 +25,7 @@ import { type HomeserverContainer, type StartedHomeserverContainer } from "./Hom import { type StartedMatrixAuthenticationServiceContainer } from "./mas.ts"; import { Api, ClientServerApi, type Verb } from "../plugins/utils/api.ts"; -const TAG = "develop@sha256:26e0d9c5ca96218243432d48a9f8596e4c1bc10b748f0a1bddf9916b914d1216"; +const TAG = "develop@sha256:2ea87d45fc7ff3327c671b3b4447e6b2032d4f5ca07d62d8aef0d900e105c2f4"; const DEFAULT_CONFIG = { server_name: "localhost", From be3778bef0b783cc4c6b4cb5d16d7d27d10b3d8d Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 14 Mar 2025 08:52:41 +0000 Subject: [PATCH 077/458] Add key storage toggle to Encryption settings (#29310) * Add key storage toggle to Encryption settings * Keys in the acceptable order * Fix some tests * Fix import * Fix toast showing condition * Fix import order * Fix playwright tests * Fix bits lost in merge * Add key storage delete confirm screen * Fix hardcoded Element string * Fix type imports * Fix tests * Tests for key storage delete panel * Fix test * Type import * Test for the view model * Fix type import * Actually fix type imports * Test updating * Add playwright test & clarify slightly confusing comment * Show the advnced section whatever the state of key storage * Update screenshots * Copy css to its own file * Add missing doc & merge loading states * Add tsdoc & loading alt text to spinner * Turn comments into proper tsdoc * Switch to TypedEventEmitter and remove unnecessary loading state * Add screenshot * Use higher level interface * Merge the two hooks in EncryptionUserSettingsTab * Remove unused import * Don't check key backup enabled state separately as we don't need it for all the screens * Update snapshot * Use fixed recovery key function * Amalgamate duplicated CSS files * Have "key storage disabled" as a separate state * Update snapshot * Fix... bad merge? * Add backup enabled mock to more tests * More snapshots * Use defer util * Update to use EncryptionCardButtons * Update snapshots * Use EncryptionCardEmphasisedContent * Update snapshots * Update snapshot * Try screenshot from CI playwright * Try playwright screenshots again * More screenshots * Rename to match files * Test that 4S secrets are deleted * Make description clearer * Fix typo & move related states together * Add comment * More comments * Fix hook docs * restoreAllMocks * Update snapshot because pulling in upstream has caused IDs to shift * Switch icon as apparenty the error icon has changed * Update snapshot * Missing copyright * Re-order states and also sort out indenting * Remove phantom space * Clarify 'button' * Clarify docs more * Explain thinking behind updating * Switch to getActiveBackupVersion which checks that key backup is happining on this device, which is consistent with EX. * Add use of Key Storage Panel Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> * Change key storage panel to be consistent ie. using getActiveBackupVersion(), and add comment * Add tsdoc Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> * Use BACKUP_DISABLED_ACCOUNT_DATA_KEY in more places * Expand doc Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> * Undo random yarn lock change * Use aggregate method for disabling key storage in https://github.com/matrix-org/matrix-js-sdk/pull/4742 * Fix tests * Use key backup status event to update * Comment formatting Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> * Fix comment & put check inside if statement * Add comment * Prettier * Fix comment * Update snapshot Which has gained nowrap due to 917d53a56fd6de290fdf2269a330d62fe6464907 --------- Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- .../encryption-tab.spec.ts | 36 +++- .../encryption-details-linux.png | Bin 17264 -> 17215 bytes .../reset-cryptographic-identity-linux.png | Bin 50646 -> 50646 bytes .../default-tab-linux.png | Bin 42241 -> 52606 bytes .../delete-key-storage-confirm-linux.png | Bin 0 -> 55103 bytes .../default-recovery-linux.png | Bin 18645 -> 18612 bytes .../set-up-recovery-linux.png | Bin 19109 -> 19108 bytes res/css/_components.pcss | 1 + .../settings/encryption/_KeyStoragePanel.pcss | 10 ++ src/DeviceListener.ts | 11 +- .../encryption/KeyStoragePanelViewModel.ts | 116 +++++++++++++ .../encryption/DeleteKeyStoragePanel.tsx | 79 +++++++++ .../settings/encryption/KeyStoragePanel.tsx | 75 +++++++++ .../tabs/user/EncryptionUserSettingsTab.tsx | 61 +++++-- src/i18n/strings/en_EN.json | 13 ++ test/test-utils/test-utils.ts | 3 + .../KeyStoragePanelViewModel-test.ts | 91 ++++++++++ .../encryption/DeleteKeyStoragePanel-test.tsx | 96 +++++++++++ .../DeleteKeyStoragePanel-test.tsx.snap | 156 ++++++++++++++++++ .../user/EncryptionUserSettingsTab-test.tsx | 48 +++++- 20 files changed, 772 insertions(+), 24 deletions(-) create mode 100644 playwright/snapshots/settings/encryption-user-tab/encryption-tab.spec.ts/delete-key-storage-confirm-linux.png create mode 100644 res/css/components/views/settings/encryption/_KeyStoragePanel.pcss create mode 100644 src/components/viewmodels/settings/encryption/KeyStoragePanelViewModel.ts create mode 100644 src/components/views/settings/encryption/DeleteKeyStoragePanel.tsx create mode 100644 src/components/views/settings/encryption/KeyStoragePanel.tsx create mode 100644 test/unit-tests/components/viewmodels/settings/encryption/KeyStoragePanelViewModel-test.ts create mode 100644 test/unit-tests/components/views/settings/encryption/DeleteKeyStoragePanel-test.tsx create mode 100644 test/unit-tests/components/views/settings/encryption/__snapshots__/DeleteKeyStoragePanel-test.tsx.snap diff --git a/playwright/e2e/settings/encryption-user-tab/encryption-tab.spec.ts b/playwright/e2e/settings/encryption-user-tab/encryption-tab.spec.ts index 107f8085cc..427c801ef4 100644 --- a/playwright/e2e/settings/encryption-user-tab/encryption-tab.spec.ts +++ b/playwright/e2e/settings/encryption-user-tab/encryption-tab.spec.ts @@ -17,9 +17,7 @@ import { } from "../../crypto/utils"; test.describe("Encryption tab", () => { - test.use({ - displayName: "Alice", - }); + test.use({ displayName: "Alice" }); let recoveryKey: GeneratedSecretStorageKey; let expectedBackupVersion: string; @@ -111,4 +109,36 @@ test.describe("Encryption tab", () => { // The user is prompted to reset their identity await expect(dialog.getByText("Forgot your recovery key? You’ll need to reset your identity.")).toBeVisible(); }); + + test("should warn before turning off key storage", { tag: "@screenshot" }, async ({ page, app, util }) => { + await verifySession(app, recoveryKey.encodedPrivateKey); + await util.openEncryptionTab(); + + await page.getByRole("checkbox", { name: "Allow key storage" }).click(); + + await expect( + page.getByRole("heading", { name: "Are you sure you want to turn off key storage and delete it?" }), + ).toBeVisible(); + + await expect(util.getEncryptionTabContent()).toMatchScreenshot("delete-key-storage-confirm.png"); + + const deleteRequestPromises = [ + page.waitForRequest((req) => req.url().endsWith("/account_data/m.cross_signing.master")), + page.waitForRequest((req) => req.url().endsWith("/account_data/m.cross_signing.self_signing")), + page.waitForRequest((req) => req.url().endsWith("/account_data/m.cross_signing.user_signing")), + page.waitForRequest((req) => req.url().endsWith("/account_data/m.megolm_backup.v1")), + page.waitForRequest((req) => req.url().endsWith("/account_data/m.secret_storage.default_key")), + page.waitForRequest((req) => req.url().includes("/account_data/m.secret_storage.key.")), + ]; + + await page.getByRole("button", { name: "Delete key storage" }).click(); + + await expect(page.getByRole("checkbox", { name: "Allow key storage" })).not.toBeChecked(); + + for (const prom of deleteRequestPromises) { + const request = await prom; + expect(request.method()).toBe("PUT"); + expect(request.postData()).toBe(JSON.stringify({})); + } + }); }); diff --git a/playwright/snapshots/settings/encryption-user-tab/advanced.spec.ts/encryption-details-linux.png b/playwright/snapshots/settings/encryption-user-tab/advanced.spec.ts/encryption-details-linux.png index 51c0bd8740ac93d222d1408dbec519ce704952d0..6a95f36da716988ea9d56b9e1d4bd179d507d691 100644 GIT binary patch literal 17215 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 KBuc~#1O6|TH^wsn literal 17264 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 delta 329 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�U6w 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 DxmC>2 literal 0 HcmV?d00001 diff --git a/playwright/snapshots/settings/encryption-user-tab/recovery.spec.ts/default-recovery-linux.png b/playwright/snapshots/settings/encryption-user-tab/recovery.spec.ts/default-recovery-linux.png index fb778886c650c25ffadfb07bda95b40f38857040..9c23f7ea20124bd0a6d00d4aedf07eaf7882c237 100644 GIT binary patch literal 18612 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
F6x3e=d&5$u0J`pj|!PPF7 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�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 DDB|#& diff --git a/playwright/snapshots/settings/encryption-user-tab/recovery.spec.ts/set-up-recovery-linux.png b/playwright/snapshots/settings/encryption-user-tab/recovery.spec.ts/set-up-recovery-linux.png index d34640d213c827210c9c8bdc93285e16e786ebe8..e7dcea94369cef90e543067477868d3e528ec012 100644 GIT binary patch literal 19108 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 void; + + /** + * True if the state is still loading for the first time + */ + loading: boolean; + + /** + * True if the status is in the process of being changed + */ + busy: boolean; +} + +/** Returns a ViewModel for use in {@link KeyStoragePanel} and {@link DeleteKeyStoragePanel}. */ +export function useKeyStoragePanelViewModel(): KeyStoragePanelState { + const [isEnabled, setIsEnabled] = useState(undefined); + const [loading, setLoading] = useState(true); + // Whilst the change is being made, the toggle will reflect the pending value rather than the actual state + const [pendingValue, setPendingValue] = useState(undefined); + + const matrixClient = useMatrixClientContext(); + + const checkStatus = useCallback(async () => { + const crypto = matrixClient.getCrypto(); + if (!crypto) { + logger.error("Can't check key backup status: no crypto module available"); + return; + } + // The toggle is enabled only if this device will upload megolm keys to the backup. + // This is consistent with EX. + const activeBackupVersion = await crypto.getActiveSessionBackupVersion(); + setIsEnabled(activeBackupVersion !== null); + }, [matrixClient]); + + useEffect(() => { + (async () => { + await checkStatus(); + setLoading(false); + })(); + }, [checkStatus]); + + const setEnabled = useCallback( + async (enable: boolean) => { + setPendingValue(enable); + try { + // stop the device listener since enabling or (especially) disabling key storage must be + // done with a sequence of API calls that will put the account in a slightly different + // state each time, so suppress any warning toasts until the process is finished (when + // we'll turn it back on again.) + DeviceListener.sharedInstance().stop(); + + const crypto = matrixClient.getCrypto(); + if (!crypto) { + logger.error("Can't change key backup status: no crypto module available"); + return; + } + if (enable) { + // If there is no existing key backup on the server, create one. + // `resetKeyBackup` will delete any existing backup, so we only do this if there is no existing backup. + const currentKeyBackup = await crypto.checkKeyBackupAndEnable(); + if (currentKeyBackup === null) { + await crypto.resetKeyBackup(); + + // resetKeyBackup fires this off in the background without waiting, so we need to do it + // explicitly and wait for it, otherwise it won't be enabled yet when we check again. + await crypto.checkKeyBackupAndEnable(); + } + + // Set the flag so that EX no longer thinks the user wants backup disabled + await matrixClient.setAccountData(BACKUP_DISABLED_ACCOUNT_DATA_KEY, { disabled: false }); + } else { + // This method will delete the key backup as well as server side recovery keys and other + // server-side crypto data. + await crypto.disableKeyStorage(); + + // Set a flag to say that the user doesn't want key backup. + // Element X uses this to determine whether to set up automatically, + // so this will stop EX turning it back on spontaneously. + await matrixClient.setAccountData(BACKUP_DISABLED_ACCOUNT_DATA_KEY, { disabled: true }); + } + + await checkStatus(); + } finally { + setPendingValue(undefined); + DeviceListener.sharedInstance().start(matrixClient); + } + }, + [setPendingValue, checkStatus, matrixClient], + ); + + return { isEnabled: pendingValue ?? isEnabled, setEnabled, loading, busy: pendingValue !== undefined }; +} diff --git a/src/components/views/settings/encryption/DeleteKeyStoragePanel.tsx b/src/components/views/settings/encryption/DeleteKeyStoragePanel.tsx new file mode 100644 index 0000000000..31fac19f07 --- /dev/null +++ b/src/components/views/settings/encryption/DeleteKeyStoragePanel.tsx @@ -0,0 +1,79 @@ +/* + * Copyright 2025 New Vector 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 { Breadcrumb, Button, VisualList, VisualListItem } from "@vector-im/compound-web"; +import CrossIcon from "@vector-im/compound-design-tokens/assets/web/icons/close"; +import ErrorIcon from "@vector-im/compound-design-tokens/assets/web/icons/error-solid"; +import React, { useCallback, useState } from "react"; + +import { _t } from "../../../../languageHandler"; +import { EncryptionCard } from "./EncryptionCard"; +import { useKeyStoragePanelViewModel } from "../../../viewmodels/settings/encryption/KeyStoragePanelViewModel"; +import SdkConfig from "../../../../SdkConfig"; +import { EncryptionCardButtons } from "./EncryptionCardButtons"; +import { EncryptionCardEmphasisedContent } from "./EncryptionCardEmphasisedContent"; + +interface Props { + /** + * Called when the user either cancels the operation or key storage has been disabled + */ + onFinish: () => void; +} + +/** + * Confirms that the user really wants to turn off and delete their key storage. Part of the "Encryption" settings tab. + */ +export function DeleteKeyStoragePanel({ onFinish }: Props): JSX.Element { + const { setEnabled } = useKeyStoragePanelViewModel(); + const [busy, setBusy] = useState(false); + + const onDeleteClick = useCallback(async () => { + setBusy(true); + try { + await setEnabled(false); + } finally { + setBusy(false); + } + onFinish(); + }, [setEnabled, onFinish]); + + return ( + <> + + + + {_t("settings|encryption|delete_key_storage|description")} + + + {_t("settings|encryption|delete_key_storage|list_first")} + + + {_t("settings|encryption|delete_key_storage|list_second", { brand: SdkConfig.get().brand })} + + + + + + + + + + ); +} diff --git a/src/components/views/settings/encryption/KeyStoragePanel.tsx b/src/components/views/settings/encryption/KeyStoragePanel.tsx new file mode 100644 index 0000000000..0de55942a7 --- /dev/null +++ b/src/components/views/settings/encryption/KeyStoragePanel.tsx @@ -0,0 +1,75 @@ +/* + * Copyright 2025 New Vector 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, { useCallback } from "react"; +import { InlineField, InlineSpinner, Label, Root, ToggleControl } from "@vector-im/compound-web"; + +import type { FormEvent } from "react"; +import { SettingsSection } from "../shared/SettingsSection"; +import { _t } from "../../../../languageHandler"; +import { SettingsHeader } from "../SettingsHeader"; +import { useKeyStoragePanelViewModel } from "../../../viewmodels/settings/encryption/KeyStoragePanelViewModel"; + +interface Props { + /** + * Called when the user turns off the "allow key storage" toggle + */ + onKeyStorageDisableClick: () => void; +} + +/** + * This component allows the user to set up or change their recovery key. + * + * It is used within the "Encryption" settings tab. + */ +export const KeyStoragePanel: React.FC = ({ onKeyStorageDisableClick }) => { + const { isEnabled, setEnabled, loading, busy } = useKeyStoragePanelViewModel(); + + const onKeyBackupChange = useCallback( + (e: FormEvent) => { + if (e.currentTarget.checked) { + setEnabled(true); + } else { + onKeyStorageDisableClick(); + } + }, + [setEnabled, onKeyStorageDisableClick], + ); + + if (loading) { + return ; + } + + return ( + + } + subHeading={_t("settings|encryption|key_storage|description", undefined, { + a: (sub) => ( + + {sub} + + ), + })} + > + + } + > + + + {busy && } + + + ); +}; diff --git a/src/components/views/settings/tabs/user/EncryptionUserSettingsTab.tsx b/src/components/views/settings/tabs/user/EncryptionUserSettingsTab.tsx index 2a041a04c8..3af555ed49 100644 --- a/src/components/views/settings/tabs/user/EncryptionUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/EncryptionUserSettingsTab.tsx @@ -8,6 +8,7 @@ import React, { type JSX, useCallback, useEffect, useState } from "react"; import { Button, InlineSpinner, Separator } from "@vector-im/compound-web"; import ComputerIcon from "@vector-im/compound-design-tokens/assets/web/icons/computer"; +import { CryptoEvent } from "matrix-js-sdk/src/crypto-api"; import SettingsTab from "../SettingsTab"; import { RecoveryPanel } from "../../encryption/RecoveryPanel"; @@ -21,11 +22,15 @@ import { SettingsSubheader } from "../../SettingsSubheader"; import { AdvancedPanel } from "../../encryption/AdvancedPanel"; import { ResetIdentityPanel } from "../../encryption/ResetIdentityPanel"; import { RecoveryPanelOutOfSync } from "../../encryption/RecoveryPanelOutOfSync"; +import { useTypedEventEmitter } from "../../../../../hooks/useEventEmitter"; +import { KeyStoragePanel } from "../../encryption/KeyStoragePanel"; +import { DeleteKeyStoragePanel } from "../../encryption/DeleteKeyStoragePanel"; /** * The state in the encryption settings tab. * - "loading": We are checking if the device is verified. * - "main": The main panel with all the sections (Key storage, recovery, advanced). + * - "key_storage_disabled": The user has chosen to disable key storage and options are unavailable as a result. * - "set_up_encryption": The panel to show when the user is setting up their encryption. * This happens when the user doesn't have cross-signing enabled, or their current device is not verified. * - "change_recovery_key": The panel to show when the user is changing their recovery key. @@ -33,19 +38,22 @@ import { RecoveryPanelOutOfSync } from "../../encryption/RecoveryPanelOutOfSync" * - "set_recovery_key": The panel to show when the user is setting up their recovery key. * This happens when the user doesn't have a key a recovery key and the user clicks on "Set up recovery key" button of the RecoveryPanel. * - "reset_identity_compromised": The panel to show when the user is resetting their identity, in te case where their key is compromised. - * - "reset_identity_forgot": The panel to show when the user is resetting their identity, in the case where they forgot their recovery key. - * - `secrets_not_cached`: The secrets are not cached locally. This can happen if we verified another device and secret-gossiping failed, or the other device itself lacked the secrets. + * - "reset_identity_forgot": The panel to show when the user is resetting their identity, in the case where they forgot their recovery key. + * - "secrets_not_cached": The secrets are not cached locally. This can happen if we verified another device and secret-gossiping failed, or the other device itself lacked the secrets. * If the "set_up_encryption" and "secrets_not_cached" conditions are both filled, "set_up_encryption" prevails. + * - "key_storage_delete": The confirmation page asking if the user really wants to turn off key storage. */ export type State = | "loading" | "main" + | "key_storage_disabled" | "set_up_encryption" | "change_recovery_key" | "set_recovery_key" | "reset_identity_compromised" | "reset_identity_forgot" - | "secrets_not_cached"; + | "secrets_not_cached" + | "key_storage_delete"; interface EncryptionUserSettingsTabProps { /** @@ -63,6 +71,7 @@ export function EncryptionUserSettingsTab({ initialState = "loading" }: Encrypti const checkEncryptionState = useCheckEncryptionState(state, setState); let content: JSX.Element; + switch (state) { case "loading": content = ; @@ -78,15 +87,23 @@ export function EncryptionUserSettingsTab({ initialState = "loading" }: Encrypti /> ); break; + case "key_storage_disabled": case "main": content = ( <> - - setupNewKey ? setState("set_recovery_key") : setState("change_recovery_key") - } - /> + setState("key_storage_delete")} /> + {/* We only show the "Recovery" panel if key storage is enabled.*/} + {state === "main" && ( + <> + + setupNewKey ? setState("set_recovery_key") : setState("change_recovery_key") + } + /> + + + )} setState("reset_identity_compromised")} /> ); @@ -111,6 +128,9 @@ export function EncryptionUserSettingsTab({ initialState = "loading" }: Encrypti /> ); break; + case "key_storage_delete": + content = ; + break; } return ( @@ -124,10 +144,12 @@ export function EncryptionUserSettingsTab({ initialState = "loading" }: Encrypti * Hook to check if the user needs: * - to go through the SetupEncryption flow. * - to enter their recovery key, if the secrets are not cached locally. + * ...and also whether megolm key backup is enabled on this device (which we use to set the state of the 'allow key storage' toggle) * - * If the user needs to set up the encryption, the state will be set to "set_up_encryption". - * If the user secrets are not cached, the state will be set to "secrets_not_cached". - * Otherwise, the state will be set to "main". + * If cross signing is set up, key backup is enabled and the secrets are cached, the state will be set to "main". + * If cross signing is not set up, the state will be set to "set_up_encryption". + * If key backup is not enabled, the state will be set to "key_storage_disabled". + * If secrets are missing, the state will be set to "secrets_not_cached". * * The state is set once when the component is first mounted. * Also returns a callback function which can be called to re-run the logic. @@ -146,8 +168,14 @@ function useCheckEncryptionState(state: State, setState: (state: State) => void) const cachedSecrets = (await crypto.getCrossSigningStatus()).privateKeysCachedLocally; const secretsOk = cachedSecrets.masterKey && cachedSecrets.selfSigningKey && cachedSecrets.userSigningKey; - if (isCrossSigningReady && secretsOk) setState("main"); + // Also check the key backup status + const activeBackupVersion = await crypto.getActiveSessionBackupVersion(); + + const keyStorageEnabled = activeBackupVersion !== null; + + if (isCrossSigningReady && keyStorageEnabled && secretsOk) setState("main"); else if (!isCrossSigningReady) setState("set_up_encryption"); + else if (!keyStorageEnabled) setState("key_storage_disabled"); else setState("secrets_not_cached"); }, [matrixClient, setState]); @@ -156,6 +184,15 @@ function useCheckEncryptionState(state: State, setState: (state: State) => void) if (state === "loading") checkEncryptionState(); }, [checkEncryptionState, state]); + useTypedEventEmitter(matrixClient, CryptoEvent.KeyBackupStatus, (): void => { + // Recheck the status if the key backup status has changed so we can keep the page up to date. + // Note that this could potentially update the UI while the user is trying to do something, although + // if their key backup status is changing then they're changing encryption related things + // on another device. This code is written with the assumption that it's better for the UI to refresh + // and be up to date with whatever changes they've made. + checkEncryptionState(); + }); + // Also return the callback so that the component can re-run the logic. return checkEncryptionState; } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 9281382715..5570279115 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2510,10 +2510,23 @@ "session_key": "Session key:", "title": "Advanced" }, + "delete_key_storage": { + "breadcrumb_page": "Delete key storage", + "confirm": "Delete key storage", + "description": "Deleting key storage will remove your cryptographic identity and message keys from the server and turn off the following security features:", + "list_first": "You will not have encrypted message history on new devices", + "list_second": "You will lose access to your encrypted messages if you are signed out of %(brand)s everywhere", + "title": "Are you sure you want to turn off key storage and delete it?" + }, "device_not_verified_button": "Verify this device", "device_not_verified_description": "You need to verify this device in order to view your encryption settings.", "device_not_verified_title": "Device not verified", "dialog_title": "Settings: Encryption", + "key_storage": { + "allow_key_storage": "Allow key storage", + "description": "Store your cryptographic identity and message keys securely on the server. This will allow you to view your message history on any new devices.
Learn more", + "title": "Key storage" + }, "recovery": { "change_recovery_confirm_button": "Confirm new recovery key", "change_recovery_confirm_description": "Enter your new recovery key below to finish. Your old one will no longer work.", diff --git a/test/test-utils/test-utils.ts b/test/test-utils/test-utils.ts index a8b53abb0e..321ff8b27e 100644 --- a/test/test-utils/test-utils.ts +++ b/test/test-utils/test-utils.ts @@ -151,9 +151,11 @@ export function createTestClient(): MatrixClient { }, }), isCrossSigningReady: jest.fn().mockResolvedValue(false), + disableKeyStorage: jest.fn(), resetEncryption: jest.fn(), getSessionBackupPrivateKey: jest.fn().mockResolvedValue(null), isSecretStorageReady: jest.fn().mockResolvedValue(false), + deleteKeyBackupVersion: jest.fn(), }), getPushActionsForEvent: jest.fn(), @@ -192,6 +194,7 @@ export function createTestClient(): MatrixClient { }), mxcUrlToHttp: jest.fn().mockImplementation((mxc: string) => `http://this.is.a.url/${mxc.substring(6)}`), setAccountData: jest.fn(), + deleteAccountData: jest.fn(), setRoomAccountData: jest.fn(), setRoomTopic: jest.fn(), setRoomReadMarkers: jest.fn().mockResolvedValue({}), diff --git a/test/unit-tests/components/viewmodels/settings/encryption/KeyStoragePanelViewModel-test.ts b/test/unit-tests/components/viewmodels/settings/encryption/KeyStoragePanelViewModel-test.ts new file mode 100644 index 0000000000..68333d0fea --- /dev/null +++ b/test/unit-tests/components/viewmodels/settings/encryption/KeyStoragePanelViewModel-test.ts @@ -0,0 +1,91 @@ +/* +Copyright 2025 New Vector 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 { renderHook } from "jest-matrix-react"; +import { act } from "react"; +import { mocked } from "jest-mock"; + +import type { MatrixClient } from "matrix-js-sdk/src/matrix"; +import type { KeyBackupCheck, KeyBackupInfo } from "matrix-js-sdk/src/crypto-api"; +import { useKeyStoragePanelViewModel } from "../../../../../../src/components/viewmodels/settings/encryption/KeyStoragePanelViewModel"; +import { createTestClient, withClientContextRenderOptions } from "../../../../../test-utils"; + +describe("KeyStoragePanelViewModel", () => { + let matrixClient: MatrixClient; + + beforeEach(() => { + matrixClient = createTestClient(); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + it("should update the pending value immediately", async () => { + const { result } = renderHook( + () => useKeyStoragePanelViewModel(), + withClientContextRenderOptions(matrixClient), + ); + act(() => { + result.current.setEnabled(true); + }); + expect(result.current.isEnabled).toBe(true); + expect(result.current.busy).toBe(true); + }); + + it("should call resetKeyBackup if there is no backup currently", async () => { + mocked(matrixClient.getCrypto()!.checkKeyBackupAndEnable).mockResolvedValue(null); + + const { result } = renderHook( + () => useKeyStoragePanelViewModel(), + withClientContextRenderOptions(matrixClient), + ); + + await result.current.setEnabled(true); + expect(mocked(matrixClient.getCrypto()!.resetKeyBackup)).toHaveBeenCalled(); + }); + + it("should not call resetKeyBackup if there is a backup currently", async () => { + mocked(matrixClient.getCrypto()!.checkKeyBackupAndEnable).mockResolvedValue({} as KeyBackupCheck); + + const { result } = renderHook( + () => useKeyStoragePanelViewModel(), + withClientContextRenderOptions(matrixClient), + ); + + await result.current.setEnabled(true); + expect(mocked(matrixClient.getCrypto()!.resetKeyBackup)).not.toHaveBeenCalled(); + }); + + it("should set account data flag when enabling", async () => { + mocked(matrixClient.getCrypto()!.checkKeyBackupAndEnable).mockResolvedValue(null); + + const { result } = renderHook( + () => useKeyStoragePanelViewModel(), + withClientContextRenderOptions(matrixClient), + ); + + await result.current.setEnabled(true); + expect(mocked(matrixClient.setAccountData)).toHaveBeenCalledWith("m.org.matrix.custom.backup_disabled", { + disabled: false, + }); + }); + + it("should delete key storage when disabling", async () => { + mocked(matrixClient.getCrypto()!.checkKeyBackupAndEnable).mockResolvedValue({} as KeyBackupCheck); + mocked(matrixClient.getCrypto()!.getKeyBackupInfo).mockResolvedValue({ version: "99" } as KeyBackupInfo); + + const { result } = renderHook( + () => useKeyStoragePanelViewModel(), + withClientContextRenderOptions(matrixClient), + ); + + await result.current.setEnabled(false); + + expect(mocked(matrixClient.getCrypto()!.disableKeyStorage)).toHaveBeenCalled(); + }); +}); diff --git a/test/unit-tests/components/views/settings/encryption/DeleteKeyStoragePanel-test.tsx b/test/unit-tests/components/views/settings/encryption/DeleteKeyStoragePanel-test.tsx new file mode 100644 index 0000000000..eb9e557025 --- /dev/null +++ b/test/unit-tests/components/views/settings/encryption/DeleteKeyStoragePanel-test.tsx @@ -0,0 +1,96 @@ +/* + * Copyright 2025 New Vector 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 from "react"; +import { render, screen, waitFor } from "jest-matrix-react"; +import userEvent from "@testing-library/user-event"; +import { mocked } from "jest-mock"; +import { defer } from "matrix-js-sdk/src/utils"; + +import type { MatrixClient } from "matrix-js-sdk/src/matrix"; +import { createTestClient, withClientContextRenderOptions } from "../../../../../test-utils"; +import { DeleteKeyStoragePanel } from "../../../../../../src/components/views/settings/encryption/DeleteKeyStoragePanel"; +import { useKeyStoragePanelViewModel } from "../../../../../../src/components/viewmodels/settings/encryption/KeyStoragePanelViewModel"; + +jest.mock("../../../../../../src/components/viewmodels/settings/encryption/KeyStoragePanelViewModel", () => ({ + useKeyStoragePanelViewModel: jest + .fn() + .mockReturnValue({ setEnabled: jest.fn(), isEnabled: true, loading: false, busy: false }), +})); + +describe("", () => { + let matrixClient: MatrixClient; + + beforeEach(() => { + matrixClient = createTestClient(); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + it("should match snapshot", async () => { + const { asFragment } = render( + {}} />, + withClientContextRenderOptions(matrixClient), + ); + expect(asFragment()).toMatchSnapshot(); + }); + + it("should call onFinished when cancel pressed", async () => { + const user = userEvent.setup(); + + const onFinish = jest.fn(); + render(, withClientContextRenderOptions(matrixClient)); + + await user.click(screen.getByRole("button", { name: "Cancel" })); + expect(onFinish).toHaveBeenCalled(); + }); + + it("should call disable key storage when confirm pressed", async () => { + const setEnabled = jest.fn(); + + mocked(useKeyStoragePanelViewModel).mockReturnValue({ + setEnabled, + isEnabled: true, + loading: false, + busy: false, + }); + + const user = userEvent.setup(); + + const onFinish = jest.fn(); + render(, withClientContextRenderOptions(matrixClient)); + + await user.click(screen.getByRole("button", { name: "Delete key storage" })); + + expect(setEnabled).toHaveBeenCalledWith(false); + }); + + it("should wait with button disabled while setEnabled runs", async () => { + const setEnabledDefer = defer(); + + mocked(useKeyStoragePanelViewModel).mockReturnValue({ + setEnabled: jest.fn().mockReturnValue(setEnabledDefer.promise), + isEnabled: true, + loading: false, + busy: false, + }); + + const user = userEvent.setup(); + + const onFinish = jest.fn(); + render(, withClientContextRenderOptions(matrixClient)); + + await user.click(screen.getByRole("button", { name: "Delete key storage" })); + + expect(onFinish).not.toHaveBeenCalled(); + expect(screen.getByRole("button", { name: "Delete key storage" })).toHaveAttribute("aria-disabled", "true"); + setEnabledDefer.resolve(); + await waitFor(() => expect(onFinish).toHaveBeenCalled()); + }); +}); diff --git a/test/unit-tests/components/views/settings/encryption/__snapshots__/DeleteKeyStoragePanel-test.tsx.snap b/test/unit-tests/components/views/settings/encryption/__snapshots__/DeleteKeyStoragePanel-test.tsx.snap new file mode 100644 index 0000000000..52541c468b --- /dev/null +++ b/test/unit-tests/components/views/settings/encryption/__snapshots__/DeleteKeyStoragePanel-test.tsx.snap @@ -0,0 +1,156 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` should match snapshot 1`] = ` + + +
+
+
+ + + +
+

+ Are you sure you want to turn off key storage and delete it? +

+
+
+ Deleting key storage will remove your cryptographic identity and message keys from the server and turn off the following security features: +
    +
  • + + You will not have encrypted message history on new devices +
  • +
  • + + You will lose access to your encrypted messages if you are signed out of Element everywhere +
  • +
+
+
+ + +
+
+
+`; diff --git a/test/unit-tests/components/views/settings/tabs/user/EncryptionUserSettingsTab-test.tsx b/test/unit-tests/components/views/settings/tabs/user/EncryptionUserSettingsTab-test.tsx index 536dadf305..04b34573ac 100644 --- a/test/unit-tests/components/views/settings/tabs/user/EncryptionUserSettingsTab-test.tsx +++ b/test/unit-tests/components/views/settings/tabs/user/EncryptionUserSettingsTab-test.tsx @@ -6,10 +6,11 @@ */ import React from "react"; -import { render, screen } from "jest-matrix-react"; +import { act, render, screen } from "jest-matrix-react"; import { type MatrixClient } from "matrix-js-sdk/src/matrix"; import { waitFor } from "@testing-library/dom"; import userEvent from "@testing-library/user-event"; +import { CryptoEvent } from "matrix-js-sdk/src/crypto-api"; import { EncryptionUserSettingsTab, @@ -66,12 +67,21 @@ describe("", () => { expect(spy).toHaveBeenCalled(); }); - it("should display the recovery panel when the encryption is set up", async () => { + it("should display the recovery panel when key storage is enabled", async () => { + jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue("1"); renderComponent(); await waitFor(() => expect(screen.getByText("Recovery")).toBeInTheDocument()); }); + it("should not display the recovery panel when key storage is not enabled", async () => { + jest.spyOn(matrixClient.getCrypto()!, "getKeyBackupInfo").mockResolvedValue(null); + jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue(null); + renderComponent(); + await expect(screen.queryByText("Recovery")).not.toBeInTheDocument(); + }); + it("should display the recovery out of sync panel when secrets are not cached", async () => { + jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue("1"); // Secrets are not cached jest.spyOn(matrixClient.getCrypto()!, "getCrossSigningStatus").mockResolvedValue({ privateKeysInSecretStorage: true, @@ -96,6 +106,7 @@ describe("", () => { }); it("should display the change recovery key panel when the user clicks on the change recovery button", async () => { + jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue("1"); const user = userEvent.setup(); const { asFragment } = renderComponent(); @@ -109,6 +120,7 @@ describe("", () => { }); it("should display the set up recovery key when the user clicks on the set up recovery key button", async () => { + jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue("1"); jest.spyOn(matrixClient.secretStorage, "getDefaultKeyId").mockResolvedValue(null); const user = userEvent.setup(); @@ -123,6 +135,8 @@ describe("", () => { }); it("should display the reset identity panel when the user clicks on the reset cryptographic identity panel", async () => { + jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue("1"); + const user = userEvent.setup(); const { asFragment } = renderComponent(); @@ -137,17 +151,41 @@ describe("", () => { expect(asFragment()).toMatchSnapshot(); }); - it("should enter reset flow when showResetIdentity is set", () => { + it("should enter reset flow when showResetIdentity is set", async () => { + jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue("1"); + renderComponent({ initialState: "reset_identity_forgot" }); - expect( - screen.getByRole("heading", { name: "Forgot your recovery key? You’ll need to reset your identity." }), + await expect( + await screen.findByRole("heading", { + name: "Forgot your recovery key? You’ll need to reset your identity.", + }), ).toBeVisible(); }); + it("should update when key backup status event is fired", async () => { + jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue("1"); + + renderComponent(); + + await expect(await screen.findByRole("heading", { name: "Recovery" })).toBeVisible(); + + jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue(null); + + act(() => { + matrixClient.emit(CryptoEvent.KeyBackupStatus, false); + }); + + await waitFor(() => { + expect(screen.queryByRole("heading", { name: "Recovery" })).toBeNull(); + }); + }); + it("should re-check the encryption state and displays the correct panel when the user clicks cancel the reset identity flow", async () => { const user = userEvent.setup(); + jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue("1"); + // Secrets are not cached jest.spyOn(matrixClient.getCrypto()!, "getCrossSigningStatus").mockResolvedValue({ privateKeysInSecretStorage: true, From f4b03a1b06b325fc21fadd61512632c7462919c5 Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Fri, 14 Mar 2025 15:11:04 +0530 Subject: [PATCH 078/458] Room List Store: Save preferred sorting algorithm and use that on app launch (#29493) * Add `type` property to Sorter So that we can uniquely identify any given sorting algorithm. * Add a getter for the active sort algorithm * Define a setting to store the sorting algorithm * Add a method to resort the list of rooms - Just one method where you specify the sorting algorithm by type. - Persist the new sorting algorithm using SettingsStore. * On startup, use preferred sorter * Add tests --- src/settings/Settings.tsx | 6 +++ src/stores/room-list-v3/RoomListStoreV3.ts | 49 ++++++++++++++----- .../room-list-v3/skip-list/RoomSkipList.ts | 9 +++- .../skip-list/sorters/AlphabeticSorter.ts | 6 ++- .../skip-list/sorters/RecencySorter.ts | 6 ++- .../room-list-v3/skip-list/sorters/index.ts | 23 +++++++++ .../room-list-v3/RoomListStoreV3-test.ts | 20 +++++++- 7 files changed, 101 insertions(+), 18 deletions(-) diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 439b0c112f..3046813f4d 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -44,6 +44,7 @@ import { type ReleaseAnnouncementData } from "../stores/ReleaseAnnouncementStore import { type Json, type JsonValue } from "../@types/json.ts"; import { type RecentEmojiData } from "../emojipicker/recent.ts"; import { type Assignable } from "../@types/common.ts"; +import { SortingAlgorithm } from "../stores/room-list-v3/skip-list/sorters/index.ts"; export const defaultWatchManager = new WatchManager(); @@ -311,6 +312,7 @@ export interface Settings { "lowBandwidth": IBaseSetting; "fallbackICEServerAllowed": IBaseSetting; "showImages": IBaseSetting; + "RoomList.preferredSorting": IBaseSetting; "RightPanel.phasesGlobal": IBaseSetting; "RightPanel.phases": IBaseSetting; "enableEventIndexing": IBaseSetting; @@ -1114,6 +1116,10 @@ export const SETTINGS: Settings = { displayName: _td("settings|image_thumbnails"), default: true, }, + "RoomList.preferredSorting": { + supportedLevels: [SettingLevel.DEVICE], + default: SortingAlgorithm.Recency, + }, "RightPanel.phasesGlobal": { supportedLevels: [SettingLevel.DEVICE], default: null, diff --git a/src/stores/room-list-v3/RoomListStoreV3.ts b/src/stores/room-list-v3/RoomListStoreV3.ts index 8d1bf8331f..286a5f0554 100644 --- a/src/stores/room-list-v3/RoomListStoreV3.ts +++ b/src/stores/room-list-v3/RoomListStoreV3.ts @@ -31,6 +31,8 @@ import { RoomsFilter } from "./skip-list/filters/RoomsFilter"; import { InvitesFilter } from "./skip-list/filters/InvitesFilter"; import { MentionsFilter } from "./skip-list/filters/MentionsFilter"; import { LowPriorityFilter } from "./skip-list/filters/LowPriorityFilter"; +import { type Sorter, SortingAlgorithm } from "./skip-list/sorters"; +import { SettingLevel } from "../../settings/SettingLevel"; /** * These are the filters passed to the room skip list. @@ -93,28 +95,32 @@ export class RoomListStoreV3Class extends AsyncStoreWithClient { } /** - * Re-sort the list of rooms by alphabetic order. + * Resort the list of rooms using a different algorithm. + * @param algorithm The sorting algorithm to use. */ - public useAlphabeticSorting(): void { - if (this.roomSkipList) { - const sorter = new AlphabeticSorter(); - this.roomSkipList.useNewSorter(sorter, this.getRooms()); - } + public resort(algorithm: SortingAlgorithm): void { + if (!this.roomSkipList) throw new Error("Cannot resort room list before skip list is created."); + if (!this.matrixClient) throw new Error("Cannot resort room list without matrix client."); + if (this.roomSkipList.activeSortAlgorithm === algorithm) return; + const sorter = + algorithm === SortingAlgorithm.Alphabetic + ? new AlphabeticSorter() + : new RecencySorter(this.matrixClient.getSafeUserId()); + this.roomSkipList.useNewSorter(sorter, this.getRooms()); + this.emit(LISTS_UPDATE_EVENT); + SettingsStore.setValue("RoomList.preferredSorting", null, SettingLevel.DEVICE, algorithm); } /** - * Re-sort the list of rooms by recency. + * Currently active sorting algorithm if the store is ready or undefined otherwise. */ - public useRecencySorting(): void { - if (this.roomSkipList && this.matrixClient) { - const sorter = new RecencySorter(this.matrixClient?.getSafeUserId() ?? ""); - this.roomSkipList.useNewSorter(sorter, this.getRooms()); - } + public get activeSortAlgorithm(): SortingAlgorithm | undefined { + return this.roomSkipList?.activeSortAlgorithm; } protected async onReady(): Promise { if (this.roomSkipList?.initialized || !this.matrixClient) return; - const sorter = new RecencySorter(this.matrixClient.getSafeUserId()); + const sorter = this.getPreferredSorter(this.matrixClient.getSafeUserId()); this.roomSkipList = new RoomSkipList(sorter, FILTERS); await SpaceStore.instance.storeReadyPromise; const rooms = this.getRooms(); @@ -214,6 +220,23 @@ export class RoomListStoreV3Class extends AsyncStoreWithClient { } } + /** + * Create the correct sorter depending on the persisted user preference. + * @param myUserId The user-id of our user. + * @returns Sorter object that can be passed to the skip list. + */ + private getPreferredSorter(myUserId: string): Sorter { + const preferred = SettingsStore.getValue("RoomList.preferredSorting"); + switch (preferred) { + case SortingAlgorithm.Alphabetic: + return new AlphabeticSorter(); + case SortingAlgorithm.Recency: + return new RecencySorter(myUserId); + default: + throw new Error(`Got unknown sort preference from RoomList.preferredSorting setting`); + } + } + /** * Add a room to the skiplist and emit an update. * @param room The room to add to the skiplist diff --git a/src/stores/room-list-v3/skip-list/RoomSkipList.ts b/src/stores/room-list-v3/skip-list/RoomSkipList.ts index 1653d8068d..5de15eaa46 100644 --- a/src/stores/room-list-v3/skip-list/RoomSkipList.ts +++ b/src/stores/room-list-v3/skip-list/RoomSkipList.ts @@ -6,7 +6,7 @@ Please see LICENSE files in the repository root for full details. */ import type { Room } from "matrix-js-sdk/src/matrix"; -import type { Sorter } from "./sorters"; +import type { Sorter, SortingAlgorithm } from "./sorters"; import type { Filter, FilterKey } from "./filters"; import { RoomNode } from "./RoomNode"; import { shouldPromote } from "./utils"; @@ -204,4 +204,11 @@ export class RoomSkipList implements Iterable { public get size(): number { return this.levels[0].size; } + + /** + * The currently active sorting algorithm. + */ + public get activeSortAlgorithm(): SortingAlgorithm { + return this.sorter.type; + } } diff --git a/src/stores/room-list-v3/skip-list/sorters/AlphabeticSorter.ts b/src/stores/room-list-v3/skip-list/sorters/AlphabeticSorter.ts index 5c279efb08..50a1b09d17 100644 --- a/src/stores/room-list-v3/skip-list/sorters/AlphabeticSorter.ts +++ b/src/stores/room-list-v3/skip-list/sorters/AlphabeticSorter.ts @@ -6,7 +6,7 @@ Please see LICENSE files in the repository root for full details. */ import type { Room } from "matrix-js-sdk/src/matrix"; -import type { Sorter } from "."; +import { type Sorter, SortingAlgorithm } from "."; export class AlphabeticSorter implements Sorter { private readonly collator = new Intl.Collator(); @@ -20,4 +20,8 @@ export class AlphabeticSorter implements Sorter { public comparator(roomA: Room, roomB: Room): number { return this.collator.compare(roomA.name, roomB.name); } + + public get type(): SortingAlgorithm.Alphabetic { + return SortingAlgorithm.Alphabetic; + } } diff --git a/src/stores/room-list-v3/skip-list/sorters/RecencySorter.ts b/src/stores/room-list-v3/skip-list/sorters/RecencySorter.ts index 7e8b3bd8c7..38eb9a298b 100644 --- a/src/stores/room-list-v3/skip-list/sorters/RecencySorter.ts +++ b/src/stores/room-list-v3/skip-list/sorters/RecencySorter.ts @@ -6,7 +6,7 @@ Please see LICENSE files in the repository root for full details. */ import type { Room } from "matrix-js-sdk/src/matrix"; -import type { Sorter } from "."; +import { type Sorter, SortingAlgorithm } from "."; import { getLastTs } from "../../../room-list/algorithms/tag-sorting/RecentAlgorithm"; export class RecencySorter implements Sorter { @@ -23,6 +23,10 @@ export class RecencySorter implements Sorter { return roomBLastTs - roomALastTs; } + public get type(): SortingAlgorithm.Recency { + return SortingAlgorithm.Recency; + } + private getTs(room: Room, cache?: { [roomId: string]: number }): number { const ts = cache?.[room.roomId] ?? getLastTs(room, this.myUserId); if (cache) { diff --git a/src/stores/room-list-v3/skip-list/sorters/index.ts b/src/stores/room-list-v3/skip-list/sorters/index.ts index c71553665e..40381448c8 100644 --- a/src/stores/room-list-v3/skip-list/sorters/index.ts +++ b/src/stores/room-list-v3/skip-list/sorters/index.ts @@ -8,6 +8,29 @@ Please see LICENSE files in the repository root for full details. import type { Room } from "matrix-js-sdk/src/matrix"; export interface Sorter { + /** + * Performs an initial sort of rooms and returns a new array containing + * the result. + * @param rooms An array of rooms. + */ sort(rooms: Room[]): Room[]; + /** + * The comparator used for sorting. + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#comparefn + * @param roomA Room + * @param roomB Room + */ comparator(roomA: Room, roomB: Room): number; + /** + * A string that uniquely identifies this given sorter. + */ + type: SortingAlgorithm; +} + +/** + * All the available sorting algorithms. + */ +export const enum SortingAlgorithm { + Recency = "Recency", + Alphabetic = "Alphabetic", } diff --git a/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts b/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts index ec27049c89..0fdef53729 100644 --- a/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts +++ b/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts @@ -24,6 +24,8 @@ import { DefaultTagID } from "../../../../src/stores/room-list/models"; import { FilterKey } from "../../../../src/stores/room-list-v3/skip-list/filters"; import { RoomNotificationStateStore } from "../../../../src/stores/notifications/RoomNotificationStateStore"; import DMRoomMap from "../../../../src/utils/DMRoomMap"; +import { SortingAlgorithm } from "../../../../src/stores/room-list-v3/skip-list/sorters"; +import SettingsStore from "../../../../src/settings/SettingsStore"; describe("RoomListStoreV3", () => { async function getRoomListStore() { @@ -53,6 +55,10 @@ describe("RoomListStoreV3", () => { }) as () => DMRoomMap); }); + afterEach(() => { + jest.restoreAllMocks(); + }); + it("Provides an unsorted list of rooms", async () => { const { store, rooms } = await getRoomListStore(); expect(store.getRooms()).toEqual(rooms); @@ -69,14 +75,24 @@ describe("RoomListStoreV3", () => { const { store, rooms, client } = await getRoomListStore(); // List is sorted by recency, sort by alphabetical now - store.useAlphabeticSorting(); + store.resort(SortingAlgorithm.Alphabetic); let sortedRooms = new AlphabeticSorter().sort(rooms); expect(store.getSortedRooms()).toEqual(sortedRooms); + expect(store.activeSortAlgorithm).toEqual(SortingAlgorithm.Alphabetic); // Go back to recency sorting - store.useRecencySorting(); + store.resort(SortingAlgorithm.Recency); sortedRooms = new RecencySorter(client.getSafeUserId()).sort(rooms); expect(store.getSortedRooms()).toEqual(sortedRooms); + expect(store.activeSortAlgorithm).toEqual(SortingAlgorithm.Recency); + }); + + it("Uses preferred sorter on startup", async () => { + jest.spyOn(SettingsStore, "getValue").mockImplementation(() => { + return SortingAlgorithm.Alphabetic; + }); + const { store } = await getRoomListStore(); + expect(store.activeSortAlgorithm).toEqual(SortingAlgorithm.Alphabetic); }); describe("Updates", () => { From f9a0bb290493aa2f188f107c1459644107be37fa Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 14 Mar 2025 10:06:44 +0000 Subject: [PATCH 079/458] Add analytics constant to encryption tab (#29489) As it got stuck in review for 5 months and we all forgot about it --- package.json | 2 +- src/components/views/dialogs/UserSettingsDialog.tsx | 1 + yarn.lock | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 974be1666e..acfeff4c48 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "@fontsource/inconsolata": "^5", "@fontsource/inter": "^5", "@formatjs/intl-segmenter": "^11.5.7", - "@matrix-org/analytics-events": "^0.29.0", + "@matrix-org/analytics-events": "^0.29.2", "@matrix-org/emojibase-bindings": "^1.3.4", "@matrix-org/react-sdk-module-api": "^2.4.0", "@matrix-org/spec": "^1.7.0", diff --git a/src/components/views/dialogs/UserSettingsDialog.tsx b/src/components/views/dialogs/UserSettingsDialog.tsx index a8e184f083..6a94ae8842 100644 --- a/src/components/views/dialogs/UserSettingsDialog.tsx +++ b/src/components/views/dialogs/UserSettingsDialog.tsx @@ -191,6 +191,7 @@ export default function UserSettingsDialog(props: IProps): JSX.Element { _td("settings|encryption|title"), , , + "UserSettingsEncryption", ), ); diff --git a/yarn.lock b/yarn.lock index 228da15928..a68136e1dc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2051,10 +2051,10 @@ rw "^1.3.3" tinyqueue "^3.0.0" -"@matrix-org/analytics-events@^0.29.0": - version "0.29.1" - resolved "https://registry.yarnpkg.com/@matrix-org/analytics-events/-/analytics-events-0.29.1.tgz#b812b932d82de1409fa47199260c9a4d4f8349e8" - integrity sha512-EyN6TMG4fCeNoQEa0uYTNnMLT4M/F3eCU/usjLDHkVgIcwevvBCHxw2379IbOm4kJBbhSW/pcNkGRKntWu0J9g== +"@matrix-org/analytics-events@^0.29.2": + version "0.29.2" + resolved "https://registry.yarnpkg.com/@matrix-org/analytics-events/-/analytics-events-0.29.2.tgz#20d9877f11d5e411f1610f396f9e490673d6da50" + integrity sha512-kpCdf6DBxgE7MbBbYr7FvahrktHHtiph3QN10I6nBAAPQ+hmR3aZHBECxjxLQ9RxvtBF9nlKK4bgy2YrNp6j3A== "@matrix-org/emojibase-bindings@^1.3.4": version "1.3.4" From 4e3daa5df59a821907f48d23591f51676b710ce9 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Fri, 14 Mar 2025 11:59:45 +0000 Subject: [PATCH 080/458] [create-pull-request] automated change (#29495) Co-authored-by: t3chguy <2403652+t3chguy@users.noreply.github.com> --- src/i18n/strings/cs.json | 10 +- src/i18n/strings/cy.json | 1050 ++++++++++++++++++----------------- src/i18n/strings/de_DE.json | 2 +- src/i18n/strings/en_EN.json | 2 +- src/i18n/strings/fr.json | 4 +- src/i18n/strings/nb_NO.json | 5 +- 6 files changed, 552 insertions(+), 521 deletions(-) diff --git a/src/i18n/strings/cs.json b/src/i18n/strings/cs.json index 762e2e1868..e65f13f3e4 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -1057,8 +1057,8 @@ "verify_reset_warning_1": "Resetování ověřovacích klíčů nelze vrátit zpět. Po jejich resetování nebudete mít přístup ke starým zašifrovaným zprávám a všem přátelům, kteří vás dříve ověřili, se zobrazí bezpečnostní varování, dokud se u nich znovu neověříte.", "verify_reset_warning_2": "Pokračujte pouze v případě, že jste si jisti, že jste ztratili všechna ostatní zařízení a klíč pro obnovení.", "verify_using_device": "Ověřit pomocí jiného zařízení", - "verify_using_key": "Ověření pomocí klíče pro obnovení", - "verify_using_key_or_phrase": "Ověření pomocí klíče pro obnovení nebo fráze", + "verify_using_key": "Ověřit pomocí klíče pro obnovení", + "verify_using_key_or_phrase": "Ověřit pomocí klíče pro obnovení nebo fráze", "waiting_for_user_accept": "Čekáme, než %(displayName)s výzvu přijme…", "waiting_other_device": "Čekáme na ověření na jiném zařízení…", "waiting_other_device_details": "Čekáme na ověření na vašem dalším zařízení, %(deviceName)s (%(deviceId)s)…", @@ -2104,6 +2104,12 @@ "failed_add_tag": "Nepodařilo se přidat štítek %(tagName)s k místnosti", "failed_remove_tag": "Nepodařilo se odstranit štítek %(tagName)s z místnosti", "failed_set_dm_tag": "Nepodařilo se nastavit značku přímé zprávy", + "filters": { + "favourite": "Oblíbené", + "people": "Lidé", + "rooms": "Místnosti", + "unread": "Nepřečtené" + }, "home_menu_label": "Možnosti domovské obrazovky", "join_public_room_label": "Připojit se k veřejné místnosti", "joining_rooms_status": { diff --git a/src/i18n/strings/cy.json b/src/i18n/strings/cy.json index d4c6089a55..24416cd947 100644 --- a/src/i18n/strings/cy.json +++ b/src/i18n/strings/cy.json @@ -1,10 +1,10 @@ { "a11y": { "emoji_picker": "Dewisydd Emoji", - "jump_first_invite": "Neidio i'r gwahoddiad cyntaf.", + "jump_first_invite": "Symud i'r gwahoddiad cyntaf.", "message_composer": "Neges cyfansoddwr", "recent_rooms": "Ystafelloedd diweddar", - "room_name": "Ystafell %(name)s", + "room_name": "Ystafell %(matere)s", "room_status_bar": "Bar statws ystafell", "seek_bar_label": "Bar chwilio sain", "unread_messages": "Negeseuon heb eu darllen.", @@ -104,7 +104,7 @@ "save": "Cadw", "search": "Chwilio", "send_report": "Anfon adroddiad", - "set_avatar": "Gosod llun proffil", + "set_avatar": "Gosod llun proffil", "share": "Rhannu", "show": "Dangos", "show_advanced": "Dangos uwch", @@ -231,8 +231,8 @@ "no_hs_url_provided": "Heb ddarparu URL gweinydd cartref", "oidc": { "error_title": "Heb allu eich mewngofnodi", - "generic_auth_error": "Aeth rhywbeth o'i le yn ystod y dilysu. Ewch i'r dudalen mewngofnodi a cheisiwch eto.", - "missing_or_invalid_stored_state": "Rydym wedi gofyn i'r porwr gofio pa weinydd cartref rydych chi'n ei ddefnyddio i'ch galluogi i fewngofnodi, ond yn anffodus mae eich porwr wedi anghofio hynny. Ewch i'r dudalen mewngofnodi a cheisiwch eto." + "generic_auth_error": "Aeth rhywbeth o'i le yn ystod y dilysu. Mynd i'r dudalen mewngofnodi a cheisiwch eto.", + "missing_or_invalid_stored_state": "Rydym wedi gofyn i'r porwr gofio pa weinydd cartref rydych chi'n ei ddefnyddio i'ch galluogi i fewngofnodi, ond yn anffodus mae eich porwr wedi anghofio hynny. Mynd i'r dudalen mewngofnodi a cheisiwch eto." }, "password_field_keep_going_prompt": "Daliwch ati…", "password_field_label": "Rhowch gyfrinair", @@ -258,7 +258,7 @@ "error_other_device_already_signed_in": "Nid oes angen i chi wneud unrhyw beth arall.", "error_other_device_already_signed_in_title": "Mae eich dyfais arall eisoes wedi mewngofnodi", "error_rate_limited": "Gormod o ymdrechion mewn amser byr. Arhoswch beth amser cyn ceisio eto.", - "error_unexpected": "Digwyddodd gwall annisgwyl. Mae'r cais i gysylltu eich dyfais arall wedi'i ganslo.", + "error_unexpected": "Digwyddodd gwall annisgwyl. Mae'r cais i gysylltu eich dyfais arall wedi'i ddiddymu.", "error_unsupported_protocol": "Nid yw'r ddyfais hon yn cefnogi mewngofnodi i'r ddyfais arall gyda chod QR.", "error_unsupported_protocol_title": "Dyfais arall ddim yn gydnaws", "error_user_cancelled": "Cafodd y mewngofnodi ei ddiddymu ar y ddyfais arall.", @@ -279,7 +279,7 @@ }, "register_action": "Creu Cyfrif", "registration": { - "continue_without_email_description": "Yn syml, os na fyddwch chi'n ychwanegu e-bost ac yn anghofio'ch cyfrinair, fe allech chi golli mynediad i'ch cyfrif yn barhaol .", + "continue_without_email_description": "Yn syml, os na fyddwch chi'n ychwanegu e-bost ac yn anghofio'ch cyfrinair, fe allech chi golli mynediad i'ch cyfrif yn barhaol.", "continue_without_email_field_label": "E-bost (dewisol)", "continue_without_email_title": "Parhau heb e-bost" }, @@ -310,25 +310,25 @@ "reset_password_email_not_found_title": "Ni ddaethpwyd o hyd i'r cyfeiriad e-bost hwn", "reset_password_title": "Ailosod eich cyfrinair", "server_picker_custom": "Gweinydd cartref arall", - "server_picker_description": "Gallwch ddefnyddio'r opsiynau gweinydd arferol i fewngofnodi i weinyddion Matrics eraill trwy nodi URL gweinydd cartref gwahanol. Mae hyn yn eich galluogi i ddefnyddio %(brand)s gyda chyfrif Matrics presennol ar weinydd cartref gwahanol.", + "server_picker_description": "Gallwch ddefnyddio'r dewisiadau gweinydd arferol i fewngofnodi i weinyddion Matrics eraill trwy nodi URL gweinydd cartref gwahanol. Mae hyn yn eich galluogi i ddefnyddio %(brand)s gyda chyfrif Matrics presennol ar weinydd cartref gwahanol.", "server_picker_description_matrix.org": "Ymunwch â miliynau am ddim ar y gweinydd cyhoeddus mwyaf", "server_picker_dialog_title": "Penderfynwch ble mae'ch cyfrif yn cael ei gynnal", "server_picker_explainer": "Defnyddiwch eich gweinydd cartref Matrix dewisol os oes gennych chi un, neu gwesteiwch un eich hun.", "server_picker_failed_validate_homeserver": "Methu dilysu'r gweinydd cartref", - "server_picker_intro": "Rydyn ni'n galw'r mannau lle gallwch chi gynnal eich cyfrif yn 'homeservers'.", + "server_picker_intro": "Rydyn ni'n galw'r gofodau lle gallwch chi gynnal eich cyfrif yn 'homeservers'.", "server_picker_invalid_url": "URL annilys", "server_picker_learn_more": "Am weinyddion cartref", "server_picker_matrix.org": "Matrix.org yw'r gweinydd cartref cyhoeddus mwyaf yn y byd, felly mae'n lle da i lawer.", "server_picker_required": "Nodwch gweinydd cartref", "server_picker_title": "Mewngofnodwch i'ch gweinydd cartref", - "server_picker_title_default": "Opsiynau Gweinydd", + "server_picker_title_default": "Dewisiadau'r Gweinydd", "server_picker_title_registration": "Cyfrif gwesteiwr ymlaen", "session_logged_out_description": "Er diogelwch, mae'r sesiwn hon wedi'i hallgofnodi. Mewngofnodwch eto.", "session_logged_out_title": "Wedi Allgofnodi", "set_email": { "description": "Bydd hyn yn caniatáu i chi ailosod eich cyfrinair a derbyn hysbysiadau.", "verification_pending_description": "Gwiriwch eich e-bost a chliciwch ar y ddolen sydd ynddo. Unwaith y gwneir hyn, cliciwch parhau.", - "verification_pending_title": "Yn Aros i Wirio" + "verification_pending_title": "Yn Yn aros i Wirio" }, "set_email_prompt": "Ydych chi am osod cyfeiriad e-bost?", "sign_in_description": "Defnyddiwch eich cyfrif i barhau.", @@ -347,13 +347,13 @@ "soft_logout_heading": "Rydych chi wedi allgofnodi", "soft_logout_intro_password": "Rhowch eich cyfrinair i fewngofnodi ac adennill mynediad i'ch cyfrif.", "soft_logout_intro_sso": "Mewngofnodwch ac adennill mynediad i'ch cyfrif.", - "soft_logout_intro_unsupported_auth": "Ni allwch fewngofnodi i'ch cyfrif. Cysylltwch â gweinyddwr eich gweinydd cartref am ragor o wybodaeth.", + "soft_logout_intro_unsupported_auth": "Allwch chi ddim fewngofnodi i'ch cyfrif. Cysylltwch â gweinyddwr eich gweinydd cartref am ragor o wybodaeth.", "soft_logout_subheading": "Clirio data personol", "soft_logout_warning": "Rhybudd: mae eich data personol (gan gynnwys allweddi amgryptio) yn dal i gael ei storio yn y sesiwn hon. Cliriwch ef os ydych wedi gorffen defnyddio'r sesiwn hon, neu eisiau mewngofnodi i gyfrif arall.", "sso": "Mewngofnod Sengl", - "sso_complete_in_browser_dialog_title": "Ewch i'ch porwr i gwblhau Mewngofnodi", - "sso_failed_missing_storage": "Rydym wedi gofyn i'r porwr gofio pa weinydd cartref rydych chi'n ei ddefnyddio i'ch galluogi i fewngofnodi, ond yn anffodus mae eich porwr wedi anghofio hynny. Ewch i'r dudalen mewngofnodi a cheisiwch eto.", - "sso_or_username_password": "%(ssoButtons)s Neu %(usernamePassword)s", + "sso_complete_in_browser_dialog_title": "Mynd i'ch porwr i gwblhau Mewngofnodi", + "sso_failed_missing_storage": "Rydym wedi gofyn i'r porwr gofio pa weinydd cartref rydych chi'n ei ddefnyddio i'ch galluogi i fewngofnodi, ond yn anffodus mae eich porwr wedi anghofio hynny. Mynd i'r dudalen mewngofnodi a cheisiwch eto.", + "sso_or_username_password": "%(ssoButtons)s Neu %(usermaterePassword)s", "sync_footer_subtitle": "Os ydych chi wedi ymuno â llawer o ystafelloedd, gallai hyn gymryd peth amser", "syncing": "Cydweddu…", "uia": { @@ -363,7 +363,7 @@ "email_resend_prompt": "Heb ei dderbyn? Ei anfon eto", "email_resent": "Ailanfonwyd!", "fallback_button": "Dechrau dilysu", - "mas_cross_signing_reset_cta": "Ewch i'ch cyfrif", + "mas_cross_signing_reset_cta": "Mynd i'ch cyfrif", "mas_cross_signing_reset_description": "Ailosodwch eich hunaniaeth trwy ddarparwr eich cyfrif ac yna dewch yn ôl a chlicio \"Ailgynnig\".", "msisdn": "Mae neges destun wedi'i hanfon at %(msisdn)s", "msisdn_token_incorrect": "Tocyn yn anghywir", @@ -394,32 +394,41 @@ "before_submitting": "Rydym yn argymell creu mater GitHub i sicrhau bod eich adroddiad yn cael ei ddarllen.", "collecting_information": "Casglu gwybodaeth fersiwn ap", "collecting_logs": "Casglu cofnodion", - "create_new_issue": "Os gwelwch yn dda crewch fater newydd ar GitHub fel y gallwn ymchwilio i'r byg hwn.", - "description": "Mae cofnodion dadfygio yn cynnwys data defnydd cymhwysiad gan gynnwys eich enw defnyddiwr, IDau neu arallenwau'r ystafelloedd yr ydych wedi ymweld â nhw, pa elfennau UI y gwnaethoch ryngweithio â nhw ddiwethaf, ac enwau defnyddwyr defnyddwyr eraill. Nid ydynt yn cynnwys negeseuon.", + "create_new_issue": "Crewch fater newydd ar GitHub fel y gallwn ymchwilio i'r byg hwn.", + "description": "Mae cofnodion dadfygio yn cynnwys data defnydd cymhwysiad gan gynnwys eich enw defnyddiwr, IDau neu arallenwau'r ystafelloedd yr ydych wedi ymweld â nhw, pa elfennau UI y gwnaethoch ryngweithio â nhw ddiwethaf, ac enwau defnyddwyr defnyddwyr eraill. Nid ydyn nhw'n cynnwys negeseuon.", "download_logs": "Llwytho logiau i lawr", "downloading_logs": "Wrthi'n llwytho logiau i lawr", "error_empty": "Dywedwch wrthym beth aeth o'i le neu, yn well, crëwch fater GitHub sy'n disgrifio'r broblem.", + "failed_download_logs": "Wedi methu llwytho i lawr logiau dadfygio: ", + "failed_send_logs_causes": { + "disallowed_app": "Gwrthodwyd eich adroddiad gwall. Nid yw'r gweinydd rageshake yn cefnogi'r rhaglen hon.", + "rejected_generic": "Gwrthodwyd eich adroddiad gwall. Gwrthododd y gweinydd rageshake gynnwys yr adroddiad oherwydd polisi.", + "rejected_recovery_key": "Gwrthodwyd eich adroddiad gwall am resymau diogelwch, gan ei fod yn cynnwys allwedd adfer.", + "rejected_version": "Gwrthodwyd eich adroddiad gwall gan fod y fersiwn rydych chi'n ei rhedeg yn rhy hen.", + "server_unknown_error": "Daeth y gweinydd rageshake ar draws gwall anhysbys ac ni allai drin yr adroddiad.", + "unknown_error": "Wedi methu ag anfon cofnodion." + }, "github_issue": "Mater GitHub", "introduction": "Os ydych chi wedi cyflwyno byg trwy GitHub, gall logiau dadfygio ein helpu i ddod o hyd i'r broblem. ", - "log_request": "Er mwyn ein helpu i atal hyn yn y dyfodol, anfonwch logiau atom .", + "log_request": "Er mwyn ein helpu i atal hyn yn y dyfodol, anfonwch logiau atom.", "logs_sent": "Logiau wedi'u hanfon", "matrix_security_issue": "I roi gwybod am fater diogelwch yn ymwneud â Matrix, darllenwch y Polisi Datgelu Diogelwch Matrix.org .", - "preparing_download": "Paratoi i lawrlwytho logiau", + "preparing_download": "Paratoi i lwytho logiau i lawr", "preparing_logs": "Paratoi i anfon logiau", "send_logs": "Anfon logiau", "submit_debug_logs": "Cyflwynwch gofnodion dadfygio", "textarea_label": "Nodiadau", "thank_you": "Diolch!", - "title": "Adrodd namau", + "title": "Adrodd gwallau", "unsupported_browser": "Nodyn atgoffa: Nid yw eich porwr yn cael ei gefnogi, felly mae'n bosibl y bydd eich profiad yn anrhagweladwy.", - "uploading_logs": "Wrthi'n uwchlwytho logiau", - "waiting_for_server": "Aros am ymateb gan y gweinydd" + "uploading_logs": "Wrthi'n lwytho logiau i fyny", + "waiting_for_server": "Yn aros am ymateb gan y gweinydd" }, "cannot_invite_without_identity_server": "Methu gwahodd defnyddiwr trwy e-bost heb weinydd adnabod. Gallwch gysylltu ag un o dan \"Gosodiadau\".", "cannot_reach_homeserver": "Methu cyrraedd homeserver", "cannot_reach_homeserver_detail": "Sicrhewch fod gennych gysylltiad rhyngrwyd sefydlog, neu cysylltwch â gweinyddwr y gweinydd", "cant_load_page": "Methu llwytho'r dudalen", - "chat_card_back_action_label": "Yn ôl i sgwrsio", + "chat_card_back_action_label": "Nôl i sgwrsio", "chat_effects": { "confetti_description": "Yn anfon y neges a roddwyd gyda conffeti", "confetti_message": "yn anfon conffeti", @@ -427,9 +436,9 @@ "fireworks_message": "yn anfon tân gwyllt", "hearts_description": "Yn anfon y neges a roddwyd gyda chalonnau", "hearts_message": "yn anfon calonnau", - "rainfall_description": "Yn anfon y neges a roddir gyda glawiad", + "rainfall_description": "Yn anfon y neges a roddir gyda glaw", "rainfall_message": "yn anfon glaw", - "snowfall_description": "Yn anfon y neges a roddwyd gyda chwymp eira", + "snowfall_description": "Yn anfon y neges a roddwyd gydag eira", "snowfall_message": "yn anfon eira", "spaceinvaders_description": "Yn anfon y neges a roddwyd gydag effaith ar thema gofod", "spaceinvaders_message": "yn anfon goresgynwyr gofod" @@ -468,9 +477,9 @@ "favourites": "Ffefrynnau", "feedback": "Adborth", "filter_results": "Hidlo canlyniadau", - "forward_message": "Neges ymlaen", + "forward_message": "Anfonwyd neges ymlaen", "general": "Cyffredinol", - "go_to_settings": "Cer i'r Gosodiadau", + "go_to_settings": "Mynd i'r Gosodiadau", "guest": "Gwestai", "help": "Cymorth", "historical": "Hanesyddol", @@ -521,7 +530,7 @@ "reactions": "Adweithiau", "recommended": "Argymhellwyd", "report_a_bug": "Adrodd byg", - "room": "Stafell", + "room": "Ystafell", "room_name": "Enw'r ystafell", "rooms": "Ystafelloedd", "save": "Cadw", @@ -531,13 +540,13 @@ "select_all": "Dewis y cyfan", "server": "Gweinydd", "settings": "Gosodiadau", - "setup_secure_messages": "Gosod Negeseuon Diogel", + "setup_secure_messages": "Gosod Negeseuon Diogel", "show_more": "Dangos mwy", "someone": "Rhywun", "space": "Bwlch", "spaces": "Bylchau", "sticker": "Sticer", - "stickerpack": "Pecyn sticer", + "stickerpack": "Pecyn sticeri", "success": "Llwyddiant", "suggestions": "Awgrymiadau", "support": "Cymorth", @@ -637,9 +646,9 @@ "join_rule_invite_label": "Dim ond pobl a wahoddwyd fydd yn gallu dod o hyd i'r ystafell hon ac ymuno â hi.", "join_rule_knock_label": "Gall unrhyw un wneud cais i ymuno, ond mae angen i weinyddwyr neu gymedrolwyr ganiatáu mynediad. Gallwch newid hyn yn nes ymlaen.", "join_rule_public_label": "Bydd unrhyw un yn gallu dod o hyd i'r ystafell hon ac ymuno â hi.", - "join_rule_public_parent_space_label": "Bydd unrhyw un yn gallu dod o hyd i'r ystafell hon ac ymuno â hi, nid dim ond aelodau o .", + "join_rule_public_parent_space_label": "Bydd unrhyw un yn gallu dod o hyd i'r ystafell hon ac ymuno â hi, nid dim ond aelodau o.", "join_rule_restricted": "Yn weladwy i aelodau'r gofod", - "join_rule_restricted_label": "Pawb i mewn yn gallu dod o hyd i'r ystafell hon ac ymuno â hi.", + "join_rule_restricted_label": "Bydd pawb yn yn gallu dod o hyd i'r ystafell hon ac ymuno â hi.", "name_validation_required": "Rhowch enw ar gyfer yr ystafell", "room_visibility_label": "Gwelededd ystafell", "title_private_room": "Creu ystafell breifat", @@ -648,20 +657,20 @@ "topic_label": "Pwnc (dewisol)", "unfederated": "Rhwystro unrhyw un nad yw'n rhan o %(serverName)s rhag ymuno â'r ystafell hon byth.", "unfederated_label_default_off": "Efallai y byddwch yn galluogi hyn os mai dim ond ar gyfer cydweithio â thimau mewnol ar eich gweinydd cartref y bydd yr ystafell yn cael ei defnyddio. Nid oes modd newid hyn yn ddiweddarach.", - "unfederated_label_default_on": "Efallai y byddwch yn analluogi hyn os bydd yr ystafell yn cael ei defnyddio ar gyfer cydweithio â thimau allanol sydd â'u gweinydd cartref eu hunain. Ni ellir newid hyn yn ddiweddarach.", + "unfederated_label_default_on": "Efallai y byddwch yn analluogi hyn os bydd yr ystafell yn cael ei defnyddio ar gyfer cydweithio â thimau allanol sydd â'u gweinydd cartref eu hunain. Nid oes modd newid hyn yn ddiweddarach.", "unsupported_version": "Nid yw'r gweinydd yn cefnogi'r fersiwn ystafell a nodwyd." }, "create_space": { "add_details_prompt": "Ychwanegwch rai manylion i helpu pobl i'w adnabod.", - "add_details_prompt_2": "Gallwch newid y rhain unrhyw bryd.", + "add_details_prompt_2": "Gallwch newid y rhain ar unrhyw bryd.", "add_existing_rooms_description": "Dewiswch ystafelloedd neu sgyrsiau i'w hychwanegu. Dim ond lle i chi yw hwn, ni fydd neb yn cael gwybod. Gallwch ychwanegu mwy yn ddiweddarach.", "add_existing_rooms_heading": "Beth ydych chi eisiau ei drefnu?", "address_label": "Cyfeiriad", - "address_placeholder": "e.e. fy-gofod", + "address_placeholder": "e.e. fy-ngofod", "creating": "Wrthi'n creu…", "creating_rooms": "Wrthi'n creu ystafelloedd…", - "done_action": "Ewch i'm gofod", - "done_action_first_room": "Ewch i fy ystafell gyntaf", + "done_action": "Mynd i'm gofod", + "done_action_first_room": "Mynd i fy ystafell gyntaf", "explainer": "Mae gofodau yn ffordd newydd o grwpio ystafelloedd a phobl. Pa fath o Ofod ydych chi am ei greu? Gallwch newid hyn yn nes ymlaen.", "failed_create_initial_rooms": "Wedi methu â chreu ystafelloedd gofod cychwynnol", "failed_invite_users": "Wedi methu â gwahodd y defnyddwyr canlynol i'ch gofod: %(csvUsers)s", @@ -675,11 +684,11 @@ "personal_space_description": "Man preifat i drefnu eich ystafelloedd", "private_description": "Gwahoddiad yn unig, sydd orau i chi'ch hun neu dimau", "private_heading": "Eich lle preifat", - "private_personal_description": "Sicrhewch fod gan y bobl iawn fynediad i %(name)s", + "private_personal_description": "Sicrhewch fod gan y bobl iawn fynediad i %(matere)s", "private_personal_heading": "Gyda phwy ydych chi'n gweithio?", "private_space": "Fi a fy nghyd-chwaraewyr", "private_space_description": "Man preifat i chi a'ch cyd-chwaraewyr", - "public_description": "Mannau agored i unrhyw un, gorau i gymunedau", + "public_description": "Gofodau agored i unrhyw un, gorau i gymunedau", "public_heading": "Eich gofod cyhoeddus", "search_public_button": "Chwilio am gofodau cyhoeddus", "setup_rooms_community_description": "Gadewch i ni greu ystafell ar gyfer pob un ohonyn nhw.", @@ -688,28 +697,28 @@ "setup_rooms_private_description": "Byddwn yn creu ystafelloedd ar gyfer pob un ohonyn nhw.", "setup_rooms_private_heading": "Pa brosiectau y mae eich tîm yn gweithio arnyn nhw?", "share_description": "Dim ond chi yw e ar hyn o bryd, bydd hyd yn oed yn well gydag eraill.", - "share_heading": "Rhannu %(name)s", + "share_heading": "Rhanwch %(matere)s", "skip_action": "Hepgor am nawr", "subspace_adding": "Yn ychwanegu…", "subspace_beta_notice": "Ychwanegwch le at ofod rydych chi'n ei reoli.", "subspace_dropdown_title": "Creu gofod", "subspace_existing_space_prompt": "Eisiau ychwanegu gofod presennol yn lle?", - "subspace_join_rule_invite_description": "Dim ond y bobl a wahoddir fydd yn gallu dod o hyd i'r gofod hwn ac ymuno ag ef.", + "subspace_join_rule_invite_description": "Dim ond y bobl sy'n cel gwahoddiad fydd yn gallu dod o hyd i'r gofod hwn ac ymuno ag ef.", "subspace_join_rule_invite_only": "Man preifat (gwahoddiad yn unig)", "subspace_join_rule_label": "Gwelededd gofod", - "subspace_join_rule_public_description": "Bydd unrhyw un yn gallu dod o hyd i'r gofod hwn ac ymuno ag ef, nid dim ond aelodau o .", - "subspace_join_rule_restricted_description": "Unrhyw un i mewn yn gallu dod o hyd ac ymuno." + "subspace_join_rule_public_description": "Bydd unrhyw un yn gallu dod o hyd i'r gofod hwn ac ymuno ag ef, nid dim ond aelodau o.", + "subspace_join_rule_restricted_description": "Bydd unrhyw un sydd yn yn gallu dod o hyd ac ymuno." }, "credits": { - "default_cover_photo": "Mae'r llun clawr diofyn yn © Iesu Roncero a ddefnyddir o dan delerau CC-BY-SA 4.0 .", - "twemoji": "Mae'r Twemoji celf emoji yw © Twitter, Inc a chyfranwyr eraill a ddefnyddir o dan delerau CC-BY 4.0 .", - "twemoji_colr": "Mae'r twemoji-colr ffont yw © Sefydliad Mozilla a ddefnyddir o dan delerau Apache 2.0 ." + "default_cover_photo": "Mae'r llun clawr rhagosodedig yn © Jesús Roncero sy'n cael ei ddefnyddio o dan delerauCC-BY-SA 4.0.", + "twemoji": "Mae'r celf emoji Twemoji yn © Twitter, Inc a chyfranwyr eraill sy'n cael ei ddefnyddio dan delerau CC-BY 4.0.", + "twemoji_colr": "Mae'r ffont twemoji-colr yn © Sefydliad Mozilla sy'n cael ei ddefnyddio o dan delerau Apache 2.0." }, - "desktop_default_device_name": "%(brand)s Bwrdd gwaith: %(platformName)s", + "desktop_default_device_name": "Bwrdd gwaith %(brand)s: %(platformName)s", "devtools": { "active_widgets": "Widgets Actif", "category_other": "Arall", - "category_room": "Stafell", + "category_room": "Ystafell", "caution_colon": "Rhybudd:", "client_versions": "Fersiynau Cleient", "crypto": { @@ -734,7 +743,7 @@ "cross_signing_ready": "Mae croes-arwyddo yn barod i'w ddefnyddio.", "cross_signing_status": "Statws traws-arwyddo:", "cross_signing_untrusted": "Mae gan eich cyfrif hunaniaeth traws-lofnodi mewn storfa gyfrinachol, ond nid yw'r sesiwn hon yn ymddiried ynddo eto.", - "crypto_not_available": "Nid yw modiwl cryptograffig ar gael", + "crypto_not_available": "Nid yw'r modiwl cryptograffig ar gael", "key_backup_active_version": "Fersiwn wrth gefn gweithredol:", "key_backup_active_version_none": "Dim", "key_backup_inactive_warning": "Nid yw'ch allweddi'n cael eu gwneud wrth gefn o'r sesiwn hon.", @@ -745,10 +754,10 @@ "not_found_locally": "heb ei ganfod yn lleol", "secret_storage_not_ready": "ddim yn barod", "secret_storage_ready": "barod", - "secret_storage_status": "Storio cyfrinachol:", - "self_signing_private_key_cached_status": "Allwedd breifat hunan-arwyddo:", + "secret_storage_status": "Storfa cyfrinachol:", + "self_signing_private_key_cached_status": "Allwedd breifat hunan-lofnodi:", "title": "Amgryptio o ben i ben", - "user_signing_private_key_cached_status": "Defnyddiwr yn arwyddo allwedd breifat:" + "user_signing_private_key_cached_status": "Allwedd breifat llofnodi'r defnyddiwr:" }, "developer_mode": "Modd datblygwr", "developer_tools": "Offer Datblygwr", @@ -773,7 +782,7 @@ "low_bandwidth_mode_description": "Angen gweinydd cartref cydnaws.", "main_timeline": "Prif linell amser", "no_receipt_found": "Heb ganfod derbynneb", - "notification_state": "Cyflwr hysbysu yw %(notificationState)s", + "notification_state": "Y cyflwr hysbysu yw %(notificationState)s", "notifications_debug": "Dadfygio hysbysiadau", "number_of_users": "Nifer y defnyddwyr", "original_event_source": "Ffynhonnell wreiddiol y digwyddiad", @@ -799,12 +808,12 @@ "settable_global": "Settable yn fyd-eang", "settable_room": "Gosodadwy yn yr ystafell", "setting_colon": "Gosodiad:", - "setting_definition": "Gosod diffiniad:", - "setting_id": "Gosod ID", + "setting_definition": "Gosod diffiniad:", + "setting_id": "Gosod ID", "settings_explorer": "Archwiliwr gosodiadau", "show_hidden_events": "Dangos digwyddiadau cudd yn y llinell amser", - "state_key": "Allwedd y Wladwriaeth", - "thread_root_id": "ID Root Thread: %(threadRootId)s", + "state_key": "Allwedd Cyflwr", + "thread_root_id": "ID Edau Gwraidd: %(threadRootId)s", "threads_timeline": "Llinell amser edafedd", "title": "Offer datblygwr", "toggle_event": "toglo digwyddiad", @@ -825,10 +834,10 @@ "view_servers_in_room": "Gweld gweinyddion yn yr ystafell", "view_source_decrypted_event_source": "Ffynhonnell digwyddiad wedi'i dadgryptio", "view_source_decrypted_event_source_unavailable": "Nid yw ffynhonnell wedi'i dadgryptio ar gael", - "widget_screenshots": "Galluogi sgrinluniau teclyn ar widgets a gefnogir" + "widget_screenshots": "Galluogi lluniau sgrin teclyn ar declynau syn cael eu cefnogi" }, "dialog_close_label": "Cau'r ddeialog", - "download_completed": "Lawrlwytho Wedi'i Gwblhau", + "download_completed": "Llwytho i Lawr Wedi'i Gwblhau", "emoji": { "categories": "Categorïau", "category_activities": "Gweithgareddau", @@ -843,38 +852,38 @@ "quick_reactions": "Ymatebion Cyflym" }, "emoji_picker": { - "cancel_search_label": "Canslo'r chwiliad" + "cancel_search_label": "Cau'r chwilio" }, "empty_room": "Ystafell wag", "empty_room_was_name": "Ystafell wag (roedd yn %(oldName)s)", "encryption": { "access_secret_storage_dialog": { - "enter_phrase_or_key_prompt": "Rhowch eich Ymadrodd Diogelwch neu i barhau.", + "enter_phrase_or_key_prompt": "Rhowch eich Ymadrodd Diogelwch neu i barhau.", "key_validation_text": { - "invalid_security_key": "Allwedd ddiogelwch annilys", + "invalid_security_key": "Allwedd Adfer Annilys", "recovery_key_is_correct": "Edrych yn dda!", "wrong_file_type": "Math anghywir o ffeil", - "wrong_security_key": "Allwedd Ddiogelwch Anghywir" + "wrong_security_key": "Allwedd Adfer Anghywir" }, "reset_title": "Ailosod popeth", - "reset_warning_1": "Gwnewch hyn dim ond os nad oes gennych unrhyw ddyfais arall i gwblhau'r dilysu gyda hi.", + "reset_warning_1": "Gwnewch hyn dim ond os nad oes gennych unrhyw ddyfais arall gyda chi i gwblhau'r dilysu.", "reset_warning_2": "Os byddwch yn ailosod popeth, byddwch yn ailgychwyn heb unrhyw sesiynau dibynadwy, dim defnyddwyr dibynadwy, ac efallai na fyddwch yn gallu gweld negeseuon blaenorol.", "restoring": "Adfer allweddi o'r copi wrth gefn", - "security_key_title": "Allwedd Ddiogelwch", + "security_key_title": "Allwedd Adfer", "security_phrase_incorrect_error": "Methu cyrchu storfa gyfrinachol. Gwiriwch eich bod wedi rhoi'r Ymadrodd Diogelwch cywir.", "security_phrase_title": "Ymadrodd Diogelwch", "separator": "%(securityKey)s neu %(recoveryFile)s", - "use_security_key_prompt": "Defnyddiwch eich Allwedd Ddiogelwch i barhau." + "use_security_key_prompt": "Defnyddiwch eich Allwedd Adfer i barhau." }, - "bootstrap_title": "Gosod allweddi", - "cancel_entering_passphrase_description": "Ydych chi'n siŵr eich bod am ganslo ymadrodd cyfrinair?", - "cancel_entering_passphrase_title": "Canslo mynd i mewn i gyfrinair?", - "confirm_encryption_setup_body": "Cliciwch y botwm isod i gadarnhau sefydlu amgryptio.", + "bootstrap_title": "Gosod allweddi", + "cancel_entering_passphrase_description": "Ydych chi'n siŵr eich bod am ddiddymu'r cyfrinymadrodd?", + "cancel_entering_passphrase_title": "Diddymu cyflwyno cyfrinymadrodd?", + "confirm_encryption_setup_body": "Clicio'r botwm isod i gadarnhau gosod amgryptio.", "confirm_encryption_setup_title": "Cadarnhau gosodiad amgryptio", "cross_signing_not_ready": "Nid yw traws-arwyddo wedi'i osod.", "cross_signing_ready": "Mae croes-arwyddo yn barod i'w ddefnyddio.", "cross_signing_ready_no_backup": "Mae traws-arwyddo yn barod ond nid oes copïau wrth gefn o'r allweddi.", - "cross_signing_room_normal": "Mae'r ystafell hon wedi'i hamgryptio o un pen i'r llall", + "cross_signing_room_normal": "Mae'r ystafell hon wedi'i hamgryptio o ben-i-ben", "cross_signing_room_verified": "Mae pawb yn yr ystafell hon wedi'u gwirio", "cross_signing_room_warning": "Mae rhywun yn defnyddio sesiwn anhysbys", "cross_signing_unsupported": "Nid yw eich gweinydd cartref yn cefnogi croeslofnodi.", @@ -888,22 +897,22 @@ "warning": "Mae dileu allweddi traws-arwyddo yn barhaol. Bydd unrhyw un yr ydych wedi gwirio gyda nhw yn gweld rhybuddion diogelwch. Mae bron yn sicr nad ydych am wneud hyn, oni bai eich bod wedi colli pob dyfais y gallwch groes-arwyddo ohoni." }, "enter_recovery_key": "Rhowch allwedd adfer", - "event_shield_reason_authenticity_not_guaranteed": "Ni ellir gwarantu dilysrwydd y neges hon sydd wedi'i hamgryptio ar y ddyfais hon.", + "event_shield_reason_authenticity_not_guaranteed": "Nid oes modd gwarantu dilysrwydd y neges hon sydd wedi'i hamgryptio ar y ddyfais hon.", "event_shield_reason_mismatched_sender_key": "Wedi'i amgryptio gan sesiwn heb ei wirio", "event_shield_reason_unknown_device": "Wedi'i amgryptio gan ddyfais anhysbys neu wedi'i dileu.", "event_shield_reason_unsigned_device": "Wedi'i amgryptio gan ddyfais nad yw wedi'i dilysu gan ei pherchennog.", "event_shield_reason_unverified_identity": "Wedi'i amgryptio gan ddefnyddiwr heb ei wirio.", "export_unsupported": "Nid yw eich porwr yn cynnal yr estyniadau cryptograffeg gofynnol", - "forgot_recovery_key": "Wedi anghofio allwedd adfer?", + "forgot_recovery_key": "Wedi anghofio'ch allwedd adfer?", "import_invalid_keyfile": "Ddim yn ffeil bysell %(brand)s ddilys", "import_invalid_passphrase": "Methodd y gwiriad dilysu: cyfrinair anghywir?", - "key_storage_out_of_sync": "Mae eich storfa allweddi allan o gysoni.", + "key_storage_out_of_sync": "Nid yw eich storfa allweddi wedi'i gydweddu.", "key_storage_out_of_sync_description": "Cadarnhewch eich allwedd adfer i gynnal mynediad i'ch storfa allweddi a'ch hanes negeseuon.", "messages_not_secure": { "cause_1": "Eich gweinydd cartref", - "cause_2": "Mae'r gweinydd cartref y mae'r defnyddiwr rydych chi'n ei wirio wedi'i gysylltu ag ef", - "cause_3": "Yr eiddoch, neu gysylltiad rhyngrwyd defnyddwyr eraill", - "cause_4": "Yr eiddoch, neu sesiwn y defnyddwyr eraill", + "cause_2": "Y gweinydd cartref y mae'r defnyddiwr rydych chi'n ei wirio wedi'i gysylltu ag ef", + "cause_3": "Eich cysylltiad, neu gysylltiad rhyngrwyd defnyddwyr eraill", + "cause_4": "Eich cysylltiad neu sesiwn y defnyddwyr eraill", "heading": "Gall un o’r canlynol gael ei beryglu:", "title": "Nid yw eich negeseuon yn ddiogel" }, @@ -914,8 +923,8 @@ "warning": "Os na wnaethoch chi osod y dull adfer newydd, mae'n bosibl bod ymosodwr yn ceisio cael mynediad i'ch cyfrif. Newidiwch eich cyfrinair cyfrif a gosodwch ddull adfer newydd ar unwaith yn y Gosodiadau." }, "not_supported": "", - "pinned_identity_changed": "Mae'n ymddangos bod hunaniaeth %(displayName)s ( %(userId)s ) wedi newid. Dysgwch fwy", - "pinned_identity_changed_no_displayname": "Mae'n ymddangos bod hunaniaeth %(userId)s wedi newid. Dysgwch fwy", + "pinned_identity_changed": "Mae'n ymddangos bod hunaniaeth %(displayName)s ( %(userId)s ) wedi newid. Dysgu rhagor", + "pinned_identity_changed_no_displayname": "Mae'n ymddangos bod hunaniaeth %(userId)s wedi newid. Dysgu rhagor", "recovery_method_removed": { "description_1": "Mae'r sesiwn hon wedi canfod bod eich Ymadrodd Diogelwch a'ch allwedd ar gyfer Negeseuon Diogel wedi'u dileu.", "description_2": "Os gwnaethoch hyn yn ddamweiniol, gallwch osod Negeseuon Diogel ar y sesiwn hon a fydd yn ail-amgryptio hanes negeseuon y sesiwn hon gyda dull adfer newydd.", @@ -923,11 +932,11 @@ "warning": "Os na wnaethoch chi ddileu'r dull adfer, mae'n bosibl bod ymosodwr yn ceisio cael mynediad i'ch cyfrif. Newidiwch eich cyfrinair cyfrif a gosodwch ddull adfer newydd ar unwaith yn y Gosodiadau." }, "reset_all_button": "Wedi anghofio neu golli pob dull adfer? Ailosod y cyfan", - "set_up_recovery": "Sefydlu adferiad", + "set_up_recovery": "Gosod adfer", "set_up_recovery_later": "Nid nawr", - "set_up_recovery_toast_description": "Cynhyrchwch allwedd adfer y gellir ei defnyddio i adfer hanes eich neges wedi'i hamgryptio rhag ofn i chi golli mynediad i'ch dyfeisiau.", + "set_up_recovery_toast_description": "Cynhyrchwch allwedd adfer y mae modd ei defnyddio i adfer hanes eich neges wedi'i hamgryptio rhag ofn i chi golli mynediad i'ch dyfeisiau.", "set_up_toast_description": "Diogelu rhag colli mynediad i negeseuon a data wedi'u hamgryptio", - "set_up_toast_title": "Sefydlu Copi Wrth Gefn Diogel", + "set_up_toast_title": "Gosod Copi Wrth Gefn Diogel", "setup_secure_backup": { "explainer": "Gwnewch gopi wrth gefn o'ch allweddi cyn allgofnodi er mwyn osgoi eu colli.", "title": "Gosod" @@ -935,14 +944,14 @@ "udd": { "interactive_verification_button": "Dilyswch yn rhyngweithiol trwy emoji", "other_ask_verify_text": "Gofynnwch i'r defnyddiwr hwn wirio ei sesiwn, neu ei wirio â llaw isod.", - "other_new_session_text": "Mae %(name)s (%(userId)s) wedi mewngofnodi i sesiwn newydd heb ei wirio:", - "own_ask_verify_text": "Dilyswch eich sesiwn arall gan ddefnyddio un o'r opsiynau isod.", + "other_new_session_text": "Mae %(matere)s (%(userId)s) wedi mewngofnodi i sesiwn newydd heb ei wirio:", + "own_ask_verify_text": "Dilyswch eich sesiwn arall gan ddefnyddio un o'r dewisiadau isod.", "own_new_session_text": "Fe wnaethoch chi fewngofnodi i sesiwn newydd heb ei wirio:", "title": "Heb Ymddiried" }, "unable_to_setup_keys_error": "Methu gosod allweddi", "verification": { - "accepting": "Wrth dderbyn…", + "accepting": "Yn derbyn…", "after_new_login": { "device_verified": "Dyfais wedi'i dilysu", "reset_confirmation": "Ailosod allweddi dilysu mewn gwirionedd?", @@ -950,26 +959,26 @@ "unable_to_verify": "Methu â gwirio'r ddyfais hon", "verify_this_device": "Dilyswch y ddyfais hon" }, - "cancelled": "Rydych chi wedi canslo'r dilysiad.", - "cancelled_self": "Rydych chi wedi canslo dilysiad ar eich dyfais arall.", - "cancelled_user": "%(displayName)s dilysiad wedi'i ganslo.", + "cancelled": "Rydych chi wedi diddymu'r dilysiad.", + "cancelled_self": "Rydych chi wedi diddymu dilysiad ar eich dyfais arall.", + "cancelled_user": "%(displayName)s dilysiad wedi'i ddiddymu.", "cancelling": "Wrthi'n diddymu…", "complete_action": "Iawn", "complete_description": "Rydych chi wedi dilysu'r defnyddiwr hwn yn llwyddiannus.", "complete_title": "Gwirwyd!", "error_starting_description": "Nid oeddem yn gallu dechrau sgwrs gyda'r defnyddiwr arall.", "error_starting_title": "Gwall wrth gychwyn y dilysu", - "explainer": "Mae negeseuon diogel gyda'r defnyddiwr hwn wedi'u hamgryptio o un pen i'r llall ac ni all trydydd parti eu darllen.", - "in_person": "I fod yn ddiogel, gwnewch hyn yn bersonol neu defnyddiwch ffordd ddibynadwy o gyfathrebu.", - "incoming_sas_device_dialog_text_1": "Dilyswch y ddyfais hon i'w marcio fel un y gellir ymddiried ynddi. Mae ymddiried yn y ddyfais hon yn rhoi tawelwch meddwl ychwanegol i chi a defnyddwyr eraill wrth ddefnyddio negeseuon wedi'u hamgryptio o'r dechrau i'r diwedd.", - "incoming_sas_device_dialog_text_2": "Bydd gwirio'r ddyfais hon yn ei nodi fel un y gellir ymddiried ynddo, a bydd defnyddwyr sydd wedi gwirio gyda chi yn ymddiried yn y ddyfais hon.", - "incoming_sas_dialog_title": "Cais Dilysu Dod i Mewn", - "incoming_sas_dialog_waiting": "Aros i bartner gadarnhau…", - "incoming_sas_user_dialog_text_1": "Dilyswch y defnyddiwr hwn i'w nodi fel un y gellir ymddiried ynddo. Mae ymddiried mewn defnyddwyr yn rhoi tawelwch meddwl ychwanegol i chi wrth ddefnyddio negeseuon wedi'u hamgryptio o'r dechrau i'r diwedd.", - "incoming_sas_user_dialog_text_2": "Bydd dilysu'r defnyddiwr hwn yn nodi ei sesiwn fel un y gellir ymddiried ynddi, a hefyd yn nodi bod eich sesiwn yn ymddiried ynddo.", - "no_key_or_device": "Mae'n ymddangos nad oes gennych Allwedd Ddiogelwch nac unrhyw ddyfeisiau eraill y gallwch wirio yn eu herbyn. Ni fydd y ddyfais hon yn gallu cyrchu hen negeseuon wedi'u hamgryptio. Er mwyn gwirio pwy ydych ar y ddyfais hon, bydd angen i chi ailosod eich allweddi dilysu.", + "explainer": "Mae negeseuon diogel gyda'r defnyddiwr hwn wedi'u hamgryptio pen-i-ben ac ni all trydydd parti eu darllen.", + "in_person": "I fod yn ddiogel, gwnewch hyn eich hun neu defnyddiwch ffordd ddibynadwy o gyfathrebu.", + "incoming_sas_device_dialog_text_1": "Dilyswch y ddyfais hon i'w marcio fel un y mae modd ymddiried ynddi. Mae ymddiried yn y ddyfais hon yn rhoi tawelwch meddwl ychwanegol i chi a defnyddwyr eraill wrth ddefnyddio negeseuon wedi'u hamgryptio o'r dechrau i'r diwedd.", + "incoming_sas_device_dialog_text_2": "Bydd gwirio'r ddyfais hon yn ei nodi fel un y mae modd ymddiried ynddo, a bydd defnyddwyr sydd wedi gwirio gyda chi yn ymddiried yn y ddyfais hon.", + "incoming_sas_dialog_title": "Cais Dilysu Derbyn", + "incoming_sas_dialog_waiting": "Yn aros i bartner gadarnhau…", + "incoming_sas_user_dialog_text_1": "Dilyswch y defnyddiwr hwn i'w nodi fel un y mae modd ymddiried ynddo. Mae ymddiried mewn defnyddwyr yn rhoi tawelwch meddwl ychwanegol i chi wrth ddefnyddio negeseuon wedi'u hamgryptio o'r dechrau i'r diwedd.", + "incoming_sas_user_dialog_text_2": "Bydd dilysu'r defnyddiwr hwn yn nodi ei sesiwn fel un y mae modd ymddiried ynddi, a hefyd yn nodi bod eich sesiwn yn ymddiried ynddo.", + "no_key_or_device": "Mae'n ymddangos nad oes gennych Allwedd Adfer nac unrhyw ddyfeisiau eraill y gallwch wirio yn eu herbyn. Ni fydd y ddyfais hon yn gallu cyrchu hen negeseuon wedi'u hamgryptio. Er mwyn gwirio pwy ydych ar y ddyfais hon, bydd angen i chi ailosod eich allweddi dilysu.", "no_support_qr_emoji": "Nid yw'r ddyfais rydych chi'n ceisio'i dilysu yn cefnogi sganio cod QR na dilysiad emoji, sef yr hyn y mae %(brand)s yn ei gefnogi. Ceisiwch gyda chleient gwahanol.", - "other_party_cancelled": "Mae'r parti arall wedi canslo'r dilysiad.", + "other_party_cancelled": "Mae'r parti arall wedi diddymu'r dilysiad.", "prompt_encrypted": "Gwiriwch yr holl ddefnyddwyr mewn ystafell i sicrhau ei bod yn ddiogel.", "prompt_self": "Dechreuwch ddilysu eto o'r hysbysiad.", "prompt_unencrypted": "Mewn ystafelloedd wedi'u hamgryptio, gwiriwch bob defnyddiwr i sicrhau ei fod yn ddiogel.", @@ -982,16 +991,16 @@ "request_toast_accept": "Dilysu Sesiwn", "request_toast_accept_user": "Dilysu Defnyddiwr", "request_toast_decline_counter": "Anwybyddu (%(counter)s)", - "request_toast_detail": "%(deviceId)s gan %(ip)s", - "reset_proceed_prompt": "Ewch ymlaen i ailosod", + "request_toast_detail": "%(deviceId)s oddi wrth %(ip)s", + "reset_proceed_prompt": "Mynd ymlaen i ailosod", "sas_caption_self": "Dilyswch y ddyfais hon trwy gadarnhau bod y rhif canlynol yn ymddangos ar ei sgrin.", "sas_caption_user": "Dilyswch y defnyddiwr hwn trwy gadarnhau bod y rhif canlynol yn ymddangos ar eu sgrin.", "sas_description": "Cymharwch set unigryw o emoji os nad oes gennych gamera ar y naill ddyfais na'r llall", "sas_emoji_caption_self": "Cadarnhewch fod yr emoji isod yn cael eu harddangos ar y ddwy ddyfais, yn yr un drefn:", "sas_emoji_caption_user": "Dilyswch y defnyddiwr hwn trwy gadarnhau bod yr emoji canlynol yn ymddangos ar eu sgrin.", - "sas_match": "Maent yn cyfateb", - "sas_no_match": "Nid ydynt yn cyfateb", - "sas_prompt": "Cymharwch emoji unigryw", + "sas_match": "Maen nhw'n cyfateb", + "sas_no_match": "D'yn nhw ddim yn cyfateb", + "sas_prompt": "Cymharu emoji unigryw", "scan_qr": "Gwirio trwy sganio", "scan_qr_explainer": "Gofynnwch i %(displayName)s sganio'ch cod:", "self_verification_hint": "I symud ymlaen, derbyniwch y cais dilysu ar eich dyfais arall.", @@ -1001,7 +1010,7 @@ "successful_user": "Rydych chi wedi dilysu %(displayName)s yn llwyddiannus!", "timed_out": "Daeth y cyfnod dilysu i ben.", "unsupported_method": "Methu dod o hyd i ddull dilysu a gefnogir.", - "unverified_session_toast_accept": "Ie, fi oedd e", + "unverified_session_toast_accept": "Ie, fi wnaeth", "unverified_session_toast_title": "Mewngofnod newydd. Ai chi oedd hwn?", "unverified_sessions_toast_description": "Adolygwch i sicrhau bod eich cyfrif yn ddiogel", "unverified_sessions_toast_reject": "Yn hwyrach", @@ -1010,54 +1019,54 @@ "verification_dialog_title_device": "Dilysu dyfais arall", "verification_dialog_title_user": "Cais Dilysu", "verification_skip_warning": "Heb ddilysu, ni fydd gennych fynediad i'ch holl negeseuon a gallech ymddangos fel rhai nad ydych yn ymddiried ynddynt i eraill.", - "verification_success_with_backup": "Mae eich dyfais newydd bellach wedi'i dilysu. Mae ganddo fynediad i'ch negeseuon wedi'u hamgryptio, a bydd defnyddwyr eraill yn ei ystyried yn rhai y gellir ymddiried ynddynt.", - "verification_success_without_backup": "Mae eich dyfais newydd bellach wedi'i dilysu. Bydd defnyddwyr eraill yn ei weld fel rhywbeth y gellir ymddiried ynddo.", + "verification_success_with_backup": "Mae eich dyfais newydd bellach wedi'i dilysu. Mae ganddo fynediad i'ch negeseuon wedi'u hamgryptio, a bydd defnyddwyr eraill yn ei ystyried yn rhai y mae modd ymddiried ynddynt.", + "verification_success_without_backup": "Mae eich dyfais newydd bellach wedi'i dilysu. Bydd defnyddwyr eraill yn gweld fod modd ymddiried ynddo.", "verify_emoji": "Gwirio trwy emoji", "verify_emoji_prompt": "Gwiriwch trwy gymharu emoji unigryw.", "verify_emoji_prompt_qr": "Os na allwch sganio'r cod uchod, gwiriwch trwy gymharu emoji unigryw.", "verify_later": "Byddaf yn gwirio yn ddiweddarach", "verify_reset_warning_1": "Nid oes modd dadwneud ailosod eich allweddi dilysu. Ar ôl ailosod, ni fydd gennych fynediad i hen negeseuon wedi'u hamgryptio, a bydd unrhyw ffrindiau sydd wedi'ch dilysu o'r blaen yn gweld rhybuddion diogelwch nes i chi ail-ddilysu gyda nhw.", - "verify_reset_warning_2": "Ewch ymlaen dim ond os ydych yn siŵr eich bod wedi colli eich holl ddyfeisiau eraill a'ch Allwedd Ddiogelwch.", + "verify_reset_warning_2": "Mynd ymlaen dim ond os ydych yn siŵr eich bod wedi colli eich holl ddyfeisiau eraill a'ch Allwedd Adfer.", "verify_using_device": "Gwiriwch gyda dyfais arall", - "verify_using_key": "Dilyswch gydag Allwedd Ddiogelwch", - "verify_using_key_or_phrase": "Dilyswch gydag Allwedd Ddiogelwch neu Ymadrodd", - "waiting_for_user_accept": "Aros i %(displayName)s dderbyn…", - "waiting_other_device": "Aros i chi wirio ar eich dyfais arall…", + "verify_using_key": "Dilyswch gydag Allwedd Adfer", + "verify_using_key_or_phrase": "Dilyswch gydag Allwedd Adfer neu Ymadrodd", + "waiting_for_user_accept": "Yn aros i %(displayName)s dderbyn…", + "waiting_other_device": "Yn aros i chi wirio ar eich dyfais arall…", "waiting_other_device_details": "Yn aros i chi wirio ar eich dyfais arall, %(deviceName)s (%(deviceId)s)…", - "waiting_other_user": "Aros i %(displayName)s wirio…" + "waiting_other_user": "Yn aros i %(displayName)s wirio…" }, "verification_requested_toast_title": "Gofynnwyd am ddilysiad", - "verified_identity_changed": "Mae hunaniaeth %(displayName)s ( %(userId)s ) a ddilyswyd wedi newid. Dysgwch fwy", - "verified_identity_changed_no_displayname": "Mae hunaniaeth ddilysedig %(userId)s wedi newid. Dysgwch fwy", + "verified_identity_changed": "Mae hunaniaeth %(displayName)s ( %(userId)s ) a ddilyswyd wedi newid. Dysgu rhagor", + "verified_identity_changed_no_displayname": "Mae hunaniaeth ddilysedig %(userId)s wedi newid. Dysgu rhagor", "verify_toast_description": "Efallai na fydd defnyddwyr eraill yn ymddiried ynddo", "verify_toast_title": "Gwiriwch y sesiwn hon", "withdraw_verification_action": "Tynnu'r dilysiad yn ôl" }, "error": { - "admin_contact": "Cysylltwch â gweinyddwr eich gwasanaeth i barhau i ddefnyddio'r gwasanaeth hwn.", - "admin_contact_short": "Cysylltwch â gweinyddwr eich gweinydd .", - "app_launch_unexpected_error": "Gwall annisgwyl wrth baratoi'r ap. Gweler y consol am fanylion.", + "admin_contact": "Cysylltwch â gweinyddwr eich gwasanaeth i barhau i ddefnyddio'r gwasanaeth hwn.", + "admin_contact_short": "Cysylltwch â gweinyddwr eich gweinydd.", + "app_launch_unexpected_error": "Gwall annisgwyl wrth baratoi'r ap. Gwelwch y consol am fanylion.", "cannot_load_config": "Methu llwytho ffeil ffurfweddu: adnewyddwch y dudalen i geisio eto.", "connection": "Roedd problem wrth gyfathrebu gyda'r gweinydd cartref, ceisiwch eto yn nes ymlaen.", "dialog_description_default": "Digwyddodd gwall.", - "download_media": "Wedi methu lawrlwytho cyfryngau ffynhonnell, ni ddaethpwyd o hyd i url ffynhonnell", + "download_media": "Wedi methu llwytho i lawrcyfryngau ffynhonnell, heb ddod o hyd i url ffynhonnell", "edit_history_unsupported": "Nid yw'n ymddangos bod eich gweinydd cartref yn cefnogi'r nodwedd hon.", "failed_copy": "Wedi methu â chopïo", "hs_blocked": "Mae'r gweinydd cartref hwn wedi'i rwystro gan ei weinyddwr.", - "invalid_configuration_mixed_server": "Ffurfweddiad annilys: ni ellir pennu default_hs_url ynghyd â default_server_name neu default_server_config", - "invalid_configuration_no_server": "Ffurfweddiad annilys: ni phenodwyd gweinydd rhagosodedig.", + "invalid_configuration_mixed_server": "Ffurfweddiad annilys: nid oes modd pennu default_hs_url ynghyd â default_server_matere neu default_server_config", + "invalid_configuration_no_server": "Ffurfweddiad annilys: heb benodi gweinydd rhagosodedig.", "invalid_json": "Mae eich ffurfweddiad Elfen yn cynnwys JSON annilys. Cywirwch y broblem ac ail-lwythwch y dudalen.", - "invalid_json_detail": "Y neges o'r parser yw: %(message)s", + "invalid_json_detail": "Y neges o'r didolydd yw: %(message)s", "invalid_json_generic": "JSON annilys", - "mau": "Mae'r gweinydd cartref hwn wedi cyrraedd ei derfyn Defnyddiwr Gweithredol Misol.", - "misconfigured": "Mae eich Elfen wedi'i chamgyflunio", - "mixed_content": "Methu cysylltu â homeserver trwy HTTP pan fydd URL HTTPS ym mar eich porwr. Naill ai defnyddiwch HTTPS neu galluogwch sgriptiau anniogel .", - "non_urgent_echo_failure_toast": "Nid yw eich gweinydd yn ymateb i rai ceisiadau .", + "mau": "Mae'r gweinydd cartref hwn wedi cyrraedd terfyn Defnyddiwr Gweithredol Misol.", + "misconfigured": "Mae eich Elfen wedi'i cham ffurfweddu", + "mixed_content": "Methu cysylltu â homeserver trwy HTTP pan fydd URL HTTPS ym mar eich porwr. Naill ai defnyddiwch HTTPS neu galluogwch sgriptiau anniogel.", + "non_urgent_echo_failure_toast": "Nid yw eich gweinydd yn ymateb i rai ceisiadau.", "resource_limits": "Mae'r gweinydd cartref hwn wedi mynd y tu hwnt i un o'i derfynau adnoddau.", "session_restore": { "clear_storage_button": "Clirio Storio ac Arwyddo Allan", "clear_storage_description": "Allgofnodi a dileu allweddi amgryptio?", - "description_1": "Daethom ar draws gwall wrth geisio adfer eich sesiwn flaenorol.", + "description_1": "Wedi canfod gwall wrth geisio adfer eich sesiwn flaenorol.", "description_2": "Os ydych wedi defnyddio fersiwn mwy diweddar o %(brand)s o'r blaen, mae'n bosibl y bydd eich sesiwn yn anghydnaws â'r fersiwn hon. Caewch y ffenestr hon a dychwelyd i'r fersiwn mwy diweddar.", "description_3": "Efallai y bydd clirio storfa eich porwr yn datrys y broblem, ond bydd yn eich allgofnodi ac yn achosi i unrhyw hanes sgwrsio sydd wedi'i amgryptio ddod yn annarllenadwy.", "title": "Methu adfer y sesiwn" @@ -1088,7 +1097,7 @@ "error_loading_user_profile": "Methu llwytho proffil defnyddiwr", "forget_room_failed": "Wedi methu ag anghofio ystafell %(errCode)s", "search_failed": { - "server_unavailable": "Mae'n bosib nad yw'r gweinydd ar gael, wedi ei orlwytho, neu fod y chwiliad wedi dod i ben :(", + "server_unavailable": "Mae'n bosib nad yw'r gweinydd ar gael, wedi ei orlwytho, neu fod y chwilio wedi dod i ben :(", "title": "Methodd y chwilio" } }, @@ -1105,7 +1114,7 @@ }, "m.call.invite": { "dm_receive": "Mae %(senderName)s yn galw", - "dm_send": "Aros am ateb", + "dm_send": "Yn aros am ateb", "user": "Dechreuodd %(senderName)s alwad", "you": "Rydych chi wedi dechrau galwad" }, @@ -1126,8 +1135,8 @@ "preview": "%(prefix)s: %(preview)s" }, "export_chat": { - "cancelled": "Allforio wedi'i Ganslo", - "cancelled_detail": "Cafodd yr allforyn ei ganslo'n llwyddiannus", + "cancelled": "Allforio wedi'i Ddiddymu", + "cancelled_detail": "Cafodd yr allforyn ei ddiddymu'n llwyddiannus", "confirm_stop": "Ydych chi'n siŵr eich bod am roi'r gorau i allforio eich data? Os gwnewch hynny, bydd angen i chi ddechrau o'r newydd.", "creating_html": "Wrthi'n creu HTML…", "creating_output": "Wrthi'n creu allbwn…", @@ -1135,7 +1144,7 @@ "current_timeline": "Llinell Amser Presennol", "enter_number_between_min_max": "Rhowch rif rhwng %(min)s a %(max)s", "error_fetching_file": "Gwall wrth nôl ffeil", - "export_info": "Dyma ddechrau allforio o . Wedi'i allforio gan yn %(exportDate)s.", + "export_info": "Dyma ddechrau allforio o. Wedi'i allforio gan yn %(exportDate)s.", "export_successful": "Allforio yn llwyddiannus!", "exporting_your_data": "Allforio eich data", "fetching_events": "Wrthi'n nôl digwyddiadau…", @@ -1145,25 +1154,25 @@ "generating_zip": "Cynhyrchu ZIP", "html": "HTML", "html_title": "Data wedi'i Allforio", - "include_attachments": "Cynnwysa Ymlyniadau", + "include_attachments": "Cynnwysch Atodiadau", "json": "JSON", "media_omitted": "Cyfryngau wedi'u hepgor", - "media_omitted_file_size": "Cyfryngau wedi'u hepgor - mynd dros y terfyn maint ffeil", + "media_omitted_file_size": "Cyfryngau wedi'u hepgor - wedi mynd dros y terfyn maint ffeil", "messages": "Negeseuon", "next_page": "Grŵp nesaf o negeseuon", "num_messages": "Nifer y negeseuon", - "num_messages_min_max": "Gall nifer y negeseuon fod yn rhif rhwng %(min)s a %(max)s yn unig", + "num_messages_min_max": "Gall nifer y negeseuon fod dim ond yn rhif rhwng %(min)s a %(max)s", "number_of_messages": "Nodwch nifer o negeseuon", "previous_page": "Grŵp blaenorol o negeseuon", "processing": "Wrthi'n prosesu…", "processing_event_n": "Digwyddiad prosesu %(number)s allan o %(total)s", - "select_option": "Dewiswch o'r opsiynau isod i allforio sgyrsiau o'ch llinell amser", + "select_option": "Dewiswch o'r dewisiadau isod i allforio sgyrsiau o'ch llinell amser", "size_limit": "Terfyn Maint", "size_limit_min_max": "Dim ond rhwng %(min)s MB a %(max)s MB y gall maint fod", "size_limit_postfix": "MB", "starting_export": "Yn dechrau allforio…", "successful": "Allforio yn Llwyddiannus", - "successful_detail": "Roedd eich allforyn yn llwyddiannus. Dewch o hyd iddo yn eich ffolder Lawrlwythiadau.", + "successful_detail": "Roedd eich allforyn yn llwyddiannus. Dewch o hyd iddo yn eich ffolder Llwytho i Lawr.", "text": "Testun Plaen", "title": "Allforio Sgwrs", "topic": "Pwnc: %(topic)s", @@ -1173,10 +1182,10 @@ "feedback": { "can_contact_label": "Gallwch gysylltu â mi os oes gennych unrhyw gwestiynau dilynol", "comment_label": "Sylw", - "existing_issue_link": "Gweld os gwelwch yn dda chwilod presennol ar Github yn gyntaf. Dim cyfatebiaeth? Dechreuwch un newydd .", - "may_contact_label": "Gallwch gysylltu â mi os ydych am ddilyn i fyny neu i adael i mi brofi syniadau sydd ar ddod", + "existing_issue_link": "Edrychwch ar y materion presennol ar Github yn gyntaf. Dim cyfatebiaeth? Dechreuwch un newydd.", + "may_contact_label": "Gallwch gysylltu â mi os ydych am ddilyn neu i adael i mi brofi syniadau'r dyfodol", "platform_username": "Bydd eich platfform a'ch enw defnyddiwr yn cael eu nodi i'n helpu ni i ddefnyddio'ch adborth cymaint ag y gallwn.", - "pro_type": "AWGRYM PRO: Os byddwch chi'n dechrau byg, cyflwynwch logiau dadfygio i'n helpu i ddod o hyd i'r broblem.", + "pro_type": "AWGRYM PRO: Os byddwch chi'n dechrau mater, cyflwynwchlogiau dadfygio i'n helpu i ddod o hyd i'r broblem.", "send_feedback_action": "Anfon adborth", "sent": "Anfonwyd adborth! Diolch, rydym yn ei werthfawrogi!" }, @@ -1197,48 +1206,48 @@ }, "identity_server": { "change": "Newid gweinydd hunaniaeth", - "change_prompt": "Datgysylltwch o'r gweinydd hunaniaeth a chysylltu â yn lle hynny?", - "change_server_prompt": "Os nad ydych am ddefnyddio i ddarganfod a bod yn ddarganfyddadwy gan gysylltiadau presennol yr ydych yn gwybod, rhowch weinydd hunaniaeth arall isod.", + "change_prompt": "Datgysylltwch o'r gweinydd hunaniaetha chysylltu â yn lle hynny?", + "change_server_prompt": "Os nad ydych am ddefnyddio i ganfod a bod yn ddarganfyddadwy gan gysylltiadau presennol yr ydych yn eu hadnabod, rhowch weinydd hunaniaeth arall isod.", "changed": "Mae eich gweinydd hunaniaeth wedi'i newid", "checking": "Gwirio gweinydd", - "description_connected": "Rydych chi'n defnyddio ar hyn o bryd i ddarganfod a bod yn ddarganfyddadwy gan gysylltiadau presennol rydych chi'n eu hadnabod. Gallwch newid eich gweinydd hunaniaeth isod.", + "description_connected": "Ar hyn o bryd rydych yn defnyddio i ganfod a bod yn ddarganfyddadwy gan gysylltiadau presennol rydych chi'n eu hadnabod. Gallwch newid eich gweinydd hunaniaeth isod.", "description_disconnected": "Nid ydych yn defnyddio gweinydd adnabod ar hyn o bryd. I ddarganfod a chael eich darganfod gan gysylltiadau presennol rydych chi'n eu hadnabod, ychwanegwch un isod.", "description_optional": "Mae defnyddio gweinydd hunaniaeth yn ddewisol. Os byddwch yn dewis peidio â defnyddio gweinydd hunaniaeth, ni fydd defnyddwyr eraill yn gallu eich darganfod ac ni fyddwch yn gallu gwahodd eraill trwy e-bost neu ffôn.", "disconnect": "Datgysylltu gweinydd hunaniaeth", "disconnect_anyway": "Datgysylltwch beth bynnag", - "disconnect_offline_warning": "Dylech dynnu eich data personol oddi ar weinydd hunaniaeth cyn datgysylltu. Yn anffodus, gweinydd hunaniaeth ar hyn o bryd all-lein neu ni ellir ei gyrraedd.", - "disconnect_personal_data_warning_1": "Rydych yn dal i rannu eich data personol ar y gweinydd hunaniaeth .", + "disconnect_offline_warning": "Dylech dynnu eich data personol oddi ar weinydd hunaniaeth cyn datgysylltu. Yn anffodus, gweinydd hunaniaeth ar hyn o bryd all-lein neu nid oes modd ei gyrraedd.", + "disconnect_personal_data_warning_1": "Rydych yn dal i rannu eich data personol ar y gweinydd hunaniaeth .", "disconnect_personal_data_warning_2": "Rydym yn argymell eich bod yn tynnu eich cyfeiriadau e-bost a rhifau ffôn oddi ar y gweinydd hunaniaeth cyn datgysylltu.", - "disconnect_server": "Datgysylltwch o'r gweinydd hunaniaeth ?", + "disconnect_server": "Datgysylltwch o'r gweinydd hunaniaeth ?", "disconnect_warning": "Bydd datgysylltu oddi wrth eich gweinydd hunaniaeth yn golygu na fydd defnyddwyr eraill yn gallu eich darganfod ac ni fyddwch yn gallu gwahodd eraill trwy e-bost neu ffôn.", - "do_not_use": "Peidiwch â defnyddio gweinydd adnabod", + "do_not_use": "Peidiwch â defnyddio gweinydd hunaniaeth", "error_connection": "Methu cysylltu â gweinydd hunaniaeth", - "error_invalid": "Ddim yn weinydd hunaniaeth dilys (cod statws %(code)s)", - "error_invalid_or_terms": "Ni dderbynnir telerau gwasanaeth neu mae'r gweinydd hunaniaeth yn annilys.", + "error_invalid": "Nid yw'n weinydd hunaniaeth dilys (cod statws %(code)s)", + "error_invalid_or_terms": "Nid yw'n derbyn telerau gwasanaeth neu mae'r gweinydd hunaniaeth yn annilys.", "no_terms": "Nid oes gan y gweinydd hunaniaeth rydych chi wedi'i ddewis unrhyw delerau gwasanaeth.", "suggestions": "Dylech chi:", - "suggestions_1": "gwiriwch ategion eich porwr am unrhyw beth a allai rwystro'r gweinydd hunaniaeth (fel Preifatrwydd Moch Daear)", - "suggestions_2": "cysylltwch â gweinyddwyr gweinydd hunaniaeth", + "suggestions_1": "wiro ategion eich porwr am unrhyw beth a allai rwystro'r gweinydd hunaniaeth (fel Privacy Badger)", + "suggestions_2": "cysylltu â gweinyddwyr gweinydd hunaniaeth ", "suggestions_3": "aros a cheisio eto yn nes ymlaen", "url": "Gweinydd adnabod (%(server)s)", "url_field_label": "Rhowch weinydd hunaniaeth newydd", "url_not_https": "Rhaid i URL gweinydd hunaniaeth fod yn HTTPS" }, "in_space": "Yn %(spaceName)s.", - "in_space1_and_space2": "Mewn bylchau %(space1Name)s a %(space2Name)s.", + "in_space1_and_space2": "Mewn gofodau %(space1Name)s a %(space2Name)s.", "incompatible_browser": { - "continue": "Parhewch beth bynnag", - "description": "Mae %(brand)s yn defnyddio rhai nodweddion porwr nad ydynt ar gael yn eich porwr presennol. %(detail)s", + "continue": "Parhau beth bynnag", + "description": "Mae %(brand)s yn defnyddio rhai nodweddion porwr nad ydyn nhw ar gael yn eich porwr presennol. %(detail)s", "detail_can_continue": "Os byddwch yn parhau, efallai na fydd rhai nodweddion yn gweithio ac mae risg y gallech golli data yn y dyfodol.", "detail_no_continue": "Ceisiwch ddiweddaru'r porwr hwn os nad ydych yn defnyddio'r fersiwn diweddaraf a cheisiwch eto.", "learn_more": "Dysgu rhagor", "linux": "Linux", "macos": "Mac", - "supported_browsers": "Am y profiad gorau, defnyddiwch Chrome , Firefox , Ymyl , neu saffari .", + "supported_browsers": "Am y profiad gorau, defnyddiwch Chrome, Firefox, Edge, neu Safari.", "title": "Nid yw %(brand)s yn cefnogi'r porwr hwn", - "use_desktop_heading": "Defnyddiwch %(brand)s Penbwrdd yn lle hynny", + "use_desktop_heading": "Defnyddiwch %(brand)s y Bwrdd Gwaith yn lle hynny", "use_mobile_heading": "Defnyddiwch %(brand)s ar ffôn symudol yn lle hynny", - "use_mobile_heading_after_desktop": "Neu defnyddiwch ein app symudol", + "use_mobile_heading_after_desktop": "Neu defnyddiwch ein ap symudol", "windows_64bit": "Windows (64-did)", "windows_arm_64bit": "Windows (ARM 64-did)" }, @@ -1249,6 +1258,7 @@ "error_connecting_heading": "Methu cysylltu â'r rheolwr integreiddio", "explainer": "Mae rheolwyr integreiddio yn derbyn data ffurfweddu, a gallant addasu teclynnau, anfon gwahoddiadau ystafell, a gosod lefelau pŵer ar eich rhan.", "manage_title": "Rheoli integreiddiadau", + "toggle_label": "Galluogi'r rheolwr integreiddio", "use_im": "Defnyddiwch reolwr integreiddio i reoli bots, teclynnau a phecynnau sticeri.", "use_im_default": "Defnyddiwch reolwr integreiddio (%(serverName)s) i reoli bots, teclynnau a phecynnau sticeri." }, @@ -1256,32 +1266,32 @@ "disabled_dialog_description": "Galluogi '%(manageIntegrations)s' yn y Gosodiadau i wneud hyn.", "disabled_dialog_title": "Mae integreiddiadau wedi'u hanalluogi", "impossible_dialog_description": "Nid yw eich %(brand)s yn caniatáu i chi ddefnyddio rheolwr integreiddio i wneud hyn. Cysylltwch â gweinyddwr.", - "impossible_dialog_title": "Ni chaniateir integreiddiadau" + "impossible_dialog_title": "Nid yw integreiddiadau yn cael eu caniatâu" }, "invite": { "ask_anyway_description": "Methu dod o hyd i broffiliau ar gyfer yr IDau Matrics a restrir isod - a hoffech chi ddechrau DM beth bynnag?", "ask_anyway_label": "Dechreuwch DM beth bynnag", "ask_anyway_never_warn_label": "Dechreuwch DM beth bynnag a pheidiwch byth â fy rhybuddio eto", "email_caption": "Gwahodd trwy e-bost", - "email_limit_one": "Dim ond un ar y tro y gellir anfon gwahoddiadau trwy e-bost", - "email_use_default_is": "Defnyddiwch weinydd hunaniaeth i wahodd trwy e-bost. Defnyddiwch y rhagosodiad (%(defaultIdentityServerName)s) neu reoli mewn Gosodiadau .", - "email_use_is": "Defnyddiwch weinydd hunaniaeth i wahodd trwy e-bost. Rheoli i mewn Gosodiadau .", + "email_limit_one": "Dim ond un ar y tro y mae moddanfon gwahoddiadau trwy e-bost", + "email_use_default_is": "Defnyddiwch weinydd hunaniaeth i wahodd trwy e-bost. Defnyddiwch y rhagosodiad (%(defaultIdentityServerName)s) neu reoli mewn Gosodiadau.", + "email_use_is": "Defnyddiwch weinydd hunaniaeth i wahodd trwy e-bost. Rheoli o fewn y Gosodiadau.", "error_already_invited_room": "Mae'r defnyddiwr eisoes wedi'i wahodd i'r ystafell", "error_already_invited_space": "Mae'r defnyddiwr eisoes wedi'i wahodd i'r gofod", "error_already_joined_room": "Mae'r defnyddiwr eisoes yn yr ystafell", "error_already_joined_space": "Mae'r defnyddiwr eisoes yn y gofod", - "error_bad_state": "Rhaid i'r defnyddiwr fod heb ei wahardd cyn y gellir ei wahodd.", - "error_dm": "Ni allem greu eich DM.", + "error_bad_state": "Rhaid i'r defnyddiwr fod heb ei wahardd cyn y mae moddei wahodd.", + "error_dm": "Nid oedd modd i ni greu eich DM.", "error_find_room": "Aeth rhywbeth o'i le wrth geisio gwahodd y defnyddwyr.", - "error_find_user_description": "Mae'n bosib nad yw'r defnyddwyr canlynol yn bodoli neu'n annilys, ac ni ellir eu gwahodd: %(csvNames)s", + "error_find_user_description": "Mae'n bosib nad yw'r defnyddwyr canlynol yn bodoli neu'n annilys, ac nid oes modd eu gwahodd: %(csvNames)s", "error_find_user_title": "Wedi methu dod o hyd i'r defnyddwyr canlynol", - "error_invite": "Ni allem wahodd y defnyddwyr hynny. Gwiriwch y defnyddwyr yr ydych am eu gwahodd a cheisiwch eto.", + "error_invite": "Nid oedd modd i ni wahodd y defnyddwyr hynny. Gwiriwch y defnyddwyr yr ydych am eu gwahodd a cheisiwch eto.", "error_permissions_room": "Nid oes gennych ganiatâd i wahodd pobl i'r ystafell hon.", "error_permissions_space": "Nid oes gennych ganiatâd i wahodd pobl i'r gofod hwn.", "error_profile_undisclosed": "Gall defnyddiwr fodoli neu beidio", - "error_transfer_multiple_target": "Dim ond i un defnyddiwr y gellir trosglwyddo galwad.", - "error_unfederated_room": "Mae'r ystafell hon yn ddi-ffederal. Ni allwch wahodd pobl o weinyddion allanol.", - "error_unfederated_space": "Mae'r gofod hwn yn ddiffederal. Ni allwch wahodd pobl o weinyddion allanol.", + "error_transfer_multiple_target": "Dim ond i un defnyddiwr y mae modd trosglwyddo galwad.", + "error_unfederated_room": "Mae'r ystafell hon yn ddi-ffederal. Allwch chi ddim gwahodd pobl o weinyddion allanol.", + "error_unfederated_space": "Mae'r gofod hwn yn ddiffederal. Allwch chi ddim gwahodd pobl o weinyddion allanol.", "error_unknown": "Gwall gweinydd anhysbys", "error_user_not_found": "Nid yw'r defnyddiwr yn bodoli", "error_version_unsupported_room": "Nid yw gweinydd cartref y defnyddiwr yn cefnogi'r fersiwn o'r ystafell.", @@ -1289,102 +1299,102 @@ "failed_generic": "Methodd y gweithrediad", "failed_title": "Wedi methu â gwahodd", "invalid_address": "Cyfeiriad heb ei gydnabod", - "name_email_mxid_share_room": "Gwahoddwch rywun i ddefnyddio ei enw, cyfeiriad e-bost, enw defnyddiwr (fel ) neu rannu'r ystafell hon .", - "name_email_mxid_share_space": "Gwahoddwch rywun i ddefnyddio ei enw, cyfeiriad e-bost, enw defnyddiwr (fel ) neu rhannwch y gofod hwn .", - "name_mxid_share_room": "Gwahoddwch rywun i ddefnyddio eu henw, enw defnyddiwr (fel ) neu rannu'r ystafell hon .", - "name_mxid_share_space": "Gwahoddwch rywun i ddefnyddio eu henw, enw defnyddiwr (fel ) neu rhannwch y gofod hwn .", + "name_email_mxid_share_room": "Gwahoddwch rywun i ddefnyddio ei enw, cyfeiriad e-bost, enw defnyddiwr (fel ) neu rannu'r ystafell hon.", + "name_email_mxid_share_space": "Gwahoddwch rywun i ddefnyddio ei enw, cyfeiriad e-bost, enw defnyddiwr (fel ) neu rhannu'r gofod hwn.", + "name_mxid_share_room": "Gwahoddwch rywun i ddefnyddio eu henw, enw defnyddiwr (fel ) neu rannu'r ystafell hon.", + "name_mxid_share_space": "Gwahoddwch rywun i ddefnyddio eu henw, enw defnyddiwr (fel ) neu rhannu'r gofod hwn.", "recents_section": "Sgyrsiau Diweddar", - "room_failed_partial": "Anfonasom y lleill, ond ni ellid gwahodd y bobl isod", - "room_failed_partial_title": "Ni fu modd anfon rhai gwahoddiadau", + "room_failed_partial": "Rydym wedi anfon y lleill, ond nid oes modd gwahodd y bobl isod i ", + "room_failed_partial_title": "Nid oedd modd anfon rhai gwahoddiadau", "room_failed_title": "Wedi methu gwahodd defnyddwyr i %(roomName)s", "send_link_prompt": "Neu anfonwch ddolen wahoddiad", - "start_conversation_name_email_mxid_prompt": "Dechreuwch sgwrs gyda rhywun gan ddefnyddio eu henw, cyfeiriad e-bost neu enw defnyddiwr (fel ).", - "start_conversation_name_mxid_prompt": "Dechreuwch sgwrs gyda rhywun gan ddefnyddio eu henw neu enw defnyddiwr (fel ).", + "start_conversation_name_email_mxid_prompt": "Dechreuwch sgwrs gyda rhywun gan ddefnyddio eu henw, cyfeiriad e-bost neu enw defnyddiwr (fel ).", + "start_conversation_name_mxid_prompt": "Dechreuwch sgwrs gyda rhywun gan ddefnyddio eu henw neu enw defnyddiwr (fel ).", "suggestions_disclaimer": "Efallai y bydd rhai awgrymiadau'n cael eu cuddio er preifatrwydd.", "suggestions_disclaimer_prompt": "Os na allwch weld pwy rydych yn chwilio amdano, anfonwch eich dolen wahoddiad isod.", - "suggestions_section": "Neges Uniongyrchol Yn Ddiweddar", + "suggestions_section": "Neges Uniongyrchol Ddiweddar", "to_room": "Gwahodd i %(roomName)s", "to_space": "Gwahodd i %(spaceName)s", "transfer_dial_pad_tab": "Pad deialu", "transfer_user_directory_tab": "Cyfeiriadur Defnyddwyr", - "unable_find_profiles_description_default": "Methu dod o hyd i broffiliau ar gyfer yr IDau Matrics a restrir isod - a hoffech chi eu gwahodd beth bynnag?", + "unable_find_profiles_description_default": "Methu dod o hyd i broffiliau ar gyfer yr IDau Matrics wedi'u rhestru isod - a hoffech chi eu gwahodd beth bynnag?", "unable_find_profiles_invite_label_default": "Gwahodd beth bynnag", "unable_find_profiles_invite_never_warn_label_default": "Gwahodd beth bynnag a pheidiwch byth â fy rhybuddio eto", "unable_find_profiles_title": "Efallai na fydd y defnyddwyr canlynol yn bodoli", - "unban_first_title": "Ni ellir gwahodd defnyddiwr nes ei fod heb ei wahardd" + "unban_first_title": "Nid oes modd gwahodd defnyddiwr nes ei fod heb ei ddadwahardd" }, "inviting_user1_and_user2": "Yn gwahodd %(user1)s a %(user2)s", "keyboard": { - "activate_button": "Actifadu botwm a ddewiswyd", + "activate_button": "Agor y botwm hwn", "alt": "Alt", - "autocomplete_cancel": "Canslo awtogwblhau", - "autocomplete_force": "Llu wedi'i gwblhau", + "autocomplete_cancel": "Diddymu awtogwblhau", + "autocomplete_force": "Gorfodi cwblhau", "autocomplete_navigate_next": "Awgrym awtolenwi nesaf", "autocomplete_navigate_prev": "Awgrym awtolenwi blaenorol", - "backspace": "Bysell Nôl", - "cancel_reply": "Canslo ateb neges", + "backspace": "Backspace", + "cancel_reply": "Diddymu ateb neges", "category_autocomplete": "Awtogwblhau", "category_calls": "Galwadau", "category_navigation": "Llywio", "category_room_list": "Rhestr Ystafell", "close_dialog_menu": "Caewch y ddewislen deialog neu gyd-destun", - "composer_jump_end": "Neidiwch i ddiwedd y cyfansoddwr", - "composer_jump_start": "Neidiwch i ddechrau'r cyfansoddwr", - "composer_navigate_next_history": "Llywiwch i'r neges nesaf yn hanes y cyfansoddwr", - "composer_navigate_prev_history": "Llywiwch i'r neges flaenorol yn hanes y cyfansoddwr", + "composer_jump_end": "Symud i ddiwedd y cyfansoddwr", + "composer_jump_start": "Symud i ddechrau'r cyfansoddwr", + "composer_navigate_next_history": "Ymlaen i'r neges nesaf yn hanes y cyfansoddwr", + "composer_navigate_prev_history": "Ymlaen i'r neges flaenorol yn hanes y cyfansoddwr", "composer_new_line": "Llinell newydd", "composer_redo": "Ail-wneud golygu", - "composer_toggle_bold": "Toggle Bold", + "composer_toggle_bold": "Toglo Trwm", "composer_toggle_code_block": "Toglo Bloc Cod", - "composer_toggle_italics": "Toggle Italics", + "composer_toggle_italics": "Toglo Italics", "composer_toggle_link": "Toglo Dolen", "composer_toggle_quote": "Toglo Dyfyniad", "composer_undo": "Dadwneud golygu", "control": "Ctrl", - "dismiss_read_marker_and_jump_bottom": "Diystyru'r marciwr darllen a neidio i'r gwaelod", + "dismiss_read_marker_and_jump_bottom": "Diystyru'r marciwr darllen a symud i'r gwaelod", "end": "Diwedd", "enter": "Enter", "escape": "Esc", - "go_home_view": "Ewch i Home View", + "go_home_view": "Mynd i Golwg Cartref", "home": "Cartref", - "jump_first_message": "Neidio i'r neges gyntaf", - "jump_last_message": "Neidio i'r neges olaf", - "jump_room_search": "Neidio i chwilio ystafell", - "jump_to_read_marker": "Neidio i'r neges hynaf heb ei darllen", - "keyboard_shortcuts_tab": "Agorwch y tab gosodiadau hwn", - "navigate_next_history": "Nesaf ymwelwyd ag ystafell neu ofod yn ddiweddar", - "navigate_next_message_edit": "Llywiwch i'r neges nesaf i'w golygu", + "jump_first_message": "Symud i'r neges gyntaf", + "jump_last_message": "Symud i'r neges olaf", + "jump_room_search": "Symud i chwilio ystafelloedd", + "jump_to_read_marker": "Symud i'r neges hynaf heb ei darllen", + "keyboard_shortcuts_tab": "Agor y tab gosodiadau hwn", + "navigate_next_history": "Ymwelwyd ag ystafell neu ofod ddiweddar nesaf", + "navigate_next_message_edit": "Ymlaen i'r neges nesaf i'w golygu", "navigate_prev_history": "Ystafell neu ofod yr ymwelwyd â hwy yn ddiweddar", - "navigate_prev_message_edit": "Llywiwch i'r neges flaenorol i'w golygu", - "next_landmark": "Ewch i'r tirnod nesaf", + "navigate_prev_message_edit": "Symud i'r neges flaenorol i'w golygu", + "next_landmark": "Mynd i'r tirnod nesaf", "next_room": "Ystafell nesaf neu DM", "next_unread_room": "Ystafell nesaf heb ei darllen neu DM", - "number": "{number}", + "number": "[number]", "open_user_settings": "Agor gosodiadau defnyddiwr", "page_down": "Tudalen i Lawr", "page_up": "Tudalen i Fyny", - "prev_landmark": "Ewch i'r tirnod blaenorol", + "prev_landmark": "Mynd i'r tirnod blaenorol", "prev_room": "Ystafell flaenorol neu DM", "prev_unread_room": "Ystafell flaenorol heb ei darllen neu DM", - "room_list_collapse_section": "Crebachu adran rhestr ystafelloedd", + "room_list_collapse_section": "Lleihau adran rhestr ystafelloedd", "room_list_expand_section": "Ehangu'r adran rhestr ystafelloedd", - "room_list_navigate_down": "Llywiwch i lawr yn y rhestr ystafelloedd", - "room_list_navigate_up": "Llywiwch i fyny yn y rhestr ystafelloedd", - "room_list_select_room": "Dewiswch ystafell o'r rhestr ystafelloedd", - "scroll_down_timeline": "Sgroliwch i lawr yn y llinell amser", - "scroll_up_timeline": "Sgroliwch i fyny yn y llinell amser", + "room_list_navigate_down": "Symud i lawr yn y rhestr ystafelloedd", + "room_list_navigate_up": "Symud i fyny yn y rhestr ystafelloedd", + "room_list_select_room": "Dewis ystafell o'r rhestr ystafelloedd", + "scroll_down_timeline": "Sgrolio i lawr yn y llinell amser", + "scroll_up_timeline": "Sgrolio i fyny yn y llinell amser", "search": "Chwilio (rhaid ei alluogi)", "send_sticker": "Anfon sticer", "shift": "Shift", - "space": "Bwlch", + "space": "Space", "switch_to_space": "Newid i'r gofod yn ôl rhif", "toggle_hidden_events": "Toglo gwelededd digwyddiad cudd", "toggle_microphone_mute": "Toglo tewi meicroffon", - "toggle_right_panel": "Toggle panel dde", - "toggle_space_panel": "Toggle panel gofod", - "toggle_top_left_menu": "Toggle y ddewislen chwith uchaf", + "toggle_right_panel": "Toglo panel dde", + "toggle_space_panel": "Toglo panel gofod", + "toggle_top_left_menu": "Toglo'r ddewislen chwith uchaf", "toggle_webcam_mute": "Toglo gwe-gamera ymlaen / i ffwrdd", - "upload_file": "Uwchlwythwch ffeil" + "upload_file": "Llwytho ffeil i fyny" }, "labs": { "allow_screen_share_only_mode": "Caniatáu modd rhannu sgrin yn unig", @@ -1392,25 +1402,25 @@ "automatic_debug_logs": "Anfon logiau dadfygio yn awtomatig ar unrhyw wall", "automatic_debug_logs_decryption": "Anfon logiau dadgryptio yn awtomatig ar wallau dadgryptio", "automatic_debug_logs_key_backup": "Anfon logiau dadfygio yn awtomatig pan nad yw copi wrth gefn allweddol yn gweithio", - "beta_description": "Beth sydd nesaf i %(brand)s? Labordai yw'r ffordd orau o gael pethau'n gynnar, profi nodweddion newydd a helpu i'w siapio cyn iddynt gael eu lansio.", + "beta_description": "Beth sydd nesaf i %(brand)s? Labs yw'r ffordd orau o gael pethau'n gynnar, profi nodweddion newydd a helpu i'w siapio cyn iddynt gael eu lansio.", "beta_feature": "Mae hon yn nodwedd beta", "beta_feedback_leave_button": "I adael y beta, ewch i'ch gosodiadau.", "beta_feedback_title": "Adborth beta %(featureName)s", "beta_section": "Nodweddion sydd ar ddod", "bridge_state": "Dangos gwybodaeth am bontydd mewn gosodiadau ystafell", "bridge_state_channel": "Sianel:", - "bridge_state_creator": "Darparwyd y bont hon gan .", - "bridge_state_manager": "Rheolir y bont hon gan .", - "bridge_state_workspace": "Gweithle:", + "bridge_state_creator": "Darparwyd y bont hon gan.", + "bridge_state_manager": "Mae'r bont hon yn cael ei rheoli gan .", + "bridge_state_workspace": "Gweithle: ", "click_for_info": "Cliciwch am fwy o wybodaeth", "currently_experimental": "Arbrofol ar hyn o bryd.", "custom_themes": "Cefnogi ychwanegu themâu personol", - "dynamic_room_predecessors": "Rhagflaenwyr ystafell deinamig", + "dynamic_room_predecessors": "Rhagflaenwyr ystafell deimaterig", "dynamic_room_predecessors_description": "Galluogi MSC3946 (i gefnogi archifau ystafelloedd sy'n cyrraedd yn hwyr)", "element_call_video_rooms": "Ystafelloedd fideo Element Call", "exclude_insecure_devices": "Gwahardd dyfeisiau anniogel wrth anfon/derbyn negeseuon", "exclude_insecure_devices_description": "Pan fydd y modd hwn wedi'i alluogi, ni fydd negeseuon wedi'u hamgryptio yn cael eu rhannu â dyfeisiau heb eu gwirio, a bydd negeseuon o ddyfeisiau heb eu gwirio yn cael eu dangos fel gwall. Sylwch, os ydych chi'n galluogi'r modd hwn, efallai na fyddwch chi'n gallu cyfathrebu â defnyddwyr nad ydyn nhw wedi gwirio eu dyfeisiau.", - "experimental_description": "Teimlo'n arbrofol? Rhowch gynnig ar ein syniadau diweddaraf sy'n cael eu datblygu. Nid yw'r nodweddion hyn yn derfynol; gallant fod yn ansefydlog, gallant newid, neu gallant gael eu gollwng yn gyfan gwbl. Dysgwch fwy .", + "experimental_description": "Teimlo'n arbrofol? Rhowch gynnig ar ein syniadau diweddaraf sy'n cael eu datblygu. Nid yw'r nodweddion hyn yn derfynol; gallant fod yn ansefydlog, gallant newid, neu gallant gael eu gollwng yn gyfan gwbl. Dysgu rhagor.", "experimental_section": "Rhagolygon cynnar", "extended_profiles_msc_support": "Mae angen i'ch gweinydd gefnogi MSC4133", "feature_disable_call_per_sender_encryption": "Analluogi amgryptio fesul anfonwr ar gyfer Element Call", @@ -1423,7 +1433,7 @@ "group_moderation": "Cymedroil", "group_profile": "Proffil", "group_rooms": "Ystafelloedd", - "group_spaces": "Bylchau", + "group_spaces": "Gofodau", "group_themes": "Themâu", "group_threads": "Edau", "group_ui": "Rhyngwyneb", @@ -1433,15 +1443,15 @@ "html_topic": "Dangos cynrychiolaeth HTML o bynciau ystafell", "join_beta": "Ymunwch â'r beta", "join_beta_reload": "Bydd ymuno â'r beta yn ail-lwytho %(brand)s.", - "jump_to_date": "Neidio hyd yma (ychwanegu / neidio a neidio i benawdau dyddiad)", + "jump_to_date": "Symud i ddyddiad (ychwanegu / jumtodate a neidio i benynnau dyddiad)", "jump_to_date_msc_support": "Mae angen i'ch gweinydd gefnogi MSC3030", "latex_maths": "Rendro mathemateg LaTeX mewn negeseuon", - "leave_beta": "Gadewch y beta", + "leave_beta": "Gadael y beta", "leave_beta_reload": "Bydd gadael y beta yn ail-lwytho %(brand)s.", "location_share_live": "Rhannu Lleoliad Byw", "location_share_live_description": "Gweithredu dros dro. Mae lleoliadau'n parhau yn hanes ystafelloedd.", "mjolnir": "Ffyrdd newydd o anwybyddu pobl", - "msc3531_hide_messages_pending_moderation": "Gadael i safonwyr guddio negeseuon tra'n aros i'w safoni.", + "msc3531_hide_messages_pending_moderation": "Gadael i cymedrolwyr guddio negeseuon tra'n aros i'w safoni.", "new_room_list": "Galluogi rhestr ystafelloedd newydd", "notification_settings": "Gosodiadau Hysbysu Newydd", "notification_settings_beta_caption": "Cyflwyno ffordd symlach o newid eich gosodiadau hysbysu. Addaswch eich %(brand)s, yn union fel y dymunwch.", @@ -1449,23 +1459,23 @@ "notifications": "Galluogi'r panel hysbysiadau ym mhennyn yr ystafell", "release_announcement": "Cyhoeddiad rhyddhau", "render_reaction_images": "Rendro delweddau personol mewn adweithiau", - "render_reaction_images_description": "Cyfeirir ato weithiau fel \"emos personol\".", - "report_to_moderators": "Adrodd i safonwyr", - "report_to_moderators_description": "Mewn ystafelloedd sy'n cefnogi cymedroli, bydd y botwm “Adroddiad” yn gadael i chi riportio cam-drin i safonwyr ystafelloedd.", - "sliding_sync": "Modd cysoni llithro", - "sliding_sync_description": "O dan ddatblygiad gweithredol, ni ellir ei analluogi.", - "sliding_sync_disabled_notice": "Allgofnodwch ac yn ôl i mewn i analluogi", + "render_reaction_images_description": "Weithiau'n cael eu hadnabod fel \"emojis cyfaddas\".", + "report_to_moderators": "Adrodd i cymedrolwyr", + "report_to_moderators_description": "Mewn ystafelloedd sy'n cefnogi cymedroli, bydd y botwm “Adrodd” yn gadael i chi adrodd ar gam-drin i gymedrolwyr ystafelloedd.", + "sliding_sync": "Modd Cydweddu Llithro", + "sliding_sync_description": "Wrthi'n datblygu, nid oes modd ei analluogi.", + "sliding_sync_disabled_notice": "Allgofnodwch a mewngofnodi i analluogi", "sliding_sync_server_no_support": "Nid oes gan eich gweinydd gefnogaeth", - "under_active_development": "Dan ddatblygiad gweithredol.", + "under_active_development": "Yn cael ei ddatblygu.", "unrealiable_e2e": "Annibynadwy mewn ystafelloedd wedi'u hamgryptio", "video_rooms": "Ystafelloedd fideo", "video_rooms_a_new_way_to_chat": "Ffordd newydd o sgwrsio dros lais a fideo yn %(brand)s.", "video_rooms_always_on_voip_channels": "Mae ystafelloedd fideo bob amser yn sianeli VoIP sydd wedi'u mewnosod o fewn ystafell yn %(brand)s.", "video_rooms_beta": "Mae ystafelloedd fideo yn nodwedd beta", "video_rooms_faq1_answer": "Defnyddiwch y botwm “+” yn adran ystafell y panel chwith.", - "video_rooms_faq1_question": "Sut alla i greu ystafell fideo?", - "video_rooms_faq2_answer": "Ydy, mae'r llinell amser sgwrsio yn cael ei harddangos ochr yn ochr â'r fideo.", - "video_rooms_faq2_question": "A allaf ddefnyddio sgwrs testun ochr yn ochr â'r alwad fideo?", + "video_rooms_faq1_question": "Sut mae modd creu ystafell fideo?", + "video_rooms_faq2_answer": "Oes, mae'r llinell amser sgwrsio yn cael ei harddangos ochr yn ochr â'r fideo.", + "video_rooms_faq2_question": "A oes modd defnyddio sgwrs testun ochr yn ochr â'r alwad fideo?", "video_rooms_feedbackSubheading": "Diolch am roi cynnig ar y beta, ewch i gymaint o fanylion ag y gallwch fel y gallwn ei wella.", "wysiwyg_composer": "Golygydd testun cyfoethog" }, @@ -1487,10 +1497,10 @@ "lists_new_label": "ID ystafell neu gyfeiriad y rhestr wahardd", "no_lists": "Nid ydych wedi eich tanysgrifio i unrhyw restrau", "personal_description": "Mae eich rhestr gwaharddiadau personol yn dal yr holl ddefnyddwyr/gweinyddion nad ydych chi'n bersonol am weld negeseuon ganddynt. Ar ôl anwybyddu'ch defnyddiwr/gweinydd cyntaf, bydd ystafell newydd yn ymddangos yn eich rhestr ystafelloedd o'r enw '%(myBanList)s' - arhoswch yn yr ystafell hon i gadw'r rhestr wahardd mewn grym.", - "personal_empty": "Nid ydych wedi anwybyddu unrhyw un.", + "personal_empty": "Nid ydych wedi anwybyddu neb.", "personal_heading": "Rhestr gwaharddiad personol", - "personal_new_label": "Gweinydd neu ID defnyddiwr i anwybyddu", - "personal_new_placeholder": "ee: @bot:* neu enghraifft.org", + "personal_new_label": "Gweinydd neu ID defnyddiwr i'w anwybyddu", + "personal_new_placeholder": "ee: @bot:* neu example.org", "personal_section": "Ar hyn o bryd rydych yn anwybyddu:", "room_name": "Fy Rhestr Gwaharddiadau", "room_topic": "Dyma'ch rhestr o ddefnyddwyr/gweinyddion rydych chi wedi'u rhwystro - peidiwch â gadael yr ystafell!", @@ -1502,18 +1512,18 @@ "title": "Defnyddwyr wedi'u hanwybyddu", "view_rules": "Gweld rheolau" }, - "language_dropdown_label": "Cwymp Iaith", + "language_dropdown_label": "Cwymplen Iaith", "leave_room_dialog": { "last_person_warning": "Chi yw'r unig berson yma. Os byddwch yn gadael, ni fydd neb yn gallu ymuno yn y dyfodol, gan gynnwys chi.", "leave_room_question": "Ydych chi'n siŵr eich bod am adael ystafell '%(roomName)s'?", "leave_space_question": "Ydych chi'n siŵr eich bod am adael y bwlch '%(spaceName)s'?", "room_leave_admin_warning": "Chi yw'r unig weinyddwr yn yr ystafell hon. Os byddwch yn gadael, ni fydd neb yn gallu newid gosodiadau ystafell na chymryd camau pwysig eraill.", "room_leave_mod_warning": "Chi yw'r unig gymedrolwr yn yr ystafell hon. Os byddwch yn gadael, ni fydd neb yn gallu newid gosodiadau ystafell na chymryd camau pwysig eraill.", - "room_rejoin_warning": "Nid yw'r ystafell hon yn gyhoeddus. Ni fyddwch yn gallu ailymuno heb wahoddiad.", - "space_rejoin_warning": "Nid yw'r gofod hwn yn gyhoeddus. Ni fyddwch yn gallu ailymuno heb wahoddiad." + "room_rejoin_warning": "Nid yw'r ystafell hon yn gyhoeddus. Fyddwch chi ddim yn gallu ailymuno heb wahoddiad.", + "space_rejoin_warning": "Nid yw'r gofod hwn yn gyhoeddus. Fyddwch chi ddim yn gallu ailymuno heb wahoddiad." }, "left_panel": { - "open_dial_pad": "Pad deialu agored" + "open_dial_pad": "Agor y pad deialu" }, "lightbox": { "rotate_left": "Cylchdroi i'r chwith", @@ -1521,28 +1531,28 @@ "title": "Golwg delwedd" }, "location_sharing": { - "MapStyleUrlNotConfigured": "Nid yw'r gweinydd cartref hwn wedi'i ffurfweddu i arddangos mapiau.", + "MapStyleUrlNotConfigured": "Nid yw'r gweinydd cartref hwn wedi'i ffurfweddu i ddangos mapiau.", "MapStyleUrlNotReachable": "Nid yw'r gweinydd cartref hwn wedi'i ffurfweddu'n gywir i ddangos mapiau, neu efallai na fydd modd cyrraedd y gweinydd mapiau sydd wedi'i ffurfweddu.", - "WebGLNotEnabled": "Mae angen WebGL i ddangos mapiau, a fyddech cystal â'i alluogi yng ngosodiadau eich porwr.", + "WebGLNotEnabled": "Mae angen WebGL i ddangos mapiau, galluogwch ef yng ngosodiadau eich porwr.", "click_drop_pin": "Cliciwch i ollwng pin", "click_move_pin": "Cliciwch i symud y pin", "close_sidebar": "Caewch y bar ochr", "error_fetch_location": "Methu nôl lleoliad", "error_no_perms_description": "Mae angen i chi gael y caniatâd cywir er mwyn rhannu lleoliadau yn yr ystafell hon.", "error_no_perms_title": "Nid oes gennych ganiatâd i rannu lleoliadau", - "error_send_description": "Ni allai %(brand)s anfon eich lleoliad. Ceisiwch eto yn nes ymlaen.", - "error_send_title": "Ni allem anfon eich lleoliad", + "error_send_description": "Nid oedd modd i %(brand)s anfon eich lleoliad. Ceisiwch eto yn nes ymlaen.", + "error_send_title": "Nid oedd modd i ni anfon eich lleoliad", "error_sharing_live_location": "Digwyddodd gwall wrth rannu eich lleoliad byw", "error_stopping_live_location": "Digwyddodd gwall wrth atal eich lleoliad byw", - "expand_map": "Ehangu map", + "expand_map": "Ehangu'r map", "failed_generic": "Wedi methu â nôl eich lleoliad. Ceisiwch eto yn nes ymlaen.", - "failed_load_map": "Methu llwytho map", + "failed_load_map": "Methu'r llwytho map", "failed_permission": "Gwrthodwyd caniatâd i %(brand)s nol eich lleoliad. Caniatewch fynediad lleoliad yng ngosodiadau eich porwr.", - "failed_timeout": "Wedi dod i ben yn ceisio nôl eich lleoliad. Ceisiwch eto yn nes ymlaen.", + "failed_timeout": "Daeth yr amser i ben yn ceisio nôl eich lleoliad. Ceisiwch eto yn nes ymlaen.", "failed_unknown": "Gwall anhysbys wrth nôl lleoliad. Ceisiwch eto yn nes ymlaen.", - "find_my_location": "Dod o hyd i fy lleoliad", - "live_description": "lleoliad byw %(displayName)s", - "live_enable_description": "Sylwch: nodwedd labordai yw hon sy'n defnyddio gweithrediad dros dro. Mae hyn yn golygu na fyddwch yn gallu dileu hanes eich lleoliad, a bydd defnyddwyr uwch yn gallu gweld eich hanes lleoliad hyd yn oed ar ôl i chi roi'r gorau i rannu eich lleoliad byw gyda'r ystafell hon.", + "find_my_location": "Canfod fy lleoliad", + "live_description": "Lleoliad byw %(displayName)s", + "live_enable_description": "Sylwch: nodwedd Labs yw hon sy'n defnyddio gweithrediad dros dro. Mae hyn yn golygu na fyddwch yn gallu dileu hanes eich lleoliad, a bydd defnyddwyr uwch yn gallu gweld eich hanes lleoliad hyd yn oed ar ôl i chi roi'r gorau i rannu eich lleoliad byw gyda'r ystafell hon.", "live_enable_heading": "Rhannu lleoliad byw", "live_location_active": "Rydych chi'n rhannu eich lleoliad byw", "live_location_enabled": "Lleoliad byw wedi'i alluogi", @@ -1554,7 +1564,7 @@ "live_until": "Byw tan %(expiryTime)s", "live_update_time": "Wedi diweddaru %(humanizedUpdateTime)s", "loading_live_location": "Wrthi'n llwytho lleoliad byw…", - "location_not_available": "Lleoliad ddim ar gael", + "location_not_available": "Nid yw'r lleoliad ar gael", "map_feedback": "Adborth map", "mapbox_logo": "Logo Mapbox", "reset_bearing": "Ailosod y cyfeiriant i'r gogledd", @@ -1570,21 +1580,21 @@ "invite_button_no_perms_tooltip": "Nid oes gennych ganiatâd i wahodd defnyddwyr", "invited_label": "Gwahoddwyd", "no_matches": "Dim cyfatebiaeth", - "power_label": "%(userName)s (pŵer %(powerLevelNumber)s)" + "power_label": "%(userName)s (power %(powerLevelNumber)s)" }, - "member_list_back_action_label": "Aelodau ystafell", + "member_list_back_action_label": "Aelodau'r ystafell", "message_edit_dialog_title": "Golygiadau neges", - "migrating_crypto": "Hongian yn dynn. Rydym yn diweddaru %(brand)s i wneud amgryptio yn gyflymach ac yn fwy dibynadwy.", + "migrating_crypto": "Arhoswch... Rydym yn diweddaru %(brand)s i wneud amgryptio yn gyflymach ac yn fwy dibynadwy.", "mobile_guide": { - "toast_accept": "Defnyddiwch app", + "toast_accept": "Defnyddiwch yr ap", "toast_description": "Mae %(brand)s yn arbrofol ar borwr gwe symudol. I gael profiad gwell a'r nodweddion diweddaraf, defnyddiwch ein app brodorol rhad ac am ddim.", - "toast_title": "Defnyddiwch ap i gael profiad gwell" + "toast_title": "Defnyddiwch yr ap i gael profiad gwell" }, - "name_and_id": "%(name)s (%(userId)s)", + "name_and_id": "%(matere)s (%(userId)s)", "no_more_results": "Dim mwy o ganlyniadau", "notif_panel": { "empty_description": "Nid oes gennych unrhyw hysbysiadau gweladwy.", - "empty_heading": "Rydych chi i gyd wedi'ch dal i fyny" + "empty_heading": "Rydych yn gyfredol" }, "notifications": { "all_messages": "Pob neges", @@ -1609,11 +1619,11 @@ "mentions_and_keywords": "@crybwylliadau ac allweddeiriau", "mentions_and_keywords_description": "Dim ond gyda chyfeiriadau a geiriau allweddol fel y'u gosodwyd yn eich gosodiadau y cewch eich hysbysu", "mentions_keywords": "Crybwyll ac allweddeiriau", - "message_didnt_send": "Ni anfonwyd y neges. Cliciwch am wybodaeth.", - "mute_description": "Ni fyddwch yn cael unrhyw hysbysiadau" + "message_didnt_send": "Heb anfon y neges. Cliciwch am wybodaeth.", + "mute_description": "Fyddwch chi ddim yn cael unrhyw hysbysiadau" }, "notifier": { - "m.key.verification.request": "Mae %(name)s yn gofyn am ddilysiad" + "m.key.verification.request": "Mae %(matere)s yn gofyn am ddilysiad" }, "onboarding": { "create_room": "Creu Sgwrs Grŵp", @@ -1624,48 +1634,48 @@ "no_avatar_label": "Ychwanegwch lun fel bod pobl yn gwybod mai chi sydd yno.", "send_dm": "Anfon Neges Uniongyrchol", "welcome_detail": "Nawr, gadewch i ni eich helpu i ddechrau", - "welcome_user": "Croeso %(name)s" + "welcome_user": "Croeso %(matere)s" }, "pill": { "permalink_other_room": "Neges yn %(room)s", "permalink_this_room": "Neges gan %(user)s" }, "poll": { - "create_poll_action": "Creu Pôl", + "create_poll_action": "Creu Arolwg", "create_poll_title": "Creu arolwg barn", - "disclosed_notes": "Mae pleidleiswyr yn gweld canlyniadau cyn gynted ag y byddant wedi pleidleisio", + "disclosed_notes": "Mae'r pleidleiswyr yn gweld canlyniadau cyn gynted ag y byddan nhw wedi pleidleisio", "edit_poll_title": "Golygu arolwg barn", "end_description": "Ydych chi'n siŵr eich bod am ddod â'r arolwg barn hwn i ben? Bydd hyn yn dangos canlyniadau terfynol y bleidlais ac yn atal pobl rhag gallu pleidleisio.", "end_message": "Mae'r arolwg barn wedi dod i ben. Ateb gorau: %(topAnswer)s", - "end_message_no_votes": "Mae'r arolwg barn wedi dod i ben. Ni fwriwyd unrhyw bleidleisiau.", - "end_title": "Pôl Diwedd", - "error_ending_description": "Mae'n ddrwg gennym, ni ddaeth y bleidlais i ben. Ceisiwch eto.", + "end_message_no_votes": "Mae'r arolwg barn wedi dod i ben. Neb wedi pleidleisio.", + "end_title": "Diwedd yr Arolwg", + "error_ending_description": "Ymddiheuriadau, nid yw'r bleidlais wedi dod i ben. Ceisiwch eto.", "error_ending_title": "Wedi methu â dod â'r bleidlais i ben", - "error_voting_description": "Mae'n ddrwg gennym, ni chofrestrwyd eich pleidlais. Ceisiwch eto.", + "error_voting_description": "Ymddiheuriadau, nid yw eich pleidlais wedi'i chofrestru. Ceisiwch eto.", "error_voting_title": "Pleidlais heb ei chofrestru", - "failed_send_poll_description": "Mae'n ddrwg gennym, ni chafodd yr arolwg barn y ceisioch ei greu ei bostio.", + "failed_send_poll_description": "Ymddiheuriadau, nid yw'ch arolwg wedi ei phostio.", "failed_send_poll_title": "Wedi methu â phostio'r bleidlais", "notes": "Dim ond pan fyddwch chi'n dod â'r bleidlais i ben y caiff canlyniadau eu datgelu", "options_add_button": "Ychwanegu dewis", - "options_heading": "Creu opsiynau", - "options_label": "Opsiwn %(number)s", - "options_placeholder": "Ysgrifennwch opsiwn", + "options_heading": "Creu dewisiadau", + "options_label": "Dewis %(number)s", + "options_placeholder": "Ysgrifennwch ddewis", "topic_heading": "Beth yw cwestiwn neu bwnc eich arolwg barn?", "topic_label": "Cwestiwn neu bwnc", "topic_placeholder": "Ysgrifennu rhywbeth…", - "total_decryption_errors": "Oherwydd gwallau dadgryptio, efallai na fydd rhai pleidleisiau yn cael eu cyfrif", - "total_no_votes": "Dim pleidleisiau a fwriwyd", + "total_decryption_errors": "Oherwydd gwallau dadgryptio, efallai na fydd rhai pleidleisiau'n cael eu cyfrif", + "total_no_votes": "Dim pleidleisiau wedi'u bwrw", "total_not_ended": "Bydd y canlyniadau i'w gweld pan ddaw'r bleidlais i ben", - "type_closed": "Pôl caeedig", + "type_closed": "Arolwg wedi'i chau", "type_heading": "Math o bleidlais", - "type_open": "Pôl agored", - "unable_edit_description": "Mae'n ddrwg gennym, ni allwch olygu arolwg barn ar ôl i'r pleidleisiau gael eu bwrw.", + "type_open": "Agor arolwg", + "unable_edit_description": "Ymddiheuriadau, allwch chi ddim golygu arolwg barn ar ôl i'r pleidleisiau gael eu bwrw.", "unable_edit_title": "Methu golygu'r arolwg barn" }, "power_level": { "admin": "Gweinyddwr", - "custom": "Personol (%(level)s)", - "custom_level": "Lefel Custom", + "custom": "(%(level)s) cyfaddas", + "custom_level": "Lefel Cyfaddas", "default": "Rhagosodedig", "label": "Lefel pŵer", "moderator": "Cymedrolwr", @@ -1677,30 +1687,30 @@ "away": "I ffwrdd", "busy": "Prysur", "idle": "Yn segur", - "idle_for": "Segur ar gyfer %(duration)s", + "idle_for": "Segur am %(duration)s", "offline": "All-lein", - "offline_for": "All-lein ar gyfer %(duration)s", + "offline_for": "All-lein am %(duration)s", "online": "Ar-lein", - "online_for": "Ar-lein ar gyfer %(duration)s", + "online_for": "Ar-lein am %(duration)s", "unknown": "Anhysbys", "unknown_for": "Anhysbys am %(duration)s", "unreachable": "Nid oes modd cyrraedd gweinydd y defnyddiwr" }, "quick_settings": { - "all_settings": "Pob Gosodiad", - "metaspace_section": "Piniwch i'r bar ochr", + "all_settings": "Pob gosodiad", + "metaspace_section": "Pinio i'r bar ochr", "sidebar_settings": "Rhagor o ddewisiadau", "title": "Gosodiadau cyflym" }, "quit_warning": { "call_in_progress": "Mae'n ymddangos eich bod mewn galwad, a ydych chi'n siŵr eich bod am roi'r gorau iddi?", - "file_upload_in_progress": "Mae'n ymddangos eich bod yn uwchlwytho ffeiliau, a ydych yn siŵr eich bod am roi'r gorau iddi?" + "file_upload_in_progress": "Mae'n ymddangos eich bod yn llwytho ffeiliau i fyny, a ydych yn siŵr eich bod am roi'r gorau iddi?" }, "redact": { "confirm_button": "Cadarnhau Tynnu", - "confirm_description": "Ydych chi'n siŵr eich bod am ddileu (dileu) y digwyddiad hwn?", - "confirm_description_state": "Sylwch y gallai dileu newidiadau ystafell fel hyn ddadwneud y newid.", - "error": "Ni allwch ddileu'r neges hon. (%(code)s)", + "confirm_description": "Ydych chi'n siŵr eich bod am ddileu'r digwyddiad hwn?", + "confirm_description_state": "Sylwch y gall dileu newidiadau ystafell fel hyn ddadwneud y newid.", + "error": "Allwch chi ddim ddileu'r neges hon. (%(code)s)", "ongoing": "Wrthi'n tynnu…", "reason_label": "Rheswm (dewisol)" }, @@ -1716,15 +1726,15 @@ "hide_messages_from_user": "Gwiriwch a ydych am guddio'r holl negeseuon presennol ac yn y dyfodol gan y defnyddiwr hwn.", "ignore_user": "Anwybyddu defnyddiwr", "illegal_content": "Cynnwys Anghyfreithlon", - "missing_reason": "Llenwch pam eich bod yn adrodd.", + "missing_reason": "Dywedwch pam eich bod yn adrodd.", "nature": "Dewiswch natur a disgrifiwch beth sy'n gwneud y neges hon yn ddifrïol.", - "nature_disagreement": "Mae'r hyn y mae'r defnyddiwr hwn yn ei ysgrifennu yn anghywir.\nBydd hyn yn cael ei adrodd i'r safonwyr ystafell.", - "nature_illegal": "Mae'r defnyddiwr hwn yn arddangos ymddygiad anghyfreithlon, er enghraifft trwy roi docsi ar bobl neu fygwth trais.\nBydd hyn yn cael ei adrodd i'r safonwyr ystafell a all uwchgyfeirio hyn i awdurdodau cyfreithiol.", + "nature_disagreement": "Mae'r hyn y mae'r defnyddiwr hwn yn ei ysgrifennu yn anghywir.\nBydd hyn yn cael ei adrodd i gymedrolwyr yr ystafell.", + "nature_illegal": "Mae'r defnyddiwr hwn yn dangos ymddygiad anghyfreithlon, er enghraifft trwy fygwth pobl neu fygwth trais.\nBydd hyn yn cael ei adrodd i'r cymedrolwyr ystafell a all uwchgyfeirio hyn i awdurdodau cyfreithiol.", "nature_nonstandard_admin": "Mae'r ystafell hon wedi'i neilltuo ar gyfer cynnwys anghyfreithlon neu wenwynig neu mae'r cymedrolwyr yn methu â chymedroli cynnwys anghyfreithlon neu wenwynig.\nBydd hyn yn cael ei adrodd i weinyddwyr %(homeserver)s.", "nature_nonstandard_admin_encrypted": "Mae'r ystafell hon wedi'i neilltuo ar gyfer cynnwys anghyfreithlon neu wenwynig neu mae'r cymedrolwyr yn methu â chymedroli cynnwys anghyfreithlon neu wenwynig.\nBydd hyn yn cael ei adrodd i weinyddwyr %(homeserver)s. NI fydd y gweinyddwyr yn gallu darllen cynnwys yr ystafell hon wedi'i amgryptio.", - "nature_other": "Unrhyw reswm arall. Disgrifiwch y broblem.\nBydd hyn yn cael ei adrodd i'r safonwyr ystafell.", - "nature_spam": "Mae'r defnyddiwr hwn yn sbamio'r ystafell gyda hysbysebion, dolenni i hysbysebion neu i bropaganda.\nBydd hyn yn cael ei adrodd i'r safonwyr ystafell.", - "nature_toxic": "Mae'r defnyddiwr hwn yn arddangos ymddygiad gwenwynig, er enghraifft trwy sarhau defnyddwyr eraill neu rannu cynnwys oedolion yn unig mewn ystafell sy'n gyfeillgar i deuluoedd neu dorri rheolau'r ystafell hon fel arall.\nBydd hyn yn cael ei adrodd i'r safonwyr ystafell.", + "nature_other": "Unrhyw reswm arall. Disgrifiwch y broblem.\nBydd hyn yn cael ei adrodd i'r cymedrolwyr ystafell.", + "nature_spam": "Mae'r defnyddiwr hwn yn sbamio'r ystafell gyda hysbysebion, dolenni i hysbysebion neu i bropaganda.\nBydd hyn yn cael ei adrodd i'r cymedrolwyr ystafell.", + "nature_toxic": "Mae'r defnyddiwr hwn yn arddangos ymddygiad gwenwynig, er enghraifft trwy sarhau defnyddwyr eraill neu rannu cynnwys oedolion yn unig mewn ystafell sy'n gyfeillgar i deuluoedd neu dorri rheolau'r ystafell hon fel arall.\nBydd hyn yn cael ei adrodd i'r cymedrolwyr ystafell.", "other_label": "Arall", "report_content_to_homeserver": "Adrodd Cynnwys i'ch Gweinyddwr Homeserver", "report_entire_room": "Rhoi gwybod am yr ystafell gyfan", @@ -1734,24 +1744,24 @@ "restore_key_backup_dialog": { "count_of_decryption_failures": "Wedi methu â dadgryptio %(failedCount)s sesiwn!", "count_of_successfully_restored_keys": "Wedi adfer %(sessionCount)s allwedd yn llwyddiannus", - "enter_key_description": "Cyrchwch hanes eich negeseuon diogel a gosodwch negeseuon diogel trwy nodi'ch Allwedd Ddiogelwch.", - "enter_key_title": "Rhowch Allwedd Ddiogelwch", + "enter_key_description": "Cyrchwch hanes eich negeseuon diogel a gosodwch negeseuon diogel trwy nodi'ch Allwedd Adfer.", + "enter_key_title": "Rhowch Allwedd Adfer", "enter_phrase_description": "Cyrchwch hanes eich neges ddiogel a gosodwch negeseuon diogel trwy nodi'ch Ymadrodd Diogelwch.", "enter_phrase_title": "Rhowch Ymadrodd Diogelwch", "incorrect_security_phrase_dialog": "Nid oedd modd dadgryptio copi wrth gefn gyda'r Ymadrodd Diogelwch hwn: gwiriwch eich bod wedi rhoi'r Ymadrodd Diogelwch cywir.", "incorrect_security_phrase_title": "Ymadrodd Diogelwch Anghywir", - "key_backup_warning": "Rhybudd : dim ond o gyfrifiadur rydych chi'n ymddiried ynddo y dylech chi sefydlu allwedd wrth gefn.", + "key_backup_warning": "Rhybudd: dim ond o gyfrifiadur rydych chi'n ymddiried ynddo y dylech chi greu allwedd wrth gefn.", "key_fetch_in_progress": "Wrthi'n nôl allweddi o'r gweinydd…", - "key_forgotten_text": "Os ydych wedi anghofio eich Allwedd Ddiogelwch gallwch ", - "key_is_invalid": "Ddim yn Allwedd Ddiogelwch ddilys", - "key_is_valid": "Mae hwn yn edrych fel Allwedd Ddiogelwch ddilys!", + "key_forgotten_text": "Os ydych wedi anghofio eich Allwedd Adfer gallwch ", + "key_is_invalid": "Ddim yn Allwedd Adfer ddilys", + "key_is_valid": "Mae hwn yn edrych fel Allwedd Adfer ddilys!", "keys_restored_title": "Allweddi wedi'u hadfer", "load_error_content": "Methu llwytho statws wrth gefn", "load_keys_progress": "%(completed)s o %(total)s allweddi wedi'u hadfer", "no_backup_error": "Heb ganfod copi wrth gefn!", - "phrase_forgotten_text": "Os ydych chi wedi anghofio eich Ymadrodd Diogelwch gallwch chi defnyddiwch eich Allwedd Ddiogelwch neu sefydlu opsiynau adfer newydd", - "recovery_key_mismatch_description": "Nid oedd modd dadgryptio copi wrth gefn gyda'r Allwedd Ddiogelwch hon: gwiriwch eich bod wedi rhoi'r Allwedd Ddiogelwch gywir.", - "recovery_key_mismatch_title": "Diffyg cyfatebiaeth Allwedd Ddiogelwch", + "phrase_forgotten_text": "Os ydych chi wedi anghofio eich Ymadrodd Diogelwch gallwch chi defnyddio eich Allwedd Adfer neu greu dewisiadau adfer newydd", + "recovery_key_mismatch_description": "Nid oedd modd dadgryptio copi wrth gefn gyda'r Allwedd Adfer hon: gwiriwch eich bod wedi rhoi'r Allwedd Adfer cywir.", + "recovery_key_mismatch_title": "Dim cyfatebiaeth Allwedd Adfer", "restore_failed_error": "Methu adfer copi wrth gefn" }, "right_panel": { @@ -1763,40 +1773,40 @@ "files_button": "Ffeiliau", "pinned_messages": { "empty_description": "Dewiswch neges a dewiswch “%(pinAction)s” i'w chynnwys yma.", - "empty_title": "Piniwch negeseuon pwysig fel y gellir eu darganfod yn hawdd", + "empty_title": "Piniwch negeseuon pwysig fel y mae moddeu darganfod yn hawdd", "menu": "Agor dewislen", "release_announcement": { "close": "Iawn", - "description": "Dewch o hyd i'r holl negeseuon sydd wedi'u pinio yma. Rollover unrhyw neges a dewiswch \"Pin\" i'w hychwanegu.", + "description": "Dewch o hyd i'r holl negeseuon sydd wedi'u pinio yma. Rhedwch y cyrchwr dros unrhyw neges a dewiswch \"Pinio\" i'w hychwanegu.", "title": "Pob neges newydd wedi'u pinio" }, - "reply_thread": "Ymateb i a neges edau", + "reply_thread": "Ymateb i a neges edau", "unpin_all": { "button": "Dad-binio pob neges", - "content": "Gwnewch yn siŵr eich bod chi wir eisiau dileu'r holl negeseuon sydd wedi'u pinio. Ni ellir dadwneud y weithred hon.", + "content": "Gwnewch yn siŵr eich bod chi wir eisiau dileu'r holl negeseuon sydd wedi'u pinio. Nid oes modd dadwneud y weithred hon.", "title": "Dad-binio pob neges?" }, "view": "Gweld yn yr amserlen" }, "pinned_messages_button": "Negeseuon wedi'u pinio", "poll": { - "active_heading": "Polau gweithredol", - "empty_active": "Nid oes unrhyw bolau gweithredol yn yr ystafell hon", - "empty_active_load_more": "Nid oes unrhyw bolau gweithredol. Llwythwch fwy o arolygon barn ar gyfer y misoedd blaenorol", - "empty_past": "Nid oes polau yn y gorffennol yn yr ystafell hon", - "empty_past_load_more": "Nid oes unrhyw bolau yn y gorffennol. Llwythwch fwy o arolygon barn ar gyfer y misoedd blaenorol", + "active_heading": "Arolygon gweithredol", + "empty_active": "Nid oes unrhyw arolygon gweithredol yn yr ystafell hon", + "empty_active_load_more": "Nid oes unrhyw arolygon gweithredol. Llwythwch fwy o arolygon barn y misoedd blaenorol", + "empty_past": "Nid oes arolygon o'r gorffennol yn yr ystafell hon", + "empty_past_load_more": "Nid oes unrhyw arolygon o'r gorffennol. Llwythwch fwy o arolygon barn ar gyfer y misoedd blaenorol", "load_more": "Llwytho mwy o arolygon barn", - "loading": "Wrthi'n llwytho polau", - "past_heading": "Polau'r gorffennol", - "view_in_timeline": "Gweld y pôl yn y llinell amser", - "view_poll": "Gweld arolwg barn" + "loading": "Wrthi'n llwytho arolygon", + "past_heading": "Arolygon y gorffennol", + "view_in_timeline": "Gweld yr arolwg yn y llinell amser", + "view_poll": "Gweld yr arolwg" }, "polls_button": "Arolygon", "room_summary_card": { - "title": "Gwybodaeth ystafell" + "title": "Manylion yr ystafell" }, "thread_list": { - "context_menu_label": "Opsiynau edau" + "context_menu_label": "Dewisiadau edau" }, "video_room_chat": { "title": "Sgwrs" @@ -1805,9 +1815,9 @@ "room": { "3pid_invite_email_not_found_account": "Anfonwyd y gwahoddiad hwn at %(email)s nad yw'n gysylltiedig â'ch cyfrif", "3pid_invite_email_not_found_account_room": "Anfonwyd y gwahoddiad hwn i %(roomName)s at %(email)s nad yw'n gysylltiedig â'ch cyfrif", - "3pid_invite_error_description": "Dychwelwyd gwall (%(errcode)s) wrth geisio dilysu'ch gwahoddiad. Gallech geisio trosglwyddo’r wybodaeth hon i’r sawl a’ch gwahoddodd.", + "3pid_invite_error_description": "Cafwyd gwall (%(errcode)s) wrth geisio dilysu'ch gwahoddiad. Gallech geisio trosglwyddo’r wybodaeth hon i’r sawl sydd wedi’ch gwahoddodd.", "3pid_invite_error_invite_action": "Ceisiwch ymuno beth bynnag", - "3pid_invite_error_invite_subtitle": "Dim ond gyda gwahoddiad gweithio y gallwch ymuno ag ef.", + "3pid_invite_error_invite_subtitle": "Dim ond gyda gwahoddiad sy'ngweithio y gallwch ymuno ag ef.", "3pid_invite_error_public_subtitle": "Gallwch chi ymuno yma o hyd.", "3pid_invite_error_title": "Aeth rhywbeth o'i le gyda'ch gwahoddiad.", "3pid_invite_error_title_room": "Aeth rhywbeth o'i le gyda'ch gwahoddiad i %(roomName)s", @@ -1817,37 +1827,37 @@ "context_menu": { "copy_link": "Copïo dolen ystafell", "favourite": "Ffefryn", - "forget": "Anghofiwch Ystafell", + "forget": "Anghofio'r Ystafell", "low_priority": "Blaenoriaeth Isel", - "mark_read": "Nodi fel wedi'i ddarllen", - "mark_unread": "Marciwch fel heb ei ddarllen", + "mark_read": "Marcio fel wedi'i ddarllen", + "mark_unread": "Marcio fel heb ei ddarllen", "notifications_default": "Cydweddu'r gosodiad rhagosodedig", "notifications_mute": "Tewi ystafell", - "title": "Opsiynau ystafell", + "title": "Dewisiadau ystafell", "unfavourite": "Ffafrio" }, - "creating_room_text": "Rydym yn creu ystafell gyda %(names)s", + "creating_room_text": "Rydym yn creu ystafell gyda %(materes)s", "dm_invite_action": "Dechrau sgwrsio", - "dm_invite_subtitle": "eisiau sgwrsio", + "dm_invite_subtitle": "Mae eisiau sgwrsio", "dm_invite_title": "Ydych chi eisiau sgwrsio gyda %(user)s?", - "drop_file_prompt": "Gollwng ffeil yma i uwchlwytho", + "drop_file_prompt": "Gollwng ffeil yma i'w llwytho", "edit_topic": "Golygu pwnc", "error_3pid_invite_email_lookup": "Methu dod o hyd i ddefnyddiwr trwy e-bost", - "error_cancel_knock_title": "Wedi methu â chanslo", + "error_cancel_knock_title": "Wedi methu â diddymu", "error_join_403": "Mae angen gwahoddiad arnoch i gael mynediad i'r ystafell hon.", - "error_join_404_1": "Fe wnaethoch chi geisio ymuno gan ddefnyddio ID ystafell heb ddarparu rhestr o weinyddion i ymuno â nhw. Dynodwyr mewnol yw rhifau adnabod ystafelloedd ac ni ellir eu defnyddio i ymuno ag ystafell heb wybodaeth ychwanegol.", + "error_join_404_1": "Fe wnaethoch chi geisio ymuno gan ddefnyddio ID ystafell heb ddarparu rhestr o weinyddion i ymuno â nhw. Dynodwyr mewnol yw rhifau adnabod ystafelloedd ac nid oes modd eu defnyddio i ymuno ag ystafell heb fanylion ychwanegol.", "error_join_404_2": "Os ydych chi'n gwybod cyfeiriad ystafell, ceisiwch ymuno trwy hwnnw yn lle.", "error_join_404_invite": "Mae'r person a'ch gwahoddodd eisoes wedi gadael, neu mae ei weinydd all-lein.", "error_join_404_invite_same_hs": "Mae'r person a'ch gwahoddodd eisoes wedi gadael.", "error_join_connection": "Bu gwall wrth ymuno.", - "error_join_incompatible_version_1": "Mae'n ddrwg gennym, mae eich gweinydd cartref yn rhy hen i gymryd rhan yma.", + "error_join_incompatible_version_1": "Ymddiheuriadau, mae eich gweinydd cartref yn rhy hen i gymryd rhan yma.", "error_join_incompatible_version_2": "Cysylltwch â gweinyddwr eich gweinydd cartref.", "error_join_title": "Wedi methu ag ymuno", "error_jump_to_date": "Dychwelodd y gweinydd %(statusCode)s gyda chod gwall %(errorCode)s", - "error_jump_to_date_connection": "Digwyddodd gwall rhwydwaith wrth geisio canfod a neidio i'r dyddiad a roddwyd. Mae'n bosibl bod eich gweinydd cartref i lawr neu fod problem dros dro gyda'ch cysylltiad rhyngrwyd. Ceisiwch eto. Os bydd hyn yn parhau, cysylltwch â gweinyddwr eich gweinyddwr cartref.", + "error_jump_to_date_connection": "Digwyddodd gwall rhwydwaith wrth geisio canfod a mynd i'r dyddiad a roddwyd. Mae'n bosibl bod eich gweinydd cartref i lawr neu fod problem dros dro gyda'ch cysylltiad rhyngrwyd. Ceisiwch eto. Os bydd hyn yn parhau, cysylltwch â gweinyddwr eich gweinyddwr cartref.", "error_jump_to_date_details": "Manylion gwall", "error_jump_to_date_not_found": "Nid oeddem yn gallu dod o hyd i ddigwyddiad yn edrych ymlaen o %(dateString)s. Ceisiwch ddewis dyddiad cynharach.", - "error_jump_to_date_send_logs_prompt": "Cyflwynwch os gwelwch yn dda logiau dadfygio i'n helpu i ddod o hyd i'r broblem.", + "error_jump_to_date_send_logs_prompt": "Cyflwynwch logiau dadfygio i'n helpu i ddod o hyd i'r broblem.", "error_jump_to_date_title": "Methu dod o hyd i ddigwyddiad ar y dyddiad hwnnw", "face_pile_tooltip_shortcut": "Gan gynnwys %(commaSeparatedMembers)s", "face_pile_tooltip_shortcut_joined": "Gan eich cynnwys chi, %(commaSeparatedMembers)s", @@ -1859,37 +1869,37 @@ }, "header_avatar_open_settings_label": "Agor gosodiadau ystafell", "header_face_pile_tooltip": "Pobl", - "header_untrusted_label": "Anymddiried", + "header_untrusted_label": "Dim ymddiriedaeth", "inaccessible": "Nid yw'r ystafell neu'r gofod hwn yn hygyrch ar hyn o bryd.", "inaccessible_name": "Nid yw %(roomName)s yn hygyrch ar hyn o bryd.", "inaccessible_subtitle_1": "Ceisiwch eto yn nes ymlaen, neu gofynnwch i weinyddwr ystafell neu ofod wirio a oes gennych fynediad.", - "inaccessible_subtitle_2": "Cafodd %(errcode)s ei ddychwelyd wrth geisio cael mynediad i'r ystafell neu'r gofod. Os ydych yn meddwl eich bod yn gweld y neges hon ar gam, os gwelwch yn dda cyflwyno adroddiad nam .", + "inaccessible_subtitle_2": "Cafodd %(errcode)s ei ddychwelyd wrth geisio cael mynediad i'r ystafell neu'r gofod. Os ydych yn meddwl eich bod yn gweld y neges hon ar gam, cyflwynwch adroddiad gwall.", "intro": { "dm_caption": "Dim ond y ddau ohonoch sydd yn y sgwrs hon, oni bai bod y naill neu'r llall ohonoch yn gwahodd unrhyw un i ymuno.", - "enable_encryption_prompt": "Galluogi amgryptio mewn gosodiadau.", + "enable_encryption_prompt": "Galluogi amgryptio yn y gosodiadau.", "encrypted_3pid_dm_pending_join": "Unwaith y bydd pawb wedi ymuno, byddwch yn gallu sgwrsio", "no_avatar_label": "Ychwanegwch lun, fel bod pobl yn gallu gweld eich ystafell yn hawdd.", "no_topic": "Ychwanegwch bwnc i helpu pobl i wybod beth yw ei ddiben.", "private_unencrypted_warning": "Mae eich negeseuon preifat yn cael eu hamgryptio fel arfer, ond nid yw'r ystafell hon. Fel arfer mae hyn oherwydd bod dyfais neu ddull heb ei gefnogi yn cael ei ddefnyddio, fel gwahoddiadau e-bost.", "room_invite": "Gwahoddiad i'r ystafell hon yn unig", - "send_message_start_dm": "Anfonwch eich neges gyntaf i wahodd i sgwrsio", - "start_of_dm_history": "Dyma ddechrau eich hanes neges uniongyrchol gyda .", - "start_of_room": "Dyma ddechrau .", + "send_message_start_dm": "Anfonwch eich neges gyntaf i wahodd i sgwrsio", + "start_of_dm_history": "Dyma ddechrau eich hanes neges uniongyrchol gyda .", + "start_of_room": "Dyma ddechrau .", "topic": "Pwnc: %(topic)s ", "topic_edit": "Pwnc: %(topic)s ( golygu )", - "unencrypted_warning": "Nid yw amgryptio o un pen i'r llall wedi'i alluogi", + "unencrypted_warning": "Nid yw amgryptio pen-i-ben wedi'i alluogi", "user_created": "Creodd %(displayName)s yr ystafell hon.", - "you_created": "Rydych chi wedi creu'r ystafell hon." + "you_created": "Chi sydd wedi creu'r ystafell hon." }, "invite_email_mismatch_suggestion": "Rhannwch yr e-bost hwn yn y Gosodiadau i dderbyn gwahoddiadau yn uniongyrchol yn %(brand)s.", "invite_reject_ignore": "Gwrthod ac Anwybyddu defnyddiwr", "invite_sent_to_email": "Anfonwyd y gwahoddiad hwn at %(email)s", "invite_sent_to_email_room": "Anfonwyd y gwahoddiad hwn i %(roomName)s at %(email)s", - "invite_subtitle": "Gwahoddwyd gan", + "invite_subtitle": "Gwahoddwyd gan ", "invite_this_room": "Gwahoddiad i'r ystafell hon", "invite_title": "Ydych chi am ymuno â %(roomName)s?", "inviter_unknown": "Anhysbys", - "invites_you_text": "yn eich gwahodd", + "invites_you_text": "Mae yn eich gwahodd", "join_button_account": "Cofrestru", "join_failed_needs_invite": "I weld %(roomName)s, mae angen gwahoddiad arnoch chi", "join_the_discussion": "Ymunwch â'r drafodaeth", @@ -1898,26 +1908,26 @@ "joining": "Wrthi'n ymuno…", "joining_room": "Wrthi'n ymuno â'r ystafell…", "joining_space": "Wrthi'n ymuno â'r gofod…", - "jump_read_marker": "Neidio i'r neges gyntaf heb ei darllen.", + "jump_read_marker": "Symud i'r neges gyntaf heb ei darllen.", "jump_to_bottom_button": "Sgroliwch i'r negeseuon mwyaf diweddar", - "jump_to_date": "Neidio hyd yma", + "jump_to_date": "Symud i ddyddiad", "jump_to_date_beginning": "Dechreuad yr ystafell", - "jump_to_date_prompt": "Dewiswch ddyddiad i neidio iddo", + "jump_to_date_prompt": "Dewiswch ddyddiad i fynd iddo", "kick_reason": "Rheswm: %(reason)s", "kicked_by": "Cawsoch eich tynnu gan %(memberName)s", "kicked_from_room_by": "Cawsoch eich tynnu o %(roomName)s gan %(memberName)s", - "knock_cancel_action": "Canslo cais", - "knock_denied_subtitle": "Gan nad ydych wedi cael mynediad, ni allwch ailymuno oni bai eich bod yn cael gwahoddiad gan weinyddwr neu gymedrolwr y grŵp.", + "knock_cancel_action": "Diddymu cais", + "knock_denied_subtitle": "Gan nad ydych wedi cael mynediad, allwch chi ddim ailymuno oni bai eich bod yn cael gwahoddiad gan weinyddwr neu gymedrolwr y grŵp.", "knock_denied_title": "Gwrthodwyd mynediad i chi", "knock_message_field_placeholder": "Neges (dewisol)", "knock_prompt": "Gofyn i ymuno?", "knock_prompt_name": "Gofyn i ymuno â %(roomName)s?", "knock_send_action": "Gofyn am fynediad", "knock_sent": "Anfonwyd y cais i ymuno", - "knock_sent_subtitle": "Mae eich cais i ymuno yn yr arfaeth.", + "knock_sent_subtitle": "Mae eich cais i ymuno yn yr aros.", "knock_subtitle": "Mae angen i chi gael mynediad i'r ystafell hon er mwyn gweld neu gymryd rhan yn y sgwrs. Gallwch anfon cais i ymuno isod.", "leave_error_title": "Gwall wrth adael yr ystafell", - "leave_server_notices_description": "Defnyddir yr ystafell hon ar gyfer negeseuon pwysig o'r Homeserver, felly ni allwch ei gadael.", + "leave_server_notices_description": "Mae'r ystafell hon yn cael ei defnyddio ar gyfer negeseuon pwysig o'r Homeserver, felly allwch chi ddim ei gadael.", "leave_server_notices_title": "Methu â gadael ystafell Hysbysiadau Gweinydd", "leave_unexpected_error": "Gwall gweinydd annisgwyl wrth geisio gadael yr ystafell", "link_email_to_receive_3pid_invite": "Cysylltwch yr e-bost hwn â'ch cyfrif yn y Gosodiadau i dderbyn gwahoddiadau yn uniongyrchol yn %(brand)s.", @@ -1934,7 +1944,7 @@ "button_view_all": "Gweld popeth", "description": "Mae negeseuon wedi'u pinio yn yr ystafell hon. Cliciwch i'w gweld.", "go_to_message": "Gweld y neges sydd wedi'i phinnio yn y llinell amser.", - "title": "%(index)s o %(length)s Negeseuon wedi'u pinio" + "title": "%(index)s o %(length)s Neges wedi'u pinio" }, "read_topic": "Cliciwch i ddarllen y pwnc", "rejecting": "Wrthi'n gwrthod gwahoddiad…", @@ -1946,13 +1956,13 @@ }, "status_bar": { "delete_all": "Dileu popeth", - "exceeded_resource_limit": "Ni anfonwyd eich neges oherwydd bod y gweinydd cartref hwn wedi mynd y tu hwnt i'r terfyn adnoddau. Cysylltwch â gweinyddwr eich gwasanaeth i barhau i ddefnyddio'r gwasanaeth.", - "homeserver_blocked": "Ni anfonwyd eich neges oherwydd bod y gweinydd cartref hwn wedi'i rwystro gan ei weinyddwr. Cysylltwch â gweinyddwr eich gwasanaeth i barhau i ddefnyddio'r gwasanaeth.", - "monthly_user_limit_reached": "Ni anfonwyd eich neges oherwydd bod y gweinydd cartref hwn wedi cyrraedd ei Derfyn Defnyddiwr Gweithredol Misol. Cysylltwch â gweinyddwr eich gwasanaeth i barhau i ddefnyddio'r gwasanaeth.", - "requires_consent_agreement": "Ni allwch anfon unrhyw negeseuon nes i chi adolygu a chytuno i ein telerau ac amodau .", + "exceeded_resource_limit": "Heb anfon eich neges oherwydd bod y gweinydd cartref hwn wedi mynd y tu hwnt i'r terfyn adnoddau. Cysylltwch â gweinyddwr eich gwasanaeth i barhau i ddefnyddio'r gwasanaeth.", + "homeserver_blocked": "Heb anfon eich neges oherwydd bod y gweinydd cartref hwn wedi'i rwystro gan ei weinyddwr. Cysylltwch â gweinyddwr eich gwasanaeth i barhau i ddefnyddio'r gwasanaeth.", + "monthly_user_limit_reached": "Heb anfoneich neges oherwydd bod y gweinydd cartref hwn wedi cyrraedd ei Derfyn Defnyddiwr Gweithredol Misol. Cysylltwch â gweinyddwr eich gwasanaeth i barhau i ddefnyddio'r gwasanaeth.", + "requires_consent_agreement": "Allwch chi ddim anfon unrhyw negeseuon nes i chi adolygu a chytuno i ein telerau ac amodau.", "retry_all": "Rhowch gynnig arall arni", "select_messages_to_retry": "Gallwch ddewis pob neges neu neges unigol i roi cynnig arall arni neu ei dileu", - "server_connectivity_lost_description": "Bydd negeseuon a anfonir yn cael eu storio nes bod eich cysylltiad wedi dychwelyd.", + "server_connectivity_lost_description": "Bydd negeseuon sy'n cael eu hanfon yn cael eu storio nes bod eich cysylltiad wedi dychwelyd.", "server_connectivity_lost_title": "Mae cysylltedd â'r gweinydd wedi'i golli.", "some_messages_not_sent": "Nid yw rhai o'ch negeseuon wedi'u hanfon" }, @@ -1961,26 +1971,36 @@ "upgrade_error_title": "Gwall wrth uwchraddio'r ystafell", "upgrade_warning_bar": "Bydd uwchraddio'r ystafell hon yn cau enghraifft bresennol yr ystafell ac yn creu ystafell wedi'i huwchraddio gyda'r un enw.", "upgrade_warning_bar_admins": "Dim ond gweinyddwyr ystafell fydd yn gweld y rhybudd hwn", - "upgrade_warning_bar_unstable": "Mae'r ystafell hon yn fersiwn ystafell redeg , y mae'r gweinydd cartref hwn wedi'i nodi'n ansefydlog .", + "upgrade_warning_bar_unstable": "Mae'r ystafell hon yn fersiwn ystafell redeg , y mae'r gweinydd cartref hwn wedi'i nodi'n ansefydlog.", "upgrade_warning_bar_upgraded": "Mae'r ystafell hon eisoes wedi'i huwchraddio.", "upload": { - "uploading_single_file": "Wrthi'n uwchlwytho %(filename)s" + "uploading_single_file": "Wrthi'n llwytho %(filematere)s" }, - "waiting_for_join_subtitle": "Unwaith y bydd defnyddwyr sydd wedi'u gwahodd wedi ymuno â %(brand)s, byddwch yn gallu sgwrsio a bydd yr ystafell yn cael ei hamgryptio o un pen i'r llall", - "waiting_for_join_title": "Aros i ddefnyddwyr ymuno â %(brand)s" + "waiting_for_join_subtitle": "Unwaith y bydd defnyddwyr sydd wedi'u gwahodd wedi ymuno â %(brand)s, byddwch yn gallu sgwrsio a bydd yr ystafell yn cael ei hamgryptio pen-i-ben", + "waiting_for_join_title": "Yn aros i ddefnyddwyr ymuno â %(brand)s" }, "room_list": { "add_room_label": "Ychwanegu ystafell", - "add_space_label": "Ychwanegu lle", + "add_space_label": "Ychwanegu gofod", "breadcrumbs_empty": "Dim ystafelloedd yr ymwelwyd â nhw yn ddiweddar", "breadcrumbs_label": "Ymwelwyd ag ystafelloedd yn ddiweddar", "failed_add_tag": "Wedi methu ag ychwanegu tag %(tagName)s i'r ystafell", "failed_remove_tag": "Wedi methu â thynnu'r tag %(tagName)s o'r ystafell", "failed_set_dm_tag": "Wedi methu gosod tag neges uniongyrchol", - "home_menu_label": "Opsiynau cartref", + "filters": { + "favourite": "Ffefrynnau", + "people": "Pobl", + "rooms": "Ystafelloedd", + "unread": "Heb ei ddarllen" + }, + "home_menu_label": "Dewisiadau cartref", "join_public_room_label": "Ymunwch â'r ystafell gyhoeddus", - "notification_options": "Opsiynau hysbysu", + "list_title": "Rhestr ystafelloedd", + "notification_options": "Dewisiadau hysbysu", "open_space_menu": "Agor dewislen gofod", + "room": { + "open_room": "Agor ystafell %(roomName)s" + }, "show_less": "Dangos llai", "show_previews": "Dangos rhagolwg o negeseuon", "sort_by": "Trefnu yn ôl", @@ -1992,8 +2012,8 @@ "space_settings": "Gosodiadau Gofod" }, "space_menu_label": "Dewislen %(spaceName)s", - "sublist_options": "Rhestrwch opsiynau", - "suggested_rooms_heading": "Ystafelloedd a Awgrymir" + "sublist_options": "Rhestrwch dewisiadau", + "suggested_rooms_heading": "Awgrym o Ystafelloedd" }, "room_settings": { "access": { @@ -2003,48 +2023,48 @@ "advanced": { "error_upgrade_description": "Ni fu modd cwblhau'r uwchraddio ystafell", "error_upgrade_title": "Wedi methu ag uwchraddio'r ystafell", - "information_section_room": "Gwybodaeth ystafell", - "information_section_space": "Gwybodaeth gofod", + "information_section_room": "Manylion ystafell", + "information_section_space": "Manylion gofod", "room_id": "ID ystafell fewnol", "room_predecessor": "Gweld negeseuon hŷn yn %(roomName)s.", - "room_upgrade_button": "Uwchraddio'r ystafell hon i'r fersiwn ystafell a argymhellir", + "room_upgrade_button": "Uwchraddio'r ystafell hon i'r fersiwn ystafell sy'n cael ei hargymell", "room_upgrade_warning": "Rhybudd : ni fydd uwchraddio ystafell yn mudo aelodau ystafell yn awtomatig i fersiwn newydd yr ystafell. Byddwn yn postio dolen i'r ystafell newydd yn yr hen fersiwn o'r ystafell - bydd yn rhaid i aelodau'r ystafell glicio ar y ddolen hon i ymuno â'r ystafell newydd.", "room_version": "Fersiwn ystafell:", "room_version_section": "Fersiwn ystafell", "space_predecessor": "Gweld fersiwn hŷn o %(spaceName)s.", - "space_upgrade_button": "Uwchraddio'r gofod hwn i'r fersiwn ystafell a argymhellir", - "unfederated": "Nid yw gweinyddion Matrix o bell yn hygyrch i'r ystafell hon", + "space_upgrade_button": "Uwchraddio'r gofod hwn i'r fersiwn ystafell sy'n cael ei hargymell", + "unfederated": "Nid yw gweinyddion Matrix pell yn hygyrch i'r ystafell hon", "upgrade_button": "Uwchraddio'r ystafell hon i fersiwn %(version)s", "upgrade_dialog_description": "Mae uwchraddio'r ystafell hon yn gofyn am gau'r enghraifft bresennol o'r ystafell a chreu ystafell newydd yn ei lle. Er mwyn rhoi’r profiad gorau posibl i aelodau’r ystafell, byddwn yn:", - "upgrade_dialog_description_1": "Creu ystafell newydd gyda'r un enw, disgrifiad ac avatar", + "upgrade_dialog_description_1": "Creu ystafell newydd gyda'r un enw, disgrifiad ac afatar", "upgrade_dialog_description_2": "Diweddarwch unrhyw arallenwau ystafell leol i bwyntio at yr ystafell newydd", "upgrade_dialog_description_3": "Atal defnyddwyr rhag siarad yn yr hen fersiwn o'r ystafell, a phostio neges yn cynghori defnyddwyr i symud i'r ystafell newydd", "upgrade_dialog_description_4": "Rhowch ddolen yn ôl i'r hen ystafell ar ddechrau'r ystafell newydd er mwyn i bobl allu gweld hen negeseuon", - "upgrade_dialog_title": "Uwchraddio Fersiwn Ystafell", - "upgrade_dwarning_ialog_title_public": "Uwchraddio ystafell gyhoeddus", - "upgrade_warning_dialog_description": "Mae uwchraddio ystafell yn gam gweithredu datblygedig ac fe'i argymhellir fel arfer pan fydd ystafell yn ansefydlog oherwydd bygiau, nodweddion coll neu wendidau diogelwch.", - "upgrade_warning_dialog_explainer": "Sylwch y bydd uwchraddio yn gwneud fersiwn newydd o'r ystafell . Bydd yr holl negeseuon cyfredol yn aros yn yr ystafell hon sydd wedi'i harchifo.", - "upgrade_warning_dialog_footer": "Byddwch yn uwchraddio'r ystafell hon o i .", + "upgrade_dialog_title": "Uwchraddio'r Fersiwn Ystafell", + "upgrade_dwarning_ialog_title_public": "Uwchraddio'r ystafell gyhoeddus", + "upgrade_warning_dialog_description": "Mae uwchraddio ystafell yn gam gweithredu datblygedig ac mae'n cael ei argymell fel arfer pan fydd ystafell yn ansefydlog oherwydd bygiau, nodweddion coll neu wendidau diogelwch.", + "upgrade_warning_dialog_explainer": "Sylwch y bydd uwchraddio yn gwneud fersiwn newydd o'r ystafell. Bydd yr holl negeseuon cyfredol yn aros yn yr ystafell hon sydd wedi'i harchifo.", + "upgrade_warning_dialog_footer": "Byddwch yn uwchraddio'r ystafell hon o i .", "upgrade_warning_dialog_invite_label": "Gwahodd aelodau o'r ystafell hon i'r un newydd yn awtomatig", - "upgrade_warning_dialog_report_bug_prompt": "Mae hyn fel arfer ond yn effeithio ar sut mae'r ystafell yn cael ei phrosesu ar y gweinydd. Os ydych chi'n cael problemau gyda'ch %(brand)s, rhowch wybod am nam.", - "upgrade_warning_dialog_report_bug_prompt_link": "Mae hyn fel arfer ond yn effeithio ar sut mae'r ystafell yn cael ei phrosesu ar y gweinydd. Os ydych chi'n cael problemau gyda'ch %(brand)s , rhowch wybod am nam .", + "upgrade_warning_dialog_report_bug_prompt": "Mae hyn fel arfer ond yn effeithio ar sut mae'r ystafell yn cael ei phrosesu ar y gweinydd. Os ydych chi'n cael problemau gyda'ch %(brand)s, rhowch wybod am fater.", + "upgrade_warning_dialog_report_bug_prompt_link": "Mae hyn fel arfer ond yn effeithio ar sut mae'r ystafell yn cael ei phrosesu ar y gweinydd. Os ydych chi'n cael problemau gyda'ch %(brand)s , rhowch wybod am fater.", "upgrade_warning_dialog_title": "Uwchraddio ystafell", "upgrade_warning_dialog_title_private": "Uwchraddio ystafell breifat" }, "alias_not_specified": "heb ei nodi", "bridges": { - "description": "Mae'r ystafell hon yn pontio negeseuon i'r llwyfannau canlynol. Dysgwch fwy.", - "empty": "Nid yw'r ystafell hon yn pontio negeseuon i unrhyw lwyfannau. Dysgwch fwy.", + "description": "Mae'r ystafell hon yn pontio negeseuon i'r llwyfannau canlynol. Dysgu rhagor.", + "empty": "Nid yw'r ystafell hon yn pontio negeseuon i unrhyw lwyfannau. Dysgu rhagor.", "title": "Pontydd" }, - "delete_avatar_label": "Dileu avatar", + "delete_avatar_label": "Dileu afatar", "general": { "alias_field_has_domain_invalid": "Gwahanydd parth ar goll e.e. (:domain.org)", "alias_field_has_localpart_invalid": "Enw ystafell ar goll neu wahanydd e.e. (fy-ystafell:domain.org)", "alias_field_matches_invalid": "Nid yw'r cyfeiriad hwn yn pwyntio at yr ystafell hon", "alias_field_placeholder_default": "e.e. fy-ystafell", "alias_field_required_invalid": "Rhowch gyfeiriad", - "alias_field_safe_localpart_invalid": "Ni chaniateir rhai nodau", + "alias_field_safe_localpart_invalid": "Nid oes caniatâd i rai nodau", "alias_field_taken_invalid": "Roedd gan y cyfeiriad hwn weinydd annilys neu mae eisoes yn cael ei ddefnyddio", "alias_field_taken_invalid_domain": "Mae'r cyfeiriad hwn eisoes yn cael ei ddefnyddio", "alias_field_taken_valid": "Mae'r cyfeiriad hwn ar gael i'w ddefnyddio", @@ -2052,10 +2072,10 @@ "aliases_items_label": "Cyfeiriadau cyhoeddedig eraill:", "aliases_no_items_label": "Dim cyfeiriadau cyhoeddedig eraill eto, ychwanegwch un isod", "aliases_section": "Cyfeiriadau Ystafell", - "avatar_field_label": "Avatar ystafell", + "avatar_field_label": "Afatar ystafell", "canonical_alias_field_label": "Prif gyfeiriad", - "default_url_previews_off": "Mae rhagolygon URL wedi'u hanalluogi yn ddiofyn ar gyfer cyfranogwyr yn yr ystafell hon.", - "default_url_previews_on": "Mae rhagolygon URL wedi'u galluogi yn ddiofyn ar gyfer cyfranogwyr yn yr ystafell hon.", + "default_url_previews_off": "Mae rhagolygon URL wedi'u hanalluogi fel rhagosodiad ar gyfer cyfranogwyr yn yr ystafell hon.", + "default_url_previews_on": "Mae rhagolygon URL wedi'u galluogi fel rhagosodiad ar gyfer cyfranogwyr yn yr ystafell hon.", "description_space": "Golygu gosodiadau sy'n ymwneud â'ch gofod.", "error_creating_alias_description": "Bu gwall wrth greu'r cyfeiriad hwnnw. Mae'n bosib na chaiff ei ganiatáu gan y gweinydd neu fe ddigwyddodd methiant dros dro.", "error_creating_alias_title": "Gwall wrth greu cyfeiriad", @@ -2064,11 +2084,11 @@ "error_deleting_alias_title": "Gwall wrth dynnu'r cyfeiriad", "error_publishing": "Methu cyhoeddi ystafell", "error_publishing_detail": "Bu gwall wrth gyhoeddi'r ystafell hon", - "error_save_space_settings": "Wedi methu ag arbed gosodiadau gofod.", - "error_updating_alias_description": "Bu gwall wrth ddiweddaru cyfeiriadau amgen yr ystafell. Mae'n bosib na chaiff ei ganiatáu gan y gweinydd neu fe ddigwyddodd methiant dros dro.", + "error_save_space_settings": "Wedi methu cadw gosodiadau'r gofod.", + "error_updating_alias_description": "Bu gwall wrth ddiweddaru cyfeiriadau arall yr ystafell. Mae'n bosib na chaiff ei ganiatáu gan y gweinydd neu fe ddigwyddodd methiant dros dro.", "error_updating_canonical_alias_description": "Bu gwall wrth ddiweddaru prif gyfeiriad yr ystafell. Mae'n bosib na chaiff ei ganiatáu gan y gweinydd neu fe ddigwyddodd methiant dros dro.", "error_updating_canonical_alias_title": "Gwall wrth ddiweddaru'r prif gyfeiriad", - "leave_space": "Gadael Gofod", + "leave_space": "Gadael y Gofod", "local_alias_field_label": "Cyfeiriad lleol", "local_aliases_explainer_room": "Gosodwch gyfeiriadau ar gyfer yr ystafell hon fel y gall defnyddwyr ddod o hyd i'r ystafell hon trwy eich gweinydd cartref (%(localDomain)s)", "local_aliases_explainer_space": "Gosodwch gyfeiriadau ar gyfer y gofod hwn fel y gall defnyddwyr ddod o hyd i'r gofod hwn trwy eich gweinydd cartref (%(localDomain)s)", @@ -2082,32 +2102,32 @@ "published_aliases_description": "I gyhoeddi cyfeiriad, mae angen ei osod fel cyfeiriad lleol yn gyntaf.", "published_aliases_explainer_room": "Gall unrhyw un ar unrhyw weinydd ddefnyddio cyfeiriadau cyhoeddedig i ymuno â'ch ystafell.", "published_aliases_explainer_space": "Gall unrhyw un ar unrhyw weinydd ddefnyddio cyfeiriadau cyhoeddedig i ymuno â'ch gofod.", - "published_aliases_section": "Anerchiadau Cyhoeddedig", + "published_aliases_section": "Cyfeiriadau Cyhoeddedig", "save": "Cadw'r Newidiadau", "topic_field_label": "Pwnc yr Ystafell", - "url_preview_encryption_warning": "Mewn ystafelloedd wedi'u hamgryptio, fel yr un hon, mae rhagolygon URL yn cael eu hanalluogi yn ddiofyn i sicrhau na all eich gweinydd cartref (lle mae'r rhagolygon yn cael eu cynhyrchu) gasglu gwybodaeth am ddolenni a welwch yn yr ystafell hon.", - "url_preview_explainer": "Pan fydd rhywun yn rhoi URL yn eu neges, gellir dangos rhagolwg URL i roi mwy o wybodaeth am y ddolen honno fel y teitl, disgrifiad, a delwedd o'r wefan.", + "url_preview_encryption_warning": "Mewn ystafelloedd wedi'u hamgryptio, fel yr un hon, mae rhagolygon URL yn cael eu hanalluogi fel rhagosodiad i sicrhau na all eich gweinydd cartref (lle mae'r rhagolygon yn cael eu cynhyrchu) gasglu gwybodaeth am ddolenni welwch yn yr ystafell hon.", + "url_preview_explainer": "Pan fydd rhywun yn rhoi URL yn eu neges, mae modd dangos rhagolwg URL i roi mwy o wybodaeth am y ddolen honno fel y teitl, disgrifiad, a delwedd o'r wefan.", "url_previews_section": "Rhagolygon URL", - "user_url_previews_default_off": "Rydych wedi analluogi rhagolygon URL yn ddiofyn.", - "user_url_previews_default_on": "Rydych chi wedi galluogi rhagolygon URL yn ddiofyn." + "user_url_previews_default_off": "Rydych wedi analluogi rhagolygon URL fel rhagosodiad.", + "user_url_previews_default_on": "Rydych chi wedi galluogi rhagolygon URL fel rhagosodiad." }, "notifications": { "browse_button": "Pori", - "custom_sound_prompt": "Gosod sain arferiad newydd", + "custom_sound_prompt": "Gosod sain cyfaddas newydd", "notification_sound": "Sain hysbysu", - "settings_link": "Sicrhewch hysbysiadau fel y'u gosodwyd yn eich gosodiadau", + "settings_link": "Cael hysbysiadau fel wedi'u gosod yn eich gosodiadau", "sounds_section": "Seiniau", "upload_sound_label": "Llwythwch i fyny sain personol", - "uploaded_sound": "Sain wedi'i uwchlwytho" + "uploaded_sound": "Sain wedi'i lwytho" }, "people": { "knock_empty": "Dim ceisiadau", "knock_section": "Yn gofyn i ymuno", "see_less": "Gweld llai", - "see_more": "Gweld rhagor" + "see_more": "Gweld mwy" }, "permissions": { - "add_privileged_user_description": "Rhowch ragor o freintiau i un neu fwy o ddefnyddwyr yn yr ystafell hon", + "add_privileged_user_description": "Rhoi rhagor o freintiau i un neu fwy o ddefnyddwyr yn yr ystafell hon", "add_privileged_user_filter_placeholder": "Chwilio defnyddwyr yn yr ystafell hon…", "add_privileged_user_heading": "Ychwanegu defnyddwyr breintiedig", "ban": "Gwahardd defnyddwyr", @@ -2125,8 +2145,8 @@ "m.call": "Dechrau %(brand)s galwad", "m.call.member": "Ymuno â galwadau %(brand)s", "m.reaction": "Anfon adweithiau", - "m.room.avatar": "Newid avatar ystafell", - "m.room.avatar_space": "Newid avatar gofod", + "m.room.avatar": "Newid afatar ystafell", + "m.room.avatar_space": "Newid afatar gofod", "m.room.canonical_alias": "Newid prif gyfeiriad yr ystafell", "m.room.canonical_alias_space": "Newid prif gyfeiriad y gofod", "m.room.encryption": "Galluogi amgryptio ystafell", @@ -2134,8 +2154,8 @@ "m.room.name": "Newid enw'r ystafell", "m.room.name_space": "Newid enw gofod", "m.room.pinned_events": "Rheoli digwyddiadau wedi'u pinio", - "m.room.power_levels": "Newid caniatadau", - "m.room.redaction": "Dileu negeseuon a anfonwyd gennyf", + "m.room.power_levels": "Newid caniatâd", + "m.room.redaction": "Dileu negeseuon anfonwyd gennyf", "m.room.server_acl": "Newid ACLs gweinydd", "m.room.tombstone": "Uwchraddio'r ystafell", "m.room.topic": "Newid pwnc", @@ -2153,19 +2173,19 @@ "send_event_type": "Anfon %(eventType)s digwyddiad", "state_default": "Newid gosodiadau", "title": "Rolau a Chaniatadau", - "users_default": "Rôl ddiofyn" + "users_default": "Rôl rhagosodedig" }, "security": { - "enable_encryption_confirm_description": "Unwaith y bydd wedi'i alluogi, ni ellir analluogi amgryptio ar gyfer ystafell. Ni all y gweinydd weld negeseuon a anfonir mewn ystafell wedi'i hamgryptio, dim ond cyfranogwyr yr ystafell. Gall galluogi amgryptio atal llawer o bots a phontydd rhag gweithio'n gywir. Dysgwch fwy am amgryptio.", + "enable_encryption_confirm_description": "Unwaith y bydd wedi'i alluogi, nid oes modd analluogi amgryptio ar gyfer ystafell. Fydd y gweinydd ddim yn gallu gweld negeseuon wedi'u hanfon mewn ystafell wedi'i hamgryptio, dim ond cyfranogwyr yr ystafell. Gall galluogi amgryptio atal llawer o botiau a phontydd rhag gweithio'n gywir. Dysgu rhagor am amgryptio.", "enable_encryption_confirm_title": "Galluogi amgryptio?", - "enable_encryption_public_room_confirm_description_1": "Nid yw'n cael ei argymell i ychwanegu amgryptio i ystafelloedd cyhoeddus. Gall unrhyw un ddod o hyd i ystafelloedd cyhoeddus ac ymuno â nhw, felly gall unrhyw un ddarllen negeseuon ynddynt. Ni chewch unrhyw un o fanteision amgryptio, ac ni fyddwch yn gallu ei ddiffodd yn ddiweddarach. Bydd amgryptio negeseuon mewn ystafell gyhoeddus yn gwneud derbyn ac anfon negeseuon yn arafach.", - "enable_encryption_public_room_confirm_description_2": "Er mwyn osgoi'r problemau hyn, crëwch ystafell wedi'i hamgryptio newydd ar gyfer y sgwrs rydych chi'n bwriadu ei chael.", + "enable_encryption_public_room_confirm_description_1": "Nid yw'n cael ei argymell i ychwanegu amgryptio i ystafelloedd cyhoeddus. Gall unrhyw un ddod o hyd i ystafelloedd cyhoeddus ac ymuno â nhw, felly gall unrhyw un ddarllen negeseuon ynddynt. Chewch chi ddim unrhyw un o fanteision amgryptio, nac yn gallu ei ddiffodd yn ddiweddarach. Bydd amgryptio negeseuon mewn ystafell gyhoeddus yn gwneud derbyn ac anfon negeseuon yn arafach.", + "enable_encryption_public_room_confirm_description_2": "Er mwyn osgoi'r problemau hyn, crëwch ystafell newydd wedi'i hamgryptio ar gyfer y sgwrs rydych chi'n bwriadu ei chael.", "enable_encryption_public_room_confirm_title": "Ydych chi'n siŵr eich bod am ychwanegu amgryptio i'r ystafell gyhoeddus hon?", - "encrypted_room_public_confirm_description_1": "Nid yw'n cael ei argymell i wneud ystafelloedd wedi'u hamgryptio yn gyhoeddus. Bydd yn golygu y gall unrhyw un ddod o hyd i'r ystafell ac ymuno â hi, fel y gall unrhyw un ddarllen negeseuon. Ni chewch unrhyw un o fanteision amgryptio. Bydd amgryptio negeseuon mewn ystafell gyhoeddus yn gwneud derbyn ac anfon negeseuon yn arafach.", + "encrypted_room_public_confirm_description_1": "Nid yw'n cael ei argymell i wneud ystafelloedd wedi'u hamgryptio yn gyhoeddus. Bydd yn golygu y gall unrhyw un ddod o hyd i'r ystafell ac ymuno â hi, fel y gall unrhyw un ddarllen negeseuon. Chewch chi ddim o fanteision amgryptio. Bydd amgryptio negeseuon mewn ystafell gyhoeddus yn gwneud derbyn ac anfon negeseuon yn arafach.", "encrypted_room_public_confirm_description_2": "Er mwyn osgoi'r problemau hyn, crëwch ystafell gyhoeddus newydd ar gyfer y sgwrs rydych chi'n bwriadu ei chael.", "encrypted_room_public_confirm_title": "A ydych yn siŵr eich bod am wneud yr ystafell hon wedi'i hamgryptio yn gyhoeddus?", "encryption_forced": "Mae angen amgryptio ar eich gweinydd er mwyn ei analluogi.", - "encryption_permanent": "Unwaith y bydd wedi'i alluogi, ni ellir analluogi amgryptio.", + "encryption_permanent": "Unwaith y bydd wedi'i alluogi, nid oes modd analluogi amgryptio.", "error_join_rule_change_title": "Wedi methu â diweddaru'r rheolau ymuno", "error_join_rule_change_unknown": "Methiant anhysbys", "guest_access_warning": "Bydd pobl â chleientiaid a gefnogir yn gallu ymuno â'r ystafell heb fod â chyfrif cofrestredig.", @@ -2179,24 +2199,24 @@ "join_rule_invite": "Preifat (gwahoddiad yn unig)", "join_rule_invite_description": "Dim ond pobl wahoddedig all ymuno.", "join_rule_knock": "Gofynnwch i ymuno", - "join_rule_knock_description": "Ni all pobl ymuno oni bai bod mynediad yn cael ei ganiatáu.", + "join_rule_knock_description": "Gall pobl ddim ymuno oni bai bod mynediad yn cael ei ganiatáu.", "join_rule_public_description": "Gall unrhyw un ddod o hyd ac ymuno.", "join_rule_restricted": "Aelodau gofod", - "join_rule_restricted_description": "Gall unrhyw un mewn gofod ddod o hyd i ac ymuno. Golygwch pa fylchau sydd ar gael yma.", - "join_rule_restricted_description_active_space": "Unrhyw un i mewn yn gallu dod o hyd ac ymuno. Gallwch hefyd ddewis mannau eraill.", + "join_rule_restricted_description": "Gall unrhyw un mewn gofod ganfod ac ymuno. Golygu pa osodau sydd ar gael yma.", + "join_rule_restricted_description_active_space": "Gall unrhyw un yn allu dod o hyd ac ymuno. Gallwch hefyd ddewis ofodau eraill.", "join_rule_restricted_description_prompt": "Gall unrhyw un mewn gofod ddod o hyd i ac ymuno. Gallwch ddewis bylchau lluosog.", - "join_rule_restricted_description_spaces": "Mannau gyda mynediad", - "join_rule_restricted_dialog_description": "Penderfynwch pa ofodau all gael mynediad i'r ystafell hon. Os dewisir gofod, gall ei aelodau ddod o hyd i ac ymuno .", - "join_rule_restricted_dialog_empty_warning": "Rydych chi'n dileu pob gofod. Bydd mynediad yn ddiofyn i wahoddiad yn unig", - "join_rule_restricted_dialog_filter_placeholder": "Mannau chwilio", - "join_rule_restricted_dialog_heading_known": "Mannau eraill rydych chi'n eu hadnabod", - "join_rule_restricted_dialog_heading_other": "Mannau neu ystafelloedd eraill efallai nad ydych chi'n eu hadnabod", - "join_rule_restricted_dialog_heading_room": "Mannau y gwyddoch sy'n cynnwys yr ystafell hon", - "join_rule_restricted_dialog_heading_space": "Mannau y gwyddoch sy'n cynnwys y gofod hwn", - "join_rule_restricted_dialog_heading_unknown": "Mae'r rhain yn debygol o fod yn rhai y mae gweinyddwyr ystafell eraill yn rhan ohonynt.", + "join_rule_restricted_description_spaces": "Gofodau gyda mynediad", + "join_rule_restricted_dialog_description": "Penderfynwch pa ofodau all gael mynediad i'r ystafell hon. Os fydd gofod yn cael ei ddewis, gall ei aelodau ddod o hyd i iddo ac ymuno â .", + "join_rule_restricted_dialog_empty_warning": "Rydych chi'n dileu pob gofod. Bydd mynediad fel rhagosodiad i wahoddiad yn unig", + "join_rule_restricted_dialog_filter_placeholder": "Chwilio gofodau", + "join_rule_restricted_dialog_heading_known": "Gofodau eraill rydych chi'n eu hadnabod", + "join_rule_restricted_dialog_heading_other": "Gofodau neu ystafelloedd eraill efallai nad ydych chi'n eu hadnabod", + "join_rule_restricted_dialog_heading_room": "Gofodau rydych yn eu hadnabod sy'n cynnwys yr ystafell hon", + "join_rule_restricted_dialog_heading_space": "Gofodau rydych yn eu hadnabod sy'n cynnwys y gofod hwn", + "join_rule_restricted_dialog_heading_unknown": "Mae'r rhain yn debygol o fod yn rhai y mae gweinyddwyr ystafell eraill yn rhan ohonyn nhw.", "join_rule_restricted_dialog_title": "Dewiswch fylchau", "join_rule_restricted_upgrade_description": "Bydd yr uwchraddiad hwn yn caniatáu i aelodau o fannau penodol gael mynediad i'r ystafell hon heb wahoddiad.", - "join_rule_restricted_upgrade_warning": "Mae'r ystafell hon mewn rhai mannau nad ydych chi'n weinyddwr iddynt. Yn y mannau hynny, bydd yr hen ystafell yn dal i gael ei dangos, ond bydd pobl yn cael eu hannog i ymuno â'r un newydd.", + "join_rule_restricted_upgrade_warning": "Mae'r ystafell hon mewn rhai gofodau nad ydych chi'n weinyddwr iddynt. Yn y gofodau hynny, bydd yr hen ystafell yn dal i gael ei dangos, ond bydd pobl yn cael eu hannog i ymuno â'r un newydd.", "join_rule_upgrade_awaiting_room": "Wrthi'n llwytho ystafell newydd", "join_rule_upgrade_required": "Angen uwchraddio", "join_rule_upgrade_upgrading_room": "Ystafell uwchraddio", @@ -2207,34 +2227,34 @@ "title": "Diogelwch a Phreifatrwydd" }, "title": "Gosodiadau Ystafell - %(roomName)s", - "upload_avatar_label": "Uwchlwytho avatar", + "upload_avatar_label": "Llwytho afatar i fyny", "visibility": { "alias_section": "Cyfeiriad", "error_failed_save": "Wedi methu â diweddaru gwelededd y gofod hwn", "error_update_guest_access": "Wedi methu â diweddaru mynediad gwesteion y gofod hwn", "error_update_history_visibility": "Wedi methu â diweddaru gwelededd hanes y gofod hwn", "guest_access_explainer": "Gall gwesteion ymuno â gofod heb gyfrif.", - "guest_access_explainer_public_space": "Gall hyn fod yn ddefnyddiol ar gyfer mannau cyhoeddus.", + "guest_access_explainer_public_space": "Gall hyn fod yn ddefnyddiol ar gyfer gofodau cyhoeddus.", "guest_access_label": "Galluogi mynediad gwestai", "history_visibility_anyone_space": "Gofod Rhagolwg", "history_visibility_anyone_space_description": "Caniatáu i bobl gael rhagolwg o'ch gofod cyn iddynt ymuno.", - "history_visibility_anyone_space_recommendation": "Argymhellir ar gyfer mannau cyhoeddus.", + "history_visibility_anyone_space_recommendation": "Argymhellion ar gyfer gofodau cyhoeddus.", "title": "Gwelededd" }, "voip": { "call_type_section": "Math o alwad", - "enable_element_call_caption": "Mae %(brand)s wedi'i amgryptio o un pen i'r llall, ond ar hyn o bryd mae wedi'i gyfyngu i niferoedd llai o ddefnyddwyr.", + "enable_element_call_caption": "Mae %(brand)s wedi'i amgryptio pen-i-ben, ond ar hyn o bryd mae wedi'i gyfyngu i niferoedd llai o ddefnyddwyr.", "enable_element_call_label": "Galluogi %(brand)s fel opsiwn galw ychwanegol yn yr ystafell hon", "enable_element_call_no_permissions_tooltip": "Nid oes gennych ganiatâd digonol i newid hyn." } }, - "room_summary_card_back_action_label": "Gwybodaeth ystafell", + "room_summary_card_back_action_label": "Manylion ystafell", "scalar": { "error_create": "Methu creu teclyn.", - "error_membership": "Nid ydych chi yn yr ystafell hon.", + "error_membership": "Nid ydych yn yr ystafell hon.", "error_missing_room_id": "Id ystafell ar goll.", "error_missing_room_id_request": "ID room_ ar goll yn y cais", - "error_missing_user_id_request": "ID defnyddiwr_ar goll yn y cais", + "error_missing_user_id_request": "user_id ar goll yn y cais", "error_permission": "Nid oes gennych ganiatâd i wneud hynny yn yr ystafell hon.", "error_power_level_invalid": "Rhaid i lefel pŵer fod yn gyfanrif positif.", "error_room_not_visible": "Nid yw ystafell %(roomId)s yn weladwy", @@ -2249,24 +2269,24 @@ "description_2": "Mae eich wal dân neu'ch gwrth-feirws yn rhwystro'r cais.", "description_3": "Mae estyniad porwr yn atal y cais.", "description_4": "Mae'r gweinydd all-lein.", - "description_5": "Mae'r gweinydd wedi gwadu eich cais.", + "description_5": "Mae'r gweinydd wedi gwrthod eich cais.", "description_6": "Mae eich ardal yn cael anawsterau wrth gysylltu â'r rhyngrwyd.", "description_7": "Digwyddodd gwall cysylltu wrth geisio cysylltu â'r gweinydd.", "description_8": "Nid yw'r gweinydd wedi'i ffurfweddu i ddangos beth yw'r broblem (CORS).", - "empty_timeline": "Rydych chi i gyd wedi'ch dal i fyny.", + "empty_timeline": "Rydych chi'n gyfredol nawr.", "recent_changes_heading": "Newidiadau diweddar sydd heb eu derbyn eto", "title": "Nid yw'r gweinydd yn ymateb" }, "seshat": { - "error_initialising": "Ni fu modd cychwyn chwiliad neges, gwiriwch eich gosodiadau am ragor o wybodaeth", + "error_initialising": "Nid oedd modd cychwyn chwilio negeseuon, gwiriwch eich gosodiadau am ragor o wybodaeth", "reset_button": "Ailosod storfa digwyddiad", "reset_description": "Mae'n debyg nad ydych chi eisiau ailosod eich storfa mynegai digwyddiadau", "reset_explainer": "Os felly, nodwch na fydd unrhyw un o'ch negeseuon yn cael eu dileu, ond efallai y bydd y profiad chwilio yn cael ei ddiraddio am ychydig eiliadau tra bod y mynegai yn cael ei ail-greu", "reset_title": "Ailosod storfa digwyddiad?", "warning_kind_files": "Nid yw'r fersiwn hon o %(brand)s yn cefnogi gwylio rhai ffeiliau wedi'u hamgryptio", - "warning_kind_files_app": "Defnyddiwch yr app Penbwrdd i weld yr holl ffeiliau wedi'u hamgryptio", + "warning_kind_files_app": "Defnyddiwch yr ap Bwrdd Gwaith i weld yr holl ffeiliau wedi'u hamgryptio", "warning_kind_search": "Nid yw'r fersiwn hon o %(brand)s yn cefnogi chwilio negeseuon wedi'u hamgryptio", - "warning_kind_search_app": "Defnyddiwch yr ap Penbwrdd i chwilio am negeseuon wedi'u hamgryptio" + "warning_kind_search_app": "Defnyddiwch yr ap Bwrdd Gwaith i chwilio am negeseuon wedi'u hamgryptio" }, "setting": { "help_about": { @@ -2274,11 +2294,11 @@ "brand_version": "Fersiwn %(brand)s:", "clear_cache_reload": "Clirio'r storfa ac ail-lwytho", "crypto_version": "Fersiwn crypto:", - "dialog_title": "Gosodiadau: Help & About", - "help_link": "I gael help i ddefnyddio %(brand)s, cliciwch yma .", + "dialog_title": "Gosodiadau: Cymorth ac Ynghylch", + "help_link": "I gael help i ddefnyddio %(brand)s, cliciwch yma.", "homeserver": "Mae Homeserver yn %(homeserverUrl)s", "identity_server": "Y gweinydd adnabod yw %(identityServerUrl)s", - "title": "Help ac Amdano", + "title": "Cymorth ac Ynghylch", "versions": "Fersiynau" } }, @@ -2287,9 +2307,9 @@ "dialog_title": "Gosodiadau: Cyfrif", "title": "Cyfrif" }, - "all_rooms_home": "Dangoswch bob ystafell yn y Cartref", - "all_rooms_home_description": "Bydd pob ystafell rydych chi ynddi yn ymddangos yn Hafan.", - "always_show_message_timestamps": "Dangoswch stampiau amser neges bob amser", + "all_rooms_home": "Dangos bob ystafell yn y Cartref", + "all_rooms_home_description": "Bydd pob ystafell rydych chi ynddi yn ymddangos yn y Cartref.", + "always_show_message_timestamps": "Dangos stampiau amser neges bob amser", "appearance": { "bundled_emoji_font": "Defnyddiwch ffont emoji wedi'i bwndelu", "compact_layout": "Dangos testun cryno a negeseuon", @@ -2298,10 +2318,10 @@ "custom_font_description": "Gosodwch enw ffont sydd wedi'i osod ar eich system a bydd %(brand)s yn ceisio ei ddefnyddio.", "custom_font_name": "Enw ffont y system", "custom_font_size": "Defnyddio maint cyfaddas", - "custom_theme_add": "Ychwanegu thema wedi'i haddasu", - "custom_theme_downloading": "Wrthi'n lawrlwytho thema wedi'i haddasu…", - "custom_theme_error_downloading": "Gwall wrth lawrlwytho'r thema", - "custom_theme_help": "Rhowch URL thema arfer rydych chi am ei chymhwyso.", + "custom_theme_add": "Ychwanegu thema gyfaddas", + "custom_theme_downloading": "Wrthi'n llwytho i lawr thema cyfaddas…", + "custom_theme_error_downloading": "Gwall wrth lwytho'r thema i lawr", + "custom_theme_help": "Rhowch URL thema cyfaddas rydych chi am ei gosod.", "custom_theme_invalid": "Sgema thema annilys.", "dialog_title": "Gosodiadau: Ymddangosiad", "font_size": "Maint ffont", @@ -2318,8 +2338,8 @@ "autoplay_gifs": "Awtochwarae GIFs", "autoplay_videos": "Autoplay fideos", "big_emoji": "Galluogi emoji mawr yn y sgwrs", - "code_block_expand_default": "Ehangu blociau cod yn ddiofyn", - "code_block_line_numbers": "Dangoswch rifau llinell mewn blociau cod", + "code_block_expand_default": "Ehangu blociau cod fel rhagosodiad", + "code_block_line_numbers": "Dangos rifau llinell mewn blociau cod", "disable_historical_profile": "Dangos llun proffil cyfredol ac enw ar gyfer defnyddwyr yn hanes neges", "discovery": { "title": "Sut i ddod o hyd i chi" @@ -2337,12 +2357,14 @@ "breadcrumb_title_forgot": "Wedi anghofio eich allwedd adfer? Bydd angen i chi ailosod eich hunaniaeth.", "breadcrumb_warning": "Gwnewch hyn dim ond os ydych chi'n credu bod eich cyfrif wedi'i beryglu.", "details_title": "Manylion amgryptio", + "do_not_close_warning": "Peidiwch â chau'r ffenestr hon nes bod yr ailosod wedi'i orffen", "export_keys": "Allforio allweddi", "import_keys": "Mewnforio bysellau", "other_people_device_description": "Yn ragosodedig mewn ystafelloedd wedi'u hamgryptio, peidiwch ag anfon negeseuon wedi'u hamgryptio at unrhyw un nes i chi eu gwirio", "other_people_device_label": "Peidiwch byth ag anfon negeseuon wedi'u hamgryptio i ddyfeisiau heb eu gwirio", "other_people_device_title": "Dyfeisiau pobl eraill", "reset_identity": "Ailosod hunaniaeth cryptograffig", + "reset_in_progress": "Wrthi'n ailosod...", "session_id": "ID y sesiwn:", "session_key": "Allwedd sesiwn:", "title": "Uwch" @@ -2365,7 +2387,7 @@ "key_storage_warning": "Nid yw eich storfa allweddi wedi'i chysoni. Cliciwch ar y botwm isod i ddatrys y broblem.", "save_key_description": "Peidiwch â rhannu hwn gyda neb!", "save_key_title": "Allwedd adfer", - "set_up_recovery": "Sefydlu adferiad", + "set_up_recovery": "Gosodadferiad", "set_up_recovery_confirm_button": "Gorffen sefydlu", "set_up_recovery_confirm_description": "Rhowch yr allwedd adfer a ddangosir ar y sgrin flaenorol i orffen sefydlu adferiad.", "set_up_recovery_confirm_title": "Rhowch eich allwedd adfer i gadarnhau", @@ -2396,7 +2418,7 @@ "avatar_save_progress": "Wrthi'n uwchlwytho delwedd...", "avatar_upload_error_text": "Ni chefnogir fformat y ffeil neu mae'r ddelwedd yn fwy na %(size)s.", "avatar_upload_error_text_generic": "Mae'n bosibl na chefnogir fformat y ffeil.", - "avatar_upload_error_title": "Ni fu modd uwchlwytho delwedd avatar", + "avatar_upload_error_title": "Ni fu modd uwchlwytho delwedd afatar", "confirm_adding_email_body": "Cliciwch y botwm isod i gadarnhau ychwanegu'r cyfeiriad e-bost hwn.", "confirm_adding_email_title": "Cadarnhewch ychwanegu e-bost", "deactivate_confirm_body": "Ydych chi'n siŵr eich bod am ddadactifadu'ch cyfrif? Mae hyn yn anghildroadwy.", @@ -2412,9 +2434,9 @@ "deactivate_confirm_erase_label": "Cuddio fy negeseuon oddi wrth seiri newydd", "deactivate_section": "Dadactifadu Cyfrif", "deactivate_warning": "Mae dadactifadu eich cyfrif yn weithred barhaol - byddwch yn ofalus!", - "discovery_email_empty": "Bydd opsiynau darganfod yn ymddangos unwaith y byddwch wedi ychwanegu e-bost.", + "discovery_email_empty": "Bydd dewisiadau darganfod yn ymddangos unwaith y byddwch wedi ychwanegu e-bost.", "discovery_email_verification_instructions": "Gwiriwch y ddolen yn eich mewnflwch", - "discovery_msisdn_empty": "Bydd opsiynau darganfod yn ymddangos unwaith y byddwch wedi ychwanegu rhif ffôn.", + "discovery_msisdn_empty": "Bydd dewisiadau darganfod yn ymddangos unwaith y byddwch wedi ychwanegu rhif ffôn.", "discovery_needs_terms": "Cytuno i Delerau Gwasanaeth y gweinydd hunaniaeth (%(serverName)s) i ganiatáu i chi'ch hun fod yn hawdd i'ch darganfod trwy gyfeiriad e-bost neu rif ffôn.", "discovery_needs_terms_title": "Gadewch i bobl ddod o hyd i chi", "display_name": "Enw Dangos", @@ -2450,7 +2472,7 @@ "msisdn_verification_instructions": "Rhowch y cod dilysu a anfonwyd trwy neges destun.", "msisdns_heading": "Rhifau ffôn", "oidc_manage_button": "Rheoli cyfrif", - "password_change_section": "Gosod cyfrinair cyfrif newydd…", + "password_change_section": "Gosod cyfrinair cyfrif newydd…", "password_change_success": "Cafodd eich cyfrinair ei newid yn llwyddiannus.", "personal_info": "Gwybodaeth bersonol", "profile_subtitle": "Dyma sut rydych chi'n ymddangos i eraill ar yr ap.", @@ -2463,8 +2485,8 @@ "username": "Enw defnyddiwr" }, "image_thumbnails": "Dangos rhagolygon / mân-luniau ar gyfer delweddau", - "inline_url_previews_default": "Galluogi rhagolygon URL mewnol yn ddiofyn", - "inline_url_previews_room": "Galluogi rhagolygon URL yn ddiofyn ar gyfer cyfranogwyr yn yr ystafell hon", + "inline_url_previews_default": "Galluogi rhagolygon URL mewnol fel rhagosodiad", + "inline_url_previews_room": "Galluogi rhagolygon URL fel rhagosodiad ar gyfer cyfranogwyr yn yr ystafell hon", "inline_url_previews_room_account": "Galluogi rhagolygon URL ar gyfer yr ystafell hon (yn effeithio arnoch chi yn unig)", "insert_trailing_colon_mentions": "Mewnosod colon sy'n llusgo ar ôl i'r defnyddiwr sôn amdano ar ddechrau neges", "jump_to_bottom_on_send": "Neidiwch i waelod y llinell amser pan fyddwch chi'n anfon neges", @@ -2477,28 +2499,28 @@ "setup_secure_backup": { "backup_setup_success_description": "Mae'ch allweddi bellach yn cael eu gwneud wrth gefn o'r ddyfais hon.", "backup_setup_success_title": "Copi Wrth Gefn Diogel yn llwyddiannus", - "cancel_warning": "Os byddwch yn canslo nawr, efallai y byddwch yn colli negeseuon a data wedi'u hamgryptio os byddwch yn colli mynediad at eich mewngofnodi.", + "cancel_warning": "Os byddwch yn diddymu nawr, efallai y byddwch yn colli negeseuon a data wedi'u hamgryptio os byddwch yn colli mynediad at eich mewngofnodi.", "confirm_security_phrase": "Cadarnhewch eich Ymadrodd Diogelwch", "description": "Diogelwch rhag colli mynediad i negeseuon a data wedi'u hamgryptio trwy wneud copïau wrth gefn o allweddi amgryptio ar eich gweinydd.", "download_or_copy": "%(downloadButton)s neu %(copyButton)s", "enter_phrase_description": "Rhowch Ymadrodd Diogelwch dim ond rydych chi'n ei wybod, gan ei fod yn cael ei ddefnyddio i ddiogelu'ch data. I fod yn ddiogel, ni ddylech ailddefnyddio cyfrinair eich cyfrif.", "enter_phrase_title": "Rhowch Ymadrodd Diogelwch", "enter_phrase_to_confirm": "Rhowch eich Ymadrodd Diogelwch yr eildro i'w gadarnhau.", - "generate_security_key_description": "Byddwn yn cynhyrchu Allwedd Ddiogelwch i chi ei storio yn rhywle diogel, fel rheolwr cyfrinair neu sêff.", - "generate_security_key_title": "Cynhyrchu Allwedd Ddiogelwch", + "generate_security_key_description": "Byddwn yn cynhyrchu Allwedd Adfer i chi ei storio yn rhywle diogel, fel rheolwr cyfrinair neu sêff.", + "generate_security_key_title": "Cynhyrchu Allwedd Adfer", "pass_phrase_match_failed": "Nid yw hynny'n cyfateb.", "pass_phrase_match_success": "Mae hynny'n cyfateb!", "phrase_strong_enough": "Gwych! Mae'r Ymadrodd Diogelwch hwn yn edrych yn ddigon cryf.", "secret_storage_query_failure": "Methu cwestiynu statws storio cyfrinachol", - "security_key_safety_reminder": "Storiwch eich Allwedd Ddiogelwch yn rhywle diogel, fel rheolwr cyfrinair neu sêff, gan ei fod yn cael ei ddefnyddio i ddiogelu eich data wedi'i amgryptio.", - "set_phrase_again": "Ewch yn ôl i'w osod eto.", + "security_key_safety_reminder": "Storiwch eich Allwedd Adfer yn rhywle diogel, fel rheolwr cyfrinair neu sêff, gan ei fod yn cael ei ddefnyddio i ddiogelu eich data wedi'i amgryptio.", + "set_phrase_again": "Mynd yn ôl i'w osod eto.", "settings_reminder": "Gallwch hefyd sefydlu Secure Backup a rheoli'ch allweddi yn y Gosodiadau.", "title_confirm_phrase": "Cadarnhau'r Ymadrodd Diogelwch", - "title_save_key": "Arbedwch eich Allwedd Ddiogelwch", + "title_save_key": "Arbedwch eich Allwedd Adfer", "title_set_phrase": "Gosodwch Ymadrodd Diogelwch", "unable_to_setup": "Methu sefydlu storfa gyfrinachol", "use_different_passphrase": "Defnyddio cyfrinair gwahanol?", - "use_phrase_only_you_know": "Defnyddiwch ymadrodd cyfrinachol yn unig rydych chi'n ei wybod, ac yn ddewisol arbedwch Allwedd Ddiogelwch i'w ddefnyddio fel copi wrth gefn." + "use_phrase_only_you_know": "Defnyddiwch ymadrodd cyfrinachol yn unig rydych chi'n ei wybod, ac yn ddewisol arbedwch Allwedd Adfer i'w ddefnyddio fel copi wrth gefn." } }, "key_export_import": { @@ -2526,13 +2548,13 @@ "dialog_title": "Gosodiadau: Defnyddwyr Anwybyddu" }, "notifications": { - "default_setting_description": "Bydd y gosodiad hwn yn cael ei gymhwyso yn ddiofyn i'ch holl ystafelloedd.", + "default_setting_description": "Bydd y gosodiad hwn yn cael ei gymhwyso fel rhagosodiad i'ch holl ystafelloedd.", "default_setting_section": "Rwyf am gael fy hysbysu am (Gosodiad Diofyn)", "desktop_notification_message_preview": "Dangos rhagolwg neges mewn hysbysiad bwrdd gwaith", "dialog_title": "Gosodiadau: Hysbysiadau", "email_description": "Derbyn crynodeb e-bost o hysbysiadau a gollwyd", "email_section": "Crynodeb e-bost", - "email_select": "Dewiswch pa e-byst rydych chi am anfon crynodebau atynt. Rheoli eich e-byst yn .", + "email_select": "Dewiswch pa e-byst rydych chi am anfon crynodebau atynt. Rheoli eich e-byst yn .", "enable_audible_notifications_session": "Galluogi hysbysiadau clywadwy ar gyfer y sesiwn hon", "enable_desktop_notifications_session": "Galluogi hysbysiadau bwrdd gwaith ar gyfer y sesiwn hon", "enable_email_notifications": "Galluogi hysbysiadau e-bost ar gyfer %(email)s", @@ -2549,7 +2571,7 @@ "invites": "Gwahoddiad i ystafell", "keywords": "Dangos bathodyn pan ddefnyddir geiriau allweddol mewn ystafell.", "keywords_prompt": "Rhowch eiriau allweddol yma, neu defnyddiwch ar gyfer amrywiadau sillafu neu lysenwau", - "labs_notice_prompt": "Diweddariad: Rydym wedi symleiddio Gosodiadau Hysbysiadau i'w gwneud yn haws dod o hyd i opsiynau. Nid yw rhai gosodiadau personol rydych chi wedi'u dewis yn y gorffennol yn cael eu dangos yma, ond maen nhw'n dal yn weithredol. Os ewch ymlaen, efallai y bydd rhai o'ch gosodiadau'n newid. Dysgwch fwy", + "labs_notice_prompt": "Diweddariad: Rydym wedi symleiddio Gosodiadau Hysbysiadau i'w gwneud yn haws dod o hyd i dewisiadau. Nid yw rhai gosodiadau personol rydych chi wedi'u dewis yn y gorffennol yn cael eu dangos yma, ond maen nhw'n dal yn weithredol. Os ewch ymlaen, efallai y bydd rhai o'ch gosodiadau'n newid. Dysgu rhagor", "mentions_keywords": "Crybwyll ac Allweddeiriau", "mentions_keywords_only": "Crybwyll ac Allweddeiriau yn unig", "messages_containing_keywords": "Negeseuon yn cynnwys geiriau allweddol", @@ -2557,7 +2579,7 @@ "notices": "Negeseuon a anfonwyd gan bots", "notify_at_room": "Rhowch wybod pan fydd rhywun yn sôn am ddefnyddio @room", "notify_keyword": "Rhowch wybod pan fydd rhywun yn defnyddio allweddair", - "notify_mention": "Rhoi gwybod pan fydd rhywun yn sôn am ddefnyddio @displayname neu %(mxid)s", + "notify_mention": "Rhoi gwybod pan fydd rhywun yn sôn am ddefnyddio @displaymatere neu %(mxid)s", "other_section": "Pethau eraill y credwn y gallai fod gennych ddiddordeb ynddynt:", "people_mentions_keywords": "Pobl, Crybwyll a Geiriau Allweddol", "play_sound_for_description": "Wedi'i gymhwyso'n ddiofyn i bob ystafell ar bob dyfais.", @@ -2583,7 +2605,7 @@ }, "preferences": { "Electron.enableHardwareAcceleration": "Galluogi cyflymiad caledwedd (ailgychwyn %(appName)s i ddod i rym)", - "always_show_menu_bar": "Dangoswch far dewislen y ffenestr bob amser", + "always_show_menu_bar": "Dangos far dewislen y ffenestr bob amser", "autocomplete_delay": "Oedi awtogwblhau (ms)", "code_blocks_heading": "Blociau cod", "compact_modern": "Defnyddiwch gynllun 'Modern' mwy cryno", @@ -2593,7 +2615,7 @@ "enable_hardware_acceleration": "Galluogi cyflymiad caledwedd", "enable_tray_icon": "Dangos eicon hambwrdd a lleihau ffenestr iddo ar agos", "keyboard_heading": "Bysellau brys", - "keyboard_view_shortcuts_button": "I weld yr holl lwybrau byr bysellfwrdd, cliciwch yma .", + "keyboard_view_shortcuts_button": "I weld yr holl lwybrau byr bysellfwrdd, cliciwch yma.", "media_heading": "Delweddau, GIFs a fideos", "presence_description": "Rhannwch eich gweithgarwch a'ch statws ag eraill.", "publish_timezone": "Cyhoeddi cylchfa amser ar broffil cyhoeddus", @@ -2602,10 +2624,10 @@ "room_directory_heading": "Cyfeiriadur ystafelloedd", "room_list_heading": "Rhestr ystafelloedd", "show_avatars_pills": "Dangos rhithffurfiau mewn cyfeiriadau defnyddiwr, ystafell a digwyddiad", - "show_polls_button": "Dangos y botwm polau", + "show_polls_button": "Dangos y botwm arolygon", "surround_text": "Amgylchynwch destun dethol wrth deipio nodau arbennig", "time_heading": "Yn dangos amser", - "user_timezone": "Gosod cylchfa amser" + "user_timezone": "Gosod cylchfa amser" }, "prompt_invite": "Anogwch cyn anfon gwahoddiadau i IDau matrics a allai fod yn annilys", "replace_plain_emoji": "Amnewid Emoji testun plaen yn awtomatig", @@ -2617,7 +2639,7 @@ "backup_key_stored_status": "Allwedd wrth gefn wedi'i storio:", "backup_key_unexpected_type": "math annisgwyl", "backup_key_well_formed": "wedi'i ffurfio'n dda", - "backup_keys_description": "Gwnewch gopi wrth gefn o'ch allweddi amgryptio gyda'ch data cyfrif rhag ofn i chi golli mynediad i'ch sesiynau. Bydd eich allweddi yn cael eu diogelu gydag Allwedd Ddiogelwch unigryw.", + "backup_keys_description": "Gwnewch gopi wrth gefn o'ch allweddi amgryptio gyda'ch data cyfrif rhag ofn i chi golli mynediad i'ch sesiynau. Bydd eich allweddi yn cael eu diogelu gydag Allwedd Adfer unigryw.", "bulk_options_accept_all_invites": "Derbyn pob %(invitedRooms)s gwahoddiad", "bulk_options_reject_all_invites": "Gwrthod pob %(invitedRooms)s gwahoddiad", "bulk_options_section": "Opsiynau swmp", @@ -2641,7 +2663,7 @@ "delete_backup": "Dileu copi wrth gefn", "delete_backup_confirm_description": "Ydych chi'n siŵr? Byddwch yn colli'ch negeseuon wedi'u hamgryptio os na fydd copïau wrth gefn o'ch allweddi yn gywir.", "dialog_title": "Gosodiadau: Diogelwch a Phreifatrwydd", - "e2ee_default_disabled_warning": "Mae gweinyddwr eich gweinydd wedi analluogi amgryptio pen-i-ddiwedd yn ddiofyn mewn ystafelloedd preifat a Negeseuon Uniongyrchol.", + "e2ee_default_disabled_warning": "Mae gweinyddwr eich gweinydd wedi analluogi amgryptio pen-i-ddiwedd fel rhagosodiad mewn ystafelloedd preifat a Negeseuon Uniongyrchol.", "enable_message_search": "Galluogi chwiliad negeseuon mewn ystafelloedd wedi'u hamgryptio", "encryption_section": "Amgryptio", "error_loading_key_backup_status": "Methu llwytho statws wrth gefn allwedd", @@ -2659,7 +2681,7 @@ "key_backup_connect_prompt": "Cysylltwch y sesiwn hon â chopi wrth gefn cyn allgofnodi er mwyn osgoi colli unrhyw allweddi a allai fod ar y sesiwn hon yn unig.", "key_backup_in_progress": "Wrthi'n gwneud copïau wrth gefn o %(sessionsRemaining)s allwedd…", "key_backup_inactive": "Nid yw'r sesiwn hon yn gwneud copi wrth gefn o'ch allweddi , ond mae gennych chi gopi wrth gefn yn barod y gallwch chi adfer ohono ac ychwanegu ato wrth symud ymlaen.", - "key_backup_inactive_warning": "Nid yw eich allweddi yn cael eu gwneud copi wrth gefn o'r sesiwn hon .", + "key_backup_inactive_warning": "Nid yw eich allweddi yn cael eu gwneud copi wrth gefn o'r sesiwn hon.", "key_backup_latest_version": "Fersiwn wrth gefn diweddaraf ar y gweinydd:", "message_search_disable_warning": "Os yw wedi'i analluogi, ni fydd negeseuon o ystafelloedd wedi'u hamgryptio yn ymddangos yn y canlyniadau chwilio.", "message_search_disabled": "Cadwch negeseuon wedi'u hamgryptio'n ddiogel yn lleol er mwyn iddynt ymddangos yn y canlyniadau chwilio.", @@ -2671,10 +2693,10 @@ "message_search_intro": "Mae %(brand)s yn cadw negeseuon wedi'u hamgryptio'n ddiogel yn lleol er mwyn iddynt ymddangos yn y canlyniadau chwilio:", "message_search_room_progress": "%(doneRooms)s allan o %(totalRooms)s", "message_search_section": "Chwilio neges", - "message_search_sleep_time": "Pa mor gyflym y dylid lawrlwytho negeseuon.", + "message_search_sleep_time": "Pa mor gyflym y dylid llwytho i lawrnegeseuon.", "message_search_space_used": "Gofod a ddefnyddir:", - "message_search_unsupported": "Mae %(brand)s ar goll o rai cydrannau sydd eu hangen i gadw negeseuon wedi'u hamgryptio'n ddiogel yn lleol. Os hoffech arbrofi gyda'r nodwedd hon, adeiladwch Benbwrdd %(brand)s wedi'i deilwra ag ef cydrannau chwilio wedi'u hychwanegu .", - "message_search_unsupported_web": "Ni all %(brand)s storio negeseuon wedi'u hamgryptio'n ddiogel yn lleol tra'n rhedeg mewn porwr gwe. Defnydd %(brand)s Penbwrdd i negeseuon wedi'u hamgryptio ymddangos yn y canlyniadau chwilio.", + "message_search_unsupported": "Mae %(brand)s ar goll o rai cydrannau sydd eu hangen i gadw negeseuon wedi'u hamgryptio'n ddiogel yn lleol. Os hoffech arbrofi gyda'r nodwedd hon, adeiladwch Benbwrdd %(brand)s wedi'i deilwra ag ef cydrannau chwilio wedi'u hychwanegu.", + "message_search_unsupported_web": "Ni all %(brand)s storio negeseuon wedi'u hamgryptio'n ddiogel yn lleol tra'n rhedeg mewn porwr gwe. Defnydd %(brand)s Bwrdd Gwaith i negeseuon wedi'u hamgryptio ymddangos yn y canlyniadau chwilio.", "record_session_details": "Cofnodwch enw'r cleient, y fersiwn, a'r url i adnabod sesiynau'n haws yn y rheolwr sesiwn", "restore_key_backup": "Adfer o Wrth Gefn", "secret_storage_not_ready": "ddim yn barod", @@ -2774,11 +2796,11 @@ "sidebar": { "dialog_title": "Gosodiadau: Bar Ochr", "metaspaces_favourites_description": "Grwpiwch eich holl hoff ystafelloedd a phobl mewn un lle.", - "metaspaces_home_all_rooms": "Dangoswch bob ystafell", - "metaspaces_home_all_rooms_description": "Dangoswch eich holl ystafelloedd yn y Cartref, hyd yn oed os ydyn nhw mewn gofod.", + "metaspaces_home_all_rooms": "Dangos bob ystafell", + "metaspaces_home_all_rooms_description": "Dangos eich holl ystafelloedd yn y Cartref, hyd yn oed os ydyn nhw mewn gofod.", "metaspaces_home_description": "Mae Home yn ddefnyddiol ar gyfer cael trosolwg o bopeth.", "metaspaces_orphans": "Ystafelloedd y tu allan i ofod", - "metaspaces_orphans_description": "Grwpiwch eich holl ystafelloedd nad ydynt yn rhan o ofod mewn un lle.", + "metaspaces_orphans_description": "Grwpiwch eich holl ystafelloedd nad ydyn nhw'n rhan o ofod mewn un lle.", "metaspaces_people_description": "Grwpiwch eich holl bobl mewn un lle.", "metaspaces_subsection": "Lleoedd i ddangos", "metaspaces_video_rooms": "Ystafelloedd fideo a chynadleddau", @@ -2806,7 +2828,7 @@ "echo_cancellation": "Canslo adlais", "enable_fallback_ice_server": "Caniatáu gweinydd cymorth galwadau wrth gefn (%(server)s)", "enable_fallback_ice_server_description": "Dim ond os nad yw eich gweinydd cartref yn cynnig un y mae'n berthnasol. Byddai eich cyfeiriad IP yn cael ei rannu yn ystod galwad.", - "mirror_local_feed": "Drych y porthiant fideo lleol", + "mirror_local_feed": "Drych y ffrwd fideo lleol", "missing_permissions_prompt": "Caniatadau cyfryngau ar goll, cliciwch y botwm isod i ofyn.", "noise_suppression": "Atal sŵn", "request_permissions": "Gofyn am ganiatâd cyfryngau", @@ -2836,7 +2858,7 @@ "addwidget_iframe_missing_src": "Nid oes gan iframe briodwedd src", "addwidget_invalid_protocol": "Darparwch URL teclyn https:// neu http://", "addwidget_missing_url": "Rhowch URL teclyn neu god mewnosod", - "addwidget_no_permissions": "Ni allwch addasu teclynnau yn yr ystafell hon.", + "addwidget_no_permissions": "Allwch chi ddim addasu teclynnau yn yr ystafell hon.", "ban": "Gwahardd defnyddiwr gydag ID penodol", "category_actions": "Gweithredoedd", "category_admin": "Gweinyddwr", @@ -2883,7 +2905,7 @@ "plain": "Yn anfon neges fel testun plaen, heb ei ddehongli fel marcio i lawr", "query": "Yn agor sgwrs gyda'r defnyddiwr a roddwyd", "query_not_found_phone_number": "Methu dod o hyd i ID Matrics ar gyfer rhif ffôn", - "rageshake": "Anfonwch adroddiad nam gyda logiau", + "rageshake": "Anfonwch adroddiad mater gyda logiau", "rainbow": "Yn anfon y neges a roddwyd wedi'i lliwio fel enfys", "rainbowme": "Yn anfon yr emote a roddir wedi'i liwio fel enfys", "remove": "Yn tynnu'r defnyddiwr ag ID penodol o'r ystafell hon", @@ -2946,9 +2968,9 @@ "invite_description": "Gwahodd gydag e-bost neu enw defnyddiwr", "invite_link": "Rhannu dolen gwahoddiad", "joining_space": "Yn ymuno", - "landing_welcome": "Croeso i", + "landing_welcome": "Croeso i", "leave_dialog_action": "Gadael lle", - "leave_dialog_description": "Rydych chi ar fin gadael .", + "leave_dialog_description": "Rydych chi ar fin gadael.", "leave_dialog_only_admin_room_warning": "Chi yw unig weinyddwr rhai o'r ystafelloedd neu'r gofodau yr hoffech eu gadael. Bydd eu gadael yn eu gadael heb unrhyw weinyddwyr.", "leave_dialog_only_admin_warning": "Chi yw unig weinyddwr y gofod hwn. Bydd ei adael yn golygu nad oes gan neb reolaeth drosto.", "leave_dialog_option_all": "Gadael pob ystafell", @@ -2967,7 +2989,7 @@ "search_children": "Chwilio %(spaceName)s", "search_placeholder": "Chwilio enwau a disgrifiadau", "select_room_below": "Dewiswch ystafell isod yn gyntaf", - "share_public": "Rhannwch eich man cyhoeddus", + "share_public": "Rhannwch eich gofod cyhoeddus", "suggested": "Awgrym", "suggested_tooltip": "Awgrymir yr ystafell hon fel un dda i ymuno â hi", "title_when_query_available": "Canlyniadau", @@ -3006,7 +3028,7 @@ "copy_link_text": "Copïo dolen y gwahoddiad", "create_new_room_button": "Creu ystafell newydd", "failed_querying_public_rooms": "Wedi methu â holi ystafelloedd cyhoeddus", - "failed_querying_public_spaces": "Wedi methu cwestiynu mannau cyhoeddus", + "failed_querying_public_spaces": "Wedi methu cwestiynu gofodau cyhoeddus", "group_chat_section_title": "Dewisiadau eraill", "heading_with_query": "Defnyddiwch \"%(query)s\" i chwilio", "heading_without_query": "Chwilio am", @@ -3015,7 +3037,7 @@ "message_search_section_title": "Chwiliadau eraill", "other_rooms_in_space": "Ystafelloedd eraill yn %(spaceName)s", "public_rooms_label": "Ystafelloedd cyhoeddus", - "public_spaces_label": "Mannau cyhoeddus", + "public_spaces_label": "Gofodau cyhoeddus", "recent_searches_section_title": "Chwilio diweddar", "recently_viewed_section_title": "Gwelwyd yn ddiweddar", "remove_filter": "Tynnu'r hidlydd chwilio ar gyfer %(filter)s", @@ -3023,7 +3045,7 @@ "result_may_be_hidden_warning": "Efallai y bydd rhai canlyniadau wedi'u cuddio", "search_dialog": "Deialog Chwilio", "search_messages_hint": "I chwilio negeseuon, edrychwch am yr eicon hwn ar frig ystafell", - "spaces_title": "Mannau rydych chi ynddynt", + "spaces_title": "Gofodau rydych chi ynddynt", "start_group_chat_button": "Dechreuwch sgwrs grŵp" }, "stickers": { @@ -3134,7 +3156,7 @@ }, "error_no_renderer": "Nid oedd modd dangos y digwyddiad hwn", "error_rendering_message": "Methu llwytho'r neges hon", - "historical_messages_unavailable": "Ni allwch weld negeseuon cynharach", + "historical_messages_unavailable": "Allwch chi ddim weld negeseuon cynharach", "in_room_name": " yn %(room)s", "io.element.widgets.layout": "Mae %(senderName)s wedi diweddaru cynllun yr ystafell", "late_event_separator": "Anfonwyd %(dateTime)s yn wreiddiol", @@ -3144,7 +3166,7 @@ "unable_to_find": "Wedi ceisio llwytho pwynt penodol yn llinell amser yr ystafell hon, ond ni lwyddodd i ddod o hyd iddo." }, "m.audio": { - "error_downloading_audio": "Gwall wrth lawrlwytho sain", + "error_downloading_audio": "Gwall wrth llwytho i lawrsain", "error_processing_audio": "Gwall wrth brosesu neges sain", "error_processing_voice_message": "Gwall wrth brosesu neges llais", "unnamed_audio": "Sain dienw" @@ -3155,7 +3177,7 @@ "m.call": { "video_call_ended": "Daeth galwad fideo i ben", "video_call_started": "Dechreuwyd galwad fideo yn %(roomName)s.", - "video_call_started_text": "Dechreuodd %(name)s alwad fideo", + "video_call_started_text": "Dechreuodd %(matere)s alwad fideo", "video_call_started_unsupported": "Dechreuwyd galwad fideo yn %(roomName)s. (heb ei gefnogi gan y porwr hwn)" }, "m.call.hangup": { @@ -3190,7 +3212,7 @@ "show_image": "Dangos delwedd" }, "m.key.verification.request": { - "user_wants_to_verify": "Mae %(name)s eisiau gwirio", + "user_wants_to_verify": "Mae %(matere)s eisiau gwirio", "you_started": "Anfonoch gais dilysu" }, "m.location": { @@ -3204,10 +3226,10 @@ }, "m.poll.start": "Mae %(senderName)s wedi dechrau arolwg barn - %(pollQuestion)s", "m.room.avatar": { - "changed": "Mae %(senderDisplayName)s wedi newid avatar yr ystafell.", - "changed_img": "Mae %(senderDisplayName)s wedi newid yr avatar ystafell i", - "lightbox_title": "Newidiodd %(senderDisplayName)s yr avatar ar gyfer %(roomName)s", - "removed": "Mae %(senderDisplayName)s wedi tynnu avatar yr ystafell." + "changed": "Mae %(senderDisplayName)s wedi newid afatar yr ystafell.", + "changed_img": "Mae %(senderDisplayName)s wedi newid yr afatar ystafell i", + "lightbox_title": "Newidiodd %(senderDisplayName)s yr afatar ar gyfer %(roomName)s", + "removed": "Mae %(senderDisplayName)s wedi tynnu afatar yr ystafell." }, "m.room.canonical_alias": { "changed": "Newidiodd %(senderName)s y cyfeiriadau ar gyfer yr ystafell hon.", @@ -3225,7 +3247,7 @@ "m.room.encryption": { "disable_attempt": "Wedi anwybyddu ymgais i analluogi amgryptio", "disabled": "Nid yw amgryptio wedi'i alluogi", - "enabled": "Mae negeseuon yn yr ystafell hon wedi'u hamgryptio o un pen i'r llall. Pan fydd pobl yn ymuno, gallwch chi eu gwirio yn eu proffil, dim ond tapio ar eu llun proffil.", + "enabled": "Mae negeseuon yn yr ystafell hon wedi'u hamgryptio pen-i-ben. Pan fydd pobl yn ymuno, gallwch chi eu gwirio yn eu proffil, dim ond tapio ar eu llun proffil.", "enabled_dm": "Mae negeseuon yma wedi'u hamgryptio o'r dechrau i'r diwedd. Dilyswch %(displayName)s yn eu proffil - tapiwch ar eu llun proffil.", "enabled_local": "Bydd negeseuon yn y sgwrs hon yn cael eu hamgryptio o'r dechrau i'r diwedd.", "parameters_changed": "Mae rhai paramedrau amgryptio wedi'u newid.", @@ -3248,7 +3270,7 @@ "knock": "Newidiodd %(senderDisplayName)s y rheol ymuno i ofyn am gael ymuno.", "public": "Gwnaeth %(senderDisplayName)s yr ystafell yn gyhoeddus i bwy bynnag sy'n gwybod y ddolen.", "restricted": "Mae %(senderDisplayName)s wedi newid pwy all ymuno â'r ystafell hon.", - "restricted_settings": "Mae %(senderDisplayName)s wedi newid pwy all ymuno â'r ystafell hon. Gweld gosodiadau .", + "restricted_settings": "Mae %(senderDisplayName)s wedi newid pwy all ymuno â'r ystafell hon. Gweld gosodiadau.", "unknown": "Newidiodd %(senderDisplayName)s y rheol ymuno i %(rule)s" }, "m.room.member": { @@ -3285,16 +3307,16 @@ "changed": "Newidiodd %(senderName)s y negeseuon sydd wedi'u pinio ar gyfer yr ystafell.", "changed_link": "Newidiodd %(senderName)s y negeseuon sydd wedi'u pinio ar gyfer yr ystafell.", "pinned": "Mae %(senderName)s wedi pinio neges i'r ystafell hon. Gweld yr holl negeseuon sydd wedi'u pinio.", - "pinned_link": "Mae %(senderName)s wedi pinio neges i'r ystafell hon. Gweld yr holl negeseuon sydd wedi'u pinio .", + "pinned_link": "Mae %(senderName)s wedi pinio neges i'r ystafell hon. Gweld yr holl negeseuon sydd wedi'u pinio.", "unpinned": "Mae %(senderName)s wedi dad-binio neges o'r ystafell hon. Gweld yr holl negeseuon sydd wedi'u pinio.", - "unpinned_link": "Mae %(senderName)s wedi dad-binio neges o'r ystafell hon. Gweld yr holl negeseuon sydd wedi'u pinio ." + "unpinned_link": "Mae %(senderName)s wedi dad-binio neges o'r ystafell hon. Gweld yr holl negeseuon sydd wedi'u pinio." }, "m.room.power_levels": { "changed": "Mae %(senderName)s wedi newid lefel pŵer %(powerLevelDiffText)s.", "user_from_to": "%(userId)s o %(fromPowerLevel)s i %(toPowerLevel)s" }, "m.room.server_acl": { - "all_servers_banned": "🎉 Mae pob gweinydd wedi'i wahardd rhag cymryd rhan! Ni ellir defnyddio'r ystafell hon mwyach.", + "all_servers_banned": "🎉 Mae pob gweinydd wedi'i wahardd rhag cymryd rhan! Nid oes modd defnyddio'r ystafell hon mwyach.", "changed": "Newidiodd %(senderDisplayName)s y gweinydd ACLs ar gyfer yr ystafell hon.", "set": "Gosododd %(senderDisplayName)s y gweinydd ACLs ar gyfer yr ystafell hon." }, @@ -3364,7 +3386,7 @@ "redacted": { "tooltip": "Neges wedi'i dileu ar %(date)s" }, - "redaction": "Neges wedi'i dileu gan %(name)s", + "redaction": "Neges wedi'i dileu gan %(matere)s", "reply": { "error_loading": "Methu llwytho digwyddiad yr atebwyd iddo, naill ai nid yw'n bodoli neu nid oes gennych ganiatâd i'w weld.", "in_reply_to": "Mewn atebiad i", @@ -3380,12 +3402,12 @@ "send_state_sending": "Wrthi'n anfon eich neges…", "send_state_sent": "Anfonwyd eich neges", "summary": { - "format": "%(nameList)s %(transitionList)s" + "format": "%(matereList)s %(transitionList)s" }, "thread_info_basic": "O edefyn", "typing_indicator": { "one_user": "Mae %(displayName)s yn teipio…", - "two_users": "Mae %(names)s a %(lastPerson)s yn teipio…" + "two_users": "Mae %(materes)s a %(lastPerson)s yn teipio…" }, "undecryptable_tooltip": "Nid oedd modd dadgryptio'r neges hon", "url_preview": { @@ -3402,7 +3424,7 @@ "changelog": "Cofnod Newid", "check_action": "Gwiriwch am ddiweddariad", "checking": "Wrthi'n gwirio am ddiweddariad…", - "downloading": "Wrthi'n lawrlwytho diweddariad…", + "downloading": "Wrthi'n llwytho i lawrdiweddariad…", "error_encountered": "Gwall a gafwyd (%(errorDetail)s).", "error_unable_load_commit": "Methu llwytho manylion ymrwymo: %(msg)s", "new_version_available": "Fersiwn newydd ar gael. Diweddaru nawr.", @@ -3441,7 +3463,7 @@ "ban_space_everything": "Gwaharddwch nhw o bopeth rydw i'n gallu", "ban_space_specific": "Gwaharddwch nhw o bethau penodol y gallaf eu gwneud", "deactivate_confirm_action": "Analluogi defnyddiwr", - "deactivate_confirm_description": "Bydd dadactifadu'r defnyddiwr hwn yn eu hallgofnodi a'u hatal rhag mewngofnodi eto. Yn ogystal, byddant yn gadael yr holl ystafelloedd y mae ynddynt. Ni ellir gwrthdroi'r weithred hon. Ydych chi'n siŵr eich bod am ddadactifadu'r defnyddiwr hwn?", + "deactivate_confirm_description": "Bydd dadactifadu'r defnyddiwr hwn yn eu hallgofnodi a'u hatal rhag mewngofnodi eto. Yn ogystal, byddant yn gadael yr holl ystafelloedd y mae ynddynt. Nid oes modd gwrthdroi'r weithred hon. Ydych chi'n siŵr eich bod am ddadactifadu'r defnyddiwr hwn?", "deactivate_confirm_title": "Analluogi defnyddiwr?", "demote_button": "Diraddio", "demote_self_confirm_description_space": "Ni fyddwch yn gallu dadwneud y newid hwn gan eich bod yn israddio eich hun, os mai chi yw'r defnyddiwr breintiedig olaf yn y gofod bydd yn amhosibl adennill breintiau.", @@ -3478,9 +3500,9 @@ }, "redact_button": "Dileu negeseuon", "revoke_invite": "Diddymu gwahoddiad", - "room_encrypted": "Mae negeseuon yn yr ystafell hon wedi'u hamgryptio o un pen i'r llall.", + "room_encrypted": "Mae negeseuon yn yr ystafell hon wedi'u hamgryptio pen-i-ben.", "room_encrypted_detail": "Mae eich negeseuon yn ddiogel a dim ond chi a'r derbynnydd sydd â'r allweddi unigryw i'w datgloi.", - "room_unencrypted": "Nid yw negeseuon yn yr ystafell hon wedi'u hamgryptio o un pen i'r llall.", + "room_unencrypted": "Nid yw negeseuon yn yr ystafell hon wedi'u hamgryptio pen-i-ben.", "room_unencrypted_detail": "Mewn ystafelloedd wedi'u hamgryptio, mae'ch negeseuon yn ddiogel a dim ond chi a'r derbynnydd sydd â'r allweddi unigryw i'w datgloi.", "send_message": "Anfon neges", "share_button": "Rhannu proffil", @@ -3519,11 +3541,11 @@ "call_toast_unknown_room": "Ystafell anhysbys", "camera_disabled": "Mae eich camera wedi'i ddiffodd", "camera_enabled": "Mae eich camera wedi'i alluogi o hyd", - "cannot_call_yourself_description": "Ni allwch roi galwad gyda chi'ch hun.", + "cannot_call_yourself_description": "Allwch chi ddim roi galwad gyda chi'ch hun.", "close_lobby": "Caewch y lobi", "connecting": "Yn cysylltu", "connection_lost": "Mae cysylltedd â'r gweinydd wedi'i golli", - "connection_lost_description": "Ni allwch osod galwadau heb gysylltiad â'r gweinydd.", + "connection_lost_description": "Allwch chi ddim osod galwadau heb gysylltiad â'r gweinydd.", "consulting": "Ymgynghori â %(transferTarget)s. Trosglwyddo i %(transferee)s", "default_device": "Dyfais Diofyn", "dial": "Deialwch", @@ -3543,7 +3565,7 @@ "hide_sidebar_button": "Cuddio bar ochr", "input_devices": "Dyfeisiau mewnbwn", "jitsi_call": "Cynhadledd Jitsi", - "join_button_tooltip_call_full": "Mae'n ddrwg gennym - mae'r alwad hon yn llawn ar hyn o bryd", + "join_button_tooltip_call_full": "Ymddiheuriadau - mae'r alwad hon yn llawn ar hyn o bryd", "legacy_call": "Galwad Etifeddiaeth", "maximise": "Llanw'r Sgrin", "maximise_call": "Mwyhau galwad", @@ -3565,7 +3587,7 @@ "no_media_perms_title": "Dim caniatâd cyfryngau", "no_permission_conference": "Angen Caniatâd", "no_permission_conference_description": "Nid oes gennych ganiatâd i ddechrau galwad cynadledda yn yr ystafell hon", - "on_hold": "%(name)s ar stop", + "on_hold": "%(matere)s ar stop", "output_devices": "Dyfeisiau allbwn", "screenshare_monitor": "Rhannu sgrin gyfan", "screenshare_title": "Rhannu cynnwys", @@ -3588,7 +3610,7 @@ "unknown_person": "person anhysbys", "unsilence": "Sain ymlaen", "unsupported": "Ni chefnogir galwadau", - "unsupported_browser": "Ni allwch osod galwadau yn y porwr hwn.", + "unsupported_browser": "Allwch chi ddim osod galwadau yn y porwr hwn.", "user_busy": "Defnyddiwr Prysur", "user_busy_description": "Mae'r defnyddiwr y gwnaethoch ei alw yn brysur.", "user_is_presenting": "Mae %(sharerName)s yn cyflwyno", @@ -3615,8 +3637,8 @@ "byline_empty_state_key": "gydag allwedd cyflwr gwag", "byline_state_key": "gydag allwedd cyflwr %(stateKey)s", "capability": "Y gallu %(capability)s", - "change_avatar_active_room": "Newidiwch avatar eich ystafell actif", - "change_avatar_this_room": "Newid avatar yr ystafell hon", + "change_avatar_active_room": "Newidiwch afatar eich ystafell actif", + "change_avatar_this_room": "Newid afatar yr ystafell hon", "change_name_active_room": "Newidiwch enw eich ystafell weithredol", "change_name_this_room": "Newidiwch enw'r ystafell hon", "change_topic_active_room": "Newidiwch bwnc eich ystafell weithredol", @@ -3625,8 +3647,8 @@ "receive_membership_this_room": "Gweld pryd mae pobl yn ymuno, yn gadael neu'n cael eu gwahodd i'r ystafell hon", "remove_ban_invite_leave_active_room": "Dileu, gwahardd, neu wahodd pobl i'ch ystafell actif, a gwneud i chi adael", "remove_ban_invite_leave_this_room": "Dileu, gwahardd, neu wahodd pobl i'r ystafell hon, a gwneud i chi adael", - "see_avatar_change_active_room": "Gweld pryd mae'r avatar yn newid yn eich ystafell actif", - "see_avatar_change_this_room": "Gweld pryd mae'r avatar yn newid yn yr ystafell hon", + "see_avatar_change_active_room": "Gweld pryd mae'r afatar yn newid yn eich ystafell actif", + "see_avatar_change_this_room": "Gweld pryd mae'r afatar yn newid yn yr ystafell hon", "see_event_type_sent_active_room": "Gweld %(eventType)s digwyddiad wedi'u postio i'ch ystafell dan sylw", "see_event_type_sent_this_room": "Gweld %(eventType)s digwyddiad wedi'u postio i'r ystafell hon", "see_images_sent_active_room": "Gweld delweddau sy'n cael eu postio i'ch ystafell actif", diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 00e76092e8..0517b2e5bf 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -4060,7 +4060,7 @@ "error_need_to_be_logged_in": "Du musst angemeldet sein.", "error_unable_start_audio_stream_description": "Audiostream kann nicht gestartet werden.", "error_unable_start_audio_stream_title": "Livestream konnte nicht gestartet werden", - "modal_data_warning": "Daten auf diesem Bildschirm werden mit %(widgetDomain)s geteilt", + "modal_data_warning": "Die unten aufgeführten Daten werden mit %(widgetDomain)s geteilt.", "modal_title_default": "Modales Widget", "no_name": "Unbekannte App", "open_id_permissions_dialog": { diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 5570279115..2279cfcf20 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -4095,7 +4095,7 @@ "error_need_to_be_logged_in": "You need to be logged in.", "error_unable_start_audio_stream_description": "Unable to start audio streaming.", "error_unable_start_audio_stream_title": "Failed to start livestream", - "modal_data_warning": "Data on this screen is shared with %(widgetDomain)s", + "modal_data_warning": "The data below is shared with %(widgetDomain)s", "modal_title_default": "Modal Widget", "no_name": "Unknown App", "open_id_permissions_dialog": { diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index e3722da0a5..0ed0f87ff3 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -951,7 +951,7 @@ "warning": "Si vous n’avez pas activé de nouvelle méthode de récupération, un attaquant essaye peut-être d’accéder à votre compte. Changez immédiatement le mot de passe de votre compte et configurez une nouvelle méthode de récupération dans les paramètres." }, "not_supported": "", - "pinned_identity_changed": "L'identité de %(displayName)s(%(userId)s) semble avoir changé. En savoir plus ", + "pinned_identity_changed": "L'identité de %(displayName)s (%(userId)s) semble avoir changé. En savoir plus", "pinned_identity_changed_no_displayname": "%(userId)ssemble avoir changé d'identité. En savoir plus", "recovery_method_removed": { "description_1": "Cette session a détecté que votre phrase de sécurité et clé de sécurité pour les messages sécurisés ont été supprimées.", @@ -4080,7 +4080,7 @@ "error_need_to_be_logged_in": "Vous devez être identifié.", "error_unable_start_audio_stream_description": "Impossible de démarrer la diffusion audio.", "error_unable_start_audio_stream_title": "Échec lors du démarrage de la diffusion en direct", - "modal_data_warning": "Les données sur cet écran sont partagées avec %(widgetDomain)s", + "modal_data_warning": "Les données ci-dessous sont partagées avec %(widgetDomain)s", "modal_title_default": "Fenêtre de widget", "no_name": "Application inconnue", "open_id_permissions_dialog": { diff --git a/src/i18n/strings/nb_NO.json b/src/i18n/strings/nb_NO.json index 45f6ea8ebe..5bbe695639 100644 --- a/src/i18n/strings/nb_NO.json +++ b/src/i18n/strings/nb_NO.json @@ -408,6 +408,9 @@ "downloading_logs": "Laster ned logger", "error_empty": "Fortell oss hva som gikk galt, eller bedre, opprett et GitHub-problem som beskriver problemet.", "failed_download_logs": "Kunne ikke laste ned feilsøkingslogger: ", + "failed_send_logs_causes": { + "disallowed_app": "Feilrapporten din ble avvist. Rageshake-serveren støtter ikke denne applikasjonen." + }, "github_issue": "Github-saksrapport", "introduction": "Hvis du har sendt inn en feil via GitHub, kan feilsøkingslogger hjelpe oss med å spore opp problemet. ", "log_request": "For å hjelpe oss med å forhindre dette i fremtiden, vennligst send oss loggfiler.", @@ -4059,7 +4062,7 @@ "error_need_to_be_logged_in": "Du må være logget inn.", "error_unable_start_audio_stream_description": "Kan ikke starte lydstrømming.", "error_unable_start_audio_stream_title": "Kan ikke starte livestream", - "modal_data_warning": "Data på denne skjermen deles med %(widgetDomain)s", + "modal_data_warning": "Dataene nedenfor deles med %(widgetDomain)s", "modal_title_default": "Modal Widget", "no_name": "Ukjent app", "open_id_permissions_dialog": { From 66d9d717c4a127eec21c81ad7dfe5f9380994689 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Fri, 14 Mar 2025 12:03:09 +0000 Subject: [PATCH 081/458] Add setting to hide avatars of rooms you have been invited to. (#29497) * Add ability to block images of rooms you have been invited to. * strings * Add tests * fix snapshot * tweaks * lint --- ...ab-should-be-rendered-properly-1-linux.png | Bin 252674 -> 255152 bytes src/components/views/avatars/RoomAvatar.tsx | 19 +- .../tabs/user/PreferencesUserSettingsTab.tsx | 4 +- src/i18n/strings/en_EN.json | 1 + src/settings/Settings.tsx | 8 +- .../views/avatars/RoomAvatar-test.tsx | 25 +- .../__snapshots__/RoomAvatar-test.tsx.snap | 39 ++ .../PreferencesUserSettingsTab-test.tsx.snap | 401 ++++++++++-------- 8 files changed, 304 insertions(+), 193 deletions(-) diff --git a/playwright/snapshots/settings/preferences-user-settings-tab.spec.ts/Preferences-user-settings-tab-should-be-rendered-properly-1-linux.png b/playwright/snapshots/settings/preferences-user-settings-tab.spec.ts/Preferences-user-settings-tab-should-be-rendered-properly-1-linux.png index 164c1a8a08281b6af092ab4967683d02c80d50cd..077c8ba462172291ccff85fb06445291a435ebd7 100644 GIT binary patch literal 255152 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
;YN&uYuaSyj*QR@6+n!N}yk*=1iSInfsh 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

_Ui8yg>L2s)oD{^z)b{{)N8IhaKSMC{CE9cQ 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 !g#y?NWp9*Z3~P@Bdp*oqnCwc!hTY&98E%N912 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≦W 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 Ntn_D(SR;O1x_%(wVNByICt1*HNs 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

+`; + +exports[`RoomAvatar should render an avatar for a room the user is invited to 1`] = ` +
+ + + +
+`; + exports[`RoomAvatar should render as expected for a DM room 1`] = `

?+Wuq}t;5MWSIx{Qtm(-Bk%s4*{PJ=n4SCN{Bx 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 )dhJaM4%vu#ls%&L@MB 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, "name" | "idName" | "url" | "onClick"> { // Room may be left unset here, but if it is, @@ -86,6 +94,13 @@ export default class RoomAvatar extends React.Component { }; private static getImageUrls(props: IProps): string[] { + const myMembership = props.room?.getMyMembership(); + if (myMembership === KnownMembership.Invite || !myMembership) { + if (SettingsStore.getValue("showAvatarsOnInvites") === false) { + // The user has opted out of showing avatars, so return no urls here. + return []; + } + } let oobAvatar: string | null = null; if (props.oobData.avatarUrl) { oobAvatar = mediaFromMxc(props.oobData.avatarUrl).getThumbnailOfSourceHttp( diff --git a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx index cb22bb2a0c..a7166fdb6b 100644 --- a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024, 2025 New Vector Ltd. Copyright 2019-2023 The Matrix.org Foundation C.I.C. Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> @@ -116,7 +116,7 @@ const SpellCheckSection: React.FC = () => { }; export default class PreferencesUserSettingsTab extends React.Component { - private static ROOM_LIST_SETTINGS: BooleanSettingKey[] = ["breadcrumbs"]; + private static ROOM_LIST_SETTINGS: BooleanSettingKey[] = ["breadcrumbs", "showAvatarsOnInvites"]; private static SPACES_SETTINGS: BooleanSettingKey[] = ["Spaces.allRoomsInHome"]; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 2279cfcf20..2136c8c86c 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2643,6 +2643,7 @@ "inline_url_previews_room": "Enable URL previews by default for participants in this room", "inline_url_previews_room_account": "Enable URL previews for this room (only affects you)", "insert_trailing_colon_mentions": "Insert a trailing colon after user mentions at the start of a message", + "invite_avatars": "Show avatars of rooms you have been invited to", "jump_to_bottom_on_send": "Jump to the bottom of the timeline when you send a message", "key_backup": { "backup_in_progress": "Your keys are being backed up (the first backup could take a few minutes).", diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 3046813f4d..3084263b2f 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024, 2025 New Vector Ltd. Copyright 2018-2024 The Matrix.org Foundation C.I.C. Copyright 2017 Travis Ralston @@ -312,6 +312,7 @@ export interface Settings { "lowBandwidth": IBaseSetting; "fallbackICEServerAllowed": IBaseSetting; "showImages": IBaseSetting; + "showAvatarsOnInvites": IBaseSetting; "RoomList.preferredSorting": IBaseSetting; "RightPanel.phasesGlobal": IBaseSetting; "RightPanel.phases": IBaseSetting; @@ -1116,6 +1117,11 @@ export const SETTINGS: Settings = { displayName: _td("settings|image_thumbnails"), default: true, }, + "showAvatarsOnInvites": { + supportedLevels: LEVELS_ACCOUNT_SETTINGS, + displayName: _td("settings|invite_avatars"), + default: true, + }, "RoomList.preferredSorting": { supportedLevels: [SettingLevel.DEVICE], default: SortingAlgorithm.Recency, diff --git a/test/unit-tests/components/views/avatars/RoomAvatar-test.tsx b/test/unit-tests/components/views/avatars/RoomAvatar-test.tsx index 8e7a446cbd..615e24fa69 100644 --- a/test/unit-tests/components/views/avatars/RoomAvatar-test.tsx +++ b/test/unit-tests/components/views/avatars/RoomAvatar-test.tsx @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024, 2025 New Vector Ltd. Copyright 2022 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial @@ -17,6 +17,8 @@ import DMRoomMap from "../../../../../src/utils/DMRoomMap"; import { LocalRoom } from "../../../../../src/models/LocalRoom"; import * as AvatarModule from "../../../../../src/Avatar"; import { DirectoryMember } from "../../../../../src/utils/direct-messages"; +import SettingsStore from "../../../../../src/settings/SettingsStore"; +import { SettingLevel } from "../../../../../src/settings/SettingLevel"; describe("RoomAvatar", () => { let client: MatrixClient; @@ -41,6 +43,12 @@ describe("RoomAvatar", () => { afterEach(() => { mocked(DMRoomMap.shared().getUserIdForRoomId).mockReset(); mocked(AvatarModule.defaultAvatarUrlForString).mockClear(); + SettingsStore.setValue( + "showAvatarsOnInvites", + null, + SettingLevel.ACCOUNT, + SettingsStore.getDefaultValue("showAvatarsOnInvites"), + ); }); it("should render as expected for a Room", () => { @@ -64,4 +72,19 @@ describe("RoomAvatar", () => { localRoom.targets.push(new DirectoryMember({ user_id: userId })); expect(render().container).toMatchSnapshot(); }); + it("should render an avatar for a room the user is invited to", () => { + SettingsStore.setValue("showAvatarsOnInvites", null, SettingLevel.ACCOUNT, true); + const room = new Room("!room:example.com", client, client.getSafeUserId()); + jest.spyOn(room, "getMxcAvatarUrl").mockImplementation(() => "mxc://example.com/foobar"); + room.name = "test room"; + room.updateMyMembership("invite"); + expect(render().container).toMatchSnapshot(); + }); + it("should not render an invite avatar if the user has disabled it", () => { + SettingsStore.setValue("showAvatarsOnInvites", null, SettingLevel.ACCOUNT, false); + const room = new Room("!room:example.com", client, client.getSafeUserId()); + room.name = "test room"; + room.updateMyMembership("invite"); + expect(render().container).toMatchSnapshot(); + }); }); diff --git a/test/unit-tests/components/views/avatars/__snapshots__/RoomAvatar-test.tsx.snap b/test/unit-tests/components/views/avatars/__snapshots__/RoomAvatar-test.tsx.snap index 921b17baf1..f77dcc6948 100644 --- a/test/unit-tests/components/views/avatars/__snapshots__/RoomAvatar-test.tsx.snap +++ b/test/unit-tests/components/views/avatars/__snapshots__/RoomAvatar-test.tsx.snap @@ -1,5 +1,44 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`RoomAvatar should not render an invite avatar if the user has disabled it 1`] = ` +

+
+ +
+
+
+
-
- -
+ + Always show message timestamps + + +
+
+
+
+
+
-
- -
- Use Ctrl + Enter to send a message + Enable Emoji suggestions while typing
- Surround selected text when typing special characters + Use Ctrl + Enter to send a message
- Show stickers button + Surround selected text when typing special characters
+ + Show stickers button + + +
+
+
+
+
+
-
- -
+ + Expand code blocks by default + + +
+
+
+
+
+
-
- -
- Autoplay videos + Autoplay GIFs
+ + Autoplay videos + + +
+
+
+
+
+
-
- -
- Show read receipts sent by other users + Show a placeholder for removed messages
- Show join/leave messages (invites/removes/bans unaffected) + Show read receipts sent by other users
- Show display name changes + Show join/leave messages (invites/removes/bans unaffected)
- Show chat effects (animations when receiving e.g. confetti) + Show display name changes
- Show profile picture changes + Show chat effects (animations when receiving e.g. confetti)
- Show avatars in user, room and event mentions + Show profile picture changes
- Enable big emoji in chat + Show avatars in user, room and event mentions
- Jump to the bottom of the timeline when you send a message + Enable big emoji in chat
+ + Jump to the bottom of the timeline when you send a message + + +
+
+
+
+
+
+ `; diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListPanel-test.tsx.snap b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListPanel-test.tsx.snap index 6421601173..28f3befc20 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListPanel-test.tsx.snap +++ b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListPanel-test.tsx.snap @@ -23,6 +23,35 @@ exports[` should not render the RoomListSearch component when U Home
+
    Date: Fri, 14 Mar 2025 17:22:45 +0100 Subject: [PATCH 085/458] New room list: add more options menu on room list item (#29445) * refactor(room list item): rename `RoomListCell` into `RoomListItemView` * refactor(room list item): move open room action to new room list item view model * feat(hover menu): add `hasAccessToOptionsMenu` * feat(hover menu): add to `RoomListItemViewModel` the condition to display or not the hover menu * feat(hover menu): add view model for the hover menu * feat(hover menu): add hover menu view * feat(hover menu): add hover menu to room list item * feat(hover menu): update i18n * test(view model list item): update test and add test to `showHoverMenu` * test(room list): update snapshot * test(room list item menu): add tests for view model * test(room list item menu): add tests for view * test(room list item): add tests * test(e2e): add tests for more options menu * chore: update compound web * test(e2e): fix typo --- package.json | 2 +- .../room-list-panel/room-list.spec.ts | 30 +++ .../room-list-item-hover-linux.png | Bin 0 -> 2293 bytes ...room-list-item-open-more-options-linux.png | Bin 0 -> 81877 bytes res/css/_components.pcss | 3 +- .../RoomListPanel/_RoomListItemMenuView.pcss | 12 ++ ...omListCell.pcss => _RoomListItemView.pcss} | 13 +- .../roomlist/RoomListItemMenuViewModel.tsx | 180 ++++++++++++++++++ .../roomlist/RoomListItemViewModel.tsx | 49 +++++ .../viewmodels/roomlist/RoomListViewModel.tsx | 20 -- src/components/viewmodels/roomlist/utils.ts | 25 +++ .../views/rooms/RoomListPanel/RoomList.tsx | 10 +- .../rooms/RoomListPanel/RoomListCell.tsx | 44 ----- .../RoomListPanel/RoomListItemMenuView.tsx | 154 +++++++++++++++ .../rooms/RoomListPanel/RoomListItemView.tsx | 76 ++++++++ src/i18n/strings/en_EN.json | 9 + test/test-utils/test-utils.ts | 2 +- .../RoomListItemMenuViewModel-test.tsx | 173 +++++++++++++++++ .../roomlist/RoomListItemViewModel-test.tsx | 49 +++++ .../roomlist/RoomListViewModel-test.tsx | 17 -- .../rooms/RoomListPanel/RoomList-test.tsx | 15 +- .../rooms/RoomListPanel/RoomListCell-test.tsx | 44 ----- .../RoomListItemMenuView-test.tsx | 110 +++++++++++ .../RoomListPanel/RoomListItemView-test.tsx | 68 +++++++ .../RoomListPrimaryFilters-test.tsx | 1 - .../__snapshots__/RoomList-test.tsx.snap | 80 ++++---- .../RoomListItemMenuView-test.tsx.snap | 42 ++++ ...sx.snap => RoomListItemView-test.tsx.snap} | 10 +- yarn.lock | 8 +- 29 files changed, 1044 insertions(+), 202 deletions(-) create mode 100644 playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-hover-linux.png create mode 100644 playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-open-more-options-linux.png create mode 100644 res/css/views/rooms/RoomListPanel/_RoomListItemMenuView.pcss rename res/css/views/rooms/RoomListPanel/{_RoomListCell.pcss => _RoomListItemView.pcss} (79%) create mode 100644 src/components/viewmodels/roomlist/RoomListItemMenuViewModel.tsx create mode 100644 src/components/viewmodels/roomlist/RoomListItemViewModel.tsx create mode 100644 src/components/viewmodels/roomlist/utils.ts delete mode 100644 src/components/views/rooms/RoomListPanel/RoomListCell.tsx create mode 100644 src/components/views/rooms/RoomListPanel/RoomListItemMenuView.tsx create mode 100644 src/components/views/rooms/RoomListPanel/RoomListItemView.tsx create mode 100644 test/unit-tests/components/viewmodels/roomlist/RoomListItemMenuViewModel-test.tsx create mode 100644 test/unit-tests/components/viewmodels/roomlist/RoomListItemViewModel-test.tsx delete mode 100644 test/unit-tests/components/views/rooms/RoomListPanel/RoomListCell-test.tsx create mode 100644 test/unit-tests/components/views/rooms/RoomListPanel/RoomListItemMenuView-test.tsx create mode 100644 test/unit-tests/components/views/rooms/RoomListPanel/RoomListItemView-test.tsx create mode 100644 test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListItemMenuView-test.tsx.snap rename test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/{RoomListCell-test.tsx.snap => RoomListItemView-test.tsx.snap} (78%) diff --git a/package.json b/package.json index acfeff4c48..6581f0c2e0 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "@types/png-chunks-extract": "^1.0.2", "@types/react-virtualized": "^9.21.30", "@vector-im/compound-design-tokens": "^4.0.0", - "@vector-im/compound-web": "^7.6.4", + "@vector-im/compound-web": "^7.7.2", "@vector-im/matrix-wysiwyg": "2.38.2", "@zxcvbn-ts/core": "^3.0.4", "@zxcvbn-ts/language-common": "^3.0.4", diff --git a/playwright/e2e/left-panel/room-list-panel/room-list.spec.ts b/playwright/e2e/left-panel/room-list-panel/room-list.spec.ts index ff06eda0aa..493ed0d1ab 100644 --- a/playwright/e2e/left-panel/room-list-panel/room-list.spec.ts +++ b/playwright/e2e/left-panel/room-list-panel/room-list.spec.ts @@ -11,6 +11,7 @@ import { test, expect } from "../../../element-web-test"; test.describe("Room list", () => { test.use({ + displayName: "Alice", labsFlags: ["feature_new_room_list"], }); @@ -47,4 +48,33 @@ test.describe("Room list", () => { await roomListView.getByRole("gridcell", { name: "Open room room29" }).click(); await expect(page.getByRole("heading", { name: "room29", level: 1 })).toBeVisible(); }); + + test("should open the more options menu", { tag: "@screenshot" }, async ({ page, app, user }) => { + const roomListView = getRoomList(page); + const roomItem = roomListView.getByRole("gridcell", { name: "Open room room29" }); + await roomItem.hover(); + + await expect(roomItem).toMatchScreenshot("room-list-item-hover.png"); + const roomItemMenu = roomItem.getByRole("button", { name: "More Options" }); + await roomItemMenu.click(); + await expect(page).toMatchScreenshot("room-list-item-open-more-options.png"); + + // It should make the room favourited + await page.getByRole("menuitemcheckbox", { name: "Favourited" }).click(); + + // Check that the room is favourited + await roomItem.hover(); + await roomItemMenu.click(); + await expect(page.getByRole("menuitemcheckbox", { name: "Favourited" })).toBeChecked(); + // It should show the invite dialog + await page.getByRole("menuitem", { name: "invite" }).click(); + await expect(page.getByRole("heading", { name: "Invite to room29" })).toBeVisible(); + await app.closeDialog(); + + // It should leave the room + await roomItem.hover(); + await roomItemMenu.click(); + await page.getByRole("menuitem", { name: "leave room" }).click(); + await expect(roomItem).not.toBeVisible(); + }); }); diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-hover-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-hover-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..45d5588733d88ba0b0061e92c2e7c436ab95195a GIT binary patch literal 2293 zcmaKuc|6mPAICqgwdBfI!yMDp+=ggdIcGVNMLAX&O3M)=V`7DJFH|ZS@^h3BD;;hl znq#4ejF4gIAd%+E&+qsD@AuE^{r>0mc)#C|=O3?ksuSK;QXDD{0Dz>u9qtqW2zl=G zhG5|xRSZaS*eOEcr);r6Rj=|q0DzhHI4hT^ydPs%TuyUUcKyt4{H~)0exj+V=3puu z=n6Slbg60zeZe!DJ)~MX5RL1wI#aG*WS4J2dOtL@1x6Rexjt7#r5H#Fy+XH_Wr(M^ z=4Dx?AS^rA*KO|}F6MDKbl%FJwdLlA<|oHdPFBCof;{*H}xpXEi%u!Qer4scRs2EQ)M?vEG{b;vI1I@iDM^4xmj zoBHw6tD@A&R7`5nxpUbkeV!S}nh68r5=MpZOAjd%oWmAJcO6*IIsnoe#bm4dWev*% zKS5|^@$&msTO5u{rB_LV@)7p=x2?y<{8m#21@{n+T&ud6Cf9$^50#$K~4^WQVhTK93X4+Iz=@WNb~e4K++4Qj6x zJYo$NbTbbt=^__~KLwj^yhQ~Zy`utq&B^KEk1)v1=4VGfmVkFFHVE2Y=Dd(4=t8h| z%ufZF@Kwr;;<2oAb52aLJ$yZ{*B>2quZ>!R;-Cp6@#xCQuS*DbN^Iqc!cS07XRacI z{-|*i*9${Q!OTrHG;}mI{lC55?C(EMdcpNKRz-(~ejD0!R=4HP%ped5$UYU!vu&RO z-}g;>fX@BKr~Rv9Ed88iYIu?}C^E5@?olxI=R;uYJ-x5l_$xc5LEiJ9Fv9Z}c?>viGB8ddb>^PKj0$cdyW7&Yc zeX6XzU{n#HY&`<(x3$&d8&hd@lVqbb^7t-7!_^m8CByzD6_0rr=8r6(n>*-iB??4`?8=0{TmK zd+N*YZ}&4&FNSw>v>CY`YH}@oB84pJAKRzuLqyx@N|Njfccvb}fK~nLF2#lx@q4Bx zwIKwfmmVXbpL^ zhML*sudQ!hH29UE>qa0vDVP95)01QZV>fG?n|#krlFIfY;%X|wU2;4j3nA+nF$4KlxF{|t=X&Dc?d@zoQkA@TBDk={Fn(=xk6c==v$HdEL=Fl`^BsN}Fz~qJD~k=v+?V=g zP9(H2FV8VJSb7KR<(lceeiXggGG;@(NXplgI9kKRt32;XF}F! z{q3n+;X>Zt6Ua!p>1jW+Xn}viM9O_Wsjjj0^?ji@`tUXOC2t*`-n0xu3*02Y5rLJ={G-uL<3s(CEXRsL5C{}4wL}|4NT^2- zz9up!8mQh8t`U)uk6oZAOD#73b@%unJ3W`vtu0Dx#>w{1ga!q%RCx1~i;E|DUVx=j zWF#UVUpg?)J)@LTbIaQQvD%8P|A^PCTZk3eTU-atsMyIEk6*7LkcBil-IZESPdg5W zvrj%S@Qrg^H#fV@vnhUFTU$~q==@w4o&fi?-f~TlN#;mNNkJM?F`js<)&d4YPS!pu z-;;sTRe0oyLZaa5JU z4Xw|n)ITk0Y3}zGz8GIr?pi&Z*V$m)vgQDj-!`JK6?P>{0-^h`EOPvZVo!>+$xVCd zw8YpcKmv|iY@}S;!mQm^x=Xc)2$=rTs3sn_?Sb3gUHX)M;hEM$U4vmlppEh?6CnT( zhl<0=Rx8z-fg2B-dGga4w!(mCN4&}M$D6gjg+!MK)60#EPgnf^n+`ln&CrDJ_udAa zgBg|X+ibt(90JQO2@}?2;FNWePe#U zf6;?Dw0hDA6(*UnyzT!-*iIAx>D|dpZ>x;5F5|(D2BvsVX|7B^BAqCx_A^bFa#s{F zh{F7i<2Hv(y?s-!lgwnT3cWC7r7`ZQO47lA#5H{4^>nUJ-RT(C(u&?p(`;r@M}b9} z`S793A^uM&5~gXYaa1v}LI4n8;$flxFZQ*`OADt!ZI-jPJD2=|J#20Ip^Zir?ffx- M{V_bQ3hQ(I--uU5+W-In literal 0 HcmV?d00001 diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-open-more-options-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-open-more-options-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..0501bf1e4c848e3338b9b4f15e22ee9d21b2d20a GIT binary patch literal 81877 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ɦsT^-ew6 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 FKLA9!cm4nX literal 0 HcmV?d00001 diff --git a/res/css/_components.pcss b/res/css/_components.pcss index 89948acd20..1b4dc79296 100644 --- a/res/css/_components.pcss +++ b/res/css/_components.pcss @@ -271,8 +271,9 @@ @import "./views/right_panel/_WidgetCard.pcss"; @import "./views/room_settings/_AliasSettings.pcss"; @import "./views/rooms/RoomListPanel/_RoomList.pcss"; -@import "./views/rooms/RoomListPanel/_RoomListCell.pcss"; @import "./views/rooms/RoomListPanel/_RoomListHeaderView.pcss"; +@import "./views/rooms/RoomListPanel/_RoomListItemMenuView.pcss"; +@import "./views/rooms/RoomListPanel/_RoomListItemView.pcss"; @import "./views/rooms/RoomListPanel/_RoomListPanel.pcss"; @import "./views/rooms/RoomListPanel/_RoomListPrimaryFilters.pcss"; @import "./views/rooms/RoomListPanel/_RoomListSearch.pcss"; diff --git a/res/css/views/rooms/RoomListPanel/_RoomListItemMenuView.pcss b/res/css/views/rooms/RoomListPanel/_RoomListItemMenuView.pcss new file mode 100644 index 0000000000..cabd9b2d20 --- /dev/null +++ b/res/css/views/rooms/RoomListPanel/_RoomListItemMenuView.pcss @@ -0,0 +1,12 @@ +/* + * Copyright 2025 New Vector 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. + */ + +.mx_RoomListItemMenuView { + svg { + fill: var(--cpd-color-icon-primary); + } +} diff --git a/res/css/views/rooms/RoomListPanel/_RoomListCell.pcss b/res/css/views/rooms/RoomListPanel/_RoomListItemView.pcss similarity index 79% rename from res/css/views/rooms/RoomListPanel/_RoomListCell.pcss rename to res/css/views/rooms/RoomListPanel/_RoomListItemView.pcss index 812145a73e..e53ba3dc79 100644 --- a/res/css/views/rooms/RoomListPanel/_RoomListCell.pcss +++ b/res/css/views/rooms/RoomListPanel/_RoomListItemView.pcss @@ -6,7 +6,7 @@ */ /** - * The RoomCell has the following structure: + * The RoomListItemView has the following structure: * button----------------------------------------| * | <-12px-> container--------------------------| * | | room avatar <-12px-> content-----| @@ -14,19 +14,20 @@ * | | | ----------| <-- border * |---------------------------------------------| */ -.mx_RoomListCell { +.mx_RoomListItemView { all: unset; &:hover { background-color: var(--cpd-color-bg-action-secondary-hovered); } - .mx_RoomListCell_container { + .mx_RoomListItemView_container { padding-left: var(--cpd-space-3x); font: var(--cpd-font-body-md-regular); height: 100%; - .mx_RoomListCell_content { + .mx_RoomListItemView_content { + padding-right: var(--cpd-space-3x); height: 100%; flex: 1; /* The border is only under the room name and the future hover menu */ @@ -42,3 +43,7 @@ } } } + +.mx_RoomListItemView_menu_open { + background-color: var(--cpd-color-bg-action-secondary-hovered); +} diff --git a/src/components/viewmodels/roomlist/RoomListItemMenuViewModel.tsx b/src/components/viewmodels/roomlist/RoomListItemMenuViewModel.tsx new file mode 100644 index 0000000000..6b089495a0 --- /dev/null +++ b/src/components/viewmodels/roomlist/RoomListItemMenuViewModel.tsx @@ -0,0 +1,180 @@ +/* + * Copyright 2025 New Vector 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 { useCallback } from "react"; +import { type Room, RoomEvent } from "matrix-js-sdk/src/matrix"; + +import { useMatrixClientContext } from "../../../contexts/MatrixClientContext"; +import { useEventEmitterState } from "../../../hooks/useEventEmitter"; +import { useUnreadNotifications } from "../../../hooks/useUnreadNotifications"; +import { hasAccessToOptionsMenu } from "./utils"; +import DMRoomMap from "../../../utils/DMRoomMap"; +import { DefaultTagID } from "../../../stores/room-list/models"; +import { NotificationLevel } from "../../../stores/notifications/NotificationLevel"; +import { shouldShowComponent } from "../../../customisations/helpers/UIComponents"; +import { UIComponent } from "../../../settings/UIFeature"; +import dispatcher from "../../../dispatcher/dispatcher"; +import { clearRoomNotification, setMarkedUnreadState } from "../../../utils/notifications"; +import PosthogTrackers from "../../../PosthogTrackers"; +import { tagRoom } from "../../../utils/room/tagRoom"; + +export interface RoomListItemMenuViewState { + /** + * Whether the more options menu should be shown. + */ + showMoreOptionsMenu: boolean; + /** + * Whether the room is a favourite room. + */ + isFavourite: boolean; + /** + * Can invite other user's in the room. + */ + canInvite: boolean; + /** + * Can copy the room link. + */ + canCopyRoomLink: boolean; + /** + * Can mark the room as read. + */ + canMarkAsRead: boolean; + /** + * Can mark the room as unread. + */ + canMarkAsUnread: boolean; + /** + * Mark the room as read. + * @param evt + */ + markAsRead: (evt: Event) => void; + /** + * Mark the room as unread. + * @param evt + */ + markAsUnread: (evt: Event) => void; + /** + * Toggle the room as favourite. + * @param evt + */ + toggleFavorite: (evt: Event) => void; + /** + * Toggle the room as low priority. + */ + toggleLowPriority: () => void; + /** + * Invite other users in the room. + * @param evt + */ + invite: (evt: Event) => void; + /** + * Copy the room link in the clipboard. + * @param evt + */ + copyRoomLink: (evt: Event) => void; + /** + * Leave the room. + * @param evt + */ + leaveRoom: (evt: Event) => void; +} + +export function useRoomListItemMenuViewModel(room: Room): RoomListItemMenuViewState { + const matrixClient = useMatrixClientContext(); + const roomTags = useEventEmitterState(room, RoomEvent.Tags, () => room.tags); + const { level: notificationLevel } = useUnreadNotifications(room); + + const showMoreOptionsMenu = hasAccessToOptionsMenu(room); + + const isDm = Boolean(DMRoomMap.shared().getUserIdForRoomId(room.roomId)); + const isFavourite = Boolean(roomTags[DefaultTagID.Favourite]); + const isArchived = Boolean(roomTags[DefaultTagID.Archived]); + + const canMarkAsRead = notificationLevel > NotificationLevel.None; + const canMarkAsUnread = !canMarkAsRead && !isArchived; + + const canInvite = + room.canInvite(matrixClient.getUserId()!) && !isDm && shouldShowComponent(UIComponent.InviteUsers); + const canCopyRoomLink = !isDm; + + // Actions + + const markAsRead = useCallback( + async (evt: Event): Promise => { + await clearRoomNotification(room, matrixClient); + PosthogTrackers.trackInteraction("WebRoomListRoomTileContextMenuMarkRead", evt); + }, + [room, matrixClient], + ); + + const markAsUnread = useCallback( + async (evt: Event): Promise => { + await setMarkedUnreadState(room, matrixClient, true); + PosthogTrackers.trackInteraction("WebRoomListRoomTileContextMenuMarkUnread", evt); + }, + [room, matrixClient], + ); + + const toggleFavorite = useCallback( + (evt: Event): void => { + tagRoom(room, DefaultTagID.Favourite); + PosthogTrackers.trackInteraction("WebRoomListRoomTileContextMenuFavouriteToggle", evt); + }, + [room], + ); + + const toggleLowPriority = useCallback((): void => tagRoom(room, DefaultTagID.LowPriority), [room]); + + const invite = useCallback( + (evt: Event): void => { + dispatcher.dispatch({ + action: "view_invite", + roomId: room.roomId, + }); + PosthogTrackers.trackInteraction("WebRoomListRoomTileContextMenuInviteItem", evt); + }, + [room], + ); + + const copyRoomLink = useCallback( + (evt: Event): void => { + dispatcher.dispatch({ + action: "copy_room", + room_id: room.roomId, + }); + PosthogTrackers.trackInteraction("WebRoomListRoomTileContextMenuFavouriteToggle", evt); + }, + [room], + ); + + const leaveRoom = useCallback( + (evt: Event): void => { + dispatcher.dispatch({ + action: isArchived ? "forget_room" : "leave_room", + room_id: room.roomId, + }); + PosthogTrackers.trackInteraction("WebRoomListRoomTileContextMenuLeaveItem", evt); + }, + [room, isArchived], + ); + + return { + showMoreOptionsMenu, + isFavourite, + canInvite, + canCopyRoomLink, + canMarkAsRead, + canMarkAsUnread, + markAsRead, + markAsUnread, + toggleFavorite, + toggleLowPriority, + invite, + copyRoomLink, + leaveRoom, + }; +} diff --git a/src/components/viewmodels/roomlist/RoomListItemViewModel.tsx b/src/components/viewmodels/roomlist/RoomListItemViewModel.tsx new file mode 100644 index 0000000000..9e38e6e8d8 --- /dev/null +++ b/src/components/viewmodels/roomlist/RoomListItemViewModel.tsx @@ -0,0 +1,49 @@ +/* + * Copyright 2025 New Vector 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 { useCallback } from "react"; +import { type Room } from "matrix-js-sdk/src/matrix"; + +import dispatcher from "../../../dispatcher/dispatcher"; +import type { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; +import { Action } from "../../../dispatcher/actions"; +import { hasAccessToOptionsMenu } from "./utils"; + +export interface RoomListItemViewState { + /** + * Whether the hover menu should be shown. + */ + showHoverMenu: boolean; + /** + * Open the room having given roomId. + */ + openRoom: () => void; +} + +/** + * View model for the room list item + * @see {@link RoomListItemViewState} for more information about what this view model returns. + */ +export function useRoomListItemViewModel(room: Room): RoomListItemViewState { + // incoming: Check notification menu rights + const showHoverMenu = hasAccessToOptionsMenu(room); + + // Actions + + const openRoom = useCallback((): void => { + dispatcher.dispatch({ + action: Action.ViewRoom, + room_id: room.roomId, + metricsTrigger: "RoomList", + }); + }, [room]); + + return { + showHoverMenu, + openRoom, + }; +} diff --git a/src/components/viewmodels/roomlist/RoomListViewModel.tsx b/src/components/viewmodels/roomlist/RoomListViewModel.tsx index c195613d7d..b1b39e7f0c 100644 --- a/src/components/viewmodels/roomlist/RoomListViewModel.tsx +++ b/src/components/viewmodels/roomlist/RoomListViewModel.tsx @@ -5,12 +5,7 @@ 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 { useCallback } from "react"; - import type { Room } from "matrix-js-sdk/src/matrix"; -import type { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; -import dispatcher from "../../../dispatcher/dispatcher"; -import { Action } from "../../../dispatcher/actions"; import { type PrimaryFilter, type SecondaryFilters, useFilteredRooms } from "./useFilteredRooms"; import { type SortOption, useSorter } from "./useSorter"; @@ -19,12 +14,6 @@ export interface RoomListViewState { * A list of rooms to be displayed in the left panel. */ rooms: Room[]; - - /** - * Open the room having given roomId. - */ - openRoom: (roomId: string) => void; - /** * A list of objects that provide the view enough information * to render primary room filters. @@ -60,17 +49,8 @@ export function useRoomListViewModel(): RoomListViewState { const { primaryFilters, rooms, activateSecondaryFilter, activeSecondaryFilter } = useFilteredRooms(); const { activeSortOption, sort } = useSorter(); - const openRoom = useCallback((roomId: string): void => { - dispatcher.dispatch({ - action: Action.ViewRoom, - room_id: roomId, - metricsTrigger: "RoomList", - }); - }, []); - return { rooms, - openRoom, primaryFilters, activateSecondaryFilter, activeSecondaryFilter, diff --git a/src/components/viewmodels/roomlist/utils.ts b/src/components/viewmodels/roomlist/utils.ts new file mode 100644 index 0000000000..3886d0e3b0 --- /dev/null +++ b/src/components/viewmodels/roomlist/utils.ts @@ -0,0 +1,25 @@ +/* + * Copyright 2025 New Vector 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 { type Room, KnownMembership } from "matrix-js-sdk/src/matrix"; + +import { isKnockDenied } from "../../../utils/membership"; +import { shouldShowComponent } from "../../../customisations/helpers/UIComponents"; +import { UIComponent } from "../../../settings/UIFeature"; + +/** + * Check if the user has access to the options menu. + * @param room + */ +export function hasAccessToOptionsMenu(room: Room): boolean { + return ( + room.getMyMembership() === KnownMembership.Invite || + (room.getMyMembership() !== KnownMembership.Knock && + !isKnockDenied(room) && + shouldShowComponent(UIComponent.RoomOptionsMenu)) + ); +} diff --git a/src/components/views/rooms/RoomListPanel/RoomList.tsx b/src/components/views/rooms/RoomListPanel/RoomList.tsx index 3645a72bb9..006d1b9732 100644 --- a/src/components/views/rooms/RoomListPanel/RoomList.tsx +++ b/src/components/views/rooms/RoomListPanel/RoomList.tsx @@ -10,7 +10,7 @@ import { AutoSizer, List, type ListRowProps } from "react-virtualized"; import { type RoomListViewState } from "../../../viewmodels/roomlist/RoomListViewModel"; import { _t } from "../../../../languageHandler"; -import { RoomListCell } from "./RoomListCell"; +import { RoomListItemView } from "./RoomListItemView"; interface RoomListProps { /** @@ -22,12 +22,10 @@ interface RoomListProps { /** * A virtualized list of rooms. */ -export function RoomList({ vm: { rooms, openRoom } }: RoomListProps): JSX.Element { +export function RoomList({ vm: { rooms } }: RoomListProps): JSX.Element { const roomRendererMemoized = useCallback( - ({ key, index, style }: ListRowProps) => ( - openRoom(rooms[index].roomId)} /> - ), - [rooms, openRoom], + ({ key, index, style }: ListRowProps) => , + [rooms], ); // The first div is needed to make the virtualized list take all the remaining space and scroll correctly diff --git a/src/components/views/rooms/RoomListPanel/RoomListCell.tsx b/src/components/views/rooms/RoomListPanel/RoomListCell.tsx deleted file mode 100644 index a5e9cc5df2..0000000000 --- a/src/components/views/rooms/RoomListPanel/RoomListCell.tsx +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2025 New Vector 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 } from "react"; -import { type Room } from "matrix-js-sdk/src/matrix"; - -import { _t } from "../../../../languageHandler"; -import { Flex } from "../../../utils/Flex"; -import DecoratedRoomAvatar from "../../avatars/DecoratedRoomAvatar"; - -interface RoomListCellProps extends React.HTMLAttributes { - /** - * The room to display - */ - room: Room; -} - -/** - * A cell in the room list - */ -export function RoomListCell({ room, ...props }: RoomListCellProps): JSX.Element { - return ( - - ); -} diff --git a/src/components/views/rooms/RoomListPanel/RoomListItemMenuView.tsx b/src/components/views/rooms/RoomListPanel/RoomListItemMenuView.tsx new file mode 100644 index 0000000000..ca08bf698c --- /dev/null +++ b/src/components/views/rooms/RoomListPanel/RoomListItemMenuView.tsx @@ -0,0 +1,154 @@ +/* + * Copyright 2025 New Vector 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 ComponentProps, forwardRef, type JSX, useState } from "react"; +import { IconButton, Menu, MenuItem, Separator, ToggleMenuItem, Tooltip } from "@vector-im/compound-web"; +import MarkAsReadIcon from "@vector-im/compound-design-tokens/assets/web/icons/mark-as-read"; +import MarkAsUnreadIcon from "@vector-im/compound-design-tokens/assets/web/icons/mark-as-unread"; +import FavouriteIcon from "@vector-im/compound-design-tokens/assets/web/icons/favourite"; +import ArrowDownIcon from "@vector-im/compound-design-tokens/assets/web/icons/arrow-down"; +import UserAddIcon from "@vector-im/compound-design-tokens/assets/web/icons/user-add"; +import LinkIcon from "@vector-im/compound-design-tokens/assets/web/icons/link"; +import LeaveIcon from "@vector-im/compound-design-tokens/assets/web/icons/leave"; +import OverflowIcon from "@vector-im/compound-design-tokens/assets/web/icons/overflow-horizontal"; +import { type Room } from "matrix-js-sdk/src/matrix"; + +import { _t } from "../../../../languageHandler"; +import { Flex } from "../../../utils/Flex"; +import { + type RoomListItemMenuViewState, + useRoomListItemMenuViewModel, +} from "../../../viewmodels/roomlist/RoomListItemMenuViewModel"; + +interface RoomListItemMenuViewProps { + /** + * The room to display the menu for. + */ + room: Room; + /** + * Set the menu open state. + * @param isOpen + */ + setMenuOpen: (isOpen: boolean) => void; +} + +/** + * A view for the room list item menu. + */ +export function RoomListItemMenuView({ room, setMenuOpen }: RoomListItemMenuViewProps): JSX.Element { + const vm = useRoomListItemMenuViewModel(room); + + return ( + + {vm.showMoreOptionsMenu && } + + ); +} + +interface MoreOptionsMenuProps { + /** + * The view model state for the menu. + */ + vm: RoomListItemMenuViewState; + /** + * Set the menu open state. + * @param isOpen + */ + setMenuOpen: (isOpen: boolean) => void; +} + +/** + * The more options menu for the room list item. + */ +function MoreOptionsMenu({ vm, setMenuOpen }: MoreOptionsMenuProps): JSX.Element { + const [open, setOpen] = useState(false); + + return ( + { + setOpen(isOpen); + setMenuOpen(isOpen); + }} + title={_t("room_list|room|more_options")} + showTitle={false} + align="start" + trigger={} + > + {vm.canMarkAsRead && ( + evt.stopPropagation()} + /> + )} + {vm.canMarkAsUnread && ( + evt.stopPropagation()} + /> + )} + evt.stopPropagation()} + /> + evt.stopPropagation()} + /> + {vm.canInvite && ( + evt.stopPropagation()} + /> + )} + {vm.canCopyRoomLink && ( + evt.stopPropagation()} + /> + )} + + evt.stopPropagation()} + /> + + ); +} + +interface MoreOptionsButtonProps extends ComponentProps {} + +/** + * A button to trigger the more options menu. + */ +export const MoreOptionsButton = forwardRef( + function MoreOptionsButton(props, ref) { + return ( + + + + + + ); + }, +); diff --git a/src/components/views/rooms/RoomListPanel/RoomListItemView.tsx b/src/components/views/rooms/RoomListPanel/RoomListItemView.tsx new file mode 100644 index 0000000000..20173e324e --- /dev/null +++ b/src/components/views/rooms/RoomListPanel/RoomListItemView.tsx @@ -0,0 +1,76 @@ +/* + * Copyright 2025 New Vector 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, useState } from "react"; +import { type Room } from "matrix-js-sdk/src/matrix"; +import classNames from "classnames"; + +import { useRoomListItemViewModel } from "../../../viewmodels/roomlist/RoomListItemViewModel"; +import DecoratedRoomAvatar from "../../avatars/DecoratedRoomAvatar"; +import { Flex } from "../../../utils/Flex"; +import { _t } from "../../../../languageHandler"; +import { RoomListItemMenuView } from "./RoomListItemMenuView"; + +interface RoomListItemViewPropsProps extends React.HTMLAttributes { + /** + * The room to display + */ + room: Room; +} + +/** + * An item in the room list + */ +export function RoomListItemView({ room, ...props }: RoomListItemViewPropsProps): JSX.Element { + const vm = useRoomListItemViewModel(room); + + const [isHover, setIsHover] = useState(false); + const [isMenuOpen, setIsMenuOpen] = useState(false); + // The compound menu in RoomListItemMenuView needs to be rendered when the hover menu is shown + // Using display: none; and then display:flex when hovered in CSS causes the menu to be misaligned + const showHoverDecoration = (isMenuOpen || isHover) && vm.showHoverMenu; + + return ( + + ); +} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index d85b15d25b..34e0e98be3 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2112,6 +2112,14 @@ "other": "Currently joining %(count)s rooms" }, "list_title": "Room list", + "more_options": { + "copy_link": "Copy room link", + "favourited": "Favourited", + "leave_room": "Leave room", + "low_priority": "Low priority", + "mark_read": "Mark as read", + "mark_unread": "Mark as unread" + }, "notification_options": "Notification options", "open_space_menu": "Open space menu", "primary_filters": "Room list filters", @@ -2120,6 +2128,7 @@ "other": "Currently removing messages in %(count)s rooms" }, "room": { + "more_options": "More Options", "open_room": "Open room %(roomName)s" }, "show_less": "Show less", diff --git a/test/test-utils/test-utils.ts b/test/test-utils/test-utils.ts index 321ff8b27e..1f6351b7b9 100644 --- a/test/test-utils/test-utils.ts +++ b/test/test-utils/test-utils.ts @@ -606,7 +606,7 @@ export function mkStubRoom( getState: (): RoomState | undefined => undefined, } as unknown as EventTimeline; return { - canInvite: jest.fn(), + canInvite: jest.fn().mockReturnValue(false), client, findThreadForEvent: jest.fn(), createThreadsTimelineSets: jest.fn().mockReturnValue(new Promise(() => {})), diff --git a/test/unit-tests/components/viewmodels/roomlist/RoomListItemMenuViewModel-test.tsx b/test/unit-tests/components/viewmodels/roomlist/RoomListItemMenuViewModel-test.tsx new file mode 100644 index 0000000000..89dd644208 --- /dev/null +++ b/test/unit-tests/components/viewmodels/roomlist/RoomListItemMenuViewModel-test.tsx @@ -0,0 +1,173 @@ +/* + * Copyright 2025 New Vector 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 { renderHook } from "jest-matrix-react"; +import { mocked } from "jest-mock"; +import { type MatrixClient, type Room } from "matrix-js-sdk/src/matrix"; + +import { mkStubRoom, stubClient, withClientContextRenderOptions } from "../../../../test-utils"; +import { useRoomListItemMenuViewModel } from "../../../../../src/components/viewmodels/roomlist/RoomListItemMenuViewModel"; +import { hasAccessToOptionsMenu } from "../../../../../src/components/viewmodels/roomlist/utils"; +import DMRoomMap from "../../../../../src/utils/DMRoomMap"; +import { DefaultTagID } from "../../../../../src/stores/room-list/models"; +import { useUnreadNotifications } from "../../../../../src/hooks/useUnreadNotifications"; +import { NotificationLevel } from "../../../../../src/stores/notifications/NotificationLevel"; +import { clearRoomNotification, setMarkedUnreadState } from "../../../../../src/utils/notifications"; +import { tagRoom } from "../../../../../src/utils/room/tagRoom"; +import dispatcher from "../../../../../src/dispatcher/dispatcher"; + +jest.mock("../../../../../src/components/viewmodels/roomlist/utils", () => ({ + hasAccessToOptionsMenu: jest.fn().mockReturnValue(false), +})); + +jest.mock("../../../../../src/hooks/useUnreadNotifications", () => ({ + useUnreadNotifications: jest.fn(), +})); + +jest.mock("../../../../../src/utils/notifications", () => ({ + clearRoomNotification: jest.fn(), + setMarkedUnreadState: jest.fn(), +})); + +jest.mock("../../../../../src/utils/room/tagRoom", () => ({ + tagRoom: jest.fn(), +})); + +describe("RoomListItemMenuViewModel", () => { + let matrixClient: MatrixClient; + let room: Room; + + beforeEach(() => { + matrixClient = stubClient(); + room = mkStubRoom("roomId", "roomName", matrixClient); + + DMRoomMap.makeShared(matrixClient); + jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(null); + + mocked(useUnreadNotifications).mockReturnValue({ symbol: null, count: 0, level: NotificationLevel.None }); + jest.spyOn(dispatcher, "dispatch"); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + function render() { + return renderHook(() => useRoomListItemMenuViewModel(room), withClientContextRenderOptions(matrixClient)); + } + + it("default", () => { + const { result } = render(); + expect(result.current.showMoreOptionsMenu).toBe(false); + expect(result.current.canInvite).toBe(false); + expect(result.current.isFavourite).toBe(false); + expect(result.current.canCopyRoomLink).toBe(true); + expect(result.current.canMarkAsRead).toBe(false); + expect(result.current.canMarkAsUnread).toBe(true); + }); + + it("should has showMoreOptionsMenu to be true", () => { + mocked(hasAccessToOptionsMenu).mockReturnValue(true); + const { result } = render(); + expect(result.current.showMoreOptionsMenu).toBe(true); + }); + + it("should be able to invite", () => { + jest.spyOn(room, "canInvite").mockReturnValue(true); + const { result } = render(); + expect(result.current.canInvite).toBe(true); + }); + + it("should be a favourite", () => { + room.tags = { [DefaultTagID.Favourite]: { order: 0 } }; + const { result } = render(); + expect(result.current.isFavourite).toBe(true); + }); + + it("should not be able to copy the room link", () => { + jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue("userId"); + const { result } = render(); + expect(result.current.canCopyRoomLink).toBe(false); + }); + + it("should be able to mark as read", () => { + // Add a notification + mocked(useUnreadNotifications).mockReturnValue({ + symbol: null, + count: 1, + level: NotificationLevel.Notification, + }); + const { result } = render(); + expect(result.current.canMarkAsRead).toBe(true); + expect(result.current.canMarkAsUnread).toBe(false); + }); + + // Actions + + it("should mark as read", () => { + const { result } = render(); + result.current.markAsRead(new Event("click")); + expect(mocked(clearRoomNotification)).toHaveBeenCalledWith(room, matrixClient); + }); + + it("should mark as unread", () => { + const { result } = render(); + result.current.markAsUnread(new Event("click")); + expect(mocked(setMarkedUnreadState)).toHaveBeenCalledWith(room, matrixClient, true); + }); + + it("should tag a room as favourite", () => { + const { result } = render(); + result.current.toggleFavorite(new Event("click")); + expect(mocked(tagRoom)).toHaveBeenCalledWith(room, DefaultTagID.Favourite); + }); + + it("should tag a room as low priority", () => { + const { result } = render(); + result.current.toggleLowPriority(); + expect(mocked(tagRoom)).toHaveBeenCalledWith(room, DefaultTagID.LowPriority); + }); + + it("should dispatch invite action", () => { + const { result } = render(); + result.current.invite(new Event("click")); + expect(dispatcher.dispatch).toHaveBeenCalledWith({ + action: "view_invite", + roomId: room.roomId, + }); + }); + + it("should dispatch a copy room action", () => { + const { result } = render(); + result.current.copyRoomLink(new Event("click")); + expect(dispatcher.dispatch).toHaveBeenCalledWith({ + action: "copy_room", + room_id: room.roomId, + }); + }); + + it("should dispatch forget room action", () => { + // forget room is only available for archived rooms + room.tags = { [DefaultTagID.Archived]: { order: 0 } }; + + const { result } = render(); + result.current.leaveRoom(new Event("click")); + expect(dispatcher.dispatch).toHaveBeenCalledWith({ + action: "forget_room", + room_id: room.roomId, + }); + }); + + it("should dispatch leave room action", () => { + const { result } = render(); + result.current.leaveRoom(new Event("click")); + expect(dispatcher.dispatch).toHaveBeenCalledWith({ + action: "leave_room", + room_id: room.roomId, + }); + }); +}); diff --git a/test/unit-tests/components/viewmodels/roomlist/RoomListItemViewModel-test.tsx b/test/unit-tests/components/viewmodels/roomlist/RoomListItemViewModel-test.tsx new file mode 100644 index 0000000000..2854c433e7 --- /dev/null +++ b/test/unit-tests/components/viewmodels/roomlist/RoomListItemViewModel-test.tsx @@ -0,0 +1,49 @@ +/* + * Copyright 2025 New Vector 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 { renderHook } from "jest-matrix-react"; +import { type Room } from "matrix-js-sdk/src/matrix"; +import { mocked } from "jest-mock"; + +import dispatcher from "../../../../../src/dispatcher/dispatcher"; +import { Action } from "../../../../../src/dispatcher/actions"; +import { useRoomListItemViewModel } from "../../../../../src/components/viewmodels/roomlist/RoomListItemViewModel"; +import { createTestClient, mkStubRoom } from "../../../../test-utils"; +import { hasAccessToOptionsMenu } from "../../../../../src/components/viewmodels/roomlist/utils"; + +jest.mock("../../../../../src/components/viewmodels/roomlist/utils", () => ({ + hasAccessToOptionsMenu: jest.fn().mockReturnValue(false), +})); + +describe("RoomListItemViewModel", () => { + let room: Room; + + beforeEach(() => { + const matrixClient = createTestClient(); + room = mkStubRoom("roomId", "roomName", matrixClient); + }); + + it("should dispatch view room action on openRoom", async () => { + const { result: vm } = renderHook(() => useRoomListItemViewModel(room)); + + const fn = jest.spyOn(dispatcher, "dispatch"); + vm.current.openRoom(); + expect(fn).toHaveBeenCalledWith( + expect.objectContaining({ + action: Action.ViewRoom, + room_id: room.roomId, + metricsTrigger: "RoomList", + }), + ); + }); + + it("should show hover menu if user has access to options menu", async () => { + mocked(hasAccessToOptionsMenu).mockReturnValue(true); + const { result: vm } = renderHook(() => useRoomListItemViewModel(room)); + expect(vm.current.showHoverMenu).toBe(true); + }); +}); diff --git a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx index e1e2f6ac57..99f1483d4a 100644 --- a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx +++ b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx @@ -12,8 +12,6 @@ import RoomListStoreV3 from "../../../../../src/stores/room-list-v3/RoomListStor import { mkStubRoom } from "../../../../test-utils"; import { LISTS_UPDATE_EVENT } from "../../../../../src/stores/room-list/SlidingRoomListStore"; import { useRoomListViewModel } from "../../../../../src/components/viewmodels/roomlist/RoomListViewModel"; -import dispatcher from "../../../../../src/dispatcher/dispatcher"; -import { Action } from "../../../../../src/dispatcher/actions"; import { FilterKey } from "../../../../../src/stores/room-list-v3/skip-list/filters"; import { SecondaryFilters } from "../../../../../src/components/viewmodels/roomlist/useFilteredRooms"; import { SortingAlgorithm } from "../../../../../src/stores/room-list-v3/skip-list/sorters"; @@ -56,21 +54,6 @@ describe("RoomListViewModel", () => { }); }); - it("should dispatch view room action on openRoom", async () => { - const { rooms } = mockAndCreateRooms(); - const { result: vm } = renderHook(() => useRoomListViewModel()); - - const fn = jest.spyOn(dispatcher, "dispatch"); - act(() => vm.current.openRoom(rooms[7].roomId)); - expect(fn).toHaveBeenCalledWith( - expect.objectContaining({ - action: Action.ViewRoom, - room_id: rooms[7].roomId, - metricsTrigger: "RoomList", - }), - ); - }); - describe("Filters", () => { it("should provide list of available filters", () => { mockAndCreateRooms(); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx index cd6ed29e27..11764df7b7 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx @@ -7,8 +7,7 @@ import React from "react"; import { type MatrixClient } from "matrix-js-sdk/src/matrix"; -import { render, screen, waitFor } from "jest-matrix-react"; -import userEvent from "@testing-library/user-event"; +import { render } from "jest-matrix-react"; import { mkRoom, stubClient } from "../../../../../test-utils"; import { type RoomListViewState } from "../../../../../../src/components/viewmodels/roomlist/RoomListViewModel"; @@ -31,7 +30,6 @@ describe("", () => { const rooms = Array.from({ length: 10 }, (_, i) => mkRoom(matrixClient, `room${i}`)); vm = { rooms, - openRoom: jest.fn(), primaryFilters: [], activateSecondaryFilter: () => {}, activeSecondaryFilter: SecondaryFilters.AllActivity, @@ -48,15 +46,4 @@ describe("", () => { const { asFragment } = render(); expect(asFragment()).toMatchSnapshot(); }); - - it("should open the room", async () => { - const user = userEvent.setup(); - - render(); - await waitFor(async () => { - expect(screen.getByRole("gridcell", { name: "Open room room9" })).toBeVisible(); - await user.click(screen.getByRole("gridcell", { name: "Open room room9" })); - }); - expect(vm.openRoom).toHaveBeenCalledWith(vm.rooms[9].roomId); - }); }); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListCell-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListCell-test.tsx deleted file mode 100644 index 3bbde9fb92..0000000000 --- a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListCell-test.tsx +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2025 New Vector 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 from "react"; -import { type MatrixClient, type Room } from "matrix-js-sdk/src/matrix"; -import { render, screen } from "jest-matrix-react"; -import userEvent from "@testing-library/user-event"; - -import { mkRoom, stubClient } from "../../../../../test-utils"; -import { RoomListCell } from "../../../../../../src/components/views/rooms/RoomListPanel/RoomListCell"; -import DMRoomMap from "../../../../../../src/utils/DMRoomMap"; - -describe("", () => { - let matrixClient: MatrixClient; - let room: Room; - - beforeEach(() => { - matrixClient = stubClient(); - room = mkRoom(matrixClient, "room1"); - - DMRoomMap.makeShared(matrixClient); - jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(null); - }); - - test("should render a room cell", () => { - const onClick = jest.fn(); - const { asFragment } = render(); - expect(asFragment()).toMatchSnapshot(); - }); - - test("should call onClick when clicked", async () => { - const user = userEvent.setup(); - - const onClick = jest.fn(); - render(); - - await user.click(screen.getByRole("button", { name: `Open room ${room.name}` })); - expect(onClick).toHaveBeenCalled(); - }); -}); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListItemMenuView-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListItemMenuView-test.tsx new file mode 100644 index 0000000000..de1d37ed08 --- /dev/null +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListItemMenuView-test.tsx @@ -0,0 +1,110 @@ +/* + * Copyright 2025 New Vector 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 from "react"; +import { mocked } from "jest-mock"; +import { render, screen } from "jest-matrix-react"; +import userEvent from "@testing-library/user-event"; + +import { + type RoomListItemMenuViewState, + useRoomListItemMenuViewModel, +} from "../../../../../../src/components/viewmodels/roomlist/RoomListItemMenuViewModel"; +import type { MatrixClient, Room } from "matrix-js-sdk/src/matrix"; +import { mkRoom, stubClient } from "../../../../../test-utils"; +import { RoomListItemMenuView } from "../../../../../../src/components/views/rooms/RoomListPanel/RoomListItemMenuView"; + +jest.mock("../../../../../../src/components/viewmodels/roomlist/RoomListItemMenuViewModel", () => ({ + useRoomListItemMenuViewModel: jest.fn(), +})); + +describe("", () => { + const defaultValue: RoomListItemMenuViewState = { + showMoreOptionsMenu: true, + isFavourite: true, + canInvite: true, + canMarkAsUnread: true, + canMarkAsRead: true, + canCopyRoomLink: true, + copyRoomLink: jest.fn(), + markAsUnread: jest.fn(), + markAsRead: jest.fn(), + leaveRoom: jest.fn(), + toggleLowPriority: jest.fn(), + toggleFavorite: jest.fn(), + invite: jest.fn(), + }; + + let matrixClient: MatrixClient; + let room: Room; + + beforeEach(() => { + mocked(useRoomListItemMenuViewModel).mockReturnValue(defaultValue); + matrixClient = stubClient(); + room = mkRoom(matrixClient, "room1"); + }); + + function renderMenu(setMenuOpen = jest.fn()) { + return render(); + } + + it("should render the more options menu", () => { + const { asFragment } = renderMenu(); + expect(screen.getByRole("button", { name: "More Options" })).toBeInTheDocument(); + expect(asFragment()).toMatchSnapshot(); + }); + + it("should not render the more options menu when showMoreOptionsMenu is false", () => { + mocked(useRoomListItemMenuViewModel).mockReturnValue({ ...defaultValue, showMoreOptionsMenu: false }); + renderMenu(); + expect(screen.queryByRole("button", { name: "More Options" })).toBeNull(); + }); + + it("should call setMenuOpen when the menu is opened", async () => { + const user = userEvent.setup(); + const setMenuOpen = jest.fn(); + renderMenu(setMenuOpen); + + await user.click(screen.getByRole("button", { name: "More Options" })); + expect(setMenuOpen).toHaveBeenCalledWith(true); + }); + + it("should display all the buttons and have the actions linked", async () => { + const user = userEvent.setup(); + renderMenu(); + + const openMenu = screen.getByRole("button", { name: "More Options" }); + await user.click(openMenu); + + await user.click(screen.getByRole("menuitem", { name: "Mark as read" })); + expect(defaultValue.markAsRead).toHaveBeenCalled(); + + await user.click(openMenu); + await user.click(screen.getByRole("menuitem", { name: "Mark as unread" })); + expect(defaultValue.markAsUnread).toHaveBeenCalled(); + + await user.click(openMenu); + await user.click(screen.getByRole("menuitemcheckbox", { name: "Favourited" })); + expect(defaultValue.toggleFavorite).toHaveBeenCalled(); + + await user.click(openMenu); + await user.click(screen.getByRole("menuitem", { name: "Low priority" })); + expect(defaultValue.toggleLowPriority).toHaveBeenCalled(); + + await user.click(openMenu); + await user.click(screen.getByRole("menuitem", { name: "Invite" })); + expect(defaultValue.invite).toHaveBeenCalled(); + + await user.click(openMenu); + await user.click(screen.getByRole("menuitem", { name: "Copy room link" })); + expect(defaultValue.copyRoomLink).toHaveBeenCalled(); + + await user.click(openMenu); + await user.click(screen.getByRole("menuitem", { name: "Leave room" })); + expect(defaultValue.leaveRoom).toHaveBeenCalled(); + }); +}); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListItemView-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListItemView-test.tsx new file mode 100644 index 0000000000..3023f9a9a7 --- /dev/null +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListItemView-test.tsx @@ -0,0 +1,68 @@ +/* + * Copyright 2025 New Vector 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 from "react"; +import { type MatrixClient, type Room } from "matrix-js-sdk/src/matrix"; +import { render, screen, waitFor } from "jest-matrix-react"; +import userEvent from "@testing-library/user-event"; +import { mocked } from "jest-mock"; + +import { mkRoom, stubClient, withClientContextRenderOptions } from "../../../../../test-utils"; +import { RoomListItemView } from "../../../../../../src/components/views/rooms/RoomListPanel/RoomListItemView"; +import DMRoomMap from "../../../../../../src/utils/DMRoomMap"; +import { + type RoomListItemViewState, + useRoomListItemViewModel, +} from "../../../../../../src/components/viewmodels/roomlist/RoomListItemViewModel"; + +jest.mock("../../../../../../src/components/viewmodels/roomlist/RoomListItemViewModel", () => ({ + useRoomListItemViewModel: jest.fn(), +})); + +describe("", () => { + const defaultValue: RoomListItemViewState = { + openRoom: jest.fn(), + showHoverMenu: false, + }; + let matrixClient: MatrixClient; + let room: Room; + + beforeEach(() => { + mocked(useRoomListItemViewModel).mockReturnValue(defaultValue); + matrixClient = stubClient(); + room = mkRoom(matrixClient, "room1"); + + DMRoomMap.makeShared(matrixClient); + jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(null); + }); + + test("should render a room item", () => { + const onClick = jest.fn(); + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); + + test("should call openRoom when clicked", async () => { + const user = userEvent.setup(); + render(); + + await user.click(screen.getByRole("button", { name: `Open room ${room.name}` })); + expect(defaultValue.openRoom).toHaveBeenCalled(); + }); + + test("should hover decoration if hovered", async () => { + mocked(useRoomListItemViewModel).mockReturnValue({ ...defaultValue, showHoverMenu: true }); + + const user = userEvent.setup(); + render(, withClientContextRenderOptions(matrixClient)); + const listItem = screen.getByRole("button", { name: `Open room ${room.name}` }); + expect(screen.queryByRole("button", { name: "More Options" })).toBeNull(); + + await user.hover(listItem); + await waitFor(() => expect(screen.getByRole("button", { name: "More Options" })).toBeInTheDocument()); + }); +}); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPrimaryFilters-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPrimaryFilters-test.tsx index 3bb1968371..a3e60f765d 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPrimaryFilters-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPrimaryFilters-test.tsx @@ -20,7 +20,6 @@ describe("", () => { beforeEach(() => { vm = { rooms: [], - openRoom: jest.fn(), primaryFilters: [ { name: "People", active: false, toggle: jest.fn() }, { name: "Rooms", active: true, toggle: jest.fn() }, diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomList-test.tsx.snap b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomList-test.tsx.snap index 8d3559031a..37f8a0364a 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomList-test.tsx.snap +++ b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomList-test.tsx.snap @@ -24,13 +24,13 @@ exports[` should render a room list 1`] = ` > +
+ +`; diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListCell-test.tsx.snap b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListItemView-test.tsx.snap similarity index 78% rename from test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListCell-test.tsx.snap rename to test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListItemView-test.tsx.snap index 3a28a1ad27..e63d9f91a6 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListCell-test.tsx.snap +++ b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListItemView-test.tsx.snap @@ -1,14 +1,14 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` should render a room cell 1`] = ` +exports[` should render a room item 1`] = `
.", + "email_select": "Dewiswch pa e-byst rydych chi am anfon crynodebau atynt. Rheoli eich e-byst yn .", "enable_audible_notifications_session": "Galluogi hysbysiadau clywadwy ar gyfer y sesiwn hon", "enable_desktop_notifications_session": "Galluogi hysbysiadau bwrdd gwaith ar gyfer y sesiwn hon", "enable_email_notifications": "Galluogi hysbysiadau e-bost ar gyfer %(email)s", "enable_notifications_account": "Galluogi hysbysiadau ar gyfer y cyfrif hwn", - "enable_notifications_account_detail": "Trowch i ffwrdd i analluogi hysbysiadau ar eich holl ddyfeisiau a sesiynau", + "enable_notifications_account_detail": "Diffodd i analluogi hysbysiadau ar eich holl ddyfeisiau a sesiynau", "enable_notifications_device": "Galluogi hysbysiadau ar gyfer y ddyfais hon", "error_loading": "Bu gwall wrth lwytho eich gosodiadau hysbysu.", "error_permissions_denied": "Nid oes gan %(brand)s ganiatâd i anfon hysbysiadau atoch - gwiriwch osodiadau eich porwr", - "error_permissions_missing": "Ni roddwyd caniatâd i %(brand)s anfon hysbysiadau - ceisiwch eto", + "error_permissions_missing": "Heb roi caniatâd i %(brand)s anfon hysbysiadau - ceisiwch eto", "error_saving": "Gwall wrth gadw dewisiadau hysbysiad", "error_saving_detail": "Digwyddodd gwall wrth gadw'ch dewisiadau hysbysu.", "error_title": "Methu galluogi Hysbysiadau", "error_updating": "Bu gwall wrth ddiweddaru eich dewisiadau hysbysu. Ceisiwch newid eich opsiwn eto.", "invites": "Gwahoddiad i ystafell", - "keywords": "Dangos bathodyn pan ddefnyddir geiriau allweddol mewn ystafell.", - "keywords_prompt": "Rhowch eiriau allweddol yma, neu defnyddiwch ar gyfer amrywiadau sillafu neu lysenwau", - "labs_notice_prompt": "Diweddariad: Rydym wedi symleiddio Gosodiadau Hysbysiadau i'w gwneud yn haws dod o hyd i dewisiadau. Nid yw rhai gosodiadau personol rydych chi wedi'u dewis yn y gorffennol yn cael eu dangos yma, ond maen nhw'n dal yn weithredol. Os ewch ymlaen, efallai y bydd rhai o'ch gosodiadau'n newid. Dysgu rhagor", + "keywords": "Dangos bathodyn pan yn defnyddio allweddeiriau mewn ystafell.", + "keywords_prompt": "Rhowch allweddeiriau yma, neu defnyddiwch ar gyfer amrywiadau sillafu neu lysenwau", + "labs_notice_prompt": "Diweddariad: Rydym wedi symleiddio Gosodiadau Hysbysiadau i'w gwneud yn haws dod o hyd i dewisiadau. Nid yw rhai gosodiadau cyfaddas rydych chi wedi'u dewis yn y gorffennol yn cael eu dangos yma, ond maen nhw'n dal yn weithredol. Os ewch ymlaen, efallai y bydd rhai o'ch gosodiadau'n newid. Dysgu rhagor", "mentions_keywords": "Crybwyll ac Allweddeiriau", "mentions_keywords_only": "Crybwyll ac Allweddeiriau yn unig", - "messages_containing_keywords": "Negeseuon yn cynnwys geiriau allweddol", + "messages_containing_keywords": "Negeseuon yn cynnwys allweddeiriau", "noisy": "Swnllyd", "notices": "Negeseuon a anfonwyd gan bots", "notify_at_room": "Rhowch wybod pan fydd rhywun yn sôn am ddefnyddio @room", "notify_keyword": "Rhowch wybod pan fydd rhywun yn defnyddio allweddair", "notify_mention": "Rhoi gwybod pan fydd rhywun yn sôn am ddefnyddio @displaymatere neu %(mxid)s", "other_section": "Pethau eraill y credwn y gallai fod gennych ddiddordeb ynddynt:", - "people_mentions_keywords": "Pobl, Crybwyll a Geiriau Allweddol", - "play_sound_for_description": "Wedi'i gymhwyso'n ddiofyn i bob ystafell ar bob dyfais.", + "people_mentions_keywords": "Pobl, Crybwyll ac Allweddeiriau", + "play_sound_for_description": "Wedi'i osod fel rhagosodiad i bob ystafell ar bob dyfais.", "play_sound_for_section": "Chwarae sain ar gyfer", "push_targets": "Targedau hysbysu", "quick_actions_mark_all_read": "Marciwch bob neges wedi'i darllen", - "quick_actions_reset": "Ailosod i osodiadau diofyn", + "quick_actions_reset": "Ailosod i osodiadau rhagosodedig", "quick_actions_section": "Gweithredoedd Cyflym", "room_activity": "Mae gweithgarwch ystafell newydd, uwchraddiadau a negeseuon statws yn digwydd", "rule_call": "Galwad gwahoddiad", - "rule_contains_display_name": "Negeseuon yn cynnwys fy enw arddangos", + "rule_contains_display_name": "Negeseuon yn cynnwys fy enw dangos", "rule_contains_user_name": "Negeseuon yn cynnwys fy enw defnyddiwr", "rule_encrypted": "Negeseuon wedi'u hamgryptio mewn sgyrsiau grŵp", "rule_encrypted_room_one_to_one": "Negeseuon wedi'u hamgryptio mewn sgyrsiau un-i-un", @@ -2625,11 +2638,11 @@ "room_list_heading": "Rhestr ystafelloedd", "show_avatars_pills": "Dangos rhithffurfiau mewn cyfeiriadau defnyddiwr, ystafell a digwyddiad", "show_polls_button": "Dangos y botwm arolygon", - "surround_text": "Amgylchynwch destun dethol wrth deipio nodau arbennig", + "surround_text": "Amgylchynu testun dethol wrth deipio nodau arbennig", "time_heading": "Yn dangos amser", - "user_timezone": "Gosod cylchfa amser" + "user_timezone": "Gosod cylchfa amser" }, - "prompt_invite": "Anogwch cyn anfon gwahoddiadau i IDau matrics a allai fod yn annilys", + "prompt_invite": "Annog cyn anfon gwahoddiadau i IDau matrics a allai fod yn annilys", "replace_plain_emoji": "Amnewid Emoji testun plaen yn awtomatig", "security": { "4s_public_key_in_account_data": "mewn data cyfrif", @@ -2642,7 +2655,7 @@ "backup_keys_description": "Gwnewch gopi wrth gefn o'ch allweddi amgryptio gyda'ch data cyfrif rhag ofn i chi golli mynediad i'ch sesiynau. Bydd eich allweddi yn cael eu diogelu gydag Allwedd Adfer unigryw.", "bulk_options_accept_all_invites": "Derbyn pob %(invitedRooms)s gwahoddiad", "bulk_options_reject_all_invites": "Gwrthod pob %(invitedRooms)s gwahoddiad", - "bulk_options_section": "Opsiynau swmp", + "bulk_options_section": "Dewisiadau lluosog", "cross_signing_cached": "wedi'i storio'n lleol", "cross_signing_homeserver_support": "Cefnogaeth nodwedd Homeserver:", "cross_signing_homeserver_support_exists": "yn bodoli", @@ -2675,12 +2688,12 @@ "key_backup_active_version": "Fersiwn wrth gefn gweithredol:", "key_backup_active_version_none": "Dim", "key_backup_algorithm": "Algorithm:", - "key_backup_can_be_restored": "Gellir adfer y copi wrth gefn hwn yn y sesiwn hon", + "key_backup_can_be_restored": "Mae modd adfer y copi wrth gefn hwn yn y sesiwn hon", "key_backup_complete": "Pob allwedd wrth gefn", "key_backup_connect": "Cysylltwch y sesiwn hon i Bysell Wrth Gefn", "key_backup_connect_prompt": "Cysylltwch y sesiwn hon â chopi wrth gefn cyn allgofnodi er mwyn osgoi colli unrhyw allweddi a allai fod ar y sesiwn hon yn unig.", "key_backup_in_progress": "Wrthi'n gwneud copïau wrth gefn o %(sessionsRemaining)s allwedd…", - "key_backup_inactive": "Nid yw'r sesiwn hon yn gwneud copi wrth gefn o'ch allweddi , ond mae gennych chi gopi wrth gefn yn barod y gallwch chi adfer ohono ac ychwanegu ato wrth symud ymlaen.", + "key_backup_inactive": "Nid yw'r sesiwn hon yn gwneud copi wrth gefn o'ch allweddi, ond mae gennych chi gopi wrth gefn yn barod y gallwch chi adfer ohono ac ychwanegu ato wrth symud ymlaen.", "key_backup_inactive_warning": "Nid yw eich allweddi yn cael eu gwneud copi wrth gefn o'r sesiwn hon.", "key_backup_latest_version": "Fersiwn wrth gefn diweddaraf ar y gweinydd:", "message_search_disable_warning": "Os yw wedi'i analluogi, ni fydd negeseuon o ystafelloedd wedi'u hamgryptio yn ymddangos yn y canlyniadau chwilio.", @@ -2693,19 +2706,19 @@ "message_search_intro": "Mae %(brand)s yn cadw negeseuon wedi'u hamgryptio'n ddiogel yn lleol er mwyn iddynt ymddangos yn y canlyniadau chwilio:", "message_search_room_progress": "%(doneRooms)s allan o %(totalRooms)s", "message_search_section": "Chwilio neges", - "message_search_sleep_time": "Pa mor gyflym y dylid llwytho i lawrnegeseuon.", - "message_search_space_used": "Gofod a ddefnyddir:", - "message_search_unsupported": "Mae %(brand)s ar goll o rai cydrannau sydd eu hangen i gadw negeseuon wedi'u hamgryptio'n ddiogel yn lleol. Os hoffech arbrofi gyda'r nodwedd hon, adeiladwch Benbwrdd %(brand)s wedi'i deilwra ag ef cydrannau chwilio wedi'u hychwanegu.", + "message_search_sleep_time": "Pa mor gyflym dylai negeseuon gael eu llwytho i lawr.", + "message_search_space_used": "Gofod wedi'i ddefnyddio:", + "message_search_unsupported": "Mae %(brand)s ar goll o rai cydrannau sydd eu hangen i gadw negeseuon wedi'u hamgryptio'n ddiogel yn lleol. Os hoffech arbrofi gyda'r nodwedd hon, adeiladwch Bwrdd Gwaith %(brand)s wedi'i deilwra ag ef cydrannau chwilio wedi'u hychwanegu.", "message_search_unsupported_web": "Ni all %(brand)s storio negeseuon wedi'u hamgryptio'n ddiogel yn lleol tra'n rhedeg mewn porwr gwe. Defnydd %(brand)s Bwrdd Gwaith i negeseuon wedi'u hamgryptio ymddangos yn y canlyniadau chwilio.", "record_session_details": "Cofnodwch enw'r cleient, y fersiwn, a'r url i adnabod sesiynau'n haws yn y rheolwr sesiwn", - "restore_key_backup": "Adfer o Wrth Gefn", + "restore_key_backup": "Adfer o'r Copi Wrth Gefn", "secret_storage_not_ready": "ddim yn barod", - "secret_storage_ready": "barod", + "secret_storage_ready": "yn barod", "secret_storage_status": "Storio cyfrinachol:", "send_analytics": "Anfon data dadansoddeg", "session_id": "ID y sesiwn:", "session_key": "Allwedd sesiwn:", - "strict_encryption": "Peidiwch byth ag anfon negeseuon wedi'u hamgryptio i sesiynau heb eu gwirio o'r sesiwn hon" + "strict_encryption": "Peidio byth anfon negeseuon wedi'u hamgryptio i sesiynau heb eu gwirio o'r sesiwn hon" }, "send_read_receipts": "Anfon derbynebau darllen", "send_read_receipts_unsupported": "Nid yw eich gweinydd yn cefnogi analluogi anfon derbynebau wedi'u darllen.", @@ -2725,24 +2738,24 @@ "error_set_name": "Wedi methu gosod enw'r sesiwn", "filter_all": "Y Cyfan", "filter_inactive": "Anweithredol", - "filter_inactive_description": "Anactif am %(inactiveAgeDays)s diwrnod neu fwy", + "filter_inactive_description": "Anweithredol am %(inactiveAgeDays)s diwrnod neu fwy", "filter_label": "Hidlo dyfeisiau", "filter_unverified_description": "Ddim yn barod ar gyfer negeseuon diogel", "filter_verified_description": "Yn barod ar gyfer negeseuon diogel", "hide_details": "Cuddio manylion", - "inactive_days": "Anactif am %(inactiveAgeDays)s+ diwrnod", - "inactive_sessions": "Sesiynau anactif", - "inactive_sessions_explainer_1": "Mae sesiynau anactif yn sesiynau nad ydych wedi'u defnyddio ers peth amser, ond maent yn parhau i dderbyn allweddi amgryptio.", + "inactive_days": "Anweithredol am %(inactiveAgeDays)s+ diwrnod", + "inactive_sessions": "Sesiynau anweithredol", + "inactive_sessions_explainer_1": "Mae sesiynau anweithredol yn sesiynau nad ydych wedi'u defnyddio ers peth amser, ond maent yn parhau i dderbyn allweddi amgryptio.", "inactive_sessions_explainer_2": "Mae cael gwared ar sesiynau anweithredol yn gwella diogelwch a pherfformiad, ac yn ei gwneud yn haws i chi nodi a yw sesiwn newydd yn amheus.", "inactive_sessions_list_description": "Ystyriwch allgofnodi o hen sesiynau (%(inactiveAgeDays)s diwrnod neu hŷn) nad ydych yn eu defnyddio mwyach.", "ip": "Cyfeiriad IP", "last_activity": "Gweithgaredd ddiwethaf", "manage": "Rheoli'r sesiwn hon", "mobile_session": "Sesiwn symudol", - "no_inactive_sessions": "Ni chanfuwyd unrhyw sesiynau anactif.", + "no_inactive_sessions": "Heb ganfod unrhyw sesiynau anweithredol.", "no_sessions": "Heb ganfod sesiynau.", - "no_unverified_sessions": "Ni chanfuwyd unrhyw sesiynau heb eu gwirio.", - "no_verified_sessions": "Ni chanfuwyd unrhyw sesiynau wedi'u dilysu.", + "no_unverified_sessions": "Heb ganfod unrhyw sesiynau heb eu gwirio.", + "no_verified_sessions": "Heb ganfod unrhyw sesiynau wedi'u dilysu.", "os": "System weithredu", "other_sessions_heading": "Sesiynau eraill", "push_heading": "Hysbysiadau gwthiadwy", @@ -2760,14 +2773,14 @@ "sign_in_with_qr": "Cysylltu'r ddyfais newydd", "sign_in_with_qr_button": "Dangos cod QR", "sign_in_with_qr_description": "Defnyddiwch god QR i fewngofnodi i ddyfais arall a gosod negeseuon diogel.", - "sign_in_with_qr_unsupported": "Heb ei gefnogi gan ddarparwr eich cyfrif", + "sign_in_with_qr_unsupported": "Nid yw'n cael ei gefnogi gan ddarparwr eich cyfrif", "sign_out": "Allgofnodwch o'r sesiwn hon", "sign_out_all_other_sessions": "Allgofnodi o bob sesiwn arall (%(otherSessionsCount)s)", "title": "Sesiynau", "unknown_session": "Math o sesiwn anhysbys", "unverified_session": "Sesiwn heb ei wirio", "unverified_session_explainer_1": "Nid yw'r sesiwn hon yn cefnogi amgryptio ac felly nid oes modd ei wirio.", - "unverified_session_explainer_2": "Ni fyddwch yn gallu cymryd rhan mewn ystafelloedd lle mae amgryptio wedi'i alluogi wrth ddefnyddio'r sesiwn hon.", + "unverified_session_explainer_2": "Fyddwch chi ddim yn gallu cymryd rhan mewn ystafelloedd lle mae amgryptio wedi'i alluogi wrth ddefnyddio'r sesiwn hon.", "unverified_session_explainer_3": "Ar gyfer y diogelwch a phreifatrwydd gorau, argymhellir defnyddio cleientiaid Matrix sy'n cefnogi amgryptio.", "unverified_sessions": "Sesiynau heb eu gwirio", "unverified_sessions_explainer_1": "Mae sesiynau heb eu gwirio yn sesiynau sydd wedi mewngofnodi gyda'ch tystlythyrau ond nad ydynt wedi'u traws-wirio.", @@ -2785,7 +2798,7 @@ "show_avatar_changes": "Dangos newidiadau llun proffil", "show_breadcrumbs": "Dangos llwybrau byr i ystafelloedd a welwyd yn ddiweddar uwchben y rhestr ystafelloedd", "show_chat_effects": "Dangos effeithiau sgwrsio (animeiddiadau wrth dderbyn e.e. conffeti)", - "show_displayname_changes": "Dangos newidiadau enw arddangos", + "show_displayname_changes": "Dangos newidiadau enw dangos", "show_join_leave": "Dangos negeseuon ymuno/gadael (gwahoddiadau/dileu/gwaharddiadau heb eu heffeithio)", "show_nsfw_content": "Dangos cynnwys NSFW", "show_read_receipts": "Dangos derbynebau darllen a anfonwyd gan ddefnyddwyr eraill", @@ -2795,18 +2808,18 @@ "showbold": "Dangos pob gweithgaredd yn y rhestr ystafelloedd (smotiau neu nifer o negeseuon heb eu darllen)", "sidebar": { "dialog_title": "Gosodiadau: Bar Ochr", - "metaspaces_favourites_description": "Grwpiwch eich holl hoff ystafelloedd a phobl mewn un lle.", + "metaspaces_favourites_description": "Casglwch eich holl hoff ystafelloedd a phobl mewn un lle.", "metaspaces_home_all_rooms": "Dangos bob ystafell", "metaspaces_home_all_rooms_description": "Dangos eich holl ystafelloedd yn y Cartref, hyd yn oed os ydyn nhw mewn gofod.", - "metaspaces_home_description": "Mae Home yn ddefnyddiol ar gyfer cael trosolwg o bopeth.", + "metaspaces_home_description": "Mae Cartref yn ddefnyddiol ar gyfer cael trosolwg o bopeth.", "metaspaces_orphans": "Ystafelloedd y tu allan i ofod", - "metaspaces_orphans_description": "Grwpiwch eich holl ystafelloedd nad ydyn nhw'n rhan o ofod mewn un lle.", - "metaspaces_people_description": "Grwpiwch eich holl bobl mewn un lle.", - "metaspaces_subsection": "Lleoedd i ddangos", + "metaspaces_orphans_description": "Casglwch eich holl ystafelloedd nad ydyn nhw'n rhan o ofod mewn un lle.", + "metaspaces_people_description": "Casglwch eich holl bobl mewn un lle.", + "metaspaces_subsection": "Gofodau i'w dangos", "metaspaces_video_rooms": "Ystafelloedd fideo a chynadleddau", - "metaspaces_video_rooms_description": "Grwpiwch yr holl ystafelloedd fideo preifat a chynadleddau.", + "metaspaces_video_rooms_description": "Casglwch yr holl ystafelloedd fideo preifat a chynadleddau.", "metaspaces_video_rooms_description_invite_extension": "Mewn cynadleddau gallwch wahodd pobl y tu allan i'r matrics.", - "spaces_explainer": "Mae lleoedd yn ffyrdd o grwpio ystafelloedd a phobl. Ochr yn ochr â'r lleoedd rydych chi ynddynt, gallwch chi ddefnyddio rhai sydd wedi'u hadeiladu ymlaen llaw hefyd.", + "spaces_explainer": "Mae gofodau yn ffyrdd o grwpio ystafelloedd a phobl. Ochr yn ochr â'r lleoedd rydych chi ynddynt, gallwch chi ddefnyddio rhai sydd wedi'u hadeiladu ymlaen llaw hefyd.", "title": "Bar Ochr" }, "start_automatically": "Dechreuwch yn awtomatig ar ôl mewngofnodi i'r system", @@ -2814,8 +2827,8 @@ "use_12_hour_format": "Dangos stampiau amser mewn fformat 12 awr (e.e. 2:30pm)", "use_command_enter_send_message": "Defnyddiwch Command + Enter i anfon neges", "use_command_f_search": "Defnyddiwch Command + F i chwilio llinell amser", - "use_control_enter_send_message": "Defnyddiwch Ctrl + Enter i anfon neges", - "use_control_f_search": "Defnyddiwch Ctrl + F i chwilio llinell amser", + "use_control_enter_send_message": "Defnyddio Ctrl + Enter i anfon neges", + "use_control_f_search": "Defnyddio Ctrl + F i chwilio llinell amser", "voip": { "allow_p2p": "Caniatáu Cyfoedion i Gyfoedion ar gyfer galwadau 1:1", "allow_p2p_description": "Pan fydd wedi'i alluogi, efallai y bydd y parti arall yn gallu gweld eich cyfeiriad IP", @@ -2825,17 +2838,17 @@ "auto_gain_control": "Rheolaeth ennill awtomatig", "connection_section": "Cysylltiad", "dialog_title": "Gosodiadau: Llais a Fideo", - "echo_cancellation": "Canslo adlais", + "echo_cancellation": "Diddymu adlais", "enable_fallback_ice_server": "Caniatáu gweinydd cymorth galwadau wrth gefn (%(server)s)", "enable_fallback_ice_server_description": "Dim ond os nad yw eich gweinydd cartref yn cynnig un y mae'n berthnasol. Byddai eich cyfeiriad IP yn cael ei rannu yn ystod galwad.", - "mirror_local_feed": "Drych y ffrwd fideo lleol", - "missing_permissions_prompt": "Caniatadau cyfryngau ar goll, cliciwch y botwm isod i ofyn.", - "noise_suppression": "Atal sŵn", + "mirror_local_feed": "Drychu'r ffrwd fideo lleol", + "missing_permissions_prompt": "Caniatâd cyfryngau ar goll, cliciwch y botwm isod i ofyn.", + "noise_suppression": "Lleihau sain", "request_permissions": "Gofyn am ganiatâd cyfryngau", "title": "Llais a Fideo", - "video_input_empty": "Dim gwegamerâu wedi'u canfod", + "video_input_empty": "Dim camerau gwe wedi'u canfod", "video_section": "Gosodiadau fideo", - "voice_agc": "Addaswch gyfaint y meicroffon yn awtomatig", + "voice_agc": "Addaswch maint sain y meicroffon yn awtomatig", "voice_processing": "Prosesu llais", "voice_section": "Gosodiadau llais" }, @@ -2854,7 +2867,7 @@ "title_user": "Rhannu Defnyddiwr" }, "slash_command": { - "addwidget": "Yn ychwanegu teclyn wedi'i deilwra yn ôl URL i'r ystafell", + "addwidget": "Yn ychwanegu teclyn cyfaddas yn ôl URL i'r ystafell", "addwidget_iframe_missing_src": "Nid oes gan iframe briodwedd src", "addwidget_invalid_protocol": "Darparwch URL teclyn https:// neu http://", "addwidget_missing_url": "Rhowch URL teclyn neu god mewnosod", @@ -2870,7 +2883,7 @@ "converttodm": "Yn trosi'r ystafell yn DM", "converttoroom": "Yn trosi'r DM yn ystafell", "could_not_find_room": "Methu dod o hyd i le", - "deop": "Deops defnyddiwr gydag id a roddir", + "deop": "Deops defnyddiwr gydag id wedi'i roi", "devtools": "Yn agor y deialog Offer Datblygwr", "discardsession": "Gorfodi'r sesiwn grŵp allanol gyfredol mewn ystafell wedi'i hamgryptio i gael ei thaflu", "error_invalid_rendering_type": "Gwall gorchymyn: Methu dod o hyd i'r math o rendro (%(renderingType)s)", @@ -2887,18 +2900,18 @@ "invite": "Yn gwahodd defnyddiwr ag ID a roddwyd i'r ystafell gyfredol", "invite_3pid_needs_is_error": "Defnyddiwch weinydd hunaniaeth i wahodd trwy e-bost. Rheoli mewn Gosodiadau.", "invite_3pid_use_default_is_title": "Defnyddiwch weinydd hunaniaeth", - "invite_3pid_use_default_is_title_description": "Defnyddiwch weinydd hunaniaeth i wahodd trwy e-bost. Cliciwch parhau i ddefnyddio'r gweinydd hunaniaeth ddiofyn (%(defaultIdentityServerName)s) neu rheoli yn y Gosodiadau.", + "invite_3pid_use_default_is_title_description": "Defnyddiwch weinydd hunaniaeth i wahodd trwy e-bost. Cliciwch parhau i ddefnyddio'r gweinydd hunaniaeth drhagosodedig (%(defaultIdentityServerName)s) neu rheoli yn y Gosodiadau.", "invite_failed": "Nid oedd defnyddiwr (%(user)s) wedi'i wahodd i %(roomId)s yn y pen draw ond ni roddwyd gwall o gyfleustodau'r gwahoddwr", "join": "Yn ymuno â'r ystafell gyda chyfeiriad a roddwyd", - "jumptodate": "Neidiwch i'r dyddiad a roddwyd yn y llinell amser", + "jumptodate": "Neidio i'r dyddiad a roddwyd yn y llinell amser", "jumptodate_invalid_input": "Nid oeddem yn gallu deall y dyddiad a roddwyd (%(inputDate)s). Ceisiwch ddefnyddio'r fformat BBBB-MM-DD.", "lenny": "Rhagflaenu ( ͡° ͜ʖ ͡°) i neges destun plaen", "me": "Yn dangos gweithredu", "msg": "Yn anfon neges at y defnyddiwr a roddwyd", "myavatar": "Yn newid eich llun proffil ym mhob ystafell", "myroomavatar": "Yn newid eich llun proffil yn yr ystafell gyfredol hon yn unig", - "myroomnick": "Yn newid eich llysenw arddangos yn yr ystafell bresennol yn unig", - "nick": "Yn newid eich llysenw arddangos", + "myroomnick": "Yn newid eich llysenw dangos yn yr ystafell bresennol yn unig", + "nick": "Yn newid eich llysenw dangos", "no_active_call": "Dim galwad gweithredol yn yr ystafell hon", "op": "Diffiniwch lefel pŵer defnyddiwr", "part_unknown_alias": "Cyfeiriad ystafell heb ei adnabod: %(roomAlias)s", @@ -2946,7 +2959,7 @@ "error_heading": "Ni ychwanegwyd pob un a ddewiswyd", "space_dropdown_label": "Dewis gofod", "space_dropdown_title": "Ychwanegu ystafelloedd presennol", - "subspace_moved_note": "Mae ychwanegu bylchau wedi symud." + "subspace_moved_note": "Mae ychwanegu gofodau wedi symud." }, "add_existing_subspace": { "create_button": "Creu gofod newydd", @@ -2988,7 +3001,7 @@ "room_filter_placeholder": "Chwilio am ystafelloedd", "search_children": "Chwilio %(spaceName)s", "search_placeholder": "Chwilio enwau a disgrifiadau", - "select_room_below": "Dewiswch ystafell isod yn gyntaf", + "select_room_below": "Dewis ystafell isod yn gyntaf", "share_public": "Rhannwch eich gofod cyhoeddus", "suggested": "Awgrym", "suggested_tooltip": "Awgrymir yr ystafell hon fel un dda i ymuno â hi", @@ -3002,7 +3015,7 @@ }, "spaces": { "error_no_permission_add_room": "Nid oes gennych ganiatâd i ychwanegu ystafelloedd at y gofod hwn", - "error_no_permission_add_space": "Nid oes gennych ganiatâd i ychwanegu bylchau i'r gofod hwn", + "error_no_permission_add_space": "Nid oes gennych ganiatâd i ychwanegu gofodau i'r gofod hwn", "error_no_permission_create_room": "Nid oes gennych ganiatâd i greu ystafelloedd newydd yn y gofod hwn", "error_no_permission_invite": "Nid oes gennych ganiatâd i wahodd pobl i'r gofod hwn" }, @@ -3018,7 +3031,7 @@ "network_dropdown_remove_server_adornment": "Dileu gweinydd “%(roomServer)s”", "network_dropdown_required_invalid": "Rhowch enw gweinydd", "network_dropdown_selected_label": "Sioe: Ystafelloedd matrics", - "network_dropdown_selected_label_instance": "Dangos: %(instance)s ystafell (%(server)s)", + "network_dropdown_selected_label_instance": "Dangos: ystafell %(instance)s (%(server)s)", "network_dropdown_your_server_description": "Eich gweinydd" } }, @@ -3045,7 +3058,7 @@ "result_may_be_hidden_warning": "Efallai y bydd rhai canlyniadau wedi'u cuddio", "search_dialog": "Deialog Chwilio", "search_messages_hint": "I chwilio negeseuon, edrychwch am yr eicon hwn ar frig ystafell", - "spaces_title": "Gofodau rydych chi ynddynt", + "spaces_title": "Gofodau rydych chi ynddyn nhw", "start_group_chat_button": "Dechreuwch sgwrs grŵp" }, "stickers": { @@ -3056,11 +3069,11 @@ "column_document": "Dogfen", "column_service": "Gwasanaeth", "column_summary": "Crynodeb", - "identity_server_no_terms_description_1": "Mae'r weithred hon yn gofyn am gyrchu'r gweinydd hunaniaeth ddiofyn i ddilysu cyfeiriad e-bost neu rif ffôn, ond nid oes gan y gweinydd unrhyw delerau gwasanaeth.", + "identity_server_no_terms_description_1": "Mae'r weithred hon yn gofyn am gyrchu'r gweinydd hunaniaeth drhagosodedig i ddilysu cyfeiriad e-bost neu rif ffôn, ond nid oes gan y gweinydd unrhyw delerau gwasanaeth.", "identity_server_no_terms_description_2": "Parhewch dim ond os ydych yn ymddiried ym mherchennog y gweinydd.", "identity_server_no_terms_title": "Nid oes gan weinydd hunaniaeth unrhyw delerau gwasanaeth", "inline_intro_text": "Derbyn i barhau:", - "integration_manager": "Defnyddiwch bots, pontydd, teclynnau a phecynnau sticeri", + "integration_manager": "Defnyddio botiau, pontydd, teclynnau a phecynnau sticeri", "intro": "I barhau mae angen i chi dderbyn telerau'r gwasanaeth hwn.", "summary_identity_server_1": "Dod o hyd i eraill dros y ffôn neu e-bost", "summary_identity_server_2": "Gellir dod o hyd iddo dros y ffôn neu e-bost", @@ -3077,7 +3090,7 @@ "threads": { "all_threads": "Pob edafedd", "all_threads_description": "Yn dangos pob trywydd o'r ystafell gyfredol", - "empty_description": "Defnyddiwch “%(replyInThread)s” wrth hofran dros neges.", + "empty_description": "Defnyddio “%(replyInThread)s” wrth hofran dros neges.", "empty_title": "Mae edafedd yn helpu i gadw'ch sgyrsiau ar y pwnc ac yn hawdd eu holrhain.", "error_start_thread_existing_relation": "Methu â chreu edefyn o ddigwyddiad gyda pherthynas sy'n bodoli eisoes", "mark_all_read": "Marcio'r cyfan wedi'u darllen", @@ -3207,13 +3220,13 @@ "m.image": { "error": "Methu dangos delwedd oherwydd gwall", "error_decrypting": "Gwall wrth ddadgryptio delwedd", - "error_downloading": "Gwall wrth lawrlwytho'r ddelwedd", + "error_downloading": "Gwall wrth lwytho'r ddelwedd", "sent": "Anfonodd %(senderDisplayName)s ddelwedd.", "show_image": "Dangos delwedd" }, "m.key.verification.request": { "user_wants_to_verify": "Mae %(matere)s eisiau gwirio", - "you_started": "Anfonoch gais dilysu" + "you_started": "Rydych wedi anfon cais dilysu" }, "m.location": { "full": "Mae %(senderName)s wedi rhannu eu lleoliad", @@ -3221,10 +3234,10 @@ "self_location": "Wedi rhannu eu lleoliad: " }, "m.poll.end": { - "ended": "Daeth arolwg barn i ben", - "sender_ended": "Mae %(senderName)s wedi dod â phôl i ben" + "ended": "Daeth arolwg i ben", + "sender_ended": "Mae %(senderName)s wedi dod ag arolwg i ben" }, - "m.poll.start": "Mae %(senderName)s wedi dechrau arolwg barn - %(pollQuestion)s", + "m.poll.start": "Mae %(senderName)s wedi dechrau arolwg - %(pollQuestion)s", "m.room.avatar": { "changed": "Mae %(senderDisplayName)s wedi newid afatar yr ystafell.", "changed_img": "Mae %(senderDisplayName)s wedi newid yr afatar ystafell i", @@ -3251,7 +3264,7 @@ "enabled_dm": "Mae negeseuon yma wedi'u hamgryptio o'r dechrau i'r diwedd. Dilyswch %(displayName)s yn eu proffil - tapiwch ar eu llun proffil.", "enabled_local": "Bydd negeseuon yn y sgwrs hon yn cael eu hamgryptio o'r dechrau i'r diwedd.", "parameters_changed": "Mae rhai paramedrau amgryptio wedi'u newid.", - "unsupported": "Nid yw'r amgryptio a ddefnyddir gan yr ystafell hon yn cael ei gefnogi." + "unsupported": "Nid yw'r amgryptio sy'n cael ei ddefnyddiogan yr ystafell hon yn cael ei gefnogi." }, "m.room.guest_access": { "can_join": "Mae %(senderDisplayName)s wedi caniatáu i westeion ymuno â'r ystafell.", @@ -3259,8 +3272,8 @@ "unknown": "Mae %(senderDisplayName)s wedi newid mynediad gwestai i %(rule)s" }, "m.room.history_visibility": { - "invited": "Gwnaeth %(senderName)s hanes ystafell y dyfodol yn weladwy i bob aelod ystafell, o'r pwynt y maent yn cael eu gwahodd.", - "joined": "Gwnaeth %(senderName)s hanes ystafell yn y dyfodol yn weladwy i bob aelod ystafell, o'r pwynt y gwnaethant ymuno.", + "invited": "Gwnaeth %(senderName)s hanes ystafell y dyfodol yn weladwy i bob aelod ystafell, o'r pwynt y maen nhw'n cael eu gwahodd.", + "joined": "Gwnaeth %(senderName)s hanes ystafell yn y dyfodol yn weladwy i bob aelod ystafell, o'r pwynt y gwnaetho'n nhw ymuno.", "shared": "Gwnaeth %(senderName)s hanes ystafell y dyfodol yn weladwy i bob aelod ystafell.", "unknown": "Gwnaeth %(senderName)s hanes ystafell y dyfodol yn weladwy i anhysbys (%(visibility)s).", "world_readable": "Gwnaeth %(senderName)s hanes ystafell y dyfodol yn weladwy i unrhyw un." @@ -3276,25 +3289,25 @@ "m.room.member": { "accepted_3pid_invite": "Derbyniodd %(targetName)s y gwahoddiad ar gyfer %(displayName)s", "accepted_invite": "Derbyniodd %(targetName)s wahoddiad", - "ban": "%(senderName)s gwahardd %(targetName)s", - "ban_reason": "%(senderName)s gwahardd %(targetName)s: %(reason)s", + "ban": "Mae %(senderName)s wedi gwahardd %(targetName)s", + "ban_reason": "Mae %(senderName)s wedi gwahardd %(targetName)s: %(reason)s", "change_avatar": "Mae %(senderName)s wedi newid eu llun proffil", - "change_name": "Newidiodd %(oldDisplayName)s ei enw arddangos i %(displayName)s", - "change_name_avatar": "Newidiodd %(oldDisplayName)s ei enw arddangos a llun proffil", + "change_name": "Mae %(oldDisplayName)s wedi newid ei enw dangos i %(displayName)s", + "change_name_avatar": "Mae %(oldDisplayName)s wedi newid ei enw dangos a llun proffil", "invite": "Mae %(senderName)s wedi gwahodd %(targetName)s", "join": "Ymunodd %(targetName)s â'r ystafell", "kick": "Mae %(senderName)s wedi tynnu %(targetName)s", "kick_reason": "Mae %(senderName)s wedi tynnu %(targetName)s: %(reason)s", "left": "Gadawodd %(targetName)s yr ystafell", "left_reason": "Gadawodd %(targetName)s yr ystafell: %(reason)s", - "no_change": "Ni wnaeth %(senderName)s unrhyw newid", + "no_change": "Nid yw %(senderName)s wedi gwneud unrhyw newid", "reject_invite": "Mae %(targetName)s wedi gwrthod y gwahoddiad", "reject_invite_reason": "Mae %(targetName)s wedi gwrthod y gwahoddiad: %(reason)s", "remove_avatar": "Mae %(senderName)s wedi tynnu eu llun proffil", - "remove_name": "Mae %(senderName)s wedi tynnu eu henw arddangos (%(oldDisplayName)s)", + "remove_name": "Mae %(senderName)s wedi tynnu eu henw dangos (%(oldDisplayName)s)", "set_avatar": "Mae %(senderName)s wedi gosod llun proffil", - "set_name": "Mae %(senderName)s wedi gosod eu henw arddangos i %(displayName)s", - "unban": "%(senderName)s heb ei wahardd %(targetName)s", + "set_name": "Mae %(senderName)s wedi gosod eu henw dangos i %(displayName)s", + "unban": "Mae %(senderName)s wedi ei ddad wahardd %(targetName)s", "withdrew_invite": "Tynnodd %(senderName)s wahoddiad %(targetName)s yn ôl", "withdrew_invite_reason": "Tynnodd %(senderName)s wahoddiad %(targetName)s yn ôl: %(reason)s" }, @@ -3334,13 +3347,13 @@ "error_decrypting": "Gwall wrth ddadgryptio fideo" }, "m.widget": { - "added": "widget %(widgetName)s wedi'i ychwanegu gan %(senderName)s", + "added": "Mae %(widgetName)s wedi'i ychwanegu gan %(senderName)s", "jitsi_ended": "Daeth cynhadledd fideo i ben gan %(senderName)s", "jitsi_join_right_prompt": "Ymunwch â'r gynhadledd o'r cerdyn gwybodaeth ystafell ar y dde", "jitsi_join_top_prompt": "Ymunwch â'r gynhadledd ar frig yr ystafell hon", "jitsi_started": "Cynhadledd fideo wedi'i chychwyn gan %(senderName)s", "jitsi_updated": "Cynhadledd fideo wedi'i diweddaru gan %(senderName)s", - "modified": "Teclyn %(widgetName)s wedi'i addasu gan %(senderName)s", + "modified": "Mae teclyn %(widgetName)s wedi'i addasu gan %(senderName)s", "removed": "Tynnwyd y teclyn %(widgetName)s gan %(senderName)s" }, "mab": { @@ -3348,12 +3361,12 @@ "copy_link_thread": "Copïo dolen i'r edefyn", "expand_reply_chain": "Ehangu dyfyniadau", "label": "Camau Gweithredu Neges", - "view_in_room": "Golygfa yn yr ystafell" + "view_in_room": "Golwg yn yr ystafell" }, - "message_timestamp_received_at": "Derbyniwyd yn: %(dateTime)s", - "message_timestamp_sent_at": "Anfonwyd at: %(dateTime)s", + "message_timestamp_received_at": "Derbyniwyd am: %(dateTime)s", + "message_timestamp_sent_at": "Anfonwyd am: %(dateTime)s", "mjolnir": { - "changed_rule_glob": "Mae %(senderName)s wedi diweddaru rheol gwahardd a oedd yn cyfateb %(oldGlob)s i %(newGlob)s ar gyfer %(reason)s", + "changed_rule_glob": "Mae %(senderName)s wedi diweddaru rheol gwahardd oedd yn cyfateb %(oldGlob)s i %(newGlob)s ar gyfer %(reason)s", "changed_rule_rooms": "Newidiodd %(senderName)s reol a oedd yn gwahardd ystafelloedd sy'n cyfateb i %(oldGlob)s i gyfateb %(newGlob)s am %(reason)s", "changed_rule_servers": "Newidiodd %(senderName)s reol a oedd yn gwahardd gweinyddwyr sy'n cyfateb %(oldGlob)s i gyfateb %(newGlob)s am %(reason)s", "changed_rule_users": "Newidiodd %(senderName)s reol a oedd yn gwahardd defnyddwyr rhag paru %(oldGlob)s â chyfateb %(newGlob)s am %(reason)s", @@ -3374,11 +3387,11 @@ }, "no_permission_messages_before_invite": "Nid oes gennych ganiatâd i weld negeseuon oddi cyn i chi gael eich gwahodd.", "no_permission_messages_before_join": "Nid oes gennych ganiatâd i weld negeseuon oddi cyn i chi ymuno.", - "pending_moderation": "Neges yn aros i'w safoni", - "pending_moderation_reason": "Neges yn aros i'w safoni: %(reason)s", + "pending_moderation": "Neges yn aros i'w gymedroli", + "pending_moderation_reason": "Neges yn aros i'w gymedroli: %(reason)s", "reactions": { - "add_reaction_prompt": "Ychwanegu adwaith", - "custom_reaction_fallback_label": "Ymateb personol", + "add_reaction_prompt": "Ychwanegu ymateb", + "custom_reaction_fallback_label": "Ymateb cyfaddas", "label": "Ymatebodd %(reactors)s gyda %(content)s", "tooltip_caption": "wedi ymateb gyda %(shortName)s" }, @@ -3389,8 +3402,8 @@ "redaction": "Neges wedi'i dileu gan %(matere)s", "reply": { "error_loading": "Methu llwytho digwyddiad yr atebwyd iddo, naill ai nid yw'n bodoli neu nid oes gennych ganiatâd i'w weld.", - "in_reply_to": "Mewn atebiad i", - "in_reply_to_for_export": "Mewn atebiad i'r neges hon" + "in_reply_to": "Yn ymateb i", + "in_reply_to_for_export": "Yn ymateb i'r neges hon" }, "scalar_starter_link": { "dialog_description": "Rydych ar fin cael eich tywys i wefan trydydd parti er mwyn i chi allu dilysu'ch cyfrif i'w ddefnyddio gyda %(integrationsUrl)s. Ydych chi am barhau?", @@ -3418,15 +3431,15 @@ "description": "Os byddwch yn parhau, efallai na fydd rhai nodweddion yn gweithio ac mae risg y gallech golli data yn y dyfodol. Diweddarwch eich porwr i barhau i ddefnyddio %(brand)s.", "title": "Nid yw %(brand)s yn cefnogi'r porwr hwn" }, - "unsupported_server_description": "Mae'r gweinydd hwn yn defnyddio fersiwn hŷn o Matrix. Uwchraddio i Matrics %(version)s i ddefnyddio %(brand)s heb wallau.", + "unsupported_server_description": "Mae'r gweinydd hwn yn defnyddio fersiwn hŷn o Matrix. Uwchraddiwch i Matrics %(version)s i ddefnyddio %(brand)s heb wallau.", "unsupported_server_title": "Nid yw eich gweinydd yn cael ei gefnogi", "update": { "changelog": "Cofnod Newid", "check_action": "Gwiriwch am ddiweddariad", "checking": "Wrthi'n gwirio am ddiweddariad…", - "downloading": "Wrthi'n llwytho i lawrdiweddariad…", - "error_encountered": "Gwall a gafwyd (%(errorDetail)s).", - "error_unable_load_commit": "Methu llwytho manylion ymrwymo: %(msg)s", + "downloading": "Wrthi'n llwytho diweddariad i lawr…", + "error_encountered": "Y gwall gafwyd (%(errorDetail)s).", + "error_unable_load_commit": "Methu llwytho manylion cyflwyno: %(msg)s", "new_version_available": "Fersiwn newydd ar gael. Diweddaru nawr.", "no_update": "Dim diweddariad ar gael.", "release_notes_toast_title": "Beth sy'n Newydd", @@ -3442,17 +3455,17 @@ "title": "Newid lefel mynediad yr ystafell" }, "upload_failed_generic": "Methodd y ffeil '%(fileName)s' â llwytho i fyny.", - "upload_failed_size": "Mae'r ffeil '%(fileName)s' yn fwy na chyfyngiad maint y gweinydd cartref hwn ar gyfer uwchlwythiadau", + "upload_failed_size": "Mae'r ffeil '%(fileName)s' yn fwy na chyfyngiad maint llwytho'r gweinydd cartref", "upload_failed_title": "Methodd y Llwytho", "upload_file": { "cancel_all_button": "Diddymu'r Cyfan", - "error_file_too_large": "Mae'r ffeil hon yn rhy fawr i'w huwchlwytho. Y terfyn maint ffeil yw %(limit)s ond y ffeil hon yw %(sizeOfThisFile)s.", - "error_files_too_large": "Mae'r ffeiliau hyn yn rhy fawr i'w huwchlwytho. Y terfyn maint ffeil yw %(limit)s.", - "error_some_files_too_large": "Mae rhai ffeiliau'n rhy fawr i'w huwchlwytho. Y terfyn maint ffeil yw %(limit)s.", + "error_file_too_large": "Mae'r ffeil hon yn rhy fawr i'w llwytho. Y terfyn maint ffeil yw %(limit)s ond y ffeil hon yw %(sizeOfThisFile)s.", + "error_files_too_large": "Mae'r ffeiliau hyn yn rhy fawr i'w llwytho. Y terfyn maint ffeil yw %(limit)s.", + "error_some_files_too_large": "Mae rhai ffeiliau'n rhy fawr i'w llwytho. Y terfyn maint ffeil yw %(limit)s.", "error_title": "Gwall Llwytho", "not_image": "Nid yw'r ffeil rydych chi wedi'i dewis yn ffeil delwedd ddilys.", "title": "Llwytho ffeiliau", - "title_progress": "Uwchlwytho ffeiliau (%(current)s o %(total)s)", + "title_progress": "Llwytho ffeiliau (%(current)s o %(total)s)", "upload_all_button": "Llwytho'r cyfan" }, "user_info": { @@ -3463,15 +3476,15 @@ "ban_space_everything": "Gwaharddwch nhw o bopeth rydw i'n gallu", "ban_space_specific": "Gwaharddwch nhw o bethau penodol y gallaf eu gwneud", "deactivate_confirm_action": "Analluogi defnyddiwr", - "deactivate_confirm_description": "Bydd dadactifadu'r defnyddiwr hwn yn eu hallgofnodi a'u hatal rhag mewngofnodi eto. Yn ogystal, byddant yn gadael yr holl ystafelloedd y mae ynddynt. Nid oes modd gwrthdroi'r weithred hon. Ydych chi'n siŵr eich bod am ddadactifadu'r defnyddiwr hwn?", + "deactivate_confirm_description": "Bydd cau'r defnyddiwr hwn yn eu hallgofnodi a'u hatal rhag mewngofnodi eto. Yn ogystal, byddant yn gadael yr holl ystafelloedd y mae ynddynt. Nid oes modd gwrthdroi'r weithred hon. Ydych chi'n siŵr eich bod am cau'r defnyddiwr hwn?", "deactivate_confirm_title": "Analluogi defnyddiwr?", "demote_button": "Diraddio", - "demote_self_confirm_description_space": "Ni fyddwch yn gallu dadwneud y newid hwn gan eich bod yn israddio eich hun, os mai chi yw'r defnyddiwr breintiedig olaf yn y gofod bydd yn amhosibl adennill breintiau.", - "demote_self_confirm_room": "Ni fyddwch yn gallu dadwneud y newid hwn gan eich bod yn israddio eich hun, os mai chi yw'r defnyddiwr breintiedig olaf yn yr ystafell bydd yn amhosibl adennill breintiau.", + "demote_self_confirm_description_space": "Fyddwch chi ddim yn gallu dadwneud y newid hwn gan eich bod yn israddio eich hun, os mai chi yw'r defnyddiwr breintiedig olaf yn y gofod bydd yn amhosibl adennill breintiau.", + "demote_self_confirm_room": "Fyddwch chi ddim yn gallu dadwneud y newid hwn gan eich bod yn israddio eich hun, os mai chi yw'r defnyddiwr breintiedig olaf yn yr ystafell bydd yn amhosibl adennill breintiau.", "demote_self_confirm_title": "Israddio eich hun?", - "disinvite_button_room": "Cael gwared ar yr ystafell", - "disinvite_button_room_name": "Dileu oddi wrth %(roomName)s", - "disinvite_button_space": "Cael gwared ar y gofod", + "disinvite_button_room": "Dadwahodd o'r ystafell", + "disinvite_button_room_name": "Dadwahodd o %(roomName)s", + "disinvite_button_space": "Dadwahodd o'r gofod", "error_ban_user": "Wedi methu â gwahardd defnyddiwr", "error_deactivate": "Wedi methu ag analluogi defnyddiwr", "error_kicking_user": "Wedi methu tynnu'r defnyddiwr", @@ -3482,21 +3495,21 @@ "ignore_confirm_description": "Bydd pob neges a gwahoddiad gan y defnyddiwr hwn yn cael eu cuddio. Ydych chi'n siŵr eich bod am eu hanwybyddu?", "ignore_confirm_title": "Anwybyddu %(user)s", "invited_by": "Wedi'i wahodd gan %(sender)s", - "jump_to_rr_button": "Neidiwch i ddarllen y dderbynneb", + "jump_to_rr_button": "Mynd i ddarllen y dderbynneb", "kick_button_room": "Tynnu o'r ystafell", "kick_button_room_name": "Tynnu o %(roomName)s", - "kick_button_space": "Tynnwch o'r gofod", + "kick_button_space": "Tynnu o'r gofod", "kick_button_space_everything": "Tynnwch nhw o bopeth rydw i'n gallu", "kick_space_specific": "Tynnwch nhw o bethau penodol rydw i'n gallu", - "kick_space_warning": "Byddant yn dal i allu cael mynediad at beth bynnag nad ydych yn weinyddwr iddo.", - "promote_warning": "Ni fyddwch yn gallu dadwneud y newid hwn gan eich bod yn hyrwyddo'r defnyddiwr i gael yr un lefel pŵer â chi'ch hun.", + "kick_space_warning": "Byddan nhw'n dal i allu cael mynediad at beth bynnag nad ydych yn weinyddwr iddo.", + "promote_warning": "Fyddwch chi ddim yn gallu dadwneud y newid hwn gan eich bod yn hyrwyddo'r defnyddiwr i gael yr un lefel pŵer â chi'ch hun.", "redact": { "confirm_description_2": "Ar gyfer llawer iawn o negeseuon, gallai hyn gymryd peth amser. Peidiwch ag adnewyddu eich cleient yn y cyfamser.", "confirm_keep_state_explainer": "Dad-diciwch a ydych hefyd am ddileu negeseuon system ar y defnyddiwr hwn (e.e. newid aelodaeth, newid proffil…)", "confirm_keep_state_label": "Cadw negeseuon system", "confirm_title": "Dileu negeseuon diweddar gan %(user)s", "no_recent_messages_description": "Ceisiwch sgrolio i fyny yn y llinell amser i weld a oes unrhyw rai cynharach.", - "no_recent_messages_title": "Ni chanfuwyd unrhyw negeseuon diweddar gan %(user)s" + "no_recent_messages_title": "Heb ganfod unrhyw negeseuon diweddar gan %(user)s" }, "redact_button": "Dileu negeseuon", "revoke_invite": "Diddymu gwahoddiad", @@ -3511,7 +3524,7 @@ "unban_room_confirm_title": "Dad-wahardd o %(roomName)s", "unban_space_everything": "Dad-wahardd nhw o bopeth y gallaf", "unban_space_specific": "Gwahardd nhw o bethau penodol y gallaf", - "unban_space_warning": "Ni fyddant yn gallu cael mynediad at beth bynnag nad ydych yn weinyddwr iddo.", + "unban_space_warning": "Ffyddan nhw ddim yn gallu cael mynediad at beth bynnag nad ydych yn weinyddwr iddo.", "unignore_button": "Anwybyddu", "verification_unavailable": "Nid yw dilysu defnyddiwr ar gael", "verify_button": "Dilysu Defnyddiwr", @@ -3526,47 +3539,47 @@ "voip": { "already_in_call": "Eisoes mewn galwad", "already_in_call_person": "Rydych chi eisoes mewn galwad gyda'r person hwn.", - "answered_elsewhere": "Atebwyd mewn Man arall", + "answered_elsewhere": "Atebwyd mewn Man Arall", "answered_elsewhere_description": "Atebwyd yr alwad ar ddyfais arall.", "call_failed": "Galwad wedi Methu", - "call_failed_description": "Ni ellid sefydlu'r alwad", - "call_failed_media": "Methodd yr alwad oherwydd nid oedd modd cyrchu gwe-gamera neu feicroffon. Gwiriwch fod:", - "call_failed_media_applications": "Nid oes unrhyw raglen arall yn defnyddio'r gwe-gamera", - "call_failed_media_connected": "Mae meicroffon a gwe-gamera wedi'u plygio i mewn ac wedi'u gosod yn gywir", - "call_failed_media_permissions": "Rhoddir caniatâd i ddefnyddio'r gwe-gamera", + "call_failed_description": "Nid oes modd gosod yr alwad", + "call_failed_media": "Methodd yr alwad oherwydd nid oedd modd cael at gamera gwe neu feicroffon. Gwiriwch fod:", + "call_failed_media_applications": "Nid oes unrhyw raglen arall yn defnyddio'r camera gwe", + "call_failed_media_connected": "Mae meicroffon a camera gwe wedi'u plygio i mewn ac wedi'u gosod yn gywir", + "call_failed_media_permissions": "Rhoi caniatâd i ddefnyddio'r camera gwe", "call_failed_microphone": "Methodd yr alwad oherwydd ni fu modd cyrchu'r meicroffon. Gwiriwch fod meicroffon wedi'i blygio i mewn a'i osod yn gywir.", "call_held": "Cynhaliodd %(peerName)s yr alwad", - "call_held_resume": "Fe wnaethoch chi gynnal yr ailddechrau galwad", - "call_held_switch": "Fe wnaethoch chi gynnal yr alwad Switch", + "call_held_resume": "Chi sy'n cynnal yr alwad Ailddechrau", + "call_held_switch": "Chi sy'n cynnal yr alwad Newid", "call_toast_unknown_room": "Ystafell anhysbys", "camera_disabled": "Mae eich camera wedi'i ddiffodd", "camera_enabled": "Mae eich camera wedi'i alluogi o hyd", - "cannot_call_yourself_description": "Allwch chi ddim roi galwad gyda chi'ch hun.", + "cannot_call_yourself_description": "Allwch chi ddim roi galwad i chi'ch hun.", "close_lobby": "Caewch y lobi", "connecting": "Yn cysylltu", "connection_lost": "Mae cysylltedd â'r gweinydd wedi'i golli", "connection_lost_description": "Allwch chi ddim osod galwadau heb gysylltiad â'r gweinydd.", "consulting": "Ymgynghori â %(transferTarget)s. Trosglwyddo i %(transferee)s", - "default_device": "Dyfais Diofyn", - "dial": "Deialwch", - "dialpad": "Dialpad", - "disable_camera": "Trowch y camera i ffwrdd", + "default_device": "Dyfais Rhagosodedig", + "dial": "Deial", + "dialpad": "Pad Deialu", + "disable_camera": "Diffoddwch y camera", "disable_microphone": "Tewi meicroffon", "disabled_no_one_here": "Nid oes neb yma i alw", "disabled_no_perms_start_video_call": "Nid oes gennych ganiatâd i ddechrau galwadau fideo", "disabled_no_perms_start_voice_call": "Nid oes gennych ganiatâd i ddechrau galwadau llais", - "disabled_ongoing_call": "Galwad barhaus", - "element_call": "Galwad Elfen", + "disabled_ongoing_call": "Galwad cyfredol", + "element_call": "Galwad Element", "enable_camera": "Trowch y camera ymlaen", "enable_microphone": "Dad-dewi meicroffon", "expand": "Dychwelyd i'r alwad", "get_call_link": "Rhannu cyswllt galwad", - "hangup": "Hangup", + "hangup": "Rhoi'r gorau iddi", "hide_sidebar_button": "Cuddio bar ochr", "input_devices": "Dyfeisiau mewnbwn", "jitsi_call": "Cynhadledd Jitsi", "join_button_tooltip_call_full": "Ymddiheuriadau - mae'r alwad hon yn llawn ar hyn o bryd", - "legacy_call": "Galwad Etifeddiaeth", + "legacy_call": "Hen Alwad", "maximise": "Llanw'r Sgrin", "maximise_call": "Mwyhau galwad", "metaspace_video_rooms": { @@ -3581,8 +3594,8 @@ "msisdn_lookup_failed": "Methu chwilio am y rhif ffôn", "msisdn_lookup_failed_description": "Bu gwall wrth chwilio am y rhif ffôn", "msisdn_transfer_failed": "Methu trosglwyddo galwad", - "no_audio_input_description": "Ni ddaethom o hyd i feicroffon ar eich dyfais. Gwiriwch eich gosodiadau a cheisiwch eto.", - "no_audio_input_title": "Ni chanfuwyd meicroffon", + "no_audio_input_description": "Heb ddod o hyd i feicroffon ar eich dyfais. Gwiriwch eich gosodiadau a cheisiwch eto.", + "no_audio_input_title": "Heb ganfod meicroffon", "no_media_perms_description": "Mae'n bosibl y bydd angen i chi ganiatáu i %(brand)s gael mynediad i'ch meicroffon/gwegamera â llaw", "no_media_perms_title": "Dim caniatâd cyfryngau", "no_permission_conference": "Angen Caniatâd", @@ -3593,8 +3606,8 @@ "screenshare_title": "Rhannu cynnwys", "screenshare_window": "Ffenestr cais", "show_sidebar_button": "Dangos y bar ochr", - "silence": "Galwad distawrwydd", - "silenced": "Distawodd hysbysiadau", + "silence": "Distewi galwad", + "silenced": "Hysbysiadau wedi'u distewi", "start_screenshare": "Dechreuwch rannu'ch sgrin", "stop_screenshare": "Stopiwch rannu'ch sgrin", "too_many_calls": "Gormod o Alwadau", @@ -3602,98 +3615,98 @@ "transfer_consult_first_label": "Ymgynghori yn gyntaf", "transfer_failed": "Methodd y Trosglwyddo", "transfer_failed_description": "Wedi methu trosglwyddo galwad", - "unable_to_access_audio_input_description": "Nid oeddem yn gallu cael mynediad i'ch meicroffon. Gwiriwch osodiadau eich porwr a cheisiwch eto.", + "unable_to_access_audio_input_description": "Methu cael mynediad i'ch meicroffon. Gwiriwch osodiadau eich porwr a cheisiwch eto.", "unable_to_access_audio_input_title": "Methu cael mynediad i'ch meicroffon", - "unable_to_access_media": "Methu cyrchu gwe-gamera / meicroffon", + "unable_to_access_media": "Methu cyrchu camera gwe / meicroffon", "unable_to_access_microphone": "Methu cyrchu meicroffon", "unknown_caller": "Galwr anhysbys", "unknown_person": "person anhysbys", "unsilence": "Sain ymlaen", - "unsupported": "Ni chefnogir galwadau", - "unsupported_browser": "Allwch chi ddim osod galwadau yn y porwr hwn.", - "user_busy": "Defnyddiwr Prysur", - "user_busy_description": "Mae'r defnyddiwr y gwnaethoch ei alw yn brysur.", + "unsupported": "Nid yw galwadau'n cael eu cefnogi", + "unsupported_browser": "Allwch chi ddim gosod galwadau yn y porwr hwn.", + "user_busy": "Defnyddiwr yn Brysur", + "user_busy_description": "Mae'r defnyddiwr rydych yn ei alw yn brysur.", "user_is_presenting": "Mae %(sharerName)s yn cyflwyno", "video_call": "Galwad fideo", - "video_call_started": "Dechreuwyd galwad fideo", + "video_call_started": "Galwad fideo wedi dechrau", "video_call_using": "Galwad fideo gan ddefnyddio:", "voice_call": "Galwad llais", "you_are_presenting": "Rydych chi'n cyflwyno" }, "web_default_device_name": "%(appName)s: %(browserName)s ar %(osName)s", - "welcome_to_element": "Croeso i Elfen", + "welcome_to_element": "Croeso i Element", "widget": { "added_by": "Ychwanegwyd teclyn gan", "capabilities_dialog": { "content_starting_text": "Hoffai'r teclyn hwn:", - "decline_all_permission": "Dirywiad Pawb", - "remember_Selection": "Cofiwch fy newis ar gyfer y teclyn hwn", + "decline_all_permission": "Gwrthod Pawb", + "remember_Selection": "Cofio fy newis ar gyfer y teclyn hwn", "title": "Cymeradwyo hawliau teclyn" }, "capability": { - "always_on_screen_generic": "Arhoswch ar eich sgrin wrth redeg", - "always_on_screen_viewing_another_room": "Arhoswch ar eich sgrin wrth edrych ar ystafell arall, wrth redeg", - "any_room": "Yr uchod, ond mewn unrhyw ystafell yr ymunir â chi neu y gwahoddir chi iddi hefyd", + "always_on_screen_generic": "Arhos ar eich sgrin wrth redeg", + "always_on_screen_viewing_another_room": "Arhos ar eich sgrin wrth edrych ar ystafell arall, wrth redeg", + "any_room": "Yr uchod, ond mewn unrhyw ystafell rydych yn cael eich ymuno wahodd hefyd", "byline_empty_state_key": "gydag allwedd cyflwr gwag", "byline_state_key": "gydag allwedd cyflwr %(stateKey)s", "capability": "Y gallu %(capability)s", - "change_avatar_active_room": "Newidiwch afatar eich ystafell actif", + "change_avatar_active_room": "Newidiwch afatar eich ystafell weithredol", "change_avatar_this_room": "Newid afatar yr ystafell hon", "change_name_active_room": "Newidiwch enw eich ystafell weithredol", "change_name_this_room": "Newidiwch enw'r ystafell hon", "change_topic_active_room": "Newidiwch bwnc eich ystafell weithredol", "change_topic_this_room": "Newid pwnc yr ystafell hon", - "receive_membership_active_room": "Gweld pryd mae pobl yn ymuno, yn gadael, neu'n cael eu gwahodd i'ch ystafell actif", + "receive_membership_active_room": "Gweld pryd mae pobl yn ymuno, yn gadael, neu'n cael eu gwahodd i'ch ystafell weithredol", "receive_membership_this_room": "Gweld pryd mae pobl yn ymuno, yn gadael neu'n cael eu gwahodd i'r ystafell hon", - "remove_ban_invite_leave_active_room": "Dileu, gwahardd, neu wahodd pobl i'ch ystafell actif, a gwneud i chi adael", + "remove_ban_invite_leave_active_room": "Dileu, gwahardd, neu wahodd pobl i'ch ystafell weithredol, a gwneud i chi adael", "remove_ban_invite_leave_this_room": "Dileu, gwahardd, neu wahodd pobl i'r ystafell hon, a gwneud i chi adael", - "see_avatar_change_active_room": "Gweld pryd mae'r afatar yn newid yn eich ystafell actif", + "see_avatar_change_active_room": "Gweld pryd mae'r afatar yn newid yn eich ystafell weithredol", "see_avatar_change_this_room": "Gweld pryd mae'r afatar yn newid yn yr ystafell hon", - "see_event_type_sent_active_room": "Gweld %(eventType)s digwyddiad wedi'u postio i'ch ystafell dan sylw", + "see_event_type_sent_active_room": "Gweld %(eventType)s digwyddiad wedi'u postio i'ch ystafell weithredol", "see_event_type_sent_this_room": "Gweld %(eventType)s digwyddiad wedi'u postio i'r ystafell hon", - "see_images_sent_active_room": "Gweld delweddau sy'n cael eu postio i'ch ystafell actif", + "see_images_sent_active_room": "Gweld delweddau sy'n cael eu postio i'ch ystafell weithredol", "see_images_sent_this_room": "Gweld delweddau a bostiwyd i'r ystafell hon", "see_messages_sent_active_room": "Gweld negeseuon sy'n cael eu postio i'ch ystafell weithredol", "see_messages_sent_this_room": "Gweld negeseuon sy'n cael eu postio i'r ystafell hon", - "see_msgtype_sent_active_room": "Gweld %(msgtype)s neges wedi'u postio i'ch ystafell dan sylw", + "see_msgtype_sent_active_room": "Gweld %(msgtype)s neges wedi'u postio i'ch ystafell weithredol", "see_msgtype_sent_this_room": "Gweld %(msgtype)s neges wedi'u postio i'r ystafell hon", "see_name_change_active_room": "Gweld pryd mae'r enw'n newid yn eich ystafell weithredol", "see_name_change_this_room": "Gweld pryd mae'r enw'n newid yn yr ystafell hon", - "see_sent_emotes_active_room": "Gweld emosiynau sy'n cael eu postio i'ch ystafell actif", + "see_sent_emotes_active_room": "Gweld emosiynau sy'n cael eu postio i'ch ystafell weithredol", "see_sent_emotes_this_room": "Gweld emosiynau wedi'u postio i'r ystafell hon", "see_sent_files_active_room": "Gweld ffeiliau cyffredinol sy'n cael eu postio i'ch ystafell weithredol", "see_sent_files_this_room": "Gweld ffeiliau cyffredinol sy'n cael eu postio i'r ystafell hon", - "see_sticker_posted_active_room": "Gweld pryd mae unrhyw un yn postio sticer i'ch ystafell actif", + "see_sticker_posted_active_room": "Gweld pryd mae unrhyw un yn postio sticer i'ch ystafell weithredol", "see_sticker_posted_this_room": "Gweld pryd mae sticer yn cael ei bostio yn yr ystafell hon", "see_text_messages_sent_active_room": "Gweld negeseuon testun sy'n cael eu postio i'ch ystafell weithredol", "see_text_messages_sent_this_room": "Gweld negeseuon testun sy'n cael eu postio i'r ystafell hon", "see_topic_change_active_room": "Gweld pryd mae'r pwnc yn newid yn eich ystafell weithredol", "see_topic_change_this_room": "Gweld pryd mae'r pwnc yn newid yn yr ystafell hon", - "see_videos_sent_active_room": "Gweld fideos sy'n cael eu postio i'ch ystafell actif", + "see_videos_sent_active_room": "Gweld fideos sy'n cael eu postio i'ch ystafell weithredol", "see_videos_sent_this_room": "Gweld fideos sy'n cael eu postio i'r ystafell hon", - "send_emotes_active_room": "Anfonwch emosiynau wrth i chi yn eich ystafell actif", + "send_emotes_active_room": "Anfonwch emosiynau wrth i chi yn eich ystafell weithredol", "send_emotes_this_room": "Anfon emotes wrth i chi yn yr ystafell hon", "send_event_type_active_room": "Anfon %(eventType)s digwyddiad fel chi yn eich ystafell weithredol", "send_event_type_this_room": "Anfon %(eventType)s digwyddiad fel chi yn yr ystafell hon", - "send_files_active_room": "Anfonwch ffeiliau cyffredinol wrth i chi yn eich ystafell weithredol", - "send_files_this_room": "Anfonwch ffeiliau cyffredinol wrth i chi yn yr ystafell hon", - "send_images_active_room": "Anfonwch ddelweddau wrth i chi yn eich ystafell actif", - "send_images_this_room": "Anfonwch luniau fel chi yn yr ystafell hon", - "send_messages_active_room": "Anfon negeseuon wrth i chi yn eich ystafell weithredol", - "send_messages_this_room": "Anfon negeseuon wrth i chi yn yr ystafell hon", - "send_msgtype_active_room": "Anfon %(msgtype)s neges wrth i chi yn eich ystafell weithredol", + "send_files_active_room": "Anfon ffeiliau cyffredinol fel chi yn eich ystafell weithredol", + "send_files_this_room": "Anfon ffeiliau cyffredinol fel chi yn yr ystafell hon", + "send_images_active_room": "Anfon delweddau fel chi yn eich ystafell weithredol", + "send_images_this_room": "Anfon lluniau fel chi yn yr ystafell hon", + "send_messages_active_room": "Anfon negeseuon fel chi yn eich ystafell weithredol", + "send_messages_this_room": "Anfon negeseuon fel chi yn yr ystafell hon", + "send_msgtype_active_room": "Anfon %(msgtype)s neges fel chi yn eich ystafell weithredol", "send_msgtype_this_room": "Anfon %(msgtype)s neges fel chi yn yr ystafell hon", - "send_stickers_active_room": "Anfonwch sticeri i'ch ystafell actif", - "send_stickers_active_room_as_you": "Anfonwch sticeri i'ch ystafell actif fel chi", - "send_stickers_this_room": "Anfonwch sticeri i'r ystafell hon", - "send_stickers_this_room_as_you": "Anfonwch sticeri i'r ystafell hon fel chi", - "send_text_messages_active_room": "Anfon negeseuon testun wrth i chi yn eich ystafell weithredol", + "send_stickers_active_room": "Anfon sticeri i'ch ystafell weithredol", + "send_stickers_active_room_as_you": "Anfon sticeri i'ch ystafell weithredol fel chi", + "send_stickers_this_room": "Anfon sticeri i'r ystafell hon", + "send_stickers_this_room_as_you": "Anfon sticeri i'r ystafell hon fel chi", + "send_text_messages_active_room": "Anfon negeseuon testun fel chi yn eich ystafell weithredol", "send_text_messages_this_room": "Anfon negeseuon testun fel chi yn yr ystafell hon", - "send_videos_active_room": "Anfonwch fideos wrth i chi yn eich ystafell actif", - "send_videos_this_room": "Anfonwch fideos wrth i chi yn yr ystafell hon", - "specific_room": "Yr uchod, ond yn yn ogystal", + "send_videos_active_room": "Anfon fideos fel chi yn eich ystafell weithredol", + "send_videos_this_room": "Anfon fideos fel chi yn yr ystafell hon", + "specific_room": "Yr uchod, ond yn yn ogystal", "switch_room": "Newid pa ystafell rydych chi'n edrych arni", - "switch_room_message_user": "Newidiwch pa ystafell, neges neu ddefnyddiwr rydych chi'n edrych arno" + "switch_room_message_user": "Newid pa ystafell, neges neu ddefnyddiwr rydych chi'n edrych arno" }, "close_to_view_right_panel": "Caewch y teclyn hwn i'w weld yn y panel hwn", "context_menu": { @@ -3702,12 +3715,12 @@ "move_left": "Symud i'r chwith", "move_right": "Symud i'r dde", "remove": "Tynnwch i bawb", - "revoke": "Diddymu caniatadau", + "revoke": "Diddymu caniatâd", "screenshot": "Cymryd llun", "start_audio_stream": "Dechrau ffrwd sain" }, "cookie_warning": "Gall y teclyn hwn ddefnyddio cwcis.", - "error_hangup_description": "Cawsoch eich datgysylltu o'r alwad. (Gwall: %(message)s)", + "error_hangup_description": "Rydych wedi'ch datgysylltu o'r alwad. (Gwall: %(message)s)", "error_hangup_title": "Cysylltiad wedi'i golli", "error_loading": "Gwall wrth lwytho'r teclyn", "error_mixed_content": "Gwall - Cynnwys cymysg", @@ -3715,7 +3728,7 @@ "error_need_kick_permission": "Mae angen i chi allu cicio defnyddwyr i wneud hynny.", "error_need_to_be_logged_in": "Mae angen i chi fod wedi mewngofnodi.", "error_unable_start_audio_stream_description": "Methu dechrau ffrydio sain.", - "error_unable_start_audio_stream_title": "Wedi methu cychwyn llif byw", + "error_unable_start_audio_stream_title": "Methu cychwyn llif byw", "modal_data_warning": "Mae data ar y sgrin hon yn cael ei rannu â %(widgetDomain)s", "modal_title_default": "Teclyn Modal", "no_name": "Ap Anhysbys", @@ -3724,13 +3737,13 @@ "starting_text": "Bydd y teclyn yn gwirio eich ID defnyddiwr, ond ni fydd yn gallu cyflawni gweithredoedd ar eich rhan:", "title": "Caniatáu i'r teclyn hwn wirio'ch hunaniaeth" }, - "popout": "Teclyn pop-out", + "popout": "Teclyn llamu allan", "set_room_layout": "Gosodwch y cynllun i bawb", "shared_data_avatar": "URL eich llun proffil", "shared_data_device_id": "ID eich dyfais", "shared_data_lang": "Eich iaith", "shared_data_mxid": "Eich ID defnyddiwr", - "shared_data_name": "Eich enw arddangos", + "shared_data_name": "Eich enw dangos", "shared_data_room_id": "ID ystafell", "shared_data_theme": "Eich thema", "shared_data_url": "URL %(brand)s", @@ -3738,25 +3751,25 @@ "shared_data_warning_im": "Gall defnyddio'r teclyn hwn rannu data gyda %(widgetDomain)s a'ch rheolwr integreiddio.", "shared_data_widget_id": "ID teclyn", "unencrypted_warning": "Nid yw teclynnau'n defnyddio amgryptio negeseuon.", - "unmaximise": "Dad-wneud y mwyaf", + "unmaximise": "Dad-wneud mwyaf", "unpin_to_view_right_panel": "Dad-binio'r teclyn hwn i'w weld yn y panel hwn" }, "zxcvbn": { "suggestions": { "allUppercase": "Mae prif lythrennau bron mor hawdd i'w ddyfalu â llythrennau bach", "anotherWord": "Ychwanegwch air neu ddau arall. Mae geiriau anghyffredin yn well.", - "associatedYears": "Osgoi blynyddoedd sy'n gysylltiedig â chi", - "capitalization": "Nid yw cyfalafu yn helpu llawer", + "associatedYears": "Osgowch flynyddoedd sy'n gysylltiedig â chi", + "capitalization": "Nid yw priflythrennau'n helpu llawer", "dates": "Osgowch ddyddiadau a blynyddoedd sy'n gysylltiedig â chi", "l33t": "Nid yw dirprwyon rhagweladwy fel '@' yn lle 'a' yn helpu llawer", - "longerKeyboardPattern": "Defnyddiwch batrwm bysellfwrdd hirach gyda mwy o droeon", + "longerKeyboardPattern": "Defnyddio patrwm bysellfwrdd hirach gyda mwy o droeon", "noNeed": "Nid oes angen symbolau, digidau na llythrennau mawr", "pwned": "Os ydych chi'n defnyddio'r cyfrinair hwn yn rhywle arall, dylech ei newid.", - "recentYears": "Osgoi blynyddoedd diweddar", - "repeated": "Osgowch eiriau a chymeriadau ailadroddus", + "recentYears": "Osgowch flynyddoedd diweddar", + "repeated": "Osgowch eiriau a nodau ailadroddus", "reverseWords": "Nid yw geiriau wedi'u gwrthdroi yn llawer anoddach i'w dyfalu", - "sequences": "Osgoi dilyniannau", - "useWords": "Defnyddiwch ychydig o eiriau, osgoi ymadroddion cyffredin" + "sequences": "Osgowch ddilyniannau", + "useWords": "Defnyddio ychydig o eiriau, osgowch ymadroddion cyffredin" }, "warnings": { "common": "Mae hwn yn gyfrinair cyffredin iawn", @@ -3768,12 +3781,12 @@ "pwned": "Datgelwyd eich cyfrinair gan dor-data ar y Rhyngrwyd.", "recentYears": "Mae'r blynyddoedd diwethaf yn hawdd i'w dyfalu", "sequences": "Mae dilyniannau fel abc neu 6543 yn hawdd i'w dyfalu", - "similarToCommon": "Mae hyn yn debyg i gyfrinair a ddefnyddir yn gyffredin", + "similarToCommon": "Mae hyn yn debyg i gyfrinair sy'n cael ei ddefnyddio'n gyffredin", "simpleRepeat": "Mae ailadroddiadau fel \"aaa\" yn hawdd i'w dyfalu", "straightRow": "Mae rhesi syth o allweddi yn hawdd i'w dyfalu", "topHundred": "Mae hwn yn gyfrinair cyffredin o'r 100 uchaf", "topTen": "Mae hwn yn gyfrinair cyffredin o'r 10 uchaf", - "userInputs": "Ni ddylai fod unrhyw ddata personol neu ddata cysylltiedig â thudalennau.", + "userInputs": "Dylai fod dim data personol neu ddata cysylltiedig â thudalennau.", "wordByItself": "Mae gair ynddo'i hun yn hawdd i'w ddyfalu" } } diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 0517b2e5bf..890508a829 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -407,6 +407,15 @@ "download_logs": "Protokolle herunterladen", "downloading_logs": "Lade Protokolle herunter", "error_empty": "Bitte teile uns mit, was schief lief - oder besser, beschreibe das Problem auf GitHub in einem \"Issue\".", + "failed_download_logs": "Debug-Protokolle konnten nicht heruntergeladen werden: ", + "failed_send_logs_causes": { + "disallowed_app": "Der Fehlerbericht wurde abgelehnt. Der Rageshake-Server unterstützt diese Anwendung nicht.", + "rejected_generic": "Der Bugreport wurde abgelehnt. Der Rageshake-Server hat den Inhalt des Berichts aufgrund einer Richtlinie abgelehnt.", + "rejected_recovery_key": "Der Fehlerbericht wurde aus Sicherheitsgründen abgelehnt, da er einen Wiederherstellungsschlüssel enthielt.", + "rejected_version": "Dein Fehlerbericht wurde abgelehnt, da die verwendete Version veraltet ist.", + "server_unknown_error": "Der Rageshake-Server hat einen unbekannten Fehler festgestellt und konnte den Bericht nicht verarbeiten.", + "unknown_error": "Protokolle konnten nicht gesendet werden." + }, "github_issue": "GitHub-Problem", "introduction": "Wenn du uns einen Bug auf GitHub gemeldet hast, können uns Debug-Logs helfen, das Problem zu finden. ", "log_request": "Um uns zu helfen, dies in Zukunft zu vermeiden, sende uns bitte die Protokolldateien.", @@ -446,7 +455,6 @@ "access_token": "Zugriffstoken", "accessibility": "Barrierefreiheit", "advanced": "Erweitert", - "all_rooms": "Alle Räume", "analytics": "Analysedaten", "and_n_others": { "other": "und %(count)s weitere …", @@ -1297,6 +1305,7 @@ "error_connecting_heading": "Verbindung zum Integrationsassistenten fehlgeschlagen", "explainer": "Integrationsassistenten erhalten Konfigurationsdaten und können Widgets modifizieren, Raumeinladungen verschicken und in deinem Namen Berechtigungslevel setzen.", "manage_title": "Integrationen verwalten", + "toggle_label": "Aktivieren Sie den Integrationsmanager", "use_im": "Verwende einen Integrations-Server, um Bots, Widgets und Sticker-Pakete zu verwalten.", "use_im_default": "Nutze einen Integrations-Server (%(serverName)s), um Bots, Widgets und Sticker-Pakete zu verwalten." }, @@ -2088,18 +2097,29 @@ "failed_add_tag": "Fehler beim Hinzufügen des \"%(tagName)s\"-Tags an dem Raum", "failed_remove_tag": "Entfernen der Raum-Kennzeichnung %(tagName)s fehlgeschlagen", "failed_set_dm_tag": "Fehler beim Setzen der Nachrichtenmarkierung", + "filters": { + "favourite": "Favoriten", + "people": "Personen", + "rooms": "Räume", + "unread": "Ungelesen" + }, "home_menu_label": "Startseiteneinstellungen", "join_public_room_label": "Öffentlichen Raum betreten", "joining_rooms_status": { "one": "Betrete %(count)s Raum", "other": "Betrete %(count)s Räume" }, + "list_title": "Raumliste", "notification_options": "Benachrichtigungsoptionen", "open_space_menu": "Menü „Raum öffnen“", + "primary_filters": "Filter für die Raumliste", "redacting_messages_status": { "one": "Entferne Nachrichten in %(count)s Raum", "other": "Entferne Nachrichten in %(count)s Räumen" }, + "room": { + "open_room": "Raum öffnen %(roomName)s" + }, "show_less": "Weniger anzeigen", "show_n_more": { "other": "%(count)s weitere anzeigen", @@ -2488,10 +2508,23 @@ "session_key": "Sitzungsschlüssel:", "title": "Advanced" }, + "delete_key_storage": { + "breadcrumb_page": "Schlüsselspeicher löschen", + "confirm": "Schlüsselspeicher löschen", + "description": "Durch das Löschen des Schlüsselspeichers werden Ihre kryptografische Identität und Ihre Nachrichtenschlüssel vom Server entfernt und die folgenden Sicherheitsfunktionen werden deaktiviert:", + "list_first": "Sie werden auf neuen Geräten keinen verschlüsselten Nachrichtenverlauf haben", + "list_second": "Sie verlieren den Zugriff auf Ihre verschlüsselten Nachrichten, wenn Sie von %(brand)s überall abgemeldet sind", + "title": "Möchten Sie den Schlüsselspeicher wirklich ausschalten und löschen?" + }, "device_not_verified_button": "Dieses Gerät verifizieren", "device_not_verified_description": "Sie müssen dieses Gerät verifizieren, um Ihre Verschlüsselungseinstellungen einsehen zu können.", "device_not_verified_title": "Gerät nicht verifiziert", "dialog_title": "Einstellungen: Verschlüsselung", + "key_storage": { + "allow_key_storage": "Schlüsselspeicherung zulassen", + "description": "Speichern Sie Ihre kryptografische Identität und Ihre Nachrichtenschlüssel sicher auf dem Server. Auf diese Weise können Sie Ihren Nachrichtenverlauf auf allen neuen Geräten einsehen. Erfahre mehr ", + "title": "Schlüsselspeicher" + }, "recovery": { "change_recovery_confirm_button": "Bestätigen Sie den neuen Wiederherstellungsschlüssel", "change_recovery_confirm_description": "Geben Sie unten Ihren neuen Wiederherstellungsschlüssel ein, um den Vorgang abzuschließen. Ihr alter Wiederherstellungsschlüssel funktioniert nicht mehr.", @@ -2608,6 +2641,7 @@ "inline_url_previews_room": "URL-Vorschau für Raummitglieder", "inline_url_previews_room_account": "URL-Vorschau für dich in diesem Raum", "insert_trailing_colon_mentions": "Doppelpunkt nach Erwähnungen einfügen", + "invite_avatars": "Zeigen Sie Avatare von Chatrooms an, zu denen Sie eingeladen wurden", "jump_to_bottom_on_send": "Nach Senden einer Nachricht im Verlauf nach unten springen", "key_backup": { "backup_in_progress": "Deine Schlüssel werden gesichert (Das erste Backup könnte ein paar Minuten in Anspruch nehmen).", diff --git a/src/i18n/strings/el.json b/src/i18n/strings/el.json index 19ebbed984..3307ece5e5 100644 --- a/src/i18n/strings/el.json +++ b/src/i18n/strings/el.json @@ -352,7 +352,6 @@ "access_token": "Διακριτικό πρόσβασης", "accessibility": "Προσβασιμότητα", "advanced": "Προχωρημένες", - "all_rooms": "Όλα τα δωμάτια", "analytics": "Αναλυτικά δεδομένα", "and_n_others": { "one": "και ένας ακόμα...", diff --git a/src/i18n/strings/eo.json b/src/i18n/strings/eo.json index 2c68437086..e1d1e175a0 100644 --- a/src/i18n/strings/eo.json +++ b/src/i18n/strings/eo.json @@ -333,7 +333,6 @@ "access_token": "Alirpeco", "accessibility": "Alirebleco", "advanced": "Altnivela", - "all_rooms": "Ĉiuj ĉambroj", "analytics": "Analizo", "and_n_others": { "other": "kaj %(count)s aliaj…", diff --git a/src/i18n/strings/es.json b/src/i18n/strings/es.json index 60aa278469..d1318a8aa6 100644 --- a/src/i18n/strings/es.json +++ b/src/i18n/strings/es.json @@ -387,7 +387,6 @@ "access_token": "Token de acceso", "accessibility": "Accesibilidad", "advanced": "Avanzado", - "all_rooms": "Todas las salas", "analytics": "Analítica de datos", "and_n_others": { "other": "y %(count)s más…", diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 0ec47dc662..b62c9cd7bb 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -444,7 +444,6 @@ "access_token": "Pääsuluba", "accessibility": "Ligipääsetavus", "advanced": "Teave arendajatele", - "all_rooms": "Kõik jututoad", "analytics": "Analüütika", "and_n_others": { "other": "ja %(count)s muud...", diff --git a/src/i18n/strings/fa.json b/src/i18n/strings/fa.json index 6d8d71fcff..3b93b0ba92 100644 --- a/src/i18n/strings/fa.json +++ b/src/i18n/strings/fa.json @@ -321,7 +321,6 @@ "access_token": "توکن دسترسی", "accessibility": "دسترسی", "advanced": "پیشرفته", - "all_rooms": "همه اتاق‌ها", "analytics": "تجزیه و تحلیل", "and_n_others": { "one": "و یکی دیگر ...", diff --git a/src/i18n/strings/fi.json b/src/i18n/strings/fi.json index d6f80c03d0..cb594c05d1 100644 --- a/src/i18n/strings/fi.json +++ b/src/i18n/strings/fi.json @@ -431,7 +431,6 @@ "access_token": "Käyttöpoletti", "accessibility": "Saavutettavuus", "advanced": "Lisäasetukset", - "all_rooms": "Kaikki huoneet", "analytics": "Analytiikka", "and_n_others": { "other": "ja %(count)s muuta...", diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index 0ed0f87ff3..f4edcccf82 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -455,7 +455,7 @@ "access_token": "Jeton d’accès", "accessibility": "Accessibilité", "advanced": "Avancé", - "all_rooms": "Tous les salons", + "all_chats": "Toutes les discussions", "analytics": "Collecte de données", "and_n_others": { "other": "et %(count)s autres…", @@ -2113,6 +2113,7 @@ "list_title": "Liste de salons", "notification_options": "Paramètres de notifications", "open_space_menu": "Ouvrir le menu de l’espace", + "primary_filters": "Filtre de la liste des salons", "redacting_messages_status": { "one": "Actuellement en train de supprimer les messages dans %(count)s salon", "other": "Actuellement en train de supprimer les messages dans %(count)s salons" @@ -2508,10 +2509,23 @@ "session_key": "Clé de session :", "title": "Avancé" }, + "delete_key_storage": { + "breadcrumb_page": "Désactiver la sauvegarde", + "confirm": "Désactiver la sauvegarde", + "description": "Désactiver la sauvegarde supprimera votre clé de récupération actuelle et désactivera d’autres mesures de sécurité. Dans ce cas :", + "list_first": "Pas d’accès à l’historique des discussions chiffrées sur vos nouveaux appareils", + "list_second": "Vous perdrez l'accès à vos messages chiffrés si vous êtes déconnecté de %(brand)s sur tout vos appareils", + "title": "Êtes-vous certain de vouloir désactiver la sauvegarde ?" + }, "device_not_verified_button": "Vérifiez cet appareil", "device_not_verified_description": "Vous devez vérifier cet appareil afin de visualiser vos paramètres de chiffrement.", "device_not_verified_title": "Appareil non vérifié", "dialog_title": "Paramètres : Chiffrement", + "key_storage": { + "allow_key_storage": "Autoriser le stockage des clés", + "description": "Stockez votre identité cryptographique et vos clés de message en toute sécurité sur le serveur. Cela vous permettra de consulter l'historique de vos messages sur tous les nouveaux appareils. En savoir plus", + "title": "Stockage des clés" + }, "recovery": { "change_recovery_confirm_button": "Confirmez la nouvelle clé de récupération", "change_recovery_confirm_description": "Saisissez votre nouvelle clé de récupération ci-dessous pour terminer. Votre ancienne clé ne fonctionnera plus.", @@ -2628,6 +2642,7 @@ "inline_url_previews_room": "Activer l’aperçu des URL par défaut pour les participants de ce salon", "inline_url_previews_room_account": "Activer l’aperçu des URL pour ce salon (n’affecte que vous)", "insert_trailing_colon_mentions": "Insérer deux-points après les mentions de l'utilisateur au début d'un message", + "invite_avatars": "Afficher les avatars des salons dans lesquels vous avez été invité", "jump_to_bottom_on_send": "Sauter en bas du fil de discussion lorsque vous envoyez un message", "key_backup": { "backup_in_progress": "Vous clés sont en cours de sauvegarde (la première sauvegarde peut prendre quelques minutes).", diff --git a/src/i18n/strings/gl.json b/src/i18n/strings/gl.json index f399214511..008776a8fb 100644 --- a/src/i18n/strings/gl.json +++ b/src/i18n/strings/gl.json @@ -356,7 +356,6 @@ "access_token": "Token de acceso", "accessibility": "Accesibilidade", "advanced": "Avanzado", - "all_rooms": "Todas as salas", "analytics": "Análise", "and_n_others": { "other": "e %(count)s outras...", diff --git a/src/i18n/strings/he.json b/src/i18n/strings/he.json index 1be8d900f5..63bda4eb71 100644 --- a/src/i18n/strings/he.json +++ b/src/i18n/strings/he.json @@ -325,7 +325,6 @@ "common": { "accessibility": "נגישות", "advanced": "מתקדם", - "all_rooms": "כל החדרים", "analytics": "אנליטיקה", "and_n_others": { "one": "ועוד אחד אחר...", diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index 6b569ad870..c7b62ed03f 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -446,7 +446,6 @@ "access_token": "Hozzáférési kulcs", "accessibility": "Akadálymentesség", "advanced": "Speciális", - "all_rooms": "Összes szoba", "analytics": "Analitika", "and_n_others": { "és még: %(count)s ...": "other", diff --git a/src/i18n/strings/id.json b/src/i18n/strings/id.json index c591a11e65..9e14060ce0 100644 --- a/src/i18n/strings/id.json +++ b/src/i18n/strings/id.json @@ -404,7 +404,6 @@ "access_token": "Token Akses", "accessibility": "Aksesibilitas", "advanced": "Tingkat Lanjut", - "all_rooms": "Semua ruangan", "analytics": "Analitik", "and_n_others": { "one": "dan satu lainnya...", diff --git a/src/i18n/strings/is.json b/src/i18n/strings/is.json index 179961871d..29c50b5e35 100644 --- a/src/i18n/strings/is.json +++ b/src/i18n/strings/is.json @@ -352,7 +352,6 @@ "access_token": "Aðgangsteikn", "accessibility": "Auðveldað aðgengi", "advanced": "Nánar", - "all_rooms": "Allar spjallrásir", "analytics": "Greiningar", "and_n_others": { "one": "og einn í viðbót...", diff --git a/src/i18n/strings/it.json b/src/i18n/strings/it.json index 5e240b68c3..f1d4029dc9 100644 --- a/src/i18n/strings/it.json +++ b/src/i18n/strings/it.json @@ -411,7 +411,6 @@ "access_token": "Token di accesso", "accessibility": "Accessibilità", "advanced": "Avanzato", - "all_rooms": "Tutte le stanze", "analytics": "Statistiche", "and_n_others": { "other": "e altri %(count)s ...", diff --git a/src/i18n/strings/ja.json b/src/i18n/strings/ja.json index ee9172d575..50b2186535 100644 --- a/src/i18n/strings/ja.json +++ b/src/i18n/strings/ja.json @@ -392,7 +392,6 @@ "access_token": "アクセストークン", "accessibility": "アクセシビリティー", "advanced": "詳細", - "all_rooms": "全てのルーム", "analytics": "分析", "and_n_others": { "other": "他%(count)s人…", diff --git a/src/i18n/strings/ka.json b/src/i18n/strings/ka.json index 2f5610c106..b590710b45 100644 --- a/src/i18n/strings/ka.json +++ b/src/i18n/strings/ka.json @@ -372,7 +372,6 @@ "access_token": "წვდომის ჟეტონი", "accessibility": "მარტივი წვდომა", "advanced": "გაფართოებული", - "all_rooms": "ყველა ოთახი", "analytics": "ანალიტიკა", "and_n_others": { "one": "და ერთი სხვა...", diff --git a/src/i18n/strings/lo.json b/src/i18n/strings/lo.json index eeb3bb883f..8f2e6ccb97 100644 --- a/src/i18n/strings/lo.json +++ b/src/i18n/strings/lo.json @@ -353,7 +353,6 @@ "access_token": "ເຂົ້າເຖິງToken", "accessibility": "ການເຂົ້າເຖິງ", "advanced": "ຂັ້ນສູງ", - "all_rooms": "ຫ້ອງທັງໝົດ", "analytics": "ວິເຄາະ", "and_n_others": { "one": "ແລະ ອີກອັນນຶ່ງ...", diff --git a/src/i18n/strings/lt.json b/src/i18n/strings/lt.json index 2c2a0361dd..cfc0d828d1 100644 --- a/src/i18n/strings/lt.json +++ b/src/i18n/strings/lt.json @@ -289,7 +289,6 @@ "common": { "access_token": "Prieigos žetonas", "advanced": "Išplėstiniai", - "all_rooms": "Visi kambariai", "analytics": "Analitika", "and_n_others": { "other": "ir %(count)s kitų...", diff --git a/src/i18n/strings/lv.json b/src/i18n/strings/lv.json index 97f28fc1de..8dff959ef6 100644 --- a/src/i18n/strings/lv.json +++ b/src/i18n/strings/lv.json @@ -443,7 +443,6 @@ "access_token": "Piekļuves pilvnara", "accessibility": "Pieejamība", "advanced": "Papildu", - "all_rooms": "Visas istabas", "analytics": "Analītika", "and_n_others": { "other": "un vēl %(count)s citi...", diff --git a/src/i18n/strings/mg_MG.json b/src/i18n/strings/mg_MG.json index f566a109b7..fd8c8bf1b8 100644 --- a/src/i18n/strings/mg_MG.json +++ b/src/i18n/strings/mg_MG.json @@ -408,7 +408,6 @@ "access_token": "Famantarana fidirana", "accessibility": "Fahafahana", "advanced": "Jery lavitra", - "all_rooms": "Efitra rehetra", "analytics": "Mandalina", "and_n_others": { "one": "ary ny iray hafa...", diff --git a/src/i18n/strings/nb_NO.json b/src/i18n/strings/nb_NO.json index 5bbe695639..d609580baa 100644 --- a/src/i18n/strings/nb_NO.json +++ b/src/i18n/strings/nb_NO.json @@ -409,7 +409,12 @@ "error_empty": "Fortell oss hva som gikk galt, eller bedre, opprett et GitHub-problem som beskriver problemet.", "failed_download_logs": "Kunne ikke laste ned feilsøkingslogger: ", "failed_send_logs_causes": { - "disallowed_app": "Feilrapporten din ble avvist. Rageshake-serveren støtter ikke denne applikasjonen." + "disallowed_app": "Feilrapporten din ble avvist. Rageshake-serveren støtter ikke denne applikasjonen.", + "rejected_generic": "Feilrapporten din ble avvist. Rageshake-serveren avviste innholdet i rapporten på grunn av en policy.", + "rejected_recovery_key": "Feilrapporten din ble avvist av sikkerhetsgrunner, da den inneholdt en gjenopprettingsnøkkel.", + "rejected_version": "Feilrapporten din ble avvist fordi versjonen du kjører er for gammel.", + "server_unknown_error": "Det oppstod en ukjent feil på rageshake-serveren, og rapporten kunne ikke håndteres.", + "unknown_error": "Kunne ikke sende logger." }, "github_issue": "Github-saksrapport", "introduction": "Hvis du har sendt inn en feil via GitHub, kan feilsøkingslogger hjelpe oss med å spore opp problemet. ", @@ -450,7 +455,6 @@ "access_token": "Tilgangstoken", "accessibility": "Tilgjengelighet", "advanced": "Avansert", - "all_rooms": "Alle rom", "analytics": "Statistikk", "and_n_others": { "og %(count)s andre …": "other", @@ -1301,6 +1305,7 @@ "error_connecting_heading": "Kan ikke koble til integrasjonsadministrator", "explainer": "Integreringsbehandlere mottar oppsettsdata, og kan endre på moduler, sende rominvitasjoner, og bestemme tilgangsnivår på dine vegne.", "manage_title": "Behandle integreringer", + "toggle_label": "Aktiver integrasjonsbehandleren", "use_im": "Bruk en integreringsbehandler til å behandle botter, moduler, og klistremerkepakker.", "use_im_default": "Bruk en integreringsbehandler (%(serverName)s) til å behandle botter, moduler, og klistremerkepakker." }, @@ -2093,18 +2098,29 @@ "failed_add_tag": "Kunne ikke legge til tagg %(tagName)s til rom", "failed_remove_tag": "Kunne ikke fjerne tagg %(tagName)s fra rommet", "failed_set_dm_tag": "Kan ikke sette kode på direktemeldingen", + "filters": { + "favourite": "Favoritter", + "people": "Personer", + "rooms": "Rom", + "unread": "Ulest" + }, "home_menu_label": "Hjem alternativer", "join_public_room_label": "Bli med i offentlig rom", "joining_rooms_status": { "one": "Blir for øyeblikket med i %(count)s rom", "other": "Blir for øyeblikket med i %(count)s rom" }, + "list_title": "Romliste", "notification_options": "Varselsinnstillinger", "open_space_menu": "Åpne Område-meny", + "primary_filters": "Filtre for romliste", "redacting_messages_status": { "one": "Fjerner for øyeblikket meldinger i %(count)s rom", "other": "Fjerner for øyeblikket meldinger i %(count)s rom" }, + "room": { + "open_room": "Åpne rom %(roomName)s" + }, "show_less": "Vis mindre", "show_n_more": { "one": "Vis %(count)s mer", @@ -2493,10 +2509,19 @@ "session_key": "Sesjonsnøkkel:", "title": "Avansert" }, + "delete_key_storage": { + "confirm": "Slett nøkkellagring", + "list_first": "Du vil ikke ha kryptert meldingshistorikk på nye enheter", + "list_second": "Du vil miste tilgangen til de krypterte meldingene dine hvis du logger av %(brand)s overalt", + "title": "Er du sikker på at du vil slå av nøkkellagring og slette den?" + }, "device_not_verified_button": "Bekreft denne enheten", "device_not_verified_description": "Du må bekrefte denne enheten for å kunne se krypteringsinnstillingene dine.", "device_not_verified_title": "Enhet er ikke verifisert", "dialog_title": "Innstillinger: Kryptering", + "key_storage": { + "allow_key_storage": "Tillat lagring av nøkler" + }, "recovery": { "change_recovery_confirm_button": "Bekreft ny gjenopprettingsnøkkel", "change_recovery_confirm_description": "Skriv inn den nye gjenopprettingsnøkkelen nedenfor for å fullføre. Den gamle vil ikke lenger fungere.", @@ -2613,6 +2638,7 @@ "inline_url_previews_room": "Skru på URL-forhåndsvisninger som standard for deltakerne i dette rommet", "inline_url_previews_room_account": "Skru på URL-forhåndsvisninger for dette rommet (Påvirker bare deg)", "insert_trailing_colon_mentions": "Sett inn et etterfølgende kolon etter at brukeromtaler i starten av en melding", + "invite_avatars": "Vis avatarer til rom du har blitt invitert til", "jump_to_bottom_on_send": "Gå til bunnen av tidslinjen når du vil sende en melding", "key_backup": { "backup_in_progress": "Nøklene dine blir sikkerhetskopiert (den første sikkerhetskopieringen kan ta noen minutter).", diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index ff287e80e1..2650a3831b 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -374,7 +374,6 @@ "access_token": "Toegangstoken", "accessibility": "Toegankelijkheid", "advanced": "Geavanceerd", - "all_rooms": "Alle kamers", "analytics": "Gebruiksgegevens", "and_n_others": { "other": "en %(count)s anderen…", diff --git a/src/i18n/strings/pl.json b/src/i18n/strings/pl.json index 8795a74b8e..2f96ced9e5 100644 --- a/src/i18n/strings/pl.json +++ b/src/i18n/strings/pl.json @@ -446,7 +446,6 @@ "access_token": "Token dostępu", "accessibility": "Ułatwienia dostępu", "advanced": "Zaawansowane", - "all_rooms": "Wszystkie pokoje", "analytics": "Analityka", "and_n_others": { "one": "i jeden inny...", diff --git a/src/i18n/strings/pt.json b/src/i18n/strings/pt.json index 7f348223e9..a4e71bf9b7 100644 --- a/src/i18n/strings/pt.json +++ b/src/i18n/strings/pt.json @@ -444,7 +444,6 @@ "access_token": "Token de acesso", "accessibility": "Acessibilidade", "advanced": "Avançado", - "all_rooms": "Todas as salas", "analytics": "Análise", "and_n_others": { "other": "e %(count)s outros...", diff --git a/src/i18n/strings/pt_BR.json b/src/i18n/strings/pt_BR.json index d2cd4fe848..76f50ef241 100644 --- a/src/i18n/strings/pt_BR.json +++ b/src/i18n/strings/pt_BR.json @@ -415,7 +415,6 @@ "access_token": "Símbolo de acesso", "accessibility": "Acessibilidade", "advanced": "Avançado", - "all_rooms": "Todas as salas", "analytics": "Análise", "and_n_others": { "one": "e um outro...", diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 190dbe30a1..79fbf98051 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -405,7 +405,6 @@ "access_token": "Токен доступа", "accessibility": "Доступность", "advanced": "Подробности", - "all_rooms": "Все комнаты", "analytics": "Аналитика", "and_n_others": { "other": "и %(count)s других...", diff --git a/src/i18n/strings/sk.json b/src/i18n/strings/sk.json index b5528cb237..6697b16e70 100644 --- a/src/i18n/strings/sk.json +++ b/src/i18n/strings/sk.json @@ -405,7 +405,6 @@ "access_token": "Prístupový token", "accessibility": "Prístupnosť", "advanced": "Pokročilé", - "all_rooms": "Všetky miestnosti", "analytics": "Analytické údaje", "and_n_others": { "other": "a ďalších %(count)s…", diff --git a/src/i18n/strings/sq.json b/src/i18n/strings/sq.json index bcd804bf15..c8c3d96757 100644 --- a/src/i18n/strings/sq.json +++ b/src/i18n/strings/sq.json @@ -396,7 +396,6 @@ "access_token": "Token Hyrjesh", "accessibility": "Përdorim nga persona me aftësi të kufizuara", "advanced": "Të mëtejshme", - "all_rooms": "Krejt dhomat", "analytics": "Analiza", "and_n_others": { "other": "dhe %(count)s të tjerë…", diff --git a/src/i18n/strings/sv.json b/src/i18n/strings/sv.json index a2f58e0049..34b573defb 100644 --- a/src/i18n/strings/sv.json +++ b/src/i18n/strings/sv.json @@ -444,7 +444,6 @@ "access_token": "Åtkomsttoken", "accessibility": "Tillgänglighet", "advanced": "Avancerat", - "all_rooms": "Alla rum", "analytics": "Statistik", "and_n_others": { "other": "och %(count)s andra…", diff --git a/src/i18n/strings/tr.json b/src/i18n/strings/tr.json index 9c1ad1b6fe..a183b580a3 100644 --- a/src/i18n/strings/tr.json +++ b/src/i18n/strings/tr.json @@ -444,7 +444,6 @@ "access_token": "Erişim Jetonu", "accessibility": "Erişilebilirlik", "advanced": "Gelişmiş", - "all_rooms": "Tüm odalar", "analytics": "Analizler", "and_n_others": { "one": "ve bir diğeri...", diff --git a/src/i18n/strings/uk.json b/src/i18n/strings/uk.json index 4996466148..3081cdd219 100644 --- a/src/i18n/strings/uk.json +++ b/src/i18n/strings/uk.json @@ -455,7 +455,6 @@ "access_token": "Токен доступу", "accessibility": "Доступність", "advanced": "Подробиці", - "all_rooms": "Усі кімнати", "analytics": "Аналітика", "and_n_others": { "one": "і інше...", diff --git a/src/i18n/strings/vi.json b/src/i18n/strings/vi.json index dd2e6fecf3..875ec0f1ca 100644 --- a/src/i18n/strings/vi.json +++ b/src/i18n/strings/vi.json @@ -370,7 +370,6 @@ "common": { "access_token": "Token truy cập", "advanced": "Nâng cao", - "all_rooms": "Tất cả các phòng", "analytics": "Về dữ liệu phân tích", "and_n_others": { "one": "và một cái khác…", diff --git a/src/i18n/strings/zh_Hans.json b/src/i18n/strings/zh_Hans.json index e42bb2160a..70fd454fc7 100644 --- a/src/i18n/strings/zh_Hans.json +++ b/src/i18n/strings/zh_Hans.json @@ -388,7 +388,6 @@ "access_token": "访问令牌", "accessibility": "无障碍功能", "advanced": "高级", - "all_rooms": "所有房间", "analytics": "统计分析服务", "and_n_others": { "other": "和其他%(count)s个人……", diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index f670086a7c..7eeccd6989 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -403,7 +403,6 @@ "access_token": "存取權杖", "accessibility": "可近用性", "advanced": "進階", - "all_rooms": "所有聊天室", "analytics": "分析", "and_n_others": { "other": "與另 %(count)s 個人…", From 4af5d4ac80027d6af07a4c1483c0bde7f2a7638f Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Mon, 17 Mar 2025 09:05:21 +0000 Subject: [PATCH 087/458] Do not lint playwright files. (#29510) --- .eslintignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.eslintignore b/.eslintignore index 1cdde75cbc..08ec761fb3 100644 --- a/.eslintignore +++ b/.eslintignore @@ -8,3 +8,6 @@ src/component-index.js # Auto-generated file src/modules.ts src/modules.js +# Test result files +/playwright/test-results/ +/playwright/html-report/ From ff1da50dd99e02d1548976357718e1608b795488 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 17 Mar 2025 09:16:45 +0000 Subject: [PATCH 088/458] Move a bunch of shared playwright code into @element-hq/element-web-playwright-common (#29477) * Move a bunch of shared playwright code into @element-hq/element-web-playwright-common Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Remove stale devDep Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update playwright-common Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update screenshot Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix testcontainers version Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- package.json | 17 +- playwright.config.ts | 5 +- playwright/@types/playwright-core.d.ts | 12 - playwright/Dockerfile | 9 - playwright/docker-entrypoint.sh | 5 - playwright/e2e/csAPI.ts | 4 +- playwright/e2e/editing/editing.spec.ts | 6 +- playwright/e2e/login/login-consent.spec.ts | 6 +- playwright/e2e/messages/messages.spec.ts | 2 +- playwright/e2e/oidc/index.ts | 2 +- playwright/e2e/register/email.spec.ts | 4 +- playwright/e2e/register/register.spec.ts | 10 +- playwright/e2e/spaces/spaces.spec.ts | 6 +- playwright/e2e/timeline/timeline.spec.ts | 104 +++-- playwright/element-web-test.ts | 231 ++--------- playwright/logger.ts | 63 --- .../plugins/homeserver/dendrite/index.ts | 4 +- playwright/plugins/homeserver/index.ts | 2 +- .../homeserver/synapse/consentHomeserver.ts | 19 +- .../homeserver/synapse/masHomeserver.ts | 3 +- playwright/plugins/oauth_server/index.ts | 3 +- playwright/plugins/utils/api.ts | 76 ---- playwright/plugins/utils/object.ts | 16 - playwright/plugins/utils/port.ts | 19 - playwright/plugins/utils/rand.ts | 13 - playwright/plugins/webserver/index.ts | 4 +- playwright/services.ts | 141 +------ .../with-four-members-linux.png | Bin 18392 -> 19391 bytes .../testcontainers/HomeserverContainer.ts | 24 -- playwright/testcontainers/dendrite.ts | 20 +- playwright/testcontainers/mailpit.ts | 33 -- playwright/testcontainers/mas.ts | 346 ---------------- playwright/testcontainers/synapse.ts | 391 +----------------- yarn.lock | 86 +++- 34 files changed, 226 insertions(+), 1460 deletions(-) delete mode 100644 playwright/@types/playwright-core.d.ts delete mode 100644 playwright/Dockerfile delete mode 100644 playwright/docker-entrypoint.sh delete mode 100644 playwright/logger.ts delete mode 100644 playwright/plugins/utils/api.ts delete mode 100644 playwright/plugins/utils/object.ts delete mode 100644 playwright/plugins/utils/port.ts delete mode 100644 playwright/plugins/utils/rand.ts delete mode 100644 playwright/testcontainers/HomeserverContainer.ts delete mode 100644 playwright/testcontainers/mailpit.ts delete mode 100644 playwright/testcontainers/mas.ts diff --git a/package.json b/package.json index 6581f0c2e0..7843a43c27 100644 --- a/package.json +++ b/package.json @@ -62,19 +62,19 @@ "test": "jest", "test:playwright": "playwright test", "test:playwright:open": "yarn test:playwright --ui", - "test:playwright:screenshots": "yarn test:playwright:screenshots:build && yarn test:playwright:screenshots:run", - "test:playwright:screenshots:build": "docker build playwright -t element-web-playwright", - "test:playwright:screenshots:run": "docker run --rm --network host -e BASE_URL -e CI -v $(pwd):/work/ -v $(node -e 'console.log(require(`path`).dirname(require.resolve(`matrix-js-sdk/package.json`)))'):/work/node_modules/matrix-js-sdk -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/:/tmp/ -it element-web-playwright --grep @screenshot --project=Chrome", + "test:playwright:screenshots": "playwright-screenshots --project=Chrome", "coverage": "yarn test --coverage", "analyse:webpack-bundles": "webpack-bundle-analyzer webpack-stats.json webapp", "update:jitsi": "curl -s https://meet.element.io/libs/external_api.min.js > ./res/jitsi_external_api.min.js" }, "resolutions": { + "@playwright/test": "1.50.1", "@types/react": "18.3.18", "@types/react-dom": "18.3.5", "oidc-client-ts": "3.1.0", "jwt-decode": "4.0.0", "caniuse-lite": "1.0.30001701", + "testcontainers": "10.20.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0", "wrap-ansi": "npm:wrap-ansi@^7.0.0" }, @@ -158,7 +158,6 @@ "devDependencies": { "@action-validator/cli": "^0.6.0", "@action-validator/core": "^0.6.0", - "@axe-core/playwright": "^4.8.1", "@babel/core": "^7.12.10", "@babel/eslint-parser": "^7.12.10", "@babel/eslint-plugin": "^7.12.10", @@ -178,13 +177,13 @@ "@babel/preset-typescript": "^7.12.7", "@babel/runtime": "^7.12.5", "@casualbot/jest-sonar-reporter": "2.2.7", + "@element-hq/element-web-playwright-common": "^1.1.5", "@peculiar/webcrypto": "^1.4.3", - "@playwright/test": "^1.40.1", + "@playwright/test": "^1.50.1", "@principalstudio/html-webpack-inject-preload": "^1.2.7", "@sentry/webpack-plugin": "^3.0.0", "@stylistic/eslint-plugin": "^3.0.0", "@svgr/webpack": "^8.0.0", - "@testcontainers/postgresql": "^10.16.0", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.4.8", "@testing-library/react": "^16.0.0", @@ -259,13 +258,12 @@ "jsqr": "^1.4.0", "knip": "^5.36.2", "lint-staged": "^15.0.2", - "mailpit-api": "^1.0.5", "matrix-web-i18n": "^3.2.1", "mini-css-extract-plugin": "2.9.2", "minimist": "^1.2.6", "modernizr": "^3.12.0", "node-fetch": "^2.6.7", - "playwright-core": "^1.45.1", + "playwright-core": "^1.51.0", "postcss": "8.4.46", "postcss-easings": "^4.0.0", "postcss-hexrgba": "2.1.0", @@ -282,13 +280,12 @@ "rimraf": "^6.0.0", "semver": "^7.5.2", "source-map-loader": "^5.0.0", - "strip-ansi": "^7.1.0", "stylelint": "^16.13.0", "stylelint-config-standard": "^37.0.0", "stylelint-scss": "^6.0.0", "stylelint-value-no-unknown-custom-properties": "^6.0.1", "terser-webpack-plugin": "^5.3.9", - "testcontainers": "^10.16.0", + "testcontainers": "^10.20.0", "ts-node": "^10.9.1", "typescript": "5.8.2", "util": "^0.12.5", diff --git a/playwright.config.ts b/playwright.config.ts index 09bd07bb3b..519e2d9c3b 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details. import { defineConfig, devices } from "@playwright/test"; -import { Options } from "./playwright/services"; +import { type WorkerOptions } from "./playwright/services"; const baseURL = process.env["BASE_URL"] ?? "http://localhost:8080"; @@ -21,7 +21,7 @@ const chromeProject = { }, }; -export default defineConfig({ +export default defineConfig({ projects: [ { name: "Chrome", @@ -83,6 +83,7 @@ export default defineConfig({ url: `${baseURL}/config.json`, reuseExistingServer: true, timeout: (process.env.CI ? 30 : 120) * 1000, + stdout: "pipe", }, testDir: "playwright/e2e", outputDir: "playwright/test-results", diff --git a/playwright/@types/playwright-core.d.ts b/playwright/@types/playwright-core.d.ts deleted file mode 100644 index 244f3c91d4..0000000000 --- a/playwright/@types/playwright-core.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* -Copyright 2024 New Vector Ltd. -Copyright 2024 The Matrix.org Foundation C.I.C. - -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. -*/ - -declare module "playwright-core/lib/utils" { - // This type is not public in playwright-core utils - export function sanitizeForFilePath(filePath: string): string; -} diff --git a/playwright/Dockerfile b/playwright/Dockerfile deleted file mode 100644 index 6d812037de..0000000000 --- a/playwright/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM mcr.microsoft.com/playwright:v1.51.0-noble - -WORKDIR /work - -# fonts-dejavu is needed for the same RTL rendering as on CI -RUN apt-get update && apt-get -y install docker.io fonts-dejavu - -COPY docker-entrypoint.sh /opt/docker-entrypoint.sh -ENTRYPOINT ["bash", "/opt/docker-entrypoint.sh"] diff --git a/playwright/docker-entrypoint.sh b/playwright/docker-entrypoint.sh deleted file mode 100644 index 241528a29a..0000000000 --- a/playwright/docker-entrypoint.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -set -e - -npx playwright test --update-snapshots --reporter line $@ diff --git a/playwright/e2e/csAPI.ts b/playwright/e2e/csAPI.ts index 4f12076139..c622ac99ce 100644 --- a/playwright/e2e/csAPI.ts +++ b/playwright/e2e/csAPI.ts @@ -5,11 +5,11 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import { type APIRequestContext } from "playwright-core"; +import { type APIRequestContext } from "@playwright/test"; import { type KeyBackupInfo } from "matrix-js-sdk/src/crypto-api"; +import { ClientServerApi } from "@element-hq/element-web-playwright-common/lib/utils/api.js"; import { type HomeserverInstance } from "../plugins/homeserver"; -import { ClientServerApi } from "../plugins/utils/api.ts"; /** * A small subset of the Client-Server API used to manipulate the state of the diff --git a/playwright/e2e/editing/editing.spec.ts b/playwright/e2e/editing/editing.spec.ts index 528bcc5962..6f8e68bbc3 100644 --- a/playwright/e2e/editing/editing.spec.ts +++ b/playwright/e2e/editing/editing.spec.ts @@ -267,7 +267,6 @@ test.describe("Editing", () => { app, room, axe, - checkA11y, }) => { axe.disableRules("color-contrast"); // XXX: We have some known contrast issues here @@ -282,7 +281,7 @@ test.describe("Editing", () => { const line = tile.locator(".mx_EventTile_line"); await line.hover(); await line.getByRole("button", { name: "Edit" }).click(); - await checkA11y(); + await expect(axe).toHaveNoViolations(); const editComposer = page.getByRole("textbox", { name: "Edit message" }); await editComposer.pressSequentially("Foo"); await editComposer.press("Backspace"); @@ -290,7 +289,7 @@ test.describe("Editing", () => { await editComposer.press("Backspace"); await editComposer.press("Enter"); await app.getComposerField().hover(); // XXX: move the hover to get rid of the "Edit" tooltip - await checkA11y(); + await expect(axe).toHaveNoViolations(); } await expect( page.locator(".mx_RoomView_body .mx_EventTile[data-scroll-tokens]", { hasText: "Message" }), @@ -305,7 +304,6 @@ test.describe("Editing", () => { user, app, axe, - checkA11y, bot: bob, }) => { // This tests the behaviour when a message has been edited some time after it has been sent, and we diff --git a/playwright/e2e/login/login-consent.spec.ts b/playwright/e2e/login/login-consent.spec.ts index ec6dfbf7c2..28948dc3b9 100644 --- a/playwright/e2e/login/login-consent.spec.ts +++ b/playwright/e2e/login/login-consent.spec.ts @@ -6,7 +6,7 @@ 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 { type Page } from "playwright-core"; +import { type Page } from "@playwright/test"; import { expect, test } from "../../element-web-test"; import { selectHomeserver } from "../utils"; @@ -120,7 +120,7 @@ test.describe("Login", () => { credentials, page, homeserver, - checkA11y, + axe, }) => { await page.goto("/"); @@ -149,7 +149,7 @@ test.describe("Login", () => { await expect(page.getByRole("textbox", { name: "Username" })).toBeVisible(); // Disabled because flaky - see https://github.com/vector-im/element-web/issues/24688 // cy.percySnapshot("Login"); - await checkA11y(); + await expect(axe).toHaveNoViolations(); await page.getByRole("textbox", { name: "Username" }).fill(credentials.username); await page.getByPlaceholder("Password").fill(credentials.password); diff --git a/playwright/e2e/messages/messages.spec.ts b/playwright/e2e/messages/messages.spec.ts index e5d65caff5..f430d6b18b 100644 --- a/playwright/e2e/messages/messages.spec.ts +++ b/playwright/e2e/messages/messages.spec.ts @@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details. /* See readme.md for tips on writing these tests. */ -import { type Locator, type Page } from "playwright-core"; +import { type Locator, type Page } from "@playwright/test"; import { test, expect } from "../../element-web-test"; diff --git a/playwright/e2e/oidc/index.ts b/playwright/e2e/oidc/index.ts index b1635fbd78..1989e8764f 100644 --- a/playwright/e2e/oidc/index.ts +++ b/playwright/e2e/oidc/index.ts @@ -6,7 +6,7 @@ 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 { type MailpitClient } from "mailpit-api"; +import { type MailpitClient } from "@element-hq/element-web-playwright-common/lib/testcontainers"; import { type Page } from "@playwright/test"; import { expect } from "../../element-web-test"; diff --git a/playwright/e2e/register/email.spec.ts b/playwright/e2e/register/email.spec.ts index d351893f8b..bf8a2157f5 100644 --- a/playwright/e2e/register/email.spec.ts +++ b/playwright/e2e/register/email.spec.ts @@ -34,7 +34,7 @@ test.describe("Email Registration", async () => { test( "registers an account and lands on the home page", { tag: "@screenshot" }, - async ({ page, mailpitClient, request, checkA11y }) => { + async ({ page, mailpitClient, request, axe }) => { await expect(page.getByRole("textbox", { name: "Username" })).toBeVisible(); // Hide the server text as it contains the randomly allocated Homeserver port const screenshotOptions = { mask: [page.locator(".mx_ServerPicker_server")] }; @@ -47,7 +47,7 @@ test.describe("Email Registration", async () => { await expect(page.getByText("Check your email to continue")).toBeVisible(); await expect(page).toMatchScreenshot("registration_check_your_email.png", screenshotOptions); - await checkA11y(); + await expect(axe).toHaveNoViolations(); await expect(page.getByText("An error was encountered when sending the email")).not.toBeVisible(); diff --git a/playwright/e2e/register/register.spec.ts b/playwright/e2e/register/register.spec.ts index 3df1d01678..c481b6ac43 100644 --- a/playwright/e2e/register/register.spec.ts +++ b/playwright/e2e/register/register.spec.ts @@ -33,12 +33,12 @@ test.describe("Registration", () => { test( "registers an account and lands on the home screen", { tag: "@screenshot" }, - async ({ homeserver, page, checkA11y, crypto }) => { + async ({ homeserver, page, axe, crypto }) => { await page.getByRole("button", { name: "Edit", exact: true }).click(); await expect(page.getByRole("button", { name: "Continue", exact: true })).toBeVisible(); await expect(page.locator(".mx_Dialog")).toMatchScreenshot("server-picker.png"); - await checkA11y(); + await expect(axe).toHaveNoViolations(); await page.getByRole("textbox", { name: "Other homeserver" }).fill(homeserver.baseUrl); await page.getByRole("button", { name: "Continue", exact: true }).click(); @@ -52,7 +52,7 @@ test.describe("Registration", () => { includeDialogBackground: true, }; await expect(page).toMatchScreenshot("registration.png", screenshotOptions); - await checkA11y(); + await expect(axe).toHaveNoViolations(); await page.getByRole("textbox", { name: "Username", exact: true }).fill("alice"); await page.getByPlaceholder("Password", { exact: true }).fill("totally a great password"); @@ -62,12 +62,12 @@ test.describe("Registration", () => { const dialog = page.getByRole("dialog"); await expect(dialog).toBeVisible(); await expect(page).toMatchScreenshot("email-prompt.png", screenshotOptions); - await checkA11y(); + await expect(axe).toHaveNoViolations(); await dialog.getByRole("button", { name: "Continue", exact: true }).click(); await expect(page.locator(".mx_InteractiveAuthEntryComponents_termsPolicy")).toBeVisible(); await expect(page).toMatchScreenshot("terms-prompt.png", screenshotOptions); - await checkA11y(); + await expect(axe).toHaveNoViolations(); const termsPolicy = page.locator(".mx_InteractiveAuthEntryComponents_termsPolicy"); await termsPolicy.getByRole("checkbox").click(); // Click the checkbox before terms of service anchor link diff --git a/playwright/e2e/spaces/spaces.spec.ts b/playwright/e2e/spaces/spaces.spec.ts index 01a385c9df..dce7515ef0 100644 --- a/playwright/e2e/spaces/spaces.spec.ts +++ b/playwright/e2e/spaces/spaces.spec.ts @@ -227,7 +227,7 @@ test.describe("Spaces", () => { test( "should render subspaces in the space panel only when expanded", { tag: "@screenshot" }, - async ({ page, app, user, axe, checkA11y }) => { + async ({ page, app, user, axe }) => { axe.disableRules([ // Disable this check as it triggers on nested roving tab index elements which are in practice fine "nested-interactive", @@ -249,7 +249,7 @@ test.describe("Spaces", () => { await expect(spaceTree.getByRole("button", { name: "Root Space" })).toBeVisible(); await expect(spaceTree.getByRole("button", { name: "Child Space" })).not.toBeVisible(); - await checkA11y(); + await expect(axe).toHaveNoViolations(); await expect(page.locator(".mx_SpacePanel")).toMatchScreenshot("space-panel-collapsed.png"); // This finds the expand button with the class name "mx_SpaceButton_toggleCollapse". Note there is another @@ -261,7 +261,7 @@ test.describe("Spaces", () => { await expect(item).toBeVisible(); await expect(item.locator(".mx_SpaceItem", { hasText: "Child Space" })).toBeVisible(); - await checkA11y(); + await expect(axe).toHaveNoViolations(); await expect(page.locator(".mx_SpacePanel")).toMatchScreenshot("space-panel-expanded.png"); }, ); diff --git a/playwright/e2e/timeline/timeline.spec.ts b/playwright/e2e/timeline/timeline.spec.ts index 5c1f99511e..7b13d1ccb1 100644 --- a/playwright/e2e/timeline/timeline.spec.ts +++ b/playwright/e2e/timeline/timeline.spec.ts @@ -277,7 +277,7 @@ test.describe("Timeline", () => { test( "should add inline start margin to an event line on IRC layout", { tag: "@screenshot" }, - async ({ page, app, room, axe, checkA11y }) => { + async ({ page, app, room, axe }) => { axe.disableRules("color-contrast"); await page.goto(`/#/room/${room.roomId}`); @@ -318,7 +318,7 @@ test.describe("Timeline", () => { `, }, ); - await checkA11y(); + await expect(axe).toHaveNoViolations(); }, ); }); @@ -743,68 +743,64 @@ test.describe("Timeline", () => { ).toBeVisible(); }); - test( - "should render url previews", - { tag: "@screenshot" }, - async ({ page, app, room, axe, checkA11y, context }) => { - axe.disableRules("color-contrast"); + test("should render url previews", { tag: "@screenshot" }, async ({ page, app, room, axe, context }) => { + axe.disableRules("color-contrast"); - // Element Web uses a Service Worker to rewrite unauthenticated media requests to authenticated ones, but - // the page can't see this happening. We intercept the route at the BrowserContext to ensure we get it - // post-worker, but we can't waitForResponse on that, so the page context is still used there. Because - // the page doesn't see the rewrite, it waits for the unauthenticated route. This is only confusing until - // the js-sdk (and thus the app as a whole) switches to using authenticated endpoints by default, hopefully. - await context.route( - "**/_matrix/client/v1/media/thumbnail/matrix.org/2022-08-16_yaiSVSRIsNFfxDnV?*", - async (route) => { - await route.fulfill({ - path: "playwright/sample-files/riot.png", - }); - }, - ); - await page.route( - "**/_matrix/media/v3/preview_url?url=https%3A%2F%2Fcall.element.io%2F&ts=*", - async (route) => { - await route.fulfill({ - json: { - "og:title": "Element Call", - "og:description": null, - "og:image:width": 48, - "og:image:height": 48, - "og:image": "mxc://matrix.org/2022-08-16_yaiSVSRIsNFfxDnV", - "og:image:type": "image/png", - "matrix:image:size": 2121, - }, - }); - }, - ); + // Element Web uses a Service Worker to rewrite unauthenticated media requests to authenticated ones, but + // the page can't see this happening. We intercept the route at the BrowserContext to ensure we get it + // post-worker, but we can't waitForResponse on that, so the page context is still used there. Because + // the page doesn't see the rewrite, it waits for the unauthenticated route. This is only confusing until + // the js-sdk (and thus the app as a whole) switches to using authenticated endpoints by default, hopefully. + await context.route( + "**/_matrix/client/v1/media/thumbnail/matrix.org/2022-08-16_yaiSVSRIsNFfxDnV?*", + async (route) => { + await route.fulfill({ + path: "playwright/sample-files/riot.png", + }); + }, + ); + await page.route( + "**/_matrix/media/v3/preview_url?url=https%3A%2F%2Fcall.element.io%2F&ts=*", + async (route) => { + await route.fulfill({ + json: { + "og:title": "Element Call", + "og:description": null, + "og:image:width": 48, + "og:image:height": 48, + "og:image": "mxc://matrix.org/2022-08-16_yaiSVSRIsNFfxDnV", + "og:image:type": "image/png", + "matrix:image:size": 2121, + }, + }); + }, + ); - const requestPromises: Promise[] = [ - page.waitForResponse("**/_matrix/media/v3/preview_url?url=https%3A%2F%2Fcall.element.io%2F&ts=*"), - // see context.route above for why we listen for the unauthenticated endpoint - page.waitForResponse("**/_matrix/media/v3/thumbnail/matrix.org/2022-08-16_yaiSVSRIsNFfxDnV?*"), - ]; + const requestPromises: Promise[] = [ + page.waitForResponse("**/_matrix/media/v3/preview_url?url=https%3A%2F%2Fcall.element.io%2F&ts=*"), + // see context.route above for why we listen for the unauthenticated endpoint + page.waitForResponse("**/_matrix/media/v3/thumbnail/matrix.org/2022-08-16_yaiSVSRIsNFfxDnV?*"), + ]; - await app.client.sendMessage(room.roomId, "https://call.element.io/"); - await page.goto(`/#/room/${room.roomId}`); + await app.client.sendMessage(room.roomId, "https://call.element.io/"); + await page.goto(`/#/room/${room.roomId}`); - await expect(page.locator(".mx_LinkPreviewWidget").getByText("Element Call")).toBeVisible(); - await Promise.all(requestPromises); + await expect(page.locator(".mx_LinkPreviewWidget").getByText("Element Call")).toBeVisible(); + await Promise.all(requestPromises); - await checkA11y(); + await expect(axe).toHaveNoViolations(); - await app.timeline.scrollToBottom(); - await expect(page.locator(".mx_EventTile_last")).toMatchScreenshot("url-preview.png", { - // Exclude timestamp and read marker from snapshot - mask: [page.locator(".mx_MessageTimestamp")], - css: ` + await app.timeline.scrollToBottom(); + await expect(page.locator(".mx_EventTile_last")).toMatchScreenshot("url-preview.png", { + // Exclude timestamp and read marker from snapshot + mask: [page.locator(".mx_MessageTimestamp")], + css: ` .mx_TopUnreadMessagesBar, .mx_MessagePanel_myReadMarker { display: none !important; } `, - }); - }, - ); + }); + }); test.describe("on search results panel", () => { test( diff --git a/playwright/element-web-test.ts b/playwright/element-web-test.ts index 24124d5474..8520533461 100644 --- a/playwright/element-web-test.ts +++ b/playwright/element-web-test.ts @@ -7,18 +7,18 @@ Please see LICENSE files in the repository root for full details. */ import { - expect as baseExpect, - type Locator, - type Page, type ExpectMatcherState, - type ElementHandle, + type MatcherReturnType, + type Page, + type Locator, type PlaywrightTestArgs, type Fixtures as _Fixtures, } from "@playwright/test"; -import { sanitizeForFilePath } from "playwright-core/lib/utils"; -import AxeBuilder from "@axe-core/playwright"; -import _ from "lodash"; -import { extname } from "node:path"; +import { + type TestFixtures as BaseTestFixtures, + expect as baseExpect, + type ToMatchScreenshotOptions, +} from "@element-hq/element-web-playwright-common"; import type { IConfigOptions } from "../src/IConfigOptions"; import { type Credentials } from "./plugins/homeserver"; @@ -27,71 +27,22 @@ import { Crypto } from "./pages/crypto"; import { Toasts } from "./pages/toasts"; import { Bot, type CreateBotOpts } from "./pages/bot"; import { Webserver } from "./plugins/webserver"; -import { type Options, type Services, test as base } from "./services.ts"; +import { type WorkerOptions, type Services, test as base } from "./services"; // Enable experimental service worker support // See https://playwright.dev/docs/service-workers-experimental#how-to-enable process.env["PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS"] = "1"; -// This is deliberately quite a minimal config.json, so that we can test that the default settings actually work. -const CONFIG_JSON: Partial = { - // The default language is set here for test consistency - setting_defaults: { - language: "en-GB", - }, - - // the location tests want a map style url. - map_style_url: "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx", - - features: { - // We don't want to go through the feature announcement during the e2e test - feature_release_announcement: false, - }, -}; +declare module "@element-hq/element-web-playwright-common" { + // Improve the type for the config fixture based on the real type + export interface Config extends Omit {} +} export interface CredentialsWithDisplayName extends Credentials { displayName: string; } -export interface TestFixtures { - axe: AxeBuilder; - checkA11y: () => Promise; - - /** - * The contents of the config.json to send when the client requests it. - */ - config: typeof CONFIG_JSON; - - /** - * The displayname to use for the user registered in {@link #credentials}. - * - * To set it, call `test.use({ displayName: "myDisplayName" })` in the test file or `describe` block. - * See {@link https://playwright.dev/docs/api/class-test#test-use}. - */ - displayName?: string; - - /** - * A test fixture which registers a test user on the {@link #homeserver} and supplies the details - * of the registered user. - */ - credentials: CredentialsWithDisplayName; - - /** - * The same as {@link https://playwright.dev/docs/api/class-fixtures#fixtures-page|`page`}, - * but adds an initScript which will populate localStorage with the user's details from - * {@link #credentials} and {@link #homeserver}. - * - * Similar to {@link #user}, but doesn't load the app. - */ - pageWithCredentials: Page; - - /** - * A (rather poorly-named) test fixture which registers a user per {@link #credentials}, stores - * the credentials into localStorage per {@link #homeserver}, and then loads the front page of the - * app. - */ - user: CredentialsWithDisplayName; - +export interface TestFixtures extends BaseTestFixtures { /** * The same as {@link https://playwright.dev/docs/api/class-fixtures#fixtures-page|`page`}, * but wraps the returned `Page` in a class of utilities for interacting with the Element-Web UI, @@ -105,13 +56,11 @@ export interface TestFixtures { uut?: Locator; // Unit Under Test, useful place to refer a prepared locator botCreateOpts: CreateBotOpts; bot: Bot; - labsFlags: string[]; webserver: Webserver; - disablePresence: boolean; } type CombinedTestFixtures = PlaywrightTestArgs & TestFixtures; -export type Fixtures = _Fixtures; +export type Fixtures = _Fixtures; export const test = base.extend({ context: async ({ context }, use, testInfo) => { // We skip tests instead of using grep-invert to still surface the counts in the html report @@ -121,102 +70,12 @@ export const test = base.extend({ ); await use(context); }, - disablePresence: false, - config: {}, // We merge this atop the default CONFIG_JSON in the page fixture to make extending it easier - page: async ({ homeserver, context, page, config, labsFlags, disablePresence }, use) => { - await context.route(`http://localhost:8080/config.json*`, async (route) => { - const json = { - ...CONFIG_JSON, - ...config, - default_server_config: { - "m.homeserver": { - base_url: homeserver.baseUrl, - }, - ...config.default_server_config, - }, - }; - json["features"] = { - ...json["features"], - // Enable the lab features - ...labsFlags.reduce((obj, flag) => { - obj[flag] = true; - return obj; - }, {}), - }; - if (disablePresence) { - json["enable_presence_by_hs_url"] = { - [homeserver.baseUrl]: false, - }; - } - await route.fulfill({ json }); - }); - await use(page); + + axe: async ({ axe }, use) => { + // Exclude floating UI for now + await use(axe.exclude("[data-floating-ui-portal]")); }, - displayName: undefined, - credentials: async ({ context, homeserver, displayName: testDisplayName }, use, testInfo) => { - const names = ["Alice", "Bob", "Charlie", "Daniel", "Eve", "Frank", "Grace", "Hannah", "Isaac", "Judy"]; - const password = _.uniqueId("password_"); - const displayName = testDisplayName ?? _.sample(names)!; - - const credentials = await homeserver.registerUser(`user_${testInfo.testId}`, password, displayName); - console.log(`Registered test user ${credentials.userId} with displayname ${displayName}`); - - await use({ - ...credentials, - displayName, - }); - }, - labsFlags: [], - - pageWithCredentials: async ({ page, homeserver, credentials }, use) => { - await page.addInitScript( - ({ baseUrl, credentials }) => { - // Seed the localStorage with the required credentials - window.localStorage.setItem("mx_hs_url", baseUrl); - window.localStorage.setItem("mx_user_id", credentials.userId); - window.localStorage.setItem("mx_access_token", credentials.accessToken); - window.localStorage.setItem("mx_device_id", credentials.deviceId); - window.localStorage.setItem("mx_is_guest", "false"); - window.localStorage.setItem("mx_has_pickle_key", "false"); - window.localStorage.setItem("mx_has_access_token", "true"); - - window.localStorage.setItem( - "mx_local_settings", - JSON.stringify({ - // Retain any other settings which may have already been set - ...JSON.parse(window.localStorage.getItem("mx_local_settings") || "{}"), - // Ensure the language is set to a consistent value - language: "en", - }), - ); - }, - { baseUrl: homeserver.baseUrl, credentials }, - ); - await use(page); - }, - - user: async ({ pageWithCredentials: page, credentials }, use) => { - await page.goto("/"); - await page.waitForSelector(".mx_MatrixChat", { timeout: 30000 }); - await use(credentials); - }, - - axe: async ({ page }, use) => { - await use(new AxeBuilder({ page }).exclude("[data-floating-ui-portal]")); - }, - checkA11y: async ({ axe }, use, testInfo) => - use(async () => { - const results = await axe.analyze(); - - await testInfo.attach("accessibility-scan-results", { - body: JSON.stringify(results, null, 2), - contentType: "application/json", - }); - - expect(results.violations).toEqual([]); - }), - app: async ({ page }, use) => { const app = new ElementAppPage(page); await use(app); @@ -244,35 +103,23 @@ export const test = base.extend({ }, }); -// Based on https://github.com/microsoft/playwright/blob/2b77ed4d7aafa85a600caa0b0d101b72c8437eeb/packages/playwright/src/util.ts#L206C8-L210C2 -function sanitizeFilePathBeforeExtension(filePath: string): string { - const ext = extname(filePath); - const base = filePath.substring(0, filePath.length - ext.length); - return sanitizeForFilePath(base) + ext; +interface ExtendedToMatchScreenshotOptions extends ToMatchScreenshotOptions { + includeDialogBackground?: boolean; + showTooltips?: boolean; + timeout?: number; } -export const expect = baseExpect.extend({ - async toMatchScreenshot( +type Expectations = { + toMatchScreenshot: ( this: ExpectMatcherState, receiver: Page | Locator, name: `${string}.png`, - options?: { - mask?: Array; - includeDialogBackground?: boolean; - showTooltips?: boolean; - timeout?: number; - css?: string; - }, - ) { - const testInfo = test.info(); - if (!testInfo) throw new Error(`toMatchScreenshot() must be called during the test`); - - if (!testInfo.tags.includes("@screenshot")) { - throw new Error("toMatchScreenshot() must be used in a test tagged with @screenshot"); - } - - const page = "page" in receiver ? receiver.page() : receiver; + options?: ExtendedToMatchScreenshotOptions, + ) => Promise; +}; +export const expect = baseExpect.extend({ + async toMatchScreenshot(receiver, name, options) { let css = ` .mx_MessagePanel_myReadMarker { display: none !important; @@ -322,21 +169,9 @@ export const expect = baseExpect.extend({ css += options.css; } - // We add a custom style tag before taking screenshots - const style = (await page.addStyleTag({ - content: css, - })) as ElementHandle; - - const screenshotName = sanitizeFilePathBeforeExtension(name); - await baseExpect(receiver).toHaveScreenshot(screenshotName, options); - - await style.evaluate((tag) => tag.remove()); - - testInfo.annotations.push({ - // `_` prefix hides it from the HTML reporter - type: "_screenshot", - // include a path relative to `playwright/snapshots/` - description: testInfo.snapshotPath(screenshotName).split("/playwright/snapshots/", 2)[1], + await baseExpect(receiver).toMatchScreenshot(name, { + ...options, + css, }); return { pass: true, message: () => "", name: "toMatchScreenshot" }; diff --git a/playwright/logger.ts b/playwright/logger.ts deleted file mode 100644 index da70582c38..0000000000 --- a/playwright/logger.ts +++ /dev/null @@ -1,63 +0,0 @@ -/* -Copyright 2024 New Vector 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 { type BrowserContext, type Page, type TestInfo } from "@playwright/test"; -import { type Readable } from "stream"; -import stripAnsi from "strip-ansi"; - -export class Logger { - private pages: Page[] = []; - private logs: Record = {}; - - public getConsumer(container: string) { - this.logs[container] = ""; - return (stream: Readable) => { - stream.on("data", (chunk) => { - this.logs[container] += chunk.toString(); - }); - stream.on("err", (chunk) => { - this.logs[container] += "ERR " + chunk.toString(); - }); - }; - } - - public async onTestStarted(context: BrowserContext) { - this.pages = []; - for (const id in this.logs) { - if (id.startsWith("page-")) { - delete this.logs[id]; - } else { - this.logs[id] = ""; - } - } - - context.on("console", (msg) => { - const page = msg.page(); - let pageIdx = this.pages.indexOf(page); - if (pageIdx === -1) { - this.pages.push(page); - pageIdx = this.pages.length - 1; - this.logs[`page-${pageIdx}`] = `Console logs for page with URL: ${page.url()}\n\n`; - } - const type = msg.type(); - const text = msg.text(); - this.logs[`page-${pageIdx}`] += `${type}: ${text}\n`; - }); - } - - public async onTestFinished(testInfo: TestInfo) { - if (testInfo.status !== "passed") { - for (const id in this.logs) { - if (!this.logs[id]) continue; - await testInfo.attach(id, { - body: stripAnsi(this.logs[id]), - contentType: "text/plain", - }); - } - } - } -} diff --git a/playwright/plugins/homeserver/dendrite/index.ts b/playwright/plugins/homeserver/dendrite/index.ts index bad52a869d..c139650405 100644 --- a/playwright/plugins/homeserver/dendrite/index.ts +++ b/playwright/plugins/homeserver/dendrite/index.ts @@ -6,8 +6,8 @@ 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 { type Options } from "../../../services.ts"; +import { type WorkerOptions } from "../../../services.ts"; -export const isDendrite = ({ homeserverType }: Options): boolean => { +export const isDendrite = ({ homeserverType }: WorkerOptions): boolean => { return homeserverType === "dendrite" || homeserverType === "pinecone"; }; diff --git a/playwright/plugins/homeserver/index.ts b/playwright/plugins/homeserver/index.ts index 04b1ad77f3..0571cd9615 100644 --- a/playwright/plugins/homeserver/index.ts +++ b/playwright/plugins/homeserver/index.ts @@ -6,7 +6,7 @@ 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 { type ClientServerApi } from "../utils/api.ts"; +import { type ClientServerApi } from "@element-hq/element-web-playwright-common/lib/utils/api.js"; export interface HomeserverInstance { readonly baseUrl: string; diff --git a/playwright/plugins/homeserver/synapse/consentHomeserver.ts b/playwright/plugins/homeserver/synapse/consentHomeserver.ts index 83d47512cf..9b3316bf57 100644 --- a/playwright/plugins/homeserver/synapse/consentHomeserver.ts +++ b/playwright/plugins/homeserver/synapse/consentHomeserver.ts @@ -6,30 +6,19 @@ 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 { type SynapseContainer } from "@element-hq/element-web-playwright-common/lib/testcontainers"; + import { type Fixtures } from "../../../element-web-test.ts"; export const consentHomeserver: Fixtures = { _homeserver: [ async ({ _homeserver: container, mailpit }, use) => { - container + (container as SynapseContainer) .withCopyDirectoriesToContainer([ { source: "playwright/plugins/homeserver/synapse/res", target: "/data/res" }, ]) + .withSmtpServer(mailpit) .withConfig({ - email: { - enable_notifs: false, - smtp_host: "mailpit", - smtp_port: 1025, - smtp_user: "username", - smtp_pass: "password", - require_transport_security: false, - notif_from: "Your Friendly %(app)s homeserver ", - app_name: "Matrix", - notif_template_html: "notif_mail.html", - notif_template_text: "notif_mail.txt", - notif_for_new_users: true, - client_base_url: "http://localhost/element", - }, user_consent: { template_dir: "/data/res/templates/privacy", version: "1.0", diff --git a/playwright/plugins/homeserver/synapse/masHomeserver.ts b/playwright/plugins/homeserver/synapse/masHomeserver.ts index 96fcc80bdd..342737d80d 100644 --- a/playwright/plugins/homeserver/synapse/masHomeserver.ts +++ b/playwright/plugins/homeserver/synapse/masHomeserver.ts @@ -6,7 +6,8 @@ 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 { MatrixAuthenticationServiceContainer } from "../../../testcontainers/mas.ts"; +import { MatrixAuthenticationServiceContainer } from "@element-hq/element-web-playwright-common/lib/testcontainers"; + import { type Fixtures } from "../../../element-web-test.ts"; export const masHomeserver: Fixtures = { diff --git a/playwright/plugins/oauth_server/index.ts b/playwright/plugins/oauth_server/index.ts index 8a7e9cd8ba..446426a9c1 100644 --- a/playwright/plugins/oauth_server/index.ts +++ b/playwright/plugins/oauth_server/index.ts @@ -10,8 +10,7 @@ import http from "http"; import express from "express"; import { type AddressInfo } from "net"; import { type TestInfo } from "@playwright/test"; - -import { randB64Bytes } from "../utils/rand.ts"; +import { randB64Bytes } from "@element-hq/element-web-playwright-common/lib/utils/rand.js"; export class OAuthServer { private server?: http.Server; diff --git a/playwright/plugins/utils/api.ts b/playwright/plugins/utils/api.ts deleted file mode 100644 index 90c0e2739f..0000000000 --- a/playwright/plugins/utils/api.ts +++ /dev/null @@ -1,76 +0,0 @@ -/* -Copyright 2025 New Vector 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 { type APIRequestContext } from "@playwright/test"; - -import { type Credentials } from "../homeserver"; - -export type Verb = "GET" | "POST" | "PUT" | "DELETE"; - -export class Api { - private _request?: APIRequestContext; - - constructor(private readonly baseUrl: string) {} - - public setRequest(request: APIRequestContext): void { - this._request = request; - } - - public async request(verb: "GET", path: string, token?: string, data?: never): Promise; - public async request(verb: Verb, path: string, token?: string, data?: object): Promise; - public async request(verb: Verb, path: string, token?: string, data?: object): Promise { - const url = `${this.baseUrl}${path}`; - const res = await this._request.fetch(url, { - data, - method: verb, - headers: token - ? { - Authorization: `Bearer ${token}`, - } - : undefined, - }); - - if (!res.ok()) { - throw new Error( - `Request to ${url} failed with status ${res.status()}: ${JSON.stringify(await res.json())}`, - ); - } - - return res.json(); - } -} - -export class ClientServerApi extends Api { - constructor(baseUrl: string) { - super(`${baseUrl}/_matrix/client`); - } - - public async loginUser(userId: string, password: string): Promise { - const json = await this.request<{ - access_token: string; - user_id: string; - device_id: string; - home_server: string; - }>("POST", "/v3/login", undefined, { - type: "m.login.password", - identifier: { - type: "m.id.user", - user: userId, - }, - password: password, - }); - - return { - password, - accessToken: json.access_token, - userId: json.user_id, - deviceId: json.device_id, - homeServer: json.home_server || json.user_id.split(":").slice(1).join(":"), - username: userId.slice(1).split(":")[0], - }; - } -} diff --git a/playwright/plugins/utils/object.ts b/playwright/plugins/utils/object.ts deleted file mode 100644 index bfb92fecec..0000000000 --- a/playwright/plugins/utils/object.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* -Copyright 2024 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only -Please see LICENSE files in the repository root for full details. -*/ - -/** - * Deep copy the given object. The object MUST NOT have circular references and - * MUST NOT have functions. - * @param obj - The object to deep copy. - * @returns A copy of the object without any references to the original. - */ -export function deepCopy(obj: T): T { - return JSON.parse(JSON.stringify(obj)); -} diff --git a/playwright/plugins/utils/port.ts b/playwright/plugins/utils/port.ts deleted file mode 100644 index b54e251f2f..0000000000 --- a/playwright/plugins/utils/port.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2024 New Vector Ltd. -Copyright 2022 The Matrix.org Foundation C.I.C. - -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 * as net from "net"; - -export async function getFreePort(): Promise { - return new Promise((resolve) => { - const srv = net.createServer(); - srv.listen(0, () => { - const port = (srv.address()).port; - srv.close(() => resolve(port)); - }); - }); -} diff --git a/playwright/plugins/utils/rand.ts b/playwright/plugins/utils/rand.ts deleted file mode 100644 index 94f723f0a6..0000000000 --- a/playwright/plugins/utils/rand.ts +++ /dev/null @@ -1,13 +0,0 @@ -/* -Copyright 2024 New Vector Ltd. -Copyright 2023 The Matrix.org Foundation C.I.C. - -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 crypto from "node:crypto"; - -export function randB64Bytes(numBytes: number): string { - return crypto.randomBytes(numBytes).toString("base64").replace(/=*$/, ""); -} diff --git a/playwright/plugins/webserver/index.ts b/playwright/plugins/webserver/index.ts index ba9b9e9706..fe236116bc 100644 --- a/playwright/plugins/webserver/index.ts +++ b/playwright/plugins/webserver/index.ts @@ -6,8 +6,8 @@ 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 * as http from "http"; -import { type AddressInfo } from "net"; +import * as http from "node:http"; +import { type AddressInfo } from "node:net"; export class Webserver { private server?: http.Server; diff --git a/playwright/services.ts b/playwright/services.ts index 162f4e9fbb..8ecf10e20e 100644 --- a/playwright/services.ts +++ b/playwright/services.ts @@ -5,113 +5,32 @@ 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 { test as base } from "@playwright/test"; -import { type MailpitClient } from "mailpit-api"; -import { Network, type StartedNetwork } from "testcontainers"; -import { PostgreSqlContainer, type StartedPostgreSqlContainer } from "@testcontainers/postgresql"; +import { test as base } from "@element-hq/element-web-playwright-common"; +import { + type Services as BaseServices, + type WorkerOptions as BaseWorkerOptions, +} from "@element-hq/element-web-playwright-common/lib/fixtures"; +import { type HomeserverContainer } from "@element-hq/element-web-playwright-common/lib/testcontainers"; -import { type SynapseConfig, SynapseContainer } from "./testcontainers/synapse.ts"; -import { Logger } from "./logger.ts"; -import { type StartedMatrixAuthenticationServiceContainer } from "./testcontainers/mas.ts"; -import { type HomeserverContainer, type StartedHomeserverContainer } from "./testcontainers/HomeserverContainer.ts"; -import { MailhogContainer, type StartedMailhogContainer } from "./testcontainers/mailpit.ts"; import { type OAuthServer } from "./plugins/oauth_server"; -import { DendriteContainer, PineconeContainer } from "./testcontainers/dendrite.ts"; +import { DendriteContainer, PineconeContainer } from "./testcontainers/dendrite"; import { type HomeserverType } from "./plugins/homeserver"; +import { SynapseContainer } from "./testcontainers/synapse"; -export interface TestFixtures { - mailpitClient: MailpitClient; -} - -export interface Services { - logger: Logger; - - network: StartedNetwork; - postgres: StartedPostgreSqlContainer; - mailpit: StartedMailhogContainer; - - synapseConfig: SynapseConfig; - _homeserver: HomeserverContainer; - homeserver: StartedHomeserverContainer; - // Set in masHomeserver only - mas?: StartedMatrixAuthenticationServiceContainer; +export interface Services extends BaseServices { // Set in legacyOAuthHomeserver only oAuthServer?: OAuthServer; } -export interface Options { +export interface WorkerOptions extends BaseWorkerOptions { homeserverType: HomeserverType; } -export const test = base.extend({ - logger: [ - // eslint-disable-next-line no-empty-pattern - async ({}, use) => { - const logger = new Logger(); - await use(logger); - }, - { scope: "worker" }, - ], - network: [ - // eslint-disable-next-line no-empty-pattern - async ({}, use) => { - const network = await new Network().start(); - await use(network); - await network.stop(); - }, - { scope: "worker" }, - ], - postgres: [ - async ({ logger, network }, use) => { - const container = await new PostgreSqlContainer() - .withNetwork(network) - .withNetworkAliases("postgres") - .withLogConsumer(logger.getConsumer("postgres")) - .withTmpFs({ - "/dev/shm/pgdata/data": "", - }) - .withEnvironment({ - PG_DATA: "/dev/shm/pgdata/data", - }) - .withCommand([ - "-c", - "shared_buffers=128MB", - "-c", - `fsync=off`, - "-c", - `synchronous_commit=off`, - "-c", - "full_page_writes=off", - ]) - .start(); - await use(container); - await container.stop(); - }, - { scope: "worker" }, - ], - - mailpit: [ - async ({ logger, network }, use) => { - const container = await new MailhogContainer() - .withNetwork(network) - .withNetworkAliases("mailpit") - .withLogConsumer(logger.getConsumer("mailpit")) - .start(); - await use(container); - await container.stop(); - }, - { scope: "worker" }, - ], - mailpitClient: async ({ mailpit: container }, use) => { - await container.client.deleteMessages(); - await use(container.client); - }, - - synapseConfig: [{}, { scope: "worker" }], +export const test = base.extend<{}, Services & WorkerOptions>({ homeserverType: ["synapse", { option: true, scope: "worker" }], _homeserver: [ async ({ homeserverType }, use) => { - let container: HomeserverContainer; + let container: HomeserverContainer; switch (homeserverType) { case "synapse": container = new SynapseContainer(); @@ -128,46 +47,12 @@ export const test = base.extend({ }, { scope: "worker" }, ], - homeserver: [ - async ({ homeserverType, logger, network, _homeserver: homeserver, synapseConfig, mas }, use) => { - if (homeserver instanceof SynapseContainer) { - homeserver.withConfig(synapseConfig); - } - const container = await homeserver - .withNetwork(network) - .withNetworkAliases("homeserver") - .withLogConsumer(logger.getConsumer(homeserverType)) - .withMatrixAuthenticationService(mas) - .start(); - await use(container); - await container.stop(); - }, - { scope: "worker" }, - ], - mas: [ - // eslint-disable-next-line no-empty-pattern - async ({}, use) => { - // we stub the mas fixture to allow `homeserver` to depend on it to ensure - // when it is specified by `masHomeserver` it is started before the homeserver - await use(undefined); - }, - { scope: "worker" }, - ], - - context: async ( - { homeserverType, synapseConfig, logger, context, request, _homeserver, homeserver }, - use, - testInfo, - ) => { + context: async ({ homeserverType, synapseConfig, context, _homeserver }, use, testInfo) => { testInfo.skip( !(_homeserver instanceof SynapseContainer) && Object.keys(synapseConfig).length > 0, `Test specifies Synapse config options so is unsupported with ${homeserverType}`, ); - homeserver.setRequest(request); - await logger.onTestStarted(context); await use(context); - await logger.onTestFinished(testInfo); - await homeserver.onTestFinished(testInfo); }, }); diff --git a/playwright/snapshots/right-panel/memberlist.spec.ts/with-four-members-linux.png b/playwright/snapshots/right-panel/memberlist.spec.ts/with-four-members-linux.png index d8bab27faa947e5558dfcc85f4e24e382b87b1cf..a5db88aae638325eee39eefd8b087d0b27d1e5eb 100644 GIT binary patch literal 19391 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­i!|}kqqWPqqVzOs(Z{c#x?yu6>M_POi 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 diff --git a/playwright/testcontainers/HomeserverContainer.ts b/playwright/testcontainers/HomeserverContainer.ts deleted file mode 100644 index d5be8c5301..0000000000 --- a/playwright/testcontainers/HomeserverContainer.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* -Copyright 2024 New Vector 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 { type AbstractStartedContainer, type GenericContainer } from "testcontainers"; -import { type APIRequestContext, type TestInfo } from "@playwright/test"; - -import { type HomeserverInstance } from "../plugins/homeserver"; -import { type StartedMatrixAuthenticationServiceContainer } from "./mas.ts"; - -export interface HomeserverContainer extends GenericContainer { - withConfigField(key: string, value: any): this; - withConfig(config: Partial): this; - withMatrixAuthenticationService(mas?: StartedMatrixAuthenticationServiceContainer): this; - start(): Promise; -} - -export interface StartedHomeserverContainer extends AbstractStartedContainer, HomeserverInstance { - setRequest(request: APIRequestContext): void; - onTestFinished(testInfo: TestInfo): Promise; -} diff --git a/playwright/testcontainers/dendrite.ts b/playwright/testcontainers/dendrite.ts index edf9dba91d..55938778cd 100644 --- a/playwright/testcontainers/dendrite.ts +++ b/playwright/testcontainers/dendrite.ts @@ -8,12 +8,13 @@ Please see LICENSE files in the repository root for full details. import { GenericContainer, Wait } from "testcontainers"; import * as YAML from "yaml"; import { set } from "lodash"; - -import { randB64Bytes } from "../plugins/utils/rand.ts"; -import { StartedSynapseContainer } from "./synapse.ts"; -import { deepCopy } from "../plugins/utils/object.ts"; -import { type HomeserverContainer } from "./HomeserverContainer.ts"; -import { type StartedMatrixAuthenticationServiceContainer } from "./mas.ts"; +import { randB64Bytes } from "@element-hq/element-web-playwright-common/lib/utils/rand.js"; +import { deepCopy } from "@element-hq/element-web-playwright-common/lib/utils/object.js"; +import { + StartedSynapseContainer, + type HomeserverContainer, + type StartedMatrixAuthenticationServiceContainer, +} from "@element-hq/element-web-playwright-common/lib/testcontainers"; const DEFAULT_CONFIG = { version: 2, @@ -223,7 +224,7 @@ export class DendriteContainer extends GenericContainer implements HomeserverCon .withWaitStrategy(Wait.forHttp("/_matrix/client/versions", 8008)); } - public withConfigField(key: string, value: any): this { + public withConfigField(key: string, value: unknown): this { set(this.config, key, value); return this; } @@ -236,6 +237,11 @@ export class DendriteContainer extends GenericContainer implements HomeserverCon return this; } + // Dendrite does not support SMTP at this time - https://github.com/element-hq/dendrite/issues/1298 + public withSmtpServer(): this { + return this; + } + // Dendrite does not support MAS at this time public withMatrixAuthenticationService(mas?: StartedMatrixAuthenticationServiceContainer): this { return this; diff --git a/playwright/testcontainers/mailpit.ts b/playwright/testcontainers/mailpit.ts deleted file mode 100644 index 6c47f9ab37..0000000000 --- a/playwright/testcontainers/mailpit.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* -Copyright 2024 New Vector 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 { AbstractStartedContainer, GenericContainer, type StartedTestContainer, Wait } from "testcontainers"; -import { MailpitClient } from "mailpit-api"; - -export class MailhogContainer extends GenericContainer { - constructor() { - super("axllent/mailpit:latest"); - - this.withExposedPorts(8025).withWaitStrategy(Wait.forListeningPorts()).withEnvironment({ - MP_SMTP_AUTH_ALLOW_INSECURE: "true", - MP_SMTP_AUTH_ACCEPT_ANY: "true", - }); - } - - public override async start(): Promise { - return new StartedMailhogContainer(await super.start()); - } -} - -export class StartedMailhogContainer extends AbstractStartedContainer { - public readonly client: MailpitClient; - - constructor(container: StartedTestContainer) { - super(container); - this.client = new MailpitClient(`http://${container.getHost()}:${container.getMappedPort(8025)}`); - } -} diff --git a/playwright/testcontainers/mas.ts b/playwright/testcontainers/mas.ts deleted file mode 100644 index bdd071ebc2..0000000000 --- a/playwright/testcontainers/mas.ts +++ /dev/null @@ -1,346 +0,0 @@ -/* -Copyright 2024 New Vector 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 { - AbstractStartedContainer, - GenericContainer, - type StartedTestContainer, - Wait, - type ExecResult, -} from "testcontainers"; -import { type StartedPostgreSqlContainer } from "@testcontainers/postgresql"; -import * as YAML from "yaml"; - -import { getFreePort } from "../plugins/utils/port.ts"; -import { deepCopy } from "../plugins/utils/object.ts"; -import { type Credentials } from "../plugins/homeserver"; - -const DEFAULT_CONFIG = { - http: { - listeners: [ - { - name: "web", - resources: [ - { name: "discovery" }, - { name: "human" }, - { name: "oauth" }, - { name: "compat" }, - { - name: "graphql", - playground: true, - }, - { - name: "assets", - path: "/usr/local/share/mas-cli/assets/", - }, - ], - binds: [ - { - address: "[::]:8080", - }, - ], - proxy_protocol: false, - }, - { - name: "internal", - resources: [ - { - name: "health", - }, - ], - binds: [ - { - address: "[::]:8081", - }, - ], - proxy_protocol: false, - }, - ], - trusted_proxies: ["192.128.0.0/16", "172.16.0.0/12", "10.0.0.0/10", "127.0.0.1/8", "fd00::/8", "::1/128"], - public_base: "", // Needs to be set - issuer: "", // Needs to be set - }, - database: { - host: "postgres", - port: 5432, - database: "postgres", - username: "postgres", - password: "p4S5w0rD", - max_connections: 10, - min_connections: 0, - connect_timeout: 30, - idle_timeout: 600, - max_lifetime: 1800, - }, - telemetry: { - tracing: { - exporter: "none", - propagators: [], - }, - metrics: { - exporter: "none", - }, - sentry: { - dsn: null, - }, - }, - templates: { - path: "/usr/local/share/mas-cli/templates/", - assets_manifest: "/usr/local/share/mas-cli/manifest.json", - translations_path: "/usr/local/share/mas-cli/translations/", - }, - email: { - from: '"Authentication Service" ', - reply_to: '"Authentication Service" ', - transport: "smtp", - mode: "plain", - hostname: "mailpit", - port: 1025, - username: "username", - password: "password", - }, - secrets: { - encryption: "984b18e207c55ad5fbb2a49b217481a722917ee87b2308d4cf314c83fed8e3b5", - keys: [ - { - kid: "YEAhzrKipJ", - key: "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAuIV+AW5vx52I4CuumgSxp6yvKfIAnRdALeZZCoFkIGxUli1B\nS79NJ3ls46oLh1pSD9RrhaMp6HTNoi4K3hnP9Q9v77pD7KwdFKG3UdG1zksIB0s/\n+/Ey/DmX4LPluwBBS7r/LkQ1jk745lENA++oiDqZf2D/uP8jCHlvaSNyVKTqi1ki\nOXPd4T4xBUjzuas9ze5jQVSYtfOidgnv1EzUipbIxgvH1jNt4raRlmP8mOq7xEnW\nR+cF5x6n/g17PdSEfrwO4kz6aKGZuMP5lVlDEEnMHKabFSQDBl7+Mpok6jXutbtA\nuiBnsKEahF9eoj4na4fpbRNPdIVyoaN5eGvm5wIDAQABAoIBAApyFCYEmHNWaa83\nCdVSOrRhRDE9r+c0r79pcNT1ajOjrk4qFa4yEC4R46YntCtfY5Hd1pBkIjU0l4d8\nz8Su9WTMEOwjQUEepS7L0NLi6kXZXYT8L40VpGs+32grBvBFHW0qEtQNrHJ36gMv\nx2rXoFTF7HaXiSJx3wvVxAbRqOE9tBXLsmNHaWaAdWQG5o77V9+zvMri3cAeEg2w\nVkKokb0dza7es7xG3tqS26k69SrwGeeuKo7qCHPH2cfyWmY5Yhv8iOoA59JzzbiK\nUdxyzCHskrPSpRKVkVVwmY3RBt282TmSRG7td7e5ESSj50P2e5BI5uu1Hp/dvU4F\nvYjV7kECgYEA6WqYoUpVsgQiqhvJwJIc/8gRm0mUy8TenI36z4Iim01Nt7fibWH7\nXnsFqLGjXtYNVWvBcCrUl9doEnRbJeG2eRGbGKYAWVrOeFvwM4fYvw9GoOiJdDj4\ncgWDe7eHbHE+UTqR7Nnr/UBfipoNWDh6X68HRBuXowh0Q6tOfxsrRFECgYEAyl/V\n4b8bFp3pKZZCb+KPSYsQf793cRmrBexPcLWcDPYbMZQADEZ/VLjbrNrpTOWxUWJT\nhr8MrWswnHO+l5AFu5CNO+QgV2dHLk+2w8qpdpFRPJCfXfo2D3wZ0c4cv3VCwv1V\n5y7f6XWVjDWZYV4wj6c3shxZJjZ+9Hbhf3/twbcCgYA6fuRRR3fCbRbi2qPtBrEN\nyO3gpMgNaQEA6vP4HPzfPrhDWmn8T5nXS61XYW03zxz4U1De81zj0K/cMBzHmZFJ\nNghQXQmpWwBzWVcREvJWr1Vb7erEnaJlsMwKrSvbGWYspSj82oAxr3hCG+lMOpsw\nb4S6pM+TpAK/EqdRY1WsgQKBgQCGoMaaTRXqL9bC0bEU2XVVCWxKb8c3uEmrwQ7/\n/fD4NmjUzI5TnDps1CVfkqoNe+hAKddDFqmKXHqUOfOaxDbsFje+lf5l5tDVoDYH\nfjTKKdYPIm7CiAeauYY7qpA5Vfq52Opixy4yEwUPp0CII67OggFtPaqY3zwJyWQt\n+57hdQKBgGCXM/KKt7ceUDcNJxSGjvu0zD9D5Sv2ihYlEBT/JLaTCCJdvzREevaJ\n1d+mpUAt0Lq6A8NWOMq8HPaxAik3rMQ0WtM5iG+XgsUqvTSb7NcshArDLuWGnW3m\nMC4rM0UBYAS4QweduUSH1imrwH/1Gu5+PxbiecceRMMggWpzu0Bq\n-----END RSA PRIVATE KEY-----\n", - }, - { - kid: "8J1AxrlNZT", - key: "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIF1cjfIOEdy3BXJ72x6fKpEB8WP1ddZAUJAaqqr/6CpToAoGCCqGSM49\nAwEHoUQDQgAEfHdNuI1Yeh3/uOq2PlnW2vymloOVpwBYebbw4VVsna9xhnutIdQW\ndE8hkX8Yb0pIDasrDiwllVLzSvsWJAI0Kw==\n-----END EC PRIVATE KEY-----\n", - }, - { - kid: "3BW6un1EBi", - key: "-----BEGIN EC PRIVATE KEY-----\nMIGkAgEBBDA+3ZV17r8TsiMdw1cpbTSNbyEd5SMy3VS1Mk/kz6O2Ev/3QZut8GE2\nq3eGtLBoVQigBwYFK4EEACKhZANiAASs8Wxjk/uRimRKXnPr2/wDaXkN9wMDjYQK\nmZULb+0ZP1/cXmuXuri8hUGhQvIU8KWY9PkpV+LMPEdpE54mHPKSLjq5CDXoSZ/P\n9f7cdRaOZ000KQPZfIFR9ujJTtDN7Vs=\n-----END EC PRIVATE KEY-----\n", - }, - { - kid: "pkZ0pTKK0X", - key: "-----BEGIN EC PRIVATE KEY-----\nMHQCAQEEIHenfsXYPc5yzjZKUfvmydDR1YRwdsfZYvwHf/2wsYxooAcGBSuBBAAK\noUQDQgAEON1x7Vlu+nA0KvC5vYSOHhDUkfLYNZwYSLPFVT02h9E13yFFMIJegIBl\nAer+6PMZpPc8ycyeH9N+U9NAyliBhQ==\n-----END EC PRIVATE KEY-----\n", - }, - ], - }, - passwords: { - enabled: true, - schemes: [ - { - version: 1, - algorithm: "argon2id", - }, - ], - minimum_complexity: 0, - }, - policy: { - wasm_module: "/usr/local/share/mas-cli/policy.wasm", - client_registration_entrypoint: "client_registration/violation", - register_entrypoint: "register/violation", - authorization_grant_entrypoint: "authorization_grant/violation", - password_entrypoint: "password/violation", - email_entrypoint: "email/violation", - data: { - client_registration: { - // allow non-SSL and localhost URIs - allow_insecure_uris: true, - // EW doesn't have contacts at this time - allow_missing_contacts: true, - }, - }, - }, - upstream_oauth2: { - providers: [], - }, - branding: { - service_name: null, - policy_uri: null, - tos_uri: null, - imprint: null, - logo_uri: null, - }, - account: { - password_registration_enabled: true, - }, - experimental: { - access_token_ttl: 300, - compat_token_ttl: 300, - }, - rate_limiting: { - login: { - burst: 10, - per_second: 1, - }, - registration: { - burst: 10, - per_second: 1, - }, - }, -}; - -export class MatrixAuthenticationServiceContainer extends GenericContainer { - private config: typeof DEFAULT_CONFIG; - private readonly args = ["-c", "/config/config.yaml"]; - - constructor(db: StartedPostgreSqlContainer) { - // We rely on `mas-cli manage add-email` which isn't in a release yet - // https://github.com/element-hq/matrix-authentication-service/pull/3235 - super("ghcr.io/element-hq/matrix-authentication-service:sha-0b90c33"); - - this.config = deepCopy(DEFAULT_CONFIG); - this.config.database.username = db.getUsername(); - this.config.database.password = db.getPassword(); - - this.withExposedPorts(8080, 8081) - .withWaitStrategy(Wait.forHttp("/health", 8081)) - .withCommand(["server", ...this.args]); - } - - public withConfig(config: object): this { - this.config = { - ...this.config, - ...config, - }; - return this; - } - - public override async start(): Promise { - // MAS config issuer needs to know what URL it'll be accessed from, so we have to map the port manually - const port = await getFreePort(); - - this.config.http.public_base = `http://localhost:${port}/`; - this.config.http.issuer = `http://localhost:${port}/`; - - this.withExposedPorts({ - container: 8080, - host: port, - }).withCopyContentToContainer([ - { - target: "/config/config.yaml", - content: YAML.stringify(this.config), - }, - ]); - - return new StartedMatrixAuthenticationServiceContainer( - await super.start(), - `http://localhost:${port}`, - this.args, - ); - } -} - -export class StartedMatrixAuthenticationServiceContainer extends AbstractStartedContainer { - private adminTokenPromise?: Promise; - - constructor( - container: StartedTestContainer, - public readonly baseUrl: string, - private readonly args: string[], - ) { - super(container); - } - - public async getAdminToken(): Promise { - if (this.adminTokenPromise === undefined) { - this.adminTokenPromise = this.registerUserInternal( - "admin", - "totalyinsecureadminpassword", - undefined, - true, - ).then((res) => res.accessToken); - } - return this.adminTokenPromise; - } - - private async manage(cmd: string, ...args: string[]): Promise { - const result = await this.exec(["mas-cli", "manage", cmd, ...this.args, ...args]); - if (result.exitCode !== 0) { - throw new Error(`Failed mas-cli manage ${cmd}: ${result.output}`); - } - return result; - } - - private async manageRegisterUser( - username: string, - password: string, - displayName?: string, - admin = false, - ): Promise { - const args: string[] = []; - if (admin) args.push("-a"); - const result = await this.manage( - "register-user", - ...args, - "-y", - "-p", - password, - "-d", - displayName ?? "", - username, - ); - - const registerLines = result.output.trim().split("\n"); - const userId = registerLines - .find((line) => line.includes("Matrix ID: ")) - ?.split(": ") - .pop(); - - if (!userId) { - throw new Error(`Failed to register user: ${result.output}`); - } - - return userId; - } - - private async manageIssueCompatibilityToken( - username: string, - admin = false, - ): Promise<{ accessToken: string; deviceId: string }> { - const args: string[] = []; - if (admin) args.push("--yes-i-want-to-grant-synapse-admin-privileges"); - const result = await this.manage("issue-compatibility-token", ...args, username); - - const parts = result.output.trim().split(/\s+/); - const accessToken = parts.find((part) => part.startsWith("mct_")); - const deviceId = parts.find((part) => part.startsWith("compat_session.device="))?.split("=")[1]; - - if (!accessToken || !deviceId) { - throw new Error(`Failed to issue compatibility token: ${result.output}`); - } - - return { accessToken, deviceId }; - } - - private async registerUserInternal( - username: string, - password: string, - displayName?: string, - admin = false, - ): Promise { - const userId = await this.manageRegisterUser(username, password, displayName, admin); - const { deviceId, accessToken } = await this.manageIssueCompatibilityToken(username, admin); - - return { - userId, - accessToken, - deviceId, - homeServer: userId.slice(1).split(":").slice(1).join(":"), - displayName, - username, - password, - }; - } - - public async registerUser(username: string, password: string, displayName?: string): Promise { - return this.registerUserInternal(username, password, displayName, false); - } - - public async setThreepid(username: string, medium: string, address: string): Promise { - if (medium !== "email") { - throw new Error("Only email threepids are supported by MAS"); - } - - await this.manage("add-email", username, address); - } -} diff --git a/playwright/testcontainers/synapse.ts b/playwright/testcontainers/synapse.ts index 47c2e708e2..2e841604be 100644 --- a/playwright/testcontainers/synapse.ts +++ b/playwright/testcontainers/synapse.ts @@ -1,395 +1,20 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024-2025 New Vector 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 { - AbstractStartedContainer, - GenericContainer, - type RestartOptions, - type StartedTestContainer, - Wait, -} from "testcontainers"; -import { type APIRequestContext, type TestInfo } from "@playwright/test"; -import crypto from "node:crypto"; -import * as YAML from "yaml"; -import { set } from "lodash"; - -import { getFreePort } from "../plugins/utils/port.ts"; -import { randB64Bytes } from "../plugins/utils/rand.ts"; -import { type Credentials } from "../plugins/homeserver"; -import { deepCopy } from "../plugins/utils/object.ts"; -import { type HomeserverContainer, type StartedHomeserverContainer } from "./HomeserverContainer.ts"; -import { type StartedMatrixAuthenticationServiceContainer } from "./mas.ts"; -import { Api, ClientServerApi, type Verb } from "../plugins/utils/api.ts"; +import { SynapseContainer as BaseSynapseContainer } from "@element-hq/element-web-playwright-common/lib/testcontainers"; const TAG = "develop@sha256:2ea87d45fc7ff3327c671b3b4447e6b2032d4f5ca07d62d8aef0d900e105c2f4"; -const DEFAULT_CONFIG = { - server_name: "localhost", - public_baseurl: "", // set by start method - pid_file: "/homeserver.pid", - web_client: false, - soft_file_limit: 0, - // Needs to be configured to log to the console like a good docker process - log_config: "/data/log.config", - listeners: [ - { - // Listener is always port 8008 (configured in the container) - port: 8008, - tls: false, - bind_addresses: ["::"], - type: "http", - x_forwarded: true, - resources: [ - { - names: ["client"], - compress: false, - }, - ], - }, - ], - database: { - // An sqlite in-memory database is fast & automatically wipes each time - name: "sqlite3", - args: { - database: ":memory:", - }, - }, - rc_messages_per_second: 10000, - rc_message_burst_count: 10000, - rc_registration: { - per_second: 10000, - burst_count: 10000, - }, - rc_joins: { - local: { - per_second: 9999, - burst_count: 9999, - }, - remote: { - per_second: 9999, - burst_count: 9999, - }, - }, - rc_joins_per_room: { - per_second: 9999, - burst_count: 9999, - }, - rc_3pid_validation: { - per_second: 1000, - burst_count: 1000, - }, - rc_invites: { - per_room: { - per_second: 1000, - burst_count: 1000, - }, - per_user: { - per_second: 1000, - burst_count: 1000, - }, - }, - rc_login: { - address: { - per_second: 10000, - burst_count: 10000, - }, - account: { - per_second: 10000, - burst_count: 10000, - }, - failed_attempts: { - per_second: 10000, - burst_count: 10000, - }, - }, - media_store_path: "/tmp/media_store", - max_upload_size: "50M", - max_image_pixels: "32M", - dynamic_thumbnails: false, - enable_registration: true, - enable_registration_without_verification: true, - disable_msisdn_registration: false, - registrations_require_3pid: [], - enable_metrics: false, - report_stats: false, - // These placeholders will be replaced with values generated at start - registration_shared_secret: "secret", - macaroon_secret_key: "secret", - form_secret: "secret", - // Signing key must be here: it will be generated to this file - signing_key_path: "/data/localhost.signing.key", - trusted_key_servers: [], - password_config: { - enabled: true, - }, - ui_auth: {}, - background_updates: { - // Inhibit background updates as this Synapse isn't long-lived - min_batch_size: 100000, - sleep_duration_ms: 100000, - }, - enable_authenticated_media: true, - email: undefined, - user_consent: undefined, - server_notices: undefined, - allow_guest_access: false, - experimental_features: {}, - oidc_providers: [], - serve_server_wellknown: true, - presence: { - enabled: true, - include_offline_users_on_sync: true, - }, - room_list_publication_rules: [{ action: "allow" }], -}; - -export type SynapseConfig = Partial; - -export class SynapseContainer extends GenericContainer implements HomeserverContainer { - private config: typeof DEFAULT_CONFIG; - private mas?: StartedMatrixAuthenticationServiceContainer; - - constructor() { +/** + * SynapseContainer which freezes the docker digest to stabilise tests, + * updated periodically by the `playwright-image-updates.yaml` workflow. + */ +export class SynapseContainer extends BaseSynapseContainer { + public constructor() { super(`ghcr.io/element-hq/synapse:${TAG}`); - - this.config = deepCopy(DEFAULT_CONFIG); - this.config.registration_shared_secret = randB64Bytes(16); - this.config.macaroon_secret_key = randB64Bytes(16); - this.config.form_secret = randB64Bytes(16); - - const signingKey = randB64Bytes(32); - this.withWaitStrategy(Wait.forHttp("/health", 8008)).withCopyContentToContainer([ - { target: this.config.signing_key_path, content: `ed25519 x ${signingKey}` }, - { - target: this.config.log_config, - content: YAML.stringify({ - version: 1, - formatters: { - precise: { - format: "%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s", - }, - }, - handlers: { - console: { - class: "logging.StreamHandler", - formatter: "precise", - }, - }, - loggers: { - "synapse.storage.SQL": { - level: "DEBUG", - }, - "twisted": { - handlers: ["console"], - propagate: false, - }, - }, - root: { - level: "DEBUG", - handlers: ["console"], - }, - disable_existing_loggers: false, - }), - }, - ]); - } - - public withConfigField(key: string, value: any): this { - set(this.config, key, value); - return this; - } - - public withConfig(config: Partial): this { - this.config = { - ...this.config, - ...config, - }; - return this; - } - - public withMatrixAuthenticationService(mas?: StartedMatrixAuthenticationServiceContainer): this { - this.mas = mas; - return this; - } - - public override async start(): Promise { - // Synapse config public_baseurl needs to know what URL it'll be accessed from, so we have to map the port manually - const port = await getFreePort(); - - this.withExposedPorts({ - container: 8008, - host: port, - }) - .withConfig({ - public_baseurl: `http://localhost:${port}`, - }) - .withCopyContentToContainer([ - { - target: "/data/homeserver.yaml", - content: YAML.stringify(this.config), - }, - ]); - - const container = await super.start(); - const baseUrl = `http://localhost:${port}`; - if (this.mas) { - return new StartedSynapseWithMasContainer( - container, - baseUrl, - this.config.registration_shared_secret, - this.mas, - ); - } - - return new StartedSynapseContainer(container, baseUrl, this.config.registration_shared_secret); - } -} - -export class StartedSynapseContainer extends AbstractStartedContainer implements StartedHomeserverContainer { - protected adminTokenPromise?: Promise; - protected readonly adminApi: Api; - public readonly csApi: ClientServerApi; - - constructor( - container: StartedTestContainer, - public readonly baseUrl: string, - private readonly registrationSharedSecret: string, - ) { - super(container); - this.adminApi = new Api(`${this.baseUrl}/_synapse/admin`); - this.csApi = new ClientServerApi(this.baseUrl); - } - - public restart(options?: Partial): Promise { - this.adminTokenPromise = undefined; - return super.restart(options); - } - - public setRequest(request: APIRequestContext): void { - this.csApi.setRequest(request); - this.adminApi.setRequest(request); - } - - public async onTestFinished(testInfo: TestInfo): Promise { - // Clean up the server to prevent rooms leaking between tests - await this.deletePublicRooms(); - } - - protected async deletePublicRooms(): Promise { - const token = await this.getAdminToken(); - // We hide the rooms from the room directory to save time between tests and for portability between homeservers - const { chunk: rooms } = await this.csApi.request<{ - chunk: { room_id: string }[]; - }>("GET", "/v3/publicRooms", token, {}); - await Promise.all( - rooms.map((room) => - this.csApi.request("PUT", `/v3/directory/list/room/${room.room_id}`, token, { visibility: "private" }), - ), - ); - } - - private async registerUserInternal( - username: string, - password: string, - displayName?: string, - admin = false, - ): Promise { - const path = "/v1/register"; - const { nonce } = await this.adminApi.request<{ nonce: string }>("GET", path, undefined, {}); - const mac = crypto - .createHmac("sha1", this.registrationSharedSecret) - .update(`${nonce}\0${username}\0${password}\0${admin ? "" : "not"}admin`) - .digest("hex"); - const data = await this.adminApi.request<{ - home_server: string; - access_token: string; - user_id: string; - device_id: string; - }>("POST", path, undefined, { - nonce, - username, - password, - mac, - admin, - displayname: displayName, - }); - - return { - homeServer: data.home_server || data.user_id.split(":").slice(1).join(":"), - accessToken: data.access_token, - userId: data.user_id, - deviceId: data.device_id, - password, - displayName, - username, - }; - } - - protected async getAdminToken(): Promise { - if (this.adminTokenPromise === undefined) { - this.adminTokenPromise = this.registerUserInternal( - "admin", - "totalyinsecureadminpassword", - undefined, - true, - ).then((res) => res.accessToken); - } - return this.adminTokenPromise; - } - - private async adminRequest(verb: "GET", path: string, data?: never): Promise; - private async adminRequest(verb: Verb, path: string, data?: object): Promise; - private async adminRequest(verb: Verb, path: string, data?: object): Promise { - const adminToken = await this.getAdminToken(); - return this.adminApi.request(verb, path, adminToken, data); - } - - public registerUser(username: string, password: string, displayName?: string): Promise { - return this.registerUserInternal(username, password, displayName, false); - } - - public async loginUser(userId: string, password: string): Promise { - return this.csApi.loginUser(userId, password); - } - - public async setThreepid(userId: string, medium: string, address: string): Promise { - await this.adminRequest("PUT", `/v2/users/${userId}`, { - threepids: [ - { - medium, - address, - }, - ], - }); - } -} - -export class StartedSynapseWithMasContainer extends StartedSynapseContainer { - constructor( - container: StartedTestContainer, - baseUrl: string, - registrationSharedSecret: string, - private readonly mas: StartedMatrixAuthenticationServiceContainer, - ) { - super(container, baseUrl, registrationSharedSecret); - } - - protected async getAdminToken(): Promise { - if (this.adminTokenPromise === undefined) { - this.adminTokenPromise = this.mas.getAdminToken(); - } - return this.adminTokenPromise; - } - - public registerUser(username: string, password: string, displayName?: string): Promise { - return this.mas.registerUser(username, password, displayName); - } - - public async setThreepid(userId: string, medium: string, address: string): Promise { - return this.mas.setThreepid(userId, medium, address); } } diff --git a/yarn.lock b/yarn.lock index bab0fd1c35..600521f2b9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -27,7 +27,7 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" -"@axe-core/playwright@^4.8.1": +"@axe-core/playwright@^4.10.1": version "4.10.1" resolved "https://registry.yarnpkg.com/@axe-core/playwright/-/playwright-4.10.1.tgz#c811ba8bfa244833cce422c4131e0043828c42cc" integrity sha512-EV5t39VV68kuAfMKqb/RL+YjYKhfuGim9rgIaQ6Vntb2HgaCaau0h98Y3WEUqW1+PbdzxDtDNjFAipbtZuBmEA== @@ -1551,6 +1551,19 @@ resolved "https://registry.yarnpkg.com/@element-hq/element-web-module-api/-/element-web-module-api-0.1.1.tgz#e2b24aa38aa9f7b6af3c4993e6402a8b7e2f3cb5" integrity sha512-qtEQD5nFaRJ+vfAis7uhKB66SyCjrz7O+qGz/hKJjgNhBLT/6C5DK90waKINXSw0J3stFR43IWzEk5GBOrTMow== +"@element-hq/element-web-playwright-common@^1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@element-hq/element-web-playwright-common/-/element-web-playwright-common-1.1.5.tgz#e9d4e24f0f284d16b7dc8cb9cd893521e1645be0" + integrity sha512-Cw2PqaU9YUx/qHq8nybjfxMhSGshkvZiRBPMhYnamjMTjUiSEEF74061gjIecxLF/3hgV6I0dGp5Km3FhRbTPQ== + dependencies: + "@axe-core/playwright" "^4.10.1" + "@testcontainers/postgresql" "^10.18.0" + lodash-es "^4.17.21" + mailpit-api "^1.2.0" + strip-ansi "^7.1.0" + testcontainers "^10.18.0" + yaml "^2.7.0" + "@eslint-community/eslint-utils@^4.2.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -2167,7 +2180,14 @@ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== -"@playwright/test@^1.40.1": +"@playwright/test@1.50.1": + version "1.50.1" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.50.1.tgz#027d00ca77ec79688764eb765cfe9a688807bf0b" + integrity sha512-Jii3aBg+CEDpgnuDxEp/h7BimHcUTDlpEtce89xEumlJ5ef2hqepZ+PWp1DDpYC/VO9fmWVI1IlEaoI5fK9FXQ== + dependencies: + playwright "1.50.1" + +"@playwright/test@^1.50.1": version "1.51.0" resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.51.0.tgz#8d5c8400b465a0bfdbcf993e390ceecb903ea6d2" integrity sha512-dJ0dMbZeHhI+wb77+ljx/FeC8VBP6j/rj9OAojO08JI80wTZy6vRk9KvHKiDCUh4iMpEiseMgqRBIeW+eKX6RA== @@ -2743,7 +2763,7 @@ "@svgr/plugin-jsx" "8.1.0" "@svgr/plugin-svgo" "8.1.0" -"@testcontainers/postgresql@^10.16.0": +"@testcontainers/postgresql@^10.18.0": version "10.19.0" resolved "https://registry.yarnpkg.com/@testcontainers/postgresql/-/postgresql-10.19.0.tgz#e1ff9fbfee76c23bc899865524ee8e2ee297bdf2" integrity sha512-3+yQJHCWEtp4hylfZgRxCWN1P6dGqKhFM7Bypg22NpJqq1x/dcmamVCvD+4eTdm1uHV1Ta0BkHRWejxGOyTnrw== @@ -3592,15 +3612,16 @@ classnames "^2.5.1" vaul "^1.0.0" -"@vector-im/matrix-wysiwyg-wasm@link:../../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.2-3fa19a2a17fd12d955ef1e14fd63aecbcf3b95e8-integrity/node_modules/bindings/wysiwyg-wasm": +"@vector-im/matrix-wysiwyg-wasm@link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.2-3fa19a2a17fd12d955ef1e14fd63aecbcf3b95e8-integrity/node_modules/bindings/wysiwyg-wasm": version "0.0.0" + uid "" "@vector-im/matrix-wysiwyg@2.38.2": version "2.38.2" resolved "https://registry.yarnpkg.com/@vector-im/matrix-wysiwyg/-/matrix-wysiwyg-2.38.2.tgz#3fa19a2a17fd12d955ef1e14fd63aecbcf3b95e8" integrity sha512-TUnLPgZ8/zGUccQZxjIP3MVHjqybgV4u0r6kXibs35wlXgomXjwcN5gchl3FpgGkiHbi8g3D2ao0oHaqi2GaIw== dependencies: - "@vector-im/matrix-wysiwyg-wasm" "link:../../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.2-3fa19a2a17fd12d955ef1e14fd63aecbcf3b95e8-integrity/node_modules/bindings/wysiwyg-wasm" + "@vector-im/matrix-wysiwyg-wasm" "link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.2-3fa19a2a17fd12d955ef1e14fd63aecbcf3b95e8-integrity/node_modules/bindings/wysiwyg-wasm" "@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1": version "1.14.1" @@ -3805,7 +3826,7 @@ acorn-walk@^8.0.0, acorn-walk@^8.0.2, acorn-walk@^8.1.1: dependencies: acorn "^8.11.0" -acorn@^8.0.4, acorn@^8.1.0, acorn@^8.11.0, acorn@^8.4.1, acorn@^8.9.0: +acorn@^8.0.4, acorn@^8.1.0, acorn@^8.11.0, acorn@^8.9.0: version "8.13.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.13.0.tgz#2a30d670818ad16ddd6a35d3842dacec9e5d7ca3" integrity sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w== @@ -3815,6 +3836,11 @@ acorn@^8.14.0, acorn@^8.8.1, acorn@^8.8.2: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== +acorn@^8.4.1: + version "8.14.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb" + integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== + agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -4185,15 +4211,20 @@ await-lock@^2.1.0: resolved "https://registry.yarnpkg.com/await-lock/-/await-lock-2.2.2.tgz#a95a9b269bfd2f69d22b17a321686f551152bcef" integrity sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw== -axe-core@^4.10.0, axe-core@~4.10.2: +axe-core@^4.10.0: version "4.10.2" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.10.2.tgz#85228e3e1d8b8532a27659b332e39b7fa0e022df" integrity sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w== +axe-core@~4.10.2: + version "4.10.3" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.10.3.tgz#04145965ac7894faddbac30861e5d8f11bfd14fc" + integrity sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg== + axios@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.8.2.tgz#fabe06e241dfe83071d4edfbcaa7b1c3a40f7979" - integrity sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg== + version "1.8.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.8.1.tgz#7c118d2146e9ebac512b7d1128771cdd738d11e3" + integrity sha512-NN+fvwH/kV01dYUQ3PTOZns4LWtWhOFCAhQ/pHb88WQ1hNe5V/dvFwc4VJcDL11LT9xSX0QtsR8sWUuyOuOq7g== dependencies: follow-redirects "^1.15.6" form-data "^4.0.0" @@ -8568,6 +8599,11 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash-es@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" @@ -8672,7 +8708,7 @@ magic-string@0.30.8: dependencies: "@jridgewell/sourcemap-codec" "^1.4.15" -mailpit-api@^1.0.5: +mailpit-api@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mailpit-api/-/mailpit-api-1.2.0.tgz#6cbd7c5c091fd74b000385790a1fe0c9f2a83fba" integrity sha512-oni/IwQhtbwk3ERwJ6IarKIFgz2U5684SK6Bbkau2GBo2FLoiT14UGkL3CXleYPBH5SCsnymHap1eevEOLwqaA== @@ -8762,8 +8798,8 @@ matrix-events-sdk@0.0.1: integrity sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA== "matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop": - version "37.1.0" - resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/f552370c2625e20a921a5dbf5284491bb6c22861" + version "37.0.0" + resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/d81929de4c9526e7d68ab7226804726cdef6387f" dependencies: "@babel/runtime" "^7.12.5" "@matrix-org/matrix-sdk-crypto-wasm" "^14.0.1" @@ -9559,11 +9595,25 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -playwright-core@1.51.0, playwright-core@^1.45.1: +playwright-core@1.50.1: + version "1.50.1" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.50.1.tgz#6a0484f1f1c939168f40f0ab3828c4a1592c4504" + integrity sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ== + +playwright-core@1.51.0, playwright-core@^1.51.0: version "1.51.0" resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.51.0.tgz#bb23ea6bb6298242d088ae5e966ffcf8dc9827e8" integrity sha512-x47yPE3Zwhlil7wlNU/iktF7t2r/URR3VLbH6EknJd/04Qc/PSJ0EY3CMXipmglLG+zyRxW6HNo2EGbKLHPWMg== +playwright@1.50.1: + version "1.50.1" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.50.1.tgz#2f93216511d65404f676395bfb97b41aa052b180" + integrity sha512-G8rwsOQJ63XG6BbKj2w5rHeavFjy5zynBA9zsJMMtBoe/Uf757oG12NXz6e6OirF7RCrTVAKFXbLmn1RbL7Qaw== + dependencies: + playwright-core "1.50.1" + optionalDependencies: + fsevents "2.3.2" + playwright@1.51.0: version "1.51.0" resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.51.0.tgz#9ba154497ba62bc6dc199c58ee19295eb35a4707" @@ -11951,10 +12001,10 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" -testcontainers@^10.16.0, testcontainers@^10.19.0: - version "10.19.0" - resolved "https://registry.yarnpkg.com/testcontainers/-/testcontainers-10.19.0.tgz#007138559c6de68c80334232a259f4e94fa19955" - integrity sha512-/mbcCOaj6jj2IPMMmt+YrBi71MZ4BqEzqicjAInsfEox4pVVMnYIW4CkWOdCLiuZ9nVUkoBtxFSJDTqggJNB5A== +testcontainers@10.20.0, testcontainers@^10.18.0, testcontainers@^10.19.0, testcontainers@^10.20.0: + version "10.20.0" + resolved "https://registry.yarnpkg.com/testcontainers/-/testcontainers-10.20.0.tgz#45c524ae4be9b1ffe2fb42b701f6c0a04ee2d90a" + integrity sha512-pOPm/OUIT41aMijAZ9RsYg5xOq9ciy93+pCf2D9qDI0oV8rwk91XpPoUlizll4qwxmmHsLmfZFHJTpeB+BIfmw== dependencies: "@balena/dockerignore" "^1.0.2" "@types/dockerode" "^3.3.29" From d88776e2dc32e6e5057e5e5b2949bab0d9542a64 Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Mon, 17 Mar 2025 20:37:14 +0530 Subject: [PATCH 089/458] RoomListViewModel: Add functionality to toggle message preview setting (#29511) * Add setting for showing message previews * Add hook to track and toggle message preview * Use hook in view model * Add tests * Fix tests * Fix lint * Fix typo --- .../viewmodels/roomlist/RoomListViewModel.tsx | 14 ++++++++ .../roomlist/useMessagePreviewToggle.tsx | 36 +++++++++++++++++++ src/settings/Settings.tsx | 5 +++ .../roomlist/RoomListViewModel-test.tsx | 22 ++++++++++++ .../rooms/RoomListPanel/RoomList-test.tsx | 2 ++ .../RoomListPrimaryFilters-test.tsx | 2 ++ 6 files changed, 81 insertions(+) create mode 100644 src/components/viewmodels/roomlist/useMessagePreviewToggle.tsx diff --git a/src/components/viewmodels/roomlist/RoomListViewModel.tsx b/src/components/viewmodels/roomlist/RoomListViewModel.tsx index b1b39e7f0c..6c46ca6d38 100644 --- a/src/components/viewmodels/roomlist/RoomListViewModel.tsx +++ b/src/components/viewmodels/roomlist/RoomListViewModel.tsx @@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details. import type { Room } from "matrix-js-sdk/src/matrix"; import { type PrimaryFilter, type SecondaryFilters, useFilteredRooms } from "./useFilteredRooms"; import { type SortOption, useSorter } from "./useSorter"; +import { useMessagePreviewToggle } from "./useMessagePreviewToggle"; export interface RoomListViewState { /** @@ -39,6 +40,16 @@ export interface RoomListViewState { * The currently active sort option. */ activeSortOption: SortOption; + + /** + * Whether message previews must be shown or not. + */ + shouldShowMessagePreview: boolean; + + /** + * A function to turn on/off message previews. + */ + toggleMessagePreview: () => void; } /** @@ -48,6 +59,7 @@ export interface RoomListViewState { export function useRoomListViewModel(): RoomListViewState { const { primaryFilters, rooms, activateSecondaryFilter, activeSecondaryFilter } = useFilteredRooms(); const { activeSortOption, sort } = useSorter(); + const { shouldShowMessagePreview, toggleMessagePreview } = useMessagePreviewToggle(); return { rooms, @@ -56,5 +68,7 @@ export function useRoomListViewModel(): RoomListViewState { activeSecondaryFilter, activeSortOption, sort, + shouldShowMessagePreview, + toggleMessagePreview, }; } diff --git a/src/components/viewmodels/roomlist/useMessagePreviewToggle.tsx b/src/components/viewmodels/roomlist/useMessagePreviewToggle.tsx new file mode 100644 index 0000000000..27ccd40106 --- /dev/null +++ b/src/components/viewmodels/roomlist/useMessagePreviewToggle.tsx @@ -0,0 +1,36 @@ +/* + * Copyright 2025 New Vector 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 { useCallback, useState } from "react"; + +import SettingsStore from "../../../settings/SettingsStore"; +import { SettingLevel } from "../../../settings/SettingLevel"; + +interface MessagePreviewToggleState { + shouldShowMessagePreview: boolean; + toggleMessagePreview: () => void; +} + +/** + * This hook: + * - Provides a state that tracks whether message previews are turned on or off. + * - Provides a function to toggle message previews. + */ +export function useMessagePreviewToggle(): MessagePreviewToggleState { + const [shouldShowMessagePreview, setShouldShowMessagePreview] = useState(() => + SettingsStore.getValue("RoomList.showMessagePreview"), + ); + + const toggleMessagePreview = useCallback((): void => { + setShouldShowMessagePreview((current) => { + const toggled = !current; + SettingsStore.setValue("RoomList.showMessagePreview", null, SettingLevel.DEVICE, toggled); + return toggled; + }); + }, []); + + return { toggleMessagePreview, shouldShowMessagePreview }; +} diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 3084263b2f..d887c9bb49 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -314,6 +314,7 @@ export interface Settings { "showImages": IBaseSetting; "showAvatarsOnInvites": IBaseSetting; "RoomList.preferredSorting": IBaseSetting; + "RoomList.showMessagePreview": IBaseSetting; "RightPanel.phasesGlobal": IBaseSetting; "RightPanel.phases": IBaseSetting; "enableEventIndexing": IBaseSetting; @@ -1126,6 +1127,10 @@ export const SETTINGS: Settings = { supportedLevels: [SettingLevel.DEVICE], default: SortingAlgorithm.Recency, }, + "RoomList.showMessagePreview": { + supportedLevels: [SettingLevel.DEVICE], + default: false, + }, "RightPanel.phasesGlobal": { supportedLevels: [SettingLevel.DEVICE], default: null, diff --git a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx index 99f1483d4a..43364e0d77 100644 --- a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx +++ b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx @@ -218,4 +218,26 @@ describe("RoomListViewModel", () => { expect(vm.current.activeSortOption).toEqual(SortOption.AToZ); }); }); + + describe("message preview toggle", () => { + it("should return shouldShowMessagePreview based on setting", () => { + jest.spyOn(SettingsStore, "getValue").mockImplementation(() => true); + mockAndCreateRooms(); + const { result: vm } = renderHook(() => useRoomListViewModel()); + expect(vm.current.shouldShowMessagePreview).toEqual(true); + }); + + it("should change setting on toggle", () => { + jest.spyOn(SettingsStore, "getValue").mockImplementation(() => true); + const fn = jest.spyOn(SettingsStore, "setValue").mockImplementation(async () => {}); + mockAndCreateRooms(); + const { result: vm } = renderHook(() => useRoomListViewModel()); + expect(vm.current.shouldShowMessagePreview).toEqual(true); + act(() => { + vm.current.toggleMessagePreview(); + }); + expect(vm.current.shouldShowMessagePreview).toEqual(false); + expect(fn).toHaveBeenCalled(); + }); + }); }); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx index 11764df7b7..5e2d451ff8 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx @@ -35,6 +35,8 @@ describe("", () => { activeSecondaryFilter: SecondaryFilters.AllActivity, sort: jest.fn(), activeSortOption: SortOption.Activity, + shouldShowMessagePreview: false, + toggleMessagePreview: jest.fn(), }; // Needed to render a room list cell diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPrimaryFilters-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPrimaryFilters-test.tsx index a3e60f765d..f4b97b84b6 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPrimaryFilters-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPrimaryFilters-test.tsx @@ -28,6 +28,8 @@ describe("", () => { activeSecondaryFilter: SecondaryFilters.AllActivity, sort: jest.fn(), activeSortOption: SortOption.Activity, + shouldShowMessagePreview: false, + toggleMessagePreview: jest.fn(), }; }); From a6ad6e9ae21283ea19401e13b90cb7ce8ccb99df Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 17 Mar 2025 15:07:57 +0000 Subject: [PATCH 090/458] Remove temporary awscli s3-r2 workaround (#29393) * Remove temporary awscli s3-r2 workaround Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update build_develop.yml --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .github/workflows/build_develop.yml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build_develop.yml b/.github/workflows/build_develop.yml index 55091363d7..bbb52de5a2 100644 --- a/.github/workflows/build_develop.yml +++ b/.github/workflows/build_develop.yml @@ -26,12 +26,6 @@ jobs: R2_URL: ${{ vars.CF_R2_S3_API }} R2_PUBLIC_URL: "https://element-web-develop.element.io" steps: - # Workaround for https://www.cloudflarestatus.com/incidents/t5nrjmpxc1cj - - uses: unfor19/install-aws-cli-action@v1 - with: - version: 2.22.35 - verbose: false - arch: amd64 - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -115,10 +109,11 @@ jobs: # We keep the latest develop.tar.gz on R2 instead of relying on the github artifact uploaded earlier # as the expires after 24h and requires auth to download. # Element Desktop's fetch script uses this tarball to fetch latest develop to build Nightlies. + # Checksum algorithm specified as per https://developers.cloudflare.com/r2/examples/aws/aws-cli/ - name: Deploy to R2 run: | - aws s3 cp dist/develop.tar.gz s3://$R2_BUCKET/develop.tar.gz --endpoint-url $R2_URL --region=auto - aws s3 cp _deploy/ s3://$R2_BUCKET/ --recursive --endpoint-url $R2_URL --region=auto + aws s3 cp dist/develop.tar.gz s3://$R2_BUCKET/develop.tar.gz --endpoint-url $R2_URL --region=auto --checksum-algorithm CRC32 + aws s3 cp _deploy/ s3://$R2_BUCKET/ --recursive --endpoint-url $R2_URL --region=auto --checksum-algorithm CRC32 env: AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_TOKEN }} From 550f529a303934b08efc17d9298266467f1661c8 Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Mon, 17 Mar 2025 22:08:52 +0530 Subject: [PATCH 091/458] Implement `MessagePreviewViewModel` (#29514) * Implement message preview vm * Write tests --- .../roomlist/MessagePreviewViewModel.tsx | 57 ++++++++++++++++++ .../roomlist/MessagePreviewViewModel-test.tsx | 58 +++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 src/components/viewmodels/roomlist/MessagePreviewViewModel.tsx create mode 100644 test/unit-tests/components/viewmodels/roomlist/MessagePreviewViewModel-test.tsx diff --git a/src/components/viewmodels/roomlist/MessagePreviewViewModel.tsx b/src/components/viewmodels/roomlist/MessagePreviewViewModel.tsx new file mode 100644 index 0000000000..9e141c1379 --- /dev/null +++ b/src/components/viewmodels/roomlist/MessagePreviewViewModel.tsx @@ -0,0 +1,57 @@ +/* + * Copyright 2025 New Vector 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 { useCallback, useEffect, useState } from "react"; + +import type { Room } from "matrix-js-sdk/src/matrix"; +import { type MessagePreview, MessagePreviewStore } from "../../../stores/room-list/MessagePreviewStore"; +import { useEventEmitter } from "../../../hooks/useEventEmitter"; + +interface MessagePreviewViewState { + /** + * A string representation of the message preview if available. + */ + message?: string; +} + +/** + * View model for rendering a message preview for a given room list item. + * @param room The room for which we're rendering the message preview. + * @see {@link MessagePreviewViewState} for what this view model returns. + */ +export function useMessagePreviewViewModel(room: Room): MessagePreviewViewState { + const [messagePreview, setMessagePreview] = useState(null); + + const updatePreview = useCallback(async (): Promise => { + /** + * The second argument to getPreviewForRoom is a tag id which doesn't really make + * much sense within the context of the new room list. We can pass an empty string + * to match all tags for now but we should remember to actually change the implementation + * in the store once we remove the legacy room list. + */ + const newPreview = await MessagePreviewStore.instance.getPreviewForRoom(room, ""); + setMessagePreview(newPreview); + }, [room]); + + /** + * Update when the message preview has changed for this room. + */ + useEventEmitter(MessagePreviewStore.instance, MessagePreviewStore.getPreviewChangedEventName(room), () => { + updatePreview(); + }); + + /** + * Do an initial fetch of the message preview. + */ + useEffect(() => { + updatePreview(); + }, [updatePreview]); + + return { + message: messagePreview?.text, + }; +} diff --git a/test/unit-tests/components/viewmodels/roomlist/MessagePreviewViewModel-test.tsx b/test/unit-tests/components/viewmodels/roomlist/MessagePreviewViewModel-test.tsx new file mode 100644 index 0000000000..6c5b121022 --- /dev/null +++ b/test/unit-tests/components/viewmodels/roomlist/MessagePreviewViewModel-test.tsx @@ -0,0 +1,58 @@ +/* + * Copyright 2025 New Vector 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 { renderHook, waitFor } from "jest-matrix-react"; +import { type Room } from "matrix-js-sdk/src/matrix"; + +import { createTestClient, mkStubRoom } from "../../../../test-utils"; +import { type MessagePreview, MessagePreviewStore } from "../../../../../src/stores/room-list/MessagePreviewStore"; +import { useMessagePreviewViewModel } from "../../../../../src/components/viewmodels/roomlist/MessagePreviewViewModel"; + +describe("MessagePreviewViewModel", () => { + let room: Room; + + beforeEach(() => { + const matrixClient = createTestClient(); + room = mkStubRoom("roomId", "roomName", matrixClient); + }); + + it("should do an initial fetch of the message preview", async () => { + // Mock the store to return some text. + jest.spyOn(MessagePreviewStore.instance, "getPreviewForRoom").mockImplementation(async (room) => { + return { text: "Hello world!" } as MessagePreview; + }); + + const { result: vm } = renderHook(() => useMessagePreviewViewModel(room)); + + // Eventually, vm.message should have the text from the store. + await waitFor(() => { + expect(vm.current.message).toEqual("Hello world!"); + }); + }); + + it("should fetch message preview again on update from store", async () => { + // Mock the store to return the text in variable message. + let message = "Hello World!"; + jest.spyOn(MessagePreviewStore.instance, "getPreviewForRoom").mockImplementation(async (room) => { + return { text: message } as MessagePreview; + }); + jest.spyOn(MessagePreviewStore, "getPreviewChangedEventName").mockImplementation((room) => { + return "UPDATE"; + }); + + const { result: vm } = renderHook(() => useMessagePreviewViewModel(room)); + + // Let's assume the message changed. + message = "New message!"; + MessagePreviewStore.instance.emit("UPDATE"); + + /// vm.message should be the updated message. + await waitFor(() => { + expect(vm.current.message).toEqual(message); + }); + }); +}); From 55b0b1107ea54d4641cdbb30dac1e5525ffa00ef Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Tue, 18 Mar 2025 06:15:40 +0000 Subject: [PATCH 092/458] [create-pull-request] automated change (#29515) Co-authored-by: t3chguy <2403652+t3chguy@users.noreply.github.com> --- playwright/testcontainers/synapse.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright/testcontainers/synapse.ts b/playwright/testcontainers/synapse.ts index 2e841604be..f9ea2cd1c7 100644 --- a/playwright/testcontainers/synapse.ts +++ b/playwright/testcontainers/synapse.ts @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. import { SynapseContainer as BaseSynapseContainer } from "@element-hq/element-web-playwright-common/lib/testcontainers"; -const TAG = "develop@sha256:2ea87d45fc7ff3327c671b3b4447e6b2032d4f5ca07d62d8aef0d900e105c2f4"; +const TAG = "develop@sha256:65a8084668f7b468310cf4e1f29ac6987439ab3f4cb5608d6e02ef0acb819b67"; /** * SynapseContainer which freezes the docker digest to stabilise tests, From 7de54a385ebcff7af8e2ad36a605788591fe24c4 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Tue, 18 Mar 2025 11:02:33 +0100 Subject: [PATCH 093/458] New room list: add empty state (#29512) * refactor: extract room creation and right verification * refactor: update `RoomListHeaderViewModel` to use utils * feat(room list filter): add filter key to `PrimaryFilter` model * feat(room list filter): return active primary filter * feat(room list): add create room action and rights verification * test: update room list tests * feat(empty room list): add empty room list * test(empty room list): add empty room list tests * feat(room list): use empty room list in `RoomListView` * test(room list panel): update tests * test(e2e): add e2e tests for empty room list * test(e2e): update room list header snapshot --- .../room-list-filter-sort.spec.ts | 153 ++++++++----- .../Favourite-empty-room-list-linux.png | Bin 0 -> 9457 bytes .../People-empty-room-list-linux.png | Bin 0 -> 10337 bytes .../Rooms-empty-room-list-linux.png | Bin 0 -> 7703 bytes .../default-empty-room-list-linux.png | Bin 0 -> 13284 bytes .../room-panel-empty-room-list-linux.png | Bin 0 -> 24596 bytes .../unread-empty-room-list-linux.png | Bin 0 -> 8124 bytes .../room-list-header-space-menu-linux.png | Bin 11343 -> 11376 bytes res/css/_components.pcss | 1 + .../rooms/RoomListPanel/_EmptyRoomList.pcss | 33 +++ .../roomlist/RoomListHeaderViewModel.tsx | 24 +-- .../viewmodels/roomlist/RoomListViewModel.tsx | 52 ++++- .../viewmodels/roomlist/useFilteredRooms.tsx | 12 +- src/components/viewmodels/roomlist/utils.ts | 35 ++- .../rooms/RoomListPanel/EmptyRoomList.tsx | 149 +++++++++++++ .../rooms/RoomListPanel/RoomListView.tsx | 5 +- src/i18n/strings/en_EN.json | 13 ++ .../roomlist/RoomListHeaderViewModel-test.tsx | 43 ++-- .../roomlist/RoomListViewModel-test.tsx | 49 +++++ .../viewmodels/roomlist/utils-test.ts | 69 ++++++ .../RoomListPanel/EmptyRoomList-test.tsx | 93 ++++++++ .../rooms/RoomListPanel/RoomList-test.tsx | 3 + .../RoomListPrimaryFilters-test.tsx | 8 +- .../rooms/RoomListPanel/RoomListView-test.tsx | 61 ++++++ .../__snapshots__/EmptyRoomList-test.tsx.snap | 204 ++++++++++++++++++ .../__snapshots__/RoomListPanel-test.tsx.snap | 139 +++++++----- 26 files changed, 991 insertions(+), 155 deletions(-) create mode 100644 playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Favourite-empty-room-list-linux.png create mode 100644 playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/People-empty-room-list-linux.png create mode 100644 playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Rooms-empty-room-list-linux.png create mode 100644 playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/default-empty-room-list-linux.png create mode 100644 playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/room-panel-empty-room-list-linux.png create mode 100644 playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/unread-empty-room-list-linux.png create mode 100644 res/css/views/rooms/RoomListPanel/_EmptyRoomList.pcss create mode 100644 src/components/views/rooms/RoomListPanel/EmptyRoomList.tsx create mode 100644 test/unit-tests/components/viewmodels/roomlist/utils-test.ts create mode 100644 test/unit-tests/components/views/rooms/RoomListPanel/EmptyRoomList-test.tsx create mode 100644 test/unit-tests/components/views/rooms/RoomListPanel/RoomListView-test.tsx create mode 100644 test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/EmptyRoomList-test.tsx.snap diff --git a/playwright/e2e/left-panel/room-list-panel/room-list-filter-sort.spec.ts b/playwright/e2e/left-panel/room-list-panel/room-list-filter-sort.spec.ts index 59f5a2fcab..bb87f90f19 100644 --- a/playwright/e2e/left-panel/room-list-panel/room-list-filter-sort.spec.ts +++ b/playwright/e2e/left-panel/room-list-panel/room-list-filter-sort.spec.ts @@ -18,14 +18,6 @@ test.describe("Room list filters and sort", () => { labsFlags: ["feature_new_room_list"], }); - /** - * Get the room list - * @param page - */ - function getRoomList(page: Page) { - return page.getByTestId("room-list"); - } - function getPrimaryFilters(page: Page) { return page.getByRole("listbox", { name: "Room list filters" }); } @@ -33,56 +25,113 @@ test.describe("Room list filters and sort", () => { test.beforeEach(async ({ page, app, bot, user }) => { // The notification toast is displayed above the search section await app.closeNotificationToast(); - - await app.client.createRoom({ name: "empty room" }); - - const unReadDmId = await bot.createRoom({ - name: "unread dm", - invite: [user.userId], - is_direct: true, - }); - await bot.sendMessage(unReadDmId, "I am a robot. Beep."); - - const unReadRoomId = await app.client.createRoom({ name: "unread room" }); - await app.client.inviteUser(unReadRoomId, bot.credentials.userId); - await bot.joinRoom(unReadRoomId); - await bot.sendMessage(unReadRoomId, "I am a robot. Beep."); - - const favouriteId = await app.client.createRoom({ name: "favourite room" }); - await app.client.evaluate(async (client, favouriteId) => { - await client.setRoomTag(favouriteId, "m.favourite", { order: 0.5 }); - }, favouriteId); }); - test("should filter the list (with primary filters)", { tag: "@screenshot" }, async ({ page, app, user }) => { - const roomList = getRoomList(page); - const primaryFilters = getPrimaryFilters(page); - - const allFilters = await primaryFilters.locator("option").all(); - for (const filter of allFilters) { - expect(await filter.getAttribute("aria-selected")).toBe("false"); + test.describe("Room list", () => { + /** + * Get the room list + * @param page + */ + function getRoomList(page: Page) { + return page.getByTestId("room-list"); } - await expect(primaryFilters).toMatchScreenshot("unselected-primary-filters.png"); - await primaryFilters.getByRole("option", { name: "Unread" }).click(); - // only one room should be visible - await expect(roomList.getByRole("gridcell", { name: "unread dm" })).toBeVisible(); - await expect(roomList.getByRole("gridcell", { name: "unread room" })).toBeVisible(); - expect(await roomList.locator("role=gridcell").count()).toBe(2); - await expect(primaryFilters).toMatchScreenshot("unread-primary-filters.png"); + test.beforeEach(async ({ page, app, bot, user }) => { + await app.client.createRoom({ name: "empty room" }); - await primaryFilters.getByRole("option", { name: "Favourite" }).click(); - await expect(roomList.getByRole("gridcell", { name: "favourite room" })).toBeVisible(); - expect(await roomList.locator("role=gridcell").count()).toBe(1); + const unReadDmId = await bot.createRoom({ + name: "unread dm", + invite: [user.userId], + is_direct: true, + }); + await bot.sendMessage(unReadDmId, "I am a robot. Beep."); - await primaryFilters.getByRole("option", { name: "People" }).click(); - await expect(roomList.getByRole("gridcell", { name: "unread dm" })).toBeVisible(); - expect(await roomList.locator("role=gridcell").count()).toBe(1); + const unReadRoomId = await app.client.createRoom({ name: "unread room" }); + await app.client.inviteUser(unReadRoomId, bot.credentials.userId); + await bot.joinRoom(unReadRoomId); + await bot.sendMessage(unReadRoomId, "I am a robot. Beep."); - await primaryFilters.getByRole("option", { name: "Rooms" }).click(); - await expect(roomList.getByRole("gridcell", { name: "unread room" })).toBeVisible(); - await expect(roomList.getByRole("gridcell", { name: "favourite room" })).toBeVisible(); - await expect(roomList.getByRole("gridcell", { name: "empty room" })).toBeVisible(); - expect(await roomList.locator("role=gridcell").count()).toBe(3); + const favouriteId = await app.client.createRoom({ name: "favourite room" }); + await app.client.evaluate(async (client, favouriteId) => { + await client.setRoomTag(favouriteId, "m.favourite", { order: 0.5 }); + }, favouriteId); + }); + + test("should filter the list (with primary filters)", { tag: "@screenshot" }, async ({ page, app, user }) => { + const roomList = getRoomList(page); + const primaryFilters = getPrimaryFilters(page); + + const allFilters = await primaryFilters.locator("option").all(); + for (const filter of allFilters) { + expect(await filter.getAttribute("aria-selected")).toBe("false"); + } + await expect(primaryFilters).toMatchScreenshot("unselected-primary-filters.png"); + + await primaryFilters.getByRole("option", { name: "Unread" }).click(); + // only one room should be visible + await expect(roomList.getByRole("gridcell", { name: "unread dm" })).toBeVisible(); + await expect(roomList.getByRole("gridcell", { name: "unread room" })).toBeVisible(); + expect(await roomList.locator("role=gridcell").count()).toBe(2); + await expect(primaryFilters).toMatchScreenshot("unread-primary-filters.png"); + + await primaryFilters.getByRole("option", { name: "Favourite" }).click(); + await expect(roomList.getByRole("gridcell", { name: "favourite room" })).toBeVisible(); + expect(await roomList.locator("role=gridcell").count()).toBe(1); + + await primaryFilters.getByRole("option", { name: "People" }).click(); + await expect(roomList.getByRole("gridcell", { name: "unread dm" })).toBeVisible(); + expect(await roomList.locator("role=gridcell").count()).toBe(1); + + await primaryFilters.getByRole("option", { name: "Rooms" }).click(); + await expect(roomList.getByRole("gridcell", { name: "unread room" })).toBeVisible(); + await expect(roomList.getByRole("gridcell", { name: "favourite room" })).toBeVisible(); + await expect(roomList.getByRole("gridcell", { name: "empty room" })).toBeVisible(); + expect(await roomList.locator("role=gridcell").count()).toBe(3); + }); + }); + + test.describe("Empty room list", () => { + /** + * Get the empty state + * @param page + */ + function getEmptyRoomList(page: Page) { + return page.getByTestId("empty-room-list"); + } + + test( + "should render the default placeholder when there is no filter", + { tag: "@screenshot" }, + async ({ page, app, user }) => { + const emptyRoomList = getEmptyRoomList(page); + await expect(emptyRoomList).toMatchScreenshot("default-empty-room-list.png"); + await expect(page.getByTestId("room-list-panel")).toMatchScreenshot("room-panel-empty-room-list.png"); + }, + ); + + test("should render the placeholder for unread filter", { tag: "@screenshot" }, async ({ page, app, user }) => { + const primaryFilters = getPrimaryFilters(page); + await primaryFilters.getByRole("option", { name: "Unread" }).click(); + + const emptyRoomList = getEmptyRoomList(page); + await expect(emptyRoomList).toMatchScreenshot("unread-empty-room-list.png"); + + await emptyRoomList.getByRole("button", { name: "show all chats" }).click(); + await expect(primaryFilters.getByRole("option", { name: "Unread" })).not.toBeChecked(); + }); + + ["People", "Rooms", "Favourite"].forEach((filter) => { + test( + `should render the placeholder for ${filter} filter`, + { tag: "@screenshot" }, + async ({ page, app, user }) => { + const primaryFilters = getPrimaryFilters(page); + await primaryFilters.getByRole("option", { name: filter }).click(); + + const emptyRoomList = getEmptyRoomList(page); + await expect(emptyRoomList).toMatchScreenshot(`${filter}-empty-room-list.png`); + }, + ); + }); }); }); diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Favourite-empty-room-list-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Favourite-empty-room-list-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..8cf4a3c97b3343d8e769223e3eb2f06e46d28876 GIT binary patch literal 9457 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 T&am$_gMgg0qExkn@%R4+qhk^T literal 0 HcmV?d00001 diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Rooms-empty-room-list-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Rooms-empty-room-list-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..e01564eeb402247b7f882d96436fdbefb868be48 GIT binary patch literal 7703 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 H=Ar)sz0fn7 literal 0 HcmV?d00001 diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/default-empty-room-list-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/default-empty-room-list-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..45d2a775ea0a53a0d381139b79707dd3c5e27613 GIT binary patch literal 13284 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 literal 0 HcmV?d00001 diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/unread-empty-room-list-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/unread-empty-room-list-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..94b09ac14f5fad1a0127f0d994bd0a84d07463e3 GIT binary patch literal 8124 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 Ay#N3J literal 0 HcmV?d00001 diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-header.spec.ts/room-list-header-space-menu-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-header.spec.ts/room-list-header-space-menu-linux.png index d2934c2a7695a9031a69ceee4d8a25f2a124e28d..49cf6ef08afc0993c5a46043b7307d9c0c799004 100644 GIT binary patch literal 11376 zcmch7byOT*w`BzqNbukmECjcp!3pl}?rs4ZcL`}E&=4$G@Zjza!Gi=1u8q4pQ@{7e z%r|Skd2iONSyQX2W>r^p*R6ZbzI*R;pvsC;=qSV}005xNNQ84@_a;b2=J;Mfo03n;*;#KfIdX<$ZLQ1>v;o0%oCqY72Ih)ZtcyW1DysJ_i z=GIaw=T_wFm(KwJDvkgUwy<>&I5!9=l9$KKkFK6x`#uZ&@kD`jjA9;#5GEc+yRm_X zmz3bsSedq83iEkShz5uprmLHm(Gx8Vk!Lq zIgAKvgi6zS8|ao5{O9?X1J|3p>9_Q}^WIy&9m$ z)8L9wf05W4U7tjfp5Jfjik+En3E#ZBboo6TMXUI7a?*J47BA$p_#jbamb{jR3JU|h zS@oUwY}!m7oPl95A_B}f-n6tSIu1a@Mj}C(Zr7rEh@m(|UPH{!z~Bw@3lv^v4%&Bu z#W~e-a$=Fq-LH+Zeqjo>R~ z1>fjf2>88s#7bW*;I~SgG=z$Nsik2e;F*?o&Y94?D!JVHwBgkhQVOxI2yk`X>#?in zZ*H=9i1;W*1&@;WMyqRUC*+l3sG)~U{iC+F+ath;b<*Mhm|m^Q+*auG_S2JhnB zlCHnf0mG*^0KgKXrK%}I6VKP&#B1+p=ueqBig|ifS4{?A?P8!~$e*wtc5o<{8$57e z66?KLJ#q1DSvY8rf+ui|e62g4p$ZV94+-lw9ae~*V0S$=YE6_5Y!UeL``6FPLZU`3 zSdp=bfKFZAv{>YG7cM zjW7x!jEa`FZ|~@63!S9EYOz1x>uQ) z<<&T$y#mIT{&2B% z(84zK=H^}?1R;c}YU0&HLm6b0K|kt}nLMkWW#+mB_+-x`}#5Soekap55W9e8Sn}zz ziet#p_S%z|my|dp=uuv#kav7kJF{c`VhayfP|1f9A9~=xygEAc7^M74)75VN;BPph zuYYWN{RN$?r|KnU=vo=pZJ(^{a8SY8{|vqV7MnK!0HW}wTM%vgND_Ps#hrwraxaOC zB8rF`7(@SSIRCfb`LB5YZ%;69Q8)kCSzNuv0sxz%sb*$o%=05zuf;7pZEb88>!13z zxApp`NO&9-Q`mQknNySHxpW*5h(DTFFz%BRe(>D>5?sSG z@b!jV2p$d&Pw)KER=}G>aza7^+~hRerwgsr_D5S+7uEZQA03a6kK_S-AA09mxi2$t z(^12^TY8_5qrq29E417HW zu1waPU(M&{=iMPcf9udiqv$s=d9IUc?dX`o>E*5LYzt zKVsW+`@oAJkIyK2uzj#H-dy*Ncw->~xX zVjY%O;C6^QJw5F(W_z0A2wB}*7xWlmdi%Ef``jFO!+U!>wsv;QjW{{dYWhv)u%Ncb z)wk`ImThA*Gs`XXgQKGakv$k_$K*oZZV$J^;GOfOZ}Logbl!V?{*0vBF4g^#$Egz= z(ZB{}#D1v>9f(a$A2H?i&lU%eLMkikz6&z0)i1|z@$g8M8gZN}U_nFc>gtk{8;~){ zxVX5`(a?T!q&!D>M$eiapPCdKtFEJgN4QN+Mm9G+?Y?_Xgbg*fvP%7)NLFjY0T{2| zOEWSK@q3u6s!l8{>L(;594Ff2tw z=c^zj7?IIwJmHE3%U{|wl#d68hQz3`dwLgH>F7AeW>N*bOns#K@`kixn}dT9jPUUD za&x^r8~*H^H+z`X1+>qPkDK~$=p!PAB>!zlThM1!QhMAEM4n3JY)MkNQ+q$4PZC0DzxAbvQMf5bbjl9|u4G z%DM7RnV@@BUESAC<*%(C%fBZ#ip#l+IZ~)#UnJE8+^&toGytSBS_My z8{%oh5P|0iA7yNG^z`mFnT?#5PA^ubb(o}BV(t_xw%wY(7crncDVA9tJop*x# z{FRRs@kRs$^K-KRfLo|;Ue+@-@cPwrhJ*-Gf&QT(Icn@6<+15$Lp3!$9i1K*7xD#s zn6$N{&FjdXw`IFj47G0N7?C}@ySv-FyVrNo294eZqNb{zo-bWy?y7%iGqw5AZZ;qA z!=d6&Ks(eVD@>yNsP`8-cWn3iazLgy6=k}jQN4RYV+xTADiY#P^`fe{Q(C0Uk@p?* zfF=Z(WrWoEyyZ!IbKe>O8lPaxV6#( zf-#7n8;M`R?GmFX7(vw|e%P`gH~+*_01$C7FjyM$wfM{)CO`PwH!HiV!R;i*&&U09 zczB#Nb)_~)C^R(w%uEc8vi>YA6&nG_dW40%_r-mD!ohC^0u^(>B=GWX0>kYB6AdJ2 zN(8@1LeK9{EriCaMJS}@hPDqZVyY@)<4MMiSlM5nzVIcnvr|&?z{KPsRscuAKu_;C zTl_)bahxMDAK8k=S$U#`}TWMp8V`L!QT%HM6b+kKtasrCM?jt{+s@w5;(cX6p@ zO)V>=7*rPzS1xXDKF{kULvC;e>FMcj9z&$;G|RQ?+};Nrw^v^%jzTUjc(R?myc_PW zJzZ}PD)nla(vte>7n#Q6DgZ66@93+Q*OI)m7y(`FAX z;R`jFyCt#{o80Pfrbvi%A;}t#X~^+1VR-NRUt@TJXig*TvFOhiA|Hm9WX*(e~Wk z+;DU89L=>JrCU;F#e+=b;dB`NO_=C=4h}HzsIXo_AQ$Vs;mihgal@8RDQ4Gwah=4u zqZtJN;J?tG)M*R=mxoKR*w}AzahHnKElD>MD=W|hXyz~%$iNONKHWo@)3Tu^SxsKD(wyDFA zZk?}&wqQgD>+lUOT?3^5(qJSf=fkY$CT!^vA)hmH| zTq#qCm6bJ9IKa?2(8zQ=zFW#)Lp8g(xe*^9FCj7EE!4`@0 z?OPfemQCR)a?Z)A`ha@$#)Uq3+Y=VF#x(>AJpqFsqGWB|H)I#e&zf3Q-A7#9{52{aH?d+p84&hiqXP0yy(1}u|Vzyq{UWMnb*2Kr(w6WRYc$?qqt)XsUP;I|MWnuBo zaUGc*9auT_?0J`Wae=-XpWo`|qo!7^Oc&Z2_i7dw%b0y?Bwg@beA#2c72{ueMnIp9mRiKn&`?UMIlD^L$Y^=Gmlzlu8`D@~Bb-0R*48WA)&X0NOeylZji&VQ*5^1- zag-E&UCqZ2lz%!q9rcw(e0{q{(tRvP(*7(j2V6PY%h=4uAYUR~-}z<#q~&x|McNyj z+S99ZL=eEeZmtVTYA9%cbO0DzSXh`Fzoh29*(_~lJwr9zB)~eprdOjG@ZNX| z6V1B5j`BKYTk0Q+g$jE-#=tv<%!u|`!X4~WvgT{r0g&E8zi{Z7 z@b4CRjAZKZK(KP@ML|V>g^CWlF#gewd0mPA?|s1kcgXo4R^!f0-!3`f-}a}z>pmzL zjG2Z`g#VD7?dM3hPO~j0&Ye2jM+$?+ufn=Ouq-zsz|5=EW-2Qz74%kX4M%VId)^YiQ6!Vba78fWdELLjcGKhFc(aj!zwd($wDVqe?YyE|(uZot_VB>@k%d2)6jL=r{b@I)ha)e!3$2onG(! zEg^koyAm1mjg6h1RPR&g5&$eNE($-ojoJOy7DQAd;3*gMx$=NS?-!}69-?TK>pmW@ z=6w5Bb5-oydXSFfUdKI@$P(um`K7I`En~@$FZ%Oj%=Z4ith_I~*{wRr8Jn;lj#=9m zn;;%@lLM#(Bcr3N*ALs^a4x;hHt#R@Rzt%5VPAUeX3DrZxOR4S7B7b{L3FFO98or5 z!^V!U^Q$(Xz>@z?c&V7F&2)*wJU=(@w9r6AMrLclwF_c~Fu6cUdHK=mDn5>n(>%}o zg&SnL#BlcS_2xBnqOfoW6hln3v{#i&j!R9h_rD5PJ_YSfm$5K1w!1$dg^3zAn$Gq! z$5UEVynHTdzkh&;?C+2JPfU$>oZK z5$fXRIWx{4hf4i738o0Pp(Mr-2WL^KwTP#75=!YoZ4Bj!*XI`f{u1_Pw&#iFEx3cExFF`kI=T$UY={dlR#>5)>fQuT-=UN$PPAsiC%5)qXd)$3|VNN8wi7#U&mp5sFwiv_3v5o&C+%H%Lqs)ycNj3sFbtlz(X$BJcs zq=LmN7L@BX4=((+cV<*)(9n^&X%z~eJALEgd4ES+3jS>RK#R+cJ}BWF9hYkN{?IC= z>ol3GOx|*VHjB|cHb%_r;{*%^l|Rs)@$uWq?@OS;E|xBnr&_5U70)4;A-!>SqoXs6 zqW%IU?B2Zsd_@04IDxgWjEtrIG*Ul5KdO`VUheZmC$)dkTO<}HEZ9&mc#DdPy1PY% zr%8eW%gddtea|dM_EW%wadfoNX>@VWbXU~!xSH?zBAM7es>PR|Pm|LsP;L-IgAJXY zo^EXPnsHhB7WC{fl0av^ZSkvb zUbW=~icZwMfjR?ZzOFQ%hUSV)K)`>EGf3nmYI=p`g)CqC($dn2yPTllVmER?lk>@G zkDS)v;9!b;ZLOWA#7OGHqdnhwVhAWc|1+sXz8@`{=eUF`k*8X2*!*d2!^X?&X11CN z%<+#j@qawC9;vHtWsz@sdxf3v`^czzwD`teCM3r(!;y0nG&IQXd-L=2FU>Gvhm3Em zL*v-B=X7f~vIM6yG?-5SyQO<&G$ORm?9i$%gn^skR zx&l|QRp*APIMGUNb4!!>3>Yt~i^_PsInWV&bLM_{tte^sSu&9IdnE=LpUdIB1YdNo zF$mak0ASX4iv@j-4c*w;VZo1#&!8^;$+pcomr}ijL4KnVq41?=?L6u?mt792c3IhB zPQCr2rnWXUOuEhduhGwBUqL3UDE-sdwt=mOAOa zYcWUt4?}ZNsg&gIJ-B2=;a|!u3llvd**kl{(s+9ME6Yig4%e{F#i6^m6h*x#=8Dk50v;9h8x-&gQPJpV=fZWS z?~BGc*prxzrv6^{_E|+`Wqq`efRk^rU_r(8^hnGN4l!kAWKc6XA;y76+tx8Xrpt|> zDxF?jJXk%UQ)K6a++6{_OqZVMjwDpFXK7 zE5~{tkMA5E#Y8qQ&-6W*93B425qt)`dGp3@#vuyY$^#aNGBV0={nnftPC7rXhlD5- z9y!PPYgwC_2?~AqGHjXoG#dN>stGW9Y)x#eOl%0aKiQhD;cQ%jHYbRCv9Twbnwc<$ z=cfcr_zymfPI5ykqnYo>c<))Up`nwlHy8D0)s|A~?Qw65O!Tt2dSP7QbSGxBe3SK@HHD?*`4|6VTpI)56zy!;vx{x$04q`s!k zsM)c5$q#w|jX^9yV^fo*!6Xe>^vDP*3=la6p-4!3WqXtwUUs}wy#+oh-`jm&!1%W{ zs}{jlXlU*W)Ff^$u9F*Iq0HsUNw+P>sM6Btte{R1|3GyO!dRxD($w_0s4O?y3(!Wi zvx|g6eU4XD)YK+AIs*CPp(WZ;C5fs3U##-5o0Y>?;oZ>CY-G%JP#kM$YFu5Ov#S$^ z;8@AY?cE7l+gf|xMX9K13=jK&#Hq}=!5pvS>MSupQW zQ4Ig=)WpWV5~o^S&FKSk%P@nC3btL4i3vKz9bscEU(S~V}EzLfgtQg zi4OPC|GXiq@&+t{P(t35kdTOV7lbOL-EI!21_cGp%{66Y7(&HC!{!lkTv6IOF;Ote z58~a3-u3~Bvii9$73}!t9>hJ+AZuxCdOUxjjsW!r~`UOob% zS;seLlSCX_)_cUDVEL}|*Z#?WCN-a?Qu`iCmLaTE>*2=hyTKDALIIOrYKstfZKtOx zDyj-mP!Jgljs3@ciU!A%lVdi$-@kHV0tzq*iE=@yJ4qJpg{39XyZ)Z4moN3ZuA)Xk zT6%Z)FoUGg8GMlb{z2fwKk=-sg|s~S(=Tc2z}m1ZL01wGvG6)Ejz%&+m;;4vYBC`r zz%5?d?D1q`A@Qy%|FL@GIa!RAsbxY&#)%FI6-=5VUn!j%;vyzyW~+PK>VtXt;QXUK z!1zy>GytT?SF-Vl?e6{`+Vi8#Zr$)tHZ@O1{p8`@pm*%!-Be%iVQyj7C#=}w3)l7W z>AO6b7c%g)+UA^0K|xW^HAMXnvjmQMT?>Jvr>C=waBREr0bqS@pl7zQ;+P8vEc&ss zx87=Z)mAuR)%bzGQv0jFnIEVLh3s5RgPERBNaE9;-Li%w zs2&`niT3d0>dKf3Mi|nGfzJZg;XDPNdEtK`b)5c9gul5tpp*&Uguf9w9jaWXbw8SW zO@_~YPF2HBdr&l>$OHtIwGHg^p85EI#fP_MZ-I`{Cq8u*6&+2@$Fp_}^rgRx6C8H# zxfwz9K*v;%*S4OFf?U0;vth0GgRw^cfA{!dA^=b^yZ>#Hb0e^|u8if#qK#cFMU=+E zvQ1gVM8D~}uT7A@yIV|#8e8>X>p+x8I7zDPooVd@X zeg51Fib&8}92y*i=`}30fy#;+8!DUU--HbIf^|GSp|`kROvK85r1rW2wLLNt5&-D4 zls7bp)8SH#X6NSO0$8>F!&5^9Wk#*yS#;(W7VT=^ca>-yD1T2eK1Yt(*xY<4?B{;_ zd-h@vq-2c(E}d&WSL930PtFyyb6kwi09wT~e-K-dLO!{I9b zzxEhVYS1C9bvi1mY!mA5!}4N1qg6oTzv?R-y{(Wk%-G)C4el`|r=`x%&FA9eo|~U9 z)o!B}V0s?Yx3#eeT8W$ik1btY*^FA{U>&Ylt27xDo1hKNHfHBw*Y15Wm)=}CH>az} zq-kSgV;tBX1iG$m8I>><(52<~Fxw*`ezWh8GhJR=!B#M_<51O zG8+g8yNt}gZ~#~K+S-J~#LcrU`hkJb2sznWPOi6G!v-}JsxmTA#R9()WMTza-}+*s zE6;oS+0M?Tk!j20qSjUiE32&)9TWWpKfZK)tQ9G0>>FQy(Y1Imj6trjD^C*%|I)W^ zwtko{93Ug7);-meS5v~o*0DT2-TSArtu1Rc#&s*lY01&nb`Go75uBpXRn)|Dt1u8N zi;8qX=gs$m5SPnMvvT(yLZK_IJfXPivk6hF~4hMTY{5^ak!B zm8d5xyXzdYhnOqODE{aR8>nk;)(aAC40tkel^ZHa;UGjqI<;8>A)b?qGdLvVFDZr# z3Qc%OWQ$y3bF(80bjb>=Ew}B}a%;Whwsz`Fp8djms1t z*d5_ukn@1-AGauu`Y`n_-+br?y9C(U;N-*_3IE_Vh_(@;7MfZ-6up;Z)Y6|nVFPAU z)iqAYXk+fhd9W_n+vgL7#vdxl za?SYWe{D$oFLg-JyOk3}-yN;hpdTJ+$1k2EkQIwie!3MpDrmwwf0ZUwhL94P7Ypb0 zYgr{jJHP7ObjG8jE=UD&5>|$zK z#+JDqCF~3Ag1!>Ey^5yJOQ@|yA6DeHB#e44g9o+> zA_mSRKU~WsNhUWIks>AA1P@9ocJ85|;fv+P7NVHHKuM7%97#z0(f<8eTi`^Wg=@pU zP?};qfYfpyY2+iQNIt;ZaU8NF9I`jh=KF`zh0#J2oiQKaIIVA7z{E!VIrj_MYf3GUjEzNN;o=O zH*4s4FCesBdmM`NnVO1O{r!s%S12i_$hfeepykBAK6qEMzP#TmhjD;qdb(e{zrgis zo}h8GD&q@~Y`z-k_iyC3_wz$r@T;@ChR0Te%=c6;urC>?!M|kRvZxJMAe%WEeR9!l ztQWS=%Vl%rKnXzr{aKU8M+vdDv-G;YG^^Ahf#g8TBy-iiOLqPc!`VFv<-oqWa`C(O z&RA(hLGgt`FKbG7a3iK?7M!T0h=Sj9{$Q)pQ8V~dBAcH~dVmT4lWm$?3XPo_Vk;?f zuc_tc8xQd7#f_p9M9!~E>~*(XRDF$4qC6Y}7j6~|Sbk~~JN_LVN-jH7{b1&-?U&3f zi^4ou^T`RT^-&^1GSUJ)ip&vTdwNkn1q*)qYkg#PGOr#mEVs!R1pRAxv^z!)R2jhIh%#0Oh;tyy~<8&97H~!&JyC{ML9dm zFH5K9$hO_^iwnz>rcx*QB#2~TZDN1%u3%eh^ZZ~tF|{e|`TAM1tl0kMv9os8vu;V2 zLB=m_^f;I8jxlNdcaH-BMfMP0+ds;B}T#K_E^AfK>83s_nRG=G&G_+NT*2)P=)I-K(aJZOE&LfYG+I<)dt+xWN45eDW;XURSw*?B zBIu_aCK%a~f6L0=pgftf^W;X&;m)n7Xlo)t!JA%GTYIjp$H)&M)Em(~s`(`)#RQO_ zE&>6f>8slLTXuF(dHF~XNCeB7rxOvRs`rTwH^NUK9X4o3uf8&`YHX|`1D2N?8&n$U zxAJn|x3LY2h4b_CcA9XiF)^|;X=|H*3w?3<*;gf_)j;dh%1T$`{U4m>Tpm|>?_X<0 zhszHQ&98kPAA!j)95q~b^)Y>mux}Ub_gX!kvJigdYHoHS=9{{1;Y><^JHEW^`!qNb zJIe0UZZ`g_U%(uUCp+7;7?)|KF*A$6WaDUgA9H16;~){3Z&OrJ(lcFD1YN(pn&oeC zvbT=Aa@W+#DISL;4QKfrcy`{h@N*GG*U`KEEG!96!v!d)ADZbK1+sRVxab$EU&WGVSolw4lAygYja&0C%r z6>={X5B|b{eai1F&R9|E;!+phPH=lLK*UN$U~lV`nh8mJK8I+a;o->=SkcD-v(_sA zPKpJ6iosU579Nvt2@xP0T^vLV??M16Mq}h?vmYMrv$L0Z$0vHgw;e$s^^cf7cocD6 zCY+HP%oK4u@ayY~8>V97Ys!LCWJD4r@X*#LMvH8n`K~=W7RDmzI0DE5_LXG_2c&uf z)u6&Iu-*bT>aO2rRV$*R{Tyvu*Z-`&dF79HM8x|LO${Vabj&61G%=Fb`ey-qmW!I< z^sk+No9?7V$=S%+3S?=Oebe={K9N)4{;DY4*y~lxQ&Y}tHCVez?NCJk)l>`L`Xi*2 zj!(|AD;P%Q5q@u+0)q~I-@kr|2=ab>L=L4Jlz)c| zLj=o?PfTE(!s)S3K_D`MzG>Bv!t{?4S0+q9WIboKfa^dYQWkVv@XdDXqMo8C`O)FB zf0ZP+sXun8M6U^_yJh|)Y|xyoY*vc^^d;x7T9uAjQAJeWItWB(iT`RqWqO8aAZ{u` zGN&rLO@q0|tg1h-@>J6{z&xQmmLT|xS55uE2uI5`XXxD8+W7qC>4Z9^^L5oz8x8A7 z<__WPG%pe9uBcz;+D(&>)24-mS;&(a3>7`3Cz*uQu80c+D(FRVK5}BTfYm~LTx=U* zu=vo%SKN-3WJld*a?2~>Oe#De(4c&c?VCQo2G}4=2?B_Qb$Fk|NL<$6!R8ks7yJ0~ zv<@pl+?A`6|Ia&EQTO1oMpSXIL)YZ8MaQ8nFoaQq@7b#TPOODoxuW>^ObIl-#nADr zt?e}h?`{okQqtX$!ji|^3LIJ_MK!zFtU?|VLqhx{^5@5#7)VcgzZ@;@84X*M0!wUG z+is_8GA{2gR;Iul?)Z}GfB$J@1B_1H!5!~b<2{*Oc*j0&3OtqS)g8W+c;0R5`yA(B*h zNm3dKC23&!_TT^ezs&RhasU7Fg3T5Uiw_+`Q`VyhpzVCH-(!<~!QWFm)qTW{XDg}kR?HLkO`h0(o0 zd`rI_R#<PSHrg4Qj5qA3 zroJWq&3WF~5gFAiy4d&J_e{3GbJ2%_norB%f7?^Q(LVn(KAn?Kps2n5`JNIh`syq$ zuAS!N4mEhUvuEgHo5RW0G3}kp*R(WyJH5N~BIJPqrpoU1HA7&DHRvmh+p)4ZrDVo* zWX1%jIBD5LH&*y;_lOaK-^!+)zEU^h=M9*oPfgROS574$!__iW4_Q{z(b?QOs<(p+ zVTIEyRf?mAcj;ESI=(lN)%1WHx5G_onRsQc%uA)BlG^(@R5dkMT5JP0FN;sgLO0is zJ)eyp@`tpqkDj?07`*minpON20h3xkc>mIwy>gvd^zEKvkOP6Lbo@7W&)zTurHOMe z)6no-`(!pY>H>GcS{P9$c(jp5@osuAG>jL?jQl!Bb?t6S8B4oG_6utJ~;}#PWV-Xk^ zhV69x&?9{Z!%JVNv19@L@li&J+Ij%vA`oHpj?P-m4)+@eiY_iMleId*|L}jH##vfi z{QK8wt@-*_adE`hjy-pZBsC5bN5;Jf2Nzc(49d*NNJULuT2^+nS-jS70SgHU(DRkP zyi)>wLB7awa42EzOqIx9inTARMAs*QyWr|sl7Prm!k9)*6x zj*br;=uv9wQ=+0Pd+xpt4$F1UUb_1FBT=d578ZDfLBiL!Zq6JWQc_S1=W%Rkx%1s} zwFF5F-;Gt4uZbiTHUV3DMRvB!-%V!*oeIP27zQ4Tq>=o7Qk)d43!ZaaC4OV3oaJ%wXP$&rt^YwoqcXTWZK@BA0 z>Xc{16B3xOudDlec5`@`{`YTu3~5fGO4`>RGf|P{#0rD7^an-(Mpa$iy^&8`DI{t9 zWnOL`I4@s#i@e>wi|GxMwxr8%XjszIOAW_*`hE#4&ErsojJo<%hOROQgo@g%M4C&C z5mrFY!?4rX+`M#dsqk5VENMv8^-|K&kvt@uBxt8Rv~hvZ*kRIw8z?t0*ks2?@m7D` zev7++zf0Vgn^!I&IKRv)8pgGiJ2}tqphuLM<*vc90u6P zpkJy*T8RWN5D`GXa&pY9?BY{yORG!t)z#H$amhtJsZV;MuIjGNBjuSP)QR7LaI?3w zKXP!qgu{RQQBEa70AZtr(&bw^Iv%C*1vT1UBq8ZrSEVCt%REjO=!Sb}Y5m^;u%Z=5t-Qrk>l>((;@Oq^Jc=K8iZ zKi^tFpt01Tw!FIfO=IYYRrS)sJ1MEWWBTweIVFXiGjGtB#iphf!dobYCUa;y1g@wQ zR63fifusXDCI*{aD8jQPN0xLu(z829A% z@ydN`K!6qj0l!m^mZqjmg??^!c83Y4QM*%<3(xGx2pvEFiQce>g<0;@UbU69)8hHo zq6cY#Vru`fNniK!^t44-H0IT3FCJcA!Oy#e6j(BvnskDKTgR=aCE9GpO%^!dn`i5T zvdn}1gNmNz)AP$yIDGHufP6SX)10$6hP2uFIZoK?=oK0o@KLn-Z>1teTwbW4j*N_m z-Pb;pJeGyzmzG|_wT(H6qNm!kMtl=TEbJPZno13;xjBDRG8vZV<-M~WEuEgOIhb=^ zT+}(4e;Ub)z`;YaoE_e)NJ~}DygRyyP=7=JO(jKS@1L=ZZSCw-KR1gCdmb&cxz#5o zCMG0w0m%XmhjS7QXCsNH3kRJ&geq8CZYdV@rp~bBZjX{ELQ#C5oKDIOo7^7c}Ng!XM%kA9z4)ov$nGwI?>W;c2&%=|43`5)E^qcl%RNl8r7_TSwoL2%~# zv9XSb6|P_Beg?~r+M0PwYYZFHImn$OAtAzOYptr9xZADecE%zxGEuUTeFAnb+5X4O z_Wz1_{#$Om`KEMsw$2BgU};_u*f&P`r#?;N*C3l!=*I89ulRdKMpd-KroK1&j-l~KqoHbeq#+J+wf+6(@&plbp_Rq>Dkym(&FCV zMN{aU&JPc}-`B4Z5tB4ERK}9u_l(W$Sej0RVe0GYFY%Qc*V}eA6>KNMN%;VDcJrW( zB++lGeREV-!OhLH@z<&EQTOqKg1Xxhzdm>QyczbSc zbxuxv-@!GpC^O%&r>`&l&_cwBRiU+op03{f!h)+$kb|CFgq5{@uB^I-wz?bf05w>) zFi4yRH;T_mr_W3f2{g<$tX&ZStWI@pl{8w>`z$%E4mEAdQgwBFT3U&Fd&E4{g>C-2 z8it0|?gJ8(bop>NCeE9}HXlEA^=et#uO0E|w|Lkl+`OadVoXWp zPsS%&l>j(8BR&dv=q_H~;o#<}wuy|)q&TKzc}ESA@5Ti_?OJ;+ZVh6j748(pN#U7S zZx{TXDoIF<#bv#9bS|M#Xj5JuUPyB7R|3uI&)TRW^807*AX_He0;8+o-O#KD%n4@ zS&bzE7&?IHlF$B`2oYCQbaizlA|*@y@uR`K@0ggU;QIQyueUepXJSBmkc!EdXPHP} zi4X?!N_NAxCIBG`Wo(XdYHHHgKl*!DE;IhQnIYx1E(TydqV>#OR*R^0-+Osn+_si&3>DvHlLjs!{ zaO=FchX*Fe#6b2`X3>N**=3^_>s{EBrUgbK0O9QIm!9=cUSyZCDR8;j=p>xc+5mBk z>Vp{CW7dAVkG@cch-u6{s8ABFyQ(K|U@9#&O&q>H&HxTruZ8a0fxbZUd%{Vk z=lEM@K#c~PnvZg%ohDzJnig+d-r}L<7Z)>$it_NX1p);zLwOkZ6&Jy+Y}Gr9oc?2cfTd$LHq!N)TKZ`uk7S>+=gsn%xI-IO-fk z{CCCs;+~;75^?PT_07$Gr=q8~53_ZA!un|tmc*E|i% zd2@?Q99Ml!2De9VOj^~Wf13_#VEtHJ4cXpbA0V;dv&`u&3HkcoX9|0Lpu(oI)OK2H zW%;SlGgm+s^3I*3L&%tS4HC>};v7rK!{G%1Sj*-C|-Y ztVff}drfHR>6{QcCiB;(w%IMYA)*Cl_ic(V#_gZxWoIXh8bN~4G_|%jr z`_t%bMIG_(L77o)PSqK_YNK#+k{gTs0Vl36sHpyc--%o}klVsxe37?gaB#4~pjA3w zO^el7$bZP9pNN$jOhg&v_WVRiNh?D3u%koDFC8>$jcK^D0u&K_BO{zvrVyPJ z#O$n)_n&Yan$m9)*#N<|w`ZY<8yg+pZEaaW-R$Trir^qE_R9o%X%I+kGEJ5C^3uKC_vmh)_dw-2Fm~&3 z^MJ>0Q@>{timc7$~{<19=lR zI;>WC=nBD-xG!HUEC@!vlVXOPTUCA*NdMowDYnC;soBrf)eRF9Q!ekBcX{=<^7B3v&lFyHF^sS*?<;dJ+&&DT*8SrBVp_@b`fN^DIjXeQloUgUMA6?PY(^FQ)iXs@Do0|hL z^~q6;bgttfky7piyK$rELpKxfrRnm}XjkYdXRD5TXFpM&-^rui_R>??EQeE2cWDca zb3%Tm(rlpSK{Pc_9(xN43a&oB1|PAI+a$+x=`;xm0Vkz_X$4N+0w)E4lkDuJ*Ma6d z9)o#aq!+h{J^}ein1soB(`4c*J1PM>9!g3kLmG#XY7bFjqk56auQ?8cj zRnZujQ<-9VHJ?{aJRNmdXUBh=oaG>MaV42TpXe;otEhHqEV6+8#(%EN|E2o-|9*iF z%E4JeAwXGniIewm!y^p{FzhG z`-_DI(DjA^6?&-hRfJ?bIHlHCspiel$cXv$Hk&>=dQ_g;-VVk+55Rex*Q)G)#thV-Cr<6jm#$e2W zHlWd|w!`W6=3?8CzcNV|5&WXQ;qfB4_xMz9+- z!2-Joq)0~QtZSf9J1eW%+T;VPf&yvjFiO2DB2D6ye@K*rga6Ti@Z$V@5iIBYnrBCr zHomo$9L9d_mtRmIqnO^ggPxv24%8@pZGHVEpoEKvF4xx9hHc6X7guisr`8KjY&=}?#Gf!`a@ZLJ^wrR^q3KbJhb2kWQFb^)@w&c(Z72Md0pX8AL$do zP5k1|uI}5Vj6*nArZ@>4hHa6o3xMkyA5Sq7qbJbWYnoRw2P`oFCx7IxTQa&|i01;@ z4-pku{>KVINQXes@#SN)i!5~YD0pZiL)gpoxCOba%<;bcd1A!;@>p~Y)4=2Ua$s}- zkSQC0pa8H1Z*6VITT_Lkio3lXn&1x`tfhwp?0S5a4OV`__rE*3as!Y`9m(fP4co0x z0%feVH>JwU%XLXxCnC12Oe`p{iCh6Ta7`d^#{!@l|A)=J)LK#saUV1gk?7#k$P679 zm(SBzIwd6~#NhW-*zb6GS0ZDo>+5;=xP7l!g%5N+b#-qO3T=T@B0CV)K?VNq=;-L; zQh&1IH$FYxy>r2vqG-`$W>LG`-Mu*oh5q{W<@@)_y1KfA!azWs!@{}(+>VI@egqJ~ za1^Yns?CFiotJH;Yeh*@b4$zN0hp~b0RxR`GL(<-!^S9}3}t3gh)_5KBo!SE&010! zot$!VdHG>!uUaoPm8O&x)l)@)OqmsTtvL&u)Tgoet|;eAC8)lkvaC;DZ|CZ$)7@opPY)fCHsopJt2#cUrVh8>x2ec_3pnooOyQwv zG&qKo%mJFDQglqXU7w!e8tn#j;0=S)$4K=%)aawb{doC&AXGdqqX{{5jr8=i^z`by z2V4P8Q2Bj8t+=MTddlyTDDQE4uUgFZqXGN%Kf=gUM}L>$a?6if6UpCEzhO4mD{FbIcl(fUU;F(6d7LDmBqtjfs=px;5qsya zW^SIV!E9N*z+){H8jW62;mpYFyTv=mVfU1Cb>&&C0r)N4Y_5rr+5j^%S8MG#z$yb` z_xu7qPmL+AucWMO1AaYpS~nPV7|L0lX^8}49*RP>dq-tI=cLm(9@!$hgBA_Qxr4B90#YF5=cl$0N(^aq4n3zkB^TJq3Ah49zmNK zoJ1@x$^D;+^WwGRm`Qz_T2ChuPk`wUNWnuxxvd!)83_reoO^%sS&ohl9hd3?TTVy+ z*xGXAi!2%H@9fkDfl_mF05yEn(63N2 zZEv4DzQ^^7a-*cAKNiKDVGGY<_820e^*1d}#5HCvBHa&vN{f*Kl| zFalYC41lG~&Z1pLT7))WRlRWJkeWjsA^QRZAkFC-_suV@b>-|QQf$4XhrI0V-};nUZ+cmrB(kd)n{hbQ`LIV%F0SMLJ6>H2?2PK9AJ5$8v|&hbub+pKN63j0kEICP^AnCWnyCUaCN`DI)BH<2dl0vD{=nw*%xS` z)7MXH_4AB9yO0tK>-PhTyGY!mtf>S}hKm9%PhR}m0O8~0V&Y|M&90i5m@vJC^#I`n zSoMHLGL$5Bu|2}Z%G%_93#CtJwA(sQ;VDor)}WyYnXS7TN~&0njG3F6As#S;BqpLD zqYx1j1Fx8znoLV4-h@wTyf(hOX+sH+RS1MGL)pvAZOhfC%B6k`KuZ$~jewrv^Qn4` z)h48C-NDh(-MuDDOi4-3N6kPDnp;NB>owYW`-z#E*}dsJ+*egg>+hL&y;Bc8U7>)W zAfWmIrP#gZWOtWHfTbnio;{>E(yBL_j_TaxRd0XLxyGjt7R$nTi7?W9@#?Zjx#ul)n{e7U%=LCqP8QSFZA<{@M~PnZKw$_EDrWjbw_f3maaRbso>&m8zj zK|dgn0KjeoeF2PlD=SeX(BW#c3L_ri-UC_Lvwti&oCB}|O&^;!7?dA9?=Zr<-h#hx zNc2j}R7_ZKhx^)4QeBi|S2;hw?w1KInUg%&Pa`5qiRv)}%jQ{|KuerqW?OpXqUMGH z2?6&(Kh`ACA6Mw|xBIiXrF3sK@I+*nHTSOFLqSegnfzA8ekxWMy!y}czJd9zq%+3 zlS*Xi%<-8lumDPQyMF0XjEBq$DW!UHgEPIn^T&<&3H|k@XQK-0uBWTHq8f*K$G})t zs+m7^>dgwk#G+zGxa&R85c*M+*~a@|cYpo-#*SH@2m>Xm)ZffDM_bi^YZ@setp2Mu zej@!{{~Zevds38z0@{1ez=#Y;F|(m9cE z)KXyiw>aUh`E^;t_} zCr2A_7oSsM%3UQ|>R|bQnr=0?Bjn$1R3<+wYXlkHh>IZ_6(&tbX8;|-AUP>z$#Myk Gum1+lz$GyN diff --git a/res/css/_components.pcss b/res/css/_components.pcss index 1b4dc79296..a3284fb379 100644 --- a/res/css/_components.pcss +++ b/res/css/_components.pcss @@ -270,6 +270,7 @@ @import "./views/right_panel/_VerificationPanel.pcss"; @import "./views/right_panel/_WidgetCard.pcss"; @import "./views/room_settings/_AliasSettings.pcss"; +@import "./views/rooms/RoomListPanel/_EmptyRoomList.pcss"; @import "./views/rooms/RoomListPanel/_RoomList.pcss"; @import "./views/rooms/RoomListPanel/_RoomListHeaderView.pcss"; @import "./views/rooms/RoomListPanel/_RoomListItemMenuView.pcss"; diff --git a/res/css/views/rooms/RoomListPanel/_EmptyRoomList.pcss b/res/css/views/rooms/RoomListPanel/_EmptyRoomList.pcss new file mode 100644 index 0000000000..a0fbfdaea7 --- /dev/null +++ b/res/css/views/rooms/RoomListPanel/_EmptyRoomList.pcss @@ -0,0 +1,33 @@ +/* + * Copyright 2025 New Vector 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. + */ + +.mx_EmptyRoomList_GenericPlaceholder { + align-self: center; + /** It should take 2/3 of the width **/ + width: 66%; + /** It should be positioned at 1/3 of the height **/ + padding-top: 33%; + + .mx_EmptyRoomList_GenericPlaceholder_title { + font: var(--cpd-font-body-lg-semibold); + text-align: center; + } + + .mx_EmptyRoomList_GenericPlaceholder_description { + font: var(--cpd-font-body-sm-regular); + color: var(--cpd-color-text-secondary); + text-align: center; + } + + .mx_EmptyRoomList_DefaultPlaceholder { + margin-top: var(--cpd-space-4x); + } + + button { + width: 100%; + } +} diff --git a/src/components/viewmodels/roomlist/RoomListHeaderViewModel.tsx b/src/components/viewmodels/roomlist/RoomListHeaderViewModel.tsx index 9aa63451f3..8a1fdb1fe7 100644 --- a/src/components/viewmodels/roomlist/RoomListHeaderViewModel.tsx +++ b/src/components/viewmodels/roomlist/RoomListHeaderViewModel.tsx @@ -6,10 +6,8 @@ */ import { useCallback } from "react"; -import { EventTimeline, EventType, JoinRule, type Room, RoomEvent, RoomType } from "matrix-js-sdk/src/matrix"; +import { JoinRule, type Room, RoomEvent, RoomType } from "matrix-js-sdk/src/matrix"; -import { shouldShowComponent } from "../../../customisations/helpers/UIComponents"; -import { UIComponent } from "../../../settings/UIFeature"; import { useFeatureEnabled } from "../../../hooks/useSettings"; import defaultDispatcher from "../../../dispatcher/dispatcher"; import PosthogTrackers from "../../../PosthogTrackers"; @@ -32,6 +30,7 @@ import { } from "../../../utils/space"; import { useMatrixClientContext } from "../../../contexts/MatrixClientContext"; import type { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; +import { createRoom, hasCreateRoomRights } from "./utils"; /** * Hook to get the active space and its title. @@ -128,14 +127,7 @@ export function useRoomListHeaderViewModel(): RoomListHeaderViewState { const { activeSpace, title } = useSpace(); const isSpaceRoom = Boolean(activeSpace); - const canCreateRoomInSpace = Boolean( - activeSpace - ?.getLiveTimeline() - .getState(EventTimeline.FORWARDS) - ?.maySendStateEvent(EventType.RoomAvatar, matrixClient.getSafeUserId()), - ); - // If we are in a space, we check canCreateRoomInSpace - const canCreateRoom = shouldShowComponent(UIComponent.CreateRooms) && (!isSpaceRoom || canCreateRoomInSpace); + const canCreateRoom = hasCreateRoomRights(matrixClient, activeSpace); const canCreateVideoRoom = useFeatureEnabled("feature_video_rooms"); const displayComposeMenu = canCreateRoom || canCreateVideoRoom; const displaySpaceMenu = isSpaceRoom; @@ -151,13 +143,9 @@ export function useRoomListHeaderViewModel(): RoomListHeaderViewState { PosthogTrackers.trackInteraction("WebRoomListHeaderPlusMenuCreateChatItem", e); }, []); - const createRoom = useCallback( + const createRoomMemoized = useCallback( (e: Event) => { - if (activeSpace) { - showCreateNewRoom(activeSpace); - } else { - defaultDispatcher.fire(Action.CreateRoom); - } + createRoom(activeSpace); PosthogTrackers.trackInteraction("WebRoomListHeaderPlusMenuCreateRoomItem", e); }, [activeSpace], @@ -213,7 +201,7 @@ export function useRoomListHeaderViewModel(): RoomListHeaderViewState { canInviteInSpace, canAccessSpaceSettings, createChatRoom, - createRoom, + createRoom: createRoomMemoized, createVideoRoom, openSpaceHome, inviteInSpace, diff --git a/src/components/viewmodels/roomlist/RoomListViewModel.tsx b/src/components/viewmodels/roomlist/RoomListViewModel.tsx index 6c46ca6d38..2143aeae78 100644 --- a/src/components/viewmodels/roomlist/RoomListViewModel.tsx +++ b/src/components/viewmodels/roomlist/RoomListViewModel.tsx @@ -5,22 +5,55 @@ 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 { useCallback } from "react"; + import type { Room } from "matrix-js-sdk/src/matrix"; import { type PrimaryFilter, type SecondaryFilters, useFilteredRooms } from "./useFilteredRooms"; import { type SortOption, useSorter } from "./useSorter"; import { useMessagePreviewToggle } from "./useMessagePreviewToggle"; +import { createRoom as createRoomFunc, hasCreateRoomRights } from "./utils"; +import { useEventEmitterState } from "../../../hooks/useEventEmitter"; +import { UPDATE_SELECTED_SPACE } from "../../../stores/spaces"; +import SpaceStore from "../../../stores/spaces/SpaceStore"; +import dispatcher from "../../../dispatcher/dispatcher"; +import { Action } from "../../../dispatcher/actions"; +import { useMatrixClientContext } from "../../../contexts/MatrixClientContext"; export interface RoomListViewState { /** * A list of rooms to be displayed in the left panel. */ rooms: Room[]; + + /** + * Create a chat room + * @param e - The click event + */ + createChatRoom: () => void; + + /** + * Whether the user can create a room in the current space + */ + canCreateRoom: boolean; + + /** + * Create a room + * @param e - The click event + */ + createRoom: () => void; + /** * A list of objects that provide the view enough information * to render primary room filters. */ primaryFilters: PrimaryFilter[]; + /** + * The currently active primary filter. + * If no primary filter is active, this will be undefined. + */ + activePrimaryFilter?: PrimaryFilter; + /** * A function to activate a given secondary filter. */ @@ -57,13 +90,30 @@ export interface RoomListViewState { * @see {@link RoomListViewState} for more information about what this view model returns. */ export function useRoomListViewModel(): RoomListViewState { - const { primaryFilters, rooms, activateSecondaryFilter, activeSecondaryFilter } = useFilteredRooms(); + const matrixClient = useMatrixClientContext(); + const { primaryFilters, activePrimaryFilter, rooms, activateSecondaryFilter, activeSecondaryFilter } = + useFilteredRooms(); + + const currentSpace = useEventEmitterState( + SpaceStore.instance, + UPDATE_SELECTED_SPACE, + () => SpaceStore.instance.activeSpaceRoom, + ); + const canCreateRoom = hasCreateRoomRights(matrixClient, currentSpace); + const { activeSortOption, sort } = useSorter(); const { shouldShowMessagePreview, toggleMessagePreview } = useMessagePreviewToggle(); + const createChatRoom = useCallback(() => dispatcher.fire(Action.CreateChat), []); + const createRoom = useCallback(() => createRoomFunc(currentSpace), [currentSpace]); + return { rooms, + canCreateRoom, + createRoom, + createChatRoom, primaryFilters, + activePrimaryFilter, activateSecondaryFilter, activeSecondaryFilter, activeSortOption, diff --git a/src/components/viewmodels/roomlist/useFilteredRooms.tsx b/src/components/viewmodels/roomlist/useFilteredRooms.tsx index a21918e5fa..68f8e3e380 100644 --- a/src/components/viewmodels/roomlist/useFilteredRooms.tsx +++ b/src/components/viewmodels/roomlist/useFilteredRooms.tsx @@ -27,6 +27,8 @@ export interface PrimaryFilter { active: boolean; // Text that can be used in the UI to represent this filter. name: string; + // The key of the filter + key: FilterKey; } interface FilteredRooms { @@ -34,6 +36,11 @@ interface FilteredRooms { rooms: Room[]; activateSecondaryFilter: (filter: SecondaryFilters) => void; activeSecondaryFilter: SecondaryFilters; + /** + * The currently active primary filter. + * If no primary filter is active, this will be undefined. + */ + activePrimaryFilter?: PrimaryFilter; } const filterKeyToNameMap: Map = new Map([ @@ -172,6 +179,7 @@ export function useFilteredRooms(): FilteredRooms { }, active: primaryFilter === key, name, + key, }; }; const filters: PrimaryFilter[] = []; @@ -184,5 +192,7 @@ export function useFilteredRooms(): FilteredRooms { return filters; }, [primaryFilter, updateRoomsFromStore, secondaryFilter]); - return { primaryFilters, rooms, activateSecondaryFilter, activeSecondaryFilter }; + const activePrimaryFilter = useMemo(() => primaryFilters.find((filter) => filter.active), [primaryFilters]); + + return { primaryFilters, activePrimaryFilter, rooms, activateSecondaryFilter, activeSecondaryFilter }; } diff --git a/src/components/viewmodels/roomlist/utils.ts b/src/components/viewmodels/roomlist/utils.ts index 3886d0e3b0..6220c3b961 100644 --- a/src/components/viewmodels/roomlist/utils.ts +++ b/src/components/viewmodels/roomlist/utils.ts @@ -5,11 +5,14 @@ * Please see LICENSE files in the repository root for full details. */ -import { type Room, KnownMembership } from "matrix-js-sdk/src/matrix"; +import { type Room, KnownMembership, EventTimeline, EventType, type MatrixClient } from "matrix-js-sdk/src/matrix"; import { isKnockDenied } from "../../../utils/membership"; import { shouldShowComponent } from "../../../customisations/helpers/UIComponents"; import { UIComponent } from "../../../settings/UIFeature"; +import { showCreateNewRoom } from "../../../utils/space"; +import dispatcher from "../../../dispatcher/dispatcher"; +import { Action } from "../../../dispatcher/actions"; /** * Check if the user has access to the options menu. @@ -23,3 +26,33 @@ export function hasAccessToOptionsMenu(room: Room): boolean { shouldShowComponent(UIComponent.RoomOptionsMenu)) ); } + +/** + * Create a room + * @param space - The space to create the room in + */ +export async function createRoom(space?: Room | null): Promise { + if (space) { + await showCreateNewRoom(space); + } else { + dispatcher.fire(Action.CreateRoom); + } +} + +/** + * Check if the user has the rights to create a room in the given space + * If the space is not provided, it will check if the user has the rights to create a room in general + * @param matrixClient + * @param space + */ +export function hasCreateRoomRights(matrixClient: MatrixClient, space?: Room | null): boolean { + const hasUIRight = shouldShowComponent(UIComponent.CreateRooms); + if (!space || !hasUIRight) return hasUIRight; + + return Boolean( + space + ?.getLiveTimeline() + .getState(EventTimeline.FORWARDS) + ?.maySendStateEvent(EventType.RoomAvatar, matrixClient.getSafeUserId()), + ); +} diff --git a/src/components/views/rooms/RoomListPanel/EmptyRoomList.tsx b/src/components/views/rooms/RoomListPanel/EmptyRoomList.tsx new file mode 100644 index 0000000000..c4824e2b45 --- /dev/null +++ b/src/components/views/rooms/RoomListPanel/EmptyRoomList.tsx @@ -0,0 +1,149 @@ +/* + * Copyright 2025 New Vector 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 PropsWithChildren } from "react"; +import { Button } from "@vector-im/compound-web"; +import UserAddIcon from "@vector-im/compound-design-tokens/assets/web/icons/user-add"; +import RoomIcon from "@vector-im/compound-design-tokens/assets/web/icons/room"; + +import type { RoomListViewState } from "../../../viewmodels/roomlist/RoomListViewModel"; +import { Flex } from "../../../utils/Flex"; +import { _t } from "../../../../languageHandler"; +import { FilterKey } from "../../../../stores/room-list-v3/skip-list/filters"; +import { type PrimaryFilter } from "../../../viewmodels/roomlist/useFilteredRooms"; + +interface EmptyRoomListProps { + /** + * The view model for the room list + */ + vm: RoomListViewState; +} + +/** + * The empty state for the room list + */ +export function EmptyRoomList({ vm }: EmptyRoomListProps): JSX.Element | undefined { + // If there is no active primary filter, show the default empty state + if (!vm.activePrimaryFilter) return ; + + switch (vm.activePrimaryFilter.key) { + case FilterKey.FavouriteFilter: + return ( + + ); + case FilterKey.PeopleFilter: + return ( + + ); + case FilterKey.RoomsFilter: + return ( + + ); + case FilterKey.UnreadFilter: + return ; + default: + return undefined; + } +} + +interface GenericPlaceholderProps { + /** + * The title of the placeholder + */ + title: string; + /** + * The description of the placeholder + */ + description?: string; +} + +/** + * A generic placeholder for the room list + */ +function GenericPlaceholder({ title, description, children }: PropsWithChildren): JSX.Element { + return ( + + {title} + {description && {description}} + {children} + + ); +} + +interface DefaultPlaceholderProps { + /** + * The view model for the room list + */ + vm: RoomListViewState; +} + +/** + * The default empty state for the room list when no primary filter is active + * The user can create chat or room (if they have the permission) + */ +function DefaultPlaceholder({ vm }: DefaultPlaceholderProps): JSX.Element { + return ( + + + + {vm.canCreateRoom && ( + + )} + + + ); +} + +interface UnreadPlaceholderProps { + filter: PrimaryFilter; +} + +/** + * The empty state for the room list when the unread filter is active + */ +function UnreadPlaceholder({ filter }: UnreadPlaceholderProps): JSX.Element { + return ( + + + + ); +} diff --git a/src/components/views/rooms/RoomListPanel/RoomListView.tsx b/src/components/views/rooms/RoomListPanel/RoomListView.tsx index 36fab95658..f4800f7009 100644 --- a/src/components/views/rooms/RoomListPanel/RoomListView.tsx +++ b/src/components/views/rooms/RoomListPanel/RoomListView.tsx @@ -9,6 +9,7 @@ import React, { type JSX } from "react"; import { useRoomListViewModel } from "../../../viewmodels/roomlist/RoomListViewModel"; import { RoomList } from "./RoomList"; +import { EmptyRoomList } from "./EmptyRoomList"; import { RoomListPrimaryFilters } from "./RoomListPrimaryFilters"; /** @@ -16,10 +17,12 @@ import { RoomListPrimaryFilters } from "./RoomListPrimaryFilters"; */ export function RoomListView(): JSX.Element { const vm = useRoomListViewModel(); + const isRoomListEmpty = vm.rooms.length === 0; + return ( <> - + {isRoomListEmpty ? : } ); } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 34e0e98be3..aa71cac8a7 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2096,6 +2096,19 @@ "add_space_label": "Add space", "breadcrumbs_empty": "No recently visited rooms", "breadcrumbs_label": "Recently visited rooms", + "empty": { + "no_chats": "No chats yet", + "no_chats_description": "Get started by messaging someone or by creating a room", + "no_chats_description_no_room_rights": "Get started by messaging someone", + "no_favourites": "You don't have favourite chat yet", + "no_favourites_description": "You can add a chat to your favourites in the chat settings", + "no_people": "You don’t have direct chats with anyone yet", + "no_people_description": "You can deselect filters in order to see your other chats", + "no_rooms": "You’re not in any room yet", + "no_rooms_description": "You can deselect filters in order to see your other chats", + "no_unread": "Congrats! You don’t have any unread messages", + "show_chats": "Show all chats" + }, "failed_add_tag": "Failed to add tag %(tagName)s to room", "failed_remove_tag": "Failed to remove tag %(tagName)s from room", "failed_set_dm_tag": "Failed to set direct message tag", diff --git a/test/unit-tests/components/viewmodels/roomlist/RoomListHeaderViewModel-test.tsx b/test/unit-tests/components/viewmodels/roomlist/RoomListHeaderViewModel-test.tsx index 2233949d71..399943b6cf 100644 --- a/test/unit-tests/components/viewmodels/roomlist/RoomListHeaderViewModel-test.tsx +++ b/test/unit-tests/components/viewmodels/roomlist/RoomListHeaderViewModel-test.tsx @@ -6,13 +6,12 @@ */ import { renderHook } from "jest-matrix-react"; -import { JoinRule, type MatrixClient, type Room, type RoomState, RoomType } from "matrix-js-sdk/src/matrix"; +import { JoinRule, type MatrixClient, type Room, RoomType } from "matrix-js-sdk/src/matrix"; import { mocked } from "jest-mock"; import { useRoomListHeaderViewModel } from "../../../../../src/components/viewmodels/roomlist/RoomListHeaderViewModel"; import SpaceStore from "../../../../../src/stores/spaces/SpaceStore"; import { mkStubRoom, stubClient, withClientContextRenderOptions } from "../../../../test-utils"; -import { shouldShowComponent } from "../../../../../src/customisations/helpers/UIComponents"; import SettingsStore from "../../../../../src/settings/SettingsStore"; import defaultDispatcher from "../../../../../src/dispatcher/dispatcher"; import { Action } from "../../../../../src/dispatcher/actions"; @@ -23,9 +22,11 @@ import { showSpacePreferences, showSpaceSettings, } from "../../../../../src/utils/space"; +import { createRoom, hasCreateRoomRights } from "../../../../../src/components/viewmodels/roomlist/utils"; -jest.mock("../../../../../src/customisations/helpers/UIComponents", () => ({ - shouldShowComponent: jest.fn(), +jest.mock("../../../../../src/components/viewmodels/roomlist/utils", () => ({ + hasCreateRoomRights: jest.fn().mockReturnValue(false), + createRoom: jest.fn(), })); jest.mock("../../../../../src/utils/space", () => ({ @@ -68,19 +69,19 @@ describe("useRoomListHeaderViewModel", () => { }); it("should be displayComposeMenu=true and canCreateRoom=true if the user can creates room", () => { - mocked(shouldShowComponent).mockReturnValue(false); + mocked(hasCreateRoomRights).mockReturnValue(false); const { result, rerender } = render(); expect(result.current.displayComposeMenu).toBe(false); expect(result.current.canCreateRoom).toBe(false); - mocked(shouldShowComponent).mockReturnValue(true); + mocked(hasCreateRoomRights).mockReturnValue(true); rerender(); expect(result.current.displayComposeMenu).toBe(true); expect(result.current.canCreateRoom).toBe(true); }); it("should be displayComposeMenu=true if the user can creates video room", () => { - mocked(shouldShowComponent).mockReturnValue(false); + mocked(hasCreateRoomRights).mockReturnValue(false); jest.spyOn(SettingsStore, "getValue").mockReturnValue(true); const { result } = render(); @@ -93,25 +94,6 @@ describe("useRoomListHeaderViewModel", () => { expect(result.current.displaySpaceMenu).toBe(true); }); - it("should be canCreateRoom=false if the user has not the right to create a room in a space", () => { - mocked(shouldShowComponent).mockReturnValue(true); - jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(space); - - const { result } = render(); - expect(result.current.canCreateRoom).toBe(false); - }); - - it("should be canCreateRoom=true if the user has the right to create a room in a space", () => { - mocked(shouldShowComponent).mockReturnValue(true); - jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(space); - jest.spyOn(space.getLiveTimeline(), "getState").mockReturnValue({ - maySendStateEvent: jest.fn().mockReturnValue(true), - } as unknown as RoomState); - - const { result } = render(); - expect(result.current.canCreateRoom).toBe(true); - }); - it("should be canInviteInSpace=true if the space join rule is public", () => { jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(space); jest.spyOn(space, "getJoinRule").mockReturnValue(JoinRule.Public); @@ -150,20 +132,19 @@ describe("useRoomListHeaderViewModel", () => { expect(spy).toHaveBeenCalledWith(Action.CreateChat); }); - it("should fire Action.CreateRoom when createRoom is called", () => { - const spy = jest.spyOn(defaultDispatcher, "fire"); + it("should call createRoom from utils when createRoom is called", () => { const { result } = render(); result.current.createRoom(new Event("click")); - expect(spy).toHaveBeenCalledWith(Action.CreateRoom); + expect(createRoom).toHaveBeenCalled(); }); - it("should call showCreateNewRoom when createRoom is called in a space", () => { + it("should call createRoom from utils when createRoom is called in a space", () => { jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(space); const { result } = render(); result.current.createRoom(new Event("click")); - expect(showCreateNewRoom).toHaveBeenCalledWith(space); + expect(createRoom).toHaveBeenCalledWith(space); }); it("should fire Action.CreateRoom with RoomType.UnstableCall when createVideoRoom is called and feature_element_call_video_rooms is enabled", () => { diff --git a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx index 43364e0d77..9cfb83a766 100644 --- a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx +++ b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx @@ -7,6 +7,7 @@ Please see LICENSE files in the repository root for full details. import { range } from "lodash"; import { act, renderHook, waitFor } from "jest-matrix-react"; +import { mocked } from "jest-mock"; import RoomListStoreV3 from "../../../../../src/stores/room-list-v3/RoomListStoreV3"; import { mkStubRoom } from "../../../../test-utils"; @@ -17,6 +18,14 @@ import { SecondaryFilters } from "../../../../../src/components/viewmodels/rooml import { SortingAlgorithm } from "../../../../../src/stores/room-list-v3/skip-list/sorters"; import { SortOption } from "../../../../../src/components/viewmodels/roomlist/useSorter"; import SettingsStore from "../../../../../src/settings/SettingsStore"; +import { hasCreateRoomRights, createRoom } from "../../../../../src/components/viewmodels/roomlist/utils"; +import dispatcher from "../../../../../src/dispatcher/dispatcher"; +import { Action } from "../../../../../src/dispatcher/actions"; + +jest.mock("../../../../../src/components/viewmodels/roomlist/utils", () => ({ + hasCreateRoomRights: jest.fn().mockReturnValue(false), + createRoom: jest.fn(), +})); describe("RoomListViewModel", () => { function mockAndCreateRooms() { @@ -139,6 +148,19 @@ describe("RoomListViewModel", () => { ); }); + it("should return the current active primary filter", async () => { + // Let's say that the user's preferred sorting is alphabetic + mockAndCreateRooms(); + const { result: vm } = renderHook(() => useRoomListViewModel()); + // Toggle people filter + const i = vm.current.primaryFilters.findIndex((f) => f.name === "People"); + expect(vm.current.primaryFilters[i].active).toEqual(false); + act(() => vm.current.primaryFilters[i].toggle()); + + // The active primary filter should be the People filter + expect(vm.current.activePrimaryFilter).toEqual(vm.current.primaryFilters[i]); + }); + const testcases: Array<[string, { secondary: SecondaryFilters; filterKey: FilterKey }, string]> = [ [ "Mentions only", @@ -240,4 +262,31 @@ describe("RoomListViewModel", () => { expect(fn).toHaveBeenCalled(); }); }); + + describe("Create room and chat", () => { + it("should be canCreateRoom=false if hasCreateRoomRights=false", () => { + mocked(hasCreateRoomRights).mockReturnValue(false); + const { result } = renderHook(() => useRoomListViewModel()); + expect(result.current.canCreateRoom).toBe(false); + }); + + it("should be canCreateRoom=true if hasCreateRoomRights=true", () => { + mocked(hasCreateRoomRights).mockReturnValue(true); + const { result } = renderHook(() => useRoomListViewModel()); + expect(result.current.canCreateRoom).toBe(true); + }); + + it("should call createRoom", () => { + const { result } = renderHook(() => useRoomListViewModel()); + result.current.createRoom(); + expect(mocked(createRoom)).toHaveBeenCalled(); + }); + + it("should dispatch Action.CreateChat", () => { + const spy = jest.spyOn(dispatcher, "fire"); + const { result } = renderHook(() => useRoomListViewModel()); + result.current.createChatRoom(); + expect(spy).toHaveBeenCalledWith(Action.CreateChat); + }); + }); }); diff --git a/test/unit-tests/components/viewmodels/roomlist/utils-test.ts b/test/unit-tests/components/viewmodels/roomlist/utils-test.ts new file mode 100644 index 0000000000..1fd4fc1b4a --- /dev/null +++ b/test/unit-tests/components/viewmodels/roomlist/utils-test.ts @@ -0,0 +1,69 @@ +/* + * Copyright 2025 New Vector 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 { mocked } from "jest-mock"; + +import type { MatrixClient, Room, RoomState } from "matrix-js-sdk/src/matrix"; +import { createTestClient, mkStubRoom } from "../../../../test-utils"; +import { shouldShowComponent } from "../../../../../src/customisations/helpers/UIComponents"; +import { hasCreateRoomRights, createRoom } from "../../../../../src/components/viewmodels/roomlist/utils"; +import defaultDispatcher from "../../../../../src/dispatcher/dispatcher"; +import { Action } from "../../../../../src/dispatcher/actions"; +import { showCreateNewRoom } from "../../../../../src/utils/space"; + +jest.mock("../../../../../src/customisations/helpers/UIComponents", () => ({ + shouldShowComponent: jest.fn(), +})); + +jest.mock("../../../../../src/utils/space", () => ({ + showCreateNewRoom: jest.fn(), +})); + +describe("utils", () => { + let matrixClient: MatrixClient; + let space: Room; + + beforeEach(() => { + matrixClient = createTestClient(); + space = mkStubRoom("spaceId", "spaceName", matrixClient); + }); + + describe("createRoom", () => { + it("should fire Action.CreateRoom when createRoom is called without a space", async () => { + const spy = jest.spyOn(defaultDispatcher, "fire"); + await createRoom(); + + expect(spy).toHaveBeenCalledWith(Action.CreateRoom); + }); + + it("should call showCreateNewRoom when createRoom is called in a space", async () => { + await createRoom(space); + expect(showCreateNewRoom).toHaveBeenCalledWith(space); + }); + }); + + describe("hasCreateRoomRights", () => { + it("should return false when UIComponent.CreateRooms is disabled", () => { + mocked(shouldShowComponent).mockReturnValue(false); + expect(hasCreateRoomRights(matrixClient, space)).toBe(false); + }); + + it("should return true when UIComponent.CreateRooms is enabled and no space", () => { + mocked(shouldShowComponent).mockReturnValue(true); + expect(hasCreateRoomRights(matrixClient)).toBe(true); + }); + + it("should return false in space when UIComponent.CreateRooms is enabled and the user doesn't have the rights", () => { + mocked(shouldShowComponent).mockReturnValue(true); + jest.spyOn(space.getLiveTimeline(), "getState").mockReturnValue({ + maySendStateEvent: jest.fn().mockReturnValue(true), + } as unknown as RoomState); + + expect(hasCreateRoomRights(matrixClient)).toBe(true); + }); + }); +}); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/EmptyRoomList-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/EmptyRoomList-test.tsx new file mode 100644 index 0000000000..5c41fb367c --- /dev/null +++ b/test/unit-tests/components/views/rooms/RoomListPanel/EmptyRoomList-test.tsx @@ -0,0 +1,93 @@ +/* + * Copyright 2025 New Vector 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 from "react"; +import { render, screen } from "jest-matrix-react"; +import userEvent from "@testing-library/user-event"; + +import { type RoomListViewState } from "../../../../../../src/components/viewmodels/roomlist/RoomListViewModel"; +import { SecondaryFilters } from "../../../../../../src/components/viewmodels/roomlist/useFilteredRooms"; +import { SortOption } from "../../../../../../src/components/viewmodels/roomlist/useSorter"; +import { EmptyRoomList } from "../../../../../../src/components/views/rooms/RoomListPanel/EmptyRoomList"; +import { FilterKey } from "../../../../../../src/stores/room-list-v3/skip-list/filters"; + +describe("", () => { + let vm: RoomListViewState; + + beforeEach(() => { + vm = { + rooms: [], + primaryFilters: [], + activateSecondaryFilter: jest.fn().mockReturnValue({}), + activeSecondaryFilter: SecondaryFilters.AllActivity, + sort: jest.fn(), + activeSortOption: SortOption.Activity, + createRoom: jest.fn(), + createChatRoom: jest.fn(), + canCreateRoom: true, + shouldShowMessagePreview: false, + toggleMessagePreview: jest.fn(), + }; + }); + + test("should render the default placeholder when there is no filter", async () => { + const user = userEvent.setup(); + + const { asFragment } = render(); + expect(screen.getByText("No chats yet")).toBeInTheDocument(); + expect(asFragment()).toMatchSnapshot(); + + await user.click(screen.getByRole("button", { name: "New message" })); + expect(vm.createChatRoom).toHaveBeenCalled(); + + await user.click(screen.getByRole("button", { name: "New room" })); + expect(vm.createRoom).toHaveBeenCalled(); + }); + + test("should not render the new room button if the user doesn't have the rights to create a room", async () => { + const newState = { ...vm, canCreateRoom: false }; + + const { asFragment } = render(); + expect(screen.queryByRole("button", { name: "New room" })).toBeNull(); + expect(asFragment()).toMatchSnapshot(); + }); + + it("should display the empty state for the unread filter", async () => { + const user = userEvent.setup(); + const activePrimaryFilter = { + toggle: jest.fn(), + active: true, + name: "unread", + key: FilterKey.UnreadFilter, + }; + const newState = { + ...vm, + activePrimaryFilter, + }; + + const { asFragment } = render(); + await user.click(screen.getByRole("button", { name: "Show all chats" })); + expect(activePrimaryFilter.toggle).toHaveBeenCalled(); + expect(asFragment()).toMatchSnapshot(); + }); + + it.each([ + { key: FilterKey.FavouriteFilter, name: "favourite" }, + { key: FilterKey.PeopleFilter, name: "people" }, + { key: FilterKey.RoomsFilter, name: "rooms" }, + ])("should display empty state for filter $name", ({ name, key }) => { + const activePrimaryFilter = { + toggle: jest.fn(), + active: true, + name, + key, + }; + const newState = { ...vm, activePrimaryFilter }; + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx index 5e2d451ff8..3490a3c509 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx @@ -37,6 +37,9 @@ describe("", () => { activeSortOption: SortOption.Activity, shouldShowMessagePreview: false, toggleMessagePreview: jest.fn(), + createRoom: jest.fn(), + createChatRoom: jest.fn(), + canCreateRoom: true, }; // Needed to render a room list cell diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPrimaryFilters-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPrimaryFilters-test.tsx index f4b97b84b6..301f293835 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPrimaryFilters-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPrimaryFilters-test.tsx @@ -13,6 +13,7 @@ import { type RoomListViewState } from "../../../../../../src/components/viewmod import { SecondaryFilters } from "../../../../../../src/components/viewmodels/roomlist/useFilteredRooms"; import { RoomListPrimaryFilters } from "../../../../../../src/components/views/rooms/RoomListPanel/RoomListPrimaryFilters"; import { SortOption } from "../../../../../../src/components/viewmodels/roomlist/useSorter"; +import { FilterKey } from "../../../../../../src/stores/room-list-v3/skip-list/filters"; describe("", () => { let vm: RoomListViewState; @@ -20,9 +21,12 @@ describe("", () => { beforeEach(() => { vm = { rooms: [], + canCreateRoom: true, + createRoom: jest.fn(), + createChatRoom: jest.fn(), primaryFilters: [ - { name: "People", active: false, toggle: jest.fn() }, - { name: "Rooms", active: true, toggle: jest.fn() }, + { name: "People", active: false, toggle: jest.fn(), key: FilterKey.PeopleFilter }, + { name: "Rooms", active: true, toggle: jest.fn(), key: FilterKey.RoomsFilter }, ], activateSecondaryFilter: () => {}, activeSecondaryFilter: SecondaryFilters.AllActivity, diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListView-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListView-test.tsx new file mode 100644 index 0000000000..015fe5404d --- /dev/null +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListView-test.tsx @@ -0,0 +1,61 @@ +/* + * Copyright 2025 New Vector 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 { mocked } from "jest-mock"; +import { render, screen } from "jest-matrix-react"; +import React from "react"; + +import { + type RoomListViewState, + useRoomListViewModel, +} from "../../../../../../src/components/viewmodels/roomlist/RoomListViewModel"; +import { SecondaryFilters } from "../../../../../../src/components/viewmodels/roomlist/useFilteredRooms"; +import { SortOption } from "../../../../../../src/components/viewmodels/roomlist/useSorter"; +import { RoomListView } from "../../../../../../src/components/views/rooms/RoomListPanel/RoomListView"; +import { mkRoom, stubClient } from "../../../../../test-utils"; + +jest.mock("../../../../../../src/components/viewmodels/roomlist/RoomListViewModel", () => ({ + useRoomListViewModel: jest.fn(), +})); + +describe("", () => { + const defaultValue: RoomListViewState = { + rooms: [], + primaryFilters: [], + activateSecondaryFilter: jest.fn().mockReturnValue({}), + activeSecondaryFilter: SecondaryFilters.AllActivity, + sort: jest.fn(), + activeSortOption: SortOption.Activity, + createRoom: jest.fn(), + createChatRoom: jest.fn(), + canCreateRoom: true, + toggleMessagePreview: jest.fn(), + shouldShowMessagePreview: false, + }; + const matrixClient = stubClient(); + + afterEach(() => { + jest.resetAllMocks(); + }); + + it("should render an empty room list", () => { + mocked(useRoomListViewModel).mockReturnValue(defaultValue); + + render(); + expect(screen.getByText("No chats yet")).toBeInTheDocument(); + }); + + it("should render a room list", () => { + mocked(useRoomListViewModel).mockReturnValue({ + ...defaultValue, + rooms: [mkRoom(matrixClient, "testing room")], + }); + + render(); + expect(screen.getByRole("grid", { name: "Room list" })).toBeInTheDocument(); + }); +}); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/EmptyRoomList-test.tsx.snap b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/EmptyRoomList-test.tsx.snap new file mode 100644 index 0000000000..bf1733c2ed --- /dev/null +++ b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/EmptyRoomList-test.tsx.snap @@ -0,0 +1,204 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` should display empty state for filter favourite 1`] = ` + +
+ + You don't have favourite chat yet + + + You can add a chat to your favourites in the chat settings + +
+
+`; + +exports[` should display empty state for filter people 1`] = ` + +
+ + You don’t have direct chats with anyone yet + + + You can deselect filters in order to see your other chats + +
+
+`; + +exports[` should display empty state for filter rooms 1`] = ` + +
+ + You’re not in any room yet + + + You can deselect filters in order to see your other chats + +
+
+`; + +exports[` should display the empty state for the unread filter 1`] = ` + +
+ + Congrats! You don’t have any unread messages + + +
+
+`; + +exports[` should not render the new room button if the user doesn't have the rights to create a room 1`] = ` + +
+ + No chats yet + + + Get started by messaging someone + +
+ +
+
+
+`; + +exports[` should render the default placeholder when there is no filter 1`] = ` + +
+ + No chats yet + + + Get started by messaging someone or by creating a room + +
+ + +
+
+
+`; diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListPanel-test.tsx.snap b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListPanel-test.tsx.snap index 28f3befc20..df3f60dcf4 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListPanel-test.tsx.snap +++ b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListPanel-test.tsx.snap @@ -113,34 +113,45 @@ exports[` should not render the RoomListSearch component when U
-
-
+ + Get started by messaging someone + +
+
-
-
-
-
-
+ + New message +
@@ -322,34 +333,66 @@ exports[` should render the RoomListSearch component when UICom
-
-
+ + Get started by messaging someone or by creating a room + +
+
-
-
-
-
-
+ + New message + +
From 839329b52acd3e94c55318c8efa64ddae987f41e Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Tue, 18 Mar 2025 18:19:10 +0530 Subject: [PATCH 094/458] RoomListViewModel: Track the index of the active room in the list (#29519) * Introduce a hook to track active room This hook simply keeps a state which tracks the index of the active room in the list of rooms passed through props. This index will be recomputed if the active rooms changes or if the list itself changed. * Use hook in the view model * Write tests * Fix broken tests --- .../viewmodels/roomlist/RoomListViewModel.tsx | 8 ++++ .../roomlist/useIndexForActiveRoom.tsx | 44 ++++++++++++++++++ .../roomlist/RoomListViewModel-test.tsx | 45 +++++++++++++++++++ .../RoomListPanel/EmptyRoomList-test.tsx | 1 + .../rooms/RoomListPanel/RoomList-test.tsx | 1 + .../RoomListPrimaryFilters-test.tsx | 1 + .../rooms/RoomListPanel/RoomListView-test.tsx | 1 + 7 files changed, 101 insertions(+) create mode 100644 src/components/viewmodels/roomlist/useIndexForActiveRoom.tsx diff --git a/src/components/viewmodels/roomlist/RoomListViewModel.tsx b/src/components/viewmodels/roomlist/RoomListViewModel.tsx index 2143aeae78..584e436c57 100644 --- a/src/components/viewmodels/roomlist/RoomListViewModel.tsx +++ b/src/components/viewmodels/roomlist/RoomListViewModel.tsx @@ -18,6 +18,7 @@ import SpaceStore from "../../../stores/spaces/SpaceStore"; import dispatcher from "../../../dispatcher/dispatcher"; import { Action } from "../../../dispatcher/actions"; import { useMatrixClientContext } from "../../../contexts/MatrixClientContext"; +import { useIndexForActiveRoom } from "./useIndexForActiveRoom"; export interface RoomListViewState { /** @@ -83,6 +84,11 @@ export interface RoomListViewState { * A function to turn on/off message previews. */ toggleMessagePreview: () => void; + + /** + * The index of the active room in the room list. + */ + activeIndex: number | undefined; } /** @@ -101,6 +107,7 @@ export function useRoomListViewModel(): RoomListViewState { ); const canCreateRoom = hasCreateRoomRights(matrixClient, currentSpace); + const activeIndex = useIndexForActiveRoom(rooms); const { activeSortOption, sort } = useSorter(); const { shouldShowMessagePreview, toggleMessagePreview } = useMessagePreviewToggle(); @@ -120,5 +127,6 @@ export function useRoomListViewModel(): RoomListViewState { sort, shouldShowMessagePreview, toggleMessagePreview, + activeIndex, }; } diff --git a/src/components/viewmodels/roomlist/useIndexForActiveRoom.tsx b/src/components/viewmodels/roomlist/useIndexForActiveRoom.tsx new file mode 100644 index 0000000000..210e0efd0f --- /dev/null +++ b/src/components/viewmodels/roomlist/useIndexForActiveRoom.tsx @@ -0,0 +1,44 @@ +/* + * Copyright 2025 New Vector 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 { useCallback, useEffect, useState } from "react"; + +import { SdkContextClass } from "../../../contexts/SDKContext"; +import { useDispatcher } from "../../../hooks/useDispatcher"; +import dispatcher from "../../../dispatcher/dispatcher"; +import { Action } from "../../../dispatcher/actions"; +import type { Room } from "matrix-js-sdk/src/matrix"; + +/** + * Tracks the index of the active room in the given array of rooms. + * @param rooms list of rooms + * @returns index of the active room or undefined otherwise. + */ +export function useIndexForActiveRoom(rooms: Room[]): number | undefined { + const [index, setIndex] = useState(undefined); + + const calculateIndex = useCallback( + (newRoomId?: string) => { + const activeRoomId = newRoomId ?? SdkContextClass.instance.roomViewStore.getRoomId(); + const index = rooms.findIndex((room) => room.roomId === activeRoomId); + setIndex(index === -1 ? undefined : index); + }, + [rooms], + ); + + // Re-calculate the index when the active room has changed. + useDispatcher(dispatcher, (payload) => { + if (payload.action === Action.ActiveRoomChanged) calculateIndex(payload.newRoomId); + }); + + // Re-calculate the index when the list of rooms has changed. + useEffect(() => { + calculateIndex(); + }, [calculateIndex, rooms]); + + return index; +} diff --git a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx index 9cfb83a766..4b986f8d2d 100644 --- a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx +++ b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx @@ -21,6 +21,7 @@ import SettingsStore from "../../../../../src/settings/SettingsStore"; import { hasCreateRoomRights, createRoom } from "../../../../../src/components/viewmodels/roomlist/utils"; import dispatcher from "../../../../../src/dispatcher/dispatcher"; import { Action } from "../../../../../src/dispatcher/actions"; +import { SdkContextClass } from "../../../../../src/contexts/SDKContext"; jest.mock("../../../../../src/components/viewmodels/roomlist/utils", () => ({ hasCreateRoomRights: jest.fn().mockReturnValue(false), @@ -289,4 +290,48 @@ describe("RoomListViewModel", () => { expect(spy).toHaveBeenCalledWith(Action.CreateChat); }); }); + + describe("active index", () => { + it("should recalculate active index when list of rooms change", () => { + const { rooms } = mockAndCreateRooms(); + // Let's say that the first room is the active room initially + jest.spyOn(SdkContextClass.instance.roomViewStore, "getRoomId").mockImplementation(() => rooms[0].roomId); + + const { result: vm } = renderHook(() => useRoomListViewModel()); + expect(vm.current.activeIndex).toEqual(0); + + // Let's say that a new room is added and that becomes active + const newRoom = mkStubRoom("bar:matrix.org", "Bar", undefined); + jest.spyOn(SdkContextClass.instance.roomViewStore, "getRoomId").mockImplementation(() => newRoom.roomId); + rooms.push(newRoom); + act(() => RoomListStoreV3.instance.emit(LISTS_UPDATE_EVENT)); + + // Now the active room should be the last room which we just added + expect(vm.current.activeIndex).toEqual(rooms.length - 1); + }); + + it("should recalculate active index when active room changes", () => { + const { rooms } = mockAndCreateRooms(); + const { result: vm } = renderHook(() => useRoomListViewModel()); + + // No active room yet + expect(vm.current.activeIndex).toBeUndefined(); + + // Let's say that room at index 5 becomes active + const room = rooms[5]; + act(() => { + dispatcher.dispatch( + { + action: Action.ActiveRoomChanged, + oldRoomId: null, + newRoomId: room.roomId, + }, + true, + ); + }); + + // We expect index 5 to be active now + expect(vm.current.activeIndex).toEqual(5); + }); + }); }); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/EmptyRoomList-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/EmptyRoomList-test.tsx index 5c41fb367c..b68929f74a 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/EmptyRoomList-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/EmptyRoomList-test.tsx @@ -31,6 +31,7 @@ describe("", () => { canCreateRoom: true, shouldShowMessagePreview: false, toggleMessagePreview: jest.fn(), + activeIndex: undefined, }; }); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx index 3490a3c509..0d837c3a20 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx @@ -40,6 +40,7 @@ describe("", () => { createRoom: jest.fn(), createChatRoom: jest.fn(), canCreateRoom: true, + activeIndex: undefined, }; // Needed to render a room list cell diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPrimaryFilters-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPrimaryFilters-test.tsx index 301f293835..79bfbb6dc0 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPrimaryFilters-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPrimaryFilters-test.tsx @@ -34,6 +34,7 @@ describe("", () => { activeSortOption: SortOption.Activity, shouldShowMessagePreview: false, toggleMessagePreview: jest.fn(), + activeIndex: undefined, }; }); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListView-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListView-test.tsx index 015fe5404d..f56d30976a 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListView-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListView-test.tsx @@ -35,6 +35,7 @@ describe("", () => { canCreateRoom: true, toggleMessagePreview: jest.fn(), shouldShowMessagePreview: false, + activeIndex: undefined, }; const matrixClient = stubClient(); From 425adb147a10b8de72bc83de0adc6a08fcab2865 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 18 Mar 2025 13:26:07 +0000 Subject: [PATCH 095/458] Upgrade dependency to matrix-js-sdk@37.2.0-rc.0 --- package.json | 2 +- yarn.lock | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 7843a43c27..0dd64fa05e 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,7 @@ "maplibre-gl": "^5.0.0", "matrix-encrypt-attachment": "^1.0.3", "matrix-events-sdk": "0.0.1", - "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", + "matrix-js-sdk": "37.2.0-rc.0", "matrix-widget-api": "^1.10.0", "memoize-one": "^6.0.0", "mime": "^4.0.4", diff --git a/yarn.lock b/yarn.lock index 600521f2b9..26fe8af604 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3621,7 +3621,7 @@ resolved "https://registry.yarnpkg.com/@vector-im/matrix-wysiwyg/-/matrix-wysiwyg-2.38.2.tgz#3fa19a2a17fd12d955ef1e14fd63aecbcf3b95e8" integrity sha512-TUnLPgZ8/zGUccQZxjIP3MVHjqybgV4u0r6kXibs35wlXgomXjwcN5gchl3FpgGkiHbi8g3D2ao0oHaqi2GaIw== dependencies: - "@vector-im/matrix-wysiwyg-wasm" "link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.2-3fa19a2a17fd12d955ef1e14fd63aecbcf3b95e8-integrity/node_modules/bindings/wysiwyg-wasm" + "@vector-im/matrix-wysiwyg-wasm" "link:../../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.2-3fa19a2a17fd12d955ef1e14fd63aecbcf3b95e8-integrity/node_modules/bindings/wysiwyg-wasm" "@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1": version "1.14.1" @@ -8797,9 +8797,10 @@ matrix-events-sdk@0.0.1: resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1.tgz#c8c38911e2cb29023b0bbac8d6f32e0de2c957dd" integrity sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA== -"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop": - version "37.0.0" - resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/d81929de4c9526e7d68ab7226804726cdef6387f" +matrix-js-sdk@37.2.0-rc.0: + version "37.2.0-rc.0" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-37.2.0-rc.0.tgz#b1b6dc0a3fb5839b3af05ceedc6d1ab8e511a052" + integrity sha512-Abh2QQmi9vUhi3M7qC5BFb6z2SoNRRv/pNwvX3onAXwQcQzD3vXvUWVdiSwxE/rdkSksUbcvT2fSfJNF4IfeVQ== dependencies: "@babel/runtime" "^7.12.5" "@matrix-org/matrix-sdk-crypto-wasm" "^14.0.1" From b5f8f2b9f52d82307fb4a58385aacb5b494527d4 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 18 Mar 2025 13:28:56 +0000 Subject: [PATCH 096/458] v1.11.96-rc.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0dd64fa05e..c68224005e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "element-web", - "version": "1.11.95", + "version": "1.11.96-rc.0", "description": "Element: the future of secure communication", "author": "New Vector Ltd.", "repository": { From e662c1959b45c2fcc2c55e6fba71d5a87fdc6383 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Tue, 18 Mar 2025 14:23:24 +0000 Subject: [PATCH 097/458] Add ability to hide images after clicking "show image" (#29467) * start hide * Move useSettingsValueWithSetter to useSettings * Add new setting showMediaEventIds * Add a migration path * Add an action button to hide settings. * Tweaks to MImageBody to support new setting. * Fixup and add tests * add description for migration * docs fixes * add type * i18n * appese prettier * Add tests for HideActionButton * lint * lint * Use a hook for media visibility. * Drop setting hook usage. * Fixup MImageBody test * Fixup tests * Support functional components for message body rendering. * Add a comment * Move props into IProps --- playwright/e2e/timeline/timeline.spec.ts | 15 +++- .../views/messages/HideActionButton.tsx | 44 +++++++++++ src/components/views/messages/MFileBody.tsx | 13 ++-- src/components/views/messages/MImageBody.tsx | 62 +++++++++------ .../views/messages/MImageReplyBody.tsx | 12 ++- .../views/messages/MStickerBody.tsx | 19 +++-- .../views/messages/MessageActionBar.tsx | 2 + .../views/messages/MessageEvent.tsx | 10 +-- src/components/views/rooms/ReplyTile.tsx | 5 +- src/events/EventTileFactory.tsx | 5 +- src/hooks/useMediaVisible.ts | 35 +++++++++ src/i18n/strings/en_EN.json | 1 + src/settings/Settings.tsx | 6 ++ src/settings/SettingsStore.ts | 24 ++++++ .../views/messages/HideActionButton-test.tsx | 76 +++++++++++++++++++ .../views/messages/MImageBody-test.tsx | 26 ++++++- .../unit-tests/hooks/useMediaVisible-test.tsx | 71 +++++++++++++++++ 17 files changed, 376 insertions(+), 50 deletions(-) create mode 100644 src/components/views/messages/HideActionButton.tsx create mode 100644 src/hooks/useMediaVisible.ts create mode 100644 test/unit-tests/components/views/messages/HideActionButton-test.tsx create mode 100644 test/unit-tests/hooks/useMediaVisible-test.tsx diff --git a/playwright/e2e/timeline/timeline.spec.ts b/playwright/e2e/timeline/timeline.spec.ts index 7b13d1ccb1..1f353e3e84 100644 --- a/playwright/e2e/timeline/timeline.spec.ts +++ b/playwright/e2e/timeline/timeline.spec.ts @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024, 2025 New Vector Ltd. Copyright 2022, 2023 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial @@ -905,6 +905,19 @@ test.describe("Timeline", () => { mask: [page.locator(".mx_MessageTimestamp")], }); }); + + test("should be able to hide an image", { tag: "@screenshot" }, async ({ page, app, room, context }) => { + await app.viewRoomById(room.roomId); + await sendImage(app.client, room.roomId, NEW_AVATAR); + await app.timeline.scrollToBottom(); + const imgTile = page.locator(".mx_MImageBody").first(); + await expect(imgTile).toBeVisible(); + await imgTile.hover(); + await page.getByRole("button", { name: "Hide" }).click(); + + // Check that the image is now hidden. + await expect(page.getByRole("link", { name: "Show image" })).toBeVisible(); + }); }); test.describe("message sending", { tag: ["@no-firefox", "@no-webkit"] }, () => { diff --git a/src/components/views/messages/HideActionButton.tsx b/src/components/views/messages/HideActionButton.tsx new file mode 100644 index 0000000000..8d2baf0220 --- /dev/null +++ b/src/components/views/messages/HideActionButton.tsx @@ -0,0 +1,44 @@ +/* +Copyright 2024 New Vector Ltd. +Copyright 2021 The Matrix.org Foundation C.I.C. + +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 { type MatrixEvent } from "matrix-js-sdk/src/matrix"; +import React from "react"; +import { VisibilityOffIcon } from "@vector-im/compound-design-tokens/assets/web/icons"; + +import { RovingAccessibleButton } from "../../../accessibility/RovingTabIndex"; +import { _t } from "../../../languageHandler"; +import { useMediaVisible } from "../../../hooks/useMediaVisible"; + +interface IProps { + /** + * Matrix event that this action applies to. + */ + mxEvent: MatrixEvent; +} + +/** + * Quick action button for marking a media event as hidden. + */ +export const HideActionButton: React.FC = ({ mxEvent }) => { + const [mediaIsVisible, setVisible] = useMediaVisible(mxEvent.getId()!); + + if (!mediaIsVisible) { + return; + } + + return ( + setVisible(false)} + placement="left" + > + + + ); +}; diff --git a/src/components/views/messages/MFileBody.tsx b/src/components/views/messages/MFileBody.tsx index 674e0f8583..3bb9fb1069 100644 --- a/src/components/views/messages/MFileBody.tsx +++ b/src/components/views/messages/MFileBody.tsx @@ -93,7 +93,7 @@ export function computedStyle(element: HTMLElement | null): string { interface IProps extends IBodyProps { /* whether or not to show the default placeholder for the file. Defaults to true. */ - showGenericPlaceholder: boolean; + showGenericPlaceholder?: boolean; } interface IState { @@ -105,11 +105,6 @@ export default class MFileBody extends React.Component { declare public context: React.ContextType; public state: IState = {}; - - public static defaultProps = { - showGenericPlaceholder: true, - }; - private iframe: React.RefObject = createRef(); private dummyLink: React.RefObject = createRef(); private userDidClick = false; @@ -191,15 +186,17 @@ export default class MFileBody extends React.Component { const contentUrl = this.getContentUrl(); const contentFileSize = this.content.info ? this.content.info.size : null; const fileType = this.content.info?.mimetype ?? "application/octet-stream"; + // defaultProps breaks types on IBodyProps, so instead define the default here. + const showGenericPlaceholder = this.props.showGenericPlaceholder ?? true; let showDownloadLink = - !this.props.showGenericPlaceholder || + !showGenericPlaceholder || (this.context.timelineRenderingType !== TimelineRenderingType.Room && this.context.timelineRenderingType !== TimelineRenderingType.Search && this.context.timelineRenderingType !== TimelineRenderingType.Pinned); let placeholder: React.ReactNode = null; - if (this.props.showGenericPlaceholder) { + if (showGenericPlaceholder) { placeholder = ( diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index 59d8b988a8..3fa4f01bfd 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -33,6 +33,7 @@ import { presentableTextForFile } from "../../../utils/FileUtils"; import { createReconnectedListener } from "../../../utils/connection"; import MediaProcessingError from "./shared/MediaProcessingError"; import { DecryptError, DownloadError } from "../../../utils/DecryptFile"; +import { useMediaVisible } from "../../../hooks/useMediaVisible"; enum Placeholder { NoImage, @@ -52,11 +53,25 @@ interface IState { }; hover: boolean; focus: boolean; - showImage: boolean; placeholder: Placeholder; } -export default class MImageBody extends React.Component { +interface IProps extends IBodyProps { + /** + * Should the media be behind a preview. + */ + mediaVisible: boolean; + /** + * Set the visibility of the media event. + * @param visible Should the event be visible. + */ + setMediaVisible: (visible: boolean) => void; +} + +/** + * @private Only use for inheritance. Use the default export for presentation. + */ +export class MImageBodyInner extends React.Component { public static contextType = RoomContext; declare public context: React.ContextType; @@ -73,21 +88,14 @@ export default class MImageBody extends React.Component { imgLoaded: false, hover: false, focus: false, - showImage: SettingsStore.getValue("showImages"), placeholder: Placeholder.NoImage, }; - protected showImage(): void { - localStorage.setItem("mx_ShowImage_" + this.props.mxEvent.getId(), "true"); - this.setState({ showImage: true }); - this.downloadImage(); - } - protected onClick = (ev: React.MouseEvent): void => { if (ev.button === 0 && !ev.metaKey) { ev.preventDefault(); - if (!this.state.showImage) { - this.showImage(); + if (!this.props.mediaVisible) { + this.props.setMediaVisible?.(true); return; } @@ -125,7 +133,7 @@ export default class MImageBody extends React.Component { private get shouldAutoplay(): boolean { return !( !this.state.contentUrl || - !this.state.showImage || + !this.props.mediaVisible || !this.state.isAnimated || SettingsStore.getValue("autoplayGifs") ); @@ -346,14 +354,10 @@ export default class MImageBody extends React.Component { public componentDidMount(): void { this.unmounted = false; - const showImage = - this.state.showImage || localStorage.getItem("mx_ShowImage_" + this.props.mxEvent.getId()) === "true"; - - if (showImage) { + if (this.props.mediaVisible) { // noinspection JSIgnoredPromiseFromCall this.downloadImage(); - this.setState({ showImage: true }); - } // else don't download anything because we don't want to display anything. + } // Add a 150ms timer for blurhash to first appear. if (this.props.mxEvent.getContent().info?.[BLURHASH_FIELD]) { @@ -372,6 +376,13 @@ export default class MImageBody extends React.Component { }); } + public componentDidUpdate(prevProps: Readonly): void { + if (!prevProps.mediaVisible && this.props.mediaVisible) { + // noinspection JSIgnoredPromiseFromCall + this.downloadImage(); + } + } + public componentWillUnmount(): void { this.unmounted = true; MatrixClientPeg.get()?.off(ClientEvent.Sync, this.reconnectedListener); @@ -425,7 +436,7 @@ export default class MImageBody extends React.Component { // by the same width and height logic below. if (!this.state.loadedImageDimensions) { let imageElement: JSX.Element; - if (!this.state.showImage) { + if (!this.props.mediaVisible) { imageElement = ; } else { imageElement = ( @@ -495,7 +506,7 @@ export default class MImageBody extends React.Component { ); } - if (!this.state.showImage) { + if (!this.props.mediaVisible) { img = ; showPlaceholder = false; // because we're hiding the image, so don't show the placeholder. } @@ -506,7 +517,7 @@ export default class MImageBody extends React.Component { } let banner: ReactNode | undefined; - if (this.state.showImage && hoverOrFocus) { + if (this.props.mediaVisible && hoverOrFocus) { banner = this.getBanner(content); } @@ -585,7 +596,7 @@ export default class MImageBody extends React.Component { {children} ); - } else if (!this.state.showImage) { + } else if (!this.props.mediaVisible) { return (
{children} @@ -686,3 +697,10 @@ export class HiddenImagePlaceholder extends React.PureComponent = (props) => { + const [mediaVisible, setVisible] = useMediaVisible(props.mxEvent.getId()!); + return ; +}; + +export default MImageBody; diff --git a/src/components/views/messages/MImageReplyBody.tsx b/src/components/views/messages/MImageReplyBody.tsx index 32fd27c62a..5bbb00ef44 100644 --- a/src/components/views/messages/MImageReplyBody.tsx +++ b/src/components/views/messages/MImageReplyBody.tsx @@ -9,11 +9,13 @@ Please see LICENSE files in the repository root for full details. import React from "react"; import { type ImageContent } from "matrix-js-sdk/src/types"; -import MImageBody from "./MImageBody"; +import { MImageBodyInner } from "./MImageBody"; +import { type IBodyProps } from "./IBodyProps"; +import { useMediaVisible } from "../../../hooks/useMediaVisible"; const FORCED_IMAGE_HEIGHT = 44; -export default class MImageReplyBody extends MImageBody { +class MImageReplyBodyInner extends MImageBodyInner { public onClick = (ev: React.MouseEvent): void => { ev.preventDefault(); }; @@ -35,3 +37,9 @@ export default class MImageReplyBody extends MImageBody { return
{thumbnail}
; } } +const MImageReplyBody: React.FC = (props) => { + const [mediaVisible, setVisible] = useMediaVisible(props.mxEvent.getId()!); + return ; +}; + +export default MImageReplyBody; diff --git a/src/components/views/messages/MStickerBody.tsx b/src/components/views/messages/MStickerBody.tsx index ccb9bb437b..29082512d0 100644 --- a/src/components/views/messages/MStickerBody.tsx +++ b/src/components/views/messages/MStickerBody.tsx @@ -9,16 +9,18 @@ import React, { type ComponentProps, type ReactNode } from "react"; import { type Tooltip } from "@vector-im/compound-web"; import { type MediaEventContent } from "matrix-js-sdk/src/types"; -import MImageBody from "./MImageBody"; +import { MImageBodyInner } from "./MImageBody"; import { BLURHASH_FIELD } from "../../../utils/image-media"; import IconsShowStickersSvg from "../../../../res/img/icons-show-stickers.svg"; +import { type IBodyProps } from "./IBodyProps"; +import { useMediaVisible } from "../../../hooks/useMediaVisible"; -export default class MStickerBody extends MImageBody { +class MStickerBodyInner extends MImageBodyInner { // Mostly empty to prevent default behaviour of MImageBody protected onClick = (ev: React.MouseEvent): void => { ev.preventDefault(); - if (!this.state.showImage) { - this.showImage(); + if (!this.props.mediaVisible) { + this.props.setMediaVisible?.(true); } }; @@ -26,7 +28,7 @@ export default class MStickerBody extends MImageBody { // which is added by mx_MStickerBody_wrapper protected wrapImage(contentUrl: string, children: React.ReactNode): JSX.Element { let onClick: React.MouseEventHandler | undefined; - if (!this.state.showImage) { + if (!this.props.mediaVisible) { onClick = this.onClick; } return ( @@ -75,3 +77,10 @@ export default class MStickerBody extends MImageBody { return null; // we don't need a banner, we have a tooltip } } + +const MStickerBody: React.FC = (props) => { + const [mediaVisible, setVisible] = useMediaVisible(props.mxEvent.getId()!); + return ; +}; + +export default MStickerBody; diff --git a/src/components/views/messages/MessageActionBar.tsx b/src/components/views/messages/MessageActionBar.tsx index e6838c635f..0120947b31 100644 --- a/src/components/views/messages/MessageActionBar.tsx +++ b/src/components/views/messages/MessageActionBar.tsx @@ -61,6 +61,7 @@ import { type GetRelationsForEvent, type IEventTileType } from "../rooms/EventTi import { type ButtonEvent } from "../elements/AccessibleButton"; import PinningUtils from "../../../utils/PinningUtils"; import PosthogTrackers from "../../../PosthogTrackers.ts"; +import { HideActionButton } from "./HideActionButton.tsx"; interface IOptionsButtonProps { mxEvent: MatrixEvent; @@ -535,6 +536,7 @@ export default class MessageActionBar extends React.PureComponent this.props.getTile()?.getMediaHelper?.()} key="download" />, + , ); } } else if ( diff --git a/src/components/views/messages/MessageEvent.tsx b/src/components/views/messages/MessageEvent.tsx index be63457902..ff97edd1db 100644 --- a/src/components/views/messages/MessageEvent.tsx +++ b/src/components/views/messages/MessageEvent.tsx @@ -45,8 +45,8 @@ import { type GetRelationsForEvent, type IEventTileOps } from "../rooms/EventTil // onMessageAllowed is handled internally interface IProps extends Omit { /* overrides for the msgtype-specific components, used by ReplyTile to override file rendering */ - overrideBodyTypes?: Record; - overrideEventTypes?: Record; + overrideBodyTypes?: Record>; + overrideEventTypes?: Record>; // helper function to access relations for this event getRelationsForEvent?: GetRelationsForEvent; @@ -58,7 +58,7 @@ export interface IOperableEventTile { getEventTileOps(): IEventTileOps | null; } -const baseBodyTypes = new Map([ +const baseBodyTypes = new Map>([ [MsgType.Text, TextualBody], [MsgType.Notice, TextualBody], [MsgType.Emote, TextualBody], @@ -80,7 +80,7 @@ const baseEvTypes = new Map>([ export default class MessageEvent extends React.Component implements IMediaBody, IOperableEventTile { private body: React.RefObject = createRef(); private mediaHelper?: MediaEventHelper; - private bodyTypes = new Map(baseBodyTypes.entries()); + private bodyTypes = new Map>(baseBodyTypes.entries()); private evTypes = new Map>(baseEvTypes.entries()); public static contextType = MatrixClientContext; @@ -115,7 +115,7 @@ export default class MessageEvent extends React.Component implements IMe } private updateComponentMaps(): void { - this.bodyTypes = new Map(baseBodyTypes.entries()); + this.bodyTypes = new Map>(baseBodyTypes.entries()); for (const [bodyType, bodyComponent] of Object.entries(this.props.overrideBodyTypes ?? {})) { this.bodyTypes.set(bodyType, bodyComponent); } diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index 8084b59ba3..0f2b580d7e 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -26,6 +26,7 @@ import { type ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPaylo import { renderReplyTile } from "../../../events/EventTileFactory"; import { type GetRelationsForEvent } from "../rooms/EventTile"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; +import { type IBodyProps } from "../messages/IBodyProps"; interface IProps { mxEvent: MatrixEvent; @@ -139,13 +140,13 @@ export default class ReplyTile extends React.PureComponent { ); } - const msgtypeOverrides: Record = { + const msgtypeOverrides: Record> = { [MsgType.Image]: MImageReplyBody, // Override audio and video body with file body. We also hide the download/decrypt button using CSS [MsgType.Audio]: isVoiceMessage(mxEvent) ? MVoiceMessageBody : MFileBody, [MsgType.Video]: MFileBody, }; - const evOverrides: Record = { + const evOverrides: Record> = { // Use MImageReplyBody so that the sticker isn't taking up a lot of space [EventType.Sticker]: MImageReplyBody, }; diff --git a/src/events/EventTileFactory.tsx b/src/events/EventTileFactory.tsx index e0d2a91afb..633583485a 100644 --- a/src/events/EventTileFactory.tsx +++ b/src/events/EventTileFactory.tsx @@ -42,6 +42,7 @@ import HiddenBody from "../components/views/messages/HiddenBody"; import ViewSourceEvent from "../components/views/messages/ViewSourceEvent"; import { shouldDisplayAsBeaconTile } from "../utils/beacon/timeline"; import { ElementCall } from "../models/Call"; +import { type IBodyProps } from "../components/views/messages/IBodyProps"; // Subset of EventTile's IProps plus some mixins export interface EventTileTypeProps @@ -64,8 +65,8 @@ export interface EventTileTypeProps ref?: React.RefObject; // `any` because it's effectively impossible to convince TS of a reasonable type timestamp?: JSX.Element; maxImageHeight?: number; // pixels - overrideBodyTypes?: Record; - overrideEventTypes?: Record; + overrideBodyTypes?: Record>; + overrideEventTypes?: Record>; } type FactoryProps = Omit; diff --git a/src/hooks/useMediaVisible.ts b/src/hooks/useMediaVisible.ts new file mode 100644 index 0000000000..e244d500cf --- /dev/null +++ b/src/hooks/useMediaVisible.ts @@ -0,0 +1,35 @@ +/* +Copyright 2025 New Vector 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 { useCallback } from "react"; + +import { SettingLevel } from "../settings/SettingLevel"; +import { useSettingValue } from "./useSettings"; +import SettingsStore from "../settings/SettingsStore"; + +/** + * Should the media event be visible in the client, or hidden. + * @param eventId The eventId of the media event. + * @returns A boolean describing the hidden status, and a function to set the visiblity. + */ +export function useMediaVisible(eventId: string): [boolean, (visible: boolean) => void] { + const defaultShowImages = useSettingValue("showImages", SettingLevel.DEVICE); + const eventVisibility = useSettingValue("showMediaEventIds", SettingLevel.DEVICE); + const setMediaVisible = useCallback( + (visible: boolean) => { + SettingsStore.setValue("showMediaEventIds", null, SettingLevel.DEVICE, { + ...eventVisibility, + [eventId]: visible, + }); + }, + [eventId, eventVisibility], + ); + + // Always prefer the explicit per-event user preference here. + const imgIsVisible = eventVisibility[eventId] ?? defaultShowImages; + return [imgIsVisible, setMediaVisible]; +} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index aa71cac8a7..322fcf4c93 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -64,6 +64,7 @@ "go": "Go", "go_back": "Go back", "got_it": "Got it", + "hide": "Hide", "hide_advanced": "Hide advanced", "hold": "Hold", "ignore": "Ignore", diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index d887c9bb49..8784e12b6c 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -273,6 +273,7 @@ export interface Settings { "language": IBaseSetting; "breadcrumb_rooms": IBaseSetting; "recent_emoji": IBaseSetting; + "showMediaEventIds": IBaseSetting<{ [eventId: string]: boolean }>; "SpotlightSearch.recentSearches": IBaseSetting; "SpotlightSearch.showNsfwPublicRooms": IBaseSetting; "room_directory_servers": IBaseSetting; @@ -970,6 +971,11 @@ export const SETTINGS: Settings = { supportedLevels: [SettingLevel.ACCOUNT], default: [], // list of room IDs, most recent first }, + "showMediaEventIds": { + // not really a setting + supportedLevels: [SettingLevel.DEVICE], + default: {}, // List of events => is visible + }, "SpotlightSearch.showNsfwPublicRooms": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, displayName: _td("settings|show_nsfw_content"), diff --git a/src/settings/SettingsStore.ts b/src/settings/SettingsStore.ts index 671a2ac676..7dac777399 100644 --- a/src/settings/SettingsStore.ts +++ b/src/settings/SettingsStore.ts @@ -697,6 +697,24 @@ export default class SettingsStore { client.on(ClientEvent.Sync, onSync); } + /** + * Migrate the setting for visible images to a setting. + */ + private static migrateShowImagesToSettings(): void { + const MIGRATION_DONE_FLAG = "mx_show_images_migration_done"; + if (localStorage.getItem(MIGRATION_DONE_FLAG)) return; + + logger.info("Performing one-time settings migration of shown images to settings store"); + const newValue = Object.fromEntries( + Object.keys(localStorage) + .filter((k) => k.startsWith("mx_ShowImage_")) + .map((k) => [k.slice("mx_ShowImage_".length), true]), + ); + this.setValue("showMediaEventIds", null, SettingLevel.DEVICE, newValue); + + localStorage.setItem(MIGRATION_DONE_FLAG, "true"); + } + /** * Runs or queues any setting migrations needed. */ @@ -708,6 +726,12 @@ export default class SettingsStore { // be disabled in E2EE rooms. SettingsStore.migrateURLPreviewsE2EE(isFreshLogin); + // This can be removed once enough users have run a version of Element with + // this migration. + // The consequences of missing the migration are that previously shown images + // will now be hidden again, so this fails safely. + SettingsStore.migrateShowImagesToSettings(); + // Dev notes: to add your migration, just add a new `migrateMyFeature` function, call it, and // add a comment to note when it can be removed. return; diff --git a/test/unit-tests/components/views/messages/HideActionButton-test.tsx b/test/unit-tests/components/views/messages/HideActionButton-test.tsx new file mode 100644 index 0000000000..57e92b02b8 --- /dev/null +++ b/test/unit-tests/components/views/messages/HideActionButton-test.tsx @@ -0,0 +1,76 @@ +/* +Copyright 2024,2025 New Vector Ltd. +Copyright 2024 The Matrix.org Foundation C.I.C. + +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 { fireEvent, render, screen } from "jest-matrix-react"; +import { MatrixEvent } from "matrix-js-sdk/src/matrix"; + +import { HideActionButton } from "../../../../../src/components/views/messages/HideActionButton"; +import SettingsStore from "../../../../../src/settings/SettingsStore"; +import { SettingLevel } from "../../../../../src/settings/SettingLevel"; +import type { Settings } from "../../../../../src/settings/Settings"; + +function mockSetting( + showImages: Settings["showImages"]["default"], + showMediaEventIds: Settings["showMediaEventIds"]["default"], +) { + jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName) => { + if (settingName === "showImages") { + return showImages; + } else if (settingName === "showMediaEventIds") { + return showMediaEventIds; + } + throw Error(`Unexpected setting ${settingName}`); + }); +} + +const event = new MatrixEvent({ + event_id: "$foo:bar", + room_id: "!room:id", + sender: "@user:id", + type: "m.room.message", + content: { + body: "test", + msgtype: "m.image", + url: "mxc://matrix.org/1234", + }, +}); + +describe("HideActionButton", () => { + afterEach(() => { + jest.restoreAllMocks(); + }); + it("should show button when event is visible by showMediaEventIds setting", async () => { + mockSetting(false, { "$foo:bar": true }); + render(); + expect(screen.getByRole("button")).toBeVisible(); + }); + it("should show button when event is visible by showImages setting", async () => { + mockSetting(true, {}); + render(); + expect(screen.getByRole("button")).toBeVisible(); + }); + it("should hide button when event is hidden by showMediaEventIds setting", async () => { + jest.spyOn(SettingsStore, "getValue").mockReturnValue({ "$foo:bar": false }); + render(); + expect(screen.queryByRole("button")).toBeNull(); + }); + it("should hide button when event is hidden by showImages setting", async () => { + mockSetting(false, {}); + render(); + expect(screen.queryByRole("button")).toBeNull(); + }); + it("should store event as hidden when clicked", async () => { + const spy = jest.spyOn(SettingsStore, "setValue"); + render(); + fireEvent.click(screen.getByRole("button")); + expect(spy).toHaveBeenCalledWith("showMediaEventIds", null, SettingLevel.DEVICE, { "$foo:bar": false }); + // Button should be hidden after the setting is set. + expect(screen.queryByRole("button")).toBeNull(); + }); +}); diff --git a/test/unit-tests/components/views/messages/MImageBody-test.tsx b/test/unit-tests/components/views/messages/MImageBody-test.tsx index f9ba25d7a9..9d324f13e8 100644 --- a/test/unit-tests/components/views/messages/MImageBody-test.tsx +++ b/test/unit-tests/components/views/messages/MImageBody-test.tsx @@ -6,7 +6,7 @@ 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 from "react"; +import React, { act } from "react"; import { fireEvent, render, screen, waitForElementToBeRemoved } from "jest-matrix-react"; import { EventType, getHttpUriForMxc, MatrixEvent, Room } from "matrix-js-sdk/src/matrix"; import fetchMock from "fetch-mock-jest"; @@ -27,6 +27,7 @@ import { } from "../../../../test-utils"; import { MediaEventHelper } from "../../../../../src/utils/MediaEventHelper"; import SettingsStore from "../../../../../src/settings/SettingsStore"; +import { SettingLevel } from "../../../../../src/settings/SettingLevel"; jest.mock("matrix-encrypt-attachment", () => ({ decryptAttachment: jest.fn(), @@ -57,6 +58,7 @@ describe("", () => { }, ); const encryptedMediaEvent = new MatrixEvent({ + event_id: "$foo:bar", room_id: "!room:server", sender: userId, type: EventType.RoomMessage, @@ -131,7 +133,26 @@ describe("", () => { describe("with image previews/thumbnails disabled", () => { beforeEach(() => { - jest.spyOn(SettingsStore, "getValue").mockReturnValue(false); + act(() => { + SettingsStore.setValue("showImages", null, SettingLevel.DEVICE, false); + }); + }); + + afterEach(() => { + act(() => { + SettingsStore.setValue( + "showImages", + null, + SettingLevel.DEVICE, + SettingsStore.getDefaultValue("showImages"), + ); + SettingsStore.setValue( + "showMediaEventIds", + null, + SettingLevel.DEVICE, + SettingsStore.getDefaultValue("showMediaEventIds"), + ); + }); }); it("should not download image", async () => { @@ -163,7 +184,6 @@ describe("", () => { fireEvent.click(screen.getByRole("button")); - // image fetched after clicking show image expect(fetchMock).toHaveFetched(url); // spinner while downloading image diff --git a/test/unit-tests/hooks/useMediaVisible-test.tsx b/test/unit-tests/hooks/useMediaVisible-test.tsx new file mode 100644 index 0000000000..cafc32f1bf --- /dev/null +++ b/test/unit-tests/hooks/useMediaVisible-test.tsx @@ -0,0 +1,71 @@ +/* +Copyright 2025 New Vector 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 { act, renderHook, waitFor } from "jest-matrix-react"; + +import { useMediaVisible } from "../../../src/hooks/useMediaVisible"; +import SettingsStore from "../../../src/settings/SettingsStore"; +import { SettingLevel } from "../../../src/settings/SettingLevel"; + +const EVENT_ID = "$fibble:example.org"; + +function render() { + return renderHook(() => useMediaVisible(EVENT_ID)); +} + +describe("useMediaVisible", () => { + afterEach(() => { + // Using act here as otherwise React warns about state updates not being wrapped. + act(() => { + SettingsStore.setValue( + "showMediaEventIds", + null, + SettingLevel.DEVICE, + SettingsStore.getDefaultValue("showMediaEventIds"), + ); + SettingsStore.setValue( + "showImages", + null, + SettingLevel.DEVICE, + SettingsStore.getDefaultValue("showImages"), + ); + }); + }); + + it("should display images by default", async () => { + const { result } = render(); + expect(result.current[0]).toEqual(true); + }); + + it("should hide images when the default is changed", async () => { + SettingsStore.setValue("showImages", null, SettingLevel.DEVICE, false); + const { result } = render(); + expect(result.current[0]).toEqual(false); + }); + + it("should hide images after function is called", async () => { + const { result } = render(); + expect(result.current[0]).toEqual(true); + act(() => { + result.current[1](false); + }); + await waitFor(() => { + expect(result.current[0]).toEqual(false); + }); + }); + it("should show images after function is called", async () => { + SettingsStore.setValue("showImages", null, SettingLevel.DEVICE, false); + const { result } = render(); + expect(result.current[0]).toEqual(false); + act(() => { + result.current[1](true); + }); + await waitFor(() => { + expect(result.current[0]).toEqual(true); + }); + }); +}); From cdd2622151f5452079d132c68b902569cb2833dd Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 18 Mar 2025 14:35:39 +0000 Subject: [PATCH 098/458] Doc improvements from #29138 (#29503) * Rename props & fix typo * Docs * Better docs * Add comment * Fix typo * Paragraphs in tsdoc * Add comment * Hopefully clearer comment * Really fix typo Co-authored-by: Will Hunt * Stray word Co-authored-by: Andy Balaam * Hopefully clearer comment * Typo * Formatting & clarity Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --------- Co-authored-by: Will Hunt Co-authored-by: Andy Balaam Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- playwright/e2e/crypto/toasts.spec.ts | 4 +++- playwright/e2e/crypto/utils.ts | 3 +++ src/components/views/dialogs/UserSettingsDialog.tsx | 7 ++++++- .../views/settings/encryption/ResetIdentityPanel.tsx | 2 ++ .../settings/tabs/user/EncryptionUserSettingsTab.tsx | 8 ++++---- src/toasts/SetupEncryptionToast.ts | 1 + 6 files changed, 19 insertions(+), 6 deletions(-) diff --git a/playwright/e2e/crypto/toasts.spec.ts b/playwright/e2e/crypto/toasts.spec.ts index 905a8fb1ed..5b80f822a0 100644 --- a/playwright/e2e/crypto/toasts.spec.ts +++ b/playwright/e2e/crypto/toasts.spec.ts @@ -29,7 +29,9 @@ test.describe("Key storage out of sync toast", () => { }); test("should prompt for recovery key if 'enter recovery key' pressed", { tag: "@screenshot" }, async ({ page }) => { - // Need to wait for 2 to appear since playwright only evaluates 'first()' initially, so the waiting won't work + // We need to wait for there to be two toasts as the wait below won't work in isolation: + // playwright only evaluates the 'first()' call initially, not subsequent times it checks, so + // it would always be checking the same toast, even if another one is now the first. await expect(page.getByRole("alert")).toHaveCount(2); await expect(page.getByRole("alert").first()).toMatchScreenshot("key-storage-out-of-sync-toast.png"); diff --git a/playwright/e2e/crypto/utils.ts b/playwright/e2e/crypto/utils.ts index a317a2a215..0030dc02d0 100644 --- a/playwright/e2e/crypto/utils.ts +++ b/playwright/e2e/crypto/utils.ts @@ -221,6 +221,9 @@ export async function logIntoElement(page: Page, credentials: Credentials, secur await page.locator(".mx_AuthPage").getByRole("button", { name: "Verify with Recovery Key" }).click(); const useSecurityKey = page.locator(".mx_Dialog").getByRole("button", { name: "use your Recovery Key" }); + // If the user has set a recovery *passphrase*, they'll be prompted for that first and have to click + // through to enter the recovery key which is what we have here. If they haven't, they'll be prompted + // for a recovery key straight away. We click the button if it's there so this works in both cases. if (await useSecurityKey.isVisible()) { await useSecurityKey.click(); } diff --git a/src/components/views/dialogs/UserSettingsDialog.tsx b/src/components/views/dialogs/UserSettingsDialog.tsx index 6a94ae8842..4eb0a66f1a 100644 --- a/src/components/views/dialogs/UserSettingsDialog.tsx +++ b/src/components/views/dialogs/UserSettingsDialog.tsx @@ -50,6 +50,11 @@ import { EncryptionUserSettingsTab } from "../settings/tabs/user/EncryptionUserS interface IProps { initialTabId?: UserTab; showMsc4108QrCode?: boolean; + /** + * If `true`, the flow for a user to reset their encryption will be shown. In this case, `initialTabId` must be `UserTab.Encryption`. + * + * If false or undefined, show the tab as normal. + */ showResetIdentity?: boolean; sdkContext: SdkContextClass; onFinished(): void; @@ -92,7 +97,7 @@ function titleForTabID(tabId: UserTab): React.ReactNode { export default function UserSettingsDialog(props: IProps): JSX.Element { const voipEnabled = useSettingValue(UIFeature.Voip); const mjolnirEnabled = useSettingValue("feature_mjolnir"); - // store these props in state as changing tabs back and forth should clear it + // store these props in state as changing tabs back and forth should clear them const [showMsc4108QrCode, setShowMsc4108QrCode] = useState(props.showMsc4108QrCode); const [showResetIdentity, setShowResetIdentity] = useState(props.showResetIdentity); diff --git a/src/components/views/settings/encryption/ResetIdentityPanel.tsx b/src/components/views/settings/encryption/ResetIdentityPanel.tsx index 6c25985a22..9507e52872 100644 --- a/src/components/views/settings/encryption/ResetIdentityPanel.tsx +++ b/src/components/views/settings/encryption/ResetIdentityPanel.tsx @@ -31,8 +31,10 @@ interface ResetIdentityPanelProps { /** * The variant of the panel to show. We show more warnings in the 'compromised' variant (no use in showing a user this * warning if they have to reset because they no longer have their key) + * * "compromised" is shown when the user chooses 'reset' explicitly in settings, usually because they believe their * identity has been compromised. + * * "forgot" is shown when the user has just forgotten their passphrase. */ variant: "compromised" | "forgot"; diff --git a/src/components/views/settings/tabs/user/EncryptionUserSettingsTab.tsx b/src/components/views/settings/tabs/user/EncryptionUserSettingsTab.tsx index 3af555ed49..987b1d95b6 100644 --- a/src/components/views/settings/tabs/user/EncryptionUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/EncryptionUserSettingsTab.tsx @@ -37,7 +37,7 @@ import { DeleteKeyStoragePanel } from "../../encryption/DeleteKeyStoragePanel"; * This happens when the user has a recovery key and the user clicks on "Change recovery key" button of the RecoveryPanel. * - "set_recovery_key": The panel to show when the user is setting up their recovery key. * This happens when the user doesn't have a key a recovery key and the user clicks on "Set up recovery key" button of the RecoveryPanel. - * - "reset_identity_compromised": The panel to show when the user is resetting their identity, in te case where their key is compromised. + * - "reset_identity_compromised": The panel to show when the user is resetting their identity, in the case where their key is compromised. * - "reset_identity_forgot": The panel to show when the user is resetting their identity, in the case where they forgot their recovery key. * - "secrets_not_cached": The secrets are not cached locally. This can happen if we verified another device and secret-gossiping failed, or the other device itself lacked the secrets. * If the "set_up_encryption" and "secrets_not_cached" conditions are both filled, "set_up_encryption" prevails. @@ -55,9 +55,9 @@ export type State = | "secrets_not_cached" | "key_storage_delete"; -interface EncryptionUserSettingsTabProps { +interface Props { /** - * If the tab should start in a state other than the deasult + * If the tab should start in a state other than the default */ initialState?: State; } @@ -65,7 +65,7 @@ interface EncryptionUserSettingsTabProps { /** * The encryption settings tab. */ -export function EncryptionUserSettingsTab({ initialState = "loading" }: EncryptionUserSettingsTabProps): JSX.Element { +export function EncryptionUserSettingsTab({ initialState = "loading" }: Props): JSX.Element { const [state, setState] = useState(initialState); const checkEncryptionState = useCheckEncryptionState(state, setState); diff --git a/src/toasts/SetupEncryptionToast.ts b/src/toasts/SetupEncryptionToast.ts index 8a743dfe8b..1613c5b9c9 100644 --- a/src/toasts/SetupEncryptionToast.ts +++ b/src/toasts/SetupEncryptionToast.ts @@ -161,6 +161,7 @@ export const showToast = (kind: Kind): void => { const onSecondaryClick = (): void => { if (kind === Kind.KEY_STORAGE_OUT_OF_SYNC) { + // Open the user settings dialog to the encryption tab and start the flow to reset encryption const payload: OpenToTabPayload = { action: Action.ViewUserSettings, initialTabId: UserTab.Encryption, From 56d115c2ff02842ea93b99f51bb5c6057656b01d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 14:38:09 +0000 Subject: [PATCH 099/458] Update dependency testcontainers to v10.21.0 (#29520) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 7843a43c27..28ffb3d2d8 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "oidc-client-ts": "3.1.0", "jwt-decode": "4.0.0", "caniuse-lite": "1.0.30001701", - "testcontainers": "10.20.0", + "testcontainers": "10.21.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0", "wrap-ansi": "npm:wrap-ansi@^7.0.0" }, diff --git a/yarn.lock b/yarn.lock index 600521f2b9..2f3f84e092 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3614,7 +3614,6 @@ "@vector-im/matrix-wysiwyg-wasm@link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.2-3fa19a2a17fd12d955ef1e14fd63aecbcf3b95e8-integrity/node_modules/bindings/wysiwyg-wasm": version "0.0.0" - uid "" "@vector-im/matrix-wysiwyg@2.38.2": version "2.38.2" @@ -12001,10 +12000,10 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" -testcontainers@10.20.0, testcontainers@^10.18.0, testcontainers@^10.19.0, testcontainers@^10.20.0: - version "10.20.0" - resolved "https://registry.yarnpkg.com/testcontainers/-/testcontainers-10.20.0.tgz#45c524ae4be9b1ffe2fb42b701f6c0a04ee2d90a" - integrity sha512-pOPm/OUIT41aMijAZ9RsYg5xOq9ciy93+pCf2D9qDI0oV8rwk91XpPoUlizll4qwxmmHsLmfZFHJTpeB+BIfmw== +testcontainers@10.21.0, testcontainers@^10.18.0, testcontainers@^10.19.0, testcontainers@^10.20.0: + version "10.21.0" + resolved "https://registry.yarnpkg.com/testcontainers/-/testcontainers-10.21.0.tgz#ee1973d9f783984853965da22035b58627253b81" + integrity sha512-avzqNfP0HyHaOPTztHbGnHycZWzWaeUwSPnJGCYin2LB+n/tlGjAzExVrkIaCSBwIjFkMlufEYuKWzGc8mupDQ== dependencies: "@balena/dockerignore" "^1.0.2" "@types/dockerode" "^3.3.29" From 0bef21267990d4237f5b72801de97c83f77e6fc3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 14:56:34 +0000 Subject: [PATCH 100/458] Update docker/login-action digest to 74a5d14 (#29521) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/docker.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index 35630e4c2e..1cf24facde 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -37,14 +37,14 @@ jobs: install: true - name: Login to Docker Hub - uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3 if: github.event_name != 'pull_request' with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Login to GitHub Container Registry - uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3 if: github.event_name != 'pull_request' with: registry: ghcr.io From 7b809171fcfa6ddbdabac8943237a2615525a572 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 15:01:19 +0000 Subject: [PATCH 101/458] Update guibranco/github-status-action-v2 digest to fe98467 (#29522) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 710e996b39..e94c35299a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -104,7 +104,7 @@ jobs: - name: Skip SonarCloud in merge queue if: github.event_name == 'merge_group' || inputs.disable_coverage == 'true' - uses: guibranco/github-status-action-v2@5ef6e175c333bc629f3718b083c8a2ff6e0bbfbc + uses: guibranco/github-status-action-v2@fe98467f9071758c7fc214af9dbac7f301bd23d4 with: authToken: ${{ secrets.GITHUB_TOKEN }} state: success From c6b1a92f2ebc98db30389238720296580975db67 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 15:01:24 +0000 Subject: [PATCH 102/458] Update babel monorepo to v7.26.10 (#29523) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 126 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 73 insertions(+), 53 deletions(-) diff --git a/yarn.lock b/yarn.lock index 2f3f84e092..5a4be83d3e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -57,20 +57,20 @@ integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ== "@babel/core@^7.0.0", "@babel/core@^7.11.6", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.18.5", "@babel/core@^7.21.3", "@babel/core@^7.23.9", "@babel/core@^7.24.4": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.9.tgz#71838542a4b1e49dfed353d7acbc6eb89f4a76f2" - integrity sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw== + version "7.26.10" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.10.tgz#5c876f83c8c4dcb233ee4b670c0606f2ac3000f9" + integrity sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ== dependencies: "@ampproject/remapping" "^2.2.0" "@babel/code-frame" "^7.26.2" - "@babel/generator" "^7.26.9" + "@babel/generator" "^7.26.10" "@babel/helper-compilation-targets" "^7.26.5" "@babel/helper-module-transforms" "^7.26.0" - "@babel/helpers" "^7.26.9" - "@babel/parser" "^7.26.9" + "@babel/helpers" "^7.26.10" + "@babel/parser" "^7.26.10" "@babel/template" "^7.26.9" - "@babel/traverse" "^7.26.9" - "@babel/types" "^7.26.9" + "@babel/traverse" "^7.26.10" + "@babel/types" "^7.26.10" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" @@ -78,18 +78,18 @@ semver "^6.3.1" "@babel/eslint-parser@^7.12.10": - version "7.26.8" - resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.26.8.tgz#55c4f4aae4970ae127f7a12369182ed6250e6f09" - integrity sha512-3tBctaHRW6xSub26z7n8uyOTwwUsCdvIug/oxBH9n6yCO5hMj2vwDJAo7RbBMKrM7P+W2j61zLKviJQFGOYKMg== + version "7.26.10" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.26.10.tgz#4423cb3f84c26978439feabfe23c5aa929400737" + integrity sha512-QsfQZr4AiLpKqn7fz+j7SN+f43z2DZCgGyYbNJ2vJOqKfG4E6MZer1+jqGZqKJaxq/gdO2DC/nUu45+pOL5p2Q== dependencies: "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" eslint-visitor-keys "^2.1.0" semver "^6.3.1" "@babel/eslint-plugin@^7.12.10": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/eslint-plugin/-/eslint-plugin-7.25.9.tgz#a5b6cc46085e0a7d45c5dae36055ce30c5125dab" - integrity sha512-MWg1lz+JiP9l1fXkE0qCUVo+1XwgNRPs6GTc88hmw6qN3AdgmfTSkyHt0e1xOTsKdXW5xlh2Lsk3wrFZbW5rzQ== + version "7.26.10" + resolved "https://registry.yarnpkg.com/@babel/eslint-plugin/-/eslint-plugin-7.26.10.tgz#63c70823e8f4875dab8b976aa03d7246ca23d531" + integrity sha512-vOFlmZX0tzi58ggN8w2LGNOY2VOoqgYBtj2FRy+3BjFSvNvU+RnapXywHACzLqzbDi9yvS0CZEBokJ26ioUVLA== dependencies: eslint-rule-composer "^0.3.0" @@ -103,13 +103,13 @@ "@jridgewell/trace-mapping" "^0.3.25" jsesc "^3.0.2" -"@babel/generator@^7.26.9": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.9.tgz#75a9482ad3d0cc7188a537aa4910bc59db67cbca" - integrity sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg== +"@babel/generator@^7.26.10", "@babel/generator@^7.26.9": + version "7.26.10" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.10.tgz#a60d9de49caca16744e6340c3658dfef6138c3f7" + integrity sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang== dependencies: - "@babel/parser" "^7.26.9" - "@babel/types" "^7.26.9" + "@babel/parser" "^7.26.10" + "@babel/types" "^7.26.10" "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.25" jsesc "^3.0.2" @@ -154,7 +154,7 @@ regexpu-core "^6.2.0" semver "^6.3.1" -"@babel/helper-define-polyfill-provider@^0.6.2", "@babel/helper-define-polyfill-provider@^0.6.3": +"@babel/helper-define-polyfill-provider@^0.6.3": version "0.6.3" resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz#f4f2792fae2ef382074bc2d713522cf24e6ddb21" integrity sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg== @@ -265,13 +265,13 @@ "@babel/traverse" "^7.25.9" "@babel/types" "^7.25.9" -"@babel/helpers@^7.26.9": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.9.tgz#28f3fb45252fc88ef2dc547c8a911c255fc9fef6" - integrity sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA== +"@babel/helpers@^7.26.10": + version "7.26.10" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.10.tgz#6baea3cd62ec2d0c1068778d63cb1314f6637384" + integrity sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g== dependencies: "@babel/template" "^7.26.9" - "@babel/types" "^7.26.9" + "@babel/types" "^7.26.10" "@babel/highlight@^7.25.7": version "7.25.9" @@ -297,12 +297,12 @@ dependencies: "@babel/types" "^7.26.3" -"@babel/parser@^7.26.9": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.9.tgz#d9e78bee6dc80f9efd8f2349dcfbbcdace280fd5" - integrity sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A== +"@babel/parser@^7.26.10", "@babel/parser@^7.26.9": + version "7.26.10" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.10.tgz#e9bdb82f14b97df6569b0b038edd436839c57749" + integrity sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA== dependencies: - "@babel/types" "^7.26.9" + "@babel/types" "^7.26.10" "@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.9": version "7.25.9" @@ -903,14 +903,14 @@ "@babel/helper-plugin-utils" "^7.25.9" "@babel/plugin-transform-runtime@^7.12.10": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.9.tgz#ea8be19ef134668e98f7b54daf7c4f853859dc44" - integrity sha512-Jf+8y9wXQbbxvVYTM8gO5oEF2POdNji0NMltEkG7FtmzD9PVz7/lxpqSdTvwsjTMU5HIHuDVNf2SOxLkWi+wPQ== + version "7.26.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.10.tgz#6b4504233de8238e7d666c15cde681dc62adff87" + integrity sha512-NWaL2qG6HRpONTnj4JvDU6th4jYeZOJgu3QhmFTCihib0ermtOJqktA5BduGm3suhhVe9EMP9c9+mfJ/I9slqw== dependencies: "@babel/helper-module-imports" "^7.25.9" "@babel/helper-plugin-utils" "^7.26.5" babel-plugin-polyfill-corejs2 "^0.4.10" - babel-plugin-polyfill-corejs3 "^0.10.6" + babel-plugin-polyfill-corejs3 "^0.11.0" babel-plugin-polyfill-regenerator "^0.6.1" semver "^6.3.1" @@ -1137,7 +1137,20 @@ debug "^4.3.1" globals "^11.1.0" -"@babel/traverse@^7.25.9", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.8", "@babel/traverse@^7.26.9": +"@babel/traverse@^7.25.9", "@babel/traverse@^7.26.10": + version "7.26.10" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.10.tgz#43cca33d76005dbaa93024fae536cc1946a4c380" + integrity sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A== + dependencies: + "@babel/code-frame" "^7.26.2" + "@babel/generator" "^7.26.10" + "@babel/parser" "^7.26.10" + "@babel/template" "^7.26.9" + "@babel/types" "^7.26.10" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/traverse@^7.26.5", "@babel/traverse@^7.26.8", "@babel/traverse@^7.26.9": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.9.tgz#4398f2394ba66d05d988b2ad13c219a2c857461a" integrity sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg== @@ -1167,10 +1180,10 @@ "@babel/helper-string-parser" "^7.25.9" "@babel/helper-validator-identifier" "^7.25.9" -"@babel/types@^7.25.9", "@babel/types@^7.26.9", "@babel/types@^7.4.4": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.9.tgz#08b43dec79ee8e682c2ac631c010bdcac54a21ce" - integrity sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw== +"@babel/types@^7.25.9", "@babel/types@^7.26.10", "@babel/types@^7.26.9": + version "7.26.10" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.10.tgz#396382f6335bd4feb65741eacfc808218f859259" + integrity sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ== dependencies: "@babel/helper-string-parser" "^7.25.9" "@babel/helper-validator-identifier" "^7.25.9" @@ -1183,6 +1196,14 @@ "@babel/helper-string-parser" "^7.25.9" "@babel/helper-validator-identifier" "^7.25.9" +"@babel/types@^7.4.4": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.9.tgz#08b43dec79ee8e682c2ac631c010bdcac54a21ce" + integrity sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw== + dependencies: + "@babel/helper-string-parser" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + "@balena/dockerignore@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@balena/dockerignore/-/dockerignore-1.0.2.tgz#9ffe4726915251e8eb69f44ef3547e0da2c03e0d" @@ -4294,14 +4315,6 @@ babel-plugin-polyfill-corejs2@^0.4.10: "@babel/helper-define-polyfill-provider" "^0.6.3" semver "^6.3.1" -babel-plugin-polyfill-corejs3@^0.10.6: - version "0.10.6" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz#2deda57caef50f59c525aeb4964d3b2f867710c7" - integrity sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.6.2" - core-js-compat "^3.38.0" - babel-plugin-polyfill-corejs3@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz#4e4e182f1bb37c7ba62e2af81d8dd09df31344f6" @@ -4512,7 +4525,7 @@ braces@^3.0.3, braces@~3.0.2: dependencies: fill-range "^7.1.1" -browserslist@^4.0.0, browserslist@^4.23.1, browserslist@^4.23.2, browserslist@^4.23.3, browserslist@^4.24.0, browserslist@^4.24.3: +browserslist@^4.0.0, browserslist@^4.23.1, browserslist@^4.23.2, browserslist@^4.23.3, browserslist@^4.24.0, browserslist@^4.24.3, browserslist@^4.24.4: version "4.24.4" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.4.tgz#c6b2865a3f08bcb860a0e827389003b9fe686e4b" integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A== @@ -5011,13 +5024,20 @@ copy-webpack-plugin@^13.0.0: serialize-javascript "^6.0.2" tinyglobby "^0.2.12" -core-js-compat@^3.38.0, core-js-compat@^3.38.1, core-js-compat@^3.40.0: +core-js-compat@^3.38.1: version "3.40.0" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.40.0.tgz#7485912a5a4a4315c2fdb2cbdc623e6881c88b38" integrity sha512-0XEDpr5y5mijvw8Lbc6E5AkjrHfp7eEoPlu36SWeAbcL8fn1G1ANe8DBlo2XoNN89oVpxWwOjYIPVzR4ZvsKCQ== dependencies: browserslist "^4.24.3" +core-js-compat@^3.40.0: + version "3.41.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.41.0.tgz#4cdfce95f39a8f27759b667cf693d96e5dda3d17" + integrity sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A== + dependencies: + browserslist "^4.24.4" + core-js@^3.0.0, core-js@^3.38.1: version "3.40.0" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.40.0.tgz#2773f6b06877d8eda102fc42f828176437062476" @@ -5761,9 +5781,9 @@ ejs@^3.1.8: jake "^10.8.5" electron-to-chromium@^1.5.73: - version "1.5.112" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.112.tgz#8d3d95d4d5653836327890282c8eda5c6f26626d" - integrity sha512-oen93kVyqSb3l+ziUgzIOlWt/oOuy4zRmpwestMn4rhFWAoFJeFuCVte9F2fASjeZZo7l/Cif9TiyrdW4CwEMA== + version "1.5.120" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.120.tgz#ccfdd28e9795fb8c2221cefa2c9a071501c86247" + integrity sha512-oTUp3gfX1gZI+xfD2djr2rzQdHCwHzPQrrK0CD7WpTdF0nPdQ/INcRVjWgLdCT4a9W3jFObR9DAfsuyFQnI8CQ== emittery@^0.13.1: version "0.13.1" From 7e3866dd9a04e45a47afaead24b3468333c71611 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 15:01:50 +0000 Subject: [PATCH 103/458] Update dependency @types/node to v18.19.80 (#29524) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index 5a4be83d3e..7343e6d2ed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3207,14 +3207,7 @@ dependencies: undici-types "~6.20.0" -"@types/node@18": - version "18.19.79" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.79.tgz#82fde7ac17809f4738a494b22273f0f7e6754f6e" - integrity sha512-90K8Oayimbctc5zTPHPfZloc/lGVs7f3phUAAMcTgEPtg8kKquGZDERC8K4vkBYkQQh48msiYUslYtxTWvqcAg== - dependencies: - undici-types "~5.26.4" - -"@types/node@^18.11.18": +"@types/node@18", "@types/node@^18.11.18": version "18.19.80" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.80.tgz#6d6008e8920dddcd23f9dd33da24684ef57d487c" integrity sha512-kEWeMwMeIvxYkeg1gTc01awpwLbfMRZXdIhwRcakd/KlK53jmRC26LqcbIt7fnAQTu5GzlnWmzA3H6+l1u6xxQ== From 98c691670e5cd3281ba0b7d1f2e101668f36212d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 15:02:08 +0000 Subject: [PATCH 104/458] Update dependency @vector-im/compound-design-tokens to v4.0.1 (#29525) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7343e6d2ed..8f9182e44e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3607,9 +3607,9 @@ integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== "@vector-im/compound-design-tokens@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@vector-im/compound-design-tokens/-/compound-design-tokens-4.0.0.tgz#4922404f355f09fb753e6a91cc7efe4e661c9ff1" - integrity sha512-hFfLSKrGc58rPRp9JH1mkgw3moFEgpL8RQzyDESHErq7P1lUmlIuwKFTVfK5SbdFM5GvHp7nQaFpVmxUQ3Xp+w== + version "4.0.1" + resolved "https://registry.yarnpkg.com/@vector-im/compound-design-tokens/-/compound-design-tokens-4.0.1.tgz#5c4ea7ad664d8e6206dc42e41649c80ef060a760" + integrity sha512-V4AsK1FVFxZ6DmmCoeAi8FyvE7ODMlXPWjqRGotcnVaoGNrDQrVz2ZGV85DCz5ISxB3iynYASe6OXsDVXT1zFA== "@vector-im/compound-web@^7.7.2": version "7.7.2" From c85e6d196d780b749c178d7d0450d78de2654d30 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 15:02:36 +0000 Subject: [PATCH 105/458] Update dependency @playwright/test to v1.51.0 (#29528) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 23 +---------------------- 2 files changed, 2 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index 28ffb3d2d8..a62686b89d 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "update:jitsi": "curl -s https://meet.element.io/libs/external_api.min.js > ./res/jitsi_external_api.min.js" }, "resolutions": { - "@playwright/test": "1.50.1", + "@playwright/test": "1.51.0", "@types/react": "18.3.18", "@types/react-dom": "18.3.5", "oidc-client-ts": "3.1.0", diff --git a/yarn.lock b/yarn.lock index 8f9182e44e..ed842f9734 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2201,14 +2201,7 @@ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== -"@playwright/test@1.50.1": - version "1.50.1" - resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.50.1.tgz#027d00ca77ec79688764eb765cfe9a688807bf0b" - integrity sha512-Jii3aBg+CEDpgnuDxEp/h7BimHcUTDlpEtce89xEumlJ5ef2hqepZ+PWp1DDpYC/VO9fmWVI1IlEaoI5fK9FXQ== - dependencies: - playwright "1.50.1" - -"@playwright/test@^1.50.1": +"@playwright/test@1.51.0", "@playwright/test@^1.50.1": version "1.51.0" resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.51.0.tgz#8d5c8400b465a0bfdbcf993e390ceecb903ea6d2" integrity sha512-dJ0dMbZeHhI+wb77+ljx/FeC8VBP6j/rj9OAojO08JI80wTZy6vRk9KvHKiDCUh4iMpEiseMgqRBIeW+eKX6RA== @@ -9607,25 +9600,11 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -playwright-core@1.50.1: - version "1.50.1" - resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.50.1.tgz#6a0484f1f1c939168f40f0ab3828c4a1592c4504" - integrity sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ== - playwright-core@1.51.0, playwright-core@^1.51.0: version "1.51.0" resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.51.0.tgz#bb23ea6bb6298242d088ae5e966ffcf8dc9827e8" integrity sha512-x47yPE3Zwhlil7wlNU/iktF7t2r/URR3VLbH6EknJd/04Qc/PSJ0EY3CMXipmglLG+zyRxW6HNo2EGbKLHPWMg== -playwright@1.50.1: - version "1.50.1" - resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.50.1.tgz#2f93216511d65404f676395bfb97b41aa052b180" - integrity sha512-G8rwsOQJ63XG6BbKj2w5rHeavFjy5zynBA9zsJMMtBoe/Uf757oG12NXz6e6OirF7RCrTVAKFXbLmn1RbL7Qaw== - dependencies: - playwright-core "1.50.1" - optionalDependencies: - fsevents "2.3.2" - playwright@1.51.0: version "1.51.0" resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.51.0.tgz#9ba154497ba62bc6dc199c58ee19295eb35a4707" From 6ed811d4c994b75c424b878766202d15b9410eac Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 15:02:39 +0000 Subject: [PATCH 106/458] Update typescript-eslint monorepo to v8.26.1 (#29527) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 102 +++++++++++++++++++++++++++--------------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/yarn.lock b/yarn.lock index ed842f9734..d28c129469 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1593,9 +1593,9 @@ eslint-visitor-keys "^3.3.0" "@eslint-community/eslint-utils@^4.4.0": - version "4.4.1" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56" - integrity sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA== + version "4.5.1" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz#b0fc7e06d0c94f801537fd4237edc2706d3b8e4c" + integrity sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w== dependencies: eslint-visitor-keys "^3.4.3" @@ -3424,29 +3424,29 @@ "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@^8.19.0": - version "8.26.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.0.tgz#7e880faf91f89471c30c141951e15f0eb3a0599e" - integrity sha512-cLr1J6pe56zjKYajK6SSSre6nl1Gj6xDp1TY0trpgPzjVbgDwd09v2Ws37LABxzkicmUjhEeg/fAUjPJJB1v5Q== + version "8.26.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.1.tgz#3e48eb847924161843b092c87a9b65176b53782f" + integrity sha512-2X3mwqsj9Bd3Ciz508ZUtoQQYpOhU/kWoUqIf49H8Z0+Vbh6UF/y0OEYp0Q0axOGzaBGs7QxRwq0knSQ8khQNA== dependencies: "@eslint-community/regexpp" "^4.10.0" - "@typescript-eslint/scope-manager" "8.26.0" - "@typescript-eslint/type-utils" "8.26.0" - "@typescript-eslint/utils" "8.26.0" - "@typescript-eslint/visitor-keys" "8.26.0" + "@typescript-eslint/scope-manager" "8.26.1" + "@typescript-eslint/type-utils" "8.26.1" + "@typescript-eslint/utils" "8.26.1" + "@typescript-eslint/visitor-keys" "8.26.1" graphemer "^1.4.0" ignore "^5.3.1" natural-compare "^1.4.0" ts-api-utils "^2.0.1" "@typescript-eslint/parser@^8.19.0": - version "8.26.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.26.0.tgz#9b4d2198e89f64fb81e83167eedd89a827d843a9" - integrity sha512-mNtXP9LTVBy14ZF3o7JG69gRPBK/2QWtQd0j0oH26HcY/foyJJau6pNUez7QrM5UHnSvwlQcJXKsk0I99B9pOA== + version "8.26.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.26.1.tgz#0e2f915a497519fc43f52cf2ecbfa607ff56f72e" + integrity sha512-w6HZUV4NWxqd8BdeFf81t07d7/YV9s7TCWrQQbG5uhuvGUAW+fq1usZ1Hmz9UPNLniFnD8GLSsDpjP0hm1S4lQ== dependencies: - "@typescript-eslint/scope-manager" "8.26.0" - "@typescript-eslint/types" "8.26.0" - "@typescript-eslint/typescript-estree" "8.26.0" - "@typescript-eslint/visitor-keys" "8.26.0" + "@typescript-eslint/scope-manager" "8.26.1" + "@typescript-eslint/types" "8.26.1" + "@typescript-eslint/typescript-estree" "8.26.1" + "@typescript-eslint/visitor-keys" "8.26.1" debug "^4.3.4" "@typescript-eslint/scope-manager@8.23.0": @@ -3465,21 +3465,21 @@ "@typescript-eslint/types" "8.24.1" "@typescript-eslint/visitor-keys" "8.24.1" -"@typescript-eslint/scope-manager@8.26.0": - version "8.26.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.26.0.tgz#b06623fad54a3a77fadab5f652ef75ed3780b545" - integrity sha512-E0ntLvsfPqnPwng8b8y4OGuzh/iIOm2z8U3S9zic2TeMLW61u5IH2Q1wu0oSTkfrSzwbDJIB/Lm8O3//8BWMPA== +"@typescript-eslint/scope-manager@8.26.1": + version "8.26.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.26.1.tgz#5e6ad0ac258ccf79462e91c3f43a3f1f7f31a6cc" + integrity sha512-6EIvbE5cNER8sqBu6V7+KeMZIC1664d2Yjt+B9EWUXrsyWpxx4lEZrmvxgSKRC6gX+efDL/UY9OpPZ267io3mg== dependencies: - "@typescript-eslint/types" "8.26.0" - "@typescript-eslint/visitor-keys" "8.26.0" + "@typescript-eslint/types" "8.26.1" + "@typescript-eslint/visitor-keys" "8.26.1" -"@typescript-eslint/type-utils@8.26.0": - version "8.26.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.26.0.tgz#9ee8cc98184b5f66326578de9c097edc89da6f68" - integrity sha512-ruk0RNChLKz3zKGn2LwXuVoeBcUMh+jaqzN461uMMdxy5H9epZqIBtYj7UiPXRuOpaALXGbmRuZQhmwHhaS04Q== +"@typescript-eslint/type-utils@8.26.1": + version "8.26.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.26.1.tgz#462f0bae09de72ac6e8e1af2ebe588c23224d7f8" + integrity sha512-Kcj/TagJLwoY/5w9JGEFV0dclQdyqw9+VMndxOJKtoFSjfZhLXhYjzsQEeyza03rwHx2vFEGvrJWJBXKleRvZg== dependencies: - "@typescript-eslint/typescript-estree" "8.26.0" - "@typescript-eslint/utils" "8.26.0" + "@typescript-eslint/typescript-estree" "8.26.1" + "@typescript-eslint/utils" "8.26.1" debug "^4.3.4" ts-api-utils "^2.0.1" @@ -3493,10 +3493,10 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.24.1.tgz#8777a024f3afc4ace5e48f9a804309c6dd38f95a" integrity sha512-9kqJ+2DkUXiuhoiYIUvIYjGcwle8pcPpdlfkemGvTObzgmYfJ5d0Qm6jwb4NBXP9W1I5tss0VIAnWFumz3mC5A== -"@typescript-eslint/types@8.26.0": - version "8.26.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.26.0.tgz#c4e93a8faf3a38a8d8adb007dc7834f1c89ee7bf" - integrity sha512-89B1eP3tnpr9A8L6PZlSjBvnJhWXtYfZhECqlBl1D9Lme9mHO6iWlsprBtVenQvY1HMhax1mWOjhtL3fh/u+pA== +"@typescript-eslint/types@8.26.1": + version "8.26.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.26.1.tgz#d5978721670cff263348d5062773389231a64132" + integrity sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ== "@typescript-eslint/typescript-estree@8.23.0": version "8.23.0" @@ -3526,13 +3526,13 @@ semver "^7.6.0" ts-api-utils "^2.0.1" -"@typescript-eslint/typescript-estree@8.26.0": - version "8.26.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.26.0.tgz#128972172005a7376e34ed2ecba4e29363b0cad1" - integrity sha512-tiJ1Hvy/V/oMVRTbEOIeemA2XoylimlDQ03CgPPNaHYZbpsc78Hmngnt+WXZfJX1pjQ711V7g0H7cSJThGYfPQ== +"@typescript-eslint/typescript-estree@8.26.1": + version "8.26.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.26.1.tgz#eb0e4ce31753683d83be53441a409fd5f0b34afd" + integrity sha512-yUwPpUHDgdrv1QJ7YQal3cMVBGWfnuCdKbXw1yyjArax3353rEJP1ZA+4F8nOlQ3RfS2hUN/wze3nlY+ZOhvoA== dependencies: - "@typescript-eslint/types" "8.26.0" - "@typescript-eslint/visitor-keys" "8.26.0" + "@typescript-eslint/types" "8.26.1" + "@typescript-eslint/visitor-keys" "8.26.1" debug "^4.3.4" fast-glob "^3.3.2" is-glob "^4.0.3" @@ -3540,15 +3540,15 @@ semver "^7.6.0" ts-api-utils "^2.0.1" -"@typescript-eslint/utils@8.26.0": - version "8.26.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.26.0.tgz#845d20ed8378a5594e6445f54e53b972aee7b3e6" - integrity sha512-2L2tU3FVwhvU14LndnQCA2frYC8JnPDVKyQtWFPf8IYFMt/ykEN1bPolNhNbCVgOmdzTlWdusCTKA/9nKrf8Ig== +"@typescript-eslint/utils@8.26.1": + version "8.26.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.26.1.tgz#54cc58469955f25577f659753b71a0e117a0539f" + integrity sha512-V4Urxa/XtSUroUrnI7q6yUTD3hDtfJ2jzVfeT3VK0ciizfK2q/zGC0iDh1lFMUZR8cImRrep6/q0xd/1ZGPQpg== dependencies: "@eslint-community/eslint-utils" "^4.4.0" - "@typescript-eslint/scope-manager" "8.26.0" - "@typescript-eslint/types" "8.26.0" - "@typescript-eslint/typescript-estree" "8.26.0" + "@typescript-eslint/scope-manager" "8.26.1" + "@typescript-eslint/types" "8.26.1" + "@typescript-eslint/typescript-estree" "8.26.1" "@typescript-eslint/utils@^6.0.0 || ^7.0.0 || ^8.0.0": version "8.23.0" @@ -3586,12 +3586,12 @@ "@typescript-eslint/types" "8.24.1" eslint-visitor-keys "^4.2.0" -"@typescript-eslint/visitor-keys@8.26.0": - version "8.26.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.26.0.tgz#a4876216756c69130ea958df3b77222c2ad95290" - integrity sha512-2z8JQJWAzPdDd51dRQ/oqIJxe99/hoLIqmf8RMCAJQtYDc535W/Jt2+RTP4bP0aKeBG1F65yjIZuczOXCmbWwg== +"@typescript-eslint/visitor-keys@8.26.1": + version "8.26.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.26.1.tgz#c5267fcc82795cf10280363023837deacad2647c" + integrity sha512-AjOC3zfnxd6S4Eiy3jwktJPclqhFHNyd8L6Gycf9WUPoKZpgM5PjkxY1X7uSy61xVpiJDhhk7XT2NVsN3ALTWg== dependencies: - "@typescript-eslint/types" "8.26.0" + "@typescript-eslint/types" "8.26.1" eslint-visitor-keys "^4.2.0" "@ungap/structured-clone@^1.2.0": From 2a8b26d90ab04c3332f44676d286e59cb2a3b06f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 15:03:01 +0000 Subject: [PATCH 107/458] Update dependency @sentry/browser to v9.5.0 (#29529) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 68 +++++++++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/yarn.lock b/yarn.lock index d28c129469..17d89bc76c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2504,35 +2504,35 @@ resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g== -"@sentry-internal/browser-utils@9.3.0": - version "9.3.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-9.3.0.tgz#345fa61da239186fa0ad6c7194d4a1f7df7646c7" - integrity sha512-G3z4HCUyb5nJe03EPUhWjnaHqMDt4mOTFJDNha3DGoB51lMYojpQI1Qo1u6bY4qkWVSO1c+HqOU0RVsXoAchtQ== +"@sentry-internal/browser-utils@9.6.0": + version "9.6.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-9.6.0.tgz#a3c0cc17f3562e40bca0085df5c4374f91aea44d" + integrity sha512-zk64wOc3jIHDeZ26sksRg4TfdpuAG6VP0/VZyXKX0f3QVi/jzb1VoVGfP7/BdtLo2Be1+60f7gGPyt/wvcJkqg== dependencies: - "@sentry/core" "9.3.0" + "@sentry/core" "9.6.0" -"@sentry-internal/feedback@9.3.0": - version "9.3.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-9.3.0.tgz#d60bcedd01907478b286512ce54f59682b2910e0" - integrity sha512-LQmIbQaATlN5QEwCD2Xt+7VKfwfR5W3dbn0jdF1x4hQFE/srdnOj60xMz/mj3tP5BxV552xJniGsyZ8lXHDb2A== +"@sentry-internal/feedback@9.6.0": + version "9.6.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-9.6.0.tgz#29ee78a66ff13513c84b0060a05fd8a5aa8ba361" + integrity sha512-SWGJC2eRl28KU7IHLDhHj1Kv0S9a6m1F+YYuve3ypIoYNkIyLJjy8EV6KM/Byepm+QhVTlFLh2bOQl8LUMjsNw== dependencies: - "@sentry/core" "9.3.0" + "@sentry/core" "9.6.0" -"@sentry-internal/replay-canvas@9.3.0": - version "9.3.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-9.3.0.tgz#b9432ab65152304b5f86f99efdeffcd92091f733" - integrity sha512-MhDMJeRGa55a0D541+OzTFMWwbabthhDGbAL90/NpappfyeBbAiktmCNl0BFTZuRbCGrC2m1LLCqHegCVKW4fQ== +"@sentry-internal/replay-canvas@9.6.0": + version "9.6.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-9.6.0.tgz#7ecadcfab98a1d9a7734e3edf3e0c37e1e3c1417" + integrity sha512-xNZPQvgNJ4CJSn+3tGaYao57yRqDLh79r2cf29P69jLSmKN5TT04thdMr/urCb9Ba9rcmG3uIAcJv8Y3SNm8gA== dependencies: - "@sentry-internal/replay" "9.3.0" - "@sentry/core" "9.3.0" + "@sentry-internal/replay" "9.6.0" + "@sentry/core" "9.6.0" -"@sentry-internal/replay@9.3.0": - version "9.3.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-9.3.0.tgz#c846cf77cd8deefda84316f1a938bbeae5861564" - integrity sha512-ZkH+Gahn89JygpuiFn26ZgAqJXHtnr+HjfQ2ONOFoWQHNH6X5wk75UTma55aYk1d8VcBPFoU6WjFhZoQ55SV1g== +"@sentry-internal/replay@9.6.0": + version "9.6.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-9.6.0.tgz#eb8f75a66bbea708c7a668e452c64808f8254ed7" + integrity sha512-+F9xcc4XIMzLgItis3kScbUZgOPrtMIwRL61gzSoYFyYAAp+in3Kq9vJ1eY+LcQKKnJ0DgzUFXU8YVs3yRTWxg== dependencies: - "@sentry-internal/browser-utils" "9.3.0" - "@sentry/core" "9.3.0" + "@sentry-internal/browser-utils" "9.6.0" + "@sentry/core" "9.6.0" "@sentry/babel-plugin-component-annotate@3.2.1": version "3.2.1" @@ -2540,15 +2540,15 @@ integrity sha512-tUp2e+CERpRFzTftjPxt7lg4BF0R3K+wGfeJyIqrc0tbJ2y6duT8OD0ArWoOi1g8xQ73NDn1/mEeS8pC+sbjTQ== "@sentry/browser@^9.0.0": - version "9.3.0" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-9.3.0.tgz#270e93c0f1bc10abb6651255bcaa30ba21c4928a" - integrity sha512-yPwWWQo/hpN63p0NGmk/Dd1Fx5CQRWNMfuV7dtfPBtg3vRjDecA9OLyK29AqK5h3Fl8FuJOyOqB87CvtXUqh5g== + version "9.6.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-9.6.0.tgz#220235296ffde3edbb3fffe39d8f9ca4413763f8" + integrity sha512-8tOmdbaEUVcousqnqhQ0bx+IG8kXVYV1dXgSvFQUaCsm0TEWMosoN25cSridImTN9B0M6YBY0ONx1cdKdRmw/w== dependencies: - "@sentry-internal/browser-utils" "9.3.0" - "@sentry-internal/feedback" "9.3.0" - "@sentry-internal/replay" "9.3.0" - "@sentry-internal/replay-canvas" "9.3.0" - "@sentry/core" "9.3.0" + "@sentry-internal/browser-utils" "9.6.0" + "@sentry-internal/feedback" "9.6.0" + "@sentry-internal/replay" "9.6.0" + "@sentry-internal/replay-canvas" "9.6.0" + "@sentry/core" "9.6.0" "@sentry/bundler-plugin-core@3.2.1": version "3.2.1" @@ -2618,10 +2618,10 @@ "@sentry/cli-win32-i686" "2.42.2" "@sentry/cli-win32-x64" "2.42.2" -"@sentry/core@9.3.0": - version "9.3.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-9.3.0.tgz#d5a1ab7deecd95f86316e658129d3874557cbfd9" - integrity sha512-SxQ4z7wTkfguvYb2ctNEMU9kVAbhl9ymfjhLnrvtygTwL5soLqAKdco/lX/4P9K9Osgb2Dl6urQWRl+AhzKVbQ== +"@sentry/core@9.6.0": + version "9.6.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-9.6.0.tgz#15e1a43d4e6371fac66c2d83233aeb09c4cea035" + integrity sha512-t51h6HKlPYW3TfeM09mZ6uDd95A7lgYpD5lUV54ilBA3TefS+M9I32MKwAW7yHzzWs0WQxOdm56eoDBOmRDpHQ== "@sentry/webpack-plugin@^3.0.0": version "3.2.1" From f3654e45d6647234736e03161089dfd76058f710 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 15:04:34 +0000 Subject: [PATCH 108/458] Update dependency stylelint to v16.16.0 (#29530) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/yarn.lock b/yarn.lock index 17d89bc76c..686accf0a8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6545,7 +6545,7 @@ fflate@^0.4.8: resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.4.8.tgz#f90b82aefbd8ac174213abb338bd7ef848f0f5ae" integrity sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA== -file-entry-cache@^10.0.6: +file-entry-cache@^10.0.7: version "10.0.7" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-10.0.7.tgz#e0ac34d4b8c44bea8a0a27ceb4dae982f2d32749" integrity sha512-txsf5fu3anp2ff3+gOJJzRImtrtm/oa9tYLN0iTuINZ++EyVR/nRrg2fKYwvG/pXDofcrvvb0scEbX3NyW/COw== @@ -7087,9 +7087,9 @@ hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: react-is "^16.7.0" hookified@^1.7.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/hookified/-/hookified-1.7.1.tgz#b08228173e06e9e8767bae1dffb216b8c6171b41" - integrity sha512-OXcdHsXeOiD7OJ5zvWj8Oy/6RCdLwntAX+wUrfemNcMGn6sux4xbEHi2QXwqePYhjQ/yvxxq2MvCRirdlHscBw== + version "1.8.1" + resolved "https://registry.yarnpkg.com/hookified/-/hookified-1.8.1.tgz#74a8c97d36e5f8004d230ee2156a607cc84c358c" + integrity sha512-GrO2l93P8xCWBSTBX9l2BxI78VU/MAAYag+pG8curS3aBGy0++ZlxrQ7PdUOUVMbn5BwkGb6+eRrnf43ipnFEA== hosted-git-info@^2.1.4: version "2.8.9" @@ -8416,9 +8416,9 @@ keyv@^4.5.3: json-buffer "3.0.1" keyv@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-5.3.1.tgz#d3acebeecedafd4bf2b929e8866bcd79db071f1e" - integrity sha512-13hQT2q2VIwOoaJdJa7nY3J8UVbYtMTJFHnwm9LI+SaQRfUiM6Em9KZeOVTCKbMnGcRIL3NSUFpAdjZCq24nLQ== + version "5.3.2" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-5.3.2.tgz#32edd461b51d44d42926eb72946236d79c71ae78" + integrity sha512-Lji2XRxqqa5Wg+CHLVfFKBImfJZ4pCSccu9eVWK6w4c2SDFLd8JAn1zqTuSFnsxb7ope6rMsnIHfp+eBbRBRZQ== dependencies: "@keyv/serialize" "^1.0.3" @@ -9104,11 +9104,16 @@ nan@^2.19.0, nan@^2.20.0: resolved "https://registry.yarnpkg.com/nan/-/nan-2.22.2.tgz#6b504fd029fb8f38c0990e52ad5c26772fdacfbb" integrity sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ== -nanoid@^3.3.7, nanoid@^3.3.8: +nanoid@^3.3.7: version "3.3.8" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== +nanoid@^3.3.8: + version "3.3.10" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.10.tgz#7bc882237698ef787d5cbba109e3b0168ba6e7b1" + integrity sha512-vSJJTG+t/dIKAUhUDw/dLdZ9s//5OxcHqLaDWWrW4Cdq7o6tdLIczUkMXt2MBNmk6sJRZBZRXVixs7URY1CmIg== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -11751,9 +11756,9 @@ stylelint-value-no-unknown-custom-properties@^6.0.1: resolve "^1.22.8" stylelint@^16.13.0: - version "16.15.0" - resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-16.15.0.tgz#a561cd50ad468cc4898f5c57cc1f223287fdea59" - integrity sha512-OK6Rs7EPdcdmjqiDycadZY4fw3f5/TC1X6/tGjnF3OosbwCeNs7nG+79MCAtjEg7ckwqTJTsku08e0Rmaz5nUw== + version "16.16.0" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-16.16.0.tgz#ebecf27becd277aaf752e75de324023a1e13e486" + integrity sha512-40X5UOb/0CEFnZVEHyN260HlSSUxPES+arrUphOumGWgXERHfwCD0kNBVILgQSij8iliYVwlc0V7M5bcLP9vPg== dependencies: "@csstools/css-parser-algorithms" "^3.0.4" "@csstools/css-tokenizer" "^3.0.3" @@ -11768,7 +11773,7 @@ stylelint@^16.13.0: debug "^4.3.7" fast-glob "^3.3.3" fastest-levenshtein "^1.0.16" - file-entry-cache "^10.0.6" + file-entry-cache "^10.0.7" global-modules "^2.0.0" globby "^11.1.0" globjoin "^0.1.4" From e4f9c650ee1019b33f0f78017fc22325426c302b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 16:12:40 +0000 Subject: [PATCH 109/458] Update react monorepo (#28905) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 45 +++++++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/yarn.lock b/yarn.lock index 686accf0a8..390c172af9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -132,7 +132,7 @@ lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-create-class-features-plugin@^7.25.9": +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.25.9": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.26.9.tgz#d6f83e3039547fbb39967e78043cd3c8b7820c71" integrity sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg== @@ -290,14 +290,7 @@ dependencies: "@babel/types" "^7.25.8" -"@babel/parser@^7.24.4": - version "7.26.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.3.tgz#8c51c5db6ddf08134af1ddbacf16aaab48bac234" - integrity sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA== - dependencies: - "@babel/types" "^7.26.3" - -"@babel/parser@^7.26.10", "@babel/parser@^7.26.9": +"@babel/parser@^7.24.4", "@babel/parser@^7.26.10", "@babel/parser@^7.26.9": version "7.26.10" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.10.tgz#e9bdb82f14b97df6569b0b038edd436839c57749" integrity sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA== @@ -359,6 +352,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.25.9" +"@babel/plugin-proposal-private-methods@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea" + integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": version "7.21.0-placeholder-for-preset-env.2" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" @@ -1137,7 +1138,7 @@ debug "^4.3.1" globals "^11.1.0" -"@babel/traverse@^7.25.9", "@babel/traverse@^7.26.10": +"@babel/traverse@^7.25.9", "@babel/traverse@^7.26.10", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.9": version "7.26.10" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.10.tgz#43cca33d76005dbaa93024fae536cc1946a4c380" integrity sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A== @@ -1150,7 +1151,7 @@ debug "^4.3.1" globals "^11.1.0" -"@babel/traverse@^7.26.5", "@babel/traverse@^7.26.8", "@babel/traverse@^7.26.9": +"@babel/traverse@^7.26.8": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.9.tgz#4398f2394ba66d05d988b2ad13c219a2c857461a" integrity sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg== @@ -1188,14 +1189,6 @@ "@babel/helper-string-parser" "^7.25.9" "@babel/helper-validator-identifier" "^7.25.9" -"@babel/types@^7.26.3": - version "7.26.7" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.7.tgz#5e2b89c0768e874d4d061961f3a5a153d71dc17a" - integrity sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg== - dependencies: - "@babel/helper-string-parser" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" - "@babel/types@^7.4.4": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.9.tgz#08b43dec79ee8e682c2ac631c010bdcac54a21ce" @@ -6126,21 +6119,21 @@ eslint-plugin-matrix-org@^2.0.2: integrity sha512-YjVQ0qunzVV34tpUchLWhOrOalGfRLm0tclS4dPYnXS8Ui+p12o/YtRHt+26Mg5tJ0QH76HsGC0LJKLVLNoqfg== eslint-plugin-react-compiler@^19.0.0-beta-df7b47d-20241124: - version "19.0.0-beta-df7b47d-20241124" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-compiler/-/eslint-plugin-react-compiler-19.0.0-beta-df7b47d-20241124.tgz#468751d3a8a6781189405ee56b39b80545306df8" - integrity sha512-82PfnllC8jP/68KdLAbpWuYTcfmtGLzkqy2IW85WopKMTr+4rdQpp+lfliQ/QE79wWrv/dRoADrk3Pdhq25nTw== + version "19.0.0-beta-e552027-20250112" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-compiler/-/eslint-plugin-react-compiler-19.0.0-beta-e552027-20250112.tgz#f4ad9cebe47615ebf6097a8084a30d761ee164f4" + integrity sha512-VjkIXHouCYyJHgk5HmZ1LH+fAK5CX+ULRX9iNYtwYJ+ljbivFhIT+JJyxNT/USQpCeS2Dt5ahjFeeMv0RRwTww== dependencies: "@babel/core" "^7.24.4" "@babel/parser" "^7.24.4" - "@babel/plugin-transform-private-methods" "^7.25.9" + "@babel/plugin-proposal-private-methods" "^7.18.6" hermes-parser "^0.25.1" zod "^3.22.4" zod-validation-error "^3.0.3" eslint-plugin-react-hooks@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0.tgz#72e2eefbac4b694f5324154619fee44f5f60f101" - integrity sha512-hIOwI+5hYGpJEc4uPRmz2ulCjAGD/N13Lukkh8cLV0i2IRk/bdZDYjgLVHj+U9Z704kLIdIO6iueGvxNur0sgw== + version "5.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz#1be0080901e6ac31ce7971beed3d3ec0a423d9e3" + integrity sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg== eslint-plugin-react@^7.28.0: version "7.37.4" From 4fa540962a503d4c6682975bd9443f77dedaf52e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 16:16:41 +0000 Subject: [PATCH 110/458] Update robinraju/release-downloader digest to daf26c5 (#29532) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/download-verify-element-tarball/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/download-verify-element-tarball/action.yml b/.github/actions/download-verify-element-tarball/action.yml index 75d325c543..a64bc3241b 100644 --- a/.github/actions/download-verify-element-tarball/action.yml +++ b/.github/actions/download-verify-element-tarball/action.yml @@ -11,7 +11,7 @@ runs: using: composite steps: - name: Download release tarball - uses: robinraju/release-downloader@a96f54c1b5f5e09e47d9504526e96febd949d4c2 # v1 + uses: robinraju/release-downloader@daf26c55d821e836577a15f77d86ddc078948b05 # v1 with: tag: ${{ inputs.tag }} fileName: element-*.tar.gz* From f59af3786e9de82dc94585d55648e8f4050c0e27 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 18 Mar 2025 17:54:32 +0000 Subject: [PATCH 111/458] Simplified Sliding Sync (#28515) * Experimental SSS Working branch to get SSS functional on element-web. Requires https://github.com/matrix-org/matrix-js-sdk/pull/4400 * Adjust tests to use new behaviour * Remove well-known proxy URL lookup; always use native This is actually required for SSS because otherwise it would use the proxy over native support. * Linting * Debug logging * Control the race condition when swapping between rooms * Dont' filter by space as synapse doesn't support it * Remove SS code related to registering lists and managing ranges - Update the spidering code to spider all the relevant lists. - Add canonical alias to the required_state to allow room name calcs to work. Room sort order is busted because we don't yet look at `bump_stamp`. * User bumpStamp if it is present * Drop initial room load from 20 per list to 10 * Half the batch size to trickle more quickly * Prettier * prettier on tests too * Remove proxy URL & unused import * Hopefully fix tests to assert what the behaviour is supposed to be * Move the singleton to the manager tyo fix import loop * Very well, code, I will remove you Why were you there in the first place? * Strip out more unused stuff * Fix playwright test Seems like this lack of order updating unless a room is selected was just always a bug with both regular and non-sliding sync. I have no idea how the test passed on develop because it won't run. * Fix test to do maybe what it was supposed to do... possibly? * Remove test for old pre-simplified sliding sync behaviour * Unused import * Remove sliding sync proxy & test I was wrong about what this test was asserting, it was suposed to assert that notification dots aren't shown (because SS didn't support them somehow I guess) but they are fine in SSS so the test is just no longer relevant. * Remove now pointless credentials * Remove subscription removal as SSS doesn't do that * Update tests * add test * Switch to new labs flag & break if old labs flag is enabled * Remove unused import & fix test * Fix other test * Remove name & description from old labs flag as they're not displayed anywhere so not useful * Remove old sliding sync option by making it not a feature * Add back unread nindicator test but inverted and minus the bit about disabling notification which surely would have defeated the original point anyway? * Reinstate test for room_subscriptions ...and also make tests actually use sliding sync * Use UserFriendlyError * Remove empty constructor * Remove unrelated changes * Unused import * Fix import * Avoid moving import --------- Co-authored-by: Kegan Dougal <7190048+kegsay@users.noreply.github.com> --- .../e2e/sliding-sync/sliding-sync.spec.ts | 133 ++---- src/MatrixClientPeg.ts | 6 + src/SlidingSyncManager.ts | 370 +++++++++-------- src/Unread.ts | 7 - src/components/views/rooms/RoomSublist.tsx | 33 +- src/hooks/useSlidingSyncRoomSearch.ts | 82 ---- src/i18n/strings/en_EN.json | 1 + src/settings/Settings.tsx | 16 +- .../controllers/SlidingSyncController.ts | 7 +- src/stores/MemberListStore.ts | 4 +- src/stores/RoomViewStore.tsx | 15 +- src/stores/room-list/RoomListStore.ts | 17 +- src/stores/room-list/SlidingRoomListStore.ts | 391 ------------------ .../algorithms/tag-sorting/RecentAlgorithm.ts | 6 + test/test-utils/test-utils.ts | 1 + test/unit-tests/SlidingSyncManager-test.ts | 241 ++++------- .../roomlist/RoomListViewModel-test.tsx | 2 +- .../hooks/useSlidingSyncRoomSearch-test.tsx | 84 ---- .../unit-tests/stores/MemberListStore-test.ts | 2 +- test/unit-tests/stores/RoomViewStore-test.ts | 26 +- .../room-list/SlidingRoomListStore-test.ts | 341 --------------- 21 files changed, 367 insertions(+), 1418 deletions(-) delete mode 100644 src/hooks/useSlidingSyncRoomSearch.ts delete mode 100644 src/stores/room-list/SlidingRoomListStore.ts delete mode 100644 test/unit-tests/hooks/useSlidingSyncRoomSearch-test.tsx delete mode 100644 test/unit-tests/stores/room-list/SlidingRoomListStore-test.ts diff --git a/playwright/e2e/sliding-sync/sliding-sync.spec.ts b/playwright/e2e/sliding-sync/sliding-sync.spec.ts index bf992a0edd..118bd4585e 100644 --- a/playwright/e2e/sliding-sync/sliding-sync.spec.ts +++ b/playwright/e2e/sliding-sync/sliding-sync.spec.ts @@ -7,47 +7,15 @@ Please see LICENSE files in the repository root for full details. */ import { type Page, type Request } from "@playwright/test"; -import { GenericContainer, type StartedTestContainer, Wait } from "testcontainers"; import { test as base, expect } from "../../element-web-test"; import type { ElementAppPage } from "../../pages/ElementAppPage"; import type { Bot } from "../../pages/bot"; const test = base.extend<{ - slidingSyncProxy: StartedTestContainer; testRoom: { roomId: string; name: string }; joinedBot: Bot; }>({ - slidingSyncProxy: async ({ logger, network, postgres, page, homeserver }, use, testInfo) => { - const container = await new GenericContainer("ghcr.io/matrix-org/sliding-sync:v0.99.3") - .withNetwork(network) - .withExposedPorts(8008) - .withLogConsumer(logger.getConsumer("sliding-sync-proxy")) - .withWaitStrategy(Wait.forHttp("/client/server.json", 8008)) - .withEnvironment({ - SYNCV3_SECRET: "bwahahaha", - SYNCV3_DB: `user=${postgres.getUsername()} dbname=postgres password=${postgres.getPassword()} host=postgres sslmode=disable`, - SYNCV3_SERVER: `http://homeserver:8008`, - }) - .start(); - - const proxyAddress = `http://${container.getHost()}:${container.getMappedPort(8008)}`; - await page.addInitScript((proxyAddress) => { - window.localStorage.setItem( - "mx_local_settings", - JSON.stringify({ - feature_sliding_sync_proxy_url: proxyAddress, - }), - ); - window.localStorage.setItem("mx_labs_feature_feature_sliding_sync", "true"); - }, proxyAddress); - await use(container); - await container.stop(); - }, - // Ensure slidingSyncProxy is set up before the user fixture as it relies on an init script - credentials: async ({ slidingSyncProxy, credentials }, use) => { - await use(credentials); - }, testRoom: async ({ user, app }, use) => { const name = "Test Room"; const roomId = await app.client.createRoom({ name }); @@ -82,6 +50,14 @@ test.describe("Sliding Sync", () => { }); }; + test.use({ + config: { + features: { + feature_simplified_sliding_sync: true, + }, + }, + }); + // Load the user fixture for all tests test.beforeEach(({ user }) => {}); @@ -188,15 +164,7 @@ test.describe("Sliding Sync", () => { ).not.toBeAttached(); }); - test("should not show unread indicators", async ({ page, app, joinedBot: bot, testRoom }) => { - // TODO: for now. Later we should. - - // disable notifs in this room (TODO: CS API call?) - const locator = page.getByRole("treeitem", { name: "Test Room" }); - await locator.hover(); - await locator.getByRole("button", { name: "Notification options" }).click(); - await page.getByRole("menuitemradio", { name: "Mute room" }).click(); - + test("should show unread indicators", async ({ page, app, joinedBot: bot, testRoom }) => { // create a new room so we know when the message has been received as it'll re-shuffle the room list await app.client.createRoom({ name: "Dummy" }); @@ -207,9 +175,7 @@ test.describe("Sliding Sync", () => { // wait for this message to arrive, tell by the room list resorting await checkOrder(["Test Room", "Dummy"], page); - await expect( - page.getByRole("treeitem", { name: "Test Room" }).locator(".mx_NotificationBadge"), - ).not.toBeAttached(); + await expect(page.getByRole("treeitem", { name: "Test Room" }).locator(".mx_NotificationBadge")).toBeAttached(); }); test("should update user settings promptly", async ({ page, app }) => { @@ -221,6 +187,37 @@ test.describe("Sliding Sync", () => { await expect(locator.locator(".mx_ToggleSwitch_on")).toBeAttached(); }); + test("should send subscribe_rooms on room switch if room not already subscribed", async ({ page, app }) => { + // create rooms and check room names are correct + const roomIds: string[] = []; + for (const fruit of ["Apple", "Pineapple", "Orange"]) { + const id = await app.client.createRoom({ name: fruit }); + roomIds.push(id); + await expect(page.getByRole("treeitem", { name: fruit })).toBeVisible(); + } + const [roomAId, roomPId] = roomIds; + + const matchRoomSubRequest = (subRoomId: string) => (request: Request) => { + if (!request.url().includes("/sync")) return false; + const body = request.postDataJSON(); + return body.room_subscriptions?.[subRoomId]; + }; + + // Select the Test Room and wait for playwright to get the request + const [request] = await Promise.all([ + page.waitForRequest(matchRoomSubRequest(roomAId)), + page.getByRole("treeitem", { name: "Apple", exact: true }).click(), + ]); + const roomSubscriptions = request.postDataJSON().room_subscriptions; + expect(roomSubscriptions, "room_subscriptions is object").toBeDefined(); + + // Switch to another room and wait for playwright to get the request + await Promise.all([ + page.waitForRequest(matchRoomSubRequest(roomPId)), + page.getByRole("treeitem", { name: "Pineapple", exact: true }).click(), + ]); + }); + test("should show and be able to accept/reject/rescind invites", async ({ page, app, @@ -361,52 +358,4 @@ test.describe("Sliding Sync", () => { // ensure the reply-to does not disappear await expect(page.locator(".mx_ReplyPreview")).toBeVisible(); }); - - test("should send unsubscribe_rooms for every room switch", async ({ page, app }) => { - // create rooms and check room names are correct - const roomIds: string[] = []; - for (const fruit of ["Apple", "Pineapple", "Orange"]) { - const id = await app.client.createRoom({ name: fruit }); - roomIds.push(id); - await expect(page.getByRole("treeitem", { name: fruit })).toBeVisible(); - } - const [roomAId, roomPId, roomOId] = roomIds; - - const matchRoomSubRequest = (subRoomId: string) => (request: Request) => { - if (!request.url().includes("/sync")) return false; - const body = request.postDataJSON(); - return body.txn_id && body.room_subscriptions?.[subRoomId]; - }; - const matchRoomUnsubRequest = (unsubRoomId: string) => (request: Request) => { - if (!request.url().includes("/sync")) return false; - const body = request.postDataJSON(); - return ( - body.txn_id && body.unsubscribe_rooms?.includes(unsubRoomId) && !body.room_subscriptions?.[unsubRoomId] - ); - }; - - // Select the Test Room and wait for playwright to get the request - const [request] = await Promise.all([ - page.waitForRequest(matchRoomSubRequest(roomAId)), - page.getByRole("treeitem", { name: "Apple", exact: true }).click(), - ]); - const roomSubscriptions = request.postDataJSON().room_subscriptions; - expect(roomSubscriptions, "room_subscriptions is object").toBeDefined(); - - // Switch to another room and wait for playwright to get the request - await Promise.all([ - page.waitForRequest(matchRoomSubRequest(roomPId)), - page.waitForRequest(matchRoomUnsubRequest(roomAId)), - page.getByRole("treeitem", { name: "Pineapple", exact: true }).click(), - ]); - - // And switch to even another room and wait for playwright to get the request - await Promise.all([ - page.waitForRequest(matchRoomSubRequest(roomOId)), - page.waitForRequest(matchRoomUnsubRequest(roomPId)), - page.getByRole("treeitem", { name: "Orange", exact: true }).click(), - ]); - - // TODO: Add tests for encrypted rooms - }); }); diff --git a/src/MatrixClientPeg.ts b/src/MatrixClientPeg.ts index 9682b41800..288878cddc 100644 --- a/src/MatrixClientPeg.ts +++ b/src/MatrixClientPeg.ts @@ -299,6 +299,12 @@ class MatrixClientPegClass implements IMatrixClientPeg { opts.threadSupport = true; if (SettingsStore.getValue("feature_sliding_sync")) { + throw new UserFriendlyError("sliding_sync_legacy_no_longer_supported"); + } + + // If the user has enabled the labs feature for sliding sync, set it up + // otherwise check if the feature is supported + if (SettingsStore.getValue("feature_simplified_sliding_sync")) { opts.slidingSync = await SlidingSyncManager.instance.setup(this.matrixClient); } else { SlidingSyncManager.instance.checkSupport(this.matrixClient); diff --git a/src/SlidingSyncManager.ts b/src/SlidingSyncManager.ts index adfca7c3c3..88b839312d 100644 --- a/src/SlidingSyncManager.ts +++ b/src/SlidingSyncManager.ts @@ -36,45 +36,51 @@ Please see LICENSE files in the repository root for full details. * list ops) */ -import { type MatrixClient, EventType, AutoDiscovery, Method, timeoutSignal } from "matrix-js-sdk/src/matrix"; +import { type MatrixClient, ClientEvent, EventType, type Room } from "matrix-js-sdk/src/matrix"; import { type MSC3575Filter, type MSC3575List, + type MSC3575SlidingSyncResponse, MSC3575_STATE_KEY_LAZY, MSC3575_STATE_KEY_ME, MSC3575_WILDCARD, SlidingSync, + SlidingSyncEvent, + SlidingSyncState, } from "matrix-js-sdk/src/sliding-sync"; import { logger } from "matrix-js-sdk/src/logger"; import { defer, sleep } from "matrix-js-sdk/src/utils"; -import SettingsStore from "./settings/SettingsStore"; -import SlidingSyncController from "./settings/controllers/SlidingSyncController"; - // how long to long poll for const SLIDING_SYNC_TIMEOUT_MS = 20 * 1000; +// The state events we will get for every single room/space/old room/etc +// This list is only augmented when a direct room subscription is made. (e.g you view a room) +const REQUIRED_STATE_LIST = [ + [EventType.RoomJoinRules, ""], // the public icon on the room list + [EventType.RoomAvatar, ""], // any room avatar + [EventType.RoomCanonicalAlias, ""], // for room name calculations + [EventType.RoomTombstone, ""], // lets JS SDK hide rooms which are dead + [EventType.RoomEncryption, ""], // lets rooms be configured for E2EE correctly + [EventType.RoomCreate, ""], // for isSpaceRoom checks + [EventType.SpaceChild, MSC3575_WILDCARD], // all space children + [EventType.SpaceParent, MSC3575_WILDCARD], // all space parents + [EventType.RoomMember, MSC3575_STATE_KEY_ME], // lets the client calculate that we are in fact in the room +]; + // the things to fetch when a user clicks on a room const DEFAULT_ROOM_SUBSCRIPTION_INFO = { timeline_limit: 50, // missing required_state which will change depending on the kind of room include_old_rooms: { timeline_limit: 0, - required_state: [ - // state needed to handle space navigation and tombstone chains - [EventType.RoomCreate, ""], - [EventType.RoomTombstone, ""], - [EventType.SpaceChild, MSC3575_WILDCARD], - [EventType.SpaceParent, MSC3575_WILDCARD], - [EventType.RoomMember, MSC3575_STATE_KEY_ME], - ], + required_state: REQUIRED_STATE_LIST, }, }; // lazy load room members so rooms like Matrix HQ don't take forever to load const UNENCRYPTED_SUBSCRIPTION_NAME = "unencrypted"; const UNENCRYPTED_SUBSCRIPTION = { required_state: [ - [MSC3575_WILDCARD, MSC3575_WILDCARD], // all events [EventType.RoomMember, MSC3575_STATE_KEY_ME], // except for m.room.members, get our own membership [EventType.RoomMember, MSC3575_STATE_KEY_LAZY], // ...and lazy load the rest. ], @@ -90,6 +96,72 @@ const ENCRYPTED_SUBSCRIPTION = { ...DEFAULT_ROOM_SUBSCRIPTION_INFO, }; +// the complete set of lists made in SSS. The manager will spider all of these lists depending +// on the count for each one. +const sssLists: Record = { + spaces: { + ranges: [[0, 10]], + timeline_limit: 0, // we don't care about the most recent message for spaces + required_state: REQUIRED_STATE_LIST, + include_old_rooms: { + timeline_limit: 0, + required_state: REQUIRED_STATE_LIST, + }, + filters: { + room_types: ["m.space"], + }, + }, + invites: { + ranges: [[0, 10]], + timeline_limit: 1, // most recent message display + required_state: REQUIRED_STATE_LIST, + include_old_rooms: { + timeline_limit: 0, + required_state: REQUIRED_STATE_LIST, + }, + filters: { + is_invite: true, + }, + }, + favourites: { + ranges: [[0, 10]], + timeline_limit: 1, // most recent message display + required_state: REQUIRED_STATE_LIST, + include_old_rooms: { + timeline_limit: 0, + required_state: REQUIRED_STATE_LIST, + }, + filters: { + tags: ["m.favourite"], + }, + }, + dms: { + ranges: [[0, 10]], + timeline_limit: 1, // most recent message display + required_state: REQUIRED_STATE_LIST, + include_old_rooms: { + timeline_limit: 0, + required_state: REQUIRED_STATE_LIST, + }, + filters: { + is_dm: true, + is_invite: false, + // If a DM has a Favourite & Low Prio tag then it'll be shown in those lists instead + not_tags: ["m.favourite", "m.lowpriority"], + }, + }, + untagged: { + // SSS will dupe suppress invites/dms from here, so we don't need "not dms, not invites" + ranges: [[0, 10]], + timeline_limit: 1, // most recent message display + required_state: REQUIRED_STATE_LIST, + include_old_rooms: { + timeline_limit: 0, + required_state: REQUIRED_STATE_LIST, + }, + }, +}; + export type PartialSlidingSyncRequest = { filters?: MSC3575Filter; sort?: string[]; @@ -103,6 +175,8 @@ export type PartialSlidingSyncRequest = { * sync options and code. */ export class SlidingSyncManager { + public static serverSupportsSlidingSync: boolean; + public static readonly ListSpaces = "space_list"; public static readonly ListSearch = "search_list"; private static readonly internalInstance = new SlidingSyncManager(); @@ -116,48 +190,17 @@ export class SlidingSyncManager { return SlidingSyncManager.internalInstance; } - public configure(client: MatrixClient, proxyUrl: string): SlidingSync { + private configure(client: MatrixClient, proxyUrl: string): SlidingSync { this.client = client; + // create the set of lists we will use. + const lists = new Map(); + for (const listName in sssLists) { + lists.set(listName, sssLists[listName]); + } // by default use the encrypted subscription as that gets everything, which is a safer // default than potentially missing member events. - this.slidingSync = new SlidingSync( - proxyUrl, - new Map(), - ENCRYPTED_SUBSCRIPTION, - client, - SLIDING_SYNC_TIMEOUT_MS, - ); + this.slidingSync = new SlidingSync(proxyUrl, lists, ENCRYPTED_SUBSCRIPTION, client, SLIDING_SYNC_TIMEOUT_MS); this.slidingSync.addCustomSubscription(UNENCRYPTED_SUBSCRIPTION_NAME, UNENCRYPTED_SUBSCRIPTION); - // set the space list - this.slidingSync.setList(SlidingSyncManager.ListSpaces, { - ranges: [[0, 20]], - sort: ["by_name"], - slow_get_all_rooms: true, - timeline_limit: 0, - required_state: [ - [EventType.RoomJoinRules, ""], // the public icon on the room list - [EventType.RoomAvatar, ""], // any room avatar - [EventType.RoomTombstone, ""], // lets JS SDK hide rooms which are dead - [EventType.RoomEncryption, ""], // lets rooms be configured for E2EE correctly - [EventType.RoomCreate, ""], // for isSpaceRoom checks - [EventType.SpaceChild, MSC3575_WILDCARD], // all space children - [EventType.SpaceParent, MSC3575_WILDCARD], // all space parents - [EventType.RoomMember, MSC3575_STATE_KEY_ME], // lets the client calculate that we are in fact in the room - ], - include_old_rooms: { - timeline_limit: 0, - required_state: [ - [EventType.RoomCreate, ""], - [EventType.RoomTombstone, ""], // lets JS SDK hide rooms which are dead - [EventType.SpaceChild, MSC3575_WILDCARD], // all space children - [EventType.SpaceParent, MSC3575_WILDCARD], // all space parents - [EventType.RoomMember, MSC3575_STATE_KEY_ME], // lets the client calculate that we are in fact in the room - ], - }, - filters: { - room_types: ["m.space"], - }, - }); this.configureDefer.resolve(); return this.slidingSync; } @@ -220,99 +263,113 @@ export class SlidingSyncManager { return this.slidingSync!.getListParams(listKey)!; } - public async setRoomVisible(roomId: string, visible: boolean): Promise { + /** + * Announces that the user has chosen to view the given room and that room will now + * be displayed, so it should have more state loaded. + * @param roomId The room to set visible + */ + public async setRoomVisible(roomId: string): Promise { await this.configureDefer.promise; const subscriptions = this.slidingSync!.getRoomSubscriptions(); - if (visible) { - subscriptions.add(roomId); - } else { - subscriptions.delete(roomId); - } + if (subscriptions.has(roomId)) return; + + subscriptions.add(roomId); + const room = this.client?.getRoom(roomId); - let shouldLazyLoad = !(await this.client?.getCrypto()?.isEncryptionEnabledInRoom(roomId)); - if (!room) { - // default to safety: request all state if we can't work it out. This can happen if you - // refresh the app whilst viewing a room: we call setRoomVisible before we know anything - // about the room. - shouldLazyLoad = false; + // default to safety: request all state if we can't work it out. This can happen if you + // refresh the app whilst viewing a room: we call setRoomVisible before we know anything + // about the room. + let shouldLazyLoad = false; + if (room) { + // do not lazy load encrypted rooms as we need the entire member list. + shouldLazyLoad = !(await this.client?.getCrypto()?.isEncryptionEnabledInRoom(roomId)); } - logger.log("SlidingSync setRoomVisible:", roomId, visible, "shouldLazyLoad:", shouldLazyLoad); + logger.log("SlidingSync setRoomVisible:", roomId, "shouldLazyLoad:", shouldLazyLoad); if (shouldLazyLoad) { // lazy load this room this.slidingSync!.useCustomSubscription(roomId, UNENCRYPTED_SUBSCRIPTION_NAME); } - const p = this.slidingSync!.modifyRoomSubscriptions(subscriptions); + this.slidingSync!.modifyRoomSubscriptions(subscriptions); if (room) { - return roomId; // we have data already for this room, show immediately e.g it's in a list + return; // we have data already for this room, show immediately e.g it's in a list } - try { - // wait until the next sync before returning as RoomView may need to know the current state - await p; - } catch { - logger.warn("SlidingSync setRoomVisible:", roomId, visible, "failed to confirm transaction"); - } - return roomId; + // wait until we know about this room. This may take a little while. + return new Promise((resolve) => { + logger.log(`SlidingSync setRoomVisible room ${roomId} not found, waiting for ClientEvent.Room`); + const waitForRoom = (r: Room): void => { + if (r.roomId === roomId) { + this.client?.off(ClientEvent.Room, waitForRoom); + logger.log(`SlidingSync room ${roomId} found, resolving setRoomVisible`); + resolve(); + } + }; + this.client?.on(ClientEvent.Room, waitForRoom); + }); } /** - * Retrieve all rooms on the user's account. Used for pre-populating the local search cache. - * Retrieval is gradual over time. + * Retrieve all rooms on the user's account. Retrieval is gradual over time. + * This function MUST be called BEFORE the first sync request goes out. * @param batchSize The number of rooms to return in each request. * @param gapBetweenRequestsMs The number of milliseconds to wait between requests. */ - public async startSpidering(batchSize: number, gapBetweenRequestsMs: number): Promise { - await sleep(gapBetweenRequestsMs); // wait a bit as this is called on first render so let's let things load - let startIndex = batchSize; - let hasMore = true; - let firstTime = true; - while (hasMore) { - const endIndex = startIndex + batchSize - 1; - try { - const ranges = [ - [0, batchSize - 1], - [startIndex, endIndex], - ]; - if (firstTime) { - await this.slidingSync!.setList(SlidingSyncManager.ListSearch, { - // e.g [0,19] [20,39] then [0,19] [40,59]. We keep [0,20] constantly to ensure - // any changes to the list whilst spidering are caught. - ranges: ranges, - sort: [ - "by_recency", // this list isn't shown on the UI so just sorting by timestamp is enough - ], - timeline_limit: 0, // we only care about the room details, not messages in the room - required_state: [ - [EventType.RoomJoinRules, ""], // the public icon on the room list - [EventType.RoomAvatar, ""], // any room avatar - [EventType.RoomTombstone, ""], // lets JS SDK hide rooms which are dead - [EventType.RoomEncryption, ""], // lets rooms be configured for E2EE correctly - [EventType.RoomCreate, ""], // for isSpaceRoom checks - [EventType.RoomMember, MSC3575_STATE_KEY_ME], // lets the client calculate that we are in fact in the room - ], - // we don't include_old_rooms here in an effort to reduce the impact of spidering all rooms - // on the user's account. This means some data in the search dialog results may be inaccurate - // e.g membership of space, but this will be corrected when the user clicks on the room - // as the direct room subscription does include old room iterations. - filters: { - // we get spaces via a different list, so filter them out - not_room_types: ["m.space"], - }, - }); - } else { - await this.slidingSync!.setListRanges(SlidingSyncManager.ListSearch, ranges); - } - } catch { - // do nothing, as we reject only when we get interrupted but that's fine as the next - // request will include our data - } finally { - // gradually request more over time, even on errors. - await sleep(gapBetweenRequestsMs); + private async startSpidering( + slidingSync: SlidingSync, + batchSize: number, + gapBetweenRequestsMs: number, + ): Promise { + // The manager has created several lists (see `sssLists` in this file), all of which will be spidered simultaneously. + // There are multiple lists to ensure that we can populate invites/favourites/DMs sections immediately, rather than + // potentially waiting minutes if they are all very old rooms (and hence are returned last by the server). In this + // way, the lists are effectively priority requests. We don't actually care which room goes into which list at this + // point, as the RoomListStore will calculate this based on the returned data. + + // copy the initial set of list names and ranges, we'll keep this map updated. + const listToUpperBound = new Map( + Object.keys(sssLists).map((listName) => { + return [listName, sssLists[listName].ranges[0][1]]; + }), + ); + console.log("startSpidering:", listToUpperBound); + + // listen for a response from the server. ANY 200 OK will do here, as we assume that it is ACKing + // the request change we have sent out. TODO: this may not be true if you concurrently subscribe to a room :/ + // but in that case, for spidering at least, it isn't the end of the world as request N+1 includes all indexes + // from request N. + const lifecycle = async ( + state: SlidingSyncState, + _: MSC3575SlidingSyncResponse | null, + err?: Error, + ): Promise => { + if (state !== SlidingSyncState.Complete) { + return; } - const listData = this.slidingSync!.getListData(SlidingSyncManager.ListSearch)!; - hasMore = endIndex + 1 < listData.joinedCount; - startIndex += batchSize; - firstTime = false; - } + await sleep(gapBetweenRequestsMs); // don't tightloop; even on errors + if (err) { + return; + } + + // for all lists with total counts > range => increase the range + let hasSetRanges = false; + listToUpperBound.forEach((currentUpperBound, listName) => { + const totalCount = slidingSync.getListData(listName)?.joinedCount || 0; + if (currentUpperBound < totalCount) { + // increment the upper bound + const newUpperBound = currentUpperBound + batchSize; + console.log(`startSpidering: ${listName} ${currentUpperBound} => ${newUpperBound}`); + listToUpperBound.set(listName, newUpperBound); + // make the next request. This will only send the request when this callback has finished, so if + // we set all the list ranges at once we will only send 1 new request. + slidingSync.setListRanges(listName, [[0, newUpperBound]]); + hasSetRanges = true; + } + }); + if (!hasSetRanges) { + // finish spidering + slidingSync.off(SlidingSyncEvent.Lifecycle, lifecycle); + } + }; + slidingSync.on(SlidingSyncEvent.Lifecycle, lifecycle); } /** @@ -325,42 +382,10 @@ export class SlidingSyncManager { * @returns A working Sliding Sync or undefined */ public async setup(client: MatrixClient): Promise { - const baseUrl = client.baseUrl; - const proxyUrl = SettingsStore.getValue("feature_sliding_sync_proxy_url"); - const wellKnownProxyUrl = await this.getProxyFromWellKnown(client); - - const slidingSyncEndpoint = proxyUrl || wellKnownProxyUrl || baseUrl; - - this.configure(client, slidingSyncEndpoint); - logger.info("Sliding sync activated at", slidingSyncEndpoint); - this.startSpidering(100, 50); // 100 rooms at a time, 50ms apart - - return this.slidingSync; - } - - /** - * Get the sliding sync proxy URL from the client well known - * @param client The MatrixClient to use - * @return The proxy url - */ - public async getProxyFromWellKnown(client: MatrixClient): Promise { - let proxyUrl: string | undefined; - - try { - const clientDomain = await client.getDomain(); - if (clientDomain === null) { - throw new RangeError("Homeserver domain is null"); - } - const clientWellKnown = await AutoDiscovery.findClientConfig(clientDomain); - proxyUrl = clientWellKnown?.["org.matrix.msc3575.proxy"]?.url; - } catch { - // Either client.getDomain() is null so we've shorted out, or is invalid so `AutoDiscovery.findClientConfig` has thrown - } - - if (proxyUrl != undefined) { - logger.log("getProxyFromWellKnown: client well-known declares sliding sync proxy at", proxyUrl); - } - return proxyUrl; + const slidingSync = this.configure(client, client.baseUrl); + logger.info("Simplified Sliding Sync activated at", client.baseUrl); + this.startSpidering(slidingSync, 50, 50); // 50 rooms at a time, 50ms apart + return slidingSync; } /** @@ -371,9 +396,9 @@ export class SlidingSyncManager { public async nativeSlidingSyncSupport(client: MatrixClient): Promise { // Per https://github.com/matrix-org/matrix-spec-proposals/pull/3575/files#r1589542561 // `client` can be undefined/null in tests for some reason. - const support = await client?.doesServerSupportUnstableFeature("org.matrix.msc3575"); + const support = await client?.doesServerSupportUnstableFeature("org.matrix.simplified_msc3575"); if (support) { - logger.log("nativeSlidingSyncSupport: sliding sync advertised as unstable"); + logger.log("nativeSlidingSyncSupport: org.matrix.simplified_msc3575 sliding sync advertised as unstable"); } return support; } @@ -387,20 +412,9 @@ export class SlidingSyncManager { */ public async checkSupport(client: MatrixClient): Promise { if (await this.nativeSlidingSyncSupport(client)) { - SlidingSyncController.serverSupportsSlidingSync = true; + SlidingSyncManager.serverSupportsSlidingSync = true; return; } - - const proxyUrl = await this.getProxyFromWellKnown(client); - if (proxyUrl != undefined) { - const response = await fetch(new URL("/client/server.json", proxyUrl), { - method: Method.Get, - signal: timeoutSignal(10 * 1000), // 10s - }); - if (response.status === 200) { - logger.log("checkSupport: well-known sliding sync proxy is up at", proxyUrl); - SlidingSyncController.serverSupportsSlidingSync = true; - } - } + SlidingSyncManager.serverSupportsSlidingSync = false; } } diff --git a/src/Unread.ts b/src/Unread.ts index 2c8fa0cff3..e8f4769e25 100644 --- a/src/Unread.ts +++ b/src/Unread.ts @@ -11,7 +11,6 @@ import { logger } from "matrix-js-sdk/src/logger"; import shouldHideEvent from "./shouldHideEvent"; import { haveRendererForEvent } from "./events/EventTileFactory"; -import SettingsStore from "./settings/SettingsStore"; import { RoomNotifState, getRoomNotifsState } from "./RoomNotifs"; /** @@ -44,12 +43,6 @@ export function eventTriggersUnreadCount(client: MatrixClient, ev: MatrixEvent): } export function doesRoomHaveUnreadMessages(room: Room, includeThreads: boolean): boolean { - if (SettingsStore.getValue("feature_sliding_sync")) { - // TODO: https://github.com/vector-im/element-web/issues/23207 - // Sliding Sync doesn't support unread indicator dots (yet...) - return false; - } - const toCheck: Array = [room]; if (includeThreads) { toCheck.push(...room.getThreads()); diff --git a/src/components/views/rooms/RoomSublist.tsx b/src/components/views/rooms/RoomSublist.tsx index de313246b1..3c54b98b0e 100644 --- a/src/components/views/rooms/RoomSublist.tsx +++ b/src/components/views/rooms/RoomSublist.tsx @@ -42,8 +42,6 @@ import ContextMenu, { } from "../../structures/ContextMenu"; import AccessibleButton, { type ButtonEvent } from "../../views/elements/AccessibleButton"; import type ExtraTile from "./ExtraTile"; -import SettingsStore from "../../../settings/SettingsStore"; -import { SlidingSyncManager } from "../../../SlidingSyncManager"; import NotificationBadge from "./NotificationBadge"; import RoomTile from "./RoomTile"; @@ -106,12 +104,8 @@ export default class RoomSublist extends React.Component { private heightAtStart: number; private notificationState: ListNotificationState; - private slidingSyncMode: boolean; - public constructor(props: IProps) { super(props); - // when this setting is toggled it restarts the app so it's safe to not watch this. - this.slidingSyncMode = SettingsStore.getValue("feature_sliding_sync"); this.layout = RoomListLayoutStore.instance.getLayoutFor(this.props.tagId); this.heightAtStart = 0; @@ -165,9 +159,6 @@ export default class RoomSublist extends React.Component { } private get numVisibleTiles(): number { - if (this.slidingSyncMode) { - return this.state.rooms.length; - } const nVisible = Math.ceil(this.layout.visibleTiles); return Math.min(nVisible, this.numTiles); } @@ -329,12 +320,6 @@ export default class RoomSublist extends React.Component { }; private onShowAllClick = async (): Promise => { - if (this.slidingSyncMode) { - const count = RoomListStore.instance.getCount(this.props.tagId); - await SlidingSyncManager.instance.ensureListRegistered(this.props.tagId, { - ranges: [[0, count]], - }); - } // read number of visible tiles before we mutate it const numVisibleTiles = this.numVisibleTiles; const newHeight = this.layout.tilesToPixelsWithPadding(this.numTiles, this.padding); @@ -554,13 +539,8 @@ export default class RoomSublist extends React.Component { let contextMenu: JSX.Element | undefined; if (this.state.contextMenuPosition) { - let isAlphabetical = RoomListStore.instance.getTagSorting(this.props.tagId) === SortAlgorithm.Alphabetic; - let isUnreadFirst = RoomListStore.instance.getListOrder(this.props.tagId) === ListAlgorithm.Importance; - if (this.slidingSyncMode) { - const slidingList = SlidingSyncManager.instance.slidingSync?.getListParams(this.props.tagId); - isAlphabetical = (slidingList?.sort || [])[0] === "by_name"; - isUnreadFirst = (slidingList?.sort || [])[0] === "by_notification_level"; - } + const isAlphabetical = RoomListStore.instance.getTagSorting(this.props.tagId) === SortAlgorithm.Alphabetic; + const isUnreadFirst = RoomListStore.instance.getListOrder(this.props.tagId) === ListAlgorithm.Importance; // Invites don't get some nonsense options, so only add them if we have to. let otherSections: JSX.Element | undefined; @@ -763,17 +743,12 @@ export default class RoomSublist extends React.Component { // floats above the resize handle, if we have one present. If the user has all // tiles visible, it becomes 'show less'. let showNButton: JSX.Element | undefined; - const hasMoreSlidingSync = - this.slidingSyncMode && RoomListStore.instance.getCount(this.props.tagId) > this.state.rooms.length; - if (maxTilesPx > this.state.height || hasMoreSlidingSync) { + if (maxTilesPx > this.state.height) { // the height of all the tiles is greater than the section height: we need a 'show more' button const nonPaddedHeight = this.state.height - RESIZE_HANDLE_HEIGHT - SHOW_N_BUTTON_HEIGHT; const amountFullyShown = Math.floor(nonPaddedHeight / this.layout.tileHeight); - let numMissing = this.numTiles - amountFullyShown; - if (this.slidingSyncMode) { - numMissing = RoomListStore.instance.getCount(this.props.tagId) - amountFullyShown; - } + const numMissing = this.numTiles - amountFullyShown; const label = _t("room_list|show_n_more", { count: numMissing }); let showMoreText: ReactNode = {label}; if (this.props.isMinimized) showMoreText = null; diff --git a/src/hooks/useSlidingSyncRoomSearch.ts b/src/hooks/useSlidingSyncRoomSearch.ts deleted file mode 100644 index 17eca74474..0000000000 --- a/src/hooks/useSlidingSyncRoomSearch.ts +++ /dev/null @@ -1,82 +0,0 @@ -/* -Copyright 2024 New Vector Ltd. -Copyright 2022 The Matrix.org Foundation C.I.C. - -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 { useCallback, useState } from "react"; -import { type Room } from "matrix-js-sdk/src/matrix"; - -import { MatrixClientPeg } from "../MatrixClientPeg"; -import { useLatestResult } from "./useLatestResult"; -import { SlidingSyncManager } from "../SlidingSyncManager"; - -export interface SlidingSyncRoomSearchOpts { - limit: number; - query: string; -} - -export const useSlidingSyncRoomSearch = (): { - loading: boolean; - rooms: Room[]; - search(opts: SlidingSyncRoomSearchOpts): Promise; -} => { - const [rooms, setRooms] = useState([]); - - const [loading, setLoading] = useState(false); - - const [updateQuery, updateResult] = useLatestResult<{ term: string; limit?: number }, Room[]>(setRooms); - - const search = useCallback( - async ({ limit = 100, query: term }: SlidingSyncRoomSearchOpts): Promise => { - const opts = { limit, term }; - updateQuery(opts); - - if (!term?.length) { - setRooms([]); - return true; - } - - try { - setLoading(true); - await SlidingSyncManager.instance.ensureListRegistered(SlidingSyncManager.ListSearch, { - ranges: [[0, limit]], - filters: { - room_name_like: term, - }, - }); - const rooms: Room[] = []; - const { roomIndexToRoomId } = SlidingSyncManager.instance.slidingSync!.getListData( - SlidingSyncManager.ListSearch, - )!; - let i = 0; - while (roomIndexToRoomId[i]) { - const roomId = roomIndexToRoomId[i]; - const room = MatrixClientPeg.safeGet().getRoom(roomId); - if (room) { - rooms.push(room); - } - i++; - } - updateResult(opts, rooms); - return true; - } catch (e) { - console.error("Could not fetch sliding sync rooms for params", { limit, term }, e); - updateResult(opts, []); - return false; - } finally { - setLoading(false); - // TODO: delete the list? - } - }, - [updateQuery, updateResult], - ); - - return { - loading, - rooms, - search, - } as const; -}; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 322fcf4c93..5607a613eb 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -3148,6 +3148,7 @@ "view": "Views room with given address", "whois": "Displays information about a user" }, + "sliding_sync_legacy_no_longer_supported": "Legacy sliding sync is no longer supported: please log out and back in to enable the new sliding sync flag", "space": { "add_existing_room_space": { "create": "Want to add a new room instead?", diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 8784e12b6c..6984932fd9 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -198,7 +198,8 @@ export interface Settings { "feature_html_topic": IFeature; "feature_bridge_state": IFeature; "feature_jump_to_date": IFeature; - "feature_sliding_sync": IFeature; + "feature_sliding_sync": IBaseSetting; + "feature_simplified_sliding_sync": IFeature; "feature_element_call_video_rooms": IFeature; "feature_group_calls": IFeature; "feature_disable_call_per_sender_encryption": IFeature; @@ -210,7 +211,6 @@ export interface Settings { "feature_ask_to_join": IFeature; "feature_notifications": IFeature; // These are in the feature namespace but aren't actually features - "feature_sliding_sync_proxy_url": IBaseSetting; "feature_hidebold": IBaseSetting; "useOnlyCurrentProfiles": IBaseSetting; @@ -539,7 +539,14 @@ export const SETTINGS: Settings = { true, ), }, + // legacy sliding sync flag: no longer works, will error for anyone who's still using it "feature_sliding_sync": { + supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG_PRIORITISED, + supportedLevelsAreOrdered: true, + shouldWarn: true, + default: false, + }, + "feature_simplified_sliding_sync": { isFeature: true, labsGroup: LabGroup.Developer, supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG_PRIORITISED, @@ -550,11 +557,6 @@ export const SETTINGS: Settings = { default: false, controller: new SlidingSyncController(), }, - "feature_sliding_sync_proxy_url": { - // This is not a distinct feature, it is a legacy setting for feature_sliding_sync above - supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, - default: "", - }, "feature_element_call_video_rooms": { isFeature: true, labsGroup: LabGroup.VoiceAndVideo, diff --git a/src/settings/controllers/SlidingSyncController.ts b/src/settings/controllers/SlidingSyncController.ts index 11ae1a2ba0..44de3ba8ee 100644 --- a/src/settings/controllers/SlidingSyncController.ts +++ b/src/settings/controllers/SlidingSyncController.ts @@ -11,20 +11,19 @@ import SettingController from "./SettingController"; import PlatformPeg from "../../PlatformPeg"; import SettingsStore from "../SettingsStore"; import { _t } from "../../languageHandler"; +import { SlidingSyncManager } from "../../SlidingSyncManager"; export default class SlidingSyncController extends SettingController { - public static serverSupportsSlidingSync: boolean; - public async onChange(): Promise { PlatformPeg.get()?.reload(); } public get settingDisabled(): boolean | string { // Cannot be disabled once enabled, user has been warned and must log out and back in. - if (SettingsStore.getValue("feature_sliding_sync")) { + if (SettingsStore.getValue("feature_simplified_sliding_sync")) { return _t("labs|sliding_sync_disabled_notice"); } - if (!SlidingSyncController.serverSupportsSlidingSync) { + if (!SlidingSyncManager.serverSupportsSlidingSync) { return _t("labs|sliding_sync_server_no_support"); } diff --git a/src/stores/MemberListStore.ts b/src/stores/MemberListStore.ts index 04c5824d99..29269bac94 100644 --- a/src/stores/MemberListStore.ts +++ b/src/stores/MemberListStore.ts @@ -122,7 +122,7 @@ export class MemberListStore { * @returns True if enabled */ private async isLazyLoadingEnabled(roomId: string): Promise { - if (SettingsStore.getValue("feature_sliding_sync")) { + if (SettingsStore.getValue("feature_simplified_sliding_sync")) { // only unencrypted rooms use lazy loading return !(await this.stores.client?.getCrypto()?.isEncryptionEnabledInRoom(roomId)); } @@ -134,7 +134,7 @@ export class MemberListStore { * @returns True if there is storage for lazy loading members */ private isLazyMemberStorageEnabled(): boolean { - if (SettingsStore.getValue("feature_sliding_sync")) { + if (SettingsStore.getValue("feature_simplified_sliding_sync")) { return false; } return this.stores.client!.hasLazyLoadMembersEnabled(); diff --git a/src/stores/RoomViewStore.tsx b/src/stores/RoomViewStore.tsx index 91edcbb412..633d55f3f6 100644 --- a/src/stores/RoomViewStore.tsx +++ b/src/stores/RoomViewStore.tsx @@ -372,11 +372,7 @@ export class RoomViewStore extends EventEmitter { if (prevRoomCall !== null && (!payload.view_call || payload.room_id !== this.state.roomId)) prevRoomCall.presented = false; - if (SettingsStore.getValue("feature_sliding_sync") && this.state.roomId !== payload.room_id) { - if (this.state.subscribingRoomId && this.state.subscribingRoomId !== payload.room_id) { - // unsubscribe from this room, but don't await it as we don't care when this gets done. - this.stores.slidingSyncManager.setRoomVisible(this.state.subscribingRoomId, false); - } + if (SettingsStore.getValue("feature_simplified_sliding_sync") && this.state.roomId !== payload.room_id) { this.setState({ subscribingRoomId: payload.room_id, roomId: payload.room_id, @@ -392,13 +388,8 @@ export class RoomViewStore extends EventEmitter { }); // set this room as the room subscription. We need to await for it as this will fetch // all room state for this room, which is required before we get the state below. - await this.stores.slidingSyncManager.setRoomVisible(payload.room_id, true); - // Whilst we were subscribing another room was viewed, so stop what we're doing and - // unsubscribe - if (this.state.subscribingRoomId !== payload.room_id) { - this.stores.slidingSyncManager.setRoomVisible(payload.room_id, false); - return; - } + await this.stores.slidingSyncManager.setRoomVisible(payload.room_id); + // Re-fire the payload: we won't re-process it because the prev room ID == payload room ID now this.dis?.dispatch({ ...payload, diff --git a/src/stores/room-list/RoomListStore.ts b/src/stores/room-list/RoomListStore.ts index e1d2f7b7e8..6985e007bd 100644 --- a/src/stores/room-list/RoomListStore.ts +++ b/src/stores/room-list/RoomListStore.ts @@ -33,7 +33,6 @@ import { VisibilityProvider } from "./filters/VisibilityProvider"; import { SpaceWatcher } from "./SpaceWatcher"; import { type IRoomTimelineActionPayload } from "../../actions/MatrixActionCreators"; import { type RoomListStore as Interface, RoomListStoreEvent } from "./Interface"; -import { SlidingRoomListStoreClass } from "./SlidingRoomListStore"; import { UPDATE_EVENT } from "../AsyncStore"; import { SdkContextClass } from "../../contexts/SDKContext"; import { getChangedOverrideRoomMutePushRules } from "./utils/roomMute"; @@ -406,6 +405,9 @@ export class RoomListStoreClass extends AsyncStoreWithClient implem public setTagSorting(tagId: TagID, sort: SortAlgorithm): void { this.setAndPersistTagSorting(tagId, sort); + // We'll always need an update after changing the sort order, so mark for update and trigger + // immediately. + this.updateFn.mark(); this.updateFn.trigger(); } @@ -642,16 +644,9 @@ export default class RoomListStore { public static get instance(): Interface { if (!RoomListStore.internalInstance) { - if (SettingsStore.getValue("feature_sliding_sync")) { - logger.info("using SlidingRoomListStoreClass"); - const instance = new SlidingRoomListStoreClass(defaultDispatcher, SdkContextClass.instance); - instance.start(); - RoomListStore.internalInstance = instance; - } else { - const instance = new RoomListStoreClass(defaultDispatcher); - instance.start(); - RoomListStore.internalInstance = instance; - } + const instance = new RoomListStoreClass(defaultDispatcher); + instance.start(); + RoomListStore.internalInstance = instance; } return this.internalInstance; diff --git a/src/stores/room-list/SlidingRoomListStore.ts b/src/stores/room-list/SlidingRoomListStore.ts deleted file mode 100644 index b7ff70c671..0000000000 --- a/src/stores/room-list/SlidingRoomListStore.ts +++ /dev/null @@ -1,391 +0,0 @@ -/* -Copyright 2024 New Vector Ltd. -Copyright 2022 The Matrix.org Foundation C.I.C. - -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 { type EmptyObject, type Room } from "matrix-js-sdk/src/matrix"; -import { logger } from "matrix-js-sdk/src/logger"; -import { type MSC3575Filter, SlidingSyncEvent } from "matrix-js-sdk/src/sliding-sync"; -import { type Optional } from "matrix-events-sdk"; - -import { type RoomUpdateCause, type TagID, OrderedDefaultTagIDs, DefaultTagID } from "./models"; -import { type ITagMap, ListAlgorithm, SortAlgorithm } from "./algorithms/models"; -import { type ActionPayload } from "../../dispatcher/payloads"; -import { type MatrixDispatcher } from "../../dispatcher/dispatcher"; -import { type IFilterCondition } from "./filters/IFilterCondition"; -import { AsyncStoreWithClient } from "../AsyncStoreWithClient"; -import { type RoomListStore as Interface, RoomListStoreEvent } from "./Interface"; -import { MetaSpace, type SpaceKey, UPDATE_SELECTED_SPACE } from "../spaces"; -import { LISTS_LOADING_EVENT } from "./RoomListStore"; -import { UPDATE_EVENT } from "../AsyncStore"; -import { type SdkContextClass } from "../../contexts/SDKContext"; - -export const SlidingSyncSortToFilter: Record = { - [SortAlgorithm.Alphabetic]: ["by_name", "by_recency"], - [SortAlgorithm.Recent]: ["by_notification_level", "by_recency"], - [SortAlgorithm.Manual]: ["by_recency"], -}; - -const filterConditions: Record = { - [DefaultTagID.Invite]: { - is_invite: true, - }, - [DefaultTagID.Favourite]: { - tags: ["m.favourite"], - }, - [DefaultTagID.DM]: { - is_dm: true, - is_invite: false, - // If a DM has a Favourite & Low Prio tag then it'll be shown in those lists instead - not_tags: ["m.favourite", "m.lowpriority"], - }, - [DefaultTagID.Untagged]: { - is_dm: false, - is_invite: false, - not_room_types: ["m.space"], - not_tags: ["m.favourite", "m.lowpriority"], - // spaces filter added dynamically - }, - [DefaultTagID.LowPriority]: { - tags: ["m.lowpriority"], - // If a room has both Favourite & Low Prio tags then it'll be shown under Favourites - not_tags: ["m.favourite"], - }, - // TODO https://github.com/vector-im/element-web/issues/23207 - // DefaultTagID.ServerNotice, - // DefaultTagID.Suggested, - // DefaultTagID.Archived, -}; - -export const LISTS_UPDATE_EVENT = RoomListStoreEvent.ListsUpdate; - -export class SlidingRoomListStoreClass extends AsyncStoreWithClient implements Interface { - private tagIdToSortAlgo: Record = {}; - private tagMap: ITagMap = {}; - private counts: Record = {}; - private stickyRoomId: Optional; - - public constructor( - dis: MatrixDispatcher, - private readonly context: SdkContextClass, - ) { - super(dis); - this.setMaxListeners(20); // RoomList + LeftPanel + 8xRoomSubList + spares - } - - public async setTagSorting(tagId: TagID, sort: SortAlgorithm): Promise { - logger.info("SlidingRoomListStore.setTagSorting ", tagId, sort); - this.tagIdToSortAlgo[tagId] = sort; - switch (sort) { - case SortAlgorithm.Alphabetic: - await this.context.slidingSyncManager.ensureListRegistered(tagId, { - sort: SlidingSyncSortToFilter[SortAlgorithm.Alphabetic], - }); - break; - case SortAlgorithm.Recent: - await this.context.slidingSyncManager.ensureListRegistered(tagId, { - sort: SlidingSyncSortToFilter[SortAlgorithm.Recent], - }); - break; - case SortAlgorithm.Manual: - logger.error("cannot enable manual sort in sliding sync mode"); - break; - default: - logger.error("unknown sort mode: ", sort); - } - } - - public getTagSorting(tagId: TagID): SortAlgorithm { - let algo = this.tagIdToSortAlgo[tagId]; - if (!algo) { - logger.warn("SlidingRoomListStore.getTagSorting: no sort algorithm for tag ", tagId); - algo = SortAlgorithm.Recent; // why not, we have to do something.. - } - return algo; - } - - public getCount(tagId: TagID): number { - return this.counts[tagId] || 0; - } - - public setListOrder(tagId: TagID, order: ListAlgorithm): void { - // TODO: https://github.com/vector-im/element-web/issues/23207 - } - - public getListOrder(tagId: TagID): ListAlgorithm { - // TODO: handle unread msgs first? https://github.com/vector-im/element-web/issues/23207 - return ListAlgorithm.Natural; - } - - /** - * Adds a filter condition to the room list store. Filters may be applied async, - * and thus might not cause an update to the store immediately. - * @param {IFilterCondition} filter The filter condition to add. - */ - public async addFilter(filter: IFilterCondition): Promise { - // Do nothing, the filters are only used by SpaceWatcher to see if a room should appear - // in the room list. We do not support arbitrary code for filters in sliding sync. - } - - /** - * Removes a filter condition from the room list store. If the filter was - * not previously added to the room list store, this will no-op. The effects - * of removing a filter may be applied async and therefore might not cause - * an update right away. - * @param {IFilterCondition} filter The filter condition to remove. - */ - public removeFilter(filter: IFilterCondition): void { - // Do nothing, the filters are only used by SpaceWatcher to see if a room should appear - // in the room list. We do not support arbitrary code for filters in sliding sync. - } - - /** - * Gets the tags for a room identified by the store. The returned set - * should never be empty, and will contain DefaultTagID.Untagged if - * the store is not aware of any tags. - * @param room The room to get the tags for. - * @returns The tags for the room. - */ - public getTagsForRoom(room: Room): TagID[] { - // check all lists for each tag we know about and see if the room is there - const tags: TagID[] = []; - for (const tagId in this.tagIdToSortAlgo) { - const listData = this.context.slidingSyncManager.slidingSync?.getListData(tagId); - if (!listData) { - continue; - } - for (const roomIndex in listData.roomIndexToRoomId) { - const roomId = listData.roomIndexToRoomId[roomIndex]; - if (roomId === room.roomId) { - tags.push(tagId); - break; - } - } - } - return tags; - } - - /** - * Manually update a room with a given cause. This should only be used if the - * room list store would otherwise be incapable of doing the update itself. Note - * that this may race with the room list's regular operation. - * @param {Room} room The room to update. - * @param {RoomUpdateCause} cause The cause to update for. - */ - public async manualRoomUpdate(room: Room, cause: RoomUpdateCause): Promise { - // TODO: this is only used when you forget a room, not that important for now. - } - - public get orderedLists(): ITagMap { - return this.tagMap; - } - - private refreshOrderedLists(tagId: string, roomIndexToRoomId: Record): void { - const tagMap = this.tagMap; - - // this room will not move due to it being viewed: it is sticky. This can be null to indicate - // no sticky room if you aren't viewing a room. - this.stickyRoomId = this.context.roomViewStore.getRoomId(); - let stickyRoomNewIndex = -1; - const stickyRoomOldIndex = (tagMap[tagId] || []).findIndex((room): boolean => { - return room.roomId === this.stickyRoomId; - }); - - // order from low to high - const orderedRoomIndexes = Object.keys(roomIndexToRoomId) - .map((numStr) => { - return Number(numStr); - }) - .sort((a, b) => { - return a - b; - }); - const seenRoomIds = new Set(); - const orderedRoomIds = orderedRoomIndexes.map((i) => { - const rid = roomIndexToRoomId[i]; - if (seenRoomIds.has(rid)) { - logger.error("room " + rid + " already has an index position: duplicate room!"); - } - seenRoomIds.add(rid); - if (!rid) { - throw new Error("index " + i + " has no room ID: Map => " + JSON.stringify(roomIndexToRoomId)); - } - if (rid === this.stickyRoomId) { - stickyRoomNewIndex = i; - } - return rid; - }); - logger.debug( - `SlidingRoomListStore.refreshOrderedLists ${tagId} sticky: ${this.stickyRoomId}`, - `${stickyRoomOldIndex} -> ${stickyRoomNewIndex}`, - "rooms:", - orderedRoomIds.length < 30 ? orderedRoomIds : orderedRoomIds.length, - ); - - if (this.stickyRoomId && stickyRoomOldIndex >= 0 && stickyRoomNewIndex >= 0) { - // this update will move this sticky room from old to new, which we do not want. - // Instead, keep the sticky room ID index position as it is, swap it with - // whatever was in its place. - // Some scenarios with sticky room S and bump room B (other letters unimportant): - // A, S, C, B S, A, B - // B, A, S, C <---- without sticky rooms ---> B, S, A - // B, S, A, C <- with sticky rooms applied -> S, B, A - // In other words, we need to swap positions to keep it locked in place. - const inWayRoomId = orderedRoomIds[stickyRoomOldIndex]; - orderedRoomIds[stickyRoomOldIndex] = this.stickyRoomId; - orderedRoomIds[stickyRoomNewIndex] = inWayRoomId; - } - - // now set the rooms - const rooms: Room[] = []; - orderedRoomIds.forEach((roomId) => { - const room = this.matrixClient?.getRoom(roomId); - if (!room) { - return; - } - rooms.push(room); - }); - tagMap[tagId] = rooms; - this.tagMap = tagMap; - } - - private onSlidingSyncListUpdate(tagId: string, joinCount: number, roomIndexToRoomId: Record): void { - this.counts[tagId] = joinCount; - this.refreshOrderedLists(tagId, roomIndexToRoomId); - // let the UI update - this.emit(LISTS_UPDATE_EVENT); - } - - private onRoomViewStoreUpdated(): void { - // we only care about this to know when the user has clicked on a room to set the stickiness value - if (this.context.roomViewStore.getRoomId() === this.stickyRoomId) { - return; - } - - let hasUpdatedAnyList = false; - - // every list with the OLD sticky room ID needs to be resorted because it now needs to take - // its proper place as it is no longer sticky. The newly sticky room can remain the same though, - // as we only actually care about its sticky status when we get list updates. - const oldStickyRoom = this.stickyRoomId; - // it's not safe to check the data in slidingSync as it is tracking the server's view of the - // room list. There's an edge case whereby the sticky room has gone outside the window and so - // would not be present in the roomIndexToRoomId map anymore, and hence clicking away from it - // will make it disappear eventually. We need to check orderedLists as that is the actual - // sorted renderable list of rooms which sticky rooms apply to. - for (const tagId in this.orderedLists) { - const list = this.orderedLists[tagId]; - const room = list.find((room) => { - return room.roomId === oldStickyRoom; - }); - if (room) { - // resort it based on the slidingSync view of the list. This may cause this old sticky - // room to cease to exist. - const listData = this.context.slidingSyncManager.slidingSync?.getListData(tagId); - if (!listData) { - continue; - } - this.refreshOrderedLists(tagId, listData.roomIndexToRoomId); - hasUpdatedAnyList = true; - } - } - // in the event we didn't call refreshOrderedLists, it helps to still remember the sticky room ID. - this.stickyRoomId = this.context.roomViewStore.getRoomId(); - - if (hasUpdatedAnyList) { - this.emit(LISTS_UPDATE_EVENT); - } - } - - protected async onReady(): Promise { - logger.info("SlidingRoomListStore.onReady"); - // permanent listeners: never get destroyed. Could be an issue if we want to test this in isolation. - this.context.slidingSyncManager.slidingSync!.on(SlidingSyncEvent.List, this.onSlidingSyncListUpdate.bind(this)); - this.context.roomViewStore.addListener(UPDATE_EVENT, this.onRoomViewStoreUpdated.bind(this)); - this.context.spaceStore.on(UPDATE_SELECTED_SPACE, this.onSelectedSpaceUpdated.bind(this)); - if (this.context.spaceStore.activeSpace) { - this.onSelectedSpaceUpdated(this.context.spaceStore.activeSpace, false); - } - - // sliding sync has an initial response for spaces. Now request all the lists. - // We do the spaces list _first_ to avoid potential flickering on DefaultTagID.Untagged list - // which would be caused by initially having no `spaces` filter set, and then suddenly setting one. - OrderedDefaultTagIDs.forEach((tagId) => { - const filter = filterConditions[tagId]; - if (!filter) { - logger.info("SlidingRoomListStore.onReady unsupported list ", tagId); - return; // we do not support this list yet. - } - const sort = SortAlgorithm.Recent; // default to recency sort, TODO: read from config - this.tagIdToSortAlgo[tagId] = sort; - this.emit(LISTS_LOADING_EVENT, tagId, true); - this.context.slidingSyncManager - .ensureListRegistered(tagId, { - filters: filter, - sort: SlidingSyncSortToFilter[sort], - }) - .then(() => { - this.emit(LISTS_LOADING_EVENT, tagId, false); - }); - }); - } - - private onSelectedSpaceUpdated = (activeSpace: SpaceKey, allRoomsInHome: boolean): void => { - logger.info("SlidingRoomListStore.onSelectedSpaceUpdated", activeSpace); - // update the untagged filter - const tagId = DefaultTagID.Untagged; - const filters = filterConditions[tagId]; - const oldSpace = filters.spaces?.[0]; - filters.spaces = activeSpace && activeSpace != MetaSpace.Home ? [activeSpace] : undefined; - if (oldSpace !== activeSpace) { - // include subspaces in this list - this.context.spaceStore.traverseSpace( - activeSpace, - (roomId: string) => { - if (roomId === activeSpace) { - return; - } - if (!filters.spaces) { - filters.spaces = []; - } - filters.spaces.push(roomId); // add subspace - }, - false, - ); - - this.emit(LISTS_LOADING_EVENT, tagId, true); - this.context.slidingSyncManager - .ensureListRegistered(tagId, { - filters: filters, - }) - .then(() => { - this.emit(LISTS_LOADING_EVENT, tagId, false); - }); - } - }; - - // Intended for test usage - public async resetStore(): Promise { - // Test function - } - - /** - * Regenerates the room whole room list, discarding any previous results. - * - * Note: This is only exposed externally for the tests. Do not call this from within - * the app. - * @param trigger Set to false to prevent a list update from being sent. Should only - * be used if the calling code will manually trigger the update. - */ - public regenerateAllLists({ trigger = true }): void { - // Test function - } - - protected async onNotReady(): Promise { - await this.resetStore(); - } - - protected async onAction(payload: ActionPayload): Promise {} -} diff --git a/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts b/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts index e84f538993..e41eeee816 100644 --- a/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts +++ b/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts @@ -69,6 +69,12 @@ export const getLastTs = (r: Room, userId: string): number => { if (!r?.timeline) { return Number.MAX_SAFE_INTEGER; } + // MSC4186: Simplified Sliding Sync sets this. + // If it's present, sort by it. + const bumpStamp = r.getBumpStamp(); + if (bumpStamp) { + return bumpStamp; + } // If the room hasn't been joined yet, it probably won't have a timeline to // parse. We'll still fall back to the timeline if this fails, but chances diff --git a/test/test-utils/test-utils.ts b/test/test-utils/test-utils.ts index 1f6351b7b9..75a42c86bc 100644 --- a/test/test-utils/test-utils.ts +++ b/test/test-utils/test-utils.ts @@ -661,6 +661,7 @@ export function mkStubRoom( getUnreadNotificationCount: jest.fn(() => 0), getRoomUnreadNotificationCount: jest.fn().mockReturnValue(0), getVersion: jest.fn().mockReturnValue("1"), + getBumpStamp: jest.fn().mockReturnValue(0), hasMembershipState: () => false, isElementVideoRoom: jest.fn().mockReturnValue(false), isSpaceRoom: jest.fn().mockReturnValue(false), diff --git a/test/unit-tests/SlidingSyncManager-test.ts b/test/unit-tests/SlidingSyncManager-test.ts index ddc5911262..20d9110bcc 100644 --- a/test/unit-tests/SlidingSyncManager-test.ts +++ b/test/unit-tests/SlidingSyncManager-test.ts @@ -6,18 +6,31 @@ 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 { SlidingSync } from "matrix-js-sdk/src/sliding-sync"; +import { type SlidingSync, SlidingSyncEvent, SlidingSyncState } from "matrix-js-sdk/src/sliding-sync"; import { mocked } from "jest-mock"; -import { type MatrixClient, MatrixEvent, Room } from "matrix-js-sdk/src/matrix"; +import { ClientEvent, type MatrixClient, MatrixEvent, Room } from "matrix-js-sdk/src/matrix"; import fetchMockJest from "fetch-mock-jest"; +import EventEmitter from "events"; +import { waitFor } from "jest-matrix-react"; import { SlidingSyncManager } from "../../src/SlidingSyncManager"; -import { stubClient } from "../test-utils"; -import SlidingSyncController from "../../src/settings/controllers/SlidingSyncController"; -import SettingsStore from "../../src/settings/SettingsStore"; +import { mkStubRoom, stubClient } from "../test-utils"; -jest.mock("matrix-js-sdk/src/sliding-sync"); -const MockSlidingSync = >(SlidingSync); +class MockSlidingSync extends EventEmitter { + lists = {}; + listModifiedCount = 0; + terminated = false; + needsResend = false; + modifyRoomSubscriptions = jest.fn(); + getRoomSubscriptions = jest.fn(); + useCustomSubscription = jest.fn(); + getListParams = jest.fn(); + setList = jest.fn(); + setListRanges = jest.fn(); + getListData = jest.fn(); + extensions = jest.fn(); + desiredRoomSubscriptions = jest.fn(); +} describe("SlidingSyncManager", () => { let manager: SlidingSyncManager; @@ -25,12 +38,12 @@ describe("SlidingSyncManager", () => { let client: MatrixClient; beforeEach(() => { - slidingSync = new MockSlidingSync(); + slidingSync = new MockSlidingSync() as unknown as SlidingSync; manager = new SlidingSyncManager(); client = stubClient(); // by default the client has no rooms: stubClient magically makes rooms annoyingly. mocked(client.getRoom).mockReturnValue(null); - manager.configure(client, "invalid"); + (manager as any).configure(client, "invalid"); manager.slidingSync = slidingSync; fetchMockJest.reset(); fetchMockJest.get("https://proxy/client/server.json", {}); @@ -39,12 +52,13 @@ describe("SlidingSyncManager", () => { describe("setRoomVisible", () => { it("adds a subscription for the room", async () => { const roomId = "!room:id"; + mocked(client.getRoom).mockReturnValue(mkStubRoom(roomId, "foo", client)); const subs = new Set(); mocked(slidingSync.getRoomSubscriptions).mockReturnValue(subs); - mocked(slidingSync.modifyRoomSubscriptions).mockResolvedValue("yep"); - await manager.setRoomVisible(roomId, true); + await manager.setRoomVisible(roomId); expect(slidingSync.modifyRoomSubscriptions).toHaveBeenCalledWith(new Set([roomId])); }); + it("adds a custom subscription for a lazy-loadable room", async () => { const roomId = "!lazy:id"; const room = new Room(roomId, client, client.getUserId()!); @@ -67,19 +81,37 @@ describe("SlidingSyncManager", () => { }); const subs = new Set(); mocked(slidingSync.getRoomSubscriptions).mockReturnValue(subs); - mocked(slidingSync.modifyRoomSubscriptions).mockResolvedValue("yep"); - await manager.setRoomVisible(roomId, true); + await manager.setRoomVisible(roomId); expect(slidingSync.modifyRoomSubscriptions).toHaveBeenCalledWith(new Set([roomId])); // we aren't prescriptive about what the sub name is. expect(slidingSync.useCustomSubscription).toHaveBeenCalledWith(roomId, expect.anything()); }); + + it("waits if the room is not yet known", async () => { + const roomId = "!room:id"; + mocked(client.getRoom).mockReturnValue(null); + const subs = new Set(); + mocked(slidingSync.getRoomSubscriptions).mockReturnValue(subs); + + const setVisibleDone = jest.fn(); + manager.setRoomVisible(roomId).then(setVisibleDone); + + await waitFor(() => expect(client.getRoom).toHaveBeenCalledWith(roomId)); + + expect(setVisibleDone).not.toHaveBeenCalled(); + + const stubRoom = mkStubRoom(roomId, "foo", client); + mocked(client.getRoom).mockReturnValue(stubRoom); + client.emit(ClientEvent.Room, stubRoom); + + await waitFor(() => expect(setVisibleDone).toHaveBeenCalled()); + }); }); describe("ensureListRegistered", () => { it("creates a new list based on the key", async () => { const listKey = "key"; mocked(slidingSync.getListParams).mockReturnValue(null); - mocked(slidingSync.setList).mockResolvedValue("yep"); await manager.ensureListRegistered(listKey, { sort: ["by_recency"], }); @@ -96,7 +128,6 @@ describe("SlidingSyncManager", () => { mocked(slidingSync.getListParams).mockReturnValue({ ranges: [[0, 42]], }); - mocked(slidingSync.setList).mockResolvedValue("yep"); await manager.ensureListRegistered(listKey, { sort: ["by_recency"], }); @@ -114,7 +145,6 @@ describe("SlidingSyncManager", () => { mocked(slidingSync.getListParams).mockReturnValue({ ranges: [[0, 42]], }); - mocked(slidingSync.setList).mockResolvedValue("yep"); await manager.ensureListRegistered(listKey, { ranges: [[0, 52]], }); @@ -128,7 +158,6 @@ describe("SlidingSyncManager", () => { ranges: [[0, 42]], sort: ["by_recency"], }); - mocked(slidingSync.setList).mockResolvedValue("yep"); await manager.ensureListRegistered(listKey, { ranges: [[0, 42]], sort: ["by_recency"], @@ -139,183 +168,77 @@ describe("SlidingSyncManager", () => { }); describe("startSpidering", () => { - it("requests in batchSizes", async () => { + it("requests in expanding batchSizes", async () => { const gapMs = 1; const batchSize = 10; - mocked(slidingSync.setList).mockResolvedValue("yep"); - mocked(slidingSync.setListRanges).mockResolvedValue("yep"); mocked(slidingSync.getListData).mockImplementation((key) => { return { joinedCount: 64, roomIndexToRoomId: {}, }; }); - await manager.startSpidering(batchSize, gapMs); + await (manager as any).startSpidering(slidingSync, batchSize, gapMs); + // we expect calls for 10,19 -> 20,29 -> 30,39 -> 40,49 -> 50,59 -> 60,69 const wantWindows = [ - [10, 19], - [20, 29], - [30, 39], - [40, 49], - [50, 59], - [60, 69], + [0, 10], + [0, 20], + [0, 30], + [0, 40], + [0, 50], + [0, 60], + [0, 70], ]; - expect(slidingSync.getListData).toHaveBeenCalledTimes(wantWindows.length); - expect(slidingSync.setList).toHaveBeenCalledTimes(1); - expect(slidingSync.setListRanges).toHaveBeenCalledTimes(wantWindows.length - 1); - wantWindows.forEach((range, i) => { - if (i === 0) { - // eslint-disable-next-line jest/no-conditional-expect - expect(slidingSync.setList).toHaveBeenCalledWith( - SlidingSyncManager.ListSearch, - // eslint-disable-next-line jest/no-conditional-expect - expect.objectContaining({ - ranges: [[0, batchSize - 1], range], - }), - ); - return; - } - expect(slidingSync.setListRanges).toHaveBeenCalledWith(SlidingSyncManager.ListSearch, [ - [0, batchSize - 1], - range, - ]); - }); + + for (let i = 1; i < wantWindows.length; ++i) { + // each time we emit, it should expand the range of all 5 lists by 10 until + // they all include all the rooms (64), which is 6 emits. + slidingSync.emit(SlidingSyncEvent.Lifecycle, SlidingSyncState.Complete, null, undefined); + await waitFor(() => expect(slidingSync.getListData).toHaveBeenCalledTimes(i * 5)); + expect(slidingSync.setListRanges).toHaveBeenCalledTimes(i * 5); + expect(slidingSync.setListRanges).toHaveBeenCalledWith("spaces", [wantWindows[i]]); + } }); it("handles accounts with zero rooms", async () => { const gapMs = 1; const batchSize = 10; - mocked(slidingSync.setList).mockResolvedValue("yep"); mocked(slidingSync.getListData).mockImplementation((key) => { return { joinedCount: 0, roomIndexToRoomId: {}, }; }); - await manager.startSpidering(batchSize, gapMs); - expect(slidingSync.getListData).toHaveBeenCalledTimes(1); - expect(slidingSync.setList).toHaveBeenCalledTimes(1); - expect(slidingSync.setList).toHaveBeenCalledWith( - SlidingSyncManager.ListSearch, - expect.objectContaining({ - ranges: [ - [0, batchSize - 1], - [batchSize, batchSize + batchSize - 1], - ], - }), - ); - }); - it("continues even when setList rejects", async () => { - const gapMs = 1; - const batchSize = 10; - mocked(slidingSync.setList).mockRejectedValue("narp"); - mocked(slidingSync.getListData).mockImplementation((key) => { - return { - joinedCount: 0, - roomIndexToRoomId: {}, - }; - }); - await manager.startSpidering(batchSize, gapMs); - expect(slidingSync.getListData).toHaveBeenCalledTimes(1); - expect(slidingSync.setList).toHaveBeenCalledTimes(1); - expect(slidingSync.setList).toHaveBeenCalledWith( - SlidingSyncManager.ListSearch, - expect.objectContaining({ - ranges: [ - [0, batchSize - 1], - [batchSize, batchSize + batchSize - 1], - ], - }), - ); + await (manager as any).startSpidering(slidingSync, batchSize, gapMs); + slidingSync.emit(SlidingSyncEvent.Lifecycle, SlidingSyncState.Complete, null, undefined); + await waitFor(() => expect(slidingSync.getListData).toHaveBeenCalledTimes(5)); + // should not have needed to expand the range + expect(slidingSync.setListRanges).not.toHaveBeenCalled(); }); }); describe("checkSupport", () => { beforeEach(() => { - SlidingSyncController.serverSupportsSlidingSync = false; - jest.spyOn(manager, "getProxyFromWellKnown").mockResolvedValue("https://proxy/"); + SlidingSyncManager.serverSupportsSlidingSync = false; }); it("shorts out if the server has 'native' sliding sync support", async () => { jest.spyOn(manager, "nativeSlidingSyncSupport").mockResolvedValue(true); - expect(SlidingSyncController.serverSupportsSlidingSync).toBeFalsy(); + expect(SlidingSyncManager.serverSupportsSlidingSync).toBeFalsy(); await manager.checkSupport(client); - expect(manager.getProxyFromWellKnown).not.toHaveBeenCalled(); // We return earlier - expect(SlidingSyncController.serverSupportsSlidingSync).toBeTruthy(); - }); - it("tries to find a sliding sync proxy url from the client well-known if there's no 'native' support", async () => { - jest.spyOn(manager, "nativeSlidingSyncSupport").mockResolvedValue(false); - expect(SlidingSyncController.serverSupportsSlidingSync).toBeFalsy(); - await manager.checkSupport(client); - expect(manager.getProxyFromWellKnown).toHaveBeenCalled(); - expect(SlidingSyncController.serverSupportsSlidingSync).toBeTruthy(); - }); - it("should query well-known on server_name not baseUrl", async () => { - fetchMockJest.get("https://matrix.org/.well-known/matrix/client", { - "m.homeserver": { - base_url: "https://matrix-client.matrix.org", - server: "matrix.org", - }, - "org.matrix.msc3575.proxy": { - url: "https://proxy/", - }, - }); - fetchMockJest.get("https://matrix-client.matrix.org/_matrix/client/versions", { versions: ["v1.4"] }); - - mocked(manager.getProxyFromWellKnown).mockRestore(); - jest.spyOn(manager, "nativeSlidingSyncSupport").mockResolvedValue(false); - expect(SlidingSyncController.serverSupportsSlidingSync).toBeFalsy(); - await manager.checkSupport(client); - expect(SlidingSyncController.serverSupportsSlidingSync).toBeTruthy(); - expect(fetchMockJest).not.toHaveFetched("https://matrix-client.matrix.org/.well-known/matrix/client"); - }); - }); - describe("nativeSlidingSyncSupport", () => { - beforeEach(() => { - SlidingSyncController.serverSupportsSlidingSync = false; - }); - it("should make an OPTIONS request to avoid unintended side effects", async () => { - // See https://github.com/element-hq/element-web/issues/27426 - - const unstableSpy = jest - .spyOn(client, "doesServerSupportUnstableFeature") - .mockImplementation(async (feature: string) => { - expect(feature).toBe("org.matrix.msc3575"); - return true; - }); - const proxySpy = jest.spyOn(manager, "getProxyFromWellKnown").mockResolvedValue("https://proxy/"); - - expect(SlidingSyncController.serverSupportsSlidingSync).toBeFalsy(); - await manager.checkSupport(client); // first thing it does is call nativeSlidingSyncSupport - expect(proxySpy).not.toHaveBeenCalled(); - expect(unstableSpy).toHaveBeenCalled(); - expect(SlidingSyncController.serverSupportsSlidingSync).toBeTruthy(); + expect(SlidingSyncManager.serverSupportsSlidingSync).toBeTruthy(); }); }); describe("setup", () => { + let untypedManager: any; + beforeEach(() => { - jest.spyOn(manager, "configure"); - jest.spyOn(manager, "startSpidering"); + untypedManager = manager; + jest.spyOn(untypedManager, "configure"); + jest.spyOn(untypedManager, "startSpidering"); }); - it("uses the baseUrl as a proxy if no proxy is set in the client well-known and the server has no native support", async () => { + it("uses the baseUrl", async () => { await manager.setup(client); - expect(manager.configure).toHaveBeenCalled(); - expect(manager.configure).toHaveBeenCalledWith(client, client.baseUrl); - expect(manager.startSpidering).toHaveBeenCalled(); - }); - it("uses the proxy declared in the client well-known", async () => { - jest.spyOn(manager, "getProxyFromWellKnown").mockResolvedValue("https://proxy/"); - await manager.setup(client); - expect(manager.configure).toHaveBeenCalled(); - expect(manager.configure).toHaveBeenCalledWith(client, "https://proxy/"); - expect(manager.startSpidering).toHaveBeenCalled(); - }); - it("uses the legacy `feature_sliding_sync_proxy_url` if it was set", async () => { - jest.spyOn(manager, "getProxyFromWellKnown").mockResolvedValue("https://proxy/"); - jest.spyOn(SettingsStore, "getValue").mockImplementation((name: string): any => { - if (name === "feature_sliding_sync_proxy_url") return "legacy-proxy"; - }); - await manager.setup(client); - expect(manager.configure).toHaveBeenCalled(); - expect(manager.configure).toHaveBeenCalledWith(client, "legacy-proxy"); - expect(manager.startSpidering).toHaveBeenCalled(); + expect(untypedManager.configure).toHaveBeenCalled(); + expect(untypedManager.configure).toHaveBeenCalledWith(client, client.baseUrl); + expect(untypedManager.startSpidering).toHaveBeenCalled(); }); }); }); diff --git a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx index 4b986f8d2d..f14a7e0acd 100644 --- a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx +++ b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx @@ -11,7 +11,7 @@ import { mocked } from "jest-mock"; import RoomListStoreV3 from "../../../../../src/stores/room-list-v3/RoomListStoreV3"; import { mkStubRoom } from "../../../../test-utils"; -import { LISTS_UPDATE_EVENT } from "../../../../../src/stores/room-list/SlidingRoomListStore"; +import { LISTS_UPDATE_EVENT } from "../../../../../src/stores/room-list/RoomListStore"; import { useRoomListViewModel } from "../../../../../src/components/viewmodels/roomlist/RoomListViewModel"; import { FilterKey } from "../../../../../src/stores/room-list-v3/skip-list/filters"; import { SecondaryFilters } from "../../../../../src/components/viewmodels/roomlist/useFilteredRooms"; diff --git a/test/unit-tests/hooks/useSlidingSyncRoomSearch-test.tsx b/test/unit-tests/hooks/useSlidingSyncRoomSearch-test.tsx deleted file mode 100644 index d2ee9ad3bb..0000000000 --- a/test/unit-tests/hooks/useSlidingSyncRoomSearch-test.tsx +++ /dev/null @@ -1,84 +0,0 @@ -/* -Copyright 2024 New Vector Ltd. -Copyright 2023 The Matrix.org Foundation C.I.C. - -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 { waitFor, renderHook, act } from "jest-matrix-react"; -import { mocked } from "jest-mock"; -import { type SlidingSync } from "matrix-js-sdk/src/sliding-sync"; -import { Room } from "matrix-js-sdk/src/matrix"; - -import { useSlidingSyncRoomSearch } from "../../../src/hooks/useSlidingSyncRoomSearch"; -import { MockEventEmitter, stubClient } from "../../test-utils"; -import { SlidingSyncManager } from "../../../src/SlidingSyncManager"; - -describe("useSlidingSyncRoomSearch", () => { - afterAll(() => { - jest.restoreAllMocks(); - }); - - it("should display rooms when searching", async () => { - const client = stubClient(); - const roomA = new Room("!a:localhost", client, client.getUserId()!); - const roomB = new Room("!b:localhost", client, client.getUserId()!); - const slidingSync = mocked( - new MockEventEmitter({ - getListData: jest.fn(), - }) as unknown as SlidingSync, - ); - jest.spyOn(SlidingSyncManager.instance, "ensureListRegistered").mockResolvedValue({ - ranges: [[0, 9]], - }); - SlidingSyncManager.instance.slidingSync = slidingSync; - mocked(slidingSync.getListData).mockReturnValue({ - joinedCount: 2, - roomIndexToRoomId: { - 0: roomA.roomId, - 1: roomB.roomId, - }, - }); - mocked(client.getRoom).mockImplementation((roomId) => { - switch (roomId) { - case roomA.roomId: - return roomA; - case roomB.roomId: - return roomB; - default: - return null; - } - }); - - // first check that everything is empty - const { result } = renderHook(() => useSlidingSyncRoomSearch()); - const query = { - limit: 10, - query: "foo", - }; - expect(result.current.loading).toBe(false); - expect(result.current.rooms).toEqual([]); - - // run the query - act(() => { - result.current.search(query); - }); - - // wait for loading to finish - await waitFor(() => { - expect(result.current.loading).toBe(false); - }); - - // now we expect there to be rooms - expect(result.current.rooms).toEqual([roomA, roomB]); - - // run the query again - act(() => { - result.current.search(query); - }); - await waitFor(() => { - expect(result.current.loading).toBe(false); - }); - }); -}); diff --git a/test/unit-tests/stores/MemberListStore-test.ts b/test/unit-tests/stores/MemberListStore-test.ts index 883bb13f11..9139dde85d 100644 --- a/test/unit-tests/stores/MemberListStore-test.ts +++ b/test/unit-tests/stores/MemberListStore-test.ts @@ -161,7 +161,7 @@ describe("MemberListStore", () => { describe("sliding sync", () => { beforeEach(() => { jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName, roomId, value) => { - return settingName === "feature_sliding_sync"; // this is enabled, everything else is disabled. + return settingName === "feature_simplified_sliding_sync"; // this is enabled, everything else is disabled. }); client.members = jest.fn(); }); diff --git a/test/unit-tests/stores/RoomViewStore-test.ts b/test/unit-tests/stores/RoomViewStore-test.ts index be08015fc1..b730853a89 100644 --- a/test/unit-tests/stores/RoomViewStore-test.ts +++ b/test/unit-tests/stores/RoomViewStore-test.ts @@ -383,43 +383,35 @@ describe("RoomViewStore", function () { describe("Sliding Sync", function () { beforeEach(() => { jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName, roomId, value) => { - return settingName === "feature_sliding_sync"; // this is enabled, everything else is disabled. + return settingName === "feature_simplified_sliding_sync"; // this is enabled, everything else is disabled. }); }); it("subscribes to the room", async () => { - const setRoomVisible = jest - .spyOn(slidingSyncManager, "setRoomVisible") - .mockReturnValue(Promise.resolve("")); + const setRoomVisible = jest.spyOn(slidingSyncManager, "setRoomVisible").mockReturnValue(Promise.resolve()); const subscribedRoomId = "!sub1:localhost"; dis.dispatch({ action: Action.ViewRoom, room_id: subscribedRoomId }); await untilDispatch(Action.ActiveRoomChanged, dis); expect(roomViewStore.getRoomId()).toBe(subscribedRoomId); - expect(setRoomVisible).toHaveBeenCalledWith(subscribedRoomId, true); + expect(setRoomVisible).toHaveBeenCalledWith(subscribedRoomId); }); - // Regression test for an in-the-wild bug where rooms would rapidly switch forever in sliding sync mode + // Previously a regression test for an in-the-wild bug where rooms would rapidly switch forever in sliding sync mode + // although that was before the complexity was removed with similified mode. I've removed the complexity but kept the + // test anyway. it("doesn't get stuck in a loop if you view rooms quickly", async () => { - const setRoomVisible = jest - .spyOn(slidingSyncManager, "setRoomVisible") - .mockReturnValue(Promise.resolve("")); + const setRoomVisible = jest.spyOn(slidingSyncManager, "setRoomVisible").mockReturnValue(Promise.resolve()); const subscribedRoomId = "!sub1:localhost"; const subscribedRoomId2 = "!sub2:localhost"; dis.dispatch({ action: Action.ViewRoom, room_id: subscribedRoomId }, true); dis.dispatch({ action: Action.ViewRoom, room_id: subscribedRoomId2 }, true); await untilDispatch(Action.ActiveRoomChanged, dis); - // sub(1) then unsub(1) sub(2), unsub(1) - const wantCalls = [ - [subscribedRoomId, true], - [subscribedRoomId, false], - [subscribedRoomId2, true], - [subscribedRoomId, false], - ]; + // should view 1, then 2 + const wantCalls = [[subscribedRoomId], [subscribedRoomId2]]; expect(setRoomVisible).toHaveBeenCalledTimes(wantCalls.length); wantCalls.forEach((v, i) => { try { expect(setRoomVisible.mock.calls[i][0]).toEqual(v[0]); - expect(setRoomVisible.mock.calls[i][1]).toEqual(v[1]); } catch { throw new Error(`i=${i} got ${setRoomVisible.mock.calls[i]} want ${v}`); } diff --git a/test/unit-tests/stores/room-list/SlidingRoomListStore-test.ts b/test/unit-tests/stores/room-list/SlidingRoomListStore-test.ts deleted file mode 100644 index dbe06ab326..0000000000 --- a/test/unit-tests/stores/room-list/SlidingRoomListStore-test.ts +++ /dev/null @@ -1,341 +0,0 @@ -/* -Copyright 2024 New Vector Ltd. -Copyright 2022 The Matrix.org Foundation C.I.C. - -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 { mocked } from "jest-mock"; -import { type SlidingSync, SlidingSyncEvent } from "matrix-js-sdk/src/sliding-sync"; -import { Room } from "matrix-js-sdk/src/matrix"; - -import { - LISTS_UPDATE_EVENT, - SlidingRoomListStoreClass, - SlidingSyncSortToFilter, -} from "../../../../src/stores/room-list/SlidingRoomListStore"; -import { type SpaceStoreClass } from "../../../../src/stores/spaces/SpaceStore"; -import { MockEventEmitter, stubClient, untilEmission } from "../../../test-utils"; -import { TestSdkContext } from "../../TestSdkContext"; -import { SlidingSyncManager } from "../../../../src/SlidingSyncManager"; -import { type RoomViewStore } from "../../../../src/stores/RoomViewStore"; -import { MatrixDispatcher } from "../../../../src/dispatcher/dispatcher"; -import { SortAlgorithm } from "../../../../src/stores/room-list/algorithms/models"; -import { DefaultTagID, type TagID } from "../../../../src/stores/room-list/models"; -import { MetaSpace, UPDATE_SELECTED_SPACE } from "../../../../src/stores/spaces"; -import { LISTS_LOADING_EVENT } from "../../../../src/stores/room-list/RoomListStore"; -import { UPDATE_EVENT } from "../../../../src/stores/AsyncStore"; - -jest.mock("../../../../src/SlidingSyncManager"); -const MockSlidingSyncManager = >(SlidingSyncManager); - -describe("SlidingRoomListStore", () => { - let store: SlidingRoomListStoreClass; - let context: TestSdkContext; - let dis: MatrixDispatcher; - let activeSpace: string; - - beforeEach(async () => { - context = new TestSdkContext(); - context.client = stubClient(); - context._SpaceStore = new MockEventEmitter({ - traverseSpace: jest.fn(), - get activeSpace() { - return activeSpace; - }, - }) as SpaceStoreClass; - context._SlidingSyncManager = new MockSlidingSyncManager(); - context._SlidingSyncManager.slidingSync = mocked( - new MockEventEmitter({ - getListData: jest.fn(), - }) as unknown as SlidingSync, - ); - context._RoomViewStore = mocked( - new MockEventEmitter({ - getRoomId: jest.fn(), - }) as unknown as RoomViewStore, - ); - mocked(context._SlidingSyncManager.ensureListRegistered).mockResolvedValue({ - ranges: [[0, 10]], - }); - - dis = new MatrixDispatcher(); - store = new SlidingRoomListStoreClass(dis, context); - }); - - describe("spaces", () => { - it("alters 'filters.spaces' on the DefaultTagID.Untagged list when the selected space changes", async () => { - await store.start(); // call onReady - const spaceRoomId = "!foo:bar"; - - const p = untilEmission(store, LISTS_LOADING_EVENT, (listName, isLoading) => { - return listName === DefaultTagID.Untagged && !isLoading; - }); - - // change the active space - activeSpace = spaceRoomId; - context._SpaceStore!.emit(UPDATE_SELECTED_SPACE, spaceRoomId, false); - await p; - - expect(context._SlidingSyncManager!.ensureListRegistered).toHaveBeenCalledWith(DefaultTagID.Untagged, { - filters: expect.objectContaining({ - spaces: [spaceRoomId], - }), - }); - }); - - it("gracefully handles subspaces in the home metaspace", async () => { - const subspace = "!sub:space"; - mocked(context._SpaceStore!.traverseSpace).mockImplementation( - (spaceId: string, fn: (roomId: string) => void) => { - fn(subspace); - }, - ); - activeSpace = MetaSpace.Home; - await store.start(); // call onReady - - expect(context._SlidingSyncManager!.ensureListRegistered).toHaveBeenCalledWith(DefaultTagID.Untagged, { - filters: expect.objectContaining({ - spaces: [subspace], - }), - }); - }); - - it("alters 'filters.spaces' on the DefaultTagID.Untagged list if it loads with an active space", async () => { - // change the active space before we are ready - const spaceRoomId = "!foo2:bar"; - activeSpace = spaceRoomId; - const p = untilEmission(store, LISTS_LOADING_EVENT, (listName, isLoading) => { - return listName === DefaultTagID.Untagged && !isLoading; - }); - await store.start(); // call onReady - await p; - expect(context._SlidingSyncManager!.ensureListRegistered).toHaveBeenCalledWith( - DefaultTagID.Untagged, - expect.objectContaining({ - filters: expect.objectContaining({ - spaces: [spaceRoomId], - }), - }), - ); - }); - - it("includes subspaces in 'filters.spaces' when the selected space has subspaces", async () => { - await store.start(); // call onReady - const spaceRoomId = "!foo:bar"; - const subSpace1 = "!ss1:bar"; - const subSpace2 = "!ss2:bar"; - - const p = untilEmission(store, LISTS_LOADING_EVENT, (listName, isLoading) => { - return listName === DefaultTagID.Untagged && !isLoading; - }); - - mocked(context._SpaceStore!.traverseSpace).mockImplementation( - (spaceId: string, fn: (roomId: string) => void) => { - if (spaceId === spaceRoomId) { - fn(subSpace1); - fn(subSpace2); - } - }, - ); - - // change the active space - activeSpace = spaceRoomId; - context._SpaceStore!.emit(UPDATE_SELECTED_SPACE, spaceRoomId, false); - await p; - - expect(context._SlidingSyncManager!.ensureListRegistered).toHaveBeenCalledWith(DefaultTagID.Untagged, { - filters: expect.objectContaining({ - spaces: [spaceRoomId, subSpace1, subSpace2], - }), - }); - }); - }); - - it("setTagSorting alters the 'sort' option in the list", async () => { - const tagId: TagID = "foo"; - await store.setTagSorting(tagId, SortAlgorithm.Alphabetic); - expect(context._SlidingSyncManager!.ensureListRegistered).toHaveBeenCalledWith(tagId, { - sort: SlidingSyncSortToFilter[SortAlgorithm.Alphabetic], - }); - expect(store.getTagSorting(tagId)).toEqual(SortAlgorithm.Alphabetic); - - await store.setTagSorting(tagId, SortAlgorithm.Recent); - expect(context._SlidingSyncManager!.ensureListRegistered).toHaveBeenCalledWith(tagId, { - sort: SlidingSyncSortToFilter[SortAlgorithm.Recent], - }); - expect(store.getTagSorting(tagId)).toEqual(SortAlgorithm.Recent); - }); - - it("getTagsForRoom gets the tags for the room", async () => { - await store.start(); - const roomA = "!a:localhost"; - const roomB = "!b:localhost"; - const keyToListData: Record }> = { - [DefaultTagID.Untagged]: { - joinedCount: 10, - roomIndexToRoomId: { - 0: roomA, - 1: roomB, - }, - }, - [DefaultTagID.Favourite]: { - joinedCount: 2, - roomIndexToRoomId: { - 0: roomB, - }, - }, - }; - mocked(context._SlidingSyncManager!.slidingSync!.getListData).mockImplementation((key: string) => { - return keyToListData[key] || null; - }); - - expect(store.getTagsForRoom(new Room(roomA, context.client!, context.client!.getUserId()!))).toEqual([ - DefaultTagID.Untagged, - ]); - expect(store.getTagsForRoom(new Room(roomB, context.client!, context.client!.getUserId()!))).toEqual([ - DefaultTagID.Favourite, - DefaultTagID.Untagged, - ]); - }); - - it("emits LISTS_UPDATE_EVENT when slidingSync lists update", async () => { - await store.start(); - const roomA = "!a:localhost"; - const roomB = "!b:localhost"; - const roomC = "!c:localhost"; - const tagId = DefaultTagID.Favourite; - const joinCount = 10; - const roomIndexToRoomId = { - // mixed to ensure we sort - 1: roomB, - 2: roomC, - 0: roomA, - }; - const rooms = [ - new Room(roomA, context.client!, context.client!.getUserId()!), - new Room(roomB, context.client!, context.client!.getUserId()!), - new Room(roomC, context.client!, context.client!.getUserId()!), - ]; - mocked(context.client!.getRoom).mockImplementation((roomId: string) => { - switch (roomId) { - case roomA: - return rooms[0]; - case roomB: - return rooms[1]; - case roomC: - return rooms[2]; - } - return null; - }); - const p = untilEmission(store, LISTS_UPDATE_EVENT); - context.slidingSyncManager.slidingSync!.emit(SlidingSyncEvent.List, tagId, joinCount, roomIndexToRoomId); - await p; - expect(store.getCount(tagId)).toEqual(joinCount); - expect(store.orderedLists[tagId]).toEqual(rooms); - }); - - it("sets the sticky room on the basis of the viewed room in RoomViewStore", async () => { - await store.start(); - // seed the store with 3 rooms - const roomIdA = "!a:localhost"; - const roomIdB = "!b:localhost"; - const roomIdC = "!c:localhost"; - const tagId = DefaultTagID.Favourite; - const joinCount = 10; - const roomIndexToRoomId = { - // mixed to ensure we sort - 1: roomIdB, - 2: roomIdC, - 0: roomIdA, - }; - const roomA = new Room(roomIdA, context.client!, context.client!.getUserId()!); - const roomB = new Room(roomIdB, context.client!, context.client!.getUserId()!); - const roomC = new Room(roomIdC, context.client!, context.client!.getUserId()!); - mocked(context.client!.getRoom).mockImplementation((roomId: string) => { - switch (roomId) { - case roomIdA: - return roomA; - case roomIdB: - return roomB; - case roomIdC: - return roomC; - } - return null; - }); - mocked(context._SlidingSyncManager!.slidingSync!.getListData).mockImplementation((key: string) => { - if (key !== tagId) { - return null; - } - return { - roomIndexToRoomId: roomIndexToRoomId, - joinedCount: joinCount, - }; - }); - let p = untilEmission(store, LISTS_UPDATE_EVENT); - context.slidingSyncManager.slidingSync!.emit(SlidingSyncEvent.List, tagId, joinCount, roomIndexToRoomId); - await p; - expect(store.orderedLists[tagId]).toEqual([roomA, roomB, roomC]); - - // make roomB sticky and inform the store - mocked(context.roomViewStore.getRoomId).mockReturnValue(roomIdB); - context.roomViewStore.emit(UPDATE_EVENT); - - // bump room C to the top, room B should not move from i=1 despite the list update saying to - roomIndexToRoomId[0] = roomIdC; - roomIndexToRoomId[1] = roomIdA; - roomIndexToRoomId[2] = roomIdB; - p = untilEmission(store, LISTS_UPDATE_EVENT); - context.slidingSyncManager.slidingSync!.emit(SlidingSyncEvent.List, tagId, joinCount, roomIndexToRoomId); - await p; - - // check that B didn't move and that A was put below B - expect(store.orderedLists[tagId]).toEqual([roomC, roomB, roomA]); - - // make room C sticky: rooms should move as a result, without needing an additional list update - mocked(context.roomViewStore.getRoomId).mockReturnValue(roomIdC); - p = untilEmission(store, LISTS_UPDATE_EVENT); - context.roomViewStore.emit(UPDATE_EVENT); - await p; - expect(store.orderedLists[tagId].map((r) => r.roomId)).toEqual([roomC, roomA, roomB].map((r) => r.roomId)); - }); - - it("gracefully handles unknown room IDs", async () => { - await store.start(); - const roomIdA = "!a:localhost"; - const roomIdB = "!b:localhost"; // does not exist - const roomIdC = "!c:localhost"; - const roomIndexToRoomId = { - 0: roomIdA, - 1: roomIdB, // does not exist - 2: roomIdC, - }; - const tagId = DefaultTagID.Favourite; - const joinCount = 10; - // seed the store with 2 rooms - const roomA = new Room(roomIdA, context.client!, context.client!.getUserId()!); - const roomC = new Room(roomIdC, context.client!, context.client!.getUserId()!); - mocked(context.client!.getRoom).mockImplementation((roomId: string) => { - switch (roomId) { - case roomIdA: - return roomA; - case roomIdC: - return roomC; - } - return null; - }); - mocked(context._SlidingSyncManager!.slidingSync!.getListData).mockImplementation((key: string) => { - if (key !== tagId) { - return null; - } - return { - roomIndexToRoomId: roomIndexToRoomId, - joinedCount: joinCount, - }; - }); - const p = untilEmission(store, LISTS_UPDATE_EVENT); - context.slidingSyncManager.slidingSync!.emit(SlidingSyncEvent.List, tagId, joinCount, roomIndexToRoomId); - await p; - expect(store.orderedLists[tagId]).toEqual([roomA, roomC]); - }); -}); From 4d97af0baf1a4fb2b89a8689b54f569b883b0148 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 18:07:41 +0000 Subject: [PATCH 112/458] Update dependency caniuse-lite to v1.0.30001704 (#29526) * Update dependency caniuse-lite to v1.0.30001704 * Update tests Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --- package.json | 2 +- test/unit-tests/SupportedBrowser-test.ts | 4 ++-- yarn.lock | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index a62686b89d..65adce904d 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ "@types/react-dom": "18.3.5", "oidc-client-ts": "3.1.0", "jwt-decode": "4.0.0", - "caniuse-lite": "1.0.30001701", + "caniuse-lite": "1.0.30001704", "testcontainers": "10.21.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0", "wrap-ansi": "npm:wrap-ansi@^7.0.0" diff --git a/test/unit-tests/SupportedBrowser-test.ts b/test/unit-tests/SupportedBrowser-test.ts index 2da2016392..3769798d46 100644 --- a/test/unit-tests/SupportedBrowser-test.ts +++ b/test/unit-tests/SupportedBrowser-test.ts @@ -68,9 +68,9 @@ describe("SupportedBrowser", () => { // Latest Firefox on macOS Sonoma "Mozilla/5.0 (Macintosh; Intel Mac OS X 14.7; rv:135.0) Gecko/20100101 Firefox/135.0", // Latest Edge on Windows - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/131.0.2903.86", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/134.0.3124.72", // Latest Edge on macOS - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/131.0.2903.86", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/134.0.3124.72", // Latest Firefox on Windows "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:135.0) Gecko/20100101 Firefox/135.0", // Latest Firefox on Linux diff --git a/yarn.lock b/yarn.lock index 390c172af9..172b151347 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4653,10 +4653,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@1.0.30001701, caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001646, caniuse-lite@^1.0.30001688: - version "1.0.30001701" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001701.tgz#ad9c90301f7153cf6b3314d16cc30757285bf9e7" - integrity sha512-faRs/AW3jA9nTwmJBSO1PQ6L/EOgsB5HMQQq4iCu5zhPgVVgO/pZRHlmatwijZKetFw8/Pr4q6dEN8sJuq8qTw== +caniuse-lite@1.0.30001704, caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001646, caniuse-lite@^1.0.30001688: + version "1.0.30001704" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001704.tgz#6644fe909d924ac3a7125e8a0ab6af95b1f32990" + integrity sha512-+L2IgBbV6gXB4ETf0keSvLr7JUrRVbIaB/lrQ1+z8mRcQiisG5k+lG6O4n6Y5q6f5EuNfaYXKgymucphlEXQew== chalk@5.2.0: version "5.2.0" From 98470b804580c4e4bffc452efa2e4222feed83f3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 18:08:06 +0000 Subject: [PATCH 113/458] Update all non-major dependencies (#29533) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 4 +- yarn.lock | 113 ++++++++++++++++++++++++--------------------------- 2 files changed, 56 insertions(+), 61 deletions(-) diff --git a/package.json b/package.json index 65adce904d..cc4e06fdd1 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "@playwright/test": "1.51.0", "@types/react": "18.3.18", "@types/react-dom": "18.3.5", - "oidc-client-ts": "3.1.0", + "oidc-client-ts": "3.2.0", "jwt-decode": "4.0.0", "caniuse-lite": "1.0.30001704", "testcontainers": "10.21.0", @@ -274,7 +274,7 @@ "postcss-preset-env": "^10.0.0", "postcss-scss": "^4.0.4", "postcss-simple-vars": "^7.0.1", - "prettier": "3.5.2", + "prettier": "3.5.3", "process": "^0.11.10", "raw-loader": "^4.0.2", "rimraf": "^6.0.0", diff --git a/yarn.lock b/yarn.lock index 172b151347..23e8cd8ce1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2527,10 +2527,10 @@ "@sentry-internal/browser-utils" "9.6.0" "@sentry/core" "9.6.0" -"@sentry/babel-plugin-component-annotate@3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-3.2.1.tgz#90e40750a63ef5ce3d67498ed0cfccc587ab4cd8" - integrity sha512-tUp2e+CERpRFzTftjPxt7lg4BF0R3K+wGfeJyIqrc0tbJ2y6duT8OD0ArWoOi1g8xQ73NDn1/mEeS8pC+sbjTQ== +"@sentry/babel-plugin-component-annotate@3.2.2": + version "3.2.2" + resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-3.2.2.tgz#0c5f26e417b8f524924fa4531b82ad5603216e90" + integrity sha512-D+SKQ266ra/wo87s9+UI/rKQi3qhGPCR8eSCDe0VJudhjHsqyNU+JJ5lnIGCgmZaWFTXgdBP/gdr1Iz1zqGs4Q== "@sentry/browser@^9.0.0": version "9.6.0" @@ -2543,13 +2543,13 @@ "@sentry-internal/replay-canvas" "9.6.0" "@sentry/core" "9.6.0" -"@sentry/bundler-plugin-core@3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@sentry/bundler-plugin-core/-/bundler-plugin-core-3.2.1.tgz#9c1c8b9acaca3ae5eeae2a04529f70212dd2937e" - integrity sha512-1wId05LXf6LyTeNwqyhSDSWYbYtFT/NQRqq3sW7hcL4nZuAgzT82PSvxeeCgR/D2qXOj7RCYXXZtyWzzo3wtXA== +"@sentry/bundler-plugin-core@3.2.2": + version "3.2.2" + resolved "https://registry.yarnpkg.com/@sentry/bundler-plugin-core/-/bundler-plugin-core-3.2.2.tgz#c9193b0c97acf0097fdb820d86eaaad9c9b6b2c4" + integrity sha512-YGrtmqQ2jMixccX2slVG/Lw7pCGJL3DGB3clmY9mO8QBEBIN3/gEANiHJVWwRidpUOS/0b7yVVGAdwZ87oPwTg== dependencies: "@babel/core" "^7.18.5" - "@sentry/babel-plugin-component-annotate" "3.2.1" + "@sentry/babel-plugin-component-annotate" "3.2.2" "@sentry/cli" "2.42.2" dotenv "^16.3.1" find-up "^5.0.0" @@ -2617,11 +2617,11 @@ integrity sha512-t51h6HKlPYW3TfeM09mZ6uDd95A7lgYpD5lUV54ilBA3TefS+M9I32MKwAW7yHzzWs0WQxOdm56eoDBOmRDpHQ== "@sentry/webpack-plugin@^3.0.0": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-3.2.1.tgz#83756c64c59a2be39e05beda30b08753f7b80780" - integrity sha512-wP/JDljhB9pCFc62rSwWbIglF2Os8FLV68pQuyJnmImM9cjGjlK6UO+qKa2pOLYsmAcnn+t3Bhu77bbzPIStCg== + version "3.2.2" + resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-3.2.2.tgz#716ab462279c25cea17490d02cb1d22b00f3f661" + integrity sha512-6OkVKNOjKk8P9j7oh6svZ+kEP1i9YIHBC2aGWL2XsgeZTIrMBxJAXtOf+qSrfMAxEtibSroGVOMQc/y3WJTQtg== dependencies: - "@sentry/bundler-plugin-core" "3.2.1" + "@sentry/bundler-plugin-core" "3.2.2" unplugin "1.0.1" uuid "^9.0.0" @@ -3830,12 +3830,12 @@ acorn@^8.0.4, acorn@^8.1.0, acorn@^8.11.0, acorn@^8.9.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.13.0.tgz#2a30d670818ad16ddd6a35d3842dacec9e5d7ca3" integrity sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w== -acorn@^8.14.0, acorn@^8.8.1, acorn@^8.8.2: +acorn@^8.14.0: version "8.14.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== -acorn@^8.4.1: +acorn@^8.4.1, acorn@^8.8.1, acorn@^8.8.2: version "8.14.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb" integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== @@ -5018,9 +5018,9 @@ core-js-compat@^3.40.0: browserslist "^4.24.4" core-js@^3.0.0, core-js@^3.38.1: - version "3.40.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.40.0.tgz#2773f6b06877d8eda102fc42f828176437062476" - integrity sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ== + version "3.41.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.41.0.tgz#57714dafb8c751a6095d028a7428f1fb5834a776" + integrity sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA== core-util-is@~1.0.0: version "1.0.3" @@ -5173,14 +5173,14 @@ css-loader@^7.0.0: semver "^7.5.4" css-minimizer-webpack-plugin@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-7.0.0.tgz#b77a3d2f7c0fd02d3ac250dcc2f79065363f3cd3" - integrity sha512-niy66jxsQHqO+EYbhPuIhqRQ1mNcNVUHrMnkzzir9kFOERJUaQDDRhh7dKDz33kBpkWMF9M8Vx0QlDbc5AHOsw== + version "7.0.2" + resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-7.0.2.tgz#aa1b01c6033f5b2f86ddb60c1f5bddd012b50cac" + integrity sha512-nBRWZtI77PBZQgcXMNqiIXVshiQOVLGSf2qX/WZfG8IQfMbeHUMXaBWQmiiSTmPJUflQxHjZjzAmuyO7tpL2Jg== dependencies: "@jridgewell/trace-mapping" "^0.3.25" - cssnano "^7.0.1" + cssnano "^7.0.4" jest-worker "^29.7.0" - postcss "^8.4.38" + postcss "^8.4.40" schema-utils "^4.2.0" serialize-javascript "^6.0.2" @@ -5301,7 +5301,7 @@ cssnano-utils@^5.0.0: resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-5.0.0.tgz#b53a0343dd5d21012911882db6ae7d2eae0e3687" integrity sha512-Uij0Xdxc24L6SirFr25MlwC2rCFX6scyUmuKpzI+JQ7cyqDEwD42fJ0xfB3yLfOnRDU5LKGgjQ9FA6LYh76GWQ== -cssnano@^7.0.1: +cssnano@^7.0.4: version "7.0.6" resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-7.0.6.tgz#63d54fd42bc017f6aaed69e47d9aaef85b7850ec" integrity sha512-54woqx8SCbp8HwvNZYn68ZFAepuouZW4lTwiMVnBErM3VkO7/Sd4oTOt3Zz3bPx3kxQ36aISppyXj2Md4lg8bw== @@ -5693,9 +5693,9 @@ domutils@^2.5.2, domutils@^2.8.0: domhandler "^4.2.0" domutils@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" - integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== + version "3.2.2" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.2.2.tgz#edbfe2b668b0c1d97c24baf0f1062b132221bc78" + integrity sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw== dependencies: dom-serializer "^2.0.0" domelementtype "^2.3.0" @@ -6035,9 +6035,9 @@ eslint-config-google@^0.14.0: integrity sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw== eslint-config-prettier@^10.0.0: - version "10.0.2" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-10.0.2.tgz#47444de8aa104ce82c2f91ad2a5e96b62c01e20d" - integrity sha512-1105/17ZIMjmCOJOPNfVdbXafLCLj3hPmkmB7dLgt7XsQ/zkxSuDerE/xgO3RxoHysR1N1whmquY0lSn2O0VLg== + version "10.1.1" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-10.1.1.tgz#cf0ff6e5c4e7e15f129f1f1ce2a5ecba92dec132" + integrity sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw== eslint-import-resolver-node@^0.3.9: version "0.3.9" @@ -8426,9 +8426,9 @@ kleur@^3.0.3: integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== knip@^5.36.2: - version "5.45.0" - resolved "https://registry.yarnpkg.com/knip/-/knip-5.45.0.tgz#18eda62ffca7ec9cbee7732470b8415ae29e2d8f" - integrity sha512-OUyO9FUEVCM6/j0gl+PP/LDeJEs4hIdE8n4vK4xrtjN1g3Qu4Ws1oexbWTCJ+8xt8Tgse4Yvhx96OqF/UVl3Ug== + version "5.46.0" + resolved "https://registry.yarnpkg.com/knip/-/knip-5.46.0.tgz#8444881f9382901b4022775ba99e2df4de1df991" + integrity sha512-WedHSK5xNBWYgm64Rt5B9b0CVXL2kRBcyCeet3NHgdv9en3QE4AWSDPEiX48NoPUBW3h//9S0VwLF5MG/MPi3g== dependencies: "@nodelib/fs.walk" "3.0.1" "@snyk/github-codeowners" "1.1.0" @@ -8499,12 +8499,7 @@ lie@~3.3.0: dependencies: immediate "~3.0.5" -lilconfig@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.2.tgz#e4a7c3cb549e3a606c8dcc32e5ae1005e62c05cb" - integrity sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow== - -lilconfig@^3.1.3: +lilconfig@^3.1.2, lilconfig@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.3.tgz#a1bcfd6257f9585bf5ae14ceeebb7b559025e4c4" integrity sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw== @@ -8542,9 +8537,9 @@ linkifyjs@4.2.0: integrity sha512-pCj3PrQyATaoTYKHrgWRF3SJwsm61udVh+vuls/Rl6SptiDhgE7ziUIudAedRY9QEfynmM7/RmLEfPUyw1HPCw== lint-staged@^15.0.2: - version "15.4.3" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-15.4.3.tgz#e73587cc857f580c99f907abefe9ac8d8d5e74c1" - integrity sha512-FoH1vOeouNh1pw+90S+cnuoFwRfUD9ijY2GKy5h7HS3OR7JVir2N2xrsa0+Twc1B7cW72L+88geG5cW4wIhn7g== + version "15.5.0" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-15.5.0.tgz#fa6464cfb06e0faf5bb167f83186e952ff6e569e" + integrity sha512-WyCzSbfYGhK7cU+UuDDkzUiytbfbi0ZdPy2orwtM75P3WTtQBzmG40cCxIa8Ii2+XjfxzLH6Be46tUfWS85Xfg== dependencies: chalk "^5.4.1" commander "^13.1.0" @@ -9282,10 +9277,10 @@ obuf@^1.0.0, obuf@^1.1.2: resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== -oidc-client-ts@3.1.0, oidc-client-ts@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/oidc-client-ts/-/oidc-client-ts-3.1.0.tgz#28d3254951a1c64cc9780042c61492a71b2240dd" - integrity sha512-IDopEXjiwjkmJLYZo6BTlvwOtnlSniWZkKZoXforC/oLZHC9wkIxd25Kwtmo5yKFMMVcsp3JY6bhcNJqdYk8+g== +oidc-client-ts@3.2.0, oidc-client-ts@^3.0.1: + version "3.2.0" + resolved "https://registry.yarnpkg.com/oidc-client-ts/-/oidc-client-ts-3.2.0.tgz#37e6e563bfeabc4aa1497a9a963f8e3d73168316" + integrity sha512-wUvVcG3SXzZDKHxi/VGQGaTUk9qguMKfYh26Y1zOVrQsu1zp85JWx/SjZzKSXK5j3NA1RcasgMoaHe6gt1WNtw== dependencies: jwt-decode "^4.0.0" @@ -9647,11 +9642,11 @@ postcss-attribute-case-insensitive@^7.0.1: postcss-selector-parser "^7.0.0" postcss-calc@^10.0.2: - version "10.0.2" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-10.0.2.tgz#15f01635a27b9d38913a98c4ef2877f5b715b439" - integrity sha512-DT/Wwm6fCKgpYVI7ZEWuPJ4az8hiEHtCUeYjZXqU7Ou4QqYh1Df2yCQ7Ca6N7xqKPFkxN3fhf+u9KSoOCJNAjg== + version "10.1.1" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-10.1.1.tgz#52b385f2e628239686eb6e3a16207a43f36064ca" + integrity sha512-NYEsLHh8DgG/PRH2+G9BTuUdtf9ViS+vdoQ0YA5OQdGsfN4ztiwtDWNtBl9EKeqNMFnIu8IKZ0cLxEQ5r5KVMw== dependencies: - postcss-selector-parser "^6.1.2" + postcss-selector-parser "^7.0.0" postcss-value-parser "^4.2.0" postcss-clamp@^4.1.0: @@ -10244,7 +10239,7 @@ postcss@8.4.46: picocolors "^1.1.0" source-map-js "^1.2.1" -postcss@^8.3.11, postcss@^8.4.33, postcss@^8.4.38: +postcss@^8.3.11, postcss@^8.4.33: version "8.4.47" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.47.tgz#5bf6c9a010f3e724c503bf03ef7947dcb0fea365" integrity sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ== @@ -10253,7 +10248,7 @@ postcss@^8.3.11, postcss@^8.4.33, postcss@^8.4.38: picocolors "^1.1.0" source-map-js "^1.2.1" -postcss@^8.5.3: +postcss@^8.4.40, postcss@^8.5.3: version "8.5.3" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.3.tgz#1463b6f1c7fb16fe258736cba29a2de35237eafb" integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A== @@ -10286,10 +10281,10 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prettier@3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.5.2.tgz#d066c6053200da0234bf8fa1ef45168abed8b914" - integrity sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg== +prettier@3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.5.3.tgz#4fc2ce0d657e7a02e602549f053b239cb7dfe1b5" + integrity sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw== prettier@^2.6.2: version "2.8.8" @@ -11951,9 +11946,9 @@ temporal-spec@^0.2.4: integrity sha512-lDMFv4nKQrSjlkHKAlHVqKrBG4DyFfa9F74cmBZ3Iy3ed8yvWnlWSIdi4IKfSqwmazAohBNwiN64qGx4y5Q3IQ== terser-webpack-plugin@^5.3.11, terser-webpack-plugin@^5.3.9: - version "5.3.12" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.12.tgz#d9518c80493081bace668aa8613b22e4a838810c" - integrity sha512-jDLYqo7oF8tJIttjXO6jBY5Hk8p3A8W4ttih7cCEq64fQFWmgJ4VqAQjKr7WwIDlmXKEc6QeoRb5ecjZ+2afcg== + version "5.3.14" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz#9031d48e57ab27567f02ace85c7d690db66c3e06" + integrity sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw== dependencies: "@jridgewell/trace-mapping" "^0.3.25" jest-worker "^27.4.5" From d2c334dd250755c5475534121ba1546289add425 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Wed, 19 Mar 2025 06:16:03 +0000 Subject: [PATCH 114/458] [create-pull-request] automated change (#29540) Co-authored-by: t3chguy <2403652+t3chguy@users.noreply.github.com> --- playwright/testcontainers/synapse.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright/testcontainers/synapse.ts b/playwright/testcontainers/synapse.ts index f9ea2cd1c7..c7c9a96d23 100644 --- a/playwright/testcontainers/synapse.ts +++ b/playwright/testcontainers/synapse.ts @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. import { SynapseContainer as BaseSynapseContainer } from "@element-hq/element-web-playwright-common/lib/testcontainers"; -const TAG = "develop@sha256:65a8084668f7b468310cf4e1f29ac6987439ab3f4cb5608d6e02ef0acb819b67"; +const TAG = "develop@sha256:ab201cdfc4d8ddae71d7157132aa1da6e479b9247aafeaab310c9a8af1de6a44"; /** * SynapseContainer which freezes the docker digest to stabilise tests, From 35aed69604aa3df44ee77418b4a97fa2553f4ca5 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Wed, 19 Mar 2025 06:20:49 +0000 Subject: [PATCH 115/458] [create-pull-request] automated change (#29541) Co-authored-by: t3chguy <2403652+t3chguy@users.noreply.github.com> --- src/i18n/strings/cy.json | 24 +++++++++++++ src/i18n/strings/fr.json | 23 +++++++++++++ src/i18n/strings/nb_NO.json | 21 +++++++++++ src/i18n/strings/pl.json | 69 ++++++++++++++++++++++++++++++++++++- src/i18n/strings/uk.json | 27 ++++++++++++++- 5 files changed, 162 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/cy.json b/src/i18n/strings/cy.json index a5614f8cd5..4cfd2a8921 100644 --- a/src/i18n/strings/cy.json +++ b/src/i18n/strings/cy.json @@ -447,6 +447,7 @@ "access_token": "Tocyn Mynediad", "accessibility": "Hygyrchedd", "advanced": "Uwch", + "all_chats": "Pob Sgwrs", "analytics": "Dadansoddi Gwe", "appearance": "Gwedd", "application": "Rhaglen", @@ -1983,6 +1984,19 @@ "add_space_label": "Ychwanegu gofod", "breadcrumbs_empty": "Dim ystafelloedd yr ymwelwyd â nhw yn ddiweddar", "breadcrumbs_label": "Ymwelwyd ag ystafelloedd yn ddiweddar", + "empty": { + "no_chats": "Dim sgyrsiau eto", + "no_chats_description": "Dechreuwch drwy anfon neges at rywun neu drwy greu ystafell", + "no_chats_description_no_room_rights": "Dechreuwch trwy anfon neges at rywun", + "no_favourites": "Nid oes gennych hoff sgwrs eto", + "no_favourites_description": "Gallwch ychwanegu sgwrs at eich ffefrynnau yn y gosodiadau sgwrsio", + "no_people": "Nid oes gennych chi sgyrsiau uniongyrchol gydag unrhyw un eto", + "no_people_description": "Gallwch ddad-ddewis hidlwyr er mwyn gweld eich sgyrsiau eraill", + "no_rooms": "Nid ydych mewn unrhyw ystafell eto", + "no_rooms_description": "Gallwch ddad-ddewis hidlwyr er mwyn gweld eich sgyrsiau eraill", + "no_unread": "Llongyfarchiadau! Nid oes gennych unrhyw negeseuon heb eu darllen", + "show_chats": "Dangos pob sgwrs" + }, "failed_add_tag": "Wedi methu ag ychwanegu tag %(tagName)s i'r ystafell", "failed_remove_tag": "Wedi methu â thynnu'r tag %(tagName)s o'r ystafell", "failed_set_dm_tag": "Wedi methu gosod tag neges uniongyrchol", @@ -1995,10 +2009,19 @@ "home_menu_label": "Dewisiadau cartref", "join_public_room_label": "Ymuno â'r ystafell gyhoeddus", "list_title": "Rhestr ystafelloedd", + "more_options": { + "copy_link": "Copïo dolen ystafell", + "favourited": "Ffafrio", + "leave_room": "Gadael yr ystafell", + "low_priority": "Blaenoriaeth isel", + "mark_read": "Marcio fel wedi'i ddarllen", + "mark_unread": "Marcio fel heb ei ddarllen" + }, "notification_options": "Dewisiadau hysbysu", "open_space_menu": "Agor dewislen gofod", "primary_filters": "Hidlau rhestr ystafelloedd", "room": { + "more_options": "Rhagor o Ddewisiadau", "open_room": "Agor ystafell %(roomName)s" }, "show_less": "Dangos llai", @@ -2502,6 +2525,7 @@ "inline_url_previews_room": "Galluogi rhagolygon URL fel rhagosodiad ar gyfer cyfranogwyr yn yr ystafell hon", "inline_url_previews_room_account": "Galluogi rhagolygon URL ar gyfer yr ystafell hon (yn effeithio arnoch chi yn unig)", "insert_trailing_colon_mentions": "Mewnosod colon sy'n llusgo ar ôl i'r defnyddiwr sôn amdano ar ddechrau neges", + "invite_avatars": "Dangos afatarau ystafelloedd y cawsoch eich gwahodd iddynn nhw", "jump_to_bottom_on_send": "Neidio i waelod y llinell amser pan fyddwch chi'n anfon neges", "key_backup": { "backup_in_progress": "Mae copi wrth gefn o'ch allweddi (gallai'r copi wrth gefn cyntaf gymryd ychydig funudau).", diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index f4edcccf82..bfd2e2608e 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -64,6 +64,7 @@ "go": "C’est parti", "go_back": "Revenir en arrière", "got_it": "Compris", + "hide": "Masquer", "hide_advanced": "Masquer les paramètres avancés", "hold": "Mettre en pause", "ignore": "Ignorer", @@ -2095,6 +2096,19 @@ "add_space_label": "Ajouter un espace", "breadcrumbs_empty": "Aucun salon visité récemment", "breadcrumbs_label": "Salons visités récemment", + "empty": { + "no_chats": "Pas encore de discussions", + "no_chats_description": "Commencez par envoyer un message à quelqu'un ou en créant un salon", + "no_chats_description_no_room_rights": "Commencez par envoyer un message à quelqu'un", + "no_favourites": "Vous n'avez pas encore de discussion favorite", + "no_favourites_description": "Vous pouvez ajouter une discussion à vos favoris dans les paramètres de discussion", + "no_people": "Vous n'avez encore de discussions", + "no_people_description": "Veuillez désélectionner des filtres pour voir vos discussions", + "no_rooms": "Vous n’êtes membre d’aucun salon", + "no_rooms_description": "Veuillez désélectionner des filtres pour voir vos discussions", + "no_unread": "Félicitations ! Vous n'avez aucun message non lu", + "show_chats": "Afficher toutes les discussions" + }, "failed_add_tag": "Échec de l’ajout de l’étiquette %(tagName)s au salon", "failed_remove_tag": "Échec de la suppression de l’étiquette %(tagName)s du salon", "failed_set_dm_tag": "Échec de l’ajout de l’étiquette de conversation privée", @@ -2111,6 +2125,14 @@ "other": "Vous êtes en train de rejoindre %(count)s salons" }, "list_title": "Liste de salons", + "more_options": { + "copy_link": "Copier le lien du salon", + "favourited": "Favorisé", + "leave_room": "Quitter le salon", + "low_priority": "Priorité basse", + "mark_read": "Marquer comme lu", + "mark_unread": "Marquer comme non lu" + }, "notification_options": "Paramètres de notifications", "open_space_menu": "Ouvrir le menu de l’espace", "primary_filters": "Filtre de la liste des salons", @@ -2119,6 +2141,7 @@ "other": "Actuellement en train de supprimer les messages dans %(count)s salons" }, "room": { + "more_options": "Plus d’options", "open_room": "Ouvrir salon %(roomName)s" }, "show_less": "En voir moins", diff --git a/src/i18n/strings/nb_NO.json b/src/i18n/strings/nb_NO.json index d609580baa..cdf5f0a620 100644 --- a/src/i18n/strings/nb_NO.json +++ b/src/i18n/strings/nb_NO.json @@ -64,6 +64,7 @@ "go": "Gå", "go_back": "Gå tilbake", "got_it": "Jeg forstår", + "hide": "Skjul", "hide_advanced": "Skjul avansert", "hold": "Hold", "ignore": "Ignorer", @@ -455,6 +456,7 @@ "access_token": "Tilgangstoken", "accessibility": "Tilgjengelighet", "advanced": "Avansert", + "all_chats": "Alle chatter", "analytics": "Statistikk", "and_n_others": { "og %(count)s andre …": "other", @@ -2095,6 +2097,16 @@ "add_space_label": "Legg til område", "breadcrumbs_empty": "Ingen nylig besøkte rom", "breadcrumbs_label": "Nylig besøkte rom", + "empty": { + "no_chats": "Ingen chatter ennå", + "no_chats_description": "Kom i gang ved å sende meldinger til noen eller ved å opprette et rom", + "no_chats_description_no_room_rights": "Kom i gang med å sende meldinger til noen", + "no_favourites_description": "Du kan legge til en chat til dine favoritter i chat-innstillingene", + "no_people": "Du har ikke direkte chatter med noen ennå", + "no_rooms": "Du er ikke med i noen rom ennå", + "no_unread": "Gratulerer! Du har ingen uleste meldinger", + "show_chats": "Vis alle chatter" + }, "failed_add_tag": "Kunne ikke legge til tagg %(tagName)s til rom", "failed_remove_tag": "Kunne ikke fjerne tagg %(tagName)s fra rommet", "failed_set_dm_tag": "Kan ikke sette kode på direktemeldingen", @@ -2111,6 +2123,14 @@ "other": "Blir for øyeblikket med i %(count)s rom" }, "list_title": "Romliste", + "more_options": { + "copy_link": "Kopier romlenke", + "favourited": "Favorittmerket", + "leave_room": "Forlat rommet", + "low_priority": "Lav prioritet", + "mark_read": "Marker som lest", + "mark_unread": "Marker som ulest" + }, "notification_options": "Varselsinnstillinger", "open_space_menu": "Åpne Område-meny", "primary_filters": "Filtre for romliste", @@ -2119,6 +2139,7 @@ "other": "Fjerner for øyeblikket meldinger i %(count)s rom" }, "room": { + "more_options": "Flere alternativer", "open_room": "Åpne rom %(roomName)s" }, "show_less": "Vis mindre", diff --git a/src/i18n/strings/pl.json b/src/i18n/strings/pl.json index 2f96ced9e5..249902cc70 100644 --- a/src/i18n/strings/pl.json +++ b/src/i18n/strings/pl.json @@ -64,6 +64,7 @@ "go": "Przejdź", "go_back": "Wróć", "got_it": "Rozumiem", + "hide": "Ukryj", "hide_advanced": "Ukryj zaawansowane", "hold": "Wstrzymaj", "ignore": "Ignoruj", @@ -407,6 +408,15 @@ "download_logs": "Pobierz dzienniki", "downloading_logs": "Pobieranie logów", "error_empty": "Powiedz nam, co poszło nie tak, lub nawet lepiej - utwórz zgłoszenie na platformie GitHub, które opisuje problem.", + "failed_download_logs": "Nie udało się pobrać dzienników debugowania: ", + "failed_send_logs_causes": { + "disallowed_app": "Twój raport o błędzie został odrzucony. Serwer gniewnego potrząśnięcia nie obsługuje tej aplikacji.", + "rejected_generic": "Twój raport o błędzie został odrzucony. Serwer gniewnego potrząśnięcia odrzucił zawartość zgłoszenia ze względu na jej politykę.", + "rejected_recovery_key": "Twój raport o błędzie został odrzucony ze względów bezpieczeństwa, ponieważ zawierał on klucz przywracania.", + "rejected_version": "Twój raport o błędzie został odrzucony, ponieważ wersja aplikacji jest zbyt stara.", + "server_unknown_error": "Serwer gniewnego potrząśnięcia napotkał nieznany błąd i nie mógł obsłużyć raportu.", + "unknown_error": "Nie udało się wysłać logów." + }, "github_issue": "Zgłoszenie GitHub", "introduction": "Jeśli zgłosiłeś błąd za pomocą serwisu GitHub, dzienniki debugowania mogą pomóc nam w namierzeniu problemu. ", "log_request": "Aby uniknąć tego problemu w przyszłości, wyślij nam dzienniki.", @@ -446,6 +456,7 @@ "access_token": "Token dostępu", "accessibility": "Ułatwienia dostępu", "advanced": "Zaawansowane", + "all_chats": "Wszystkie czaty", "analytics": "Analityka", "and_n_others": { "one": "i jeden inny...", @@ -1305,6 +1316,7 @@ "error_connecting_heading": "Nie udało się połączyć z menedżerem integracji", "explainer": "Zarządcy integracji otrzymują dane konfiguracji, mogą modyfikować widżety, wysyłać zaproszenia do pokojów i ustawiać poziom uprawnień w Twoim imieniu.", "manage_title": "Zarządzaj integracjami", + "toggle_label": "Włącz menedżer integracji", "use_im": "Użyj zarządcy integracji aby zarządzać botami, widżetami i pakietami naklejek.", "use_im_default": "Użyj zarządcy Integracji %(serverName)s aby zarządzać botami, widżetami i pakietami naklejek." }, @@ -2098,20 +2110,54 @@ "add_space_label": "Dodaj przestrzeń", "breadcrumbs_empty": "Brak ostatnio odwiedzonych pokojów", "breadcrumbs_label": "Ostatnio odwiedzane pokoje", + "empty": { + "no_chats": "Nie ma jeszcze czatów", + "no_chats_description": "Zacznij od wysłania wiadomości lub utworzenia pokoju", + "no_chats_description_no_room_rights": "Wyślij komuś wiadomość, aby rozpocząć.", + "no_favourites": "Nie masz jeszcze ulubionego czatu", + "no_favourites_description": "Dodaj czat do ulubionych w ustawieniach czatu", + "no_people": "Nie prowadzisz jeszcze z nikim czatów prywatnych", + "no_people_description": "Wyczyść filtry, aby zobaczyć pozostałe czaty", + "no_rooms": "Nie jesteś jeszcze w żadnym pokoju", + "no_rooms_description": "Wyczyść filtry, aby zobaczyć pozostałe czaty", + "no_unread": "Brawo! Nie masz żadnych nieprzeczytanych wiadomości", + "show_chats": "Pokaż wszystkie czaty" + }, "failed_add_tag": "Nie można dodać tagu %(tagName)s do pokoju", "failed_remove_tag": "Nie udało się usunąć tagu %(tagName)s z pokoju", "failed_set_dm_tag": "Nie udało się ustawić tagu wiadomości prywatnych", + "filters": { + "favourite": "Ulubione", + "people": "Osoby", + "rooms": "Pokoje", + "unread": "Nieprzeczytane" + }, "home_menu_label": "Opcje głównej", "join_public_room_label": "Dołącz do publicznego pokoju", "joining_rooms_status": { "one": "Aktualnie dołączanie do %(count)s pokoju", "other": "Aktualnie dołączanie do %(count)s pokoi" }, + "list_title": "Lista pokoi", + "more_options": { + "copy_link": "Kopiuj link pokoju", + "favourited": "Ulubiony", + "leave_room": "Opuść pokój", + "low_priority": "Niski priorytet", + "mark_read": "Oznacz jako przeczytane", + "mark_unread": "Oznacz jako nieprzeczytane" + }, "notification_options": "Opcje powiadomień", + "open_space_menu": "Otwórz menu przestrzeni", + "primary_filters": "Filtry listy pokoi", "redacting_messages_status": { "one": "Aktualnie usuwanie wiadomości z %(count)s pokoju", "other": "Aktualnie usuwanie wiadomości z %(count)s pokoi" }, + "room": { + "more_options": "Więcej opcji", + "open_room": "Pokój otwarty %(roomName)s" + }, "show_less": "Pokaż mniej", "show_n_more": { "one": "Pokaż %(count)s więcej", @@ -2123,6 +2169,10 @@ "sort_by_activity": "Aktywności", "sort_by_alphabet": "A-Z", "sort_unread_first": "Pokazuj najpierw pokoje z nieprzeczytanymi wiadomościami", + "space_menu": { + "home": "Główna przestrzeni", + "space_settings": "Ustawienia przestrzeni" + }, "space_menu_label": "menu %(spaceName)s", "sublist_options": "Ustawienia listy", "suggested_rooms_heading": "Sugerowane pokoje" @@ -2485,20 +2535,35 @@ "breadcrumb_title_forgot": "Nie pamiętasz klucza przywracania? Musisz zresetować swoją tożsamość.", "breadcrumb_warning": "Zrób to tylko wtedy, gdy uważasz, że Twoje konto zostało naruszone.", "details_title": "Szczegóły szyfrowania", + "do_not_close_warning": "Nie zamykaj tego okna, dopóki reset nie zostanie zakończony", "export_keys": "Eksportuj klucze", "import_keys": "Importuj klucze", "other_people_device_description": "Domyślnie w pokojach szyfrowanych nie będziesz mógł wysyłać wiadomości, jeśli nie zweryfikujesz członków w pokoju", "other_people_device_label": "Nigdy nie wysyłaj wiadomości szyfrowanych do niezweryfikowanych urządzeń", "other_people_device_title": "Urządzenia innych osób", "reset_identity": "Zresetuj tożsamość kryptograficzną", + "reset_in_progress": "Resetowanie w toku...", "session_id": "ID sesji:", "session_key": "Klucz sesji:", "title": "Zaawansowane" }, + "delete_key_storage": { + "breadcrumb_page": "Usuń magazyn kluczy", + "confirm": "Usuń magazyn kluczy", + "description": "Usunięcie magazynu kluczy usunie Twoją tożsamość kryptograficzną, klucze wiadomości z serwera i wyłączy następujące funkcje bezpieczeństwa:", + "list_first": "Nowe urządzenia nie będą posiadały Twojej historii wiadomości szyfrowanych", + "list_second": "Utracisz dostęp do swoich wiadomości szyfrowanych, jeśli wylogujesz się wszędzie z %(brand)s", + "title": "Czy na pewno chcesz wyłączyć magazyn kluczy i go wyłączyć?" + }, "device_not_verified_button": "Zweryfikuj to urządzenie", "device_not_verified_description": "Aby wyświetlić ustawienia szyfrowania, musisz zweryfikować to urządzenie.", "device_not_verified_title": "Urządzenie niezweryfikowane", "dialog_title": "Ustawienia: Szyfrowanie", + "key_storage": { + "allow_key_storage": "Zezwól na magazynowanie kluczy", + "description": "Przechowuj swoją tożsamość kryptograficzną i klucze wiadomości bezpiecznie na serwerze. Umożliwi Ci to przeglądanie historii wiadomości na wszystkich nowych urządzeniach.Dowiedz się więcej", + "title": "Magazyn kluczy" + }, "recovery": { "change_recovery_confirm_button": "Potwierdź nowy klucz przywracania", "change_recovery_confirm_description": "Wprowadź poniżej nowy klucz przywracania, aby zakończyć. Stary klucz przestanie działać.", @@ -2615,6 +2680,7 @@ "inline_url_previews_room": "Włącz domyślny podgląd URL dla uczestników w tym pokoju", "inline_url_previews_room_account": "Włącz podgląd URL dla tego pokoju (dotyczy tylko Ciebie)", "insert_trailing_colon_mentions": "Wstawiaj dwukropek po wzmiance użytkownika na początku wiadomości", + "invite_avatars": "Pokaż awatary pokoi, do których zostałeś zaproszony", "jump_to_bottom_on_send": "Przejdź na dół osi czasu po wysłaniu wiadomości", "key_backup": { "backup_in_progress": "Tworzy się kopia zapasowa Twoich kluczy (pierwsza kopia może potrwać kilka minut).", @@ -3096,6 +3162,7 @@ "view": "Przegląda pokój z podanym adresem", "whois": "Pokazuje informacje na temat użytkownika" }, + "sliding_sync_legacy_no_longer_supported": "Starsza metoda synchronizacji sliding sync nie jest już obsługiwana: zaloguj się ponownie, aby włączyć nową flagę synchronizacji sliding sync", "space": { "add_existing_room_space": { "create": "Chcesz zamiast tego dodać nowy pokój?", @@ -4069,7 +4136,7 @@ "error_need_to_be_logged_in": "Musisz być zalogowany.", "error_unable_start_audio_stream_description": "Nie można rozpocząć przesyłania strumienia audio.", "error_unable_start_audio_stream_title": "Nie udało się rozpocząć transmisji na żywo", - "modal_data_warning": "Dane na tym ekranie są współdzielone z %(widgetDomain)s", + "modal_data_warning": "Poniższe dane są współdzielone z %(widgetDomain)s", "modal_title_default": "Widżet modalny", "no_name": "Nieznana aplikacja", "open_id_permissions_dialog": { diff --git a/src/i18n/strings/uk.json b/src/i18n/strings/uk.json index 3081cdd219..d882295447 100644 --- a/src/i18n/strings/uk.json +++ b/src/i18n/strings/uk.json @@ -455,6 +455,7 @@ "access_token": "Токен доступу", "accessibility": "Доступність", "advanced": "Подробиці", + "all_chats": "Усі бесіди", "analytics": "Аналітика", "and_n_others": { "one": "і інше...", @@ -2115,13 +2116,23 @@ "other": "Приєднання до %(count)s кімнат" }, "list_title": "Список кімнат", + "more_options": { + "copy_link": "Копіювати посилання на кімнату", + "favourited": "Обране", + "leave_room": "Вийти з кімнати", + "low_priority": "Неважливі", + "mark_read": "Позначити прочитаним", + "mark_unread": "Позначити непрочитаним" + }, "notification_options": "Параметри сповіщень", "open_space_menu": "Відкрити меню простору", + "primary_filters": "Фільтри списку кімнат", "redacting_messages_status": { "one": "Триває видалення повідомлень в %(count)s кімнаті", "other": "Триває видалення повідомлень у %(count)s кімнатах" }, "room": { + "more_options": "Інші опції", "open_room": "Відкрити кімнату %(roomName)s" }, "show_less": "Згорнути", @@ -2512,10 +2523,23 @@ "session_key": "Ключ сеансу:", "title": "Додатково" }, + "delete_key_storage": { + "breadcrumb_page": "Видалити сховище ключів", + "confirm": "Видалити сховище ключів", + "description": "Видалення сховища ключів вилучить вашу криптографічну ідентичність і ключі повідомлень з сервера, а також вимкне такі функції безпеки:", + "list_first": "Ви не матимете історії зашифрованих повідомлень на нових пристроях", + "list_second": "Ви втратите доступ до своїх зашифрованих повідомлень, якщо ви вийдете з %(brand)s на всіх пристроях", + "title": "Ви впевнені, що хочете вимкнути зберігання ключів і видалити їх?" + }, "device_not_verified_button": "Верифікувати цей пристрій", "device_not_verified_description": "Верифікуйте цей пристрій, щоб переглянути налаштування шифрування.", "device_not_verified_title": "Пристрій не верифіковано", "dialog_title": "Налаштування: Шифрування", + "key_storage": { + "allow_key_storage": "Дозволити зберігання ключів", + "description": "Надійно зберігайте свою криптографічну ідентичність і ключі повідомлень на сервері. Це дозволить вам переглядати історію повідомлень на будь-яких нових пристроях. Докладніше", + "title": "Сховище ключів" + }, "recovery": { "change_recovery_confirm_button": "Підтвердити новий ключ відновлення", "change_recovery_confirm_description": "Введіть новий ключ відновлення нижче, щоб завершити. Ваш старий ключ більше не працюватиме.", @@ -2632,6 +2656,7 @@ "inline_url_previews_room": "Увімкнути попередній перегляд гіперпосилань за умовчанням для учасників цієї кімнати", "inline_url_previews_room_account": "Увімкнути попередній перегляд гіперпосилань в цій кімнаті (стосується тільки вас)", "insert_trailing_colon_mentions": "Додавати двокрапку після згадки користувача на початку повідомлення", + "invite_avatars": "Показувати аватари кімнат, до яких вас запросили", "jump_to_bottom_on_send": "Переходити вниз стрічки під час надсилання повідомлення", "key_backup": { "backup_in_progress": "Створюється резервна копія ваших ключів (перше копіювання може тривати кілька хвилин).", @@ -4084,7 +4109,7 @@ "error_need_to_be_logged_in": "Вам потрібно увійти.", "error_unable_start_audio_stream_description": "Не вдалося почати аудіотрансляцію.", "error_unable_start_audio_stream_title": "Не вдалося почати живу трансляцію", - "modal_data_warning": "Дані на цьому екрані надсилаються до %(widgetDomain)s", + "modal_data_warning": "Наведені далі дані надсилаються на %(widgetDomain)s", "modal_title_default": "Модальний віджет", "no_name": "Невідомий додаток", "open_id_permissions_dialog": { From 3587161a2ce0a26febe919552dc09db6d2563608 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Wed, 19 Mar 2025 09:39:12 +0100 Subject: [PATCH 116/458] New room list: add selection decoration (#29531) * fix(room list): remove 1px extra padding * feat(room list): add selection decoration to room list item and scroll list to this element * test(room list item): add is selected test * test(room list): update snapshot * test(e2e): add test to keep the room list item visible * test(e2e): update snapshots --- .../room-list-panel/room-list.spec.ts | 16 ++++++ .../room-list-item-hover-linux.png | Bin 2293 -> 2293 bytes ...room-list-item-open-more-options-linux.png | Bin 81877 -> 81869 bytes .../views/rooms/RoomListPanel/_RoomList.pcss | 5 -- .../RoomListPanel/_RoomListItemView.pcss | 4 ++ .../views/rooms/RoomListPanel/RoomList.tsx | 9 ++-- .../rooms/RoomListPanel/RoomListItemView.tsx | 8 ++- .../RoomListPanel/RoomListItemView-test.tsx | 15 ++++-- .../__snapshots__/RoomList-test.tsx.snap | 10 ++++ .../RoomListItemView-test.tsx.snap | 51 ++++++++++++++++++ 10 files changed, 106 insertions(+), 12 deletions(-) diff --git a/playwright/e2e/left-panel/room-list-panel/room-list.spec.ts b/playwright/e2e/left-panel/room-list-panel/room-list.spec.ts index 493ed0d1ab..ed402bc625 100644 --- a/playwright/e2e/left-panel/room-list-panel/room-list.spec.ts +++ b/playwright/e2e/left-panel/room-list-panel/room-list.spec.ts @@ -77,4 +77,20 @@ test.describe("Room list", () => { await page.getByRole("menuitem", { name: "leave room" }).click(); await expect(roomItem).not.toBeVisible(); }); + + test("should scroll to the current room", async ({ page, app, user }) => { + const roomListView = getRoomList(page); + await roomListView.hover(); + // Scroll to the end of the room list + await page.mouse.wheel(0, 1000); + + await roomListView.getByRole("gridcell", { name: "Open room room0" }).click(); + + const filters = page.getByRole("listbox", { name: "Room list filters" }); + await filters.getByRole("option", { name: "People" }).click(); + await expect(roomListView.getByRole("gridcell", { name: "Open room room0" })).not.toBeVisible(); + + await filters.getByRole("option", { name: "People" }).click(); + await expect(roomListView.getByRole("gridcell", { name: "Open room room0" })).toBeVisible(); + }); }); diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-hover-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-hover-linux.png index 45d5588733d88ba0b0061e92c2e7c436ab95195a..0188cb76b2fd4a68dba4a09f7122ac3bdaf818fe 100644 GIT binary patch literal 2293 zcmZ{mdpOe#8^?bmtfYq$<&i^^h*BmwMlnZ247d9Wwi(*NUD|)^u*E8kT}@PoW(%_Cb=c3g#HxwWg;SwSIoNqnaCJwLlR$^v z4|6&AF*)zZ6;su($BrXBJj8P+IQ?78IG!SBIy-wyQ!0rK1^`^lfUia~_YwdIN^WM$ z0Kn}pF>U}b^6>xRjuxT~RlV)U+rtYzIkD>qFm)Kjn%_J7;)2&d5sEQ^f_eSpNT;TAbL2#`$FdP7b=NW z2&Ibo$WhY($-GR$2SvrdHx392Lk1wg_gZ;^aHLLq%<|74UHN%_7vRFbCPzOKBW~GBmhKPYS&4RR4%f31885^r0d)5I;&yE zypnN zCIv*p;DOhM8CZ02&L~A~A$49Syrl9V5Fj(KlGV3Za(R^;8lP%nG?-41^vl}V2AMIR zAU3f(rQ7%3QJ1%qB3WJU5V-6*2xG~!DTjfos@z!5E-bRPev*<>^VGm9TU#Zj(@Q>X zHGJnK)c3k`o}Gqr!jZL`)wjn7?^?1trmpCF14>3n%Bx|iDj9!_F>m;jcz7lCczUj9 zjmxK=>(kp|>|c}Zfta_kv9Wc2J!<`D9*;LRJ_FhXU8)&S zckNwdML|y-t~&r~4Zh%Bc1~%8di$dK)ms@C0|luPnEj&N!Zq-rXq|+Hrl%)QB!~{` z4d_MuR#H`nqp=xvg3peKK8EuaS@SnSC@4awSHYdk?Cg(DaWS4&iiA!d24x7PN%N}B z>Yd${8M+sY!%_cuB73#RMfct}vpCWGenjmYq1!=`WP^a<;i$2!{G1#O&Cm+712jnV z{h4Xhz5CcNOlE4+ndDGmZExchF#!WnWG3(Pnrq)$~qUT3&pHUO4Q|G5ev(&)Nzu_MAmcj_2PslS;l=Kg}2lt5F`@Yv1K#rnT$M_XGB`{nc0#^OBTYD@I_ zH7swjysE6PuP@Dl&0Y1CO|vf@{eTX1b&Zei&oFCikoJ495MrdKzrC|#P8J3p_4M_< z{>lx~(bv7tzx1Ec#(D5rHZb*`?0;;6tiRe@SgG!}(UAdIlqpb9sSZXehj~niuSzAu1 zs1T8nSyUJo06Kc}2s&7svcmngKgCZ@j_+;kE~y|)3JVGf^-tRy;lg%f%N%#U<|cuB zF1NQgpE~h#Z45l^)zbL7rJH+XC|H0)d zpVxP~8UC6651YM`(IR2;Om?r>U>8()$29px-ZrgUdB6d4#XnWiZ0oEzK;{Rtq9$h> znuMHgkl%LzoNH{ey821@coE3v!RCkG!v)YTEiDufEiAT~F8oYphL}zAv7sRN!8}qR*E*OwJ*ia zPd4K<`hY6O5(Fr5M(jeaASOR~`L^^≥z&P@TmFuTz} zXpy9qJtU70EC2{XQ~L|rD?^P+r}B00Jwk{muTB^FSmnR<)_Z;=LxKNdiS`}_cCsCoE6Bcq}_ z-?e!F*;whL0MM!{i0c9Y>vEF&_T+z|gnXTBdGauSuFn2%{1OFPS8raBYOP1?`xwC7 L*alt&yB+&4i)(X^ delta 2291 zcmaKuYdq5r8^(W5OLG2en8TQwvmx46P9c#j%3+0}v>ak&OssyC^KwchlROS3#7YNe zBbviP5gA2>p#zCDr#znL{qwxJKKGmZbKUpn`{KHO%lwv6Pj$u}lMsW60RSN3U~hX0 z00g{tW+PF-9aRiWa?Dm&201Fbe&#oQ*HsgJtfi&qXeJos2HjtLsd@@?!7GL}tXei0 zW7~P;Ooc|VeSszM-SF_1D5f~h?U^b%#ZXe8er}94~X?g!! z2wTdu3avxZU5tvVjEyykv9+O6s(nTK4|g31BH-;e18(k~7iw*ce}qwPxg&yDmBFhIxBnvoL?5tEy3PrxzdW~|__|>nEW0X9nM}o|2A?~Z zd(!u*p{%(eFfMLf^selHGTtS8actMV^_+bW{V{B=hJVh8Jn$2OQ5LJXTfN0*yH9}BS&tK=EQqdDj1 zoEai}c>3P2J~-)J8?%AL!4imKF;$aamyjN0uD^FFBUj{etN+&`Dz+Brsiz7gKtmT{9aLq6o~78!ZT>yjO- zOfX(;|Ngx8$u56WZEfw(pFhv```ot#2}B|!v-3dS3G1RSAIb+E98zT+_+zRVKu%3g zthT~4wMo1)yW-`y#^;t8GJeuMQa9V#xx!TuR8&e@Td#0cadL9Pa?V8X`dX;hluuj3187YYChQ0~koFCLg<^&Fu?)EZ}SMTsQ)+hlH zJ!~C%zNea8YrjwtQ|ia|sfJMD4w{k#tI~s^k2hr2{JKrHqelLo>CLZ=j+N@|-J&jW zUyRb}O-&)*-rkrD54UbYL$|xFL2iH6ahjv#20xlXXkP8PqdQhh8mpybb_eJfSQHO^ z#p}7_@sA59L}BSk(m~*6T}z7}c;6NQrE!!E3UD4ecc3&8^@J(@)GEBu#QRXea3ov? zAjuZxU9T?5?_$p>gb;|EO>g;sp-zoa{iGg6 zn7`w%*EDr-K_;+g_zx51$A^|?auYEbsIw~;`Mt1tG{V@p=JDfwt(I!YgJ+SIoaPM% zEDG0YNTC=BwM$#mHR;Jx@WjM~ zpV4Mx!*TBg5ZQC!cynyQ*FKMs8oVA^JR;&BPMV?N&2Imi5xp@FdM^+E#Qizv(?rSH zs=j^{pRlxbQ8D;fIxJP1yS!HEe%1I&&-BoI@V;9qA)d=QIXNsy=HApVb3$Q7_wPG} zgh=g>y<9sjLsCz^zM;Lc(QU1fp<$EhGF1HNDGlvVIdm2LJyad+!I%kMqYiYWZbby*r5XE$=9D+a~F_KHvA*8rQ%+M2wr?gZIGCxzou6D>JjwM2tem5wkOjE1 z!FkRZrIgw%n}A1ZE3yHj-Y>I|E3#P}N3CdZGS>6gD=2g!jYe~$RM66nBM_{U_YD2w zoYpPOv$=L9&+6(*>-b%t>LU^mel}Zf3DU_RTT)UI+L(&dos0-DC!HRp7Z1GmU;nRe~l8h+o4cUQg%v)}M}LF0JU#G|y%hcNSWvS&SUG z92)SLEN+&j8b@&u5h(%yJ~kd6_Wx>t4ryuO6r|m1_SnuZzu*trnt$kE(8W7F25>lv Kv#qxFz5Z`*Q%C0j diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-open-more-options-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-open-more-options-linux.png index 0501bf1e4c848e3338b9b4f15e22ee9d21b2d20a..083cab778e3fabba0cf7b1ca2d2b88e97f3e95c3 100644 GIT binary patch delta 76178 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

L4q&o8M2}xP7CO3C$e9eQK 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 D@}f#Y diff --git a/res/css/views/rooms/RoomListPanel/_RoomList.pcss b/res/css/views/rooms/RoomListPanel/_RoomList.pcss index 2563c1b675..54798f1ea9 100644 --- a/res/css/views/rooms/RoomListPanel/_RoomList.pcss +++ b/res/css/views/rooms/RoomListPanel/_RoomList.pcss @@ -7,9 +7,4 @@ .mx_RoomList { height: 100%; - - .mx_RoomList_List { - /* Avoid when on hover, the background color to be on top of the right border */ - padding-right: 1px; - } } diff --git a/res/css/views/rooms/RoomListPanel/_RoomListItemView.pcss b/res/css/views/rooms/RoomListPanel/_RoomListItemView.pcss index e53ba3dc79..2e1d42d62e 100644 --- a/res/css/views/rooms/RoomListPanel/_RoomListItemView.pcss +++ b/res/css/views/rooms/RoomListPanel/_RoomListItemView.pcss @@ -47,3 +47,7 @@ .mx_RoomListItemView_menu_open { background-color: var(--cpd-color-bg-action-secondary-hovered); } + +.mx_RoomListItemView_selected { + background-color: var(--cpd-color-bg-action-secondary-pressed); +} diff --git a/src/components/views/rooms/RoomListPanel/RoomList.tsx b/src/components/views/rooms/RoomListPanel/RoomList.tsx index 006d1b9732..67f36b2a19 100644 --- a/src/components/views/rooms/RoomListPanel/RoomList.tsx +++ b/src/components/views/rooms/RoomListPanel/RoomList.tsx @@ -22,10 +22,12 @@ interface RoomListProps { /** * A virtualized list of rooms. */ -export function RoomList({ vm: { rooms } }: RoomListProps): JSX.Element { +export function RoomList({ vm: { rooms, activeIndex } }: RoomListProps): JSX.Element { const roomRendererMemoized = useCallback( - ({ key, index, style }: ListRowProps) => , - [rooms], + ({ key, index, style }: ListRowProps) => ( + + ), + [rooms, activeIndex], ); // The first div is needed to make the virtualized list take all the remaining space and scroll correctly @@ -41,6 +43,7 @@ export function RoomList({ vm: { rooms } }: RoomListProps): JSX.Element { rowHeight={48} height={height} width={width} + scrollToIndex={activeIndex} /> )} diff --git a/src/components/views/rooms/RoomListPanel/RoomListItemView.tsx b/src/components/views/rooms/RoomListPanel/RoomListItemView.tsx index 20173e324e..37ad4ec848 100644 --- a/src/components/views/rooms/RoomListPanel/RoomListItemView.tsx +++ b/src/components/views/rooms/RoomListPanel/RoomListItemView.tsx @@ -20,12 +20,16 @@ interface RoomListItemViewPropsProps extends React.HTMLAttributes vm.openRoom()} onMouseOver={() => setIsHover(true)} diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListItemView-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListItemView-test.tsx index 3023f9a9a7..217015451c 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListItemView-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListItemView-test.tsx @@ -42,13 +42,13 @@ describe("", () => { test("should render a room item", () => { const onClick = jest.fn(); - const { asFragment } = render(); + const { asFragment } = render(); expect(asFragment()).toMatchSnapshot(); }); test("should call openRoom when clicked", async () => { const user = userEvent.setup(); - render(); + render(); await user.click(screen.getByRole("button", { name: `Open room ${room.name}` })); expect(defaultValue.openRoom).toHaveBeenCalled(); @@ -58,11 +58,20 @@ describe("", () => { mocked(useRoomListItemViewModel).mockReturnValue({ ...defaultValue, showHoverMenu: true }); const user = userEvent.setup(); - render(, withClientContextRenderOptions(matrixClient)); + render(, withClientContextRenderOptions(matrixClient)); const listItem = screen.getByRole("button", { name: `Open room ${room.name}` }); expect(screen.queryByRole("button", { name: "More Options" })).toBeNull(); await user.hover(listItem); await waitFor(() => expect(screen.getByRole("button", { name: "More Options" })).toBeInTheDocument()); }); + + test("should be selected if isSelected=true", async () => { + const { asFragment } = render(); + expect(screen.queryByRole("button", { name: `Open room ${room.name}` })).toHaveAttribute( + "aria-selected", + "true", + ); + expect(asFragment()).toMatchSnapshot(); + }); }); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomList-test.tsx.snap b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomList-test.tsx.snap index 37f8a0364a..00c0793080 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomList-test.tsx.snap +++ b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomList-test.tsx.snap @@ -24,6 +24,7 @@ exports[` should render a room list 1`] = ` > + +`; + exports[` should render a room item 1`] = `

  • @@ -297,7 +382,11 @@ exports[`SpaceHierarchy renders 1`] = `
    - Nested space + + Nested space +
    renders 1`] = ` > Join
    - - - - +
    +
    +
  • renders 1`] = ` />
  • @@ -374,7 +487,11 @@ exports[`SpaceHierarchy renders 1`] = `
    - Nested room + + Nested room +
    renders 1`] = ` Join
    - - - - +
    +
    +
  • diff --git a/test/unit-tests/components/views/dialogs/__snapshots__/ExportDialog-test.tsx.snap b/test/unit-tests/components/views/dialogs/__snapshots__/ExportDialog-test.tsx.snap index 4d2a2d54a4..bb11ed96b2 100644 --- a/test/unit-tests/components/views/dialogs/__snapshots__/ExportDialog-test.tsx.snap +++ b/test/unit-tests/components/views/dialogs/__snapshots__/ExportDialog-test.tsx.snap @@ -150,28 +150,53 @@ exports[` renders export dialog 1`] = `
    - - -
    should list spaces which are not par

    Other spaces you know

    - +
    + + + 0 members + +
    +
    + +
    should render with byline of "this is a byline" 1`] = ` - +
    + + + this is a byline + +
    +
    + +
    `; exports[` should render with byline of undefined 1`] = ` - +
    + +
    +
    + +
    `; diff --git a/test/unit-tests/components/views/settings/devices/__snapshots__/FilteredDeviceListHeader-test.tsx.snap b/test/unit-tests/components/views/settings/devices/__snapshots__/FilteredDeviceListHeader-test.tsx.snap index d92286d23a..d8fa0c9d87 100644 --- a/test/unit-tests/components/views/settings/devices/__snapshots__/FilteredDeviceListHeader-test.tsx.snap +++ b/test/unit-tests/components/views/settings/devices/__snapshots__/FilteredDeviceListHeader-test.tsx.snap @@ -9,29 +9,50 @@ exports[` renders correctly when all devices are sel - - - - +
    +
    +
    renders correctly when no devices are sele - - - - +
    +
    +
    renders selected tile 1`] = ` renders unselected device tile with checkbox 1
    - - -
    `; diff --git a/test/unit-tests/components/views/settings/notifications/Notifications2-test.tsx b/test/unit-tests/components/views/settings/notifications/Notifications2-test.tsx index 2a6a3d56db..d33b5c4e26 100644 --- a/test/unit-tests/components/views/settings/notifications/Notifications2-test.tsx +++ b/test/unit-tests/components/views/settings/notifications/Notifications2-test.tsx @@ -39,8 +39,7 @@ const labelActivityStatus = "New room activity, upgrades and status messages occ const labelActivityBots = "Messages sent by bots"; const labelMentionUser = "Notify when someone mentions using @displayname or @mxid"; const labelMentionRoom = "Notify when someone mentions using @room"; -const labelMentionKeyword = - "Notify when someone uses a keyword" + "Enter keywords here, or use for spelling variations or nicknames"; +const labelMentionKeyword = "Notify when someone uses a keyword"; const labelResetDefault = "Reset to default settings"; const keywords = ["justjann3", "justj4nn3", "justj4nne", "Janne", "J4nne", "Jann3", "jann3", "j4nne", "janne"]; diff --git a/test/unit-tests/components/views/settings/notifications/__snapshots__/Notifications2-test.tsx.snap b/test/unit-tests/components/views/settings/notifications/__snapshots__/Notifications2-test.tsx.snap index 035d144820..6ce079e9d2 100644 --- a/test/unit-tests/components/views/settings/notifications/__snapshots__/Notifications2-test.tsx.snap +++ b/test/unit-tests/components/views/settings/notifications/__snapshots__/Notifications2-test.tsx.snap @@ -232,108 +232,177 @@ exports[` correctly handles the loading/disabled state 1`] = `
    - -
    + + + +
    - - - - -
    - - Mentions and Keywords - -
    - -
    + + + +
    - - - - -
    - - Audio and Video calls - -
    - +
    + +
    +
    + +
    correctly handles the loading/disabled state 1`] = `
    - -
    +
    + + +
    - - - - -
    - - New room activity, upgrades and status messages occur - -
    - -
    + + + +
    - - - - -
    - - Messages sent by bots - -
    - +
    + +
    +
    + +
    correctly handles the loading/disabled state 1`] = `
    - -
    +
    + + +
    - - - - -
    - - Notify when someone mentions using @displayname or @userId:matrix.org - -
    - -
    + + + +
    - - - - -
    - - Notify when someone uses a keyword - - -
    - +
    + + + Enter keywords here, or use for spelling variations or nicknames + +
    +
    + +
    @@ -997,105 +1206,174 @@ exports[` matches the snapshot 1`] = `
    - -
    +
    + + +
    - - - - -
    - - Mentions and Keywords - -
    - -
    + + + +
    - - - - -
    - - Audio and Video calls - -
    - +
    + +
    +
    + +
    matches the snapshot 1`] = `
    - -
    +
    + + +
    - - - - -
    - - New room activity, upgrades and status messages occur - -
    - -
    + + + +
    - - - - -
    - - Messages sent by bots - -
    - +
    + +
    +
    + +
    matches the snapshot 1`] = `
    - -
    +
    + + +
    - - - - -
    - - Notify when someone mentions using @displayname or @userId:matrix.org - -
    - -
    + + + +
    - - - - -
    - - Notify when someone uses a keyword - - -
    - +
    + + + Enter keywords here, or use for spelling variations or nicknames + +
    +
    + +
    @@ -1704,38 +2122,61 @@ exports[` matches the snapshot 1`] = `
    - +
    + +
    +
    + +
    diff --git a/test/unit-tests/components/views/settings/tabs/user/__snapshots__/SessionManagerTab-test.tsx.snap b/test/unit-tests/components/views/settings/tabs/user/__snapshots__/SessionManagerTab-test.tsx.snap index 03d9235b73..173876b0c3 100644 --- a/test/unit-tests/components/views/settings/tabs/user/__snapshots__/SessionManagerTab-test.tsx.snap +++ b/test/unit-tests/components/views/settings/tabs/user/__snapshots__/SessionManagerTab-test.tsx.snap @@ -383,28 +383,49 @@ exports[` goes to filtered list from security recommendatio - - - - +
    +
    +
    renders sidebar settings with guest spa url
    - - - - - + +
    - - - - + +
    - - - - + +
    - - - - + +
    - -
    @@ -322,30 +463,53 @@ exports[` renders sidebar settings without guest spa u
    - - - - - + +
    - - - - + +
    - - - - + +
    - - - - + +
    - -
    From 5a6c9a4c9ad8b07b9bc98c6334f228ed9e0885f8 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Fri, 21 Mar 2025 06:22:19 +0000 Subject: [PATCH 125/458] [create-pull-request] automated change (#29559) Co-authored-by: t3chguy <2403652+t3chguy@users.noreply.github.com> --- src/i18n/strings/fr.json | 1 + src/i18n/strings/hu.json | 3 ++- src/i18n/strings/nb_NO.json | 45 +++++++++++++++++++++---------------- src/i18n/strings/uk.json | 15 +++++++++++++ 4 files changed, 44 insertions(+), 20 deletions(-) diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index bfd2e2608e..d816ea9c25 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -3147,6 +3147,7 @@ "view": "Affiche le salon avec cette adresse", "whois": "Affiche des informations à propos de l’utilisateur" }, + "sliding_sync_legacy_no_longer_supported": "L'ancienne fonctionnalité Sliding Sync n'est plus prise en charge : veuillez vous déconnecter puis vous reconnecter pour activer la nouvelle fonctionnalité Sliding Sync", "space": { "add_existing_room_space": { "create": "Voulez-vous plutôt ajouter un nouveau salon ?", diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index c7b62ed03f..86c6b1909b 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -1235,6 +1235,7 @@ "change": "Azonosítási kiszolgáló módosítása", "change_prompt": "Bontja a kapcsolatot a(z) azonosítási kiszolgálóval, és inkább ehhez kapcsolódik: ?", "change_server_prompt": "Ha nem szeretné a(z) kiszolgálót használnia kapcsolatok kereséséhez, és hogy megtalálják az ismerősei, akkor adjon meg egy másik azonosítási kiszolgálót.", + "changed": "Az azonosítási kiszolgáló megváltozott", "checking": "Kiszolgáló ellenőrzése", "description_connected": "Jelenleg a(z) kiszolgálót használja a kapcsolatok kereséséhez, és hogy megtalálják az ismerősei. A használt azonosítási kiszolgálót alább tudja megváltoztatni.", "description_disconnected": "Jelenleg nem használ azonosítási kiszolgálót. A kapcsolatok kereséséhez, és hogy megtalálják az ismerősei, adjon hozzá egy azonosítási kiszolgálót.", @@ -4027,7 +4028,7 @@ "error_need_to_be_logged_in": "Be kell jelentkeznie.", "error_unable_start_audio_stream_description": "A hangközvetítés indítása sikertelen.", "error_unable_start_audio_stream_title": "Az élő adás indítása sikertelen", - "modal_data_warning": "Az ezen a képernyőn látható adatok megosztásra kerülnek ezzel: %(widgetDomain)s", + "modal_data_warning": "A lenti adatok megosztásra kerülnek ezzel: %(widgetDomain)s", "modal_title_default": "Előugró kisalkalmazás", "no_name": "Ismeretlen alkalmazás", "open_id_permissions_dialog": { diff --git a/src/i18n/strings/nb_NO.json b/src/i18n/strings/nb_NO.json index cdf5f0a620..791a4bddd2 100644 --- a/src/i18n/strings/nb_NO.json +++ b/src/i18n/strings/nb_NO.json @@ -459,8 +459,8 @@ "all_chats": "Alle chatter", "analytics": "Statistikk", "and_n_others": { - "og %(count)s andre …": "other", - "og én annen …": "one" + "one": "og en annen...", + "other": "og %(count)s andre..." }, "appearance": "Utseende", "application": "Applikasjon", @@ -1378,8 +1378,8 @@ "other": "Invitere %(user)s og %(count)s andre" }, "items_and_n_others": { - " og %(count)s andre": "other", - " og én annen": "one" + "one": " og en annen", + "other": " og %(count)s andre" }, "keyboard": { "activate_button": "Aktiver valgt knapp", @@ -2101,9 +2101,12 @@ "no_chats": "Ingen chatter ennå", "no_chats_description": "Kom i gang ved å sende meldinger til noen eller ved å opprette et rom", "no_chats_description_no_room_rights": "Kom i gang med å sende meldinger til noen", + "no_favourites": "Du har ikke favorittchat ennå", "no_favourites_description": "Du kan legge til en chat til dine favoritter i chat-innstillingene", "no_people": "Du har ikke direkte chatter med noen ennå", + "no_people_description": "Du kan fjerne merket for filtre for å se de andre chattene dine", "no_rooms": "Du er ikke med i noen rom ennå", + "no_rooms_description": "Du kan fjerne merket for filtre for å se de andre chattene dine", "no_unread": "Gratulerer! Du har ingen uleste meldinger", "show_chats": "Vis alle chatter" }, @@ -2531,7 +2534,9 @@ "title": "Avansert" }, "delete_key_storage": { + "breadcrumb_page": "Slett nøkkellagring", "confirm": "Slett nøkkellagring", + "description": "Hvis du sletter nøkkellagring, fjernes den kryptografiske identiteten og meldingsnøklene fra serveren og deaktivere følgende sikkerhetsfunksjoner:", "list_first": "Du vil ikke ha kryptert meldingshistorikk på nye enheter", "list_second": "Du vil miste tilgangen til de krypterte meldingene dine hvis du logger av %(brand)s overalt", "title": "Er du sikker på at du vil slå av nøkkellagring og slette den?" @@ -2541,7 +2546,9 @@ "device_not_verified_title": "Enhet er ikke verifisert", "dialog_title": "Innstillinger: Kryptering", "key_storage": { - "allow_key_storage": "Tillat lagring av nøkler" + "allow_key_storage": "Tillat lagring av nøkler", + "description": "Lagre din kryptografiske identitet og meldingsnøkler sikkert på serveren. Dette lar deg se meldingsloggen din på alle nye enheter.
    Lær mer ", + "title": "Nøkkellager" }, "recovery": { "change_recovery_confirm_button": "Bekreft ny gjenopprettingsnøkkel", @@ -3636,12 +3643,12 @@ "send_state_sent": "Meldingen ble sendt", "summary": { "banned": { - "ble bannlyst": "one", - "ble bannlyst %(count)s ganger": "other" + "one": "ble utestengt", + "other": "ble utestengt %(count)s ganger" }, "banned_multiple": { - "ble bannlyst": "one", - "ble bannlyst %(count)s ganger": "other" + "one": "ble utestengt", + "other": "ble utestengt %(count)s ganger" }, "changed_avatar": { "one": "%(oneUser)sendret profilbildet deres", @@ -3652,8 +3659,8 @@ "other": "%(severalUsers)sendret profilbildet deres %(count)s ganger" }, "changed_name": { - "%(oneUser)s endret navnet sitt": "one", - "%(oneUser)sendret navnet sitt %(count)s ganger": "other" + "one": "%(oneUser)s endret navn", + "other": "%(oneUser)s endret navn %(count)s ganger" }, "changed_name_multiple": { "%(severalUsers)s endret navnene sine": "one" @@ -3706,12 +3713,12 @@ "other": "ble fjernet %(count)s ganger" }, "left": { - "%(oneUser)s forlot rommet %(count)s ganger": "other", - "%(oneUser)s forlot rommet": "one" + "one": "%(oneUser)s forlot", + "other": "%(oneUser)s forlot %(count)s ganger" }, "left_multiple": { - "%(severalUsers)s forlot rommet %(count)s ganger": "other", - "%(severalUsers)s forlot rommet": "one" + "one": "%(severalUsers)s forlot", + "other": "%(severalUsers)s forlot %(count)s ganger" }, "no_change": { "one": "%(oneUser)sgjorde ingen endringer", @@ -3762,12 +3769,12 @@ "other": "%(severalUsers)sendret serverens ACLer %(count)s ganger" }, "unbanned": { - "fikk bannlysningen sin opphevet %(count)s ganger": "other", - "fikk bannlysningen sin opphevet": "one" + "one": "fikk opphevet forbudet", + "other": "fikk opphevet forbudet %(count)s ganger" }, "unbanned_multiple": { - "fikk bannlysningene sine opphevet %(count)s ganger": "other", - "fikk bannlysningene sine opphevet": "one" + "one": "fikk opphevet forbudet", + "other": "fikk opphevet forbudet %(count)s ganger" } }, "thread_info_basic": "Fra en tråd", diff --git a/src/i18n/strings/uk.json b/src/i18n/strings/uk.json index d882295447..6a5156a14a 100644 --- a/src/i18n/strings/uk.json +++ b/src/i18n/strings/uk.json @@ -64,6 +64,7 @@ "go": "Уперед", "go_back": "Назад", "got_it": "Зрозуміло", + "hide": "Сховати", "hide_advanced": "Сховати розширені", "hold": "Утримувати", "ignore": "Ігнорувати", @@ -2100,6 +2101,19 @@ "add_space_label": "Додати простір", "breadcrumbs_empty": "Немає недавно відвіданих кімнат", "breadcrumbs_label": "Недавно відвідані кімнати", + "empty": { + "no_chats": "Ще немає бесід", + "no_chats_description": "Почніть користування, надіславши комусь повідомлення або створивши кімнату", + "no_chats_description_no_room_rights": "Розпочніть користування, написавши комусь повідомлення", + "no_favourites": "У вас ще немає обраних бесід", + "no_favourites_description": "Ви можете додати бесіду до обраних у її налаштуваннях", + "no_people": "У вас ще немає особистих бесід", + "no_people_description": "Ви можете очистити фільтри, щоб побачити інші ваші бесіди", + "no_rooms": "Ви ще не входили до кімнат", + "no_rooms_description": "Ви можете очистити фільтри, щоб побачити інші ваші бесіди", + "no_unread": "Вітаємо! У вас немає непрочитаних повідомлень", + "show_chats": "Показати всі бесіди" + }, "failed_add_tag": "Не вдалось додати до кімнати мітку %(tagName)s", "failed_remove_tag": "Не вдалося прибрати з кімнати мітку %(tagName)s", "failed_set_dm_tag": "Не вдалося встановити мітку особистого повідомлення", @@ -3138,6 +3152,7 @@ "view": "Перегляд кімнати з вказаною адресою", "whois": "Показує відомості про користувача" }, + "sliding_sync_legacy_no_longer_supported": "Застаріла ковзна синхронізація більше не підтримується: вийдіть і ввійдіть знову, щоб увімкнути новий прапорець ковзної синхронізації", "space": { "add_existing_room_space": { "create": "Хочете додати нову кімнату натомість?", From 0dc295e3b8c706cd2af036a6aa13d9e6bbec9c8f Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Fri, 21 Mar 2025 13:58:00 +0530 Subject: [PATCH 126/458] RoomListStore: Unread filter should only filter rooms having unread counts (#29555) * Use `hasUnreadCount` instead of `isUnread` * Fix broken test * Write test --- .../room-list-panel/room-list.spec.ts | 37 +++++++++++++++++++ .../skip-list/filters/UnreadFilter.ts | 2 +- .../room-list-v3/RoomListStoreV3-test.ts | 4 +- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/playwright/e2e/left-panel/room-list-panel/room-list.spec.ts b/playwright/e2e/left-panel/room-list-panel/room-list.spec.ts index ed402bc625..6f19bf60d1 100644 --- a/playwright/e2e/left-panel/room-list-panel/room-list.spec.ts +++ b/playwright/e2e/left-panel/room-list-panel/room-list.spec.ts @@ -93,4 +93,41 @@ test.describe("Room list", () => { await filters.getByRole("option", { name: "People" }).click(); await expect(roomListView.getByRole("gridcell", { name: "Open room room0" })).toBeVisible(); }); + + test("unread filter should only match unread rooms that have a count", async ({ page, app, bot }) => { + const roomListView = getRoomList(page); + // Let's create a new room and invite the bot + const room1Id = await app.client.createRoom({ + name: "Unread Room 1", + invite: [bot.credentials?.userId], + }); + await bot.awaitRoomMembership(room1Id); + + // Let's create another room as well + const room2Id = await app.client.createRoom({ + name: "Unread Room 2", + invite: [bot.credentials?.userId], + }); + await bot.awaitRoomMembership(room2Id); + + // Let's configure unread room 1 so that we only get notification for mentions and keywords + await app.viewRoomById(room1Id); + await app.settings.openRoomSettings("Notifications"); + await page.getByText("@mentions & keywords").click(); + await app.settings.closeDialog(); + + // Let's open a room other than room 1 or room 2 + await roomListView.getByRole("gridcell", { name: "Open room room29" }).click(); + + // Let's make the bot send a new message in both room 1 and room 2 + await bot.sendMessage(room1Id, "Hello!"); + await bot.sendMessage(room2Id, "Hello!"); + + // Let's activate the unread filter now + await page.getByRole("option", { name: "Unread" }).click(); + + // Unread filter should only show room 2!! + await expect(roomListView.getByRole("gridcell", { name: "Open room Unread Room 2" })).toBeVisible(); + await expect(roomListView.getByRole("gridcell", { name: "Open room Unread Room 1" })).not.toBeVisible(); + }); }); diff --git a/src/stores/room-list-v3/skip-list/filters/UnreadFilter.ts b/src/stores/room-list-v3/skip-list/filters/UnreadFilter.ts index c830f1d55b..e2ffc8f0f4 100644 --- a/src/stores/room-list-v3/skip-list/filters/UnreadFilter.ts +++ b/src/stores/room-list-v3/skip-list/filters/UnreadFilter.ts @@ -11,7 +11,7 @@ import { RoomNotificationStateStore } from "../../../notifications/RoomNotificat export class UnreadFilter implements Filter { public matches(room: Room): boolean { - return RoomNotificationStateStore.instance.getRoomState(room).isUnread; + return RoomNotificationStateStore.instance.getRoomState(room).hasUnreadCount; } public get key(): FilterKey.UnreadFilter { diff --git a/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts b/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts index 0fdef53729..573e7a38b4 100644 --- a/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts +++ b/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts @@ -457,7 +457,7 @@ describe("RoomListStoreV3", () => { // Let's say 8, 27 are unread jest.spyOn(RoomNotificationStateStore.instance, "getRoomState").mockImplementation((room) => { const state = { - isUnread: [rooms[8], rooms[27]].includes(room), + hasUnreadCount: [rooms[8], rooms[27]].includes(room), } as unknown as RoomNotificationState; return state; }); @@ -588,7 +588,7 @@ describe("RoomListStoreV3", () => { // Let's say 8, 27 are unread jest.spyOn(RoomNotificationStateStore.instance, "getRoomState").mockImplementation((room) => { const state = { - isUnread: [rooms[8], rooms[27]].includes(room), + hasUnreadCount: [rooms[8], rooms[27]].includes(room), } as unknown as RoomNotificationState; return state; }); From 3a39486468acd4ec40dc3c2e99751914bd31ad0e Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Fri, 21 Mar 2025 16:16:20 +0530 Subject: [PATCH 127/458] RoomListViewModel: Reset any primary filter on secondary filter change (#29562) * Reset primary filter when secondary filter is applied * Add test --- .../viewmodels/roomlist/useFilteredRooms.tsx | 20 +++++----------- .../roomlist/RoomListViewModel-test.tsx | 23 +++++++++++++++++++ 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/components/viewmodels/roomlist/useFilteredRooms.tsx b/src/components/viewmodels/roomlist/useFilteredRooms.tsx index 68f8e3e380..5e1554fcdc 100644 --- a/src/components/viewmodels/roomlist/useFilteredRooms.tsx +++ b/src/components/viewmodels/roomlist/useFilteredRooms.tsx @@ -145,22 +145,14 @@ export function useFilteredRooms(): FilteredRooms { // SecondaryFilter is an enum for the UI, let's convert it to something // that the store will understand. const secondary = secondaryFiltersToFilterKeyMap.get(filter); - - // Active primary filter may need to be toggled off when applying this secondary filer. - let primary = primaryFilter; - if ( - primaryFilter !== undefined && - secondary !== undefined && - !isPrimaryFilterCompatible(primaryFilter, secondary) - ) { - primary = undefined; - } - setActiveSecondaryFilter(filter); - setPrimaryFilter(primary); - updateRoomsFromStore(filterUndefined([primary, secondary])); + + // Reset any active primary filters. + setPrimaryFilter(undefined); + + updateRoomsFromStore(filterUndefined([secondary])); }, - [activeSecondaryFilter, primaryFilter, updateRoomsFromStore], + [activeSecondaryFilter, updateRoomsFromStore], ); /** diff --git a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx index f14a7e0acd..07421fc0b3 100644 --- a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx +++ b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx @@ -162,6 +162,29 @@ describe("RoomListViewModel", () => { expect(vm.current.activePrimaryFilter).toEqual(vm.current.primaryFilters[i]); }); + it("should remove any active primary filters when secondary filter is changed", async () => { + const { fn } = mockAndCreateRooms(); + const { result: vm } = renderHook(() => useRoomListViewModel()); + + // Let's first toggle the People filter + const i = vm.current.primaryFilters.findIndex((f) => f.name === "People"); + act(() => { + vm.current.primaryFilters[i].toggle(); + }); + expect(vm.current.primaryFilters[i].active).toEqual(true); + + // Let's say we toggle the mentions secondary filter + act(() => { + vm.current.activateSecondaryFilter(SecondaryFilters.MentionsOnly); + }); + + // Primary filer should have been unapplied + expect(vm.current.primaryFilters[i].active).toEqual(false); + + // RLS call must include only the secondary filter + expect(fn).toHaveBeenLastCalledWith(expect.arrayContaining([FilterKey.MentionsFilter])); + }); + const testcases: Array<[string, { secondary: SecondaryFilters; filterKey: FilterKey }, string]> = [ [ "Mentions only", From 0d28df0f67022db00c65a2af52fde45f69d81c77 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 21 Mar 2025 11:34:06 +0000 Subject: [PATCH 128/458] Reuse PushProcessor from MatrixClient (#29561) * Reuse PushProcessor from MatrixClient Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Reuse PushProcessor getPushRuleGlobRegex Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * delint Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update regex handling Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/LegacyCallHandler.tsx | 3 +-- src/components/views/messages/TextualBody.tsx | 19 ++++++++----------- .../controllers/NotificationControllers.ts | 5 +---- src/utils/pillify.tsx | 6 ++---- src/utils/pushRules/monitorSyncedPushRules.ts | 14 ++++++-------- src/utils/pushRules/updatePushRuleActions.ts | 5 +---- test/unit-tests/LegacyCallHandler-test.ts | 4 ++++ .../structures/LoggedInView-test.tsx | 3 +++ .../views/messages/TextualBody-test.tsx | 3 +++ .../views/settings/Notifications-test.tsx | 3 +++ test/unit-tests/utils/pillify-test.tsx | 3 +++ 11 files changed, 35 insertions(+), 33 deletions(-) diff --git a/src/LegacyCallHandler.tsx b/src/LegacyCallHandler.tsx index 4361d3d027..608d396dda 100644 --- a/src/LegacyCallHandler.tsx +++ b/src/LegacyCallHandler.tsx @@ -22,7 +22,6 @@ import { type MatrixCall, } from "matrix-js-sdk/src/webrtc/call"; import { logger } from "matrix-js-sdk/src/logger"; -import { PushProcessor } from "matrix-js-sdk/src/pushprocessor"; import { CallEventHandlerEvent } from "matrix-js-sdk/src/webrtc/callEventHandler"; import { MatrixClientPeg } from "./MatrixClientPeg"; @@ -596,7 +595,7 @@ export default class LegacyCallHandler extends TypedEventEmitter { pushDetails.rule.kind === PushRuleKind.ContentSpecific && pushDetails.rule.pattern ) { - this.pillifyNotificationKeywords([content], this.regExpForKeywordPattern(pushDetails.rule.pattern)); + this.pillifyNotificationKeywords( + [content], + PushProcessor.getPushRuleGlobRegex(pushDetails.rule.pattern, true), + ); } } @@ -235,12 +238,12 @@ export default class TextualBody extends React.Component { continue; } const match = text.match(exp); - if (!match || match.length < 3) { + if (!match || match.length < 2) { node = node.nextSibling; continue; } - const keywordText = match[2]; - const idx = match.index! + match[1].length; + const keywordText = match[1]; + const idx = match.index!; const before = text.substring(0, idx); const after = text.substring(idx + keywordText.length); @@ -265,12 +268,6 @@ export default class TextualBody extends React.Component { } } - private regExpForKeywordPattern(pattern: string): RegExp { - // Reflects the push notification pattern-matching implementation at - // https://github.com/matrix-org/matrix-js-sdk/blob/dbd7d26968b94700827bac525c39afff2c198e61/src/pushprocessor.ts#L570 - return new RegExp("(^|\\W)(" + globToRegexp(pattern) + ")(\\W|$)", "i"); - } - private findLinks(nodes: ArrayLike): string[] { let links: string[] = []; diff --git a/src/settings/controllers/NotificationControllers.ts b/src/settings/controllers/NotificationControllers.ts index 20b0d7cf7c..8ec17977b5 100644 --- a/src/settings/controllers/NotificationControllers.ts +++ b/src/settings/controllers/NotificationControllers.ts @@ -8,8 +8,6 @@ Please see LICENSE files in the repository root for full details. */ import { logger } from "matrix-js-sdk/src/logger"; -// XXX: This feels wrong. -import { PushProcessor } from "matrix-js-sdk/src/pushprocessor"; import { PushRuleActionName } from "matrix-js-sdk/src/matrix"; import SettingController from "./SettingController"; @@ -20,8 +18,7 @@ import { type SettingLevel } from "../SettingLevel"; // default action on this rule is dont_notify, but it could be something else export function isPushNotifyDisabled(): boolean { // Return the value of the master push rule as a default - const processor = new PushProcessor(MatrixClientPeg.safeGet()); - const masterRule = processor.getPushRuleById(".m.rule.master"); + const masterRule = MatrixClientPeg.safeGet().pushProcessor.getPushRuleById(".m.rule.master"); if (!masterRule) { logger.warn("No master push rule! Notifications are disabled for this user."); diff --git a/src/utils/pillify.tsx b/src/utils/pillify.tsx index e39fd813bb..6c83ad6553 100644 --- a/src/utils/pillify.tsx +++ b/src/utils/pillify.tsx @@ -7,7 +7,6 @@ Please see LICENSE files in the repository root for full details. */ import React, { StrictMode } from "react"; -import { PushProcessor } from "matrix-js-sdk/src/pushprocessor"; import { type MatrixClient, type MatrixEvent, RuleId } from "matrix-js-sdk/src/matrix"; import { TooltipProvider } from "@vector-im/compound-web"; @@ -119,11 +118,10 @@ export function pillifyLinks( } if (roomNotifTextNodes.length > 0) { - const pushProcessor = new PushProcessor(matrixClient); - const atRoomRule = pushProcessor.getPushRuleById( + const atRoomRule = matrixClient.pushProcessor.getPushRuleById( mxEvent.getContent()["m.mentions"] !== undefined ? RuleId.IsRoomMention : RuleId.AtRoomNotification, ); - if (atRoomRule && pushProcessor.ruleMatchesEvent(atRoomRule, mxEvent)) { + if (atRoomRule && matrixClient.pushProcessor.ruleMatchesEvent(atRoomRule, mxEvent)) { // Now replace all those nodes with Pills for (const roomNotifTextNode of roomNotifTextNodes) { // Set the next node to be processed to the one after the node diff --git a/src/utils/pushRules/monitorSyncedPushRules.ts b/src/utils/pushRules/monitorSyncedPushRules.ts index 2c9684722c..0e9620fe13 100644 --- a/src/utils/pushRules/monitorSyncedPushRules.ts +++ b/src/utils/pushRules/monitorSyncedPushRules.ts @@ -12,15 +12,16 @@ import { EventType, type RuleId, type IAnnotatedPushRule, + type IPushRule, + type PushRuleKind, } from "matrix-js-sdk/src/matrix"; -import { PushProcessor } from "matrix-js-sdk/src/pushprocessor"; import { logger } from "matrix-js-sdk/src/logger"; import { VectorPushRulesDefinitions, type VectorPushRuleDefinition } from "../../notifications"; import { updateExistingPushRulesWithActions } from "./updatePushRuleActions"; const pushRuleAndKindToAnnotated = ( - ruleAndKind: ReturnType, + ruleAndKind: { rule: IPushRule; kind: PushRuleKind } | null, ): IAnnotatedPushRule | undefined => ruleAndKind ? { @@ -34,23 +35,21 @@ const pushRuleAndKindToAnnotated = ( * And updates any that are out of sync * Ignores ruleIds that do not exist for the user * @param matrixClient - cli - * @param pushProcessor - processor used to retrieve current state of rules * @param ruleId - primary rule * @param definition - VectorPushRuleDefinition of the primary rule */ const monitorSyncedRule = async ( matrixClient: MatrixClient, - pushProcessor: PushProcessor, ruleId: RuleId | string, definition: VectorPushRuleDefinition, ): Promise => { - const primaryRule = pushRuleAndKindToAnnotated(pushProcessor.getPushRuleAndKindById(ruleId)); + const primaryRule = pushRuleAndKindToAnnotated(matrixClient.pushProcessor.getPushRuleAndKindById(ruleId)); if (!primaryRule) { return; } const syncedRules: IAnnotatedPushRule[] | undefined = definition.syncedRuleIds - ?.map((ruleId) => pushRuleAndKindToAnnotated(pushProcessor.getPushRuleAndKindById(ruleId))) + ?.map((ruleId) => pushRuleAndKindToAnnotated(matrixClient.pushProcessor.getPushRuleAndKindById(ruleId))) .filter((n?: IAnnotatedPushRule): n is IAnnotatedPushRule => Boolean(n)); // no synced rules to manage @@ -94,11 +93,10 @@ export const monitorSyncedPushRules = async ( if (accountDataEvent?.getType() !== EventType.PushRules) { return; } - const pushProcessor = new PushProcessor(matrixClient); Object.entries(VectorPushRulesDefinitions).forEach(async ([ruleId, definition]) => { try { - await monitorSyncedRule(matrixClient, pushProcessor, ruleId, definition); + await monitorSyncedRule(matrixClient, ruleId, definition); } catch (error) { logger.error(`Failed to fully synchronise push rules for ${ruleId}`, error); } diff --git a/src/utils/pushRules/updatePushRuleActions.ts b/src/utils/pushRules/updatePushRuleActions.ts index 1d872e5207..8a383cace6 100644 --- a/src/utils/pushRules/updatePushRuleActions.ts +++ b/src/utils/pushRules/updatePushRuleActions.ts @@ -7,7 +7,6 @@ Please see LICENSE files in the repository root for full details. */ import { type MatrixClient, type IPushRule, type PushRuleAction, type PushRuleKind } from "matrix-js-sdk/src/matrix"; -import { PushProcessor } from "matrix-js-sdk/src/pushprocessor"; /** * Sets the actions for a given push rule id and kind @@ -51,10 +50,8 @@ export const updateExistingPushRulesWithActions = async ( ruleIds?: IPushRule["rule_id"][], actions?: PushRuleAction[], ): Promise => { - const pushProcessor = new PushProcessor(matrixClient); - const rules: PushRuleAndKind[] | undefined = ruleIds - ?.map((ruleId) => pushProcessor.getPushRuleAndKindById(ruleId)) + ?.map((ruleId) => matrixClient.pushProcessor.getPushRuleAndKindById(ruleId)) .filter((n: PushRuleAndKind | null): n is PushRuleAndKind => Boolean(n)); if (!rules?.length) { diff --git a/test/unit-tests/LegacyCallHandler-test.ts b/test/unit-tests/LegacyCallHandler-test.ts index d10c232b65..664e091393 100644 --- a/test/unit-tests/LegacyCallHandler-test.ts +++ b/test/unit-tests/LegacyCallHandler-test.ts @@ -22,6 +22,7 @@ import { mocked } from "jest-mock"; import { CallEventHandlerEvent } from "matrix-js-sdk/src/webrtc/callEventHandler"; import fetchMock from "fetch-mock-jest"; import { waitFor } from "jest-matrix-react"; +import { PushProcessor } from "matrix-js-sdk/src/pushprocessor"; import LegacyCallHandler, { AudioID, @@ -473,6 +474,9 @@ describe("LegacyCallHandler without third party protocols", () => { throw new Error("Endpoint unsupported."); }; + // @ts-expect-error + MatrixClientPeg.safeGet().pushProcessor = new PushProcessor(MatrixClientPeg.safeGet()); + audioElement = document.createElement("audio"); audioElement.id = "remoteAudio"; document.body.appendChild(audioElement); diff --git a/test/unit-tests/components/structures/LoggedInView-test.tsx b/test/unit-tests/components/structures/LoggedInView-test.tsx index beca86ddcf..6d24cbe416 100644 --- a/test/unit-tests/components/structures/LoggedInView-test.tsx +++ b/test/unit-tests/components/structures/LoggedInView-test.tsx @@ -19,6 +19,7 @@ import { import { MediaHandler } from "matrix-js-sdk/src/webrtc/mediaHandler"; import { logger } from "matrix-js-sdk/src/logger"; import userEvent from "@testing-library/user-event"; +import { PushProcessor } from "matrix-js-sdk/src/pushprocessor"; import LoggedInView from "../../../../src/components/structures/LoggedInView"; import { SDKContext } from "../../../../src/contexts/SDKContext"; @@ -75,6 +76,8 @@ describe("", () => { jest.clearAllMocks(); mockClient.getMediaHandler.mockReturnValue(mediaHandler); mockClient.setPushRuleActions.mockReset().mockResolvedValue({}); + // @ts-expect-error + mockClient.pushProcessor = new PushProcessor(mockClient); }); describe("synced push rules", () => { diff --git a/test/unit-tests/components/views/messages/TextualBody-test.tsx b/test/unit-tests/components/views/messages/TextualBody-test.tsx index 753534a93f..db4790976a 100644 --- a/test/unit-tests/components/views/messages/TextualBody-test.tsx +++ b/test/unit-tests/components/views/messages/TextualBody-test.tsx @@ -10,6 +10,7 @@ import React from "react"; import { type MatrixClient, type MatrixEvent, PushRuleKind } from "matrix-js-sdk/src/matrix"; import { mocked, type MockedObject } from "jest-mock"; import { render, waitFor } from "jest-matrix-react"; +import { PushProcessor } from "matrix-js-sdk/src/pushprocessor"; import { getMockClientWithEventEmitter, mkEvent, mkMessage, mkStubRoom } from "../../../../test-utils"; import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg"; @@ -85,6 +86,8 @@ describe("", () => { throw new Error("MockClient event not found"); }, }); + // @ts-expect-error + defaultMatrixClient.pushProcessor = new PushProcessor(defaultMatrixClient); mocked(defaultRoom).findEventById.mockImplementation((eventId: string) => { if (eventId === defaultEvent.getId()) return defaultEvent; diff --git a/test/unit-tests/components/views/settings/Notifications-test.tsx b/test/unit-tests/components/views/settings/Notifications-test.tsx index 00653e1a3b..1566013aba 100644 --- a/test/unit-tests/components/views/settings/Notifications-test.tsx +++ b/test/unit-tests/components/views/settings/Notifications-test.tsx @@ -36,6 +36,7 @@ import { } from "jest-matrix-react"; import { mocked } from "jest-mock"; import userEvent from "@testing-library/user-event"; +import { PushProcessor } from "matrix-js-sdk/src/pushprocessor"; import Notifications from "../../../../../src/components/views/settings/Notifications"; import SettingsStore from "../../../../../src/settings/SettingsStore"; @@ -301,6 +302,8 @@ describe("", () => { mockClient.getPushRules.mockClear().mockResolvedValue(pushRules); mockClient.addPushRule.mockClear(); mockClient.deletePushRule.mockClear(); + // @ts-expect-error + mockClient.pushProcessor = new PushProcessor(mockClient); userEvent.setup(); diff --git a/test/unit-tests/utils/pillify-test.tsx b/test/unit-tests/utils/pillify-test.tsx index 4cca311c57..2b5a0859bb 100644 --- a/test/unit-tests/utils/pillify-test.tsx +++ b/test/unit-tests/utils/pillify-test.tsx @@ -10,6 +10,7 @@ import React from "react"; import { act, render } from "jest-matrix-react"; import { MatrixEvent, ConditionKind, EventType, PushRuleActionName, Room, TweakName } from "matrix-js-sdk/src/matrix"; import { mocked } from "jest-mock"; +import { PushProcessor } from "matrix-js-sdk/src/pushprocessor"; import { pillifyLinks } from "../../../src/utils/pillify"; import { stubClient } from "../../test-utils"; @@ -78,6 +79,8 @@ describe("pillify", () => { }, ], }; + // @ts-expect-error + cli.pushProcessor = new PushProcessor(cli); DMRoomMap.makeShared(cli); }); From b54122884c5a28fd72003e8d77581eea7cb69146 Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Fri, 21 Mar 2025 17:41:59 +0530 Subject: [PATCH 129/458] RoomListViewModel: Make the active room sticky in the list (#29551) * Add new hook for sticky room This hook takes the filtered, sorted rooms and returns a new list of rooms such that the active room is kept in the same index even when the list has changes. * Use new hook in view model * Add tests * Use single * in comments --- .../viewmodels/roomlist/RoomListViewModel.tsx | 13 +- .../roomlist/useIndexForActiveRoom.tsx | 44 ------- .../viewmodels/roomlist/useStickyRoomList.tsx | 117 +++++++++++++++++ .../roomlist/RoomListViewModel-test.tsx | 123 +++++++++++++++--- 4 files changed, 230 insertions(+), 67 deletions(-) delete mode 100644 src/components/viewmodels/roomlist/useIndexForActiveRoom.tsx create mode 100644 src/components/viewmodels/roomlist/useStickyRoomList.tsx diff --git a/src/components/viewmodels/roomlist/RoomListViewModel.tsx b/src/components/viewmodels/roomlist/RoomListViewModel.tsx index 584e436c57..217eaefbd9 100644 --- a/src/components/viewmodels/roomlist/RoomListViewModel.tsx +++ b/src/components/viewmodels/roomlist/RoomListViewModel.tsx @@ -18,7 +18,7 @@ import SpaceStore from "../../../stores/spaces/SpaceStore"; import dispatcher from "../../../dispatcher/dispatcher"; import { Action } from "../../../dispatcher/actions"; import { useMatrixClientContext } from "../../../contexts/MatrixClientContext"; -import { useIndexForActiveRoom } from "./useIndexForActiveRoom"; +import { useStickyRoomList } from "./useStickyRoomList"; export interface RoomListViewState { /** @@ -97,8 +97,14 @@ export interface RoomListViewState { */ export function useRoomListViewModel(): RoomListViewState { const matrixClient = useMatrixClientContext(); - const { primaryFilters, activePrimaryFilter, rooms, activateSecondaryFilter, activeSecondaryFilter } = - useFilteredRooms(); + const { + primaryFilters, + activePrimaryFilter, + rooms: filteredRooms, + activateSecondaryFilter, + activeSecondaryFilter, + } = useFilteredRooms(); + const { activeIndex, rooms } = useStickyRoomList(filteredRooms); const currentSpace = useEventEmitterState( SpaceStore.instance, @@ -107,7 +113,6 @@ export function useRoomListViewModel(): RoomListViewState { ); const canCreateRoom = hasCreateRoomRights(matrixClient, currentSpace); - const activeIndex = useIndexForActiveRoom(rooms); const { activeSortOption, sort } = useSorter(); const { shouldShowMessagePreview, toggleMessagePreview } = useMessagePreviewToggle(); diff --git a/src/components/viewmodels/roomlist/useIndexForActiveRoom.tsx b/src/components/viewmodels/roomlist/useIndexForActiveRoom.tsx deleted file mode 100644 index 210e0efd0f..0000000000 --- a/src/components/viewmodels/roomlist/useIndexForActiveRoom.tsx +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2025 New Vector 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 { useCallback, useEffect, useState } from "react"; - -import { SdkContextClass } from "../../../contexts/SDKContext"; -import { useDispatcher } from "../../../hooks/useDispatcher"; -import dispatcher from "../../../dispatcher/dispatcher"; -import { Action } from "../../../dispatcher/actions"; -import type { Room } from "matrix-js-sdk/src/matrix"; - -/** - * Tracks the index of the active room in the given array of rooms. - * @param rooms list of rooms - * @returns index of the active room or undefined otherwise. - */ -export function useIndexForActiveRoom(rooms: Room[]): number | undefined { - const [index, setIndex] = useState(undefined); - - const calculateIndex = useCallback( - (newRoomId?: string) => { - const activeRoomId = newRoomId ?? SdkContextClass.instance.roomViewStore.getRoomId(); - const index = rooms.findIndex((room) => room.roomId === activeRoomId); - setIndex(index === -1 ? undefined : index); - }, - [rooms], - ); - - // Re-calculate the index when the active room has changed. - useDispatcher(dispatcher, (payload) => { - if (payload.action === Action.ActiveRoomChanged) calculateIndex(payload.newRoomId); - }); - - // Re-calculate the index when the list of rooms has changed. - useEffect(() => { - calculateIndex(); - }, [calculateIndex, rooms]); - - return index; -} diff --git a/src/components/viewmodels/roomlist/useStickyRoomList.tsx b/src/components/viewmodels/roomlist/useStickyRoomList.tsx new file mode 100644 index 0000000000..e8234d14ae --- /dev/null +++ b/src/components/viewmodels/roomlist/useStickyRoomList.tsx @@ -0,0 +1,117 @@ +/* + * Copyright 2025 New Vector 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 { useCallback, useEffect, useState } from "react"; + +import { SdkContextClass } from "../../../contexts/SDKContext"; +import { useDispatcher } from "../../../hooks/useDispatcher"; +import dispatcher from "../../../dispatcher/dispatcher"; +import { Action } from "../../../dispatcher/actions"; +import type { Room } from "matrix-js-sdk/src/matrix"; +import type { Optional } from "matrix-events-sdk"; + +function getIndexByRoomId(rooms: Room[], roomId: Optional): number | undefined { + const index = rooms.findIndex((room) => room.roomId === roomId); + return index === -1 ? undefined : index; +} + +function getRoomsWithStickyRoom( + rooms: Room[], + oldIndex: number | undefined, + newIndex: number | undefined, + isRoomChange: boolean, +): { newRooms: Room[]; newIndex: number | undefined } { + const updated = { newIndex, newRooms: rooms }; + if (isRoomChange) { + /* + * When opening another room, the index should obviously change. + */ + return updated; + } + if (newIndex === undefined || oldIndex === undefined) { + /* + * If oldIndex is undefined, then there was no active room before. + * So nothing to do in regards to sticky room. + * Similarly, if newIndex is undefined, there's no active room anymore. + */ + return updated; + } + if (newIndex === oldIndex) { + /* + * If the index hasn't changed, we have nothing to do. + */ + return updated; + } + if (oldIndex > rooms.length - 1) { + /* + * If the old index falls out of the bounds of the rooms array + * (usually because rooms were removed), we can no longer place + * the active room in the same old index. + */ + return updated; + } + + /* + * Making the active room sticky is as simple as removing it from + * its new index and placing it in the old index. + */ + const newRooms = [...rooms]; + const [newRoom] = newRooms.splice(newIndex, 1); + newRooms.splice(oldIndex, 0, newRoom); + + return { newIndex: oldIndex, newRooms }; +} + +interface StickyRoomListResult { + /** + * List of rooms with sticky active room. + */ + rooms: Room[]; + /** + * Index of the active room in the room list. + */ + activeIndex: number | undefined; +} + +/** + * - Provides a list of rooms such that the active room is sticky i.e the active room is kept + * in the same index even when the order of rooms in the list changes. + * - Provides the index of the active room. + * @param rooms list of rooms + * @see {@link StickyRoomListResult} details what this hook returns.. + */ +export function useStickyRoomList(rooms: Room[]): StickyRoomListResult { + const [listState, setListState] = useState<{ index: number | undefined; roomsWithStickyRoom: Room[] }>({ + index: undefined, + roomsWithStickyRoom: rooms, + }); + + const updateRoomsAndIndex = useCallback( + (newRoomId?: string, isRoomChange: boolean = false) => { + setListState((current) => { + const activeRoomId = newRoomId ?? SdkContextClass.instance.roomViewStore.getRoomId(); + const newActiveIndex = getIndexByRoomId(rooms, activeRoomId); + const oldIndex = current.index; + const { newIndex, newRooms } = getRoomsWithStickyRoom(rooms, oldIndex, newActiveIndex, isRoomChange); + return { index: newIndex, roomsWithStickyRoom: newRooms }; + }); + }, + [rooms], + ); + + // Re-calculate the index when the active room has changed. + useDispatcher(dispatcher, (payload) => { + if (payload.action === Action.ActiveRoomChanged) updateRoomsAndIndex(payload.newRoomId, true); + }); + + // Re-calculate the index when the list of rooms has changed. + useEffect(() => { + updateRoomsAndIndex(); + }, [rooms, updateRoomsAndIndex]); + + return { activeIndex: listState.index, rooms: listState.roomsWithStickyRoom }; +} diff --git a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx index 07421fc0b3..238de4b270 100644 --- a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx +++ b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx @@ -314,34 +314,51 @@ describe("RoomListViewModel", () => { }); }); - describe("active index", () => { - it("should recalculate active index when list of rooms change", () => { + describe("Sticky room and active index", () => { + function expectActiveRoom(vm: ReturnType, i: number, roomId: string) { + expect(vm.activeIndex).toEqual(i); + expect(vm.rooms[i].roomId).toEqual(roomId); + } + + it("active room and active index are retained on order change", () => { const { rooms } = mockAndCreateRooms(); - // Let's say that the first room is the active room initially - jest.spyOn(SdkContextClass.instance.roomViewStore, "getRoomId").mockImplementation(() => rooms[0].roomId); + + // Let's say that the room at index 5 is active + const roomId = rooms[5].roomId; + jest.spyOn(SdkContextClass.instance.roomViewStore, "getRoomId").mockImplementation(() => roomId); const { result: vm } = renderHook(() => useRoomListViewModel()); - expect(vm.current.activeIndex).toEqual(0); + expect(vm.current.activeIndex).toEqual(5); - // Let's say that a new room is added and that becomes active - const newRoom = mkStubRoom("bar:matrix.org", "Bar", undefined); - jest.spyOn(SdkContextClass.instance.roomViewStore, "getRoomId").mockImplementation(() => newRoom.roomId); - rooms.push(newRoom); + // Let's say that room at index 9 moves to index 5 + const room9 = rooms[9]; + rooms.splice(9, 1); + rooms.splice(5, 0, room9); act(() => RoomListStoreV3.instance.emit(LISTS_UPDATE_EVENT)); - // Now the active room should be the last room which we just added - expect(vm.current.activeIndex).toEqual(rooms.length - 1); + // Active room index should still be 5 + expectActiveRoom(vm.current, 5, roomId); + + // Let's add 2 new rooms from index 0 + const newRoom1 = mkStubRoom("bar1:matrix.org", "Bar 1", undefined); + const newRoom2 = mkStubRoom("bar2:matrix.org", "Bar 2", undefined); + rooms.unshift(newRoom1, newRoom2); + act(() => RoomListStoreV3.instance.emit(LISTS_UPDATE_EVENT)); + + // Active room index should still be 5 + expectActiveRoom(vm.current, 5, roomId); }); - it("should recalculate active index when active room changes", () => { + it("active room and active index are updated when another room is opened", () => { const { rooms } = mockAndCreateRooms(); + const roomId = rooms[5].roomId; + jest.spyOn(SdkContextClass.instance.roomViewStore, "getRoomId").mockImplementation(() => roomId); + const { result: vm } = renderHook(() => useRoomListViewModel()); + expectActiveRoom(vm.current, 5, roomId); - // No active room yet - expect(vm.current.activeIndex).toBeUndefined(); - - // Let's say that room at index 5 becomes active - const room = rooms[5]; + // Let's say that room at index 9 becomes active + const room = rooms[9]; act(() => { dispatcher.dispatch( { @@ -353,8 +370,76 @@ describe("RoomListViewModel", () => { ); }); - // We expect index 5 to be active now - expect(vm.current.activeIndex).toEqual(5); + // Active room index should change to reflect new room + expectActiveRoom(vm.current, 9, room.roomId); + }); + + it("active room and active index are updated when active index spills out of rooms array bounds", () => { + const { rooms } = mockAndCreateRooms(); + // Let's say that the room at index 5 is active + const roomId = rooms[5].roomId; + jest.spyOn(SdkContextClass.instance.roomViewStore, "getRoomId").mockImplementation(() => roomId); + + const { result: vm } = renderHook(() => useRoomListViewModel()); + expectActiveRoom(vm.current, 5, roomId); + + // Let's say that we remove rooms from the start of the array + for (let i = 0; i < 4; ++i) { + // We should be able to do 4 deletions before we run out of rooms + rooms.splice(0, 1); + act(() => RoomListStoreV3.instance.emit(LISTS_UPDATE_EVENT)); + expectActiveRoom(vm.current, 5, roomId); + } + + // If we remove one more room from the start, there's not going to be enough rooms + // to maintain the active index. + rooms.splice(0, 1); + act(() => RoomListStoreV3.instance.emit(LISTS_UPDATE_EVENT)); + expectActiveRoom(vm.current, 0, roomId); + }); + + it("active room and active index are retained when rooms that appear after the active room are deleted", () => { + const { rooms } = mockAndCreateRooms(); + // Let's say that the room at index 5 is active + const roomId = rooms[5].roomId; + jest.spyOn(SdkContextClass.instance.roomViewStore, "getRoomId").mockImplementation(() => roomId); + + const { result: vm } = renderHook(() => useRoomListViewModel()); + expectActiveRoom(vm.current, 5, roomId); + + // Let's say that we remove rooms from the start of the array + for (let i = 0; i < 4; ++i) { + // Deleting rooms after index 5 (active) should not update the active index + rooms.splice(6, 1); + act(() => RoomListStoreV3.instance.emit(LISTS_UPDATE_EVENT)); + expectActiveRoom(vm.current, 5, roomId); + } + }); + + it("active room index becomes undefined when active room is deleted", () => { + const { rooms } = mockAndCreateRooms(); + // Let's say that the room at index 5 is active + let roomId: string | undefined = rooms[5].roomId; + jest.spyOn(SdkContextClass.instance.roomViewStore, "getRoomId").mockImplementation(() => roomId); + + const { result: vm } = renderHook(() => useRoomListViewModel()); + expectActiveRoom(vm.current, 5, roomId); + + // Let's remove the active room (i.e room at index 5) + rooms.splice(5, 1); + roomId = undefined; + act(() => RoomListStoreV3.instance.emit(LISTS_UPDATE_EVENT)); + expect(vm.current.activeIndex).toBeUndefined(); + }); + + it("active room index is initially undefined", () => { + mockAndCreateRooms(); + + // Let's say that there's no active room currently + jest.spyOn(SdkContextClass.instance.roomViewStore, "getRoomId").mockImplementation(() => undefined); + + const { result: vm } = renderHook(() => useRoomListViewModel()); + expect(vm.current.activeIndex).toEqual(undefined); }); }); }); From e1970df70458419ce0649fa8f30b74a44ded34e8 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Fri, 21 Mar 2025 17:08:37 +0000 Subject: [PATCH 130/458] Add report room dialog button/dialog. (#29513) * Add report room dialog button/dialog. * Update copy * fixup tests / lint * Fix title in test. * update snapshot * Add unit tests for dialog * lint --- .../e2e/right-panel/right-panel.spec.ts | 14 +- .../with-leave-room-linux.png | Bin 27602 -> 28527 bytes res/css/_components.pcss | 1 + res/css/views/dialogs/_ReportRoomDialog.pcss | 16 + .../views/right_panel/_RoomSummaryCard.pcss | 4 +- .../views/dialogs/ReportRoomDialog.tsx | 95 +++++ .../views/right_panel/RoomSummaryCard.tsx | 31 +- src/i18n/strings/en_EN.json | 7 + .../views/dialogs/ReportRoomDialog-test.tsx | 66 ++++ .../ReportRoomDialog-test.tsx.snap | 100 +++++ .../RoomSummaryCard-test.tsx.snap | 345 ++++++++++++------ 11 files changed, 556 insertions(+), 123 deletions(-) create mode 100644 res/css/views/dialogs/_ReportRoomDialog.pcss create mode 100644 src/components/views/dialogs/ReportRoomDialog.tsx create mode 100644 test/unit-tests/components/views/dialogs/ReportRoomDialog-test.tsx create mode 100644 test/unit-tests/components/views/dialogs/__snapshots__/ReportRoomDialog-test.tsx.snap diff --git a/playwright/e2e/right-panel/right-panel.spec.ts b/playwright/e2e/right-panel/right-panel.spec.ts index cc03963801..44b051c987 100644 --- a/playwright/e2e/right-panel/right-panel.spec.ts +++ b/playwright/e2e/right-panel/right-panel.spec.ts @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024, 2025 New Vector Ltd. Copyright 2022 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial @@ -10,6 +10,7 @@ import { type Locator, type Page } from "@playwright/test"; import { test, expect } from "../../element-web-test"; import { checkRoomSummaryCard, viewRoomSummaryByName } from "./utils"; +import { isDendrite } from "../../plugins/homeserver/dendrite"; const ROOM_NAME = "Test room"; const ROOM_NAME_LONG = @@ -133,6 +134,17 @@ test.describe("RightPanel", () => { await page.getByLabel("Room info").nth(1).click(); await checkRoomSummaryCard(page, ROOM_NAME); }); + test.describe("room reporting", () => { + test.skip(isDendrite, "Dendrite does not implement room reporting"); + test("should handle reporting a room", async ({ page, app }) => { + await viewRoomSummaryByName(page, app, ROOM_NAME); + await page.getByRole("menuitem", { name: "Report room" }).click(); + const dialog = await page.getByRole("dialog", { name: "Report Room" }); + await dialog.getByLabel("reason").fill("This room should be reported"); + await dialog.getByRole("button", { name: "Send report" }).click(); + await expect(page.getByText("Your report was sent.")).toBeVisible(); + }); + }); }); test.describe("in spaces", () => { diff --git a/playwright/snapshots/right-panel/right-panel.spec.ts/with-leave-room-linux.png b/playwright/snapshots/right-panel/right-panel.spec.ts/with-leave-room-linux.png index a2bc63aaf4194ebb9da29ccfa94e32cf33de9623..63a49dc751266cb362eaea707378a70d114f5d52 100644 GIT binary patch literal 28527 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 z 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%0Db+thfJT=gOie)akEK^2 ztjFJ&14bO8|Kt1B4)guu{0Gs*TdA>6iosP)Xv5 zAEV#vXnRQ)-kgH`q{v2oIz)^dYGP7d5e1qX>UnPSnvK>8yZy;-xYxL~wj5A3SCVD$ zxPwV2VXhl^<(BOdV#&8$ag-Q0sH{%&9viu`j;?>JvxVA2n$$#_kZ|wQjQUvdkXve7 z(UO6h$KvWca8U5>KwK5n3-oeiM0G{arQ?5jfwu7m7tT=O${GvH&BSFfM9}l(q6U`- z@GmfaS+cUZoIqm|g12*$l6aDT)i>4$WjgRDEc6o;v;K|C>CC-F;FDD+nlfFFB!!bw>J2jYIdvGA)r&*HfL1LXDxjD( z#H}&fnj5=ozno6Rn_O~(TRy$Lc#Bue4`=njTdxB6u0$uCHjUmE5I)c$XV%p=d@e%# ze00ofLrvHuOozzuePhFj&zLRu_1xm(AndKxEUf6-b}Nds;7bRap=oadf>@$TN+dA9 zmW6dd1)ZycDR57A_qR2-Q|S>?u;tSk=WF?W*6+ln3Bxum`z6>N^p!A(b9Viyz+(w= zwvW2hac>#Ek0n{Bak=!iAhc62)Y8CA@}@FeItkbpygI1ZTeHjms5Ll%dQOG~16?h; zqAf&24d8Mp3}IT%rpJJDdy36vAyiaFV(_T6Omv?|lf(v#y%MbLm?4&i&~!ICshag` z(Ete5tPMZ<ZlIv_h{dB+dP^*e< zrnB?unz!Kj)KAk{!MMWYCRW}A|G*y)k>z^WAeDmP59T>2IIg*|g{e?Tg@CVWJ-oG=IclX4&wUFn-ynBKO$VtC+T@fjzQIL>{3y)^ovwg)0U>8R!ka`;Mp3PI=0gRylqu#a7AaupOB z#{-LsicSPrgMKO#RsRUaz6Y)I|F5n3e-l4KR(`D?)KF?d!jqB`L|o)5<~Yv-Z>5{A z;=bemD;UhfEcar<^kG_IUs$X_C;s;Sg-=%J;GdXKM_OxLbDzrV2N&Aw*J-0;Vq!9@ z%frLd^4z0_86zsnQRl@?G8otVmu%(qWqw5FK|A-hJWASWfA79~W%J10JG!r*X016e z8LuIvLGDo4R@(iT#cSX&;HMF~K#+*bJvxw}|J;7F`rBe@d#iu)UXA*0<(X~iW-+8P zn7X*i>jw#rUhD}krw*|r2fd=W$jTq4RZ?Q2L<2Ou)#+UYIAvyG*SE$uwG&&y6>sW2 z6XXA{z~nxtdSx5w>ei9jO)l*ASEt`#PjSh5|0c2GuXX={4v3!>c@g3;um6*wiwHS8-z$aNr>F*&iZ3PRV}}fu-?8*lCk3ZrZj3$ zmB^EKQG|^%BgS;2x!^Z?+Ry6b*5J>WpgEKCh^bq7 zs%7soz`1Q%uKr06hvJN>2YWfgV@F;f|Bw-Sr*5s*&1t{+>GDwQuge+ptKC0U5B*K z#8QXK|B8E*v75YG`S<5qL6FgqKTW@s(=?<|w&p*F&TUC~6T7dKra>mLL{k>}yVy z#MJ}Hutw$e$2ikj`i-wy+_Dv!Jiy9G!o_u>*~H<&YjM)^fvd^yAD!&9fHm6RWu6X+ ziHt_Yb7B%WZ+DT&GP>O{BQq6Z5bCZju%u36zlBBl$z5@T~EnS8kDDT z?kjE;Rkq0xLypAQ&ChNZY!H>621J7gzduz*8jDkD7N5%T1{*iuOr?Gx4d%-9t$wsp zNb1`>f?Cn^2LN1Uhn#I&-+)t&Y!i;4qc91B+$a}EkT4J0S$u0V4-ZxhGCg?l2!LH-!AI<_+(=vmw2x1gq?Z=Nm=POjj0{Zt^r}&( z9J`a@ze^%s&Ccx3I z#V2G)7?!e(c+@#c4vy@|SjokvEH;A_p^n9c!8%ik{{(YDD&HZ-q89$ zWfSQA0L`{UdudQ&`^pIPZ0=}r3i3VMkI!VJO+i5cw(ViGKIn|q*^yjRU7eCjvMDV7 ze7pi79dW)RbB`O9uZX%BnyJ};?<=z~V3;GXd{WEIHqL67n|F*5$F_h+q)f0kz_!x( zWJ7#Lcqgz}E_1r=8@l5|!RcT%{|YOuvLxf-bJ)3!xNtpiA*x1;97mn4ma6H9c+?da zJ*f5H;{NP=6AP?|>KvIb1QvO_KTDGi;@}y7&BF0Dh{%QmW*+*!B8%hW$`URfAHHMz zf7dkLFO4|3lb1gViB6XH`B|5Lc${_8uW8&I>n*7Y+R-DVSfwc_R|HR6*SHYQc+Fkt zY3xp0f}>f=cYmzP3Rka45AB{E>AhM}5LUfD`^_*s%td)8x6tqnW!^`&)^AaNo!(kN ztt`HP&2i)Gj!gD$KUEa7v@=nw2`ATQRiSb0{4-07=0GQNg*9rj?42vzFJ2d)5c#p= zjSBDE_5|Kz+g?ax_Jnm!l;(TF#tVL-mgRt{auBhDd6U*YQ zKfNSQPAknOyD_UCZqK@-yn=#-e3tdq2#z@Ubstmp=+M6KIIH*`C*l)-&KgCnn(jscscBh3w4DZzgM)ArLJ6N-tvI zYj0z^h$=E5_Wg3U7s3VGK@dkAZG*Kr?L|~OGxK<@wSA{o%7k&eZoB~;r;~-Fa}_2q zpB1Gn#%d^qWw-h1%4Ih+Chi*i`=@z#&U86bj3hs+fIc(AKNo0`U zSw=QN&keBu?(pD1s+oxjdBbsrikTUF<%7h+a?gg2`JRgl-hXFjXH>;)+&R8=HGTDD zB}2qS0|bh{dT^MxtrV2p3y;i)i+x>vNxBk^2WisR@Gh0GB8-F5>xjG5Xf~{NS(>%A zr}Lrw4GkUmeQcvTKt>HqIE`*54luz0dPDvEaGLsuWm9{_pSIt|-lp~a$S2qJx;-H$ zsg$|B3`AlDK29pAtE<~W|B!O4ZHKzz_tkUV&^fqP!2x4xX0KaY-kZ$U*T?-55=K&# z6&H!!t7jMYqe3JXZ+*OgZ7&EFwX}$^vg+N+>-)A(?YFp6BMHWK!Ulzk8RNoP4Ir2( zp)-NeA(Cu9;|fYc@zl35EZ<7aJU^eba+7Ow(l@ReFiRH41eZ{c!&W+;|3U3E^|&ts zuTi*Zvs0qzv+sww?}FB{rLWW`Ffu!jy=yIwqcE<>XxF02j!6?$bF9GmMFMHK>xF{O z20zRFEcPsy^?`%RNN%`zDYQ`3IvQy&MEcD3T&F9GG10aLrN|bMOf-On01bf6i{`iP z1{RP+r@Tj@ z6tpc!3wQNVL1xPVYu=&m|Mp@2{oafO_>%aJ75#G`3%#&rS4iF1-!R#~HFhrfStZdT zZ)v|$Lv7`>kBwBHtt6Z^f)Qa`;r2_#)2B0QT;?M?uxLWz7tnj?c6d;&1G)V`i5c^9 zBSJ?&8EXY0%|{%&(Cqa zM-veq-l!dp`(Q7ByZon^DVZQ^aBwA_f}EkS>gN898SOWnWxR(}4ru4h5^6mO!t!1w zFp#teEtk?#eK%&Eim0Ql#)RbC*9ApMgF)5t@uqUJe|Q;w<-6%p^5-~jq_Et;uIa(W z_{CuZR4N+ST%n_*(}6(UPBDcoYk=%&Yr)0trKP4rjE0^alx27ET1K{}c~#u^l>>!$ z<3QW>k0=jS2@wG~I))q!eiW!a9PHc>taEU5? z(~pg9kO{I`*!w&2LN>QQtqB3B3J%c4!s_0!GBYLDs%s<=_8%;gsDHBxTj~KRf1SuQAq>C0*9FU=hHuqH2WRp= zS*)F%{oH|2%I4DsTZ|qrG+X?wq+QR6SVh&jyFUNAJdiXpL7M}d&092%WC}VM8^5RH|5a3LvsCfnezIkyI>U7ev)IF@%AN4Sk)!`$OB~u8qa-sW%)-FOZFVq} ze56kh?VKX8e7jXN*|0lX8nJnHw=S1-sG6(nB=9^uZpW;(=}pj-?5(DASzdASdFO$O z>uZ-cW{kt`{mer>ev}=?#MEm=GKwr36j8m)xz1H~x-{VSEkfk zekC_~heZ4sUFUz@ZBZbyBnMkl{8yzhL1ns{q~zt#R|;Rd#Qk0cmUb1FJen=JyUEE7 zaur@8Vv$UBCw=p{Mi}kKz`$5d7kw%tG?=;^-uXMpp#HH!yCG{kl)zK6ulaqnZNgeT z+r16P-e(pruBw%0ufx)!BMT#^NB5I5ZtiDa5F#cSGEh_Fc5^Jsu@y{6r54qU;Dm-PRJ%;y z?PLkg|D0{}Cf^Se5NUBB@bkg}N+3u)yu4tw12>vvR$UVNsqg)K(4Qmnr zIof6{HE26iXeLXTEr{ZMN7frU`;`l)3rvWHAgHIh43mp!J2}V<5zKI;Ou2F3+ zB;&sy=k5gntk?gX5s+$UY>Z0*b^kB6kc`SS66PeTB>GgM0XFb3o08AsZ$J}rem9cK zg?ZfSe(uH0eA5cEv|Jmf4)X2gv&cJMM@Q3LdNh)gm1P8ebVsinQ2}dPSK-RVZ-XdI z(us+vt_s^6@+JNkXuy9%2>ct?@v6RNV0h8Z)9@Yg6AjU=6vI6NkwbUDm;nNX_(>l+0{paxf8`7aS-Z0aeUYw1jlvG(6lgnm zkcO%ar+eF_EUQ2CCxTnPXpT38XiQJ9u3*LU^Cx0eyo@uK2wdk$y=Eme_M&9bJw*bGP#RXL8` zFvK+!hodB)vU1}n9MT6AEYUQ07wQe9MGq@ z%nzRwTftK$qwskvDtph6;2@W3utXu0`zpUqKYK}s!OA0 zodeeF#b)#ke40vabGnJ5r$a+or;?gIV7_RPRB3s!QOQh{K?>$dHLaw6EsDiQyHdh` z`10d;ehsJE8|B)|E7;^6+ll+8N}AA-@AX1;Jtm~Vq{NOI-|+=!bWtbXFuR8WXm@iCC{u|UG5a$ zYrIvMPr?evWZE2^RIh=kCk}t+$Pq(Bu$ib9>36z~*0*;el_sPpG}3y}zG?nY<1%6W zMU&|(86Nrld+?u`fMpXG1$P?HHvo`bWS5`;@AjVYx3faC#K}{gmD^w`cM)F(kJTLj z1i7&PV}64C=9Rq6AhZ^xV*vqBtA^6+zrS*u3WS@nwzN}KRk~K3)FF|7*Ul~xeRw9A za$8x$qn*$D z0Huw?_wy`qmZyVV=3SG8VgdfrUMcWsz?71Mc%O_XM_WLLiSTSaBY)&tyAR1wx1x_W z0I+H*uBcu<%wc1dde6Rv@L~yb90?^ zE(v>`n(3uHCW`fG0VX6zf&L6Rqik>VxgAHto*r4N~=kb}4rs z84cWi=!s-U^AhZ+lY`+Los86P1{lYLj;Rrax0{(?PK91=&9&Q;sRF=&@re*MuWSX2 z2ImTaTf7TJnLMtC_Owm=$(%NCzPoB#{y6v=r4rBOuJs z_Jv%TM=zfc_WXE%RUz54N2quAPQ$1CD8N`D;ciRXYe1o*dEZep))0}kSk~ovWMq*> z6@(s|rSZ1QP>L^zE(C2a%Pd2ooVAsS1huu^;IVl<_@CNc+`kBaJ-o|K0Y8yEOU)+{ zRJOPAghrUg_L{)H!@*YvVBNF7gS$?N)@y~ zyeoH1qL|U#?CAr#hR{QAcAP?N^&QsV_p~t~=kyY-W9!ua-An@!x+LiXmZilloEBoo z(pkj%XjD_NIj|%HSxnTeg_%)=E9ko?%agCDA{i8np>x(F&8%d?JdxawXq%bT|VY!EuC!Z z`{Qd1_|Js1JGggqlL@Q}Sz)$MI2<8ADeO@iUe9_APuFJ6O?4{_r8*2u^Vc8!TJfCa z&X>Ac7c-fzF(*MLsQxNYvgGl_XXgUGoF}>N77OiIH2l4Kda_sZvLUHh7~86_b4wWX zgv)Bgzue;ps%s18uK#DYp5m)p7vcCU6<{EzeY!yQKUjTL_@cA(!4Ox^Z!aw=dFQtA zQu4_K;8Q+!+?cJ;LJ=Xl-MhAC<{S<8sbIVHEL&p_Y3_CK{Z^|4*5aHor_j!FtyAvb z7vwcQ6FLlGb#jZ=_xgxl^&@hZ#o4e=Z*Dy6}((zGmV ze_ag!VFA_>G{1F@Oy&Wuv2`tE{)JNp5^ONjsbwvFu{QsRl;QS}5MHV3HsWt)S~AR{ z5|8Ua!_bhKB4rn~&tBR}_(mHfW;Zt&{5*2y2Xc7Kk#8mEeqo+%WUwrr_EJ4G+mX03 zCD2_?NuQBfT=d4af%QkrL-Ar;$&aWT3J18MRo>iRsJe}+=_=+= z7Zp-`ISIUVAa0`p3Un7nT5&*kBfmU+3So+P&fhNuL1Hv6To$4jk{_pkiWt+QrO`)8 zb36qr#6HadsfRUSfqmDBNv61)8A=I^EgX)XN>1LU%oGs@dtUnX+|n9`gyj`!*Rz7^tylsY->7q!pgkp1;L+W4x){^})*z!GonxSn@)Jqe-UEV>xIc=O)y)|%HynTuIlegzerCMFDrXd{ zUTJ;lqPy?SS{K`m=<-~$OCS+E3-lm(=flo_ub5L`zX)a_@J9rIx)Yv5i>f~9Sgs0U zBh=)q2`ca>3GEojA7aOGEy872by%~?zMrMJl#Az6($KIjkCBcAq}le5Js}N0L7dZ5 zk9_uw^c9su5j1aE6|S6R*aKGj(m@rUdibtMH>YN29^vd((iUCYiV`Wx90VyfY*1r( z$9I|~6NvdcI%b++Su=!5?+t_>^g9e{8pfZ|TJ}NM#lIlK4Xh~{lo|F6cXCOY<16S| zA@!tI0FAfnkn;ba;IwxDpUtu}LbE2=T{*X~6ki-zR7=pRM~(+c5D}6nESqM-1S>vO znolpPpU?UquB=9x3~cC1j&N#b-A}V$xGtp4zE0kPtOq+Rszralym@w8r&>fpfNzW_(JuJoQ z&B?VAuIb^X?tXod=NattLf#+PTRnV6w=q9uYxyIl5u`TnWzAvX$FhhBWY4Dj$Y~6G z7%My}jn+7N8gV{2$PwJR^|_E9$m?E0mTQOHPp_-%wph(Lb62u894kr&HHf{4nvYrU zWu-4sPObbkiC>fF5wi5zPj>gu!^JJFm5c7!h^b`?I37 z`4S!LX6IO{|4L{b0)MXK+(J$sN_cmJM|k#zJ&g8RMmd_1i8Gv9VmDC?ir~j?5(Q4! z?h*x%ud#Dq!-~7d^?Zc?&-RZ0CX@Xqx=H?@pPPF@S{-0*c*!eWgK4z@SxH5SQgOq8 F{{xXDTPpwn literal 27602 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�AYY-{zt)V=Uus-dxyxSNpfs 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 diff --git a/res/css/_components.pcss b/res/css/_components.pcss index bd927c9843..9df9dcb8cb 100644 --- a/res/css/_components.pcss +++ b/res/css/_components.pcss @@ -152,6 +152,7 @@ @import "./views/dialogs/_ModalWidgetDialog.pcss"; @import "./views/dialogs/_PollCreateDialog.pcss"; @import "./views/dialogs/_RegistrationEmailPromptDialog.pcss"; +@import "./views/dialogs/_ReportRoomDialog.pcss"; @import "./views/dialogs/_RoomSettingsDialog.pcss"; @import "./views/dialogs/_RoomSettingsDialogBridges.pcss"; @import "./views/dialogs/_RoomUpgradeDialog.pcss"; diff --git a/res/css/views/dialogs/_ReportRoomDialog.pcss b/res/css/views/dialogs/_ReportRoomDialog.pcss new file mode 100644 index 0000000000..7323ac65c9 --- /dev/null +++ b/res/css/views/dialogs/_ReportRoomDialog.pcss @@ -0,0 +1,16 @@ +/* +Copyright 2025 New Vector 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. +*/ + +.mx_ReportRoomDialog { + textarea { + font: var(--cpd-font-body-md-regular); + border: 1px solid var(--cpd-color-border-interactive-primary); + background: var(--cpd-color-bg-canvas-default); + border-radius: 0.5rem; + padding: var(--cpd-space-3x) var(--cpd-space-4x); + } +} diff --git a/res/css/views/right_panel/_RoomSummaryCard.pcss b/res/css/views/right_panel/_RoomSummaryCard.pcss index eb3b14579f..3c1c07677c 100644 --- a/res/css/views/right_panel/_RoomSummaryCard.pcss +++ b/res/css/views/right_panel/_RoomSummaryCard.pcss @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024, 2025 New Vector Ltd. Copyright 2020 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial @@ -101,6 +101,6 @@ Please see LICENSE files in the repository root for full details. margin: $spacing-12 0 $spacing-4; } -.mx_RoomSummaryCard_leave { +.mx_RoomSummaryCard_bottomOptions { margin: 0 0 var(--cpd-space-8x); } diff --git a/src/components/views/dialogs/ReportRoomDialog.tsx b/src/components/views/dialogs/ReportRoomDialog.tsx new file mode 100644 index 0000000000..ff4e96ea97 --- /dev/null +++ b/src/components/views/dialogs/ReportRoomDialog.tsx @@ -0,0 +1,95 @@ +/* +Copyright 2025 New Vector 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 ChangeEventHandler, useCallback, useState } from "react"; +import { Root, Field, Label, InlineSpinner, ErrorMessage } from "@vector-im/compound-web"; + +import { _t } from "../../../languageHandler"; +import SdkConfig from "../../../SdkConfig"; +import Markdown from "../../../Markdown"; +import BaseDialog from "./BaseDialog"; +import DialogButtons from "../elements/DialogButtons"; +import { MatrixClientPeg } from "../../../MatrixClientPeg"; + +interface IProps { + roomId: string; + onFinished(complete: boolean): void; +} + +/* + * A dialog for reporting a room. + */ + +export const ReportRoomDialog: React.FC = function ({ roomId, onFinished }) { + const [error, setErr] = useState(); + const [busy, setBusy] = useState(false); + const [sent, setSent] = useState(false); + const [reason, setReason] = useState(""); + const client = MatrixClientPeg.safeGet(); + + const onReasonChange = useCallback>((e) => setReason(e.target.value), []); + const onCancel = useCallback(() => onFinished(sent), [sent, onFinished]); + const onSubmit = useCallback(async () => { + setBusy(true); + try { + await client.reportRoom(roomId, reason); + setSent(true); + } catch (ex) { + if (ex instanceof Error) { + setErr(ex.message); + } else { + setErr("Unknown error"); + } + } finally { + setBusy(false); + } + }, [roomId, reason, client]); + + const adminMessageMD = SdkConfig.getObject("report_event")?.get("admin_message_md", "adminMessageMD"); + let adminMessage: JSX.Element | undefined; + if (adminMessageMD) { + const html = new Markdown(adminMessageMD).toHTML({ externalLinks: true }); + adminMessage =

    ; + } + + return ( + onFinished(sent)} + title={_t("report_room|title")} + contentId="mx_ReportEventDialog" + > + {sent &&

    {_t("report_room|sent")}

    } + {!sent && ( + +

    {_t("report_room|description")}

    + {adminMessage} + + + + +
    + + + + +
    + +
    +
    +
    +
    +`; diff --git a/test/unit-tests/components/views/dialogs/__snapshots__/ReportRoomDialog-test.tsx.snap b/test/unit-tests/components/views/dialogs/__snapshots__/ReportRoomDialog-test.tsx.snap index 63f6f3ee10..44edfa9130 100644 --- a/test/unit-tests/components/views/dialogs/__snapshots__/ReportRoomDialog-test.tsx.snap +++ b/test/unit-tests/components/views/dialogs/__snapshots__/ReportRoomDialog-test.tsx.snap @@ -43,7 +43,7 @@ exports[`ReportRoomDialog displays admin message 1`] = ` /> Report this room to your account provider. If the messages are encrypted, your admin will not be able to read them. @@ -71,7 +71,7 @@ exports[`ReportRoomDialog displays admin message 1`] = ` class="mx_SettingsFlag_label" >
    Leave room
    @@ -79,7 +79,7 @@ exports[`ReportRoomDialog displays admin message 1`] = `
    with live location disabled goes to labs flag scr class="mx_SettingsFlag_label" >
    Enable live location sharing
    @@ -34,7 +34,7 @@ exports[` with live location disabled goes to labs flag scr
    ", () => { }); it("renders join and reject action buttons correctly", () => { - const component = getComponent({ inviterName, room, onJoinClick, onRejectClick }); - expect(getActions(component)).toMatchSnapshot(); - }); - - it("renders reject and ignore action buttons when handler is provided", () => { - const onRejectAndIgnoreClick = jest.fn(); - const component = getComponent({ - inviterName, - room, - onJoinClick, - onRejectClick, - onRejectAndIgnoreClick, - }); + const component = getComponent({ inviterName, room, onJoinClick, onDeclineClick: onRejectClick }); expect(getActions(component)).toMatchSnapshot(); }); it("renders join and reject action buttons in reverse order when room can previewed", () => { // when room is previewed action buttons are rendered left to right, with primary on the right - const component = getComponent({ inviterName, room, onJoinClick, onRejectClick, canPreview: true }); + const component = getComponent({ + inviterName, + room, + onJoinClick, + onDeclineClick: onRejectClick, + canPreview: true, + }); expect(getActions(component)).toMatchSnapshot(); }); it("joins room on primary button click", () => { - const component = getComponent({ inviterName, room, onJoinClick, onRejectClick }); + const component = getComponent({ inviterName, room, onJoinClick, onDeclineClick: onRejectClick }); fireEvent.click(getPrimaryActionButton(component)!); expect(onJoinClick).toHaveBeenCalled(); }); it("rejects invite on secondary button click", () => { - const component = getComponent({ inviterName, room, onJoinClick, onRejectClick }); + const component = getComponent({ inviterName, room, onJoinClick, onDeclineClick: onRejectClick }); fireEvent.click(getSecondaryActionButton(component)!); expect(onRejectClick).toHaveBeenCalled(); @@ -337,18 +331,6 @@ describe("", () => { const component = getComponent({ inviterName, room }); expect(getMessage(component)).toMatchSnapshot(); }); - - it("renders join and reject action buttons with correct labels", () => { - const onRejectAndIgnoreClick = jest.fn(); - const component = getComponent({ - inviterName, - room, - onJoinClick, - onRejectAndIgnoreClick, - onRejectClick, - }); - expect(getActions(component)).toMatchSnapshot(); - }); }); }); @@ -364,7 +346,7 @@ describe("", () => { async () => { const onJoinClick = jest.fn(); const onRejectClick = jest.fn(); - const component = getComponent({ ...props, onJoinClick, onRejectClick }); + const component = getComponent({ ...props, onJoinClick, onDeclineClick: onRejectClick }); await waitFor(() => expect(getPrimaryActionButton(component)).toBeTruthy()); if (expectSecondaryButton) expect(getSecondaryActionButton(component)).toBeFalsy(); fireEvent.click(getPrimaryActionButton(component)!); diff --git a/test/unit-tests/components/views/rooms/__snapshots__/RoomPreviewBar-test.tsx.snap b/test/unit-tests/components/views/rooms/__snapshots__/RoomPreviewBar-test.tsx.snap index e89552dd85..dc44db8d21 100644 --- a/test/unit-tests/components/views/rooms/__snapshots__/RoomPreviewBar-test.tsx.snap +++ b/test/unit-tests/components/views/rooms/__snapshots__/RoomPreviewBar-test.tsx.snap @@ -339,34 +339,6 @@ exports[` with an invite without an invited email for a dm roo
    `; -exports[` with an invite without an invited email for a dm room renders join and reject action buttons with correct labels 1`] = ` -
    -
    - Start chatting -
    -
    - Reject & Ignore user -
    -
    - Reject -
    -
    -`; - exports[` with an invite without an invited email for a non-dm room renders invite message 1`] = `
    with an invite without an invited email for a non-dm role="button" tabindex="0" > - Reject + Decline
    `; @@ -435,7 +407,7 @@ exports[` with an invite without an invited email for a non-dm role="button" tabindex="0" > - Reject + Decline
    with an invite without an invited email for a non-dm
    `; - -exports[` with an invite without an invited email for a non-dm room renders reject and ignore action buttons when handler is provided 1`] = ` -
    -
    - Accept -
    -
    - Reject & Ignore user -
    -
    - Reject -
    -
    -`; diff --git a/test/unit-tests/components/views/settings/__snapshots__/Notifications-test.tsx.snap b/test/unit-tests/components/views/settings/__snapshots__/Notifications-test.tsx.snap index 25d06ffc23..f6fcc63262 100644 --- a/test/unit-tests/components/views/settings/__snapshots__/Notifications-test.tsx.snap +++ b/test/unit-tests/components/views/settings/__snapshots__/Notifications-test.tsx.snap @@ -10,22 +10,22 @@ exports[` main notification switches renders only enable notifi class="mx_SettingsFlag_label" >
    Enable notifications for this account
    Turn off to disable notifications on all your devices and sessions
    main notification switches renders only enable notifi >