mirror of https://github.com/vector-im/riot-web
Merge branch 'develop' of github.com:matrix-org/matrix-react-sdk into export-conversations
commit
6a4e2672f6
171
CHANGELOG.md
171
CHANGELOG.md
|
@ -1,3 +1,174 @@
|
|||
Changes in [3.25.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.25.0) (2021-07-05)
|
||||
=====================================================================================================
|
||||
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.25.0-rc.1...v3.25.0)
|
||||
|
||||
* Remove reminescent references to the tinter
|
||||
[\#6316](https://github.com/matrix-org/matrix-react-sdk/pull/6316)
|
||||
* Update to released version of js-sdk
|
||||
|
||||
Changes in [3.25.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.25.0-rc.1) (2021-06-29)
|
||||
===============================================================================================================
|
||||
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.24.0...v3.25.0-rc.1)
|
||||
|
||||
* Update to js-sdk v12.0.1-rc.1
|
||||
* Translations update from Weblate
|
||||
[\#6286](https://github.com/matrix-org/matrix-react-sdk/pull/6286)
|
||||
* Fix back button on user info card after clicking a permalink
|
||||
[\#6277](https://github.com/matrix-org/matrix-react-sdk/pull/6277)
|
||||
* Group ACLs with MELS
|
||||
[\#6280](https://github.com/matrix-org/matrix-react-sdk/pull/6280)
|
||||
* Fix editState not getting passed through
|
||||
[\#6282](https://github.com/matrix-org/matrix-react-sdk/pull/6282)
|
||||
* Migrate message context menu to IconizedContextMenu
|
||||
[\#5671](https://github.com/matrix-org/matrix-react-sdk/pull/5671)
|
||||
* Improve audio recording performance
|
||||
[\#6240](https://github.com/matrix-org/matrix-react-sdk/pull/6240)
|
||||
* Fix multiple timeline panels handling composer and edit events
|
||||
[\#6278](https://github.com/matrix-org/matrix-react-sdk/pull/6278)
|
||||
* Let m.notice messages mark a room as unread
|
||||
[\#6281](https://github.com/matrix-org/matrix-react-sdk/pull/6281)
|
||||
* Removes the override on the Bubble Container
|
||||
[\#5953](https://github.com/matrix-org/matrix-react-sdk/pull/5953)
|
||||
* Fix IRC layout regressions
|
||||
[\#6193](https://github.com/matrix-org/matrix-react-sdk/pull/6193)
|
||||
* Fix trashcan.svg by exporting it with its viewbox
|
||||
[\#6248](https://github.com/matrix-org/matrix-react-sdk/pull/6248)
|
||||
* Fix tiny scrollbar dot on chrome/electron in Forward Dialog
|
||||
[\#6276](https://github.com/matrix-org/matrix-react-sdk/pull/6276)
|
||||
* Upgrade puppeteer to use newer version of Chrome
|
||||
[\#6268](https://github.com/matrix-org/matrix-react-sdk/pull/6268)
|
||||
* Make toast dismiss button less prominent
|
||||
[\#6275](https://github.com/matrix-org/matrix-react-sdk/pull/6275)
|
||||
* Encrypt the voice message file if needed
|
||||
[\#6269](https://github.com/matrix-org/matrix-react-sdk/pull/6269)
|
||||
* Fix hyper-precise presence
|
||||
[\#6270](https://github.com/matrix-org/matrix-react-sdk/pull/6270)
|
||||
* Fix issues around private spaces, including previewable
|
||||
[\#6265](https://github.com/matrix-org/matrix-react-sdk/pull/6265)
|
||||
* Make _pinned messages_ in `m.room.pinned_events` event clickable
|
||||
[\#6257](https://github.com/matrix-org/matrix-react-sdk/pull/6257)
|
||||
* Fix space avatar management layout being broken
|
||||
[\#6266](https://github.com/matrix-org/matrix-react-sdk/pull/6266)
|
||||
* Convert EntityTile, MemberTile and PresenceLabel to TS
|
||||
[\#6251](https://github.com/matrix-org/matrix-react-sdk/pull/6251)
|
||||
* Fix UserInfo not working when rendered without a room
|
||||
[\#6260](https://github.com/matrix-org/matrix-react-sdk/pull/6260)
|
||||
* Update membership reason handling, including leave reason displaying
|
||||
[\#6253](https://github.com/matrix-org/matrix-react-sdk/pull/6253)
|
||||
* Consolidate types with js-sdk changes
|
||||
[\#6220](https://github.com/matrix-org/matrix-react-sdk/pull/6220)
|
||||
* Fix edit history modal
|
||||
[\#6258](https://github.com/matrix-org/matrix-react-sdk/pull/6258)
|
||||
* Convert MemberList to TS
|
||||
[\#6249](https://github.com/matrix-org/matrix-react-sdk/pull/6249)
|
||||
* Fix two PRs duplicating the css attribute
|
||||
[\#6259](https://github.com/matrix-org/matrix-react-sdk/pull/6259)
|
||||
* Improve invite error messages in InviteDialog for room invites
|
||||
[\#6201](https://github.com/matrix-org/matrix-react-sdk/pull/6201)
|
||||
* Fix invite dialog being cut off when it has limited results
|
||||
[\#6256](https://github.com/matrix-org/matrix-react-sdk/pull/6256)
|
||||
* Fix pinning event in a room which hasn't had events pinned in before
|
||||
[\#6255](https://github.com/matrix-org/matrix-react-sdk/pull/6255)
|
||||
* Allow modal widget buttons to be disabled when the modal opens
|
||||
[\#6178](https://github.com/matrix-org/matrix-react-sdk/pull/6178)
|
||||
* Decrease e2e shield fill mask size so that it doesn't overlap
|
||||
[\#6250](https://github.com/matrix-org/matrix-react-sdk/pull/6250)
|
||||
* Dial Pad UI bug fixes
|
||||
[\#5786](https://github.com/matrix-org/matrix-react-sdk/pull/5786)
|
||||
* Simple handling of mid-call output changes
|
||||
[\#6247](https://github.com/matrix-org/matrix-react-sdk/pull/6247)
|
||||
* Improve ForwardDialog performance by using TruncatedList
|
||||
[\#6228](https://github.com/matrix-org/matrix-react-sdk/pull/6228)
|
||||
* Fix dependency and lockfile mismatch
|
||||
[\#6246](https://github.com/matrix-org/matrix-react-sdk/pull/6246)
|
||||
* Improve room directory click behaviour
|
||||
[\#6234](https://github.com/matrix-org/matrix-react-sdk/pull/6234)
|
||||
* Fix keyboard accessibility of the space panel
|
||||
[\#6239](https://github.com/matrix-org/matrix-react-sdk/pull/6239)
|
||||
* Add ways to manage addresses for Spaces
|
||||
[\#6151](https://github.com/matrix-org/matrix-react-sdk/pull/6151)
|
||||
* Hide communities invites and the community autocompleter when Spaces on
|
||||
[\#6244](https://github.com/matrix-org/matrix-react-sdk/pull/6244)
|
||||
* Convert bunch of files to TS
|
||||
[\#6241](https://github.com/matrix-org/matrix-react-sdk/pull/6241)
|
||||
* Open local addresses section by default when there are no existing local
|
||||
addresses
|
||||
[\#6179](https://github.com/matrix-org/matrix-react-sdk/pull/6179)
|
||||
* Allow reordering of the space panel via Drag and Drop
|
||||
[\#6137](https://github.com/matrix-org/matrix-react-sdk/pull/6137)
|
||||
* Replace drag and drop mechanism in communities with something simpler
|
||||
[\#6134](https://github.com/matrix-org/matrix-react-sdk/pull/6134)
|
||||
* EventTilePreview fixes
|
||||
[\#6000](https://github.com/matrix-org/matrix-react-sdk/pull/6000)
|
||||
* Upgrade @types/react and @types/react-dom
|
||||
[\#6233](https://github.com/matrix-org/matrix-react-sdk/pull/6233)
|
||||
* Fix type error in the SpaceStore
|
||||
[\#6242](https://github.com/matrix-org/matrix-react-sdk/pull/6242)
|
||||
* Add experimental options to the Spaces beta
|
||||
[\#6199](https://github.com/matrix-org/matrix-react-sdk/pull/6199)
|
||||
* Consolidate types with js-sdk changes
|
||||
[\#6215](https://github.com/matrix-org/matrix-react-sdk/pull/6215)
|
||||
* Fix branch matching for Buildkite
|
||||
[\#6236](https://github.com/matrix-org/matrix-react-sdk/pull/6236)
|
||||
* Migrate SearchBar to TypeScript
|
||||
[\#6230](https://github.com/matrix-org/matrix-react-sdk/pull/6230)
|
||||
* Add support to keyboard shortcuts dialog for [digits]
|
||||
[\#6088](https://github.com/matrix-org/matrix-react-sdk/pull/6088)
|
||||
* Fix modal opening race condition
|
||||
[\#6238](https://github.com/matrix-org/matrix-react-sdk/pull/6238)
|
||||
* Deprecate FormButton in favour of AccessibleButton
|
||||
[\#6229](https://github.com/matrix-org/matrix-react-sdk/pull/6229)
|
||||
* Add PR template
|
||||
[\#6216](https://github.com/matrix-org/matrix-react-sdk/pull/6216)
|
||||
* Prefer canonical aliases while autocompleting rooms
|
||||
[\#6222](https://github.com/matrix-org/matrix-react-sdk/pull/6222)
|
||||
* Fix quote button
|
||||
[\#6232](https://github.com/matrix-org/matrix-react-sdk/pull/6232)
|
||||
* Restore branch matching support for GitHub Actions e2e tests
|
||||
[\#6224](https://github.com/matrix-org/matrix-react-sdk/pull/6224)
|
||||
* Fix View Source accessing renamed private field on MatrixEvent
|
||||
[\#6225](https://github.com/matrix-org/matrix-react-sdk/pull/6225)
|
||||
* Fix ConfirmUserActionDialog returning an input field rather than text
|
||||
[\#6219](https://github.com/matrix-org/matrix-react-sdk/pull/6219)
|
||||
* Revert "Partially restore immutable event objects at the rendering layer"
|
||||
[\#6221](https://github.com/matrix-org/matrix-react-sdk/pull/6221)
|
||||
* Add jq to e2e tests Dockerfile
|
||||
[\#6218](https://github.com/matrix-org/matrix-react-sdk/pull/6218)
|
||||
* Partially restore immutable event objects at the rendering layer
|
||||
[\#6196](https://github.com/matrix-org/matrix-react-sdk/pull/6196)
|
||||
* Update MSC number references for voice messages
|
||||
[\#6197](https://github.com/matrix-org/matrix-react-sdk/pull/6197)
|
||||
* Fix phase enum usage in JS modules as well
|
||||
[\#6214](https://github.com/matrix-org/matrix-react-sdk/pull/6214)
|
||||
* Migrate some dialogs to TypeScript
|
||||
[\#6185](https://github.com/matrix-org/matrix-react-sdk/pull/6185)
|
||||
* Typescript fixes due to MatrixEvent being TSified
|
||||
[\#6208](https://github.com/matrix-org/matrix-react-sdk/pull/6208)
|
||||
* Allow click-to-ping, quote & emoji picker for edit composer too
|
||||
[\#5858](https://github.com/matrix-org/matrix-react-sdk/pull/5858)
|
||||
* Add call silencing
|
||||
[\#6082](https://github.com/matrix-org/matrix-react-sdk/pull/6082)
|
||||
* Fix types in SlashCommands
|
||||
[\#6207](https://github.com/matrix-org/matrix-react-sdk/pull/6207)
|
||||
* Benchmark multiple common user scenario
|
||||
[\#6190](https://github.com/matrix-org/matrix-react-sdk/pull/6190)
|
||||
* Fix forward dialog message preview display names
|
||||
[\#6204](https://github.com/matrix-org/matrix-react-sdk/pull/6204)
|
||||
* Remove stray bullet point in reply preview
|
||||
[\#6206](https://github.com/matrix-org/matrix-react-sdk/pull/6206)
|
||||
* Stop requesting null next replies from the server
|
||||
[\#6203](https://github.com/matrix-org/matrix-react-sdk/pull/6203)
|
||||
* Fix soft crash caused by a broken shouldComponentUpdate
|
||||
[\#6202](https://github.com/matrix-org/matrix-react-sdk/pull/6202)
|
||||
* Keep composer reply when scrolling away from a highlighted event
|
||||
[\#6200](https://github.com/matrix-org/matrix-react-sdk/pull/6200)
|
||||
* Cache virtual/native room mappings when they're created
|
||||
[\#6194](https://github.com/matrix-org/matrix-react-sdk/pull/6194)
|
||||
* Disable comment-on-alert
|
||||
[\#6191](https://github.com/matrix-org/matrix-react-sdk/pull/6191)
|
||||
* Bump postcss from 7.0.35 to 7.0.36
|
||||
[\#6195](https://github.com/matrix-org/matrix-react-sdk/pull/6195)
|
||||
|
||||
Changes in [3.24.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.24.0) (2021-06-21)
|
||||
=====================================================================================================
|
||||
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.24.0-rc.1...v3.24.0)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "matrix-react-sdk",
|
||||
"version": "3.24.0",
|
||||
"version": "3.25.0",
|
||||
"description": "SDK for matrix.org using React",
|
||||
"author": "matrix.org",
|
||||
"repository": {
|
||||
|
@ -55,7 +55,6 @@
|
|||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@types/streamsaver": "^2.0.0",
|
||||
"@types/commonmark": "^0.27.4",
|
||||
"await-lock": "^2.1.0",
|
||||
"blurhash": "^1.1.3",
|
||||
"browser-encrypt-attachment": "^0.3.0",
|
||||
|
@ -81,7 +80,7 @@
|
|||
"katex": "^0.12.0",
|
||||
"linkifyjs": "^2.1.9",
|
||||
"lodash": "^4.17.20",
|
||||
"matrix-js-sdk": "12.0.0",
|
||||
"matrix-js-sdk": "12.0.1",
|
||||
"matrix-widget-api": "^0.1.0-beta.15",
|
||||
"minimist": "^1.2.5",
|
||||
"opus-recorder": "^8.0.3",
|
||||
|
@ -93,6 +92,7 @@
|
|||
"re-resizable": "^6.9.0",
|
||||
"react": "^17.0.2",
|
||||
"react-beautiful-dnd": "^13.1.0",
|
||||
"react-blurhash": "^0.1.3",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-focus-lock": "^2.5.0",
|
||||
"react-transition-group": "^4.4.1",
|
||||
|
@ -127,6 +127,7 @@
|
|||
"@peculiar/webcrypto": "^1.1.4",
|
||||
"@sinonjs/fake-timers": "^7.0.2",
|
||||
"@types/classnames": "^2.2.11",
|
||||
"@types/commonmark": "^0.27.4",
|
||||
"@types/counterpart": "^0.18.1",
|
||||
"@types/diff-match-patch": "^1.0.32",
|
||||
"@types/flux": "^3.1.9",
|
||||
|
|
|
@ -57,7 +57,6 @@
|
|||
@import "./views/avatars/_BaseAvatar.scss";
|
||||
@import "./views/avatars/_DecoratedRoomAvatar.scss";
|
||||
@import "./views/avatars/_MemberStatusMessageAvatar.scss";
|
||||
@import "./views/avatars/_PulsedAvatar.scss";
|
||||
@import "./views/avatars/_WidgetAvatar.scss";
|
||||
@import "./views/beta/_BetaCard.scss";
|
||||
@import "./views/context_menus/_CallContextMenu.scss";
|
||||
|
@ -203,6 +202,7 @@
|
|||
@import "./views/rooms/_GroupLayout.scss";
|
||||
@import "./views/rooms/_IRCLayout.scss";
|
||||
@import "./views/rooms/_JumpToBottomButton.scss";
|
||||
@import "./views/rooms/_LinkPreviewGroup.scss";
|
||||
@import "./views/rooms/_LinkPreviewWidget.scss";
|
||||
@import "./views/rooms/_MemberInfo.scss";
|
||||
@import "./views/rooms/_MemberList.scss";
|
||||
|
@ -263,6 +263,7 @@
|
|||
@import "./views/voip/_CallContainer.scss";
|
||||
@import "./views/voip/_CallView.scss";
|
||||
@import "./views/voip/_CallViewForRoom.scss";
|
||||
@import "./views/voip/_CallPreview.scss";
|
||||
@import "./views/voip/_DialPad.scss";
|
||||
@import "./views/voip/_DialPadContextMenu.scss";
|
||||
@import "./views/voip/_DialPadModal.scss";
|
||||
|
|
|
@ -121,23 +121,51 @@ $pulse-color: $pinned-unread-color;
|
|||
box-shadow: 0 0 0 0 rgba($pulse-color, 1);
|
||||
animation: mx_RightPanel_indicator_pulse 2s infinite;
|
||||
animation-iteration-count: 1;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
top: 0;
|
||||
left: 0;
|
||||
transform: scale(1);
|
||||
transform-origin: center center;
|
||||
animation-name: mx_RightPanel_indicator_pulse_shadow;
|
||||
animation-duration: inherit;
|
||||
animation-iteration-count: inherit;
|
||||
border-radius: 50%;
|
||||
background: rgba($pulse-color, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes mx_RightPanel_indicator_pulse {
|
||||
0% {
|
||||
transform: scale(0.95);
|
||||
box-shadow: 0 0 0 0 rgba($pulse-color, 0.7);
|
||||
}
|
||||
|
||||
70% {
|
||||
transform: scale(1);
|
||||
box-shadow: 0 0 0 10px rgba($pulse-color, 0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0.95);
|
||||
box-shadow: 0 0 0 0 rgba($pulse-color, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes mx_RightPanel_indicator_pulse_shadow {
|
||||
0% {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
70% {
|
||||
transform: scale(2.2);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -57,14 +57,15 @@ limitations under the License.
|
|||
|
||||
@keyframes mx_RoomView_fileDropTarget_image_animation {
|
||||
from {
|
||||
width: 0px;
|
||||
transform: scaleX(0);
|
||||
}
|
||||
to {
|
||||
width: 32px;
|
||||
transform: scaleX(1);
|
||||
}
|
||||
}
|
||||
|
||||
.mx_RoomView_fileDropTarget_image {
|
||||
width: 32px;
|
||||
animation: mx_RoomView_fileDropTarget_image_animation;
|
||||
animation-duration: 0.5s;
|
||||
margin-bottom: 16px;
|
||||
|
|
|
@ -110,24 +110,52 @@ $dot-size: 12px;
|
|||
width: $dot-size;
|
||||
transform: scale(1);
|
||||
background: rgba($pulse-color, 1);
|
||||
box-shadow: 0 0 0 0 rgba($pulse-color, 1);
|
||||
animation: mx_Beta_bluePulse 2s infinite;
|
||||
animation-iteration-count: 20;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
top: 0;
|
||||
left: 0;
|
||||
transform: scale(1);
|
||||
transform-origin: center center;
|
||||
animation-name: mx_Beta_bluePulse_shadow;
|
||||
animation-duration: inherit;
|
||||
animation-iteration-count: inherit;
|
||||
border-radius: 50%;
|
||||
background: rgba($pulse-color, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes mx_Beta_bluePulse {
|
||||
0% {
|
||||
transform: scale(0.95);
|
||||
box-shadow: 0 0 0 0 rgba($pulse-color, 0.7);
|
||||
}
|
||||
|
||||
70% {
|
||||
transform: scale(1);
|
||||
box-shadow: 0 0 0 10px rgba($pulse-color, 0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0.95);
|
||||
box-shadow: 0 0 0 0 rgba($pulse-color, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes mx_Beta_bluePulse_shadow {
|
||||
0% {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
70% {
|
||||
transform: scale(2.2);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ limitations under the License.
|
|||
left: 0;
|
||||
top: 2px; // alignment
|
||||
background-image: url("$(res)/img/element-icons/warning-badge.svg");
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
.mx_AccessSecretStorageDialog_reset_link {
|
||||
|
|
|
@ -477,8 +477,7 @@ $hover-select-border: 4px;
|
|||
|
||||
pre, code {
|
||||
font-family: $monospace-font-family !important;
|
||||
// deliberate constants as we're behind an invert filter
|
||||
color: #333;
|
||||
background-color: $header-panel-bg-color;
|
||||
}
|
||||
|
||||
pre {
|
||||
|
@ -488,11 +487,6 @@ $hover-select-border: 4px;
|
|||
overflow-x: overlay;
|
||||
overflow-y: visible;
|
||||
}
|
||||
|
||||
code {
|
||||
// deliberate constants as we're behind an invert filter
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_EventTile_lineNumbers {
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
Copyright 2021 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.
|
||||
*/
|
||||
|
||||
.mx_LinkPreviewGroup {
|
||||
.mx_LinkPreviewGroup_hide {
|
||||
cursor: pointer;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
|
||||
img {
|
||||
flex: 0 0 40px;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .mx_LinkPreviewGroup_hide img,
|
||||
.mx_LinkPreviewGroup_hide.focus-visible:focus img {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
> .mx_AccessibleButton {
|
||||
color: $accent-color;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
|
@ -33,38 +33,29 @@ limitations under the License.
|
|||
.mx_LinkPreviewWidget_caption {
|
||||
margin-left: 15px;
|
||||
flex: 1 1 auto;
|
||||
overflow-x: hidden; // cause it to wrap rather than clip
|
||||
}
|
||||
|
||||
.mx_LinkPreviewWidget_title {
|
||||
display: inline;
|
||||
font-weight: bold;
|
||||
white-space: normal;
|
||||
}
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
|
||||
.mx_LinkPreviewWidget_siteName {
|
||||
display: inline;
|
||||
.mx_LinkPreviewWidget_siteName {
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_LinkPreviewWidget_description {
|
||||
margin-top: 8px;
|
||||
white-space: normal;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.mx_LinkPreviewWidget_cancel {
|
||||
cursor: pointer;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
|
||||
img {
|
||||
flex: 0 0 40px;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_LinkPreviewWidget:hover .mx_LinkPreviewWidget_cancel img,
|
||||
.mx_LinkPreviewWidget_cancel.focus-visible:focus img {
|
||||
visibility: visible;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.mx_MatrixChat_useCompactLayout {
|
||||
|
|
|
@ -30,8 +30,8 @@ limitations under the License.
|
|||
pointer-events: initial; // restore pointer events so the user can leave/interact
|
||||
cursor: pointer;
|
||||
|
||||
.mx_CallView_video {
|
||||
width: 350px;
|
||||
.mx_VideoFeed_remote.mx_VideoFeed_voice {
|
||||
min-height: 150px;
|
||||
}
|
||||
|
||||
.mx_VideoFeed_local {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2021 Šimon Brandner <simon.bra.ag@gmail.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -14,17 +14,8 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_PulsedAvatar {
|
||||
@keyframes shadow-pulse {
|
||||
0% {
|
||||
box-shadow: 0 0 0 0px rgba($accent-color, 0.2);
|
||||
}
|
||||
100% {
|
||||
box-shadow: 0 0 0 6px rgba($accent-color, 0);
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
animation: shadow-pulse 1s infinite;
|
||||
}
|
||||
.mx_CallPreview {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
|
@ -39,7 +39,6 @@ limitations under the License.
|
|||
.mx_CallView_pip {
|
||||
width: 320px;
|
||||
padding-bottom: 8px;
|
||||
margin-top: 10px;
|
||||
background-color: $voipcall-plinth-color;
|
||||
box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.20);
|
||||
border-radius: 8px;
|
||||
|
|
|
@ -15,8 +15,6 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
.mx_VideoFeed_voice {
|
||||
// We don't want to collide with the call controls that have 52px of height
|
||||
padding-bottom: 52px;
|
||||
background-color: $inverted-bg-color;
|
||||
}
|
||||
|
||||
|
|
|
@ -119,8 +119,6 @@ $voipcall-plinth-color: #394049;
|
|||
|
||||
$theme-button-bg-color: #e3e8f0;
|
||||
$dialpad-button-bg-color: #6F7882;
|
||||
;
|
||||
|
||||
|
||||
$roomlist-button-bg-color: rgba(141, 151, 165, 0.2); // Buttons include the filter box, explore button, and sublist buttons
|
||||
$roomlist-filter-active-bg-color: $bg-color;
|
||||
|
@ -274,24 +272,7 @@ $composer-shadow-color: rgba(0, 0, 0, 0.28);
|
|||
}
|
||||
|
||||
// markdown overrides:
|
||||
.mx_EventTile_content .markdown-body pre:hover {
|
||||
border-color: #808080 !important; // inverted due to rules below
|
||||
scrollbar-color: rgba(0, 0, 0, 0.2) transparent; // copied from light theme due to inversion below
|
||||
// the code above works only in Firefox, this is for other browsers
|
||||
// see https://developer.mozilla.org/en-US/docs/Web/CSS/scrollbar-color
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(0, 0, 0, 0.2); // copied from light theme due to inversion below
|
||||
}
|
||||
}
|
||||
.mx_EventTile_content .markdown-body {
|
||||
pre, code {
|
||||
filter: invert(1);
|
||||
}
|
||||
|
||||
pre code {
|
||||
filter: none;
|
||||
}
|
||||
|
||||
table {
|
||||
tr {
|
||||
background-color: #000000;
|
||||
|
@ -301,18 +282,9 @@ $composer-shadow-color: rgba(0, 0, 0, 0.28);
|
|||
background-color: #080808;
|
||||
}
|
||||
}
|
||||
|
||||
blockquote {
|
||||
color: #919191;
|
||||
}
|
||||
}
|
||||
|
||||
// diff highlight colors
|
||||
// intentionally swapped to avoid inversion
|
||||
.hljs-addition {
|
||||
background: #fdd;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
background: #dfd;
|
||||
// highlight.js overrides
|
||||
.hljs-tag {
|
||||
color: inherit; // Without this they'd be weirdly blue which doesn't match the theme
|
||||
}
|
||||
|
|
|
@ -9,3 +9,4 @@
|
|||
@import "_dark.scss";
|
||||
@import "../../light/css/_mods.scss";
|
||||
@import "../../../../res/css/_components.scss";
|
||||
@import url("highlight.js/styles/atom-one-dark.css");
|
||||
|
|
|
@ -118,7 +118,7 @@ $voipcall-plinth-color: #394049;
|
|||
|
||||
$theme-button-bg-color: #e3e8f0;
|
||||
$dialpad-button-bg-color: #6F7882;
|
||||
;
|
||||
|
||||
|
||||
$roomlist-button-bg-color: #1A1D23; // Buttons include the filter box, explore button, and sublist buttons
|
||||
$roomlist-filter-active-bg-color: $roomlist-button-bg-color;
|
||||
|
@ -249,7 +249,7 @@ $composer-shadow-color: tranparent;
|
|||
@define-mixin mx_DialogButton_secondary {
|
||||
// flip colours for the secondary ones
|
||||
font-weight: 600;
|
||||
border: 1px solid $accent-color ! important;
|
||||
border: 1px solid $accent-color !important;
|
||||
color: $accent-color;
|
||||
background-color: $button-secondary-bg-color;
|
||||
}
|
||||
|
@ -267,18 +267,7 @@ $composer-shadow-color: tranparent;
|
|||
}
|
||||
|
||||
// markdown overrides:
|
||||
.mx_EventTile_content .markdown-body pre:hover {
|
||||
border-color: #808080 !important; // inverted due to rules below
|
||||
}
|
||||
.mx_EventTile_content .markdown-body {
|
||||
pre, code {
|
||||
filter: invert(1);
|
||||
}
|
||||
|
||||
pre code {
|
||||
filter: none;
|
||||
}
|
||||
|
||||
table {
|
||||
tr {
|
||||
background-color: #000000;
|
||||
|
@ -290,12 +279,7 @@ $composer-shadow-color: tranparent;
|
|||
}
|
||||
}
|
||||
|
||||
// diff highlight colors
|
||||
// intentionally swapped to avoid inversion
|
||||
.hljs-addition {
|
||||
background: #fdd;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
background: #dfd;
|
||||
// highlight.js overrides:
|
||||
.hljs-tag {
|
||||
color: inherit; // Without this they'd be weirdly blue which doesn't match the theme
|
||||
}
|
||||
|
|
|
@ -4,3 +4,4 @@
|
|||
@import "../../legacy-light/css/_legacy-light.scss";
|
||||
@import "_legacy-dark.scss";
|
||||
@import "../../../../res/css/_components.scss";
|
||||
@import url("highlight.js/styles/atom-one-dark.css");
|
||||
|
|
|
@ -3,3 +3,4 @@
|
|||
@import "_fonts.scss";
|
||||
@import "_legacy-light.scss";
|
||||
@import "../../../../res/css/_components.scss";
|
||||
@import url("highlight.js/styles/atom-one-light.css");
|
||||
|
|
|
@ -4,3 +4,4 @@
|
|||
@import "_light.scss";
|
||||
@import "_mods.scss";
|
||||
@import "../../../../res/css/_components.scss";
|
||||
@import url("highlight.js/styles/atom-one-light.css");
|
||||
|
|
|
@ -6,8 +6,8 @@ scripts/fetchdep.sh matrix-org matrix-js-sdk
|
|||
|
||||
pushd matrix-js-sdk
|
||||
yarn link
|
||||
yarn install $@
|
||||
yarn install --pure-lockfile $@
|
||||
popd
|
||||
|
||||
yarn link matrix-js-sdk
|
||||
yarn install $@
|
||||
yarn install --pure-lockfile $@
|
||||
|
|
|
@ -13,13 +13,13 @@
|
|||
scripts/fetchdep.sh matrix-org matrix-js-sdk
|
||||
pushd matrix-js-sdk
|
||||
yarn link
|
||||
yarn install
|
||||
yarn install --pure-lockfile
|
||||
popd
|
||||
|
||||
# Now set up the react-sdk
|
||||
yarn link matrix-js-sdk
|
||||
yarn link
|
||||
yarn install
|
||||
yarn install --pure-lockfile
|
||||
yarn reskindex
|
||||
|
||||
# Finally, set up element-web
|
||||
|
@ -27,6 +27,6 @@ scripts/fetchdep.sh vector-im element-web
|
|||
pushd element-web
|
||||
yarn link matrix-js-sdk
|
||||
yarn link matrix-react-sdk
|
||||
yarn install
|
||||
yarn install --pure-lockfile
|
||||
yarn build:res
|
||||
popd
|
||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import "matrix-js-sdk/src/@types/global"; // load matrix-js-sdk's type extensions first
|
||||
import * as ModernizrStatic from "modernizr";
|
||||
import "@types/modernizr";
|
||||
|
||||
import ContentMessages from "../ContentMessages";
|
||||
import { IMatrixClientPeg } from "../MatrixClientPeg";
|
||||
|
@ -46,10 +46,10 @@ import { VoiceRecordingStore } from "../stores/VoiceRecordingStore";
|
|||
import PerformanceMonitor from "../performance";
|
||||
import UIStore from "../stores/UIStore";
|
||||
import { SetupEncryptionStore } from "../stores/SetupEncryptionStore";
|
||||
import { RoomScrollStateStore } from "../stores/RoomScrollStateStore";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
Modernizr: ModernizrStatic;
|
||||
matrixChat: ReturnType<Renderer>;
|
||||
mxMatrixClientPeg: IMatrixClientPeg;
|
||||
Olm: {
|
||||
|
@ -87,6 +87,7 @@ declare global {
|
|||
mxPerformanceEntryNames: any;
|
||||
mxUIStore: UIStore;
|
||||
mxSetupEncryptionStore?: SetupEncryptionStore;
|
||||
mxRoomScrollStateStore?: RoomScrollStateStore;
|
||||
}
|
||||
|
||||
interface Document {
|
||||
|
|
|
@ -390,6 +390,7 @@ export class Analytics {
|
|||
{ expl: _td('Your device resolution'), value: resolution },
|
||||
];
|
||||
|
||||
// FIXME: Using an import will result in test failures
|
||||
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
|
||||
Modal.createTrackedDialog('Analytics Details', '', ErrorDialog, {
|
||||
title: _t('Analytics'),
|
||||
|
|
|
@ -77,6 +77,7 @@ export default class AsyncWrapper extends React.Component<IProps, IState> {
|
|||
const Component = this.state.component;
|
||||
return <Component {...this.props} />;
|
||||
} else if (this.state.error) {
|
||||
// FIXME: Using an import will result in test failures
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||
return <BaseDialog onFinished={this.props.onFinished} title={_t("Error")}>
|
||||
|
|
|
@ -49,8 +49,6 @@ const MAX_HEIGHT = 600;
|
|||
const PHYS_HIDPI = [0x00, 0x00, 0x16, 0x25, 0x00, 0x00, 0x16, 0x25, 0x01];
|
||||
|
||||
export const BLURHASH_FIELD = "xyz.amorgan.blurhash"; // MSC2448
|
||||
const BLURHASH_X_COMPONENTS = 6;
|
||||
const BLURHASH_Y_COMPONENTS = 6;
|
||||
|
||||
export class UploadCanceledError extends Error {}
|
||||
|
||||
|
@ -137,8 +135,9 @@ function createThumbnail(
|
|||
imageData.data,
|
||||
imageData.width,
|
||||
imageData.height,
|
||||
BLURHASH_X_COMPONENTS,
|
||||
BLURHASH_Y_COMPONENTS,
|
||||
// use 4 components on the longer dimension, if square then both
|
||||
imageData.width >= imageData.height ? 4 : 3,
|
||||
imageData.height >= imageData.width ? 4 : 3,
|
||||
);
|
||||
canvas.toBlob(function(thumbnail) {
|
||||
resolve({
|
||||
|
@ -419,6 +418,7 @@ export default class ContentMessages {
|
|||
|
||||
const isQuoting = Boolean(RoomViewStore.getQuotingEvent());
|
||||
if (isQuoting) {
|
||||
// FIXME: Using an import will result in Element crashing
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
const { finished } = Modal.createTrackedDialog<[boolean]>('Upload Reply Warning', '', QuestionDialog, {
|
||||
title: _t('Replying With Files'),
|
||||
|
@ -453,6 +453,7 @@ export default class ContentMessages {
|
|||
}
|
||||
|
||||
if (tooBigFiles.length > 0) {
|
||||
// FIXME: Using an import will result in Element crashing
|
||||
const UploadFailureDialog = sdk.getComponent("dialogs.UploadFailureDialog");
|
||||
const { finished } = Modal.createTrackedDialog<[boolean]>('Upload Failure', '', UploadFailureDialog, {
|
||||
badFiles: tooBigFiles,
|
||||
|
@ -463,7 +464,6 @@ export default class ContentMessages {
|
|||
if (!shouldContinue) return;
|
||||
}
|
||||
|
||||
const UploadConfirmDialog = sdk.getComponent("dialogs.UploadConfirmDialog");
|
||||
let uploadAll = false;
|
||||
// Promise to complete before sending next file into room, used for synchronisation of file-sending
|
||||
// to match the order the files were specified in
|
||||
|
@ -471,6 +471,8 @@ export default class ContentMessages {
|
|||
for (let i = 0; i < okFiles.length; ++i) {
|
||||
const file = okFiles[i];
|
||||
if (!uploadAll) {
|
||||
// FIXME: Using an import will result in Element crashing
|
||||
const UploadConfirmDialog = sdk.getComponent("dialogs.UploadConfirmDialog");
|
||||
const { finished } = Modal.createTrackedDialog<[boolean, boolean]>('Upload Files confirmation',
|
||||
'', UploadConfirmDialog, {
|
||||
file,
|
||||
|
@ -567,7 +569,7 @@ export default class ContentMessages {
|
|||
dis.dispatch<UploadStartedPayload>({ action: Action.UploadStarted, upload });
|
||||
|
||||
// Focus the composer view
|
||||
dis.fire(Action.FocusComposer);
|
||||
dis.fire(Action.FocusSendMessageComposer);
|
||||
|
||||
function onProgress(ev) {
|
||||
upload.total = ev.total;
|
||||
|
@ -606,6 +608,7 @@ export default class ContentMessages {
|
|||
{ fileName: upload.fileName },
|
||||
);
|
||||
}
|
||||
// FIXME: Using an import will result in Element crashing
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createTrackedDialog('Upload failed', '', ErrorDialog, {
|
||||
title: _t('Upload Failed'),
|
||||
|
|
|
@ -16,12 +16,12 @@ limitations under the License.
|
|||
|
||||
import { randomString } from "matrix-js-sdk/src/randomstring";
|
||||
import { IContent } from "matrix-js-sdk/src/models/event";
|
||||
import { sleep } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import { getCurrentLanguage } from './languageHandler';
|
||||
import PlatformPeg from './PlatformPeg';
|
||||
import SdkConfig from './SdkConfig';
|
||||
import { MatrixClientPeg } from "./MatrixClientPeg";
|
||||
import { sleep } from "./utils/promise";
|
||||
import RoomViewStore from "./stores/RoomViewStore";
|
||||
import { Action } from "./dispatcher/actions";
|
||||
|
||||
|
|
|
@ -160,7 +160,8 @@ export default class DeviceListener {
|
|||
// which result in account data changes affecting checks below.
|
||||
if (
|
||||
ev.getType().startsWith('m.secret_storage.') ||
|
||||
ev.getType().startsWith('m.cross_signing.')
|
||||
ev.getType().startsWith('m.cross_signing.') ||
|
||||
ev.getType() === 'm.megolm_backup.v1'
|
||||
) {
|
||||
this._recheck();
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@ import Presence from './Presence';
|
|||
import dis from './dispatcher/dispatcher';
|
||||
import DMRoomMap from './utils/DMRoomMap';
|
||||
import Modal from './Modal';
|
||||
import * as sdk from './index';
|
||||
import ActiveWidgetStore from './stores/ActiveWidgetStore';
|
||||
import PlatformPeg from "./PlatformPeg";
|
||||
import { sendLoginRequest } from "./Login";
|
||||
|
@ -52,6 +51,10 @@ import CallHandler from './CallHandler';
|
|||
import LifecycleCustomisations from "./customisations/Lifecycle";
|
||||
import ErrorDialog from "./components/views/dialogs/ErrorDialog";
|
||||
import { _t } from "./languageHandler";
|
||||
import LazyLoadingResyncDialog from "./components/views/dialogs/LazyLoadingResyncDialog";
|
||||
import LazyLoadingDisabledDialog from "./components/views/dialogs/LazyLoadingDisabledDialog";
|
||||
import SessionRestoreErrorDialog from "./components/views/dialogs/SessionRestoreErrorDialog";
|
||||
import StorageEvictedDialog from "./components/views/dialogs/StorageEvictedDialog";
|
||||
|
||||
const HOMESERVER_URL_KEY = "mx_hs_url";
|
||||
const ID_SERVER_URL_KEY = "mx_is_url";
|
||||
|
@ -238,8 +241,6 @@ export function handleInvalidStoreError(e: InvalidStoreError): Promise<void> {
|
|||
return Promise.resolve().then(() => {
|
||||
const lazyLoadEnabled = e.value;
|
||||
if (lazyLoadEnabled) {
|
||||
const LazyLoadingResyncDialog =
|
||||
sdk.getComponent("views.dialogs.LazyLoadingResyncDialog");
|
||||
return new Promise((resolve) => {
|
||||
Modal.createDialog(LazyLoadingResyncDialog, {
|
||||
onFinished: resolve,
|
||||
|
@ -250,8 +251,6 @@ export function handleInvalidStoreError(e: InvalidStoreError): Promise<void> {
|
|||
// between LL/non-LL version on same host.
|
||||
// as disabling LL when previously enabled
|
||||
// is a strong indicator of this (/develop & /app)
|
||||
const LazyLoadingDisabledDialog =
|
||||
sdk.getComponent("views.dialogs.LazyLoadingDisabledDialog");
|
||||
return new Promise((resolve) => {
|
||||
Modal.createDialog(LazyLoadingDisabledDialog, {
|
||||
onFinished: resolve,
|
||||
|
@ -451,9 +450,6 @@ export async function restoreFromLocalStorage(opts?: { ignoreGuest?: boolean }):
|
|||
async function handleLoadSessionFailure(e: Error): Promise<boolean> {
|
||||
console.error("Unable to load session", e);
|
||||
|
||||
const SessionRestoreErrorDialog =
|
||||
sdk.getComponent('views.dialogs.SessionRestoreErrorDialog');
|
||||
|
||||
const modal = Modal.createTrackedDialog('Session Restore Error', '', SessionRestoreErrorDialog, {
|
||||
error: e.message,
|
||||
});
|
||||
|
@ -612,7 +608,6 @@ async function doSetLoggedIn(
|
|||
}
|
||||
|
||||
function showStorageEvictedDialog(): Promise<boolean> {
|
||||
const StorageEvictedDialog = sdk.getComponent('views.dialogs.StorageEvictedDialog');
|
||||
return new Promise(resolve => {
|
||||
Modal.createTrackedDialog('Storage evicted', '', StorageEvictedDialog, {
|
||||
onFinished: resolve,
|
||||
|
|
|
@ -219,6 +219,7 @@ class _MatrixClientPeg implements IMatrixClientPeg {
|
|||
} catch (e) {
|
||||
if (e && e.name === 'InvalidCryptoStoreError') {
|
||||
// The js-sdk found a crypto DB too new for it to use
|
||||
// FIXME: Using an import will result in test failures
|
||||
const CryptoStoreTooNewDialog =
|
||||
sdk.getComponent("views.dialogs.CryptoStoreTooNewDialog");
|
||||
Modal.createDialog(CryptoStoreTooNewDialog);
|
||||
|
|
|
@ -20,12 +20,15 @@ import { SettingLevel } from "./settings/SettingLevel";
|
|||
import { setMatrixCallAudioInput, setMatrixCallVideoInput } from "matrix-js-sdk/src/matrix";
|
||||
import EventEmitter from 'events';
|
||||
|
||||
interface IMediaDevices {
|
||||
audioOutput: Array<MediaDeviceInfo>;
|
||||
audioInput: Array<MediaDeviceInfo>;
|
||||
videoInput: Array<MediaDeviceInfo>;
|
||||
// XXX: MediaDeviceKind is a union type, so we make our own enum
|
||||
export enum MediaDeviceKindEnum {
|
||||
AudioOutput = "audiooutput",
|
||||
AudioInput = "audioinput",
|
||||
VideoInput = "videoinput",
|
||||
}
|
||||
|
||||
export type IMediaDevices = Record<MediaDeviceKindEnum, Array<MediaDeviceInfo>>;
|
||||
|
||||
export enum MediaDeviceHandlerEvent {
|
||||
AudioOutputChanged = "audio_output_changed",
|
||||
}
|
||||
|
@ -51,20 +54,14 @@ export default class MediaDeviceHandler extends EventEmitter {
|
|||
|
||||
try {
|
||||
const devices = await navigator.mediaDevices.enumerateDevices();
|
||||
const output = {
|
||||
[MediaDeviceKindEnum.AudioOutput]: [],
|
||||
[MediaDeviceKindEnum.AudioInput]: [],
|
||||
[MediaDeviceKindEnum.VideoInput]: [],
|
||||
};
|
||||
|
||||
const audioOutput = [];
|
||||
const audioInput = [];
|
||||
const videoInput = [];
|
||||
|
||||
devices.forEach((device) => {
|
||||
switch (device.kind) {
|
||||
case 'audiooutput': audioOutput.push(device); break;
|
||||
case 'audioinput': audioInput.push(device); break;
|
||||
case 'videoinput': videoInput.push(device); break;
|
||||
}
|
||||
});
|
||||
|
||||
return { audioOutput, audioInput, videoInput };
|
||||
devices.forEach((device) => output[device.kind].push(device));
|
||||
return output;
|
||||
} catch (error) {
|
||||
console.warn('Unable to refresh WebRTC Devices: ', error);
|
||||
}
|
||||
|
@ -106,6 +103,14 @@ export default class MediaDeviceHandler extends EventEmitter {
|
|||
setMatrixCallVideoInput(deviceId);
|
||||
}
|
||||
|
||||
public setDevice(deviceId: string, kind: MediaDeviceKindEnum): void {
|
||||
switch (kind) {
|
||||
case MediaDeviceKindEnum.AudioOutput: this.setAudioOutput(deviceId); break;
|
||||
case MediaDeviceKindEnum.AudioInput: this.setAudioInput(deviceId); break;
|
||||
case MediaDeviceKindEnum.VideoInput: this.setVideoInput(deviceId); break;
|
||||
}
|
||||
}
|
||||
|
||||
public static getAudioOutput(): string {
|
||||
return SettingsStore.getValueAt(SettingLevel.DEVICE, "webrtc_audiooutput");
|
||||
}
|
||||
|
|
|
@ -18,10 +18,10 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import classNames from 'classnames';
|
||||
import { defer } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import Analytics from './Analytics';
|
||||
import dis from './dispatcher/dispatcher';
|
||||
import { defer } from './utils/promise';
|
||||
import AsyncWrapper from './AsyncWrapper';
|
||||
|
||||
const DIALOG_CONTAINER_ID = "mx_Dialog_Container";
|
||||
|
|
|
@ -27,7 +27,6 @@ import * as TextForEvent from './TextForEvent';
|
|||
import Analytics from './Analytics';
|
||||
import * as Avatar from './Avatar';
|
||||
import dis from './dispatcher/dispatcher';
|
||||
import * as sdk from './index';
|
||||
import { _t } from './languageHandler';
|
||||
import Modal from './Modal';
|
||||
import SettingsStore from "./settings/SettingsStore";
|
||||
|
@ -37,6 +36,7 @@ import { isPushNotifyDisabled } from "./settings/controllers/NotificationControl
|
|||
import RoomViewStore from "./stores/RoomViewStore";
|
||||
import UserActivity from "./UserActivity";
|
||||
import { mediaFromMxc } from "./customisations/Media";
|
||||
import ErrorDialog from "./components/views/dialogs/ErrorDialog";
|
||||
|
||||
/*
|
||||
* Dispatches:
|
||||
|
@ -240,7 +240,6 @@ export const Notifier = {
|
|||
? _t('%(brand)s does not have permission to send you notifications - ' +
|
||||
'please check your browser settings', { brand })
|
||||
: _t('%(brand)s was not given permission to send notifications - please try again', { brand });
|
||||
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
|
||||
Modal.createTrackedDialog('Unable to enable Notifications', result, ErrorDialog, {
|
||||
title: _t('Unable to enable Notifications'),
|
||||
description,
|
||||
|
|
|
@ -22,13 +22,13 @@ import { User } from "matrix-js-sdk/src/models/user";
|
|||
import { MatrixClientPeg } from './MatrixClientPeg';
|
||||
import MultiInviter, { CompletionStates } from './utils/MultiInviter';
|
||||
import Modal from './Modal';
|
||||
import * as sdk from './';
|
||||
import { _t } from './languageHandler';
|
||||
import InviteDialog, { KIND_DM, KIND_INVITE, Member } from "./components/views/dialogs/InviteDialog";
|
||||
import CommunityPrototypeInviteDialog from "./components/views/dialogs/CommunityPrototypeInviteDialog";
|
||||
import { CommunityPrototypeStore } from "./stores/CommunityPrototypeStore";
|
||||
import BaseAvatar from "./components/views/avatars/BaseAvatar";
|
||||
import { mediaFromMxc } from "./customisations/Media";
|
||||
import ErrorDialog from "./components/views/dialogs/ErrorDialog";
|
||||
|
||||
export interface IInviteResult {
|
||||
states: CompletionStates;
|
||||
|
@ -51,7 +51,6 @@ export function inviteMultipleToRoom(roomId: string, addresses: string[]): Promi
|
|||
|
||||
export function showStartChatInviteDialog(initialText = ""): void {
|
||||
// This dialog handles the room creation internally - we don't need to worry about it.
|
||||
const InviteDialog = sdk.getComponent("dialogs.InviteDialog");
|
||||
Modal.createTrackedDialog(
|
||||
'Start DM', '', InviteDialog, { kind: KIND_DM, initialText },
|
||||
/*className=*/null, /*isPriority=*/false, /*isStatic=*/true,
|
||||
|
@ -111,7 +110,6 @@ export function inviteUsersToRoom(roomId: string, userIds: string[]): Promise<vo
|
|||
showAnyInviteErrors(result.states, room, result.inviter);
|
||||
}).catch((err) => {
|
||||
console.error(err.stack);
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createTrackedDialog('Failed to invite', '', ErrorDialog, {
|
||||
title: _t("Failed to invite"),
|
||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||
|
@ -131,7 +129,6 @@ export function showAnyInviteErrors(
|
|||
// Just get the first message because there was a fatal problem on the first
|
||||
// user. This usually means that no other users were attempted, making it
|
||||
// pointless for us to list who failed exactly.
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createTrackedDialog('Failed to invite users to the room', '', ErrorDialog, {
|
||||
title: _t("Failed to invite users to the room:", { roomName: room.name }),
|
||||
description: inviter.getErrorText(failedUsers[0]),
|
||||
|
@ -178,7 +175,6 @@ export function showAnyInviteErrors(
|
|||
</div>
|
||||
</div>;
|
||||
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createTrackedDialog("Some invites could not be sent", "", ErrorDialog, {
|
||||
title: _t("Some invites couldn't be sent"),
|
||||
description,
|
||||
|
|
|
@ -14,7 +14,8 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { ICryptoCallbacks, ISecretStorageKeyInfo } from 'matrix-js-sdk/src/matrix';
|
||||
import { ICryptoCallbacks } from 'matrix-js-sdk/src/matrix';
|
||||
import { ISecretStorageKeyInfo } from 'matrix-js-sdk/src/crypto/api';
|
||||
import { MatrixClient } from 'matrix-js-sdk/src/client';
|
||||
import Modal from './Modal';
|
||||
import * as sdk from './index';
|
||||
|
@ -354,6 +355,7 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f
|
|||
throw new Error("Secret storage creation canceled");
|
||||
}
|
||||
} else {
|
||||
// FIXME: Using an import will result in test failures
|
||||
const InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog");
|
||||
await cli.bootstrapCrossSigning({
|
||||
authUploadDeviceSigningKeys: async (makeRequest) => {
|
||||
|
|
|
@ -23,7 +23,6 @@ import { User } from "matrix-js-sdk/src/models/user";
|
|||
import * as ContentHelpers from 'matrix-js-sdk/src/content-helpers';
|
||||
import { MatrixClientPeg } from './MatrixClientPeg';
|
||||
import dis from './dispatcher/dispatcher';
|
||||
import * as sdk from './index';
|
||||
import { _t, _td } from './languageHandler';
|
||||
import Modal from './Modal';
|
||||
import MultiInviter from './utils/MultiInviter';
|
||||
|
@ -50,6 +49,12 @@ import { UIFeature } from "./settings/UIFeature";
|
|||
import { CHAT_EFFECTS } from "./effects";
|
||||
import CallHandler from "./CallHandler";
|
||||
import { guessAndSetDMRoom } from "./Rooms";
|
||||
import UploadConfirmDialog from './components/views/dialogs/UploadConfirmDialog';
|
||||
import ErrorDialog from './components/views/dialogs/ErrorDialog';
|
||||
import DevtoolsDialog from './components/views/dialogs/DevtoolsDialog';
|
||||
import RoomUpgradeWarningDialog from "./components/views/dialogs/RoomUpgradeWarningDialog";
|
||||
import InfoDialog from "./components/views/dialogs/InfoDialog";
|
||||
import SlashCommandHelpDialog from "./components/views/dialogs/SlashCommandHelpDialog";
|
||||
|
||||
// XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816
|
||||
interface HTMLInputEvent extends Event {
|
||||
|
@ -63,7 +68,6 @@ const singleMxcUpload = async (): Promise<any> => {
|
|||
fileSelector.onchange = (ev: HTMLInputEvent) => {
|
||||
const file = ev.target.files[0];
|
||||
|
||||
const UploadConfirmDialog = sdk.getComponent("dialogs.UploadConfirmDialog");
|
||||
Modal.createTrackedDialog('Upload Files confirmation', '', UploadConfirmDialog, {
|
||||
file,
|
||||
onFinished: (shouldContinue) => {
|
||||
|
@ -246,7 +250,6 @@ export const Commands = [
|
|||
args: '<query>',
|
||||
description: _td('Searches DuckDuckGo for results'),
|
||||
runFn: function() {
|
||||
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
|
||||
// TODO Don't explain this away, actually show a search UI here.
|
||||
Modal.createTrackedDialog('Slash Commands', '/ddg is not a command', ErrorDialog, {
|
||||
title: _t('/ddg is not a command'),
|
||||
|
@ -269,8 +272,6 @@ export const Commands = [
|
|||
return reject(_t("You do not have the required permissions to use this command."));
|
||||
}
|
||||
|
||||
const RoomUpgradeWarningDialog = sdk.getComponent("dialogs.RoomUpgradeWarningDialog");
|
||||
|
||||
const { finished } = Modal.createTrackedDialog('Slash Commands', 'upgrade room confirmation',
|
||||
RoomUpgradeWarningDialog, { roomId: roomId, targetVersion: args }, /*className=*/null,
|
||||
/*isPriority=*/false, /*isStatic=*/true);
|
||||
|
@ -314,7 +315,6 @@ export const Commands = [
|
|||
|
||||
if (checkForUpgradeFn) cli.removeListener('Room', checkForUpgradeFn);
|
||||
|
||||
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
|
||||
Modal.createTrackedDialog('Slash Commands', 'room upgrade error', ErrorDialog, {
|
||||
title: _t('Error upgrading room'),
|
||||
description: _t(
|
||||
|
@ -434,7 +434,6 @@ export const Commands = [
|
|||
const topic = topicEvents && topicEvents.getContent().topic;
|
||||
const topicHtml = topic ? linkifyAndSanitizeHtml(topic) : _t('This room has no topic.');
|
||||
|
||||
const InfoDialog = sdk.getComponent('dialogs.InfoDialog');
|
||||
Modal.createTrackedDialog('Slash Commands', 'Topic', InfoDialog, {
|
||||
title: room.name,
|
||||
description: <div dangerouslySetInnerHTML={{ __html: topicHtml }} />,
|
||||
|
@ -737,7 +736,6 @@ export const Commands = [
|
|||
ignoredUsers.push(userId); // de-duped internally in the js-sdk
|
||||
return success(
|
||||
cli.setIgnoredUsers(ignoredUsers).then(() => {
|
||||
const InfoDialog = sdk.getComponent('dialogs.InfoDialog');
|
||||
Modal.createTrackedDialog('Slash Commands', 'User ignored', InfoDialog, {
|
||||
title: _t('Ignored user'),
|
||||
description: <div>
|
||||
|
@ -768,7 +766,6 @@ export const Commands = [
|
|||
if (index !== -1) ignoredUsers.splice(index, 1);
|
||||
return success(
|
||||
cli.setIgnoredUsers(ignoredUsers).then(() => {
|
||||
const InfoDialog = sdk.getComponent('dialogs.InfoDialog');
|
||||
Modal.createTrackedDialog('Slash Commands', 'User unignored', InfoDialog, {
|
||||
title: _t('Unignored user'),
|
||||
description: <div>
|
||||
|
@ -838,7 +835,6 @@ export const Commands = [
|
|||
command: 'devtools',
|
||||
description: _td('Opens the Developer Tools dialog'),
|
||||
runFn: function(roomId) {
|
||||
const DevtoolsDialog = sdk.getComponent('dialogs.DevtoolsDialog');
|
||||
Modal.createDialog(DevtoolsDialog, { roomId });
|
||||
return success();
|
||||
},
|
||||
|
@ -943,7 +939,6 @@ export const Commands = [
|
|||
await cli.setDeviceVerified(userId, deviceId, true);
|
||||
|
||||
// Tell the user we verified everything
|
||||
const InfoDialog = sdk.getComponent('dialogs.InfoDialog');
|
||||
Modal.createTrackedDialog('Slash Commands', 'Verified key', InfoDialog, {
|
||||
title: _t('Verified key'),
|
||||
description: <div>
|
||||
|
@ -1000,8 +995,6 @@ export const Commands = [
|
|||
command: "help",
|
||||
description: _td("Displays list of commands with usages and descriptions"),
|
||||
runFn: function() {
|
||||
const SlashCommandHelpDialog = sdk.getComponent('dialogs.SlashCommandHelpDialog');
|
||||
|
||||
Modal.createTrackedDialog('Slash Commands', 'Help', SlashCommandHelpDialog);
|
||||
return success();
|
||||
},
|
||||
|
|
|
@ -189,6 +189,7 @@ export function dialogTermsInteractionCallback(
|
|||
): Promise<string[]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
console.log("Terms that need agreement", policiesAndServicePairs);
|
||||
// FIXME: Using an import will result in test failures
|
||||
const TermsDialog = sdk.getComponent("views.dialogs.TermsDialog");
|
||||
|
||||
Modal.createTrackedDialog('Terms of Service', '', TermsDialog, {
|
||||
|
|
|
@ -17,10 +17,10 @@ limitations under the License.
|
|||
import * as React from "react";
|
||||
import classNames from "classnames";
|
||||
|
||||
import * as sdk from "../index";
|
||||
import Modal from "../Modal";
|
||||
import { _t, _td } from "../languageHandler";
|
||||
import { isMac, Key } from "../Keyboard";
|
||||
import InfoDialog from "../components/views/dialogs/InfoDialog";
|
||||
|
||||
// TS: once languageHandler is TS we can probably inline this into the enum
|
||||
_td("Navigation");
|
||||
|
@ -375,7 +375,6 @@ export const toggleDialog = () => {
|
|||
</div>;
|
||||
});
|
||||
|
||||
const InfoDialog = sdk.getComponent('dialogs.InfoDialog');
|
||||
activeModal = Modal.createTrackedDialog("Keyboard Shortcuts", "", InfoDialog, {
|
||||
className: "mx_KeyboardShortcutsDialog",
|
||||
title: _t("Keyboard Shortcuts"),
|
||||
|
|
|
@ -19,13 +19,13 @@ import { asyncAction } from './actionCreators';
|
|||
import Modal from '../Modal';
|
||||
import * as Rooms from '../Rooms';
|
||||
import { _t } from '../languageHandler';
|
||||
import * as sdk from '../index';
|
||||
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { AsyncActionPayload } from "../dispatcher/payloads";
|
||||
import RoomListStore from "../stores/room-list/RoomListStore";
|
||||
import { SortAlgorithm } from "../stores/room-list/algorithms/models";
|
||||
import { DefaultTagID } from "../stores/room-list/models";
|
||||
import ErrorDialog from '../components/views/dialogs/ErrorDialog';
|
||||
|
||||
export default class RoomListActions {
|
||||
/**
|
||||
|
@ -88,7 +88,6 @@ export default class RoomListActions {
|
|||
return Rooms.guessAndSetDMRoom(
|
||||
room, newTag === DefaultTagID.DM,
|
||||
).catch((err) => {
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
console.error("Failed to set direct chat tag " + err);
|
||||
Modal.createTrackedDialog('Failed to set direct chat tag', '', ErrorDialog, {
|
||||
title: _t('Failed to set direct chat tag'),
|
||||
|
@ -109,7 +108,6 @@ export default class RoomListActions {
|
|||
const promiseToDelete = matrixClient.deleteRoomTag(
|
||||
roomId, oldTag,
|
||||
).catch(function(err) {
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
console.error("Failed to remove tag " + oldTag + " from room: " + err);
|
||||
Modal.createTrackedDialog('Failed to remove tag from room', '', ErrorDialog, {
|
||||
title: _t('Failed to remove tag %(tagName)s from room', { tagName: oldTag }),
|
||||
|
@ -129,7 +127,6 @@ export default class RoomListActions {
|
|||
metaData = metaData || {};
|
||||
|
||||
const promiseToAdd = matrixClient.setRoomTag(roomId, newTag, metaData).catch(function(err) {
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
console.error("Failed to add tag " + newTag + " to room: " + err);
|
||||
Modal.createTrackedDialog('Failed to add tag to room', '', ErrorDialog, {
|
||||
title: _t('Failed to add tag %(tagName)s to room', { tagName: newTag }),
|
||||
|
|
|
@ -15,7 +15,6 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import * as sdk from '../../../../index';
|
||||
import { _t } from '../../../../languageHandler';
|
||||
import SdkConfig from '../../../../SdkConfig';
|
||||
import SettingsStore from "../../../../settings/SettingsStore";
|
||||
|
@ -24,6 +23,9 @@ import Modal from '../../../../Modal';
|
|||
import { formatBytes, formatCountLong } from "../../../../utils/FormattingUtils";
|
||||
import EventIndexPeg from "../../../../indexing/EventIndexPeg";
|
||||
import { SettingLevel } from "../../../../settings/SettingLevel";
|
||||
import Field from '../../../../components/views/elements/Field';
|
||||
import BaseDialog from "../../../../components/views/dialogs/BaseDialog";
|
||||
import DialogButtons from "../../../../components/views/elements/DialogButtons";
|
||||
|
||||
interface IProps {
|
||||
onFinished: (confirmed: boolean) => void;
|
||||
|
@ -145,7 +147,6 @@ export default class ManageEventIndexDialog extends React.Component<IProps, ISta
|
|||
|
||||
render() {
|
||||
const brand = SdkConfig.get().brand;
|
||||
const Field = sdk.getComponent('views.elements.Field');
|
||||
|
||||
let crawlerState;
|
||||
if (this.state.currentRoom === null) {
|
||||
|
@ -176,15 +177,12 @@ export default class ManageEventIndexDialog extends React.Component<IProps, ISta
|
|||
<Field
|
||||
label={_t('Message downloading sleep time(ms)')}
|
||||
type='number'
|
||||
value={this.state.crawlerSleepTime}
|
||||
value={this.state.crawlerSleepTime.toString()}
|
||||
onChange={this.onCrawlerSleepTimeChange} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||
|
||||
return (
|
||||
<BaseDialog className='mx_ManageEventIndexDialog'
|
||||
onFinished={this.props.onFinished}
|
||||
|
|
|
@ -22,12 +22,12 @@ import AutocompleteProvider from './AutocompleteProvider';
|
|||
import { MatrixClientPeg } from '../MatrixClientPeg';
|
||||
import QueryMatcher from './QueryMatcher';
|
||||
import { PillCompletion } from './Components';
|
||||
import * as sdk from '../index';
|
||||
import { sortBy } from "lodash";
|
||||
import { makeGroupPermalink } from "../utils/permalinks/Permalinks";
|
||||
import { ICompletion, ISelectionRange } from "./Autocompleter";
|
||||
import FlairStore from "../stores/FlairStore";
|
||||
import { mediaFromMxc } from "../customisations/Media";
|
||||
import BaseAvatar from '../components/views/avatars/BaseAvatar';
|
||||
|
||||
const COMMUNITY_REGEX = /\B\+\S*/g;
|
||||
|
||||
|
@ -56,8 +56,6 @@ export default class CommunityProvider extends AutocompleteProvider {
|
|||
force = false,
|
||||
limit = -1,
|
||||
): Promise<ICompletion[]> {
|
||||
const BaseAvatar = sdk.getComponent('views.avatars.BaseAvatar');
|
||||
|
||||
// Disable autocompletions when composing commands because of various issues
|
||||
// (see https://github.com/vector-im/element-web/issues/4762)
|
||||
if (/^(\/join|\/leave)/.test(query)) {
|
||||
|
|
|
@ -21,8 +21,8 @@ import AutocompleteProvider from './AutocompleteProvider';
|
|||
import { _t } from '../languageHandler';
|
||||
import { MatrixClientPeg } from '../MatrixClientPeg';
|
||||
import { PillCompletion } from './Components';
|
||||
import * as sdk from '../index';
|
||||
import { ICompletion, ISelectionRange } from "./Autocompleter";
|
||||
import RoomAvatar from '../components/views/avatars/RoomAvatar';
|
||||
|
||||
const AT_ROOM_REGEX = /@\S*/g;
|
||||
|
||||
|
@ -40,8 +40,6 @@ export default class NotifProvider extends AutocompleteProvider {
|
|||
force = false,
|
||||
limit = -1,
|
||||
): Promise<ICompletion[]> {
|
||||
const RoomAvatar = sdk.getComponent('views.avatars.RoomAvatar');
|
||||
|
||||
const client = MatrixClientPeg.get();
|
||||
|
||||
if (!this.room.currentState.mayTriggerNotifOfType('room', client.credentials.userId)) return [];
|
||||
|
|
|
@ -21,7 +21,6 @@ import React from 'react';
|
|||
import { _t } from '../languageHandler';
|
||||
import AutocompleteProvider from './AutocompleteProvider';
|
||||
import { PillCompletion } from './Components';
|
||||
import * as sdk from '../index';
|
||||
import QueryMatcher from './QueryMatcher';
|
||||
import { sortBy } from 'lodash';
|
||||
import { MatrixClientPeg } from '../MatrixClientPeg';
|
||||
|
@ -33,6 +32,7 @@ import { RoomState } from "matrix-js-sdk/src/models/room-state";
|
|||
import { EventTimeline } from "matrix-js-sdk/src/models/event-timeline";
|
||||
import { makeUserPermalink } from "../utils/permalinks/Permalinks";
|
||||
import { ICompletion, ISelectionRange } from "./Autocompleter";
|
||||
import MemberAvatar from '../components/views/avatars/MemberAvatar';
|
||||
|
||||
const USER_REGEX = /\B@\S*/g;
|
||||
|
||||
|
@ -108,8 +108,6 @@ export default class UserProvider extends AutocompleteProvider {
|
|||
force = false,
|
||||
limit = -1,
|
||||
): Promise<ICompletion[]> {
|
||||
const MemberAvatar = sdk.getComponent('views.avatars.MemberAvatar');
|
||||
|
||||
// lazy-load user list into matcher
|
||||
if (!this.users) this._makeUsers();
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
|||
import { Room } from 'matrix-js-sdk/src/models/room';
|
||||
import { TimelineWindow } from 'matrix-js-sdk/src/timeline-window';
|
||||
|
||||
import * as sdk from '../../index';
|
||||
import { MatrixClientPeg } from '../../MatrixClientPeg';
|
||||
import EventIndexPeg from "../../indexing/EventIndexPeg";
|
||||
import { _t } from '../../languageHandler';
|
||||
|
@ -34,6 +33,9 @@ import DesktopBuildsNotice, { WarningKind } from "../views/elements/DesktopBuild
|
|||
import { replaceableComponent } from "../../utils/replaceableComponent";
|
||||
|
||||
import ResizeNotifier from '../../utils/ResizeNotifier';
|
||||
import TimelinePanel from "./TimelinePanel";
|
||||
import Spinner from "../views/elements/Spinner";
|
||||
import { TileShape } from '../views/rooms/EventTile';
|
||||
|
||||
interface IProps {
|
||||
roomId: string;
|
||||
|
@ -237,8 +239,6 @@ class FilePanel extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
// wrap a TimelinePanel with the jump-to-event bits turned off.
|
||||
const TimelinePanel = sdk.getComponent("structures.TimelinePanel");
|
||||
const Loader = sdk.getComponent("elements.Spinner");
|
||||
|
||||
const emptyState = (<div className="mx_RightPanel_empty mx_FilePanel_empty">
|
||||
<h2>{_t('No files visible in this room')}</h2>
|
||||
|
@ -264,7 +264,7 @@ class FilePanel extends React.Component<IProps, IState> {
|
|||
timelineSet={this.state.timelineSet}
|
||||
showUrlPreview = {false}
|
||||
onPaginationRequest={this.onPaginationRequest}
|
||||
tileShape="file_grid"
|
||||
tileShape={TileShape.FileGrid}
|
||||
resizeNotifier={this.props.resizeNotifier}
|
||||
empty={emptyState}
|
||||
/>
|
||||
|
@ -277,7 +277,7 @@ class FilePanel extends React.Component<IProps, IState> {
|
|||
onClose={this.props.onClose}
|
||||
previousPhase={RightPanelPhases.RoomSummary}
|
||||
>
|
||||
<Loader />
|
||||
<Spinner />
|
||||
</BaseCard>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ import FlairStore from '../../stores/FlairStore';
|
|||
import { showGroupAddRoomDialog } from '../../GroupAddressPicker';
|
||||
import { makeGroupPermalink, makeUserPermalink } from "../../utils/permalinks/Permalinks";
|
||||
import { Group } from "matrix-js-sdk/src/models/group";
|
||||
import { sleep } from "../../utils/promise";
|
||||
import { sleep } from "matrix-js-sdk/src/utils";
|
||||
import RightPanelStore from "../../stores/RightPanelStore";
|
||||
import AutoHideScrollbar from "./AutoHideScrollbar";
|
||||
import { mediaFromMxc } from "../../customisations/Media";
|
||||
|
|
|
@ -96,6 +96,7 @@ const HomePage: React.FC<IProps> = ({ justRegistered = false }) => {
|
|||
const pageUrl = getHomePageUrl(config);
|
||||
|
||||
if (pageUrl) {
|
||||
// FIXME: Using an import will result in wrench-element-tests failures
|
||||
const EmbeddedPage = sdk.getComponent('structures.EmbeddedPage');
|
||||
return <EmbeddedPage className="mx_HomePage" url={pageUrl} scrollbar={true} />;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ import { Key } from '../../Keyboard';
|
|||
import PageTypes from '../../PageTypes';
|
||||
import MediaDeviceHandler from '../../MediaDeviceHandler';
|
||||
import { fixupColorFonts } from '../../utils/FontManager';
|
||||
import * as sdk from '../../index';
|
||||
import dis from '../../dispatcher/dispatcher';
|
||||
import { IMatrixClientCreds } from '../../MatrixClientPeg';
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
|
@ -59,6 +58,11 @@ import { replaceableComponent } from "../../utils/replaceableComponent";
|
|||
import CallHandler, { CallHandlerEvent } from '../../CallHandler';
|
||||
import { MatrixCall } from 'matrix-js-sdk/src/webrtc/call';
|
||||
import AudioFeedArrayForCall from '../views/voip/AudioFeedArrayForCall';
|
||||
import RoomView from './RoomView';
|
||||
import ToastContainer from './ToastContainer';
|
||||
import MyGroups from "./MyGroups";
|
||||
import UserView from "./UserView";
|
||||
import GroupView from "./GroupView";
|
||||
|
||||
// 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.
|
||||
|
@ -78,8 +82,8 @@ interface IProps {
|
|||
hideToSRUsers: boolean;
|
||||
resizeNotifier: ResizeNotifier;
|
||||
// eslint-disable-next-line camelcase
|
||||
page_type: string;
|
||||
autoJoin: boolean;
|
||||
page_type?: string;
|
||||
autoJoin?: boolean;
|
||||
threepidInvite?: IThreepidInvite;
|
||||
roomOobData?: IOOBData;
|
||||
currentRoomId: string;
|
||||
|
@ -394,7 +398,7 @@ class LoggedInView extends React.Component<IProps, IState> {
|
|||
// refocusing during a paste event will make the
|
||||
// paste end up in the newly focused element,
|
||||
// so dispatch synchronously before paste happens
|
||||
dis.fire(Action.FocusComposer, true);
|
||||
dis.fire(Action.FocusSendMessageComposer, true);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -548,7 +552,7 @@ class LoggedInView extends React.Component<IProps, IState> {
|
|||
|
||||
if (!isClickShortcut && ev.key !== Key.TAB && !canElementReceiveInput(ev.target)) {
|
||||
// synchronous dispatch so we focus before key generates input
|
||||
dis.fire(Action.FocusComposer, true);
|
||||
dis.fire(Action.FocusSendMessageComposer, true);
|
||||
ev.stopPropagation();
|
||||
// we should *not* preventDefault() here as
|
||||
// that would prevent typing in the now-focussed composer
|
||||
|
@ -567,12 +571,6 @@ class LoggedInView extends React.Component<IProps, IState> {
|
|||
};
|
||||
|
||||
render() {
|
||||
const RoomView = sdk.getComponent('structures.RoomView');
|
||||
const UserView = sdk.getComponent('structures.UserView');
|
||||
const GroupView = sdk.getComponent('structures.GroupView');
|
||||
const MyGroups = sdk.getComponent('structures.MyGroups');
|
||||
const ToastContainer = sdk.getComponent('structures.ToastContainer');
|
||||
|
||||
let pageElement;
|
||||
|
||||
switch (this.props.page_type) {
|
||||
|
|
|
@ -19,6 +19,8 @@ import { createClient } from "matrix-js-sdk/src/matrix";
|
|||
import { InvalidStoreError } from "matrix-js-sdk/src/errors";
|
||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { sleep, defer, IDeferred } from "matrix-js-sdk/src/utils";
|
||||
|
||||
// focus-visible is a Polyfill for the :focus-visible CSS pseudo-attribute used by _AccessibleButton.scss
|
||||
import 'focus-visible';
|
||||
// what-input helps improve keyboard accessibility
|
||||
|
@ -34,7 +36,6 @@ import dis from "../../dispatcher/dispatcher";
|
|||
import Notifier from '../../Notifier';
|
||||
|
||||
import Modal from "../../Modal";
|
||||
import * as sdk from '../../index';
|
||||
import { showRoomInviteDialog, showStartChatInviteDialog } from '../../RoomInvite';
|
||||
import * as Rooms from '../../Rooms';
|
||||
import linkifyMatrix from "../../linkify-matrix";
|
||||
|
@ -55,7 +56,6 @@ import DMRoomMap from '../../utils/DMRoomMap';
|
|||
import ThemeWatcher from "../../settings/watchers/ThemeWatcher";
|
||||
import { FontWatcher } from '../../settings/watchers/FontWatcher';
|
||||
import { storeRoomAliasInCache } from '../../RoomAliasCache';
|
||||
import { defer, IDeferred, sleep } from "../../utils/promise";
|
||||
import ToastStore from "../../stores/ToastStore";
|
||||
import * as StorageManager from "../../utils/StorageManager";
|
||||
import type LoggedInViewType from "./LoggedInView";
|
||||
|
@ -84,9 +84,27 @@ import RoomListStore from "../../stores/room-list/RoomListStore";
|
|||
import { RoomUpdateCause } from "../../stores/room-list/models";
|
||||
import defaultDispatcher from "../../dispatcher/dispatcher";
|
||||
import SecurityCustomisations from "../../customisations/Security";
|
||||
import Spinner from "../views/elements/Spinner";
|
||||
import QuestionDialog from "../views/dialogs/QuestionDialog";
|
||||
import UserSettingsDialog from '../views/dialogs/UserSettingsDialog';
|
||||
import CreateGroupDialog from '../views/dialogs/CreateGroupDialog';
|
||||
import CreateRoomDialog from '../views/dialogs/CreateRoomDialog';
|
||||
import RoomDirectory from './RoomDirectory';
|
||||
import KeySignatureUploadFailedDialog from "../views/dialogs/KeySignatureUploadFailedDialog";
|
||||
import IncomingSasDialog from "../views/dialogs/IncomingSasDialog";
|
||||
import CompleteSecurity from "./auth/CompleteSecurity";
|
||||
import LoggedInView from './LoggedInView';
|
||||
import Welcome from "../views/auth/Welcome";
|
||||
import ForgotPassword from "./auth/ForgotPassword";
|
||||
import E2eSetup from "./auth/E2eSetup";
|
||||
import Registration from './auth/Registration';
|
||||
import Login from "./auth/Login";
|
||||
import ErrorBoundary from '../views/elements/ErrorBoundary';
|
||||
import VerificationRequestToast from '../views/toasts/VerificationRequestToast';
|
||||
|
||||
import PerformanceMonitor, { PerformanceEntryNames } from "../../performance";
|
||||
import UIStore, { UI_EVENTS } from "../../stores/UIStore";
|
||||
import SoftLogout from './auth/SoftLogout';
|
||||
|
||||
/** constants for MatrixChat.state.view */
|
||||
export enum Views {
|
||||
|
@ -155,7 +173,12 @@ interface IRoomInfo {
|
|||
/* eslint-enable camelcase */
|
||||
|
||||
interface IProps { // TODO type things better
|
||||
config: Record<string, any>;
|
||||
config: {
|
||||
piwik: {
|
||||
policyUrl: string;
|
||||
};
|
||||
[key: string]: any;
|
||||
};
|
||||
serverConfig?: ValidatedServerConfig;
|
||||
onNewScreen: (screen: string, replaceLast: boolean) => void;
|
||||
enableGuest?: boolean;
|
||||
|
@ -420,7 +443,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
CountlyAnalytics.instance.trackPageChange(durationMs);
|
||||
}
|
||||
if (this.focusComposer) {
|
||||
dis.fire(Action.FocusComposer);
|
||||
dis.fire(Action.FocusSendMessageComposer);
|
||||
this.focusComposer = false;
|
||||
}
|
||||
}
|
||||
|
@ -518,7 +541,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
|
||||
onAction = (payload) => {
|
||||
// console.log(`MatrixClientPeg.onAction: ${payload.action}`);
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
|
||||
// Start the onboarding process for certain actions
|
||||
if (MatrixClientPeg.get() && MatrixClientPeg.get().isGuest() &&
|
||||
|
@ -612,8 +634,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
onFinished: (confirm) => {
|
||||
if (confirm) {
|
||||
// FIXME: controller shouldn't be loading a view :(
|
||||
const Loader = sdk.getComponent("elements.Spinner");
|
||||
const modal = Modal.createDialog(Loader, null, 'mx_Dialog_spinner');
|
||||
const modal = Modal.createDialog(Spinner, null, 'mx_Dialog_spinner');
|
||||
|
||||
MatrixClientPeg.get().leave(payload.room_id).then(() => {
|
||||
modal.close();
|
||||
|
@ -649,7 +670,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
case Action.ViewUserSettings: {
|
||||
const tabPayload = payload as OpenToTabPayload;
|
||||
const UserSettingsDialog = sdk.getComponent("dialogs.UserSettingsDialog");
|
||||
Modal.createTrackedDialog('User settings', '', UserSettingsDialog,
|
||||
{ initialTabId: tabPayload.initialTabId },
|
||||
/*className=*/null, /*isPriority=*/false, /*isStatic=*/true);
|
||||
|
@ -662,11 +682,12 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
this.createRoom(payload.public, payload.defaultName);
|
||||
break;
|
||||
case 'view_create_group': {
|
||||
let CreateGroupDialog = sdk.getComponent("dialogs.CreateGroupDialog");
|
||||
if (SettingsStore.getValue("feature_communities_v2_prototypes")) {
|
||||
CreateGroupDialog = CreateCommunityPrototypeDialog;
|
||||
}
|
||||
Modal.createTrackedDialog('Create Community', '', CreateGroupDialog);
|
||||
const prototype = SettingsStore.getValue("feature_communities_v2_prototypes");
|
||||
Modal.createTrackedDialog(
|
||||
'Create Community',
|
||||
'',
|
||||
prototype ? CreateCommunityPrototypeDialog : CreateGroupDialog,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case Action.ViewRoomDirectory: {
|
||||
|
@ -676,7 +697,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
room_id: SpaceStore.instance.activeSpace.roomId,
|
||||
});
|
||||
} else {
|
||||
const RoomDirectory = sdk.getComponent("structures.RoomDirectory");
|
||||
Modal.createTrackedDialog('Room directory', '', RoomDirectory, {
|
||||
initialText: payload.initialText,
|
||||
}, 'mx_RoomDirectory_dialogWrapper', false, true);
|
||||
|
@ -1018,7 +1038,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
const CreateRoomDialog = sdk.getComponent('dialogs.CreateRoomDialog');
|
||||
const modal = Modal.createTrackedDialog('Create Room', '', CreateRoomDialog, {
|
||||
defaultPublic,
|
||||
defaultName,
|
||||
|
@ -1115,7 +1134,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
|
||||
private leaveRoom(roomId: string) {
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
const roomToLeave = MatrixClientPeg.get().getRoom(roomId);
|
||||
const warnings = this.leaveRoomWarnings(roomId);
|
||||
|
||||
|
@ -1142,8 +1160,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
const d = leaveRoomBehaviour(roomId);
|
||||
|
||||
// FIXME: controller shouldn't be loading a view :(
|
||||
const Loader = sdk.getComponent("elements.Spinner");
|
||||
const modal = Modal.createDialog(Loader, null, 'mx_Dialog_spinner');
|
||||
const modal = Modal.createDialog(Spinner, null, 'mx_Dialog_spinner');
|
||||
|
||||
d.finally(() => modal.close());
|
||||
dis.dispatch({
|
||||
|
@ -1410,7 +1427,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
showNotificationsToast(false);
|
||||
}
|
||||
|
||||
dis.fire(Action.FocusComposer);
|
||||
dis.fire(Action.FocusSendMessageComposer);
|
||||
this.setState({
|
||||
ready: true,
|
||||
});
|
||||
|
@ -1438,7 +1455,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
});
|
||||
});
|
||||
cli.on('no_consent', function(message, consentUri) {
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
Modal.createTrackedDialog('No Consent Dialog', '', QuestionDialog, {
|
||||
title: _t('Terms and Conditions'),
|
||||
description: <div>
|
||||
|
@ -1547,8 +1563,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
});
|
||||
|
||||
cli.on("crypto.keySignatureUploadFailure", (failures, source, continuation) => {
|
||||
const KeySignatureUploadFailedDialog =
|
||||
sdk.getComponent('views.dialogs.KeySignatureUploadFailedDialog');
|
||||
Modal.createTrackedDialog(
|
||||
'Failed to upload key signatures',
|
||||
'Failed to upload key signatures',
|
||||
|
@ -1558,7 +1572,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
|
||||
cli.on("crypto.verification.request", request => {
|
||||
if (request.verifier) {
|
||||
const IncomingSasDialog = sdk.getComponent("views.dialogs.IncomingSasDialog");
|
||||
Modal.createTrackedDialog('Incoming Verification', '', IncomingSasDialog, {
|
||||
verifier: request.verifier,
|
||||
}, null, /* priority = */ false, /* static = */ true);
|
||||
|
@ -1568,7 +1581,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
title: _t("Verification requested"),
|
||||
icon: "verification",
|
||||
props: { request },
|
||||
component: sdk.getComponent("toasts.VerificationRequestToast"),
|
||||
component: VerificationRequestToast,
|
||||
priority: 90,
|
||||
});
|
||||
}
|
||||
|
@ -1976,21 +1989,18 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
let view = null;
|
||||
|
||||
if (this.state.view === Views.LOADING) {
|
||||
const Spinner = sdk.getComponent('elements.Spinner');
|
||||
view = (
|
||||
<div className="mx_MatrixChat_splash">
|
||||
<Spinner />
|
||||
</div>
|
||||
);
|
||||
} else if (this.state.view === Views.COMPLETE_SECURITY) {
|
||||
const CompleteSecurity = sdk.getComponent('structures.auth.CompleteSecurity');
|
||||
view = (
|
||||
<CompleteSecurity
|
||||
onFinished={this.onCompleteSecurityE2eSetupFinished}
|
||||
/>
|
||||
);
|
||||
} else if (this.state.view === Views.E2E_SETUP) {
|
||||
const E2eSetup = sdk.getComponent('structures.auth.E2eSetup');
|
||||
view = (
|
||||
<E2eSetup
|
||||
onFinished={this.onCompleteSecurityE2eSetupFinished}
|
||||
|
@ -2011,7 +2021,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
* we should go through and figure out what we actually need to pass down, as well
|
||||
* as using something like redux to avoid having a billion bits of state kicking around.
|
||||
*/
|
||||
const LoggedInView = sdk.getComponent('structures.LoggedInView');
|
||||
view = (
|
||||
<LoggedInView
|
||||
{...this.props}
|
||||
|
@ -2019,14 +2028,12 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
ref={this.loggedInView}
|
||||
matrixClient={MatrixClientPeg.get()}
|
||||
onRoomCreated={this.onRoomCreated}
|
||||
onCloseAllSettings={this.onCloseAllSettings}
|
||||
onRegistered={this.onRegistered}
|
||||
currentRoomId={this.state.currentRoomId}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
// we think we are logged in, but are still waiting for the /sync to complete
|
||||
const Spinner = sdk.getComponent('elements.Spinner');
|
||||
let errorBox;
|
||||
if (this.state.syncError && !isStoreError) {
|
||||
errorBox = <div className="mx_MatrixChat_syncError">
|
||||
|
@ -2044,10 +2051,8 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
);
|
||||
}
|
||||
} else if (this.state.view === Views.WELCOME) {
|
||||
const Welcome = sdk.getComponent('auth.Welcome');
|
||||
view = <Welcome />;
|
||||
} else if (this.state.view === Views.REGISTER && SettingsStore.getValue(UIFeature.Registration)) {
|
||||
const Registration = sdk.getComponent('structures.auth.Registration');
|
||||
const email = ThreepidInviteStore.instance.pickBestInvite()?.toEmail;
|
||||
view = (
|
||||
<Registration
|
||||
|
@ -2066,7 +2071,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
/>
|
||||
);
|
||||
} else if (this.state.view === Views.FORGOT_PASSWORD && SettingsStore.getValue(UIFeature.PasswordReset)) {
|
||||
const ForgotPassword = sdk.getComponent('structures.auth.ForgotPassword');
|
||||
view = (
|
||||
<ForgotPassword
|
||||
onComplete={this.onLoginClick}
|
||||
|
@ -2077,7 +2081,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
);
|
||||
} else if (this.state.view === Views.LOGIN) {
|
||||
const showPasswordReset = SettingsStore.getValue(UIFeature.PasswordReset);
|
||||
const Login = sdk.getComponent('structures.auth.Login');
|
||||
view = (
|
||||
<Login
|
||||
isSyncing={this.state.pendingInitialSync}
|
||||
|
@ -2093,7 +2096,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
/>
|
||||
);
|
||||
} else if (this.state.view === Views.SOFT_LOGOUT) {
|
||||
const SoftLogout = sdk.getComponent('structures.auth.SoftLogout');
|
||||
view = (
|
||||
<SoftLogout
|
||||
realQueryParams={this.props.realQueryParams}
|
||||
|
@ -2105,7 +2107,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
console.error(`Unknown view ${this.state.view}`);
|
||||
}
|
||||
|
||||
const ErrorBoundary = sdk.getComponent('elements.ErrorBoundary');
|
||||
return <ErrorBoundary>
|
||||
{view}
|
||||
</ErrorBoundary>;
|
||||
|
|
|
@ -48,6 +48,9 @@ import { ActionPayload } from "../../dispatcher/payloads";
|
|||
const MAX_NAME_LENGTH = 80;
|
||||
const MAX_TOPIC_LENGTH = 800;
|
||||
|
||||
const LAST_SERVER_KEY = "mx_last_room_directory_server";
|
||||
const LAST_INSTANCE_KEY = "mx_last_room_directory_instance";
|
||||
|
||||
function track(action: string) {
|
||||
Analytics.trackEvent('RoomDirectory', action);
|
||||
}
|
||||
|
@ -61,7 +64,7 @@ interface IState {
|
|||
loading: boolean;
|
||||
protocolsLoading: boolean;
|
||||
error?: string;
|
||||
instanceId: string | symbol;
|
||||
instanceId: string;
|
||||
roomServer: string;
|
||||
filterString: string;
|
||||
selectedCommunityId?: string;
|
||||
|
@ -116,6 +119,36 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
|
|||
} else if (!selectedCommunityId) {
|
||||
MatrixClientPeg.get().getThirdpartyProtocols().then((response) => {
|
||||
this.protocols = response;
|
||||
const myHomeserver = MatrixClientPeg.getHomeserverName();
|
||||
const lsRoomServer = localStorage.getItem(LAST_SERVER_KEY);
|
||||
const lsInstanceId = localStorage.getItem(LAST_INSTANCE_KEY);
|
||||
|
||||
let roomServer = myHomeserver;
|
||||
if (
|
||||
SdkConfig.get().roomDirectory?.servers?.includes(lsRoomServer) ||
|
||||
SettingsStore.getValue("room_directory_servers")?.includes(lsRoomServer)
|
||||
) {
|
||||
roomServer = lsRoomServer;
|
||||
}
|
||||
|
||||
let instanceId: string = null;
|
||||
if (roomServer === myHomeserver && (
|
||||
lsInstanceId === ALL_ROOMS ||
|
||||
Object.values(this.protocols).some(p => p.instances.some(i => i.instance_id === lsInstanceId))
|
||||
)) {
|
||||
instanceId = lsInstanceId;
|
||||
}
|
||||
|
||||
// Refresh the room list only if validation failed and we had to change these
|
||||
if (this.state.instanceId !== instanceId || this.state.roomServer !== roomServer) {
|
||||
this.setState({
|
||||
protocolsLoading: false,
|
||||
instanceId,
|
||||
roomServer,
|
||||
});
|
||||
this.refreshRoomList();
|
||||
return;
|
||||
}
|
||||
this.setState({ protocolsLoading: false });
|
||||
}, (err) => {
|
||||
console.warn(`error loading third party protocols: ${err}`);
|
||||
|
@ -150,8 +183,8 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
|
|||
publicRooms: [],
|
||||
loading: true,
|
||||
error: null,
|
||||
instanceId: undefined,
|
||||
roomServer: MatrixClientPeg.getHomeserverName(),
|
||||
instanceId: localStorage.getItem(LAST_INSTANCE_KEY),
|
||||
roomServer: localStorage.getItem(LAST_SERVER_KEY),
|
||||
filterString: this.props.initialText || "",
|
||||
selectedCommunityId,
|
||||
communityName: null,
|
||||
|
@ -342,7 +375,7 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
|
|||
}
|
||||
};
|
||||
|
||||
private onOptionChange = (server: string, instanceId?: string | symbol) => {
|
||||
private onOptionChange = (server: string, instanceId?: string) => {
|
||||
// clear next batch so we don't try to load more rooms
|
||||
this.nextBatch = null;
|
||||
this.setState({
|
||||
|
@ -360,6 +393,14 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
|
|||
// find the five gitter ones, at which point we do not want
|
||||
// to render all those rooms when switching back to 'all networks'.
|
||||
// Easiest to just blow away the state & re-fetch.
|
||||
|
||||
// We have to be careful here so that we don't set instanceId = "undefined"
|
||||
localStorage.setItem(LAST_SERVER_KEY, server);
|
||||
if (instanceId) {
|
||||
localStorage.setItem(LAST_INSTANCE_KEY, instanceId);
|
||||
} else {
|
||||
localStorage.removeItem(LAST_INSTANCE_KEY);
|
||||
}
|
||||
};
|
||||
|
||||
private onFillRequest = (backwards: boolean) => {
|
||||
|
|
|
@ -131,7 +131,7 @@ export default class RoomSearch extends React.PureComponent<IProps, IState> {
|
|||
switch (action) {
|
||||
case RoomListAction.ClearSearch:
|
||||
this.clearInput();
|
||||
defaultDispatcher.fire(Action.FocusComposer);
|
||||
defaultDispatcher.fire(Action.FocusSendMessageComposer);
|
||||
break;
|
||||
case RoomListAction.NextRoom:
|
||||
case RoomListAction.PrevRoom:
|
||||
|
|
|
@ -118,12 +118,12 @@ export default class RoomStatusBar extends React.PureComponent {
|
|||
this.setState({ isResending: false });
|
||||
});
|
||||
this.setState({ isResending: true });
|
||||
dis.fire(Action.FocusComposer);
|
||||
dis.fire(Action.FocusSendMessageComposer);
|
||||
};
|
||||
|
||||
_onCancelAllClick = () => {
|
||||
Resend.cancelUnsentEvents(this.props.room);
|
||||
dis.fire(Action.FocusComposer);
|
||||
dis.fire(Action.FocusSendMessageComposer);
|
||||
};
|
||||
|
||||
_onRoomLocalEchoUpdated = (event, room, oldEventId, oldStatus) => {
|
||||
|
|
|
@ -34,7 +34,6 @@ import { RoomPermalinkCreator } from '../../utils/permalinks/Permalinks';
|
|||
import ResizeNotifier from '../../utils/ResizeNotifier';
|
||||
import ContentMessages from '../../ContentMessages';
|
||||
import Modal from '../../Modal';
|
||||
import * as sdk from '../../index';
|
||||
import CallHandler, { PlaceCallType } from '../../CallHandler';
|
||||
import dis from '../../dispatcher/dispatcher';
|
||||
import * as Rooms from '../../Rooms';
|
||||
|
@ -42,7 +41,7 @@ import eventSearch, { searchPagination } from '../../Searching';
|
|||
import MainSplit from './MainSplit';
|
||||
import RightPanel from './RightPanel';
|
||||
import RoomViewStore from '../../stores/RoomViewStore';
|
||||
import RoomScrollStateStore from '../../stores/RoomScrollStateStore';
|
||||
import RoomScrollStateStore, { ScrollState } from '../../stores/RoomScrollStateStore';
|
||||
import WidgetEchoStore from '../../stores/WidgetEchoStore';
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
import { Layout } from "../../settings/Layout";
|
||||
|
@ -82,6 +81,14 @@ import { replaceableComponent } from "../../utils/replaceableComponent";
|
|||
import UIStore from "../../stores/UIStore";
|
||||
import EditorStateTransfer from "../../utils/EditorStateTransfer";
|
||||
import { throttle } from "lodash";
|
||||
import ErrorDialog from '../views/dialogs/ErrorDialog';
|
||||
import SearchResultTile from '../views/rooms/SearchResultTile';
|
||||
import Spinner from "../views/elements/Spinner";
|
||||
import UploadBar from './UploadBar';
|
||||
import RoomStatusBar from "./RoomStatusBar";
|
||||
import MessageComposer from '../views/rooms/MessageComposer';
|
||||
import JumpToBottomButton from "../views/rooms/JumpToBottomButton";
|
||||
import TopUnreadMessagesBar from "../views/rooms/TopUnreadMessagesBar";
|
||||
|
||||
const DEBUG = false;
|
||||
let debuglog = function(msg: string) {};
|
||||
|
@ -811,17 +818,16 @@ export default class RoomView extends React.Component<IProps, IState> {
|
|||
|
||||
case Action.ComposerInsert: {
|
||||
// re-dispatch to the correct composer
|
||||
if (this.state.editState) {
|
||||
dis.dispatch({
|
||||
...payload,
|
||||
action: "edit_composer_insert",
|
||||
});
|
||||
} else {
|
||||
dis.dispatch({
|
||||
...payload,
|
||||
action: "send_composer_insert",
|
||||
});
|
||||
}
|
||||
dis.dispatch({
|
||||
...payload,
|
||||
action: this.state.editState ? "edit_composer_insert" : "send_composer_insert",
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case Action.FocusAComposer: {
|
||||
// re-dispatch to the correct composer
|
||||
dis.fire(this.state.editState ? Action.FocusEditMessageComposer : Action.FocusSendMessageComposer);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1239,7 +1245,7 @@ export default class RoomView extends React.Component<IProps, IState> {
|
|||
ContentMessages.sharedInstance().sendContentListToRoom(
|
||||
ev.dataTransfer.files, this.state.room.roomId, this.context,
|
||||
);
|
||||
dis.fire(Action.FocusComposer);
|
||||
dis.fire(Action.FocusSendMessageComposer);
|
||||
|
||||
this.setState({
|
||||
draggingFile: false,
|
||||
|
@ -1328,7 +1334,6 @@ export default class RoomView extends React.Component<IProps, IState> {
|
|||
searchResults: results,
|
||||
});
|
||||
}, (error) => {
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
console.error("Search failed", error);
|
||||
Modal.createTrackedDialog('Search failed', '', ErrorDialog, {
|
||||
title: _t("Search failed"),
|
||||
|
@ -1344,9 +1349,6 @@ export default class RoomView extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
private getSearchResultTiles() {
|
||||
const SearchResultTile = sdk.getComponent('rooms.SearchResultTile');
|
||||
const Spinner = sdk.getComponent("elements.Spinner");
|
||||
|
||||
// XXX: todo: merge overlapping results somehow?
|
||||
// XXX: why doesn't searching on name work?
|
||||
|
||||
|
@ -1466,7 +1468,6 @@ export default class RoomView extends React.Component<IProps, IState> {
|
|||
console.error("Failed to reject invite: %s", error);
|
||||
|
||||
const msg = error.message ? error.message : JSON.stringify(error);
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createTrackedDialog('Failed to reject invite', '', ErrorDialog, {
|
||||
title: _t("Failed to reject invite"),
|
||||
description: msg,
|
||||
|
@ -1500,7 +1501,6 @@ export default class RoomView extends React.Component<IProps, IState> {
|
|||
console.error("Failed to reject invite: %s", error);
|
||||
|
||||
const msg = error.message ? error.message : JSON.stringify(error);
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createTrackedDialog('Failed to reject invite', '', ErrorDialog, {
|
||||
title: _t("Failed to reject invite"),
|
||||
description: msg,
|
||||
|
@ -1547,7 +1547,7 @@ export default class RoomView extends React.Component<IProps, IState> {
|
|||
} else {
|
||||
// Otherwise we have to jump manually
|
||||
this.messagePanel.jumpToLiveTimeline();
|
||||
dis.fire(Action.FocusComposer);
|
||||
dis.fire(Action.FocusSendMessageComposer);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1577,7 +1577,7 @@ export default class RoomView extends React.Component<IProps, IState> {
|
|||
// get the current scroll position of the room, so that it can be
|
||||
// restored when we switch back to it.
|
||||
//
|
||||
private getScrollState() {
|
||||
private getScrollState(): ScrollState {
|
||||
const messagePanel = this.messagePanel;
|
||||
if (!messagePanel) return null;
|
||||
|
||||
|
@ -1834,10 +1834,8 @@ export default class RoomView extends React.Component<IProps, IState> {
|
|||
let isStatusAreaExpanded = true;
|
||||
|
||||
if (ContentMessages.sharedInstance().getCurrentUploads().length > 0) {
|
||||
const UploadBar = sdk.getComponent('structures.UploadBar');
|
||||
statusBar = <UploadBar room={this.state.room} />;
|
||||
} else if (!this.state.searchResults) {
|
||||
const RoomStatusBar = sdk.getComponent('structures.RoomStatusBar');
|
||||
isStatusAreaExpanded = this.state.statusBarVisible;
|
||||
statusBar = <RoomStatusBar
|
||||
room={this.state.room}
|
||||
|
@ -1943,12 +1941,9 @@ export default class RoomView extends React.Component<IProps, IState> {
|
|||
myMembership === 'join' && !this.state.searchResults
|
||||
);
|
||||
if (canSpeak) {
|
||||
const MessageComposer = sdk.getComponent('rooms.MessageComposer');
|
||||
messageComposer =
|
||||
<MessageComposer
|
||||
room={this.state.room}
|
||||
callState={this.state.callState}
|
||||
showApps={this.state.showApps}
|
||||
e2eStatus={this.state.e2eStatus}
|
||||
resizeNotifier={this.props.resizeNotifier}
|
||||
replyToEvent={this.state.replyToEvent}
|
||||
|
@ -2034,7 +2029,6 @@ export default class RoomView extends React.Component<IProps, IState> {
|
|||
let topUnreadMessagesBar = null;
|
||||
// Do not show TopUnreadMessagesBar if we have search results showing, it makes no sense
|
||||
if (this.state.showTopUnreadMessagesBar && !this.state.searchResults) {
|
||||
const TopUnreadMessagesBar = sdk.getComponent('rooms.TopUnreadMessagesBar');
|
||||
topUnreadMessagesBar = (
|
||||
<TopUnreadMessagesBar onScrollUpClick={this.jumpToReadMarker} onCloseClick={this.forgetReadMarker} />
|
||||
);
|
||||
|
@ -2042,7 +2036,6 @@ export default class RoomView extends React.Component<IProps, IState> {
|
|||
let jumpToBottom;
|
||||
// Do not show JumpToBottomButton if we have search results showing, it makes no sense
|
||||
if (!this.state.atEndOfLiveTimeline && !this.state.searchResults) {
|
||||
const JumpToBottomButton = sdk.getComponent('rooms.JumpToBottomButton');
|
||||
jumpToBottom = (<JumpToBottomButton
|
||||
highlight={this.state.room.getUnreadNotificationCount(NotificationCountType.Highlight) > 0}
|
||||
numUnreadMessages={this.state.numUnreadMessages}
|
||||
|
|
|
@ -18,9 +18,9 @@ limitations under the License.
|
|||
|
||||
import * as React from "react";
|
||||
import { _t } from '../../languageHandler';
|
||||
import * as sdk from "../../index";
|
||||
import AutoHideScrollbar from './AutoHideScrollbar';
|
||||
import { replaceableComponent } from "../../utils/replaceableComponent";
|
||||
import AccessibleButton from "../views/elements/AccessibleButton";
|
||||
|
||||
/**
|
||||
* Represents a tab for the TabbedView.
|
||||
|
@ -82,8 +82,6 @@ export default class TabbedView extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
private _renderTabLabel(tab: Tab) {
|
||||
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
||||
|
||||
let classes = "mx_TabbedView_tabLabel ";
|
||||
|
||||
const idx = this.props.tabs.indexOf(tab);
|
||||
|
|
|
@ -32,7 +32,6 @@ import RoomContext from "../../contexts/RoomContext";
|
|||
import UserActivity from "../../UserActivity";
|
||||
import Modal from "../../Modal";
|
||||
import dis from "../../dispatcher/dispatcher";
|
||||
import * as sdk from "../../index";
|
||||
import { Key } from '../../Keyboard';
|
||||
import Timer from '../../utils/Timer';
|
||||
import shouldHideEvent from '../../shouldHideEvent';
|
||||
|
@ -47,6 +46,7 @@ import ResizeNotifier from "../../utils/ResizeNotifier";
|
|||
import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks";
|
||||
import Spinner from "../views/elements/Spinner";
|
||||
import EditorStateTransfer from '../../utils/EditorStateTransfer';
|
||||
import ErrorDialog from '../views/dialogs/ErrorDialog';
|
||||
|
||||
const PAGINATE_SIZE = 20;
|
||||
const INITIAL_SIZE = 20;
|
||||
|
@ -1096,7 +1096,6 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
console.error(
|
||||
`Error loading timeline panel at ${eventId}: ${error}`,
|
||||
);
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
|
||||
let onFinished;
|
||||
|
||||
|
|
|
@ -15,39 +15,42 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import * as sdk from '../../../index';
|
||||
import { SetupEncryptionStore, Phase } from '../../../stores/SetupEncryptionStore';
|
||||
import SetupEncryptionBody from "./SetupEncryptionBody";
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
|
||||
@replaceableComponent("structures.auth.CompleteSecurity")
|
||||
export default class CompleteSecurity extends React.Component {
|
||||
static propTypes = {
|
||||
onFinished: PropTypes.func.isRequired,
|
||||
};
|
||||
interface IProps {
|
||||
onFinished: () => void;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
interface IState {
|
||||
phase: Phase;
|
||||
}
|
||||
|
||||
@replaceableComponent("structures.auth.CompleteSecurity")
|
||||
export default class CompleteSecurity extends React.Component<IProps, IState> {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
const store = SetupEncryptionStore.sharedInstance();
|
||||
store.on("update", this._onStoreUpdate);
|
||||
store.on("update", this.onStoreUpdate);
|
||||
store.start();
|
||||
this.state = { phase: store.phase };
|
||||
}
|
||||
|
||||
_onStoreUpdate = () => {
|
||||
private onStoreUpdate = (): void => {
|
||||
const store = SetupEncryptionStore.sharedInstance();
|
||||
this.setState({ phase: store.phase });
|
||||
};
|
||||
|
||||
componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
const store = SetupEncryptionStore.sharedInstance();
|
||||
store.off("update", this._onStoreUpdate);
|
||||
store.off("update", this.onStoreUpdate);
|
||||
store.stop();
|
||||
}
|
||||
|
||||
render() {
|
||||
public render() {
|
||||
const AuthPage = sdk.getComponent("auth.AuthPage");
|
||||
const CompleteSecurityBody = sdk.getComponent("auth.CompleteSecurityBody");
|
||||
const { phase } = this.state;
|
|
@ -15,20 +15,19 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import AuthPage from '../../views/auth/AuthPage';
|
||||
import CompleteSecurityBody from '../../views/auth/CompleteSecurityBody';
|
||||
import CreateCrossSigningDialog from '../../views/dialogs/security/CreateCrossSigningDialog';
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
|
||||
@replaceableComponent("structures.auth.E2eSetup")
|
||||
export default class E2eSetup extends React.Component {
|
||||
static propTypes = {
|
||||
onFinished: PropTypes.func.isRequired,
|
||||
accountPassword: PropTypes.string,
|
||||
tokenLogin: PropTypes.bool,
|
||||
};
|
||||
interface IProps {
|
||||
onFinished: () => void;
|
||||
accountPassword?: string;
|
||||
tokenLogin?: boolean;
|
||||
}
|
||||
|
||||
@replaceableComponent("structures.auth.E2eSetup")
|
||||
export default class E2eSetup extends React.Component<IProps> {
|
||||
render() {
|
||||
return (
|
||||
<AuthPage>
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { _t, _td } from '../../../languageHandler';
|
||||
import * as sdk from '../../../index';
|
||||
import Modal from "../../../Modal";
|
||||
|
@ -31,27 +30,50 @@ import PassphraseField from '../../views/auth/PassphraseField';
|
|||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import { PASSWORD_MIN_SCORE } from '../../views/auth/RegistrationForm';
|
||||
|
||||
// Phases
|
||||
// Show the forgot password inputs
|
||||
const PHASE_FORGOT = 1;
|
||||
// Email is in the process of being sent
|
||||
const PHASE_SENDING_EMAIL = 2;
|
||||
// Email has been sent
|
||||
const PHASE_EMAIL_SENT = 3;
|
||||
// User has clicked the link in email and completed reset
|
||||
const PHASE_DONE = 4;
|
||||
import { IValidationResult } from "../../views/elements/Validation";
|
||||
|
||||
enum Phase {
|
||||
// Show the forgot password inputs
|
||||
Forgot = 1,
|
||||
// Email is in the process of being sent
|
||||
SendingEmail = 2,
|
||||
// Email has been sent
|
||||
EmailSent = 3,
|
||||
// User has clicked the link in email and completed reset
|
||||
Done = 4,
|
||||
}
|
||||
|
||||
interface IProps {
|
||||
serverConfig: ValidatedServerConfig;
|
||||
onServerConfigChange: (serverConfig: ValidatedServerConfig) => void;
|
||||
onLoginClick?: () => void;
|
||||
onComplete: () => void;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
phase: Phase;
|
||||
email: string;
|
||||
password: string;
|
||||
password2: string;
|
||||
errorText: string;
|
||||
|
||||
// We perform liveliness checks later, but for now suppress the errors.
|
||||
// We also track the server dead errors independently of the regular errors so
|
||||
// that we can render it differently, and override any other error the user may
|
||||
// be seeing.
|
||||
serverIsAlive: boolean;
|
||||
serverErrorIsFatal: boolean;
|
||||
serverDeadError: string;
|
||||
|
||||
passwordFieldValid: boolean;
|
||||
}
|
||||
|
||||
@replaceableComponent("structures.auth.ForgotPassword")
|
||||
export default class ForgotPassword extends React.Component {
|
||||
static propTypes = {
|
||||
serverConfig: PropTypes.instanceOf(ValidatedServerConfig).isRequired,
|
||||
onServerConfigChange: PropTypes.func.isRequired,
|
||||
onLoginClick: PropTypes.func,
|
||||
onComplete: PropTypes.func.isRequired,
|
||||
};
|
||||
export default class ForgotPassword extends React.Component<IProps, IState> {
|
||||
private reset: PasswordReset;
|
||||
|
||||
state = {
|
||||
phase: PHASE_FORGOT,
|
||||
phase: Phase.Forgot,
|
||||
email: "",
|
||||
password: "",
|
||||
password2: "",
|
||||
|
@ -64,30 +86,31 @@ export default class ForgotPassword extends React.Component {
|
|||
serverIsAlive: true,
|
||||
serverErrorIsFatal: false,
|
||||
serverDeadError: "",
|
||||
passwordFieldValid: false,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
CountlyAnalytics.instance.track("onboarding_forgot_password_begin");
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
public componentDidMount() {
|
||||
this.reset = null;
|
||||
this._checkServerLiveliness(this.props.serverConfig);
|
||||
this.checkServerLiveliness(this.props.serverConfig);
|
||||
}
|
||||
|
||||
// TODO: [REACT-WARNING] Replace with appropriate lifecycle event
|
||||
// eslint-disable-next-line camelcase
|
||||
UNSAFE_componentWillReceiveProps(newProps) {
|
||||
public UNSAFE_componentWillReceiveProps(newProps: IProps): void {
|
||||
if (newProps.serverConfig.hsUrl === this.props.serverConfig.hsUrl &&
|
||||
newProps.serverConfig.isUrl === this.props.serverConfig.isUrl) return;
|
||||
|
||||
// Do a liveliness check on the new URLs
|
||||
this._checkServerLiveliness(newProps.serverConfig);
|
||||
this.checkServerLiveliness(newProps.serverConfig);
|
||||
}
|
||||
|
||||
async _checkServerLiveliness(serverConfig) {
|
||||
private async checkServerLiveliness(serverConfig): Promise<void> {
|
||||
try {
|
||||
await AutoDiscoveryUtils.validateServerConfigWithStaticUrls(
|
||||
serverConfig.hsUrl,
|
||||
|
@ -98,28 +121,28 @@ export default class ForgotPassword extends React.Component {
|
|||
serverIsAlive: true,
|
||||
});
|
||||
} catch (e) {
|
||||
this.setState(AutoDiscoveryUtils.authComponentStateForError(e, "forgot_password"));
|
||||
this.setState(AutoDiscoveryUtils.authComponentStateForError(e, "forgot_password") as IState);
|
||||
}
|
||||
}
|
||||
|
||||
submitPasswordReset(email, password) {
|
||||
public submitPasswordReset(email: string, password: string): void {
|
||||
this.setState({
|
||||
phase: PHASE_SENDING_EMAIL,
|
||||
phase: Phase.SendingEmail,
|
||||
});
|
||||
this.reset = new PasswordReset(this.props.serverConfig.hsUrl, this.props.serverConfig.isUrl);
|
||||
this.reset.resetPassword(email, password).then(() => {
|
||||
this.setState({
|
||||
phase: PHASE_EMAIL_SENT,
|
||||
phase: Phase.EmailSent,
|
||||
});
|
||||
}, (err) => {
|
||||
this.showErrorDialog(_t('Failed to send email') + ": " + err.message);
|
||||
this.setState({
|
||||
phase: PHASE_FORGOT,
|
||||
phase: Phase.Forgot,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
onVerify = async ev => {
|
||||
private onVerify = async (ev: React.MouseEvent): Promise<void> => {
|
||||
ev.preventDefault();
|
||||
if (!this.reset) {
|
||||
console.error("onVerify called before submitPasswordReset!");
|
||||
|
@ -127,17 +150,17 @@ export default class ForgotPassword extends React.Component {
|
|||
}
|
||||
try {
|
||||
await this.reset.checkEmailLinkClicked();
|
||||
this.setState({ phase: PHASE_DONE });
|
||||
this.setState({ phase: Phase.Done });
|
||||
} catch (err) {
|
||||
this.showErrorDialog(err.message);
|
||||
}
|
||||
};
|
||||
|
||||
onSubmitForm = async ev => {
|
||||
private onSubmitForm = async (ev: React.FormEvent): Promise<void> => {
|
||||
ev.preventDefault();
|
||||
|
||||
// refresh the server errors, just in case the server came back online
|
||||
await this._checkServerLiveliness(this.props.serverConfig);
|
||||
await this.checkServerLiveliness(this.props.serverConfig);
|
||||
|
||||
await this['password_field'].validate({ allowEmpty: false });
|
||||
|
||||
|
@ -172,27 +195,27 @@ export default class ForgotPassword extends React.Component {
|
|||
}
|
||||
};
|
||||
|
||||
onInputChanged = (stateKey, ev) => {
|
||||
private onInputChanged = (stateKey: string, ev: React.FormEvent<HTMLInputElement>) => {
|
||||
this.setState({
|
||||
[stateKey]: ev.target.value,
|
||||
});
|
||||
[stateKey]: ev.currentTarget.value,
|
||||
} as any);
|
||||
};
|
||||
|
||||
onLoginClick = ev => {
|
||||
private onLoginClick = (ev: React.MouseEvent): void => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
this.props.onLoginClick();
|
||||
};
|
||||
|
||||
showErrorDialog(body, title) {
|
||||
public showErrorDialog(description: string, title?: string) {
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createTrackedDialog('Forgot Password Error', '', ErrorDialog, {
|
||||
title: title,
|
||||
description: body,
|
||||
title,
|
||||
description,
|
||||
});
|
||||
}
|
||||
|
||||
onPasswordValidate(result) {
|
||||
private onPasswordValidate(result: IValidationResult) {
|
||||
this.setState({
|
||||
passwordFieldValid: result.valid,
|
||||
});
|
||||
|
@ -316,16 +339,16 @@ export default class ForgotPassword extends React.Component {
|
|||
|
||||
let resetPasswordJsx;
|
||||
switch (this.state.phase) {
|
||||
case PHASE_FORGOT:
|
||||
case Phase.Forgot:
|
||||
resetPasswordJsx = this.renderForgot();
|
||||
break;
|
||||
case PHASE_SENDING_EMAIL:
|
||||
case Phase.SendingEmail:
|
||||
resetPasswordJsx = this.renderSendingEmail();
|
||||
break;
|
||||
case PHASE_EMAIL_SENT:
|
||||
case Phase.EmailSent:
|
||||
resetPasswordJsx = this.renderEmailSent();
|
||||
break;
|
||||
case PHASE_DONE:
|
||||
case Phase.Done:
|
||||
resetPasswordJsx = this.renderDone();
|
||||
break;
|
||||
}
|
|
@ -18,7 +18,6 @@ import React, { ReactNode } from 'react';
|
|||
import { MatrixError } from "matrix-js-sdk/src/http-api";
|
||||
|
||||
import { _t, _td } from '../../../languageHandler';
|
||||
import * as sdk from '../../../index';
|
||||
import Login, { ISSOFlow, LoginFlow } from '../../../Login';
|
||||
import SdkConfig from '../../../SdkConfig';
|
||||
import { messageForResourceLimitError } from '../../../utils/ErrorUtils';
|
||||
|
@ -36,6 +35,8 @@ import Spinner from "../../views/elements/Spinner";
|
|||
import SSOButtons from "../../views/elements/SSOButtons";
|
||||
import ServerPicker from "../../views/elements/ServerPicker";
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import AuthBody from "../../views/auth/AuthBody";
|
||||
import AuthHeader from "../../views/auth/AuthHeader";
|
||||
|
||||
// These are used in several places, and come from the js-sdk's autodiscovery
|
||||
// stuff. We define them here so that they'll be picked up by i18n.
|
||||
|
@ -541,8 +542,6 @@ export default class LoginComponent extends React.PureComponent<IProps, IState>
|
|||
};
|
||||
|
||||
render() {
|
||||
const AuthHeader = sdk.getComponent("auth.AuthHeader");
|
||||
const AuthBody = sdk.getComponent("auth.AuthBody");
|
||||
const loader = this.isBusy() && !this.state.busyLoggingIn ?
|
||||
<div className="mx_Login_loader"><Spinner /></div> : null;
|
||||
|
||||
|
|
|
@ -18,19 +18,24 @@ import { createClient } from 'matrix-js-sdk/src/matrix';
|
|||
import React, { ReactNode } from 'react';
|
||||
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||
|
||||
import * as sdk from '../../../index';
|
||||
import { _t, _td } from '../../../languageHandler';
|
||||
import { messageForResourceLimitError } from '../../../utils/ErrorUtils';
|
||||
import AutoDiscoveryUtils, { ValidatedServerConfig } from "../../../utils/AutoDiscoveryUtils";
|
||||
import classNames from "classnames";
|
||||
import * as Lifecycle from '../../../Lifecycle';
|
||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||
import { IMatrixClientCreds, MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||
import AuthPage from "../../views/auth/AuthPage";
|
||||
import Login, { ISSOFlow } from "../../../Login";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import SSOButtons from "../../views/elements/SSOButtons";
|
||||
import ServerPicker from '../../views/elements/ServerPicker';
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import RegistrationForm from '../../views/auth/RegistrationForm';
|
||||
import AccessibleButton from '../../views/elements/AccessibleButton';
|
||||
import AuthBody from "../../views/auth/AuthBody";
|
||||
import AuthHeader from "../../views/auth/AuthHeader";
|
||||
import InteractiveAuth from "../InteractiveAuth";
|
||||
import Spinner from "../../views/elements/Spinner";
|
||||
|
||||
interface IProps {
|
||||
serverConfig: ValidatedServerConfig;
|
||||
|
@ -47,13 +52,7 @@ interface IProps {
|
|||
// - The user's password, if available and applicable (may be cached in memory
|
||||
// for a short time so the user is not required to re-enter their password
|
||||
// for operations like uploading cross-signing keys).
|
||||
onLoggedIn(params: {
|
||||
userId: string;
|
||||
deviceId: string;
|
||||
homeserverUrl: string;
|
||||
identityServerUrl?: string;
|
||||
accessToken: string;
|
||||
}, password: string): void;
|
||||
onLoggedIn(params: IMatrixClientCreds, password: string): void;
|
||||
makeRegistrationUrl(params: {
|
||||
/* eslint-disable camelcase */
|
||||
client_secret: string;
|
||||
|
@ -246,7 +245,7 @@ export default class Registration extends React.Component<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
private onFormSubmit = formVals => {
|
||||
private onFormSubmit = async (formVals): Promise<void> => {
|
||||
this.setState({
|
||||
errorText: "",
|
||||
busy: true,
|
||||
|
@ -442,10 +441,6 @@ export default class Registration extends React.Component<IProps, IState> {
|
|||
};
|
||||
|
||||
private renderRegisterComponent() {
|
||||
const InteractiveAuth = sdk.getComponent('structures.InteractiveAuth');
|
||||
const Spinner = sdk.getComponent('elements.Spinner');
|
||||
const RegistrationForm = sdk.getComponent('auth.RegistrationForm');
|
||||
|
||||
if (this.state.matrixClient && this.state.doingUIAuth) {
|
||||
return <InteractiveAuth
|
||||
matrixClient={this.state.matrixClient}
|
||||
|
@ -516,10 +511,6 @@ export default class Registration extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
render() {
|
||||
const AuthHeader = sdk.getComponent('auth.AuthHeader');
|
||||
const AuthBody = sdk.getComponent("auth.AuthBody");
|
||||
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
||||
|
||||
let errorText;
|
||||
const err = this.state.errorText;
|
||||
if (err) {
|
||||
|
|
|
@ -21,7 +21,7 @@ import Modal from '../../../Modal';
|
|||
import VerificationRequestDialog from '../../views/dialogs/VerificationRequestDialog';
|
||||
import { SetupEncryptionStore, Phase } from '../../../stores/SetupEncryptionStore';
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import { ISecretStorageKeyInfo } from 'matrix-js-sdk';
|
||||
import { ISecretStorageKeyInfo } from 'matrix-js-sdk/src/crypto/api';
|
||||
import EncryptionPanel from "../../views/right_panel/EncryptionPanel";
|
||||
import AccessibleButton from '../../views/elements/AccessibleButton';
|
||||
import Spinner from '../../views/elements/Spinner';
|
||||
|
|
|
@ -16,7 +16,6 @@ limitations under the License.
|
|||
|
||||
import React from 'react';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import * as sdk from '../../../index';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import * as Lifecycle from '../../../Lifecycle';
|
||||
import Modal from '../../../Modal';
|
||||
|
@ -26,6 +25,12 @@ import AuthPage from "../../views/auth/AuthPage";
|
|||
import { SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY } from "../../../BasePlatform";
|
||||
import SSOButtons from "../../views/elements/SSOButtons";
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import ConfirmWipeDeviceDialog from '../../views/dialogs/ConfirmWipeDeviceDialog';
|
||||
import Field from '../../views/elements/Field';
|
||||
import AccessibleButton from '../../views/elements/AccessibleButton';
|
||||
import Spinner from "../../views/elements/Spinner";
|
||||
import AuthHeader from "../../views/auth/AuthHeader";
|
||||
import AuthBody from "../../views/auth/AuthBody";
|
||||
|
||||
const LOGIN_VIEW = {
|
||||
LOADING: 1,
|
||||
|
@ -94,7 +99,6 @@ export default class SoftLogout extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
onClearAll = () => {
|
||||
const ConfirmWipeDeviceDialog = sdk.getComponent('dialogs.ConfirmWipeDeviceDialog');
|
||||
Modal.createTrackedDialog('Clear Data', 'Soft Logout', ConfirmWipeDeviceDialog, {
|
||||
onFinished: (wipeData) => {
|
||||
if (!wipeData) return;
|
||||
|
@ -202,7 +206,6 @@ export default class SoftLogout extends React.Component<IProps, IState> {
|
|||
|
||||
private renderSignInSection() {
|
||||
if (this.state.loginView === LOGIN_VIEW.LOADING) {
|
||||
const Spinner = sdk.getComponent("elements.Spinner");
|
||||
return <Spinner />;
|
||||
}
|
||||
|
||||
|
@ -214,9 +217,6 @@ export default class SoftLogout extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
if (this.state.loginView === LOGIN_VIEW.PASSWORD) {
|
||||
const Field = sdk.getComponent("elements.Field");
|
||||
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
||||
|
||||
let error = null;
|
||||
if (this.state.errorText) {
|
||||
error = <span className='mx_Login_error'>{this.state.errorText}</span>;
|
||||
|
@ -286,10 +286,6 @@ export default class SoftLogout extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
render() {
|
||||
const AuthHeader = sdk.getComponent("auth.AuthHeader");
|
||||
const AuthBody = sdk.getComponent("auth.AuthBody");
|
||||
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
||||
|
||||
return (
|
||||
<AuthPage>
|
||||
<AuthHeader />
|
||||
|
|
|
@ -18,7 +18,6 @@ import React, { ChangeEvent, createRef, FormEvent, MouseEvent } from 'react';
|
|||
import classNames from 'classnames';
|
||||
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||
|
||||
import * as sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import AccessibleButton from "../elements/AccessibleButton";
|
||||
|
@ -26,6 +25,8 @@ import Spinner from "../elements/Spinner";
|
|||
import CountlyAnalytics from "../../../CountlyAnalytics";
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import { LocalisedPolicy, Policies } from '../../../Terms';
|
||||
import Field from '../elements/Field';
|
||||
import CaptchaForm from "./CaptchaForm";
|
||||
|
||||
/* This file contains a collection of components which are used by the
|
||||
* InteractiveAuth to prompt the user to enter the information needed
|
||||
|
@ -164,8 +165,7 @@ export class PasswordAuthEntry extends React.Component<IAuthEntryProps, IPasswor
|
|||
|
||||
let submitButtonOrSpinner;
|
||||
if (this.props.busy) {
|
||||
const Loader = sdk.getComponent("elements.Spinner");
|
||||
submitButtonOrSpinner = <Loader />;
|
||||
submitButtonOrSpinner = <Spinner />;
|
||||
} else {
|
||||
submitButtonOrSpinner = (
|
||||
<input type="submit"
|
||||
|
@ -185,8 +185,6 @@ export class PasswordAuthEntry extends React.Component<IAuthEntryProps, IPasswor
|
|||
);
|
||||
}
|
||||
|
||||
const Field = sdk.getComponent('elements.Field');
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>{ _t("Confirm your identity by entering your account password below.") }</p>
|
||||
|
@ -236,13 +234,11 @@ export class RecaptchaAuthEntry extends React.Component<IRecaptchaAuthEntryProps
|
|||
|
||||
render() {
|
||||
if (this.props.busy) {
|
||||
const Loader = sdk.getComponent("elements.Spinner");
|
||||
return <Loader />;
|
||||
return <Spinner />;
|
||||
}
|
||||
|
||||
let errorText = this.props.errorText;
|
||||
|
||||
const CaptchaForm = sdk.getComponent("views.auth.CaptchaForm");
|
||||
let sitePublicKey;
|
||||
if (!this.props.stageParams || !this.props.stageParams.public_key) {
|
||||
errorText = _t(
|
||||
|
@ -390,8 +386,7 @@ export class TermsAuthEntry extends React.Component<ITermsAuthEntryProps, ITerms
|
|||
|
||||
render() {
|
||||
if (this.props.busy) {
|
||||
const Loader = sdk.getComponent("elements.Spinner");
|
||||
return <Loader />;
|
||||
return <Spinner />;
|
||||
}
|
||||
|
||||
const checkboxes = [];
|
||||
|
@ -590,8 +585,7 @@ export class MsisdnAuthEntry extends React.Component<IMsisdnAuthEntryProps, IMsi
|
|||
|
||||
render() {
|
||||
if (this.state.requestingToken) {
|
||||
const Loader = sdk.getComponent("elements.Spinner");
|
||||
return <Loader />;
|
||||
return <Spinner />;
|
||||
} else {
|
||||
const enableSubmit = Boolean(this.state.token);
|
||||
const submitClasses = classNames({
|
||||
|
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||
|
||||
import React from 'react';
|
||||
|
||||
import * as sdk from '../../../index';
|
||||
import * as Email from '../../../email';
|
||||
import { looksValid as phoneNumberLooksValid } from '../../../phonenumber';
|
||||
import Modal from '../../../Modal';
|
||||
|
@ -31,6 +30,7 @@ import CountlyAnalytics from "../../../CountlyAnalytics";
|
|||
import Field from '../elements/Field';
|
||||
import RegistrationEmailPromptDialog from '../dialogs/RegistrationEmailPromptDialog';
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import CountryDropdown from "./CountryDropdown";
|
||||
|
||||
enum RegistrationField {
|
||||
Email = "field_email",
|
||||
|
@ -471,7 +471,6 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
|
|||
if (!this.showPhoneNumber()) {
|
||||
return null;
|
||||
}
|
||||
const CountryDropdown = sdk.getComponent('views.auth.CountryDropdown');
|
||||
const phoneLabel = this.authStepIsRequired('m.login.msisdn') ?
|
||||
_t("Phone") :
|
||||
_t("Phone (optional)");
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
|
||||
Copyright 2015, 2016, 2018, 2019, 2021 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2015 - 2021 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.
|
||||
|
@ -16,12 +16,11 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { EventStatus } from 'matrix-js-sdk/src/models/event';
|
||||
import { EventStatus, MatrixEvent } from 'matrix-js-sdk/src/models/event';
|
||||
import { EventType, RelationType } from "matrix-js-sdk/src/@types/event";
|
||||
|
||||
import { MatrixClientPeg } from '../../../MatrixClientPeg';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import * as sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import Modal from '../../../Modal';
|
||||
import Resend from '../../../Resend';
|
||||
|
@ -29,53 +28,65 @@ import SettingsStore from '../../../settings/SettingsStore';
|
|||
import { isUrlPermitted } from '../../../HtmlUtils';
|
||||
import { isContentActionable } from '../../../utils/EventUtils';
|
||||
import IconizedContextMenu, { IconizedContextMenuOption, IconizedContextMenuOptionList } from './IconizedContextMenu';
|
||||
import { EventType } from "matrix-js-sdk/src/@types/event";
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import { ReadPinsEventId } from "../right_panel/PinnedMessagesCard";
|
||||
import ForwardDialog from "../dialogs/ForwardDialog";
|
||||
import { Action } from "../../../dispatcher/actions";
|
||||
import ReportEventDialog from '../dialogs/ReportEventDialog';
|
||||
import ViewSource from '../../structures/ViewSource';
|
||||
import ConfirmRedactDialog from '../dialogs/ConfirmRedactDialog';
|
||||
import ErrorDialog from '../dialogs/ErrorDialog';
|
||||
import ShareDialog from '../dialogs/ShareDialog';
|
||||
import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks";
|
||||
|
||||
export function canCancel(eventStatus) {
|
||||
export function canCancel(eventStatus: EventStatus): boolean {
|
||||
return eventStatus === EventStatus.QUEUED || eventStatus === EventStatus.NOT_SENT;
|
||||
}
|
||||
|
||||
interface IEventTileOps {
|
||||
isWidgetHidden(): boolean;
|
||||
unhideWidget(): void;
|
||||
}
|
||||
|
||||
interface IProps {
|
||||
/* the MatrixEvent associated with the context menu */
|
||||
mxEvent: MatrixEvent;
|
||||
/* an optional EventTileOps implementation that can be used to unhide preview widgets */
|
||||
eventTileOps?: IEventTileOps;
|
||||
permalinkCreator?: RoomPermalinkCreator;
|
||||
/* an optional function to be called when the user clicks collapse thread, if not provided hide button */
|
||||
collapseReplyThread?(): void;
|
||||
/* callback called when the menu is dismissed */
|
||||
onFinished(): void;
|
||||
/* if the menu is inside a dialog, we sometimes need to close that dialog after click (forwarding) */
|
||||
onCloseDialog?(): void;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
canRedact: boolean;
|
||||
canPin: boolean;
|
||||
}
|
||||
|
||||
@replaceableComponent("views.context_menus.MessageContextMenu")
|
||||
export default class MessageContextMenu extends React.Component {
|
||||
static propTypes = {
|
||||
/* the MatrixEvent associated with the context menu */
|
||||
mxEvent: PropTypes.object.isRequired,
|
||||
|
||||
/* an optional EventTileOps implementation that can be used to unhide preview widgets */
|
||||
eventTileOps: PropTypes.object,
|
||||
|
||||
/* an optional function to be called when the user clicks collapse thread, if not provided hide button */
|
||||
collapseReplyThread: PropTypes.func,
|
||||
|
||||
/* callback called when the menu is dismissed */
|
||||
onFinished: PropTypes.func,
|
||||
|
||||
/* if the menu is inside a dialog, we sometimes need to close that dialog after click (forwarding) */
|
||||
onCloseDialog: PropTypes.func,
|
||||
};
|
||||
|
||||
export default class MessageContextMenu extends React.Component<IProps, IState> {
|
||||
state = {
|
||||
canRedact: false,
|
||||
canPin: false,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
MatrixClientPeg.get().on('RoomMember.powerLevel', this._checkPermissions);
|
||||
this._checkPermissions();
|
||||
MatrixClientPeg.get().on('RoomMember.powerLevel', this.checkPermissions);
|
||||
this.checkPermissions();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const cli = MatrixClientPeg.get();
|
||||
if (cli) {
|
||||
cli.removeListener('RoomMember.powerLevel', this._checkPermissions);
|
||||
cli.removeListener('RoomMember.powerLevel', this.checkPermissions);
|
||||
}
|
||||
}
|
||||
|
||||
_checkPermissions = () => {
|
||||
private checkPermissions = (): void => {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const room = cli.getRoom(this.props.mxEvent.getRoomId());
|
||||
|
||||
|
@ -93,7 +104,7 @@ export default class MessageContextMenu extends React.Component {
|
|||
this.setState({ canRedact, canPin });
|
||||
};
|
||||
|
||||
_isPinned() {
|
||||
private isPinned(): boolean {
|
||||
const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId());
|
||||
const pinnedEvent = room.currentState.getStateEvents(EventType.RoomPinnedEvents, '');
|
||||
if (!pinnedEvent) return false;
|
||||
|
@ -101,38 +112,35 @@ export default class MessageContextMenu extends React.Component {
|
|||
return content.pinned && Array.isArray(content.pinned) && content.pinned.includes(this.props.mxEvent.getId());
|
||||
}
|
||||
|
||||
onResendReactionsClick = () => {
|
||||
for (const reaction of this._getUnsentReactions()) {
|
||||
private onResendReactionsClick = (): void => {
|
||||
for (const reaction of this.getUnsentReactions()) {
|
||||
Resend.resend(reaction);
|
||||
}
|
||||
this.closeMenu();
|
||||
};
|
||||
|
||||
onReportEventClick = () => {
|
||||
const ReportEventDialog = sdk.getComponent("dialogs.ReportEventDialog");
|
||||
private onReportEventClick = (): void => {
|
||||
Modal.createTrackedDialog('Report Event', '', ReportEventDialog, {
|
||||
mxEvent: this.props.mxEvent,
|
||||
}, 'mx_Dialog_reportEvent');
|
||||
this.closeMenu();
|
||||
};
|
||||
|
||||
onViewSourceClick = () => {
|
||||
const ViewSource = sdk.getComponent('structures.ViewSource');
|
||||
private onViewSourceClick = (): void => {
|
||||
Modal.createTrackedDialog('View Event Source', '', ViewSource, {
|
||||
mxEvent: this.props.mxEvent,
|
||||
}, 'mx_Dialog_viewsource');
|
||||
this.closeMenu();
|
||||
};
|
||||
|
||||
onRedactClick = () => {
|
||||
const ConfirmRedactDialog = sdk.getComponent("dialogs.ConfirmRedactDialog");
|
||||
private onRedactClick = (): void => {
|
||||
Modal.createTrackedDialog('Confirm Redact Dialog', '', ConfirmRedactDialog, {
|
||||
onFinished: async (proceed, reason) => {
|
||||
onFinished: async (proceed: boolean, reason?: string) => {
|
||||
if (!proceed) return;
|
||||
|
||||
const cli = MatrixClientPeg.get();
|
||||
try {
|
||||
if (this.props.onCloseDialog) this.props.onCloseDialog();
|
||||
this.props.onCloseDialog?.();
|
||||
await cli.redactEvent(
|
||||
this.props.mxEvent.getRoomId(),
|
||||
this.props.mxEvent.getId(),
|
||||
|
@ -145,7 +153,6 @@ export default class MessageContextMenu extends React.Component {
|
|||
// (e.g. no errcode or statusCode) as in that case the redactions end up in the
|
||||
// detached queue and we show the room status bar to allow retry
|
||||
if (typeof code !== "undefined") {
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
// display error message stating you couldn't delete this.
|
||||
Modal.createTrackedDialog('You cannot delete this message', '', ErrorDialog, {
|
||||
title: _t('Error'),
|
||||
|
@ -158,7 +165,7 @@ export default class MessageContextMenu extends React.Component {
|
|||
this.closeMenu();
|
||||
};
|
||||
|
||||
onForwardClick = () => {
|
||||
private onForwardClick = (): void => {
|
||||
Modal.createTrackedDialog('Forward Message', '', ForwardDialog, {
|
||||
matrixClient: MatrixClientPeg.get(),
|
||||
event: this.props.mxEvent,
|
||||
|
@ -167,12 +174,12 @@ export default class MessageContextMenu extends React.Component {
|
|||
this.closeMenu();
|
||||
};
|
||||
|
||||
onPinClick = () => {
|
||||
private onPinClick = (): void => {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const room = cli.getRoom(this.props.mxEvent.getRoomId());
|
||||
const eventId = this.props.mxEvent.getId();
|
||||
|
||||
const pinnedIds = room?.currentState?.getStateEvents(EventType.RoomPinnedEvents, "")?.pinned || [];
|
||||
const pinnedIds = room?.currentState?.getStateEvents(EventType.RoomPinnedEvents, "")?.getContent().pinned || [];
|
||||
if (pinnedIds.includes(eventId)) {
|
||||
pinnedIds.splice(pinnedIds.indexOf(eventId), 1);
|
||||
} else {
|
||||
|
@ -188,18 +195,16 @@ export default class MessageContextMenu extends React.Component {
|
|||
this.closeMenu();
|
||||
};
|
||||
|
||||
closeMenu = () => {
|
||||
if (this.props.onFinished) this.props.onFinished();
|
||||
private closeMenu = (): void => {
|
||||
this.props.onFinished();
|
||||
};
|
||||
|
||||
onUnhidePreviewClick = () => {
|
||||
if (this.props.eventTileOps) {
|
||||
this.props.eventTileOps.unhideWidget();
|
||||
}
|
||||
private onUnhidePreviewClick = (): void => {
|
||||
this.props.eventTileOps?.unhideWidget();
|
||||
this.closeMenu();
|
||||
};
|
||||
|
||||
onQuoteClick = () => {
|
||||
private onQuoteClick = (): void => {
|
||||
dis.dispatch({
|
||||
action: Action.ComposerInsert,
|
||||
event: this.props.mxEvent,
|
||||
|
@ -207,9 +212,8 @@ export default class MessageContextMenu extends React.Component {
|
|||
this.closeMenu();
|
||||
};
|
||||
|
||||
onPermalinkClick = (e) => {
|
||||
private onPermalinkClick = (e: React.MouseEvent): void => {
|
||||
e.preventDefault();
|
||||
const ShareDialog = sdk.getComponent("dialogs.ShareDialog");
|
||||
Modal.createTrackedDialog('share room message dialog', '', ShareDialog, {
|
||||
target: this.props.mxEvent,
|
||||
permalinkCreator: this.props.permalinkCreator,
|
||||
|
@ -217,30 +221,27 @@ export default class MessageContextMenu extends React.Component {
|
|||
this.closeMenu();
|
||||
};
|
||||
|
||||
onCollapseReplyThreadClick = () => {
|
||||
private onCollapseReplyThreadClick = (): void => {
|
||||
this.props.collapseReplyThread();
|
||||
this.closeMenu();
|
||||
};
|
||||
|
||||
_getReactions(filter) {
|
||||
private getReactions(filter: (e: MatrixEvent) => boolean): MatrixEvent[] {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const room = cli.getRoom(this.props.mxEvent.getRoomId());
|
||||
const eventId = this.props.mxEvent.getId();
|
||||
return room.getPendingEvents().filter(e => {
|
||||
const relation = e.getRelation();
|
||||
return relation &&
|
||||
relation.rel_type === "m.annotation" &&
|
||||
relation.event_id === eventId &&
|
||||
filter(e);
|
||||
return relation?.rel_type === RelationType.Annotation && relation.event_id === eventId && filter(e);
|
||||
});
|
||||
}
|
||||
|
||||
_getPendingReactions() {
|
||||
return this._getReactions(e => canCancel(e.status));
|
||||
private getPendingReactions(): MatrixEvent[] {
|
||||
return this.getReactions(e => canCancel(e.status));
|
||||
}
|
||||
|
||||
_getUnsentReactions() {
|
||||
return this._getReactions(e => e.status === EventStatus.NOT_SENT);
|
||||
private getUnsentReactions(): MatrixEvent[] {
|
||||
return this.getReactions(e => e.status === EventStatus.NOT_SENT);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -248,16 +249,17 @@ export default class MessageContextMenu extends React.Component {
|
|||
const me = cli.getUserId();
|
||||
const mxEvent = this.props.mxEvent;
|
||||
const eventStatus = mxEvent.status;
|
||||
const unsentReactionsCount = this._getUnsentReactions().length;
|
||||
let resendReactionsButton;
|
||||
let redactButton;
|
||||
let forwardButton;
|
||||
let pinButton;
|
||||
let unhidePreviewButton;
|
||||
let externalURLButton;
|
||||
let quoteButton;
|
||||
let collapseReplyThread;
|
||||
let redactItemList;
|
||||
const unsentReactionsCount = this.getUnsentReactions().length;
|
||||
|
||||
let resendReactionsButton: JSX.Element;
|
||||
let redactButton: JSX.Element;
|
||||
let forwardButton: JSX.Element;
|
||||
let pinButton: JSX.Element;
|
||||
let unhidePreviewButton: JSX.Element;
|
||||
let externalURLButton: JSX.Element;
|
||||
let quoteButton: JSX.Element;
|
||||
let collapseReplyThread: JSX.Element;
|
||||
let redactItemList: JSX.Element;
|
||||
|
||||
// status is SENT before remote-echo, null after
|
||||
const isSent = !eventStatus || eventStatus === EventStatus.SENT;
|
||||
|
@ -296,7 +298,7 @@ export default class MessageContextMenu extends React.Component {
|
|||
pinButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconPin"
|
||||
label={ this._isPinned() ? _t('Unpin') : _t('Pin') }
|
||||
label={ this.isPinned() ? _t('Unpin') : _t('Pin') }
|
||||
onClick={this.onPinClick}
|
||||
/>
|
||||
);
|
||||
|
@ -327,16 +329,20 @@ export default class MessageContextMenu extends React.Component {
|
|||
if (this.props.permalinkCreator) {
|
||||
permalink = this.props.permalinkCreator.forEvent(this.props.mxEvent.getId());
|
||||
}
|
||||
// XXX: if we use room ID, we should also include a server where the event can be found (other than in the domain of the event ID)
|
||||
const permalinkButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconPermalink"
|
||||
onClick={this.onPermalinkClick}
|
||||
label= {_t('Share')}
|
||||
element="a"
|
||||
href={permalink}
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
{
|
||||
// XXX: Typescript signature for AccessibleButton doesn't work properly for non-inputs like `a`
|
||||
...{
|
||||
href: permalink,
|
||||
target: "_blank",
|
||||
rel: "noreferrer noopener",
|
||||
}
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -351,8 +357,8 @@ export default class MessageContextMenu extends React.Component {
|
|||
}
|
||||
|
||||
// Bridges can provide a 'external_url' to link back to the source.
|
||||
if (typeof (mxEvent.event.content.external_url) === "string" &&
|
||||
isUrlPermitted(mxEvent.event.content.external_url)
|
||||
if (typeof (mxEvent.getContent().external_url) === "string" &&
|
||||
isUrlPermitted(mxEvent.getContent().external_url)
|
||||
) {
|
||||
externalURLButton = (
|
||||
<IconizedContextMenuOption
|
||||
|
@ -360,9 +366,14 @@ export default class MessageContextMenu extends React.Component {
|
|||
onClick={this.closeMenu}
|
||||
label={ _t('Source URL') }
|
||||
element="a"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
href={mxEvent.event.content.external_url}
|
||||
{
|
||||
// XXX: Typescript signature for AccessibleButton doesn't work properly for non-inputs like `a`
|
||||
...{
|
||||
target: "_blank",
|
||||
rel: "noreferrer noopener",
|
||||
href: mxEvent.getContent().external_url,
|
||||
}
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -377,7 +388,7 @@ export default class MessageContextMenu extends React.Component {
|
|||
);
|
||||
}
|
||||
|
||||
let reportEventButton;
|
||||
let reportEventButton: JSX.Element;
|
||||
if (mxEvent.getSender() !== me) {
|
||||
reportEventButton = (
|
||||
<IconizedContextMenuOption
|
|
@ -18,6 +18,7 @@ import React, { ReactNode, useContext, useMemo, useState } from "react";
|
|||
import classNames from "classnames";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||
import { sleep } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import { _t } from '../../../languageHandler';
|
||||
import { IDialogProps } from "./IDialogProps";
|
||||
|
@ -29,7 +30,6 @@ import RoomAvatar from "../avatars/RoomAvatar";
|
|||
import { getDisplayAliasForRoom } from "../../../Rooms";
|
||||
import AccessibleButton from "../elements/AccessibleButton";
|
||||
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
|
||||
import { sleep } from "../../../utils/promise";
|
||||
import DMRoomMap from "../../../utils/DMRoomMap";
|
||||
import { calculateRoomVia } from "../../../utils/permalinks/Permalinks";
|
||||
import StyledCheckbox from "../elements/StyledCheckbox";
|
||||
|
|
|
@ -19,6 +19,7 @@ limitations under the License.
|
|||
|
||||
import React, { createRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { sleep } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import { _t, _td } from '../../../languageHandler';
|
||||
import * as sdk from '../../../index';
|
||||
|
@ -30,7 +31,6 @@ import * as Email from '../../../email';
|
|||
import IdentityAuthClient from '../../../IdentityAuthClient';
|
||||
import { getDefaultIdentityServerUrl, useDefaultIdentityServer } from '../../../utils/IdentityServerUtils';
|
||||
import { abbreviateUrl } from '../../../utils/UrlUtils';
|
||||
import { sleep } from "../../../utils/promise";
|
||||
import { Key } from "../../../Keyboard";
|
||||
import { Action } from "../../../dispatcher/actions";
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
|
|
|
@ -15,11 +15,11 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import * as sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import { SettingLevel } from "../../../settings/SettingLevel";
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import BaseDialog from "./BaseDialog";
|
||||
|
||||
interface IProps {
|
||||
unknownProfileUsers: Array<{
|
||||
|
@ -50,8 +50,6 @@ export default class AskInviteAnywayDialog extends React.Component<IProps> {
|
|||
};
|
||||
|
||||
public render() {
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
|
||||
const errorList = this.props.unknownProfileUsers
|
||||
.map(address => <li key={address.userId}>{address.userId}: {address.errorText}</li>);
|
||||
|
||||
|
|
|
@ -18,13 +18,17 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import * as sdk from '../../../index';
|
||||
import SdkConfig from '../../../SdkConfig';
|
||||
import Modal from '../../../Modal';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import sendBugReport, { downloadBugReport } from '../../../rageshake/submit-rageshake';
|
||||
import AccessibleButton from "../elements/AccessibleButton";
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import QuestionDialog from "./QuestionDialog";
|
||||
import BaseDialog from "./BaseDialog";
|
||||
import Field from '../elements/Field';
|
||||
import Spinner from "../elements/Spinner";
|
||||
import DialogButtons from "../elements/DialogButtons";
|
||||
|
||||
interface IProps {
|
||||
onFinished: (success: boolean) => void;
|
||||
|
@ -93,7 +97,6 @@ export default class BugReportDialog extends React.Component<IProps, IState> {
|
|||
}).then(() => {
|
||||
if (!this.unmounted) {
|
||||
this.props.onFinished(false);
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
// N.B. first param is passed to piwik and so doesn't want i18n
|
||||
Modal.createTrackedDialog('Bug report sent', '', QuestionDialog, {
|
||||
title: _t('Logs sent'),
|
||||
|
@ -160,11 +163,6 @@ export default class BugReportDialog extends React.Component<IProps, IState> {
|
|||
};
|
||||
|
||||
public render() {
|
||||
const Loader = sdk.getComponent("elements.Spinner");
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||
const Field = sdk.getComponent('elements.Field');
|
||||
|
||||
let error = null;
|
||||
if (this.state.err) {
|
||||
error = <div className="error">
|
||||
|
@ -176,7 +174,7 @@ export default class BugReportDialog extends React.Component<IProps, IState> {
|
|||
if (this.state.busy) {
|
||||
progress = (
|
||||
<div className="progress">
|
||||
<Loader />
|
||||
<Spinner />
|
||||
{this.state.progress} ...
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -16,9 +16,10 @@ Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import * as sdk from '../../../index';
|
||||
import request from 'browser-request';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import QuestionDialog from "./QuestionDialog";
|
||||
import Spinner from "../elements/Spinner";
|
||||
|
||||
interface IProps {
|
||||
newVersion: string;
|
||||
|
@ -65,9 +66,6 @@ export default class ChangelogDialog extends React.Component<IProps> {
|
|||
}
|
||||
|
||||
public render() {
|
||||
const Spinner = sdk.getComponent('views.elements.Spinner');
|
||||
const QuestionDialog = sdk.getComponent('dialogs.QuestionDialog');
|
||||
|
||||
const logs = REPOS.map(repo => {
|
||||
let content;
|
||||
if (this.state[repo] == null) {
|
||||
|
|
|
@ -15,9 +15,12 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import * as sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import ConfirmRedactDialog from './ConfirmRedactDialog';
|
||||
import ErrorDialog from './ErrorDialog';
|
||||
import BaseDialog from "./BaseDialog";
|
||||
import Spinner from "../elements/Spinner";
|
||||
|
||||
interface IProps {
|
||||
redact: () => Promise<void>;
|
||||
|
@ -73,7 +76,6 @@ export default class ConfirmAndWaitRedactDialog extends React.PureComponent<IPro
|
|||
public render() {
|
||||
if (this.state.isRedacting) {
|
||||
if (this.state.redactionErrorCode) {
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
const code = this.state.redactionErrorCode;
|
||||
return (
|
||||
<ErrorDialog
|
||||
|
@ -83,8 +85,6 @@ export default class ConfirmAndWaitRedactDialog extends React.PureComponent<IPro
|
|||
/>
|
||||
);
|
||||
} else {
|
||||
const BaseDialog = sdk.getComponent("dialogs.BaseDialog");
|
||||
const Spinner = sdk.getComponent('elements.Spinner');
|
||||
return (
|
||||
<BaseDialog
|
||||
onFinished={this.props.onFinished}
|
||||
|
@ -95,7 +95,6 @@ export default class ConfirmAndWaitRedactDialog extends React.PureComponent<IPro
|
|||
);
|
||||
}
|
||||
} else {
|
||||
const ConfirmRedactDialog = sdk.getComponent("dialogs.ConfirmRedactDialog");
|
||||
return <ConfirmRedactDialog onFinished={this.onParentFinished} />;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,9 +15,9 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import * as sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import TextInputDialog from "./TextInputDialog";
|
||||
|
||||
interface IProps {
|
||||
onFinished: (success: boolean) => void;
|
||||
|
@ -29,7 +29,6 @@ interface IProps {
|
|||
@replaceableComponent("views.dialogs.ConfirmRedactDialog")
|
||||
export default class ConfirmRedactDialog extends React.Component<IProps> {
|
||||
render() {
|
||||
const TextInputDialog = sdk.getComponent('views.dialogs.TextInputDialog');
|
||||
return (
|
||||
<TextInputDialog onFinished={this.props.onFinished}
|
||||
title={_t("Confirm Removal")}
|
||||
|
|
|
@ -17,11 +17,14 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
import { MatrixClient } from 'matrix-js-sdk/src/client';
|
||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||
import * as sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import { GroupMemberType } from '../../../groups';
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import { mediaFromMxc } from "../../../customisations/Media";
|
||||
import MemberAvatar from '../avatars/MemberAvatar';
|
||||
import BaseAvatar from '../avatars/BaseAvatar';
|
||||
import BaseDialog from "./BaseDialog";
|
||||
import DialogButtons from "../elements/DialogButtons";
|
||||
|
||||
interface IProps {
|
||||
// matrix-js-sdk (room) member object. Supply either this or 'groupMember'
|
||||
|
@ -67,11 +70,6 @@ export default class ConfirmUserActionDialog extends React.Component<IProps> {
|
|||
};
|
||||
|
||||
public render() {
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||
const MemberAvatar = sdk.getComponent("views.avatars.MemberAvatar");
|
||||
const BaseAvatar = sdk.getComponent("views.avatars.BaseAvatar");
|
||||
|
||||
const confirmButtonClass = this.props.danger ? 'danger' : '';
|
||||
|
||||
let reasonBox;
|
||||
|
|
|
@ -16,8 +16,9 @@ limitations under the License.
|
|||
|
||||
import React from 'react';
|
||||
import { _t } from "../../../languageHandler";
|
||||
import * as sdk from "../../../index";
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import BaseDialog from "./BaseDialog";
|
||||
import DialogButtons from "../elements/DialogButtons";
|
||||
|
||||
interface IProps {
|
||||
onFinished: (success: boolean) => void;
|
||||
|
@ -34,9 +35,6 @@ export default class ConfirmWipeDeviceDialog extends React.Component<IProps> {
|
|||
};
|
||||
|
||||
render() {
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||
|
||||
return (
|
||||
<BaseDialog
|
||||
className='mx_ConfirmWipeDeviceDialog'
|
||||
|
|
|
@ -15,11 +15,12 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import * as sdk from '../../../index';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import { MatrixClientPeg } from '../../../MatrixClientPeg';
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import BaseDialog from "./BaseDialog";
|
||||
import Spinner from "../elements/Spinner";
|
||||
|
||||
interface IProps {
|
||||
onFinished: (success: boolean) => void;
|
||||
|
@ -106,9 +107,6 @@ export default class CreateGroupDialog extends React.Component<IProps, IState> {
|
|||
};
|
||||
|
||||
render() {
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
const Spinner = sdk.getComponent('elements.Spinner');
|
||||
|
||||
if (this.state.creating) {
|
||||
return <Spinner />;
|
||||
}
|
||||
|
|
|
@ -16,21 +16,22 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import * as sdk from '../../../index';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import SdkConfig from '../../../SdkConfig';
|
||||
import Modal from '../../../Modal';
|
||||
import BaseDialog from "./BaseDialog";
|
||||
import DialogButtons from "../elements/DialogButtons";
|
||||
import QuestionDialog from "./QuestionDialog";
|
||||
|
||||
interface IProps {
|
||||
onFinished: (success: boolean) => void;
|
||||
}
|
||||
|
||||
export default (props: IProps) => {
|
||||
const CryptoStoreTooNewDialog: React.FC<IProps> = (props: IProps) => {
|
||||
const brand = SdkConfig.get().brand;
|
||||
|
||||
const _onLogoutClicked = () => {
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
Modal.createTrackedDialog('Logout e2e db too new', '', QuestionDialog, {
|
||||
title: _t("Sign out"),
|
||||
description: _t(
|
||||
|
@ -58,8 +59,6 @@ export default (props: IProps) => {
|
|||
{ brand },
|
||||
);
|
||||
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||
return (<BaseDialog className="mx_CryptoStoreTooNewDialog"
|
||||
contentId='mx_Dialog_content'
|
||||
title={_t("Incompatible Database")}
|
||||
|
@ -79,3 +78,5 @@ export default (props: IProps) => {
|
|||
</DialogButtons>
|
||||
</BaseDialog>);
|
||||
};
|
||||
|
||||
export default CryptoStoreTooNewDialog;
|
||||
|
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||
|
||||
import React from 'react';
|
||||
|
||||
import * as sdk from '../../../index';
|
||||
import Analytics from '../../../Analytics';
|
||||
import { MatrixClientPeg } from '../../../MatrixClientPeg';
|
||||
import * as Lifecycle from '../../../Lifecycle';
|
||||
|
@ -26,6 +25,7 @@ import InteractiveAuth, { ERROR_USER_CANCELLED } from "../../structures/Interact
|
|||
import { DEFAULT_PHASE, PasswordAuthEntry, SSOAuthEntry } from "../auth/InteractiveAuthEntryComponents";
|
||||
import StyledCheckbox from "../elements/StyledCheckbox";
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import BaseDialog from "./BaseDialog";
|
||||
|
||||
interface IProps {
|
||||
onFinished: (success: boolean) => void;
|
||||
|
@ -165,8 +165,6 @@ export default class DeactivateAccountDialog extends React.Component<IProps, ISt
|
|||
}
|
||||
|
||||
public render() {
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
|
||||
let error = null;
|
||||
if (this.state.errStr) {
|
||||
error = <div className="error">
|
||||
|
|
|
@ -16,7 +16,6 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React, { useState, useEffect, ChangeEvent, MouseEvent } from 'react';
|
||||
import * as sdk from '../../../index';
|
||||
import SyntaxHighlight from '../elements/SyntaxHighlight';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import Field from "../elements/Field";
|
||||
|
@ -42,6 +41,8 @@ import { replaceableComponent } from "../../../utils/replaceableComponent";
|
|||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { SettingLevel } from '../../../settings/SettingLevel';
|
||||
import BaseDialog from "./BaseDialog";
|
||||
import TruncatedList from "../elements/TruncatedList";
|
||||
|
||||
interface IGenericEditorProps {
|
||||
onBack: () => void;
|
||||
|
@ -369,7 +370,6 @@ class FilteredList extends React.PureComponent<IFilteredListProps, IFilteredList
|
|||
};
|
||||
|
||||
render() {
|
||||
const TruncatedList = sdk.getComponent("elements.TruncatedList");
|
||||
return <div>
|
||||
<Field label={_t('Filter results')} autoFocus={true} size={64}
|
||||
type="text" autoComplete="off" value={this.props.query} onChange={this.onQuery}
|
||||
|
@ -1261,7 +1261,6 @@ export default class DevtoolsDialog extends React.PureComponent<IProps, IState>
|
|||
</React.Fragment>;
|
||||
}
|
||||
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
return (
|
||||
<BaseDialog className="mx_QuestionDialog" onFinished={this.props.onFinished} title={_t('Developer Tools')}>
|
||||
{ body }
|
||||
|
|
|
@ -26,9 +26,9 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import * as sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import BaseDialog from "./BaseDialog";
|
||||
|
||||
interface IProps {
|
||||
onFinished: (success: boolean) => void;
|
||||
|
@ -57,7 +57,6 @@ export default class ErrorDialog extends React.Component<IProps, IState> {
|
|||
};
|
||||
|
||||
public render() {
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
return (
|
||||
<BaseDialog
|
||||
className="mx_ErrorDialog"
|
||||
|
|
|
@ -18,7 +18,6 @@ import React, { createRef } from 'react';
|
|||
import classNames from 'classnames';
|
||||
|
||||
import { _t, _td } from "../../../languageHandler";
|
||||
import * as sdk from "../../../index";
|
||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||
import { makeRoomPermalink, makeUserPermalink } from "../../../utils/permalinks/Permalinks";
|
||||
import DMRoomMap from "../../../utils/DMRoomMap";
|
||||
|
@ -65,6 +64,9 @@ import { copyPlaintext, selectText } from "../../../utils/strings";
|
|||
import * as ContextMenu from "../../structures/ContextMenu";
|
||||
import { toRightOf } from "../../structures/ContextMenu";
|
||||
import GenericTextContextMenu from "../context_menus/GenericTextContextMenu";
|
||||
import QuestionDialog from "./QuestionDialog";
|
||||
import Spinner from "../elements/Spinner";
|
||||
import BaseDialog from "./BaseDialog";
|
||||
|
||||
// we have a number of types defined from the Matrix spec which can't reasonably be altered here.
|
||||
/* eslint-disable camelcase */
|
||||
|
@ -1046,7 +1048,6 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
|
|||
if (this.unmounted) return;
|
||||
|
||||
if (failed.length > 0) {
|
||||
const QuestionDialog = sdk.getComponent('dialogs.QuestionDialog');
|
||||
Modal.createTrackedDialog('Invite Paste Fail', '', QuestionDialog, {
|
||||
title: _t('Failed to find the following users'),
|
||||
description: _t(
|
||||
|
@ -1158,7 +1159,6 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
|
|||
const toRender = sourceMembers.slice(0, showNum);
|
||||
const hasMore = toRender.length < sourceMembers.length;
|
||||
|
||||
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
|
||||
let showMore = null;
|
||||
if (hasMore) {
|
||||
showMore = (
|
||||
|
@ -1269,10 +1269,6 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
|
|||
};
|
||||
|
||||
render() {
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
|
||||
const Spinner = sdk.getComponent("elements.Spinner");
|
||||
|
||||
let spinner = null;
|
||||
if (this.state.busy) {
|
||||
spinner = <Spinner w={20} h={20} />;
|
||||
|
|
|
@ -15,7 +15,6 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import * as sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import { ensureDMExists } from "../../../createRoom";
|
||||
import { IDialogProps } from "./IDialogProps";
|
||||
|
@ -26,6 +25,10 @@ import Markdown from '../../../Markdown';
|
|||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import StyledRadioButton from "../elements/StyledRadioButton";
|
||||
import BaseDialog from "./BaseDialog";
|
||||
import DialogButtons from "../elements/DialogButtons";
|
||||
import Field from "../elements/Field";
|
||||
import Spinner from "../elements/Spinner";
|
||||
|
||||
interface IProps extends IDialogProps {
|
||||
mxEvent: MatrixEvent;
|
||||
|
@ -239,11 +242,6 @@ export default class ReportEventDialog extends React.Component<IProps, IState> {
|
|||
};
|
||||
|
||||
render() {
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||
const Loader = sdk.getComponent('elements.Spinner');
|
||||
const Field = sdk.getComponent('elements.Field');
|
||||
|
||||
let error = null;
|
||||
if (this.state.err) {
|
||||
error = <div className="error">
|
||||
|
@ -255,7 +253,7 @@ export default class ReportEventDialog extends React.Component<IProps, IState> {
|
|||
if (this.state.busy) {
|
||||
progress = (
|
||||
<div className="progress">
|
||||
<Loader />
|
||||
<Spinner />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -24,12 +24,12 @@ import GeneralRoomSettingsTab from "../settings/tabs/room/GeneralRoomSettingsTab
|
|||
import SecurityRoomSettingsTab from "../settings/tabs/room/SecurityRoomSettingsTab";
|
||||
import NotificationSettingsTab from "../settings/tabs/room/NotificationSettingsTab";
|
||||
import BridgeSettingsTab from "../settings/tabs/room/BridgeSettingsTab";
|
||||
import * as sdk from "../../../index";
|
||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import { UIFeature } from "../../../settings/UIFeature";
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import BaseDialog from "./BaseDialog";
|
||||
|
||||
export const ROOM_GENERAL_TAB = "ROOM_GENERAL_TAB";
|
||||
export const ROOM_SECURITY_TAB = "ROOM_SECURITY_TAB";
|
||||
|
@ -119,8 +119,6 @@ export default class RoomSettingsDialog extends React.Component<IProps> {
|
|||
}
|
||||
|
||||
render() {
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
|
||||
const roomName = MatrixClientPeg.get().getRoom(this.props.roomId).name;
|
||||
return (
|
||||
<BaseDialog
|
||||
|
|
|
@ -22,7 +22,6 @@ import { User } from "matrix-js-sdk/src/models/user";
|
|||
import { Group } from "matrix-js-sdk/src/models/group";
|
||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import * as sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import QRCode from "../elements/QRCode";
|
||||
import { RoomPermalinkCreator, makeGroupPermalink, makeUserPermalink } from "../../../utils/permalinks/Permalinks";
|
||||
|
@ -35,6 +34,8 @@ import { IDialogProps } from "./IDialogProps";
|
|||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import { UIFeature } from "../../../settings/UIFeature";
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import BaseDialog from "./BaseDialog";
|
||||
import GenericTextContextMenu from "../context_menus/GenericTextContextMenu.js";
|
||||
|
||||
const socials = [
|
||||
{
|
||||
|
@ -119,7 +120,6 @@ export default class ShareDialog extends React.PureComponent<IProps, IState> {
|
|||
|
||||
const successful = await copyPlaintext(this.getUrl());
|
||||
const buttonRect = target.getBoundingClientRect();
|
||||
const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu');
|
||||
const { close } = ContextMenu.createMenu(GenericTextContextMenu, {
|
||||
...toRightOf(buttonRect, 2),
|
||||
message: successful ? _t('Copied!') : _t('Failed to copy'),
|
||||
|
@ -230,7 +230,6 @@ export default class ShareDialog extends React.PureComponent<IProps, IState> {
|
|||
</>;
|
||||
}
|
||||
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
return <BaseDialog
|
||||
title={title}
|
||||
className='mx_ShareDialog'
|
||||
|
|
|
@ -16,11 +16,12 @@ limitations under the License.
|
|||
|
||||
import url from 'url';
|
||||
import React from 'react';
|
||||
import * as sdk from '../../../index';
|
||||
import { _t, pickBestLanguage } from '../../../languageHandler';
|
||||
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import { SERVICE_TYPES } from "matrix-js-sdk/src/service-types";
|
||||
import DialogButtons from "../elements/DialogButtons";
|
||||
import BaseDialog from "./BaseDialog";
|
||||
|
||||
interface ITermsCheckboxProps {
|
||||
onChange: (url: string, checked: boolean) => void;
|
||||
|
@ -117,9 +118,6 @@ export default class TermsDialog extends React.PureComponent<ITermsDialogProps,
|
|||
};
|
||||
|
||||
public render() {
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||
|
||||
const rows = [];
|
||||
for (const policiesAndService of this.props.policiesAndServicePairs) {
|
||||
const parsedBaseUrl = url.parse(policiesAndService.service.baseUrl);
|
||||
|
|
|
@ -16,11 +16,12 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import * as sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import filesize from "filesize";
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import { getBlobSafeMimeType } from '../../../utils/blobs';
|
||||
import BaseDialog from "./BaseDialog";
|
||||
import DialogButtons from "../elements/DialogButtons";
|
||||
|
||||
interface IProps {
|
||||
file: File;
|
||||
|
@ -67,9 +68,6 @@ export default class UploadConfirmDialog extends React.Component<IProps> {
|
|||
};
|
||||
|
||||
render() {
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||
|
||||
let title;
|
||||
if (this.props.totalFiles > 1 && this.props.currentIndex !== undefined) {
|
||||
title = _t(
|
||||
|
|
|
@ -28,11 +28,11 @@ import PreferencesUserSettingsTab from "../settings/tabs/user/PreferencesUserSet
|
|||
import VoiceUserSettingsTab from "../settings/tabs/user/VoiceUserSettingsTab";
|
||||
import HelpUserSettingsTab from "../settings/tabs/user/HelpUserSettingsTab";
|
||||
import FlairUserSettingsTab from "../settings/tabs/user/FlairUserSettingsTab";
|
||||
import * as sdk from "../../../index";
|
||||
import SdkConfig from "../../../SdkConfig";
|
||||
import MjolnirUserSettingsTab from "../settings/tabs/user/MjolnirUserSettingsTab";
|
||||
import { UIFeature } from "../../../settings/UIFeature";
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import BaseDialog from "./BaseDialog";
|
||||
|
||||
export enum UserTab {
|
||||
General = "USER_GENERAL_TAB",
|
||||
|
@ -162,8 +162,6 @@ export default class UserSettingsDialog extends React.Component<IProps, IState>
|
|||
}
|
||||
|
||||
render() {
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
|
||||
return (
|
||||
<BaseDialog
|
||||
className='mx_UserSettingsDialog'
|
||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||
import { debounce } from "lodash";
|
||||
import classNames from 'classnames';
|
||||
import React, { ChangeEvent, FormEvent } from 'react';
|
||||
import { ISecretStorageKeyInfo } from "matrix-js-sdk/src";
|
||||
import { ISecretStorageKeyInfo } from "matrix-js-sdk/src/crypto/api";
|
||||
|
||||
import * as sdk from '../../../../index';
|
||||
import { MatrixClientPeg } from '../../../../MatrixClientPeg';
|
||||
|
|
|
@ -16,8 +16,9 @@ limitations under the License.
|
|||
|
||||
import React from 'react';
|
||||
import { _t } from "../../../../languageHandler";
|
||||
import * as sdk from "../../../../index";
|
||||
import { replaceableComponent } from "../../../../utils/replaceableComponent";
|
||||
import BaseDialog from "../BaseDialog";
|
||||
import DialogButtons from "../../elements/DialogButtons";
|
||||
|
||||
interface IProps {
|
||||
onFinished: (success: boolean) => void;
|
||||
|
@ -34,9 +35,6 @@ export default class ConfirmDestroyCrossSigningDialog extends React.Component<IP
|
|||
};
|
||||
|
||||
render() {
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||
|
||||
return (
|
||||
<BaseDialog
|
||||
className='mx_ConfirmDestroyCrossSigningDialog'
|
||||
|
|
|
@ -41,7 +41,8 @@ import QuestionDialog from "../dialogs/QuestionDialog";
|
|||
import UIStore from "../../../stores/UIStore";
|
||||
import { compare } from "../../../utils/strings";
|
||||
|
||||
export const ALL_ROOMS = Symbol("ALL_ROOMS");
|
||||
// XXX: We would ideally use a symbol here but we can't since we save this value to localStorage
|
||||
export const ALL_ROOMS = "ALL_ROOMS";
|
||||
|
||||
const SETTING_NAME = "room_directory_servers";
|
||||
|
||||
|
@ -94,8 +95,7 @@ export interface IInstance {
|
|||
fields: object;
|
||||
network_id: string;
|
||||
// XXX: this is undocumented but we rely on it.
|
||||
// we inject a fake entry with a symbolic instance_id.
|
||||
instance_id: string | symbol;
|
||||
instance_id: string;
|
||||
}
|
||||
|
||||
export interface IProtocol {
|
||||
|
@ -112,8 +112,8 @@ export type Protocols = Record<string, IProtocol>;
|
|||
interface IProps {
|
||||
protocols: Protocols;
|
||||
selectedServerName: string;
|
||||
selectedInstanceId: string | symbol;
|
||||
onOptionChange(server: string, instanceId?: string | symbol): void;
|
||||
selectedInstanceId: string;
|
||||
onOptionChange(server: string, instanceId?: string): void;
|
||||
}
|
||||
|
||||
// This dropdown sources homeservers from three places:
|
||||
|
@ -171,7 +171,7 @@ const NetworkDropdown = ({ onOptionChange, protocols = {}, selectedServerName, s
|
|||
|
||||
const protocolsList = server === hsName ? Object.values(protocols) : [];
|
||||
if (protocolsList.length > 0) {
|
||||
// add a fake protocol with the ALL_ROOMS symbol
|
||||
// add a fake protocol with ALL_ROOMS
|
||||
protocolsList.push({
|
||||
instances: [{
|
||||
fields: [],
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { ReactHTML } from 'react';
|
||||
|
||||
import { Key } from '../../../Keyboard';
|
||||
import classnames from 'classnames';
|
||||
|
@ -29,7 +29,7 @@ export type ButtonEvent = React.MouseEvent<Element> | React.KeyboardEvent<Elemen
|
|||
*/
|
||||
interface IProps extends React.InputHTMLAttributes<Element> {
|
||||
inputRef?: React.Ref<Element>;
|
||||
element?: string;
|
||||
element?: keyof ReactHTML;
|
||||
// The kind of button, similar to how Bootstrap works.
|
||||
// See available classes for AccessibleButton for options.
|
||||
kind?: string;
|
||||
|
@ -122,7 +122,7 @@ export default function AccessibleButton({
|
|||
}
|
||||
|
||||
AccessibleButton.defaultProps = {
|
||||
element: 'div',
|
||||
element: 'div' as keyof ReactHTML,
|
||||
role: 'button',
|
||||
tabIndex: 0,
|
||||
};
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
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 React from 'react';
|
||||
import { decode } from "blurhash";
|
||||
|
||||
interface IProps {
|
||||
blurhash: string;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export default class BlurhashPlaceholder extends React.PureComponent<IProps> {
|
||||
private canvas: React.RefObject<HTMLCanvasElement> = React.createRef();
|
||||
|
||||
public componentDidMount() {
|
||||
this.draw();
|
||||
}
|
||||
|
||||
public componentDidUpdate() {
|
||||
this.draw();
|
||||
}
|
||||
|
||||
private draw() {
|
||||
if (!this.canvas.current) return;
|
||||
|
||||
try {
|
||||
const { width, height } = this.props;
|
||||
|
||||
const pixels = decode(this.props.blurhash, Math.ceil(width), Math.ceil(height));
|
||||
const ctx = this.canvas.current.getContext("2d");
|
||||
const imgData = ctx.createImageData(width, height);
|
||||
imgData.data.set(pixels);
|
||||
ctx.putImageData(imgData, 0, 0);
|
||||
} catch (e) {
|
||||
console.error("Error rendering blurhash: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
return <canvas height={this.props.height} width={this.props.width} ref={this.canvas} />;
|
||||
}
|
||||
}
|
|
@ -260,6 +260,7 @@ export default class Field extends React.PureComponent<PropShapes, IState> {
|
|||
});
|
||||
|
||||
// Handle displaying feedback on validity
|
||||
// FIXME: Using an import will result in test failures
|
||||
const Tooltip = sdk.getComponent("elements.Tooltip");
|
||||
let fieldTooltip;
|
||||
if (tooltipContent || this.state.feedback) {
|
||||
|
|
|
@ -24,7 +24,7 @@ import FocusLock from "react-focus-lock";
|
|||
import MemberAvatar from "../avatars/MemberAvatar";
|
||||
import { ContextMenuTooltipButton } from "../../../accessibility/context_menu/ContextMenuTooltipButton";
|
||||
import MessageContextMenu from "../context_menus/MessageContextMenu";
|
||||
import { aboveLeftOf, ContextMenu } from '../../structures/ContextMenu';
|
||||
import { aboveLeftOf } from '../../structures/ContextMenu';
|
||||
import MessageTimestamp from "../messages/MessageTimestamp";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import { formatFullDate } from "../../../DateUtils";
|
||||
|
@ -122,7 +122,7 @@ export default class ImageView extends React.Component<IProps, IState> {
|
|||
const image = this.image.current;
|
||||
const imageWrapper = this.imageWrapper.current;
|
||||
|
||||
const rotation = inputRotation || this.state.rotation;
|
||||
const rotation = inputRotation ?? this.state.rotation;
|
||||
|
||||
const imageIsNotFlipped = rotation % 180 === 0;
|
||||
|
||||
|
@ -304,17 +304,13 @@ export default class ImageView extends React.Component<IProps, IState> {
|
|||
let contextMenu = null;
|
||||
if (this.state.contextMenuDisplayed) {
|
||||
contextMenu = (
|
||||
<ContextMenu
|
||||
<MessageContextMenu
|
||||
{...aboveLeftOf(this.contextMenuButton.current.getBoundingClientRect())}
|
||||
mxEvent={this.props.mxEvent}
|
||||
permalinkCreator={this.props.permalinkCreator}
|
||||
onFinished={this.onCloseContextMenu}
|
||||
>
|
||||
<MessageContextMenu
|
||||
mxEvent={this.props.mxEvent}
|
||||
permalinkCreator={this.props.permalinkCreator}
|
||||
onFinished={this.onCloseContextMenu}
|
||||
onCloseDialog={this.props.onFinished}
|
||||
/>
|
||||
</ContextMenu>
|
||||
onCloseDialog={this.props.onFinished}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -341,7 +341,7 @@ export default class ReplyThread extends React.Component {
|
|||
events,
|
||||
});
|
||||
|
||||
dis.fire(Action.FocusComposer);
|
||||
dis.fire(Action.FocusSendMessageComposer);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
|
@ -27,6 +27,7 @@ interface IProps {
|
|||
value: string;
|
||||
label?: string;
|
||||
placeholder?: string;
|
||||
disabled?: boolean;
|
||||
onChange?(value: string): void;
|
||||
}
|
||||
|
||||
|
@ -68,6 +69,7 @@ export default class RoomAliasField extends React.PureComponent<IProps, IState>
|
|||
onChange={this.onChange}
|
||||
value={this.props.value.substring(1, this.props.value.length - this.props.domain.length - 1)}
|
||||
maxLength={maxlength}
|
||||
disabled={this.props.disabled}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -17,11 +17,11 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
|
||||
import Dropdown from "../../views/elements/Dropdown";
|
||||
import * as sdk from '../../../index';
|
||||
import PlatformPeg from "../../../PlatformPeg";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import { _t } from "../../../languageHandler";
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import Spinner from "./Spinner";
|
||||
|
||||
function languageMatchesSearchQuery(query, language) {
|
||||
if (language.label.toUpperCase().includes(query.toUpperCase())) return true;
|
||||
|
@ -84,7 +84,6 @@ export default class SpellCheckLanguagesDropdown extends React.Component<SpellCh
|
|||
|
||||
render() {
|
||||
if (this.state.languages === null) {
|
||||
const Spinner = sdk.getComponent('elements.Spinner');
|
||||
return <Spinner />;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||
|
||||
import React from "react";
|
||||
import classNames from "classnames";
|
||||
import * as sdk from "../../../index";
|
||||
import AccessibleButton from "./AccessibleButton";
|
||||
|
||||
interface IProps {
|
||||
// Whether or not this toggle is in the 'on' position.
|
||||
|
@ -43,7 +43,6 @@ export default ({ checked, disabled = false, onChange, ...props }: IProps) => {
|
|||
"mx_ToggleSwitch_enabled": !disabled,
|
||||
});
|
||||
|
||||
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
|
||||
return (
|
||||
<AccessibleButton {...props}
|
||||
className={classes}
|
||||
|
|
|
@ -16,11 +16,11 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import * as sdk from '../../../index';
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import Tooltip from './Tooltip';
|
||||
|
||||
interface IProps {
|
||||
helpText: string;
|
||||
helpText: React.ReactNode | string;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
|
@ -49,7 +49,6 @@ export default class TooltipButton extends React.Component<IProps, IState> {
|
|||
};
|
||||
|
||||
render() {
|
||||
const Tooltip = sdk.getComponent("elements.Tooltip");
|
||||
const tip = this.state.hover ? <Tooltip
|
||||
className="mx_TooltipButton_container"
|
||||
tooltipClassName="mx_TooltipButton_helpText"
|
||||
|
|
|
@ -33,7 +33,7 @@ export const EMOJI_HEIGHT = 37;
|
|||
export const EMOJIS_PER_ROW = 8;
|
||||
|
||||
interface IProps {
|
||||
selectedEmojis: Set<string>;
|
||||
selectedEmojis?: Set<string>;
|
||||
showQuickReactions?: boolean;
|
||||
onChoose(unicode: string): boolean;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import EmojiPicker from "./EmojiPicker";
|
|||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import { Action } from '../../../dispatcher/actions';
|
||||
|
||||
interface IProps {
|
||||
mxEvent: MatrixEvent;
|
||||
|
@ -93,6 +94,7 @@ class ReactionPicker extends React.Component<IProps, IState> {
|
|||
this.props.mxEvent.getRoomId(),
|
||||
myReactions[reaction],
|
||||
);
|
||||
dis.dispatch({ action: Action.FocusAComposer });
|
||||
// Tell the emoji picker not to bump this in the more frequently used list.
|
||||
return false;
|
||||
} else {
|
||||
|
@ -104,6 +106,7 @@ class ReactionPicker extends React.Component<IProps, IState> {
|
|||
},
|
||||
});
|
||||
dis.dispatch({ action: "message_sent" });
|
||||
dis.dispatch({ action: Action.FocusAComposer });
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -18,6 +18,7 @@ limitations under the License.
|
|||
|
||||
import React, { createRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Blurhash } from "react-blurhash";
|
||||
|
||||
import MFileBody from './MFileBody';
|
||||
import Modal from '../../../Modal';
|
||||
|
@ -29,7 +30,6 @@ import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
|||
import InlineSpinner from '../elements/InlineSpinner';
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import { mediaFromContent } from "../../../customisations/Media";
|
||||
import BlurhashPlaceholder from "../elements/BlurhashPlaceholder";
|
||||
import { BLURHASH_FIELD } from "../../../ContentMessages";
|
||||
|
||||
@replaceableComponent("views.messages.MImageBody")
|
||||
|
@ -438,7 +438,7 @@ export default class MImageBody extends React.Component {
|
|||
// Overidden by MStickerBody
|
||||
getPlaceholder(width, height) {
|
||||
const blurhash = this.props.mxEvent.getContent().info[BLURHASH_FIELD];
|
||||
if (blurhash) return <BlurhashPlaceholder blurhash={blurhash} width={width} height={height} />;
|
||||
if (blurhash) return <Blurhash hash={blurhash} width={width} height={height} />;
|
||||
return <div className="mx_MImageBody_thumbnail_spinner">
|
||||
<InlineSpinner w={32} h={32} />
|
||||
</div>;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue