diff --git a/res/img/attach.png b/res/img/attach.png deleted file mode 100644 index 1bcb70045d..0000000000 Binary files a/res/img/attach.png and /dev/null differ diff --git a/res/img/button-text-block-quote-on.svg b/res/img/button-text-block-quote-on.svg deleted file mode 100644 index f8a86125c9..0000000000 --- a/res/img/button-text-block-quote-on.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - 3B24B8C7-64BE-4B3E-A748-94DB72E1210F - Created with sketchtool. - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/button-text-block-quote.svg b/res/img/button-text-block-quote.svg deleted file mode 100644 index d70c261f5d..0000000000 --- a/res/img/button-text-block-quote.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - BFC0418B-9081-4789-A231-B75953157748 - Created with sketchtool. - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/button-text-bold-on.svg b/res/img/button-text-bold-on.svg deleted file mode 100644 index 161e740e90..0000000000 --- a/res/img/button-text-bold-on.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - 01F3F9B2-8F38-4BAF-A345-AECAC3D88E79 - Created with sketchtool. - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/button-text-bold.svg b/res/img/button-text-bold.svg deleted file mode 100644 index 0fd0baa07e..0000000000 --- a/res/img/button-text-bold.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - 9BC64A5B-F157-43FF-BCC4-02D30CDF520B - Created with sketchtool. - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/button-text-bulleted-list-on.svg b/res/img/button-text-bulleted-list-on.svg deleted file mode 100644 index d4a40e889c..0000000000 --- a/res/img/button-text-bulleted-list-on.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - 654917CF-20A4-49B6-B0A1-9875D7B733C8 - Created with sketchtool. - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/button-text-bulleted-list.svg b/res/img/button-text-bulleted-list.svg deleted file mode 100644 index ae3e640d8e..0000000000 --- a/res/img/button-text-bulleted-list.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - B7D94619-44BC-4184-A60A-DBC5BB54E5F9 - Created with sketchtool. - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/button-text-deleted-on.svg b/res/img/button-text-deleted-on.svg deleted file mode 100644 index 2914fcabe6..0000000000 --- a/res/img/button-text-deleted-on.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - 69B11088-0F3A-4E14-BD9F-4FEF4115E99B - Created with sketchtool. - - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/button-text-deleted.svg b/res/img/button-text-deleted.svg deleted file mode 100644 index 5f262dc350..0000000000 --- a/res/img/button-text-deleted.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - A34F2223-34C6-46AE-AA47-38EC8984E9B3 - Created with sketchtool. - - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/button-text-formatting.svg b/res/img/button-text-formatting.svg deleted file mode 100644 index d697010d40..0000000000 --- a/res/img/button-text-formatting.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - diff --git a/res/img/button-text-inline-code-on.svg b/res/img/button-text-inline-code-on.svg deleted file mode 100644 index 8d1439c97b..0000000000 --- a/res/img/button-text-inline-code-on.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - B76754AB-42E6-48D2-9443-80CBC0DE02ED - Created with sketchtool. - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/button-text-inline-code.svg b/res/img/button-text-inline-code.svg deleted file mode 100644 index 24026cb709..0000000000 --- a/res/img/button-text-inline-code.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - 4CAFF494-61AE-4916-AFE8-D1E62F7CF0DE - Created with sketchtool. - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/button-text-italic-on.svg b/res/img/button-text-italic-on.svg deleted file mode 100644 index 15fe588596..0000000000 --- a/res/img/button-text-italic-on.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - 116426C2-0B55-480E-92B3-57D4B3ABAB90 - Created with sketchtool. - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/button-text-italic.svg b/res/img/button-text-italic.svg deleted file mode 100644 index b5722e827b..0000000000 --- a/res/img/button-text-italic.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - 9FBC844D-96CF-4DCB-B545-FCD23727218B - Created with sketchtool. - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/button-text-numbered-list-on.svg b/res/img/button-text-numbered-list-on.svg deleted file mode 100644 index 869a2c2cc2..0000000000 --- a/res/img/button-text-numbered-list-on.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - 294F929B-31AA-4D0C-98B3-9CA96764060D - Created with sketchtool. - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/button-text-numbered-list.svg b/res/img/button-text-numbered-list.svg deleted file mode 100644 index 8e5b8b87b6..0000000000 --- a/res/img/button-text-numbered-list.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - F0F58459-A13A-48C5-9332-ABFB96726F05 - Created with sketchtool. - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/button-text-underlined-on.svg b/res/img/button-text-underlined-on.svg deleted file mode 100644 index 870be3ce6a..0000000000 --- a/res/img/button-text-underlined-on.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - FD84FF7C-43E4-4312-90AB-5A59AD018377 - Created with sketchtool. - - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/button-text-underlined.svg b/res/img/button-text-underlined.svg deleted file mode 100644 index 26f448539c..0000000000 --- a/res/img/button-text-underlined.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - 13E7EE68-9B16-4A3D-8F9F-31E4BAB7E438 - Created with sketchtool. - - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/call.png b/res/img/call.png deleted file mode 100644 index a7805e0596..0000000000 Binary files a/res/img/call.png and /dev/null differ diff --git a/res/img/cancel-black.png b/res/img/cancel-black.png deleted file mode 100644 index 87dcfd41a8..0000000000 Binary files a/res/img/cancel-black.png and /dev/null differ diff --git a/res/img/cancel-black2.png b/res/img/cancel-black2.png deleted file mode 100644 index a928c61b09..0000000000 Binary files a/res/img/cancel-black2.png and /dev/null differ diff --git a/res/img/cancel.png b/res/img/cancel.png deleted file mode 100644 index 2bda8ff5bf..0000000000 Binary files a/res/img/cancel.png and /dev/null differ diff --git a/res/img/chevron-left.png b/res/img/chevron-left.png deleted file mode 100644 index efb0065de9..0000000000 Binary files a/res/img/chevron-left.png and /dev/null differ diff --git a/res/img/chevron-right.png b/res/img/chevron-right.png deleted file mode 100644 index 18a4684e47..0000000000 Binary files a/res/img/chevron-right.png and /dev/null differ diff --git a/res/img/chevron.png b/res/img/chevron.png deleted file mode 100644 index 81236f91bc..0000000000 Binary files a/res/img/chevron.png and /dev/null differ diff --git a/res/img/close-white.png b/res/img/close-white.png deleted file mode 100644 index d8752ed9fe..0000000000 Binary files a/res/img/close-white.png and /dev/null differ diff --git a/res/img/create-big.png b/res/img/create-big.png deleted file mode 100644 index b7307a11c7..0000000000 Binary files a/res/img/create-big.png and /dev/null differ diff --git a/res/img/create-big.svg b/res/img/create-big.svg deleted file mode 100644 index 2450542b63..0000000000 --- a/res/img/create-big.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - icons_create_room - Created with sketchtool. - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/create.png b/res/img/create.png deleted file mode 100644 index 2d6107ac50..0000000000 Binary files a/res/img/create.png and /dev/null differ diff --git a/res/img/delete.png b/res/img/delete.png deleted file mode 100644 index 8ff20a116d..0000000000 Binary files a/res/img/delete.png and /dev/null differ diff --git a/res/img/directory-big.png b/res/img/directory-big.png deleted file mode 100644 index 03cab69c4a..0000000000 Binary files a/res/img/directory-big.png and /dev/null differ diff --git a/res/img/download.png b/res/img/download.png deleted file mode 100644 index 1999ebf7ab..0000000000 Binary files a/res/img/download.png and /dev/null differ diff --git a/res/img/e2e/blacklisted.svg b/res/img/e2e/blacklisted.svg deleted file mode 100644 index ac99d23f05..0000000000 --- a/res/img/e2e/blacklisted.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/res/img/e2e/lock-verified.svg b/res/img/e2e/lock-verified.svg deleted file mode 100644 index 819dfacc49..0000000000 --- a/res/img/e2e/lock-verified.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/res/img/e2e/lock-warning.svg b/res/img/e2e/lock-warning.svg deleted file mode 100644 index de2bded7f8..0000000000 --- a/res/img/e2e/lock-warning.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/res/img/edit.png b/res/img/edit.png deleted file mode 100644 index 6f373d3f3d..0000000000 Binary files a/res/img/edit.png and /dev/null differ diff --git a/res/img/edit.svg b/res/img/edit.svg deleted file mode 100644 index 9674b31690..0000000000 --- a/res/img/edit.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/res/img/element-icons/room/composer/send.svg b/res/img/element-icons/room/composer/send.svg deleted file mode 100644 index b255a9b23b..0000000000 --- a/res/img/element-icons/room/composer/send.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/res/img/element-icons/roomlist/clear-input.svg b/res/img/element-icons/roomlist/clear-input.svg deleted file mode 100644 index 29fc097600..0000000000 --- a/res/img/element-icons/roomlist/clear-input.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/res/img/element-icons/roomlist/direct-chat.svg b/res/img/element-icons/roomlist/direct-chat.svg deleted file mode 100644 index 4b92dd9521..0000000000 --- a/res/img/element-icons/roomlist/direct-chat.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/res/img/element-icons/roomlist/e2ee-default.svg b/res/img/element-icons/roomlist/e2ee-default.svg deleted file mode 100644 index 76525f48b2..0000000000 --- a/res/img/element-icons/roomlist/e2ee-default.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/res/img/element-icons/roomlist/e2ee-error.svg b/res/img/element-icons/roomlist/e2ee-error.svg deleted file mode 100644 index 7f1a761dde..0000000000 --- a/res/img/element-icons/roomlist/e2ee-error.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/res/img/element-icons/roomlist/e2ee-none.svg b/res/img/element-icons/roomlist/e2ee-none.svg deleted file mode 100644 index cfafe6d09d..0000000000 --- a/res/img/element-icons/roomlist/e2ee-none.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/res/img/element-icons/roomlist/e2ee-trusted.svg b/res/img/element-icons/roomlist/e2ee-trusted.svg deleted file mode 100644 index 577d6a31e1..0000000000 --- a/res/img/element-icons/roomlist/e2ee-trusted.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/res/img/element-icons/roomlist/explore-rooms.svg b/res/img/element-icons/roomlist/explore-rooms.svg deleted file mode 100644 index 3786ce1153..0000000000 --- a/res/img/element-icons/roomlist/explore-rooms.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/res/img/element-icons/roomlist/search.svg b/res/img/element-icons/roomlist/search.svg deleted file mode 100644 index 3786ce1153..0000000000 --- a/res/img/element-icons/roomlist/search.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/res/img/explore.svg b/res/img/explore.svg deleted file mode 100644 index 3956e912ac..0000000000 --- a/res/img/explore.svg +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - diff --git a/res/img/feather-customised/archive.svg b/res/img/feather-customised/archive.svg deleted file mode 100644 index 428882c87b..0000000000 --- a/res/img/feather-customised/archive.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/res/img/feather-customised/arrow-down.svg b/res/img/feather-customised/arrow-down.svg deleted file mode 100644 index 4f84f627bd..0000000000 --- a/res/img/feather-customised/arrow-down.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/res/img/feather-customised/bell-crossed.svg b/res/img/feather-customised/bell-crossed.svg deleted file mode 100644 index 3ca24662b9..0000000000 --- a/res/img/feather-customised/bell-crossed.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/res/img/feather-customised/bell-mentions.custom.svg b/res/img/feather-customised/bell-mentions.custom.svg deleted file mode 100644 index fcc02f337f..0000000000 --- a/res/img/feather-customised/bell-mentions.custom.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/res/img/feather-customised/bell-notification.custom.svg b/res/img/feather-customised/bell-notification.custom.svg deleted file mode 100644 index 7bfd551f97..0000000000 --- a/res/img/feather-customised/bell-notification.custom.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/res/img/feather-customised/bell.svg b/res/img/feather-customised/bell.svg deleted file mode 100644 index b6bc5ec502..0000000000 --- a/res/img/feather-customised/bell.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/res/img/feather-customised/brush.svg b/res/img/feather-customised/brush.svg deleted file mode 100644 index d7f2738629..0000000000 --- a/res/img/feather-customised/brush.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/res/img/feather-customised/emoji3.custom.svg b/res/img/feather-customised/emoji3.custom.svg deleted file mode 100644 index d91ba1c132..0000000000 --- a/res/img/feather-customised/emoji3.custom.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/res/img/feather-customised/face.svg b/res/img/feather-customised/face.svg deleted file mode 100644 index a8ca856b67..0000000000 --- a/res/img/feather-customised/face.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/res/img/feather-customised/favourites.svg b/res/img/feather-customised/favourites.svg deleted file mode 100644 index 80f08f6e55..0000000000 --- a/res/img/feather-customised/favourites.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/res/img/feather-customised/flag.svg b/res/img/feather-customised/flag.svg deleted file mode 100644 index 983c02762b..0000000000 --- a/res/img/feather-customised/flag.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/res/img/feather-customised/flair.svg b/res/img/feather-customised/flair.svg deleted file mode 100644 index ce3a5ed6ad..0000000000 --- a/res/img/feather-customised/flair.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/res/img/feather-customised/grid.svg b/res/img/feather-customised/grid.svg deleted file mode 100644 index 4f7ab30d97..0000000000 --- a/res/img/feather-customised/grid.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/res/img/feather-customised/lock-solid.svg b/res/img/feather-customised/lock-solid.svg deleted file mode 100644 index 9eb8b6a4c5..0000000000 --- a/res/img/feather-customised/lock-solid.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/res/img/feather-customised/lock.svg b/res/img/feather-customised/lock.svg deleted file mode 100644 index 1330903b30..0000000000 --- a/res/img/feather-customised/lock.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/res/img/feather-customised/more-horizontal.svg b/res/img/feather-customised/more-horizontal.svg deleted file mode 100644 index dc6a85564e..0000000000 --- a/res/img/feather-customised/more-horizontal.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/res/img/feather-customised/notifications.svg b/res/img/feather-customised/notifications.svg deleted file mode 100644 index a590031ac3..0000000000 --- a/res/img/feather-customised/notifications.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/res/img/feather-customised/paperclip.svg b/res/img/feather-customised/paperclip.svg deleted file mode 100644 index 74a90e0fa3..0000000000 --- a/res/img/feather-customised/paperclip.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/res/img/feather-customised/phone.svg b/res/img/feather-customised/phone.svg deleted file mode 100644 index 85661c5320..0000000000 --- a/res/img/feather-customised/phone.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/res/img/feather-customised/search.svg b/res/img/feather-customised/search.svg deleted file mode 100644 index 9ce0724ea7..0000000000 --- a/res/img/feather-customised/search.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/res/img/feather-customised/share.svg b/res/img/feather-customised/share.svg deleted file mode 100644 index 7098af58aa..0000000000 --- a/res/img/feather-customised/share.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/res/img/feather-customised/sliders.svg b/res/img/feather-customised/sliders.svg deleted file mode 100644 index 5b5ec8656c..0000000000 --- a/res/img/feather-customised/sliders.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/res/img/feather-customised/star.svg b/res/img/feather-customised/star.svg deleted file mode 100644 index bcdc31aa47..0000000000 --- a/res/img/feather-customised/star.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/res/img/feather-customised/sticker.custom.svg b/res/img/feather-customised/sticker.custom.svg deleted file mode 100644 index 691e3b3925..0000000000 --- a/res/img/feather-customised/sticker.custom.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/res/img/feather-customised/sun.svg b/res/img/feather-customised/sun.svg deleted file mode 100644 index 7f51b94d1c..0000000000 --- a/res/img/feather-customised/sun.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/res/img/feather-customised/upload.svg b/res/img/feather-customised/upload.svg deleted file mode 100644 index 30c89d3819..0000000000 --- a/res/img/feather-customised/upload.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/res/img/feather-customised/user-add.svg b/res/img/feather-customised/user-add.svg deleted file mode 100644 index 6b5210c1d6..0000000000 --- a/res/img/feather-customised/user-add.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/res/img/feather-customised/users-sm.svg b/res/img/feather-customised/users-sm.svg deleted file mode 100644 index 6098be38c3..0000000000 --- a/res/img/feather-customised/users-sm.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/res/img/feather-customised/users.svg b/res/img/feather-customised/users.svg deleted file mode 100644 index b90aafdd4a..0000000000 --- a/res/img/feather-customised/users.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/res/img/feather-customised/video.svg b/res/img/feather-customised/video.svg deleted file mode 100644 index da77b6c57a..0000000000 --- a/res/img/feather-customised/video.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/res/img/filegrid.png b/res/img/filegrid.png deleted file mode 100644 index c2c2799f37..0000000000 Binary files a/res/img/filegrid.png and /dev/null differ diff --git a/res/img/filelist.png b/res/img/filelist.png deleted file mode 100644 index 3cf6cb494e..0000000000 Binary files a/res/img/filelist.png and /dev/null differ diff --git a/res/img/fullscreen.svg b/res/img/fullscreen.svg deleted file mode 100644 index e333abb6fb..0000000000 --- a/res/img/fullscreen.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - Zoom - Created with Sketch. - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/hide.png b/res/img/hide.png deleted file mode 100644 index c5aaf0dd0d..0000000000 Binary files a/res/img/hide.png and /dev/null differ diff --git a/res/img/icon-text-cancel.svg b/res/img/icon-text-cancel.svg deleted file mode 100644 index ce28d128aa..0000000000 --- a/res/img/icon-text-cancel.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - 28D80248-63BA-4A5F-9216-4CFE72784BAC - Created with sketchtool. - - - - - - - - - - \ No newline at end of file diff --git a/res/img/icons-pin.svg b/res/img/icons-pin.svg deleted file mode 100644 index a6fbf13baa..0000000000 --- a/res/img/icons-pin.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/res/img/icons-room-nobg.svg b/res/img/icons-room-nobg.svg deleted file mode 100644 index 8ca7ab272b..0000000000 --- a/res/img/icons-room-nobg.svg +++ /dev/null @@ -1,28 +0,0 @@ - -image/svg+xml - - - - - - - \ No newline at end of file diff --git a/res/img/icons-share.svg b/res/img/icons-share.svg deleted file mode 100644 index aac19080f4..0000000000 --- a/res/img/icons-share.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/res/img/info.png b/res/img/info.png deleted file mode 100644 index 699fd64e01..0000000000 Binary files a/res/img/info.png and /dev/null differ diff --git a/res/img/leave.svg b/res/img/leave.svg deleted file mode 100644 index 1acbe59313..0000000000 --- a/res/img/leave.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/res/img/list-close.png b/res/img/list-close.png deleted file mode 100644 index 82b322f9d4..0000000000 Binary files a/res/img/list-close.png and /dev/null differ diff --git a/res/img/list-open.png b/res/img/list-open.png deleted file mode 100644 index f8c8063197..0000000000 Binary files a/res/img/list-open.png and /dev/null differ diff --git a/res/img/matrix-m.svg b/res/img/matrix-m.svg deleted file mode 100644 index ccb1df0fc5..0000000000 --- a/res/img/matrix-m.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - diff --git a/res/img/menu.png b/res/img/menu.png deleted file mode 100755 index b45f88950f..0000000000 Binary files a/res/img/menu.png and /dev/null differ diff --git a/res/img/network-matrix.svg b/res/img/network-matrix.svg deleted file mode 100644 index bb8278ae39..0000000000 --- a/res/img/network-matrix.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - diff --git a/res/img/newmessages.png b/res/img/newmessages.png deleted file mode 100644 index a22156ab21..0000000000 Binary files a/res/img/newmessages.png and /dev/null differ diff --git a/res/img/placeholder.png b/res/img/placeholder.png deleted file mode 100644 index 7da32f259c..0000000000 Binary files a/res/img/placeholder.png and /dev/null differ diff --git a/res/img/react.svg b/res/img/react.svg deleted file mode 100644 index dd23c41c2c..0000000000 --- a/res/img/react.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/res/img/reply.svg b/res/img/reply.svg deleted file mode 100644 index 540e228883..0000000000 --- a/res/img/reply.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/res/img/search.png b/res/img/search.png deleted file mode 100644 index 2f98d29048..0000000000 Binary files a/res/img/search.png and /dev/null differ diff --git a/res/img/selected.png b/res/img/selected.png deleted file mode 100644 index 8931cba75f..0000000000 Binary files a/res/img/selected.png and /dev/null differ diff --git a/res/img/settings-big.png b/res/img/settings-big.png deleted file mode 100644 index cb2e0a62d0..0000000000 Binary files a/res/img/settings-big.png and /dev/null differ diff --git a/res/img/settings.png b/res/img/settings.png deleted file mode 100644 index 264b3c9bc3..0000000000 Binary files a/res/img/settings.png and /dev/null differ diff --git a/res/img/sound-indicator.svg b/res/img/sound-indicator.svg deleted file mode 100644 index 9b8de53d81..0000000000 --- a/res/img/sound-indicator.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - sound_indicator - Created with Sketch. - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/trans.png b/res/img/trans.png deleted file mode 100644 index 8ba2310a06..0000000000 Binary files a/res/img/trans.png and /dev/null differ diff --git a/res/img/typing.png b/res/img/typing.png deleted file mode 100644 index 066a0ce8fd..0000000000 Binary files a/res/img/typing.png and /dev/null differ diff --git a/res/img/upload-big.png b/res/img/upload-big.png deleted file mode 100644 index c11c0c452d..0000000000 Binary files a/res/img/upload-big.png and /dev/null differ diff --git a/res/img/upload.png b/res/img/upload.png deleted file mode 100644 index 7457bcd0f1..0000000000 Binary files a/res/img/upload.png and /dev/null differ diff --git a/res/img/video-mute.svg b/res/img/video-mute.svg deleted file mode 100644 index 6de60ba39b..0000000000 --- a/res/img/video-mute.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - icons_video copy - Created with Sketch. - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/video-unmute.svg b/res/img/video-unmute.svg deleted file mode 100644 index a6c6c3b681..0000000000 --- a/res/img/video-unmute.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - icons_video copy - Created with Sketch. - - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/video.png b/res/img/video.png deleted file mode 100644 index 2a788f6fa4..0000000000 Binary files a/res/img/video.png and /dev/null differ diff --git a/res/img/voice-mute.svg b/res/img/voice-mute.svg deleted file mode 100644 index 336641078e..0000000000 --- a/res/img/voice-mute.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - Audio - Created with Sketch. - - - - - - - - - \ No newline at end of file diff --git a/res/img/voice-unmute.svg b/res/img/voice-unmute.svg deleted file mode 100644 index 0d7e6f429f..0000000000 --- a/res/img/voice-unmute.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - Audio - Created with Sketch. - - - - - - - - - - \ No newline at end of file diff --git a/res/img/voice.png b/res/img/voice.png deleted file mode 100644 index 5ba765b0f4..0000000000 Binary files a/res/img/voice.png and /dev/null differ diff --git a/res/img/voip-chevron.svg b/res/img/voip-chevron.svg deleted file mode 100644 index 5f7cbe7153..0000000000 --- a/res/img/voip-chevron.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - Triangle 1 - Created with Sketch. - - - - - - - \ No newline at end of file diff --git a/res/img/voip-mute.png b/res/img/voip-mute.png deleted file mode 100644 index a16d1001e5..0000000000 Binary files a/res/img/voip-mute.png and /dev/null differ diff --git a/res/img/voip.png b/res/img/voip.png deleted file mode 100644 index e8f05bcc37..0000000000 Binary files a/res/img/voip.png and /dev/null differ diff --git a/res/img/warning.png b/res/img/warning.png deleted file mode 100644 index c5553530a8..0000000000 Binary files a/res/img/warning.png and /dev/null differ diff --git a/res/img/warning2.png b/res/img/warning2.png deleted file mode 100644 index db0fd4a897..0000000000 Binary files a/res/img/warning2.png and /dev/null differ diff --git a/res/img/zoom.png b/res/img/zoom.png deleted file mode 100644 index f05ea959b4..0000000000 Binary files a/res/img/zoom.png and /dev/null differ diff --git a/src/Lifecycle.js b/src/Lifecycle.js index a05392c3e9..2bebe22f14 100644 --- a/src/Lifecycle.js +++ b/src/Lifecycle.js @@ -306,6 +306,11 @@ async function _restoreFromLocalStorage(opts) { } const pickleKey = await PlatformPeg.get().getPickleKey(userId, deviceId); + if (pickleKey) { + console.log("Got pickle key"); + } else { + console.log("No pickle key available"); + } console.log(`Restoring session for ${userId}`); await _doSetLoggedIn({ @@ -364,6 +369,12 @@ export async function setLoggedIn(credentials) { ? await PlatformPeg.get().createPickleKey(credentials.userId, credentials.deviceId) : null; + if (pickleKey) { + console.log("Created pickle key"); + } else { + console.log("Pickle key not created"); + } + return _doSetLoggedIn(Object.assign({}, credentials, {pickleKey}), true); } @@ -501,6 +512,14 @@ function _persistCredentialsToLocalStorage(credentials) { localStorage.setItem("mx_access_token", credentials.accessToken); localStorage.setItem("mx_is_guest", JSON.stringify(credentials.guest)); + if (credentials.pickleKey) { + localStorage.setItem("mx_has_pickle_key", true); + } else { + if (localStorage.getItem("mx_has_pickle_key")) { + console.error("Expected a pickle key, but none provided. Encryption may not work."); + } + } + // if we didn't get a deviceId from the login, leave mx_device_id unset, // rather than setting it to "undefined". // diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx index 1f561e68ef..760ea52855 100644 --- a/src/components/structures/LoggedInView.tsx +++ b/src/components/structures/LoggedInView.tsx @@ -54,6 +54,7 @@ import LeftPanel from "./LeftPanel"; import CallContainer from '../views/voip/CallContainer'; import { ViewRoomDeltaPayload } from "../../dispatcher/payloads/ViewRoomDeltaPayload"; import RoomListStore from "../../stores/room-list/RoomListStore"; +import { ToggleRightPanelPayload } from "../../dispatcher/payloads/ToggleRightPanelPayload"; // We need to fetch each pinned message individually (if we don't already have it) // so each pinned message may trigger a request. Limit the number per room for sanity. @@ -472,8 +473,8 @@ class LoggedInView extends React.Component { case Key.PERIOD: if (ctrlCmdOnly && (this.props.page_type === "room_view" || this.props.page_type === "group_view")) { - dis.dispatch({ - action: 'toggle_right_panel', + dis.dispatch({ + action: Action.ToggleRightPanel, type: this.props.page_type === "room_view" ? "room" : "group", }); handled = true; diff --git a/src/components/structures/RightPanel.js b/src/components/structures/RightPanel.js index 776130e709..a4e3254e4c 100644 --- a/src/components/structures/RightPanel.js +++ b/src/components/structures/RightPanel.js @@ -26,7 +26,7 @@ import dis from '../../dispatcher/dispatcher'; import RateLimitedFunc from '../../ratelimitedfunc'; import { showGroupInviteDialog, showGroupAddRoomDialog } from '../../GroupAddressPicker'; import GroupStore from '../../stores/GroupStore'; -import {RIGHT_PANEL_PHASES, RIGHT_PANEL_PHASES_NO_ARGS} from "../../stores/RightPanelStorePhases"; +import {RightPanelPhases, RIGHT_PANEL_PHASES_NO_ARGS} from "../../stores/RightPanelStorePhases"; import RightPanelStore from "../../stores/RightPanelStore"; import MatrixClientContext from "../../contexts/MatrixClientContext"; import {Action} from "../../dispatcher/actions"; @@ -75,8 +75,8 @@ export default class RightPanel extends React.Component { const userForPanel = this._getUserForPanel(); if (this.props.groupId) { if (!RIGHT_PANEL_PHASES_NO_ARGS.includes(rps.groupPanelPhase)) { - dis.dispatch({action: "set_right_panel_phase", phase: RIGHT_PANEL_PHASES.GroupMemberList}); - return RIGHT_PANEL_PHASES.GroupMemberList; + dis.dispatch({action: Action.SetRightPanelPhase, phase: RightPanelPhases.GroupMemberList}); + return RightPanelPhases.GroupMemberList; } return rps.groupPanelPhase; } else if (userForPanel) { @@ -98,11 +98,11 @@ export default class RightPanel extends React.Component { ) { return rps.roomPanelPhase; } - return RIGHT_PANEL_PHASES.RoomMemberInfo; + return RightPanelPhases.RoomMemberInfo; } else { if (!RIGHT_PANEL_PHASES_NO_ARGS.includes(rps.roomPanelPhase)) { - dis.dispatch({action: "set_right_panel_phase", phase: RIGHT_PANEL_PHASES.RoomMemberList}); - return RIGHT_PANEL_PHASES.RoomMemberList; + dis.dispatch({action: Action.SetRightPanelPhase, phase: RightPanelPhases.RoomMemberList}); + return RightPanelPhases.RoomMemberList; } return rps.roomPanelPhase; } @@ -149,7 +149,7 @@ export default class RightPanel extends React.Component { onInviteToGroupButtonClick() { showGroupInviteDialog(this.props.groupId).then(() => { this.setState({ - phase: RIGHT_PANEL_PHASES.GroupMemberList, + phase: RightPanelPhases.GroupMemberList, }); }); } @@ -165,9 +165,9 @@ export default class RightPanel extends React.Component { return; } // redraw the badge on the membership list - if (this.state.phase === RIGHT_PANEL_PHASES.RoomMemberList && member.roomId === this.props.roomId) { + if (this.state.phase === RightPanelPhases.RoomMemberList && member.roomId === this.props.roomId) { this._delayedUpdate(); - } else if (this.state.phase === RIGHT_PANEL_PHASES.RoomMemberInfo && member.roomId === this.props.roomId && + } else if (this.state.phase === RightPanelPhases.RoomMemberInfo && member.roomId === this.props.roomId && member.userId === this.state.member.userId) { // refresh the member info (e.g. new power level) this._delayedUpdate(); @@ -175,7 +175,7 @@ export default class RightPanel extends React.Component { } onAction(payload) { - if (payload.action === "after_right_panel_phase_change") { + if (payload.action === Action.AfterRightPanelPhaseChange) { this.setState({ phase: payload.phase, groupRoomId: payload.groupRoomId, @@ -206,7 +206,7 @@ export default class RightPanel extends React.Component { // or the member list if we were in the member panel... phew. dis.dispatch({ action: Action.ViewUser, - member: this.state.phase === RIGHT_PANEL_PHASES.EncryptionPanel ? this.state.member : null, + member: this.state.phase === RightPanelPhases.EncryptionPanel ? this.state.member : null, }); } }; @@ -225,21 +225,21 @@ export default class RightPanel extends React.Component { let panel =
; switch (this.state.phase) { - case RIGHT_PANEL_PHASES.RoomMemberList: + case RightPanelPhases.RoomMemberList: if (this.props.roomId) { panel = ; } break; - case RIGHT_PANEL_PHASES.GroupMemberList: + case RightPanelPhases.GroupMemberList: if (this.props.groupId) { panel = ; } break; - case RIGHT_PANEL_PHASES.GroupRoomList: + case RightPanelPhases.GroupRoomList: panel = ; break; - case RIGHT_PANEL_PHASES.RoomMemberInfo: - case RIGHT_PANEL_PHASES.EncryptionPanel: + case RightPanelPhases.RoomMemberInfo: + case RightPanelPhases.EncryptionPanel: panel = ; break; - case RIGHT_PANEL_PHASES.Room3pidMemberInfo: + case RightPanelPhases.Room3pidMemberInfo: panel = ; break; - case RIGHT_PANEL_PHASES.GroupMemberInfo: + case RightPanelPhases.GroupMemberInfo: panel = ; break; - case RIGHT_PANEL_PHASES.GroupRoomInfo: + case RightPanelPhases.GroupRoomInfo: panel = ; break; - case RIGHT_PANEL_PHASES.NotificationPanel: + case RightPanelPhases.NotificationPanel: panel = ; break; - case RIGHT_PANEL_PHASES.FilePanel: + case RightPanelPhases.FilePanel: panel = ; break; } diff --git a/src/components/views/groups/GroupMemberList.js b/src/components/views/groups/GroupMemberList.js index 7b643c7346..031b875409 100644 --- a/src/components/views/groups/GroupMemberList.js +++ b/src/components/views/groups/GroupMemberList.js @@ -24,8 +24,9 @@ import GroupStore from '../../../stores/GroupStore'; import PropTypes from 'prop-types'; import { showGroupInviteDialog } from '../../../GroupAddressPicker'; import AccessibleButton from '../elements/AccessibleButton'; -import {RIGHT_PANEL_PHASES} from "../../../stores/RightPanelStorePhases"; +import {RightPanelPhases} from "../../../stores/RightPanelStorePhases"; import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; +import {Action} from "../../../dispatcher/actions"; const INITIAL_LOAD_NUM_MEMBERS = 30; @@ -164,9 +165,9 @@ export default createReactClass({ onInviteToGroupButtonClick() { showGroupInviteDialog(this.props.groupId).then(() => { dis.dispatch({ - action: 'set_right_panel_phase', - phase: RIGHT_PANEL_PHASES.GroupMemberList, - groupId: this.props.groupId, + action: Action.SetRightPanelPhase, + phase: RightPanelPhases.GroupMemberList, + refireParams: { groupId: this.props.groupId }, }); }); }, diff --git a/src/components/views/messages/MKeyVerificationRequest.js b/src/components/views/messages/MKeyVerificationRequest.js index a5b1ae26bb..01a5c2663e 100644 --- a/src/components/views/messages/MKeyVerificationRequest.js +++ b/src/components/views/messages/MKeyVerificationRequest.js @@ -22,7 +22,8 @@ import { _t } from '../../../languageHandler'; import {getNameForEventRoom, userLabelForEventRoom} from '../../../utils/KeyVerificationStateObserver'; import dis from "../../../dispatcher/dispatcher"; -import {RIGHT_PANEL_PHASES} from "../../../stores/RightPanelStorePhases"; +import {RightPanelPhases} from "../../../stores/RightPanelStorePhases"; +import {Action} from "../../../dispatcher/actions"; export default class MKeyVerificationRequest extends React.Component { constructor(props) { @@ -48,8 +49,8 @@ export default class MKeyVerificationRequest extends React.Component { const {verificationRequest} = this.props.mxEvent; const member = MatrixClientPeg.get().getUser(verificationRequest.otherUserId); dis.dispatch({ - action: "set_right_panel_phase", - phase: RIGHT_PANEL_PHASES.EncryptionPanel, + action: Action.SetRightPanelPhase, + phase: RightPanelPhases.EncryptionPanel, refireParams: {verificationRequest, member}, }); }; diff --git a/src/components/views/right_panel/EncryptionInfo.js b/src/components/views/right_panel/EncryptionInfo.tsx similarity index 87% rename from src/components/views/right_panel/EncryptionInfo.js rename to src/components/views/right_panel/EncryptionInfo.tsx index 007e2831ce..f62af65543 100644 --- a/src/components/views/right_panel/EncryptionInfo.js +++ b/src/components/views/right_panel/EncryptionInfo.tsx @@ -15,10 +15,10 @@ limitations under the License. */ import React from "react"; -import PropTypes from "prop-types"; import * as sdk from "../../../index"; import {_t} from "../../../languageHandler"; +import {RoomMember} from "matrix-js-sdk/src/models/room-member"; export const PendingActionSpinner = ({text}) => { const Spinner = sdk.getComponent('elements.Spinner'); @@ -28,7 +28,17 @@ export const PendingActionSpinner = ({text}) => {
; }; -const EncryptionInfo = ({ +interface IProps { + waitingForOtherParty: boolean; + waitingForNetwork: boolean; + member: RoomMember; + onStartVerification: () => Promise; + isRoomEncrypted: boolean; + inDialog: boolean; + isSelfVerification: boolean; +} + +const EncryptionInfo: React.FC = ({ waitingForOtherParty, waitingForNetwork, member, @@ -36,10 +46,10 @@ const EncryptionInfo = ({ isRoomEncrypted, inDialog, isSelfVerification, -}) => { - let content; +}: IProps) => { + let content: JSX.Element; if (waitingForOtherParty || waitingForNetwork) { - let text; + let text: string; if (waitingForOtherParty) { if (isSelfVerification) { text = _t("Waiting for you to accept on your other session…"); @@ -61,7 +71,7 @@ const EncryptionInfo = ({ ); } - let description; + let description: JSX.Element; if (isRoomEncrypted) { description = (
@@ -97,10 +107,5 @@ const EncryptionInfo = ({
; }; -EncryptionInfo.propTypes = { - member: PropTypes.object.isRequired, - onStartVerification: PropTypes.func.isRequired, - request: PropTypes.object, -}; export default EncryptionInfo; diff --git a/src/components/views/right_panel/EncryptionPanel.js b/src/components/views/right_panel/EncryptionPanel.tsx similarity index 86% rename from src/components/views/right_panel/EncryptionPanel.js rename to src/components/views/right_panel/EncryptionPanel.tsx index e9f94729fa..df52e5cabd 100644 --- a/src/components/views/right_panel/EncryptionPanel.js +++ b/src/components/views/right_panel/EncryptionPanel.tsx @@ -15,7 +15,6 @@ limitations under the License. */ import React, {useCallback, useEffect, useState} from "react"; -import PropTypes from "prop-types"; import EncryptionInfo from "./EncryptionInfo"; import VerificationPanel from "./VerificationPanel"; @@ -26,11 +25,23 @@ import Modal from "../../../Modal"; import {PHASE_REQUESTED, PHASE_UNSENT} from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest"; import * as sdk from "../../../index"; import {_t} from "../../../languageHandler"; +import {VerificationRequest} from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest"; +import {RoomMember} from "matrix-js-sdk/src/models/room-member"; // cancellation codes which constitute a key mismatch const MISMATCHES = ["m.key_mismatch", "m.user_error", "m.mismatched_sas"]; -const EncryptionPanel = (props) => { +interface IProps { + member: RoomMember; + onClose: () => void; + verificationRequest: VerificationRequest; + verificationRequestPromise: Promise; + layout: string; + inDialog: boolean; + isRoomEncrypted: boolean; +} + +const EncryptionPanel: React.FC = (props: IProps) => { const {verificationRequest, verificationRequestPromise, member, onClose, layout, isRoomEncrypted} = props; const [request, setRequest] = useState(verificationRequest); // state to show a spinner immediately after clicking "start verification", @@ -48,10 +59,10 @@ const EncryptionPanel = (props) => { useEffect(() => { async function awaitPromise() { setRequesting(true); - const request = await verificationRequestPromise; + const requestFromPromise = await verificationRequestPromise; setRequesting(false); - setRequest(request); - setPhase(request.phase); + setRequest(requestFromPromise); + setPhase(requestFromPromise.phase); } if (verificationRequestPromise) { awaitPromise(); @@ -90,7 +101,7 @@ const EncryptionPanel = (props) => { } }, [request]); - let cancelButton; + let cancelButton: JSX.Element; if (layout !== "dialog" && request && request.pending) { const AccessibleButton = sdk.getComponent("elements.AccessibleButton"); cancelButton = ( { setRequesting(true); const cli = MatrixClientPeg.get(); const roomId = await ensureDMExists(cli, member.userId); - const verificationRequest = await cli.requestVerificationDM(member.userId, roomId); - setRequest(verificationRequest); - setPhase(verificationRequest.phase); + const verificationRequest_ = await cli.requestVerificationDM(member.userId, roomId); + setRequest(verificationRequest_); + setPhase(verificationRequest_.phase); }, [member.userId]); const requested = @@ -144,12 +155,5 @@ const EncryptionPanel = (props) => { ); } }; -EncryptionPanel.propTypes = { - member: PropTypes.object.isRequired, - onClose: PropTypes.func.isRequired, - verificationRequest: PropTypes.object, - layout: PropTypes.string, - inDialog: PropTypes.bool, -}; export default EncryptionPanel; diff --git a/src/components/views/right_panel/GroupHeaderButtons.js b/src/components/views/right_panel/GroupHeaderButtons.tsx similarity index 60% rename from src/components/views/right_panel/GroupHeaderButtons.js rename to src/components/views/right_panel/GroupHeaderButtons.tsx index 33d9325433..44237e401f 100644 --- a/src/components/views/right_panel/GroupHeaderButtons.js +++ b/src/components/views/right_panel/GroupHeaderButtons.tsx @@ -21,65 +21,68 @@ limitations under the License. import React from 'react'; import { _t } from '../../../languageHandler'; import HeaderButton from './HeaderButton'; -import HeaderButtons, {HEADER_KIND_GROUP} from './HeaderButtons'; -import {RIGHT_PANEL_PHASES} from "../../../stores/RightPanelStorePhases"; +import HeaderButtons, {HeaderKind} from './HeaderButtons'; +import {RightPanelPhases} from "../../../stores/RightPanelStorePhases"; import {Action} from "../../../dispatcher/actions"; import {ActionPayload} from "../../../dispatcher/payloads"; +import {ViewUserPayload} from "../../../dispatcher/payloads/ViewUserPayload"; const GROUP_PHASES = [ - RIGHT_PANEL_PHASES.GroupMemberInfo, - RIGHT_PANEL_PHASES.GroupMemberList, + RightPanelPhases.GroupMemberInfo, + RightPanelPhases.GroupMemberList, ]; const ROOM_PHASES = [ - RIGHT_PANEL_PHASES.GroupRoomList, - RIGHT_PANEL_PHASES.GroupRoomInfo, + RightPanelPhases.GroupRoomList, + RightPanelPhases.GroupRoomInfo, ]; +interface IProps {} + export default class GroupHeaderButtons extends HeaderButtons { - constructor(props) { - super(props, HEADER_KIND_GROUP); - this._onMembersClicked = this._onMembersClicked.bind(this); - this._onRoomsClicked = this._onRoomsClicked.bind(this); + constructor(props: IProps) { + super(props, HeaderKind.Group); + this.onMembersClicked = this.onMembersClicked.bind(this); + this.onRoomsClicked = this.onRoomsClicked.bind(this); } - onAction(payload: ActionPayload) { + protected onAction(payload: ActionPayload) { super.onAction(payload); if (payload.action === Action.ViewUser) { - if (payload.member) { - this.setPhase(RIGHT_PANEL_PHASES.RoomMemberInfo, {member: payload.member}); + if ((payload as ViewUserPayload).member) { + this.setPhase(RightPanelPhases.RoomMemberInfo, {member: payload.member}); } else { - this.setPhase(RIGHT_PANEL_PHASES.GroupMemberList); + this.setPhase(RightPanelPhases.GroupMemberList); } } else if (payload.action === "view_group") { - this.setPhase(RIGHT_PANEL_PHASES.GroupMemberList); + this.setPhase(RightPanelPhases.GroupMemberList); } else if (payload.action === "view_group_room") { this.setPhase( - RIGHT_PANEL_PHASES.GroupRoomInfo, + RightPanelPhases.GroupRoomInfo, {groupRoomId: payload.groupRoomId, groupId: payload.groupId}, ); } else if (payload.action === "view_group_room_list") { - this.setPhase(RIGHT_PANEL_PHASES.GroupRoomList); + this.setPhase(RightPanelPhases.GroupRoomList); } else if (payload.action === "view_group_member_list") { - this.setPhase(RIGHT_PANEL_PHASES.GroupMemberList); + this.setPhase(RightPanelPhases.GroupMemberList); } else if (payload.action === "view_group_user") { - this.setPhase(RIGHT_PANEL_PHASES.GroupMemberInfo, {member: payload.member}); + this.setPhase(RightPanelPhases.GroupMemberInfo, {member: payload.member}); } } - _onMembersClicked() { - if (this.state.phase === RIGHT_PANEL_PHASES.GroupMemberInfo) { + private onMembersClicked() { + if (this.state.phase === RightPanelPhases.GroupMemberInfo) { // send the active phase to trigger a toggle - this.setPhase(RIGHT_PANEL_PHASES.GroupMemberInfo); + this.setPhase(RightPanelPhases.GroupMemberInfo); } else { // This toggles for us, if needed - this.setPhase(RIGHT_PANEL_PHASES.GroupMemberList); + this.setPhase(RightPanelPhases.GroupMemberList); } } - _onRoomsClicked() { + private onRoomsClicked() { // This toggles for us, if needed - this.setPhase(RIGHT_PANEL_PHASES.GroupRoomList); + this.setPhase(RightPanelPhases.GroupRoomList); } renderButtons() { @@ -87,13 +90,13 @@ export default class GroupHeaderButtons extends HeaderButtons { , , ]; diff --git a/src/components/views/right_panel/HeaderButton.js b/src/components/views/right_panel/HeaderButton.tsx similarity index 79% rename from src/components/views/right_panel/HeaderButton.js rename to src/components/views/right_panel/HeaderButton.tsx index 2cfc060bba..c7cd064184 100644 --- a/src/components/views/right_panel/HeaderButton.js +++ b/src/components/views/right_panel/HeaderButton.tsx @@ -19,23 +19,38 @@ limitations under the License. */ import React from 'react'; -import PropTypes from 'prop-types'; import classNames from 'classnames'; import Analytics from '../../../Analytics'; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; -export default class HeaderButton extends React.Component { - constructor() { - super(); +interface IProps { + // Whether this button is highlighted + isHighlighted: boolean; + // click handler + onClick: () => void; + // The badge to display above the icon + badge?: React.ReactNode; + // The parameters to track the click event + analytics: string[]; + + // Button name + name: string; + // Button title + title: string; +} + +export default class HeaderButton extends React.Component { + constructor(props: IProps) { + super(props); this.onClick = this.onClick.bind(this); } - onClick(ev) { + private onClick() { Analytics.trackEvent(...this.props.analytics); this.props.onClick(); } - render() { + public render() { const classes = classNames({ mx_RightPanel_headerButton: true, mx_RightPanel_headerButton_highlight: this.props.isHighlighted, @@ -51,19 +66,3 @@ export default class HeaderButton extends React.Component { />; } } - -HeaderButton.propTypes = { - // Whether this button is highlighted - isHighlighted: PropTypes.bool.isRequired, - // click handler - onClick: PropTypes.func.isRequired, - // The badge to display above the icon - badge: PropTypes.node, - // The parameters to track the click event - analytics: PropTypes.arrayOf(PropTypes.string).isRequired, - - // Button name - name: PropTypes.string.isRequired, - // Button title - title: PropTypes.string.isRequired, -}; diff --git a/src/components/views/right_panel/HeaderButtons.js b/src/components/views/right_panel/HeaderButtons.js deleted file mode 100644 index 1c66fe5828..0000000000 --- a/src/components/views/right_panel/HeaderButtons.js +++ /dev/null @@ -1,88 +0,0 @@ -/* -Copyright 2015, 2016 OpenMarket Ltd -Copyright 2017 Vector Creations Ltd -Copyright 2017 New Vector Ltd -Copyright 2018 New Vector Ltd -Copyright 2019 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import React from 'react'; -import dis from '../../../dispatcher/dispatcher'; -import RightPanelStore from "../../../stores/RightPanelStore"; - -export const HEADER_KIND_ROOM = "room"; -export const HEADER_KIND_GROUP = "group"; - -const HEADER_KINDS = [HEADER_KIND_GROUP, HEADER_KIND_ROOM]; - -export default class HeaderButtons extends React.Component { - constructor(props, kind) { - super(props); - - if (!HEADER_KINDS.includes(kind)) throw new Error(`Invalid header kind: ${kind}`); - - const rps = RightPanelStore.getSharedInstance(); - this.state = { - headerKind: kind, - phase: kind === HEADER_KIND_ROOM ? rps.visibleRoomPanelPhase : rps.visibleGroupPanelPhase, - }; - } - - componentDidMount() { - this._storeToken = RightPanelStore.getSharedInstance().addListener(this.onRightPanelUpdate.bind(this)); - this._dispatcherRef = dis.register(this.onAction.bind(this)); // used by subclasses - } - - componentWillUnmount() { - if (this._storeToken) this._storeToken.remove(); - if (this._dispatcherRef) dis.unregister(this._dispatcherRef); - } - - onAction(payload) { - // Ignore - intended to be overridden by subclasses - } - - setPhase(phase, extras) { - dis.dispatch({ - action: 'set_right_panel_phase', - phase: phase, - refireParams: extras, - }); - } - - isPhase(phases: string | string[]) { - if (Array.isArray(phases)) { - return phases.includes(this.state.phase); - } else { - return phases === this.state.phase; - } - } - - onRightPanelUpdate() { - const rps = RightPanelStore.getSharedInstance(); - if (this.state.headerKind === HEADER_KIND_ROOM) { - this.setState({phase: rps.visibleRoomPanelPhase}); - } else if (this.state.headerKind === HEADER_KIND_GROUP) { - this.setState({phase: rps.visibleGroupPanelPhase}); - } - } - - render() { - // inline style as this will be swapped around in future commits - return
- {this.renderButtons()} -
; - } -} diff --git a/src/components/views/right_panel/HeaderButtons.tsx b/src/components/views/right_panel/HeaderButtons.tsx new file mode 100644 index 0000000000..57d3075739 --- /dev/null +++ b/src/components/views/right_panel/HeaderButtons.tsx @@ -0,0 +1,110 @@ +/* +Copyright 2015, 2016 OpenMarket Ltd +Copyright 2017 Vector Creations Ltd +Copyright 2017 New Vector Ltd +Copyright 2018 New Vector Ltd +Copyright 2019 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React from 'react'; +import dis from '../../../dispatcher/dispatcher'; +import RightPanelStore from "../../../stores/RightPanelStore"; +import {RightPanelPhases} from "../../../stores/RightPanelStorePhases"; +import {Action} from '../../../dispatcher/actions'; +import {SetRightPanelPhasePayload, SetRightPanelPhaseRefireParams} from '../../../dispatcher/payloads/SetRightPanelPhasePayload'; +import {EventSubscription} from "fbemitter"; + +export enum HeaderKind { + Room = "room", + Group = "group", +} + +interface IState { + headerKind: HeaderKind; + phase: RightPanelPhases; +} + +interface IProps {} + +export default class HeaderButtons extends React.Component { + private storeToken: EventSubscription; + private dispatcherRef: string; + + constructor(props: IProps, kind: HeaderKind) { + super(props); + + const rps = RightPanelStore.getSharedInstance(); + this.state = { + headerKind: kind, + phase: kind === HeaderKind.Room ? rps.visibleRoomPanelPhase : rps.visibleGroupPanelPhase, + }; + } + + public componentDidMount() { + this.storeToken = RightPanelStore.getSharedInstance().addListener(this.onRightPanelUpdate.bind(this)); + this.dispatcherRef = dis.register(this.onAction.bind(this)); // used by subclasses + } + + public componentWillUnmount() { + if (this.storeToken) this.storeToken.remove(); + if (this.dispatcherRef) dis.unregister(this.dispatcherRef); + } + + protected onAction(payload) { + // Ignore - intended to be overridden by subclasses + } + + public setPhase(phase: RightPanelPhases, extras?: Partial) { + dis.dispatch({ + action: Action.SetRightPanelPhase, + phase: phase, + refireParams: extras, + }); + } + + public isPhase(phases: string | string[]) { + if (Array.isArray(phases)) { + return phases.includes(this.state.phase); + } else { + return phases === this.state.phase; + } + } + + private onRightPanelUpdate() { + const rps = RightPanelStore.getSharedInstance(); + if (this.state.headerKind === HeaderKind.Room) { + this.setState({phase: rps.visibleRoomPanelPhase}); + } else if (this.state.headerKind === HeaderKind.Group) { + this.setState({phase: rps.visibleGroupPanelPhase}); + } + } + + // XXX: Make renderButtons a prop + public renderButtons(): JSX.Element[] { + // Ignore - intended to be overridden by subclasses + // Return empty fragment to satisfy the type + return [ + + + ]; + } + + public render() { + // inline style as this will be swapped around in future commits + return
+ {this.renderButtons()} +
; + } +} diff --git a/src/components/views/right_panel/RoomHeaderButtons.js b/src/components/views/right_panel/RoomHeaderButtons.tsx similarity index 59% rename from src/components/views/right_panel/RoomHeaderButtons.js rename to src/components/views/right_panel/RoomHeaderButtons.tsx index 838727981d..7ac547f499 100644 --- a/src/components/views/right_panel/RoomHeaderButtons.js +++ b/src/components/views/right_panel/RoomHeaderButtons.tsx @@ -21,82 +21,82 @@ limitations under the License. import React from 'react'; import { _t } from '../../../languageHandler'; import HeaderButton from './HeaderButton'; -import HeaderButtons, {HEADER_KIND_ROOM} from './HeaderButtons'; -import {RIGHT_PANEL_PHASES} from "../../../stores/RightPanelStorePhases"; +import HeaderButtons, {HeaderKind} from './HeaderButtons'; +import {RightPanelPhases} from "../../../stores/RightPanelStorePhases"; import {Action} from "../../../dispatcher/actions"; import {ActionPayload} from "../../../dispatcher/payloads"; const MEMBER_PHASES = [ - RIGHT_PANEL_PHASES.RoomMemberList, - RIGHT_PANEL_PHASES.RoomMemberInfo, - RIGHT_PANEL_PHASES.EncryptionPanel, - RIGHT_PANEL_PHASES.Room3pidMemberInfo, + RightPanelPhases.RoomMemberList, + RightPanelPhases.RoomMemberInfo, + RightPanelPhases.EncryptionPanel, + RightPanelPhases.Room3pidMemberInfo, ]; export default class RoomHeaderButtons extends HeaderButtons { constructor(props) { - super(props, HEADER_KIND_ROOM); - this._onMembersClicked = this._onMembersClicked.bind(this); - this._onFilesClicked = this._onFilesClicked.bind(this); - this._onNotificationsClicked = this._onNotificationsClicked.bind(this); + super(props, HeaderKind.Room); + this.onMembersClicked = this.onMembersClicked.bind(this); + this.onFilesClicked = this.onFilesClicked.bind(this); + this.onNotificationsClicked = this.onNotificationsClicked.bind(this); } - onAction(payload: ActionPayload) { + protected onAction(payload: ActionPayload) { super.onAction(payload); if (payload.action === Action.ViewUser) { if (payload.member) { - this.setPhase(RIGHT_PANEL_PHASES.RoomMemberInfo, {member: payload.member}); + this.setPhase(RightPanelPhases.RoomMemberInfo, {member: payload.member}); } else { - this.setPhase(RIGHT_PANEL_PHASES.RoomMemberList); + this.setPhase(RightPanelPhases.RoomMemberList); } } else if (payload.action === "view_3pid_invite") { if (payload.event) { - this.setPhase(RIGHT_PANEL_PHASES.Room3pidMemberInfo, {event: payload.event}); + this.setPhase(RightPanelPhases.Room3pidMemberInfo, {event: payload.event}); } else { - this.setPhase(RIGHT_PANEL_PHASES.RoomMemberList); + this.setPhase(RightPanelPhases.RoomMemberList); } } } - _onMembersClicked() { - if (this.state.phase === RIGHT_PANEL_PHASES.RoomMemberInfo) { + private onMembersClicked() { + if (this.state.phase === RightPanelPhases.RoomMemberInfo) { // send the active phase to trigger a toggle // XXX: we should pass refireParams here but then it won't collapse as we desire it to - this.setPhase(RIGHT_PANEL_PHASES.RoomMemberInfo); + this.setPhase(RightPanelPhases.RoomMemberInfo); } else { // This toggles for us, if needed - this.setPhase(RIGHT_PANEL_PHASES.RoomMemberList); + this.setPhase(RightPanelPhases.RoomMemberList); } } - _onFilesClicked() { + private onFilesClicked() { // This toggles for us, if needed - this.setPhase(RIGHT_PANEL_PHASES.FilePanel); + this.setPhase(RightPanelPhases.FilePanel); } - _onNotificationsClicked() { + private onNotificationsClicked() { // This toggles for us, if needed - this.setPhase(RIGHT_PANEL_PHASES.NotificationPanel); + this.setPhase(RightPanelPhases.NotificationPanel); } - renderButtons() { + public renderButtons() { return [ , , , ]; diff --git a/src/components/views/right_panel/UserInfo.js b/src/components/views/right_panel/UserInfo.js index 719a64063d..20168faede 100644 --- a/src/components/views/right_panel/UserInfo.js +++ b/src/components/views/right_panel/UserInfo.js @@ -40,7 +40,7 @@ import E2EIcon from "../rooms/E2EIcon"; import {useEventEmitter} from "../../../hooks/useEventEmitter"; import {textualPowerLevel} from '../../../Roles'; import MatrixClientContext from "../../../contexts/MatrixClientContext"; -import {RIGHT_PANEL_PHASES} from "../../../stores/RightPanelStorePhases"; +import {RightPanelPhases} from "../../../stores/RightPanelStorePhases"; import EncryptionPanel from "./EncryptionPanel"; import { useAsyncMemo } from '../../../hooks/useAsyncMemo'; import { verifyUser, legacyVerifyUser, verifyDevice } from '../../../verification'; @@ -1480,7 +1480,7 @@ const UserInfoHeader = ({onClose, member, e2eStatus}) => { ; }; -const UserInfo = ({user, groupId, roomId, onClose, phase=RIGHT_PANEL_PHASES.RoomMemberInfo, ...props}) => { +const UserInfo = ({user, groupId, roomId, onClose, phase=RightPanelPhases.RoomMemberInfo, ...props}) => { const cli = useContext(MatrixClientContext); // Load room if we are given a room id and memoize it @@ -1500,8 +1500,8 @@ const UserInfo = ({user, groupId, roomId, onClose, phase=RIGHT_PANEL_PHASES.Room let content; switch (phase) { - case RIGHT_PANEL_PHASES.RoomMemberInfo: - case RIGHT_PANEL_PHASES.GroupMemberInfo: + case RightPanelPhases.RoomMemberInfo: + case RightPanelPhases.GroupMemberInfo: content = ( ); break; - case RIGHT_PANEL_PHASES.EncryptionPanel: + case RightPanelPhases.EncryptionPanel: classes.push("mx_UserInfo_smallAvatar"); content = ( diff --git a/src/components/views/right_panel/VerificationPanel.js b/src/components/views/right_panel/VerificationPanel.tsx similarity index 79% rename from src/components/views/right_panel/VerificationPanel.js rename to src/components/views/right_panel/VerificationPanel.tsx index 0b6790eac8..9cb7f54dd8 100644 --- a/src/components/views/right_panel/VerificationPanel.js +++ b/src/components/views/right_panel/VerificationPanel.tsx @@ -15,12 +15,15 @@ limitations under the License. */ import React from "react"; -import PropTypes from "prop-types"; import {MatrixClientPeg} from "../../../MatrixClientPeg"; import * as sdk from '../../../index'; import {verificationMethods} from 'matrix-js-sdk/src/crypto'; import {SCAN_QR_CODE_METHOD} from "matrix-js-sdk/src/crypto/verification/QRCode"; +import {VerificationRequest} from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest"; +import {RoomMember} from "matrix-js-sdk/src/models/room-member"; +import {ReciprocateQRCode} from "matrix-js-sdk/src/crypto/verification/QRCode"; +import {SAS} from "matrix-js-sdk/src/crypto/verification/SAS"; import VerificationQRCode from "../elements/crypto/VerificationQRCode"; import {_t} from "../../../languageHandler"; @@ -36,37 +39,51 @@ import { } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest"; import Spinner from "../elements/Spinner"; -export default class VerificationPanel extends React.PureComponent { - static propTypes = { - layout: PropTypes.string, - request: PropTypes.object.isRequired, - member: PropTypes.object.isRequired, - phase: PropTypes.oneOf([ - PHASE_UNSENT, - PHASE_REQUESTED, - PHASE_READY, - PHASE_STARTED, - PHASE_CANCELLED, - PHASE_DONE, - ]).isRequired, - onClose: PropTypes.func.isRequired, - isRoomEncrypted: PropTypes.bool, - }; +// XXX: Should be defined in matrix-js-sdk +enum VerificationPhase { + PHASE_UNSENT, + PHASE_REQUESTED, + PHASE_READY, + PHASE_DONE, + PHASE_STARTED, + PHASE_CANCELLED, +} - constructor(props) { +interface IProps { + layout: string; + request: VerificationRequest; + member: RoomMember; + phase: VerificationPhase; + onClose: () => void; + isRoomEncrypted: boolean; + inDialog: boolean; + key: number; +} + +interface IState { + sasEvent?: SAS; + emojiButtonClicked?: boolean; + reciprocateButtonClicked?: boolean; + reciprocateQREvent?: ReciprocateQRCode; +} + +export default class VerificationPanel extends React.PureComponent { + private hasVerifier: boolean; + + constructor(props: IProps) { super(props); this.state = {}; - this._hasVerifier = false; + this.hasVerifier = false; } - renderQRPhase() { + private renderQRPhase() { const {member, request} = this.props; - const showSAS = request.otherPartySupportsMethod(verificationMethods.SAS); - const showQR = request.otherPartySupportsMethod(SCAN_QR_CODE_METHOD); + const showSAS: boolean = request.otherPartySupportsMethod(verificationMethods.SAS); + const showQR: boolean = request.otherPartySupportsMethod(SCAN_QR_CODE_METHOD); const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const brand = SdkConfig.get().brand; - const noCommonMethodError = !showSAS && !showQR ? + const noCommonMethodError: JSX.Element = !showSAS && !showQR ?

{_t( "The session you are trying to verify doesn't support scanning a " + "QR code or emoji verification, which is what %(brand)s supports. Try " + @@ -77,41 +94,41 @@ export default class VerificationPanel extends React.PureComponent { if (this.props.layout === 'dialog') { // HACK: This is a terrible idea. - let qrBlock; - let sasBlock; + let qrBlockDialog: JSX.Element; + let sasBlockDialog: JSX.Element; if (showQR) { - qrBlock = + qrBlockDialog =

{_t("Scan this unique code")}

; } if (showSAS) { - sasBlock = + sasBlockDialog =

{_t("Compare unique emoji")}

{_t("Compare a unique set of emoji if you don't have a camera on either device")} - + {_t("Start")}
; } - const or = qrBlock && sasBlock ? + const or = qrBlockDialog && sasBlockDialog ?
{_t("or")}
: null; return (
{_t("Verify this session by completing one of the following:")}
- {qrBlock} + {qrBlockDialog} {or} - {sasBlock} + {sasBlockDialog} {noCommonMethodError}
); } - let qrBlock; + let qrBlock: JSX.Element; if (showQR) { qrBlock =

{_t("Verify by scanning")}

@@ -125,7 +142,7 @@ export default class VerificationPanel extends React.PureComponent {
; } - let sasBlock; + let sasBlock: JSX.Element; if (showSAS) { const disabled = this.state.emojiButtonClicked; const sasLabel = showQR ? @@ -140,7 +157,7 @@ export default class VerificationPanel extends React.PureComponent { disabled={disabled} kind="primary" className="mx_UserInfo_wideButton mx_VerificationPanel_verifyByEmojiButton" - onClick={this._startSAS} + onClick={this.startSAS} > {_t("Verify by emoji")}
@@ -159,22 +176,22 @@ export default class VerificationPanel extends React.PureComponent { ; } - _onReciprocateYesClick = () => { + private onReciprocateYesClick = () => { this.setState({reciprocateButtonClicked: true}); this.state.reciprocateQREvent.confirm(); }; - _onReciprocateNoClick = () => { + private onReciprocateNoClick = () => { this.setState({reciprocateButtonClicked: true}); this.state.reciprocateQREvent.cancel(); }; - _getDevice() { + private getDevice() { const deviceId = this.props.request && this.props.request.channel.deviceId; return MatrixClientPeg.get().getStoredDevice(MatrixClientPeg.get().getUserId(), deviceId); } - renderQRReciprocatePhase() { + private renderQRReciprocatePhase() { const {member, request} = this.props; let Button; // a bit of a hack, but the FormButton should only be used in the right panel @@ -189,7 +206,7 @@ export default class VerificationPanel extends React.PureComponent { _t("Almost there! Is %(displayName)s showing the same shield?", { displayName: member.displayName || member.name || member.userId, }); - let body; + let body: JSX.Element; if (this.state.reciprocateQREvent) { // riot web doesn't support scanning yet, so assume here we're the client being scanned. // @@ -202,11 +219,11 @@ export default class VerificationPanel extends React.PureComponent { + onClick={this.onReciprocateNoClick}>{_t("No")} + onClick={this.onReciprocateYesClick}>{_t("Yes")} ; } else { @@ -218,10 +235,10 @@ export default class VerificationPanel extends React.PureComponent { ; } - renderVerifiedPhase() { + private renderVerifiedPhase() { const {member, request} = this.props; - let text; + let text: string; if (!request.isSelfVerification) { if (this.props.isRoomEncrypted) { text = _t("Verify all users in a room to ensure it's secure."); @@ -230,9 +247,9 @@ export default class VerificationPanel extends React.PureComponent { } } - let description; + let description: string; if (request.isSelfVerification) { - const device = this._getDevice(); + const device = this.getDevice(); if (!device) { // This can happen if the device is logged out while we're still showing verification // UI for it. @@ -264,19 +281,19 @@ export default class VerificationPanel extends React.PureComponent { ); } - renderCancelledPhase() { + private renderCancelledPhase() { const {member, request} = this.props; const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); - let startAgainInstruction; + let startAgainInstruction: string; if (request.isSelfVerification) { startAgainInstruction = _t("Start verification again from the notification."); } else { startAgainInstruction = _t("Start verification again from their profile."); } - let text; + let text: string; if (request.cancellationCode === "m.timeout") { text = _t("Verification timed out.") + ` ${startAgainInstruction}`; } else if (request.cancellingUserId === request.otherUserId) { @@ -304,7 +321,7 @@ export default class VerificationPanel extends React.PureComponent { ); } - render() { + public render() { const {member, phase, request} = this.props; const displayName = member.displayName || member.name || member.userId; @@ -321,10 +338,10 @@ export default class VerificationPanel extends React.PureComponent { const emojis = this.state.sasEvent ? : ; @@ -345,7 +362,7 @@ export default class VerificationPanel extends React.PureComponent { return null; } - _startSAS = async () => { + private startSAS = async () => { this.setState({emojiButtonClicked: true}); const verifier = this.props.request.beginKeyVerification(verificationMethods.SAS); try { @@ -355,31 +372,31 @@ export default class VerificationPanel extends React.PureComponent { } }; - _onSasMatchesClick = () => { + private onSasMatchesClick = () => { this.state.sasEvent.confirm(); }; - _onSasMismatchesClick = () => { + private onSasMismatchesClick = () => { this.state.sasEvent.mismatch(); }; - _updateVerifierState = () => { + private updateVerifierState = () => { const {request} = this.props; const {sasEvent, reciprocateQREvent} = request.verifier; - request.verifier.off('show_sas', this._updateVerifierState); - request.verifier.off('show_reciprocate_qr', this._updateVerifierState); + request.verifier.off('show_sas', this.updateVerifierState); + request.verifier.off('show_reciprocate_qr', this.updateVerifierState); this.setState({sasEvent, reciprocateQREvent}); }; - _onRequestChange = async () => { + private onRequestChange = async () => { const {request} = this.props; - const hadVerifier = this._hasVerifier; - this._hasVerifier = !!request.verifier; - if (!hadVerifier && this._hasVerifier) { - request.verifier.on('show_sas', this._updateVerifierState); - request.verifier.on('show_reciprocate_qr', this._updateVerifierState); + const hadVerifier = this.hasVerifier; + this.hasVerifier = !!request.verifier; + if (!hadVerifier && this.hasVerifier) { + request.verifier.on('show_sas', this.updateVerifierState); + request.verifier.on('show_reciprocate_qr', this.updateVerifierState); try { - // on the requester side, this is also awaited in _startSAS, + // on the requester side, this is also awaited in startSAS, // but that's ok as verify should return the same promise. await request.verifier.verify(); } catch (err) { @@ -388,23 +405,22 @@ export default class VerificationPanel extends React.PureComponent { } }; - componentDidMount() { + public componentDidMount() { const {request} = this.props; - request.on("change", this._onRequestChange); + request.on("change", this.onRequestChange); if (request.verifier) { - const {request} = this.props; const {sasEvent, reciprocateQREvent} = request.verifier; this.setState({sasEvent, reciprocateQREvent}); } - this._onRequestChange(); + this.onRequestChange(); } - componentWillUnmount() { + public componentWillUnmount() { const {request} = this.props; if (request.verifier) { - request.verifier.off('show_sas', this._updateVerifierState); - request.verifier.off('show_reciprocate_qr', this._updateVerifierState); + request.verifier.off('show_sas', this.updateVerifierState); + request.verifier.off('show_reciprocate_qr', this.updateVerifierState); } - request.off("change", this._onRequestChange); + request.off("change", this.onRequestChange); } } diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 2e56e49be1..b73f03a9c5 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -28,6 +28,7 @@ import SettingsStore from "../../../settings/SettingsStore"; import {ContextMenu} from "../../structures/ContextMenu"; import {WidgetType} from "../../../widgets/WidgetType"; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; +import {Action} from "../../../dispatcher/actions"; // This should be below the dialog level (4000), but above the rest of the UI (1000-2000). // We sit in a context menu, so this should be given to the context menu. @@ -181,7 +182,7 @@ export default class Stickerpicker extends React.Component { case "stickerpicker_close": this.setState({showStickers: false}); break; - case "after_right_panel_phase_change": + case Action.AfterRightPanelPhaseChange: case "show_left_panel": case "hide_left_panel": this.setState({showStickers: false}); diff --git a/src/components/views/toasts/VerificationRequestToast.tsx b/src/components/views/toasts/VerificationRequestToast.tsx index cc41e81b33..8c8a74b2be 100644 --- a/src/components/views/toasts/VerificationRequestToast.tsx +++ b/src/components/views/toasts/VerificationRequestToast.tsx @@ -19,7 +19,8 @@ import React from "react"; import * as sdk from "../../../index"; import { _t } from '../../../languageHandler'; import {MatrixClientPeg} from '../../../MatrixClientPeg'; -import {RIGHT_PANEL_PHASES} from "../../../stores/RightPanelStorePhases"; +import {RightPanelPhases} from "../../../stores/RightPanelStorePhases"; +import {SetRightPanelPhasePayload} from "../../../dispatcher/payloads/SetRightPanelPhasePayload" import {userLabelForEventRoom} from "../../../utils/KeyVerificationStateObserver"; import dis from "../../../dispatcher/dispatcher"; import ToastStore from "../../../stores/ToastStore"; @@ -27,6 +28,7 @@ import Modal from "../../../Modal"; import GenericToast from "./GenericToast"; import {VerificationRequest} from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest"; import {DeviceInfo} from "matrix-js-sdk/src/crypto/deviceinfo"; +import {Action} from "../../../dispatcher/actions"; interface IProps { toastKey: string; @@ -104,9 +106,9 @@ export default class VerificationRequestToast extends React.PureComponent({ + action: Action.SetRightPanelPhase, + phase: RightPanelPhases.EncryptionPanel, refireParams: { verificationRequest: request, member: cli.getUser(request.otherUserId), diff --git a/src/dispatcher/actions.ts b/src/dispatcher/actions.ts index 519a799e67..6fb71df30d 100644 --- a/src/dispatcher/actions.ts +++ b/src/dispatcher/actions.ts @@ -79,4 +79,19 @@ export enum Action { * Changes room based on room list order and payload parameters. Should be used with ViewRoomDeltaPayload. */ ViewRoomDelta = "view_room_delta", + + /** + * Sets the phase for the right panel. Should be used with SetRightPanelPhasePayload. + */ + SetRightPanelPhase = "set_right_panel_phase", + + /** + * Toggles the right panel. Should be used with ToggleRightPanelPayload. + */ + ToggleRightPanel = "toggle_right_panel", + + /** + * Trigged after the phase of the right panel is set. Should be used with AfterRightPanelPhaseChangePayload. + */ + AfterRightPanelPhaseChange = "after_right_panel_phase_change", } diff --git a/src/dispatcher/payloads/AfterRightPanelPhaseChangePayload.ts b/src/dispatcher/payloads/AfterRightPanelPhaseChangePayload.ts new file mode 100644 index 0000000000..cfd4a2d3cc --- /dev/null +++ b/src/dispatcher/payloads/AfterRightPanelPhaseChangePayload.ts @@ -0,0 +1,30 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { RightPanelPhases } from "../../stores/RightPanelStorePhases"; +import { SetRightPanelPhaseRefireParams } from "./SetRightPanelPhasePayload"; +import { ActionPayload } from "../payloads"; +import { Action } from "../actions"; +import { VerificationRequest } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest"; + +interface AfterRightPanelPhaseChangeAction extends ActionPayload { + action: Action.AfterRightPanelPhaseChange; + phase: RightPanelPhases; + verificationRequestPromise?: Promise; +} + +export type AfterRightPanelPhaseChangePayload + = AfterRightPanelPhaseChangeAction & SetRightPanelPhaseRefireParams; diff --git a/src/dispatcher/payloads/SetRightPanelPhasePayload.ts b/src/dispatcher/payloads/SetRightPanelPhasePayload.ts new file mode 100644 index 0000000000..75dea9f3df --- /dev/null +++ b/src/dispatcher/payloads/SetRightPanelPhasePayload.ts @@ -0,0 +1,37 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { VerificationRequest } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest"; +import { RoomMember } from "matrix-js-sdk/src/models/room-member"; +import { RightPanelPhases } from "../../stores/RightPanelStorePhases"; +import { ActionPayload } from "../payloads"; +import { Action } from "../actions"; + +export interface SetRightPanelPhasePayload extends ActionPayload { + action: Action.SetRightPanelPhase; + + phase: RightPanelPhases; + refireParams?: SetRightPanelPhaseRefireParams; +} + +export interface SetRightPanelPhaseRefireParams { + member?: RoomMember; + verificationRequest?: VerificationRequest; + groupId?: string; + groupRoomId?: string; + // XXX: The type for event should 'view_3pid_invite' action's payload + event?: any; +} diff --git a/src/dispatcher/payloads/ToggleRightPanelPayload.ts b/src/dispatcher/payloads/ToggleRightPanelPayload.ts new file mode 100644 index 0000000000..0635194890 --- /dev/null +++ b/src/dispatcher/payloads/ToggleRightPanelPayload.ts @@ -0,0 +1,27 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { ActionPayload } from "../payloads"; +import { Action } from "../actions"; + +export interface ToggleRightPanelPayload extends ActionPayload { + action: Action.ToggleRightPanel; + + /** + * The type of room that the panel is toggled in. + */ + type: "group" | "room"; +} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 18e2da9a31..644cd03daf 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -426,6 +426,8 @@ "There was an error joining the room": "There was an error joining the room", "Sorry, your homeserver is too old to participate in this room.": "Sorry, your homeserver is too old to participate in this room.", "Please contact your homeserver administrator.": "Please contact your homeserver administrator.", + "The person who invited you already left the room.": "The person who invited you already left the room.", + "The person who invited you already left the room, or their server is offline.": "The person who invited you already left the room, or their server is offline.", "Failed to join room": "Failed to join room", "You joined the call": "You joined the call", "%(senderName)s joined the call": "%(senderName)s joined the call", diff --git a/src/stores/RightPanelStore.js b/src/stores/RightPanelStore.ts similarity index 57% rename from src/stores/RightPanelStore.js rename to src/stores/RightPanelStore.ts index 6920226448..dc5eb99a36 100644 --- a/src/stores/RightPanelStore.js +++ b/src/stores/RightPanelStore.ts @@ -17,163 +17,178 @@ limitations under the License. import dis from '../dispatcher/dispatcher'; import {pendingVerificationRequestForUser} from '../verification'; import {Store} from 'flux/utils'; -import SettingsStore from "../settings/SettingsStore"; -import {RIGHT_PANEL_PHASES, RIGHT_PANEL_PHASES_NO_ARGS} from "./RightPanelStorePhases"; -import {SettingLevel} from "../settings/SettingLevel"; +import SettingsStore, {SettingLevel} from "../settings/SettingsStore"; +import {RightPanelPhases, RIGHT_PANEL_PHASES_NO_ARGS} from "./RightPanelStorePhases"; +import {ActionPayload} from "../dispatcher/payloads"; +import {Action} from '../dispatcher/actions'; -const INITIAL_STATE = { +interface RightPanelStoreState { // Whether or not to show the right panel at all. We split out rooms and groups // because they're different flows for the user to follow. - showRoomPanel: SettingsStore.getValue("showRightPanelInRoom"), - showGroupPanel: SettingsStore.getValue("showRightPanelInGroup"), + showRoomPanel: boolean; + showGroupPanel: boolean; // The last phase (screen) the right panel was showing - lastRoomPhase: SettingsStore.getValue("lastRightPanelPhaseForRoom"), - lastGroupPhase: SettingsStore.getValue("lastRightPanelPhaseForGroup"), + lastRoomPhase: RightPanelPhases; + lastGroupPhase: RightPanelPhases; // Extra information about the last phase + lastRoomPhaseParams: {[key: string]: any}; +} + +const INITIAL_STATE: RightPanelStoreState = { + showRoomPanel: SettingsStore.getValue("showRightPanelInRoom"), + showGroupPanel: SettingsStore.getValue("showRightPanelInGroup"), + lastRoomPhase: SettingsStore.getValue("lastRightPanelPhaseForRoom"), + lastGroupPhase: SettingsStore.getValue("lastRightPanelPhaseForGroup"), lastRoomPhaseParams: {}, }; -const GROUP_PHASES = Object.keys(RIGHT_PANEL_PHASES).filter(k => k.startsWith("Group")); +const GROUP_PHASES = [ + RightPanelPhases.GroupMemberList, + RightPanelPhases.GroupRoomList, + RightPanelPhases.GroupRoomInfo, + RightPanelPhases.GroupMemberInfo, +]; const MEMBER_INFO_PHASES = [ - RIGHT_PANEL_PHASES.RoomMemberInfo, - RIGHT_PANEL_PHASES.Room3pidMemberInfo, - RIGHT_PANEL_PHASES.EncryptionPanel, + RightPanelPhases.RoomMemberInfo, + RightPanelPhases.Room3pidMemberInfo, + RightPanelPhases.EncryptionPanel, ]; /** * A class for tracking the state of the right panel between layouts and * sessions. */ -export default class RightPanelStore extends Store { - static _instance; +export default class RightPanelStore extends Store { + private static instance: RightPanelStore; + private state: RightPanelStoreState; constructor() { super(dis); // Initialise state - this._state = INITIAL_STATE; + this.state = INITIAL_STATE; } get isOpenForRoom(): boolean { - return this._state.showRoomPanel; + return this.state.showRoomPanel; } get isOpenForGroup(): boolean { - return this._state.showGroupPanel; + return this.state.showGroupPanel; } - get roomPanelPhase(): string { - return this._state.lastRoomPhase; + get roomPanelPhase(): RightPanelPhases { + return this.state.lastRoomPhase; } - get groupPanelPhase(): string { - return this._state.lastGroupPhase; + get groupPanelPhase(): RightPanelPhases { + return this.state.lastGroupPhase; } - get visibleRoomPanelPhase(): string { + get visibleRoomPanelPhase(): RightPanelPhases { return this.isOpenForRoom ? this.roomPanelPhase : null; } - get visibleGroupPanelPhase(): string { + get visibleGroupPanelPhase(): RightPanelPhases { return this.isOpenForGroup ? this.groupPanelPhase : null; } get roomPanelPhaseParams(): any { - return this._state.lastRoomPhaseParams || {}; + return this.state.lastRoomPhaseParams || {}; } - _setState(newState) { - this._state = Object.assign(this._state, newState); + private setState(newState: Partial) { + this.state = Object.assign(this.state, newState); SettingsStore.setValue( "showRightPanelInRoom", null, SettingLevel.DEVICE, - this._state.showRoomPanel, + this.state.showRoomPanel, ); SettingsStore.setValue( "showRightPanelInGroup", null, SettingLevel.DEVICE, - this._state.showGroupPanel, + this.state.showGroupPanel, ); - if (RIGHT_PANEL_PHASES_NO_ARGS.includes(this._state.lastRoomPhase)) { + if (RIGHT_PANEL_PHASES_NO_ARGS.includes(this.state.lastRoomPhase)) { SettingsStore.setValue( "lastRightPanelPhaseForRoom", null, SettingLevel.DEVICE, - this._state.lastRoomPhase, + this.state.lastRoomPhase, ); } - if (RIGHT_PANEL_PHASES_NO_ARGS.includes(this._state.lastGroupPhase)) { + if (RIGHT_PANEL_PHASES_NO_ARGS.includes(this.state.lastGroupPhase)) { SettingsStore.setValue( "lastRightPanelPhaseForGroup", null, SettingLevel.DEVICE, - this._state.lastGroupPhase, + this.state.lastGroupPhase, ); } this.__emitChange(); } - __onDispatch(payload) { + __onDispatch(payload: ActionPayload) { switch (payload.action) { case 'view_room': case 'view_group': // Reset to the member list if we're viewing member info - if (MEMBER_INFO_PHASES.includes(this._state.lastRoomPhase)) { - this._setState({lastRoomPhase: RIGHT_PANEL_PHASES.RoomMemberList, lastRoomPhaseParams: {}}); + if (MEMBER_INFO_PHASES.includes(this.state.lastRoomPhase)) { + this.setState({lastRoomPhase: RightPanelPhases.RoomMemberList, lastRoomPhaseParams: {}}); } // Do the same for groups - if (this._state.lastGroupPhase === RIGHT_PANEL_PHASES.GroupMemberInfo) { - this._setState({lastGroupPhase: RIGHT_PANEL_PHASES.GroupMemberList}); + if (this.state.lastGroupPhase === RightPanelPhases.GroupMemberInfo) { + this.setState({lastGroupPhase: RightPanelPhases.GroupMemberList}); } break; - case 'set_right_panel_phase': { + case Action.SetRightPanelPhase: { let targetPhase = payload.phase; let refireParams = payload.refireParams; // redirect to EncryptionPanel if there is an ongoing verification request - if (targetPhase === RIGHT_PANEL_PHASES.RoomMemberInfo && payload.refireParams) { + if (targetPhase === RightPanelPhases.RoomMemberInfo && payload.refireParams) { const {member} = payload.refireParams; const pendingRequest = pendingVerificationRequestForUser(member); if (pendingRequest) { - targetPhase = RIGHT_PANEL_PHASES.EncryptionPanel; + targetPhase = RightPanelPhases.EncryptionPanel; refireParams = { verificationRequest: pendingRequest, member, }; } } - if (!RIGHT_PANEL_PHASES[targetPhase]) { + if (!RightPanelPhases[targetPhase]) { console.warn(`Tried to switch right panel to unknown phase: ${targetPhase}`); return; } if (GROUP_PHASES.includes(targetPhase)) { - if (targetPhase === this._state.lastGroupPhase) { - this._setState({ - showGroupPanel: !this._state.showGroupPanel, + if (targetPhase === this.state.lastGroupPhase) { + this.setState({ + showGroupPanel: !this.state.showGroupPanel, }); } else { - this._setState({ + this.setState({ lastGroupPhase: targetPhase, showGroupPanel: true, }); } } else { - if (targetPhase === this._state.lastRoomPhase && !refireParams) { - this._setState({ - showRoomPanel: !this._state.showRoomPanel, + if (targetPhase === this.state.lastRoomPhase && !refireParams) { + this.setState({ + showRoomPanel: !this.state.showRoomPanel, }); } else { - this._setState({ + this.setState({ lastRoomPhase: targetPhase, showRoomPanel: true, lastRoomPhaseParams: refireParams || {}, @@ -183,27 +198,27 @@ export default class RightPanelStore extends Store { // Let things like the member info panel actually open to the right member. dis.dispatch({ - action: 'after_right_panel_phase_change', + action: Action.AfterRightPanelPhaseChange, phase: targetPhase, ...(refireParams || {}), }); break; } - case 'toggle_right_panel': + case Action.ToggleRightPanel: if (payload.type === "room") { - this._setState({ showRoomPanel: !this._state.showRoomPanel }); + this.setState({ showRoomPanel: !this.state.showRoomPanel }); } else { // group - this._setState({ showGroupPanel: !this._state.showGroupPanel }); + this.setState({ showGroupPanel: !this.state.showGroupPanel }); } break; } } static getSharedInstance(): RightPanelStore { - if (!RightPanelStore._instance) { - RightPanelStore._instance = new RightPanelStore(); + if (!RightPanelStore.instance) { + RightPanelStore.instance = new RightPanelStore(); } - return RightPanelStore._instance; + return RightPanelStore.instance; } } diff --git a/src/stores/RightPanelStorePhases.js b/src/stores/RightPanelStorePhases.ts similarity index 57% rename from src/stores/RightPanelStorePhases.js rename to src/stores/RightPanelStorePhases.ts index d9af320233..9045b17193 100644 --- a/src/stores/RightPanelStorePhases.js +++ b/src/stores/RightPanelStorePhases.ts @@ -15,28 +15,28 @@ limitations under the License. */ // These are in their own file because of circular imports being a problem. -export const RIGHT_PANEL_PHASES = Object.freeze({ +export enum RightPanelPhases { // Room stuff - RoomMemberList: 'RoomMemberList', - FilePanel: 'FilePanel', - NotificationPanel: 'NotificationPanel', - RoomMemberInfo: 'RoomMemberInfo', - EncryptionPanel: 'EncryptionPanel', + RoomMemberList = 'RoomMemberList', + FilePanel = 'FilePanel', + NotificationPanel = 'NotificationPanel', + RoomMemberInfo = 'RoomMemberInfo', + EncryptionPanel = 'EncryptionPanel', - Room3pidMemberInfo: 'Room3pidMemberInfo', + Room3pidMemberInfo = 'Room3pidMemberInfo', // Group stuff - GroupMemberList: 'GroupMemberList', - GroupRoomList: 'GroupRoomList', - GroupRoomInfo: 'GroupRoomInfo', - GroupMemberInfo: 'GroupMemberInfo', -}); + GroupMemberList = 'GroupMemberList', + GroupRoomList = 'GroupRoomList', + GroupRoomInfo = 'GroupRoomInfo', + GroupMemberInfo = 'GroupMemberInfo', +} // These are the phases that are safe to persist (the ones that don't require additional // arguments). export const RIGHT_PANEL_PHASES_NO_ARGS = [ - RIGHT_PANEL_PHASES.NotificationPanel, - RIGHT_PANEL_PHASES.FilePanel, - RIGHT_PANEL_PHASES.RoomMemberList, - RIGHT_PANEL_PHASES.GroupMemberList, - RIGHT_PANEL_PHASES.GroupRoomList, + RightPanelPhases.NotificationPanel, + RightPanelPhases.FilePanel, + RightPanelPhases.RoomMemberList, + RightPanelPhases.GroupMemberList, + RightPanelPhases.GroupRoomList, ]; diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js index 6e5007895c..3c37a31174 100644 --- a/src/stores/RoomViewStore.js +++ b/src/stores/RoomViewStore.js @@ -267,12 +267,22 @@ class RoomViewStore extends Store { console.log("Failed to join room:", msg); if (err.name === "ConnectionError") { msg = _t("There was an error joining the room"); - } - if (err.errcode === 'M_INCOMPATIBLE_ROOM_VERSION') { + } else if (err.errcode === 'M_INCOMPATIBLE_ROOM_VERSION') { msg =
{_t("Sorry, your homeserver is too old to participate in this room.")}
{_t("Please contact your homeserver administrator.")}
; + } else if (err.httpStatus === 404) { + const invitingUserId = this._getInvitingUserId(this._state.roomId); + // only provide a better error message for invites + if (invitingUserId) { + // if the inviting user is on the same HS, there can only be one cause: they left. + if (invitingUserId.endsWith(`:${MatrixClientPeg.get().getDomain()}`)) { + msg = _t("The person who invited you already left the room."); + } else { + msg = _t("The person who invited you already left the room, or their server is offline."); + } + } } const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); Modal.createTrackedDialog('Failed to join room', '', ErrorDialog, { @@ -282,6 +292,16 @@ class RoomViewStore extends Store { }); } + _getInvitingUserId(roomId) { + const cli = MatrixClientPeg.get(); + const room = cli.getRoom(roomId); + if (room && room.getMyMembership() === "invite") { + const myMember = room.getMember(cli.getUserId()); + const inviteEvent = myMember ? myMember.events.member : null; + return inviteEvent && inviteEvent.getSender(); + } + } + _joinRoomError(payload) { this._setState({ joining: false, diff --git a/src/verification.js b/src/verification.js index 1dccb7dc28..36fb8b0e4f 100644 --- a/src/verification.js +++ b/src/verification.js @@ -19,10 +19,11 @@ import dis from "./dispatcher/dispatcher"; import Modal from './Modal'; import * as sdk from './index'; import { _t } from './languageHandler'; -import {RIGHT_PANEL_PHASES} from "./stores/RightPanelStorePhases"; +import {RightPanelPhases} from "./stores/RightPanelStorePhases"; import {findDMForUser} from './createRoom'; import {accessSecretStorage} from './CrossSigningManager'; import {verificationMethods} from 'matrix-js-sdk/src/crypto'; +import {Action} from './dispatcher/actions'; async function enable4SIfNeeded() { const cli = MatrixClientPeg.get(); @@ -91,8 +92,8 @@ export async function verifyDevice(user, device) { verificationMethods.SAS, ); dis.dispatch({ - action: "set_right_panel_phase", - phase: RIGHT_PANEL_PHASES.EncryptionPanel, + action: Action.SetRightPanelPhase, + phase: RightPanelPhases.EncryptionPanel, refireParams: {member: user, verificationRequestPromise}, }); } else if (action === "legacy") { @@ -120,8 +121,8 @@ export async function legacyVerifyUser(user) { } const verificationRequestPromise = cli.requestVerification(user.userId); dis.dispatch({ - action: "set_right_panel_phase", - phase: RIGHT_PANEL_PHASES.EncryptionPanel, + action: Action.SetRightPanelPhase, + phase: RightPanelPhases.EncryptionPanel, refireParams: {member: user, verificationRequestPromise}, }); } @@ -132,8 +133,8 @@ export async function verifyUser(user) { } const existingRequest = pendingVerificationRequestForUser(user); dis.dispatch({ - action: "set_right_panel_phase", - phase: RIGHT_PANEL_PHASES.EncryptionPanel, + action: Action.SetRightPanelPhase, + phase: RightPanelPhases.EncryptionPanel, refireParams: { member: user, verificationRequest: existingRequest,