mirror of
https://github.com/element-hq/element-web
synced 2024-11-25 02:35:48 +03:00
Merge branch 'develop' into uhoreg/prepare_to_encrypt
This commit is contained in:
commit
c6ff6f2a79
75 changed files with 1727 additions and 1121 deletions
17
CHANGELOG.md
17
CHANGELOG.md
|
@ -1,6 +1,19 @@
|
|||
Changes in [2.2.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.2.2) (2020-03-11)
|
||||
Changes in [2.2.3](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.2.3) (2020-03-17)
|
||||
===================================================================================================
|
||||
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.2.1...v2.2.2)
|
||||
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.2.3-rc.1...v2.2.3)
|
||||
|
||||
* Upgrade JS SDK to 5.1.1
|
||||
* Add default on config setting to control call button in composer
|
||||
[\#4228](https://github.com/matrix-org/matrix-react-sdk/pull/4228)
|
||||
* Fix: make alternative addresses UX less confusing
|
||||
[\#4226](https://github.com/matrix-org/matrix-react-sdk/pull/4226)
|
||||
* Fix: best-effort to join room without canonical alias over federation from
|
||||
room directory
|
||||
[\#4211](https://github.com/matrix-org/matrix-react-sdk/pull/4211)
|
||||
|
||||
Changes in [2.2.3-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.2.3-rc.1) (2020-03-11)
|
||||
=============================================================================================================
|
||||
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.2.1...v2.2.3-rc.1)
|
||||
|
||||
* Update from Weblate
|
||||
[\#4200](https://github.com/matrix-org/matrix-react-sdk/pull/4200)
|
||||
|
|
12
package.json
12
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "matrix-react-sdk",
|
||||
"version": "2.2.2",
|
||||
"version": "2.2.3",
|
||||
"description": "SDK for matrix.org using React",
|
||||
"author": "matrix.org",
|
||||
"repository": {
|
||||
|
@ -40,15 +40,15 @@
|
|||
"rethemendex": "res/css/rethemendex.sh",
|
||||
"clean": "rimraf lib",
|
||||
"build": "yarn clean && git rev-parse HEAD > git-revision.txt && yarn build:compile && yarn build:types",
|
||||
"build:compile": "yarn reskindex && babel -d lib --verbose --extensions \".ts,.js\" src",
|
||||
"build:types": "tsc --emitDeclarationOnly",
|
||||
"build:compile": "yarn reskindex && babel -d lib --verbose --extensions \".ts,.js,.tsx\" src",
|
||||
"build:types": "tsc --emitDeclarationOnly --jsx react",
|
||||
"start": "echo THIS IS FOR LEGACY PURPOSES ONLY. && yarn start:all",
|
||||
"start:all": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n build,reskindex \"yarn start:build\" \"yarn reskindex:watch\"",
|
||||
"start:build": "babel src -w -s -d lib --verbose --extensions \".ts,.js\"",
|
||||
"lint": "yarn lint:types && yarn lint:ts && yarn lint:js && yarn lint:style",
|
||||
"lint:js": "eslint --max-warnings 0 --ignore-path .eslintignore.errorfiles src test",
|
||||
"lint:ts": "tslint --project ./tsconfig.json -t stylish",
|
||||
"lint:types": "tsc --noEmit",
|
||||
"lint:types": "tsc --noEmit --jsx react",
|
||||
"lint:style": "stylelint 'res/css/**/*.scss'",
|
||||
"test": "jest",
|
||||
"test:e2e": "./test/end-to-end-tests/run.sh --riot-url http://localhost:8080"
|
||||
|
@ -72,7 +72,6 @@
|
|||
"flux": "2.1.1",
|
||||
"focus-visible": "^5.0.2",
|
||||
"fuse.js": "^2.2.0",
|
||||
"gemini-scrollbar": "github:matrix-org/gemini-scrollbar#91e1e566",
|
||||
"gfm.css": "^1.1.1",
|
||||
"glob-to-regexp": "^0.4.1",
|
||||
"highlight.js": "^9.15.8",
|
||||
|
@ -93,7 +92,6 @@
|
|||
"react-beautiful-dnd": "^4.0.1",
|
||||
"react-dom": "^16.9.0",
|
||||
"react-focus-lock": "^2.2.1",
|
||||
"react-gemini-scrollbar": "github:matrix-org/react-gemini-scrollbar#9cf17f63b7c0b0ec5f31df27da0f82f7238dc594",
|
||||
"resize-observer-polyfill": "^1.5.0",
|
||||
"sanitize-html": "^1.18.4",
|
||||
"text-encoding-utf-8": "^1.0.1",
|
||||
|
@ -118,6 +116,8 @@
|
|||
"@babel/preset-typescript": "^7.7.4",
|
||||
"@babel/register": "^7.7.4",
|
||||
"@peculiar/webcrypto": "^1.0.22",
|
||||
"@types/classnames": "^2.2.10",
|
||||
"@types/react": "16.9",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"babel-jest": "^24.9.0",
|
||||
"chokidar": "^3.3.1",
|
||||
|
|
|
@ -42,10 +42,15 @@ pre, code {
|
|||
font-size: 100% !important;
|
||||
}
|
||||
|
||||
.error, .warning {
|
||||
.error, .warning,
|
||||
.text-error, .text-warning {
|
||||
color: $warning-color;
|
||||
}
|
||||
|
||||
.text-success {
|
||||
color: $accent-color;
|
||||
}
|
||||
|
||||
b {
|
||||
// On Firefox, the default weight for `<b>` is `bolder` which results in no bold
|
||||
// effect since we only have specific weights of our fonts available.
|
||||
|
@ -202,37 +207,6 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus {
|
|||
transition: opacity 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
/* XXX: critical hack to GeminiScrollbar to allow them to work in FF 42 and Chrome 48.
|
||||
Stop the scrollbar view from pushing out the container's overall sizing, which causes
|
||||
flexbox to adapt to the new size and cause the view to keep growing.
|
||||
*/
|
||||
.gm-scrollbar-container .gm-scroll-view {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
/* Expand thumbs on hoverover */
|
||||
.gm-scrollbar {
|
||||
border-radius: 5px !important;
|
||||
}
|
||||
.gm-scrollbar.-vertical {
|
||||
width: 6px;
|
||||
transition: width 120ms ease-out !important;
|
||||
}
|
||||
.gm-scrollbar.-vertical:hover,
|
||||
.gm-scrollbar.-vertical:active {
|
||||
width: 8px;
|
||||
transition: width 120ms ease-out !important;
|
||||
}
|
||||
.gm-scrollbar.-horizontal {
|
||||
height: 6px;
|
||||
transition: height 120ms ease-out !important;
|
||||
}
|
||||
.gm-scrollbar.-horizontal:hover,
|
||||
.gm-scrollbar.-horizontal:active {
|
||||
height: 8px;
|
||||
transition: height 120ms ease-out !important;
|
||||
}
|
||||
|
||||
// These are magic constants which are excluded from tinting, to let themes
|
||||
// (which only have CSS, unlike skins) tell the app what their non-tinted
|
||||
// colourscheme is by inspecting the stylesheet DOM.
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
@import "./views/dialogs/_GroupAddressPicker.scss";
|
||||
@import "./views/dialogs/_IncomingSasDialog.scss";
|
||||
@import "./views/dialogs/_InviteDialog.scss";
|
||||
@import "./views/dialogs/_KeyboardShortcutsDialog.scss";
|
||||
@import "./views/dialogs/_MessageEditHistoryDialog.scss";
|
||||
@import "./views/dialogs/_NewSessionReviewDialog.scss";
|
||||
@import "./views/dialogs/_RoomSettingsDialog.scss";
|
||||
|
@ -177,7 +178,6 @@
|
|||
@import "./views/rooms/_RoomTile.scss";
|
||||
@import "./views/rooms/_RoomUpgradeWarningBar.scss";
|
||||
@import "./views/rooms/_SearchBar.scss";
|
||||
@import "./views/rooms/_SearchableEntityList.scss";
|
||||
@import "./views/rooms/_SendMessageComposer.scss";
|
||||
@import "./views/rooms/_Stickers.scss";
|
||||
@import "./views/rooms/_TopUnreadMessagesBar.scss";
|
||||
|
|
|
@ -180,10 +180,6 @@ limitations under the License.
|
|||
line-height: 2em;
|
||||
}
|
||||
|
||||
.mx_GroupView > .mx_MainSplit {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.mx_GroupView_body {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
@ -341,8 +337,8 @@ limitations under the License.
|
|||
display: none;
|
||||
}
|
||||
|
||||
.mx_GroupView_body .gm-scroll-view > * {
|
||||
margin: 11px 50px 0px 68px;
|
||||
.mx_GroupView_body .mx_AutoHideScrollbar_offset > * {
|
||||
margin: 11px 50px 50px 68px;
|
||||
}
|
||||
|
||||
.mx_GroupView_groupDesc textarea {
|
||||
|
@ -370,7 +366,7 @@ limitations under the License.
|
|||
padding: 40px 20px;
|
||||
}
|
||||
|
||||
.mx_GroupView .mx_MemberInfo .gm-scroll-view > :not(.mx_MemberInfo_avatar) {
|
||||
.mx_GroupView .mx_MemberInfo .mx_AutoHideScrollbar_offset > :not(.mx_MemberInfo_avatar) {
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ limitations under the License.
|
|||
display: flex;
|
||||
flex-direction: row;
|
||||
min-width: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
// move hit area 5px to the right so it doesn't overlap with the timeline scrollbar
|
||||
|
|
|
@ -76,13 +76,6 @@ limitations under the License.
|
|||
flex: 1 1 0;
|
||||
min-width: 0;
|
||||
|
||||
/* Experimental fix for https://github.com/vector-im/vector-web/issues/947
|
||||
and https://github.com/vector-im/vector-web/issues/946.
|
||||
Empirically this stops the MessagePanel's width exploding outwards when
|
||||
gemini is in 'prevented' mode
|
||||
*/
|
||||
overflow-x: auto;
|
||||
|
||||
/* To fix https://github.com/vector-im/riot-web/issues/3298 where Safari
|
||||
needed height 100% all the way down to the HomePage. Height does not
|
||||
have to be auto, empirically.
|
||||
|
|
|
@ -67,9 +67,6 @@ limitations under the License.
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.mx_MyGroups_headerCard_header {
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
|
@ -98,6 +95,11 @@ limitations under the License.
|
|||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.mx_MyGroups_scrollable {
|
||||
overflow-y: inherit;
|
||||
}
|
||||
|
||||
.mx_MyGroups_placeholder {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2015, 2016 OpenMarket Ltd
|
||||
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.
|
||||
|
@ -45,9 +46,8 @@ limitations under the License.
|
|||
}
|
||||
|
||||
.mx_RoomDirectory_listheader {
|
||||
display: flex;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
display: block;
|
||||
margin-top: 13px;
|
||||
}
|
||||
|
||||
.mx_RoomDirectory_searchbox {
|
||||
|
@ -64,7 +64,7 @@ limitations under the License.
|
|||
}
|
||||
|
||||
.mx_RoomDirectory_table {
|
||||
font-size: 14px;
|
||||
font-size: 12px;
|
||||
color: $primary-fg-color;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
|
@ -112,6 +112,7 @@ limitations under the License.
|
|||
|
||||
.mx_RoomDirectory_name {
|
||||
display: inline-block;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
|
@ -148,8 +149,8 @@ limitations under the License.
|
|||
padding: 0;
|
||||
}
|
||||
|
||||
.mx_RoomDirectory p {
|
||||
font-size: 14px;
|
||||
.mx_RoomDirectory > span {
|
||||
font-size: 15px;
|
||||
margin-top: 0;
|
||||
|
||||
.mx_AccessibleButton {
|
||||
|
|
|
@ -23,6 +23,7 @@ limitations under the License.
|
|||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.mx_TagPanel_items_selected {
|
||||
|
@ -57,6 +58,7 @@ limitations under the License.
|
|||
|
||||
.mx_TagPanel .mx_TagPanel_scroller {
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mx_TagPanel .mx_TagPanel_tagTileContainer {
|
||||
|
|
|
@ -37,6 +37,10 @@ limitations under the License.
|
|||
font-size: 15px;
|
||||
}
|
||||
|
||||
.mx_CompleteSecurity_waiting {
|
||||
color: $notice-secondary-color;
|
||||
}
|
||||
|
||||
.mx_CompleteSecurity_actionRow {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
|
65
res/css/views/dialogs/_KeyboardShortcutsDialog.scss
Normal file
65
res/css/views/dialogs/_KeyboardShortcutsDialog.scss
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
.mx_KeyboardShortcutsDialog {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
flex-direction: column;
|
||||
margin-bottom: -50px;
|
||||
max-height: 700px; // XXX: this may need adjusting when adding new shortcuts
|
||||
|
||||
.mx_KeyboardShortcutsDialog_category {
|
||||
width: 33.3333%; // 3 columns
|
||||
margin: 0 0 40px;
|
||||
|
||||
& > div {
|
||||
padding-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0 0 10px;
|
||||
}
|
||||
|
||||
h5 {
|
||||
margin: 15px 0 5px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
kbd {
|
||||
padding: 5px;
|
||||
border-radius: 4px;
|
||||
background-color: $reaction-row-button-bg-color;
|
||||
margin-right: 5px;
|
||||
min-width: 20px;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
border: 1px solid $kbd-border-color;
|
||||
box-shadow: 0 2px $kbd-border-color;
|
||||
margin-bottom: 4px;
|
||||
text-transform: capitalize;
|
||||
|
||||
& + kbd {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_KeyboardShortcutsDialog_inline div {
|
||||
display: inline;
|
||||
}
|
||||
}
|
|
@ -14,14 +14,6 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
// CSS voodoo to support a gemini-scrollbar for the contents of the dialog
|
||||
.mx_Dialog_unknownDevice .mx_Dialog {
|
||||
// ideally we'd shrink the height to fit when needed, but in practice this
|
||||
// is a pain in the ass. plus might as well make the dialog big given how
|
||||
// important it is.
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.mx_UnknownDeviceDialog {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
|
@ -44,6 +36,7 @@ limitations under the License.
|
|||
|
||||
.mx_UnknownDeviceDialog .mx_Dialog_content {
|
||||
margin-bottom: 24px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.mx_UnknownDeviceDialog_deviceList > li {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2015, 2016 OpenMarket Ltd
|
||||
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.
|
||||
|
@ -15,70 +15,149 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
.mx_NetworkDropdown {
|
||||
height: 32px;
|
||||
position: relative;
|
||||
}
|
||||
width: max-content;
|
||||
padding-right: 32px;
|
||||
margin-left: auto;
|
||||
margin-right: 9px;
|
||||
margin-top: 12px;
|
||||
|
||||
.mx_NetworkDropdown_input {
|
||||
position: relative;
|
||||
border-radius: 3px;
|
||||
border: 1px solid $strong-input-border-color;
|
||||
font-weight: 300;
|
||||
font-size: 13px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.mx_NetworkDropdown_arrow {
|
||||
border-color: $primary-fg-color transparent transparent;
|
||||
border-style: solid;
|
||||
border-width: 5px 5px 0;
|
||||
display: block;
|
||||
height: 0;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 16px;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.mx_NetworkDropdown_networkoption {
|
||||
height: 37px;
|
||||
line-height: 37px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.mx_NetworkDropdown_networkoption img {
|
||||
margin: 5px;
|
||||
width: 25px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
input.mx_NetworkDropdown_networkoption, input.mx_NetworkDropdown_networkoption:focus {
|
||||
border: 0;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
.mx_AccessibleButton {
|
||||
width: max-content;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_NetworkDropdown_menu {
|
||||
position: absolute;
|
||||
left: -1px;
|
||||
right: -1px;
|
||||
top: 100%;
|
||||
z-index: 2;
|
||||
min-width: 204px;
|
||||
margin: 0;
|
||||
padding: 0px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid $accent-color;
|
||||
box-sizing: border-box;
|
||||
border-radius: 4px;
|
||||
border: 1px solid $dialog-close-fg-color;
|
||||
background-color: $primary-bg-color;
|
||||
}
|
||||
|
||||
.mx_NetworkDropdown_menu .mx_NetworkDropdown_networkoption:hover {
|
||||
background-color: $focus-bg-color;
|
||||
}
|
||||
|
||||
.mx_NetworkDropdown_menu_network {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.mx_NetworkDropdown_server {
|
||||
padding: 12px 0;
|
||||
border-bottom: 1px solid $input-darker-fg-color;
|
||||
|
||||
.mx_NetworkDropdown_server_title {
|
||||
padding: 0 10px;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 20px;
|
||||
margin-bottom: 4px;
|
||||
|
||||
// remove server button
|
||||
.mx_AccessibleButton {
|
||||
position: absolute;
|
||||
display: inline;
|
||||
right: 12px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
margin-top: 4px;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
mask-repeat: no-repeat;
|
||||
mask-position: center;
|
||||
mask-size: contain;
|
||||
mask-image: url('$(res)/img/feather-customised/x.svg');
|
||||
background-color: $notice-primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mx_NetworkDropdown_server_subtitle {
|
||||
padding: 0 10px;
|
||||
font-size: 10px;
|
||||
line-height: 14px;
|
||||
margin-top: -4px;
|
||||
margin-bottom: 4px;
|
||||
color: $muted-fg-color;
|
||||
}
|
||||
|
||||
.mx_NetworkDropdown_server_network {
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
padding: 4px 10px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
&[aria-checked=true]::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
right: 10px;
|
||||
mask-repeat: no-repeat;
|
||||
mask-position: center;
|
||||
mask-size: contain;
|
||||
mask-image: url('$(res)/img/feather-customised/check.svg');
|
||||
background-color: $input-valid-border-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mx_NetworkDropdown_server_add,
|
||||
.mx_NetworkDropdown_server_network {
|
||||
&:hover {
|
||||
background-color: $header-panel-bg-color;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_NetworkDropdown_server_add {
|
||||
padding: 16px 10px 16px 32px;
|
||||
position: relative;
|
||||
border-radius: 0 0 4px 4px;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
left: 7px;
|
||||
mask-repeat: no-repeat;
|
||||
mask-position: center;
|
||||
mask-size: contain;
|
||||
mask-image: url('$(res)/img/feather-customised/plus.svg');
|
||||
background-color: $muted-fg-color;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_NetworkDropdown_handle {
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
right: -28px; // - (24 + 4)
|
||||
mask-repeat: no-repeat;
|
||||
mask-position: center;
|
||||
mask-size: contain;
|
||||
mask-image: url('$(res)/img/feather-customised/chevron-down.svg');
|
||||
background-color: $primary-fg-color;
|
||||
}
|
||||
|
||||
.mx_NetworkDropdown_handle_server {
|
||||
color: $muted-fg-color;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_NetworkDropdown_dialog .mx_Dialog {
|
||||
width: 45vw;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ limitations under the License.
|
|||
display: flex;
|
||||
padding-left: 9px;
|
||||
padding-right: 9px;
|
||||
margin: 0 5px 0 0 !important;
|
||||
}
|
||||
|
||||
.mx_DirectorySearchBox_joinButton {
|
||||
|
|
|
@ -20,14 +20,21 @@ limitations under the License.
|
|||
}
|
||||
|
||||
.mx_EditableItem {
|
||||
display: flex;
|
||||
margin-bottom: 5px;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.mx_EditableItem_delete {
|
||||
order: 3;
|
||||
margin-right: 5px;
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
mask-image: url('$(res)/img/feather-customised/cancel.svg');
|
||||
mask-repeat: no-repeat;
|
||||
background-color: $warning-color;
|
||||
mask-size: 100%;
|
||||
}
|
||||
|
||||
.mx_EditableItem_email {
|
||||
|
@ -36,12 +43,19 @@ limitations under the License.
|
|||
|
||||
.mx_EditableItem_promptText {
|
||||
margin-right: 10px;
|
||||
order: 2;
|
||||
}
|
||||
|
||||
.mx_EditableItem_confirmBtn {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.mx_EditableItem_item {
|
||||
flex: auto 1 0;
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.mx_EditableItemList_label {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,20 @@ limitations under the License.
|
|||
box-shadow: none;
|
||||
}
|
||||
|
||||
.mx_AliasSettings summary {
|
||||
cursor: pointer;
|
||||
.mx_AliasSettings {
|
||||
summary {
|
||||
cursor: pointer;
|
||||
color: $accent-color;
|
||||
font-weight: 600;
|
||||
list-style: none;
|
||||
|
||||
// list-style doesn't do it for webkit
|
||||
&::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_AliasSettings_localAliasHeader {
|
||||
margin-top: 35px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,9 @@ limitations under the License.
|
|||
h3 {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
// break-word, with fallback to break-all, which is wider supported
|
||||
word-break: break-all;
|
||||
word-break: break-word;
|
||||
|
||||
&.mx_RoomPreviewBar_spinnerTitle {
|
||||
display: flex;
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
Copyright 2016 OpenMarket Ltd
|
||||
|
||||
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_SearchableEntityList {
|
||||
display: flex;
|
||||
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.mx_SearchableEntityList_query {
|
||||
font-family: $font-family;
|
||||
border-radius: 3px;
|
||||
border: 1px solid $input-border-color;
|
||||
padding: 9px;
|
||||
color: $primary-fg-color;
|
||||
background-color: $primary-bg-color;
|
||||
margin-left: 3px;
|
||||
font-size: 15px;
|
||||
margin-bottom: 8px;
|
||||
width: 189px;
|
||||
}
|
||||
|
||||
.mx_SearchableEntityList_query::-moz-placeholder {
|
||||
color: $primary-fg-color;
|
||||
opacity: 0.5;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.mx_SearchableEntityList_query::-webkit-input-placeholder {
|
||||
color: $primary-fg-color;
|
||||
opacity: 0.5;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.mx_SearchableEntityList_listWrapper {
|
||||
flex: 1;
|
||||
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.mx_SearchableEntityList_list {
|
||||
display: table;
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mx_SearchableEntityList_list .mx_EntityTile_chevron {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mx_SearchableEntityList_hrWrapper {
|
||||
width: 100%;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.mx_SearchableEntityList hr {
|
||||
height: 1px;
|
||||
border: 0px;
|
||||
color: $primary-fg-color;
|
||||
background-color: $primary-fg-color;
|
||||
margin-right: 15px;
|
||||
margin-top: 11px;
|
||||
margin-bottom: 11px;
|
||||
}
|
|
@ -47,11 +47,15 @@ limitations under the License.
|
|||
|
||||
.mx_SettingsTab_section {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.mx_SettingsTab_section .mx_SettingsFlag {
|
||||
margin-right: 100px;
|
||||
margin-bottom: 10px;
|
||||
.mx_SettingsFlag {
|
||||
margin-right: 100px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
&.mx_SettingsTab_subsectionText .mx_SettingsFlag {
|
||||
margin-right: 0px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_SettingsTab_section .mx_SettingsFlag .mx_SettingsFlag_label {
|
||||
|
|
3
res/img/feather-customised/chevron-down.svg
Normal file
3
res/img/feather-customised/chevron-down.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 9L12 15L18 9" stroke="#2E2F32" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 195 B |
|
@ -165,6 +165,8 @@ $reaction-row-button-hover-border-color: $header-panel-text-primary-color;
|
|||
$reaction-row-button-selected-bg-color: #1f6954;
|
||||
$reaction-row-button-selected-border-color: $accent-color;
|
||||
|
||||
$kbd-border-color: #000000;
|
||||
|
||||
$tooltip-timeline-bg-color: $tagpanel-bg-color;
|
||||
$tooltip-timeline-fg-color: #ffffff;
|
||||
|
||||
|
@ -219,10 +221,6 @@ $user-tile-hover-bg-color: $header-panel-bg-color;
|
|||
filter: invert(1);
|
||||
}
|
||||
|
||||
.gm-scrollbar .thumb {
|
||||
filter: invert(1);
|
||||
}
|
||||
|
||||
// markdown overrides:
|
||||
.mx_EventTile_content .markdown-body pre:hover {
|
||||
border-color: #808080 !important; // inverted due to rules below
|
||||
|
|
|
@ -290,6 +290,8 @@ $reaction-row-button-hover-border-color: $focus-bg-color;
|
|||
$reaction-row-button-selected-bg-color: #e9fff9;
|
||||
$reaction-row-button-selected-border-color: $accent-color;
|
||||
|
||||
$kbd-border-color: $reaction-row-button-border-color;
|
||||
|
||||
$tooltip-timeline-bg-color: $tagpanel-bg-color;
|
||||
$tooltip-timeline-fg-color: #ffffff;
|
||||
|
||||
|
|
|
@ -6,16 +6,8 @@
|
|||
|
||||
set -ev
|
||||
|
||||
upload_logs() {
|
||||
echo "--- Uploading logs"
|
||||
buildkite-agent artifact upload "logs/**/*;synapse/installations/consent/homeserver.log"
|
||||
}
|
||||
|
||||
handle_error() {
|
||||
EXIT_CODE=$?
|
||||
if [ $TESTS_STARTED -eq 1 ]; then
|
||||
upload_logs
|
||||
fi
|
||||
exit $EXIT_CODE
|
||||
}
|
||||
|
||||
|
|
|
@ -237,7 +237,7 @@ const walkOpts = {
|
|||
const fullPath = path.join(root, fileStats.name);
|
||||
|
||||
let trs;
|
||||
if (fileStats.name.endsWith('.js')) {
|
||||
if (fileStats.name.endsWith('.js') || fileStats.name.endsWith('.tsx')) {
|
||||
trs = getTranslationsJs(fullPath);
|
||||
} else if (fileStats.name.endsWith('.html')) {
|
||||
trs = getTranslationsOther(fullPath);
|
||||
|
|
|
@ -8,11 +8,14 @@ var chokidar = require('chokidar');
|
|||
var componentIndex = path.join('src', 'component-index.js');
|
||||
var componentIndexTmp = componentIndex+".tmp";
|
||||
var componentsDir = path.join('src', 'components');
|
||||
var componentGlob = '**/*.js';
|
||||
var componentJsGlob = '**/*.js';
|
||||
var componentTsGlob = '**/*.tsx';
|
||||
var prevFiles = [];
|
||||
|
||||
function reskindex() {
|
||||
var files = glob.sync(componentGlob, {cwd: componentsDir}).sort();
|
||||
var jsFiles = glob.sync(componentJsGlob, {cwd: componentsDir}).sort();
|
||||
var tsFiles = glob.sync(componentTsGlob, {cwd: componentsDir}).sort();
|
||||
var files = [...tsFiles, ...jsFiles];
|
||||
if (!filesHaveChanged(files, prevFiles)) {
|
||||
return;
|
||||
}
|
||||
|
@ -36,7 +39,7 @@ function reskindex() {
|
|||
strm.write("let components = {};\n");
|
||||
|
||||
for (var i = 0; i < files.length; ++i) {
|
||||
var file = files[i].replace('.js', '');
|
||||
var file = files[i].replace('.js', '').replace('.tsx', '');
|
||||
|
||||
var moduleName = (file.replace(/\//g, '.'));
|
||||
var importName = moduleName.replace(/\./g, "$");
|
||||
|
@ -79,7 +82,7 @@ if (!args.w) {
|
|||
}
|
||||
|
||||
var watchDebouncer = null;
|
||||
chokidar.watch(path.join(componentsDir, componentGlob)).on('all', (event, path) => {
|
||||
chokidar.watch(path.join(componentsDir, componentJsGlob)).on('all', (event, path) => {
|
||||
if (path === componentIndex) return;
|
||||
if (watchDebouncer) clearTimeout(watchDebouncer);
|
||||
watchDebouncer = setTimeout(reskindex, 1000);
|
||||
|
|
|
@ -143,7 +143,7 @@ function _setCallListeners(call) {
|
|||
"if you proceed without verifying them, it will be "+
|
||||
"possible for someone to eavesdrop on your call.",
|
||||
),
|
||||
button: _t('Review Devices'),
|
||||
button: _t('Review Sessions'),
|
||||
onFinished: function(confirmed) {
|
||||
if (confirmed) {
|
||||
const room = MatrixClientPeg.get().getRoom(call.roomId);
|
||||
|
|
|
@ -99,9 +99,13 @@ export default class DeviceListener {
|
|||
}
|
||||
|
||||
async _recheck() {
|
||||
if (!SettingsStore.isFeatureEnabled("feature_cross_signing")) return;
|
||||
const cli = MatrixClientPeg.get();
|
||||
|
||||
if (
|
||||
!SettingsStore.isFeatureEnabled("feature_cross_signing") ||
|
||||
!await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")
|
||||
) return;
|
||||
|
||||
if (!cli.isCryptoEnabled()) return;
|
||||
if (!cli.getCrossSigningId()) {
|
||||
if (this._dismissedThisDeviceToast) {
|
||||
|
|
|
@ -40,6 +40,7 @@ export const Key = {
|
|||
GREATER_THAN: ">",
|
||||
BACKTICK: "`",
|
||||
SPACE: " ",
|
||||
SLASH: "/",
|
||||
A: "a",
|
||||
B: "b",
|
||||
C: "c",
|
||||
|
@ -68,8 +69,9 @@ export const Key = {
|
|||
Z: "z",
|
||||
};
|
||||
|
||||
export const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
|
||||
|
||||
export function isOnlyCtrlOrCmdKeyEvent(ev) {
|
||||
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
|
||||
if (isMac) {
|
||||
return ev.metaKey && !ev.altKey && !ev.ctrlKey && !ev.shiftKey;
|
||||
} else {
|
||||
|
@ -78,7 +80,6 @@ export function isOnlyCtrlOrCmdKeyEvent(ev) {
|
|||
}
|
||||
|
||||
export function isOnlyCtrlOrCmdIgnoreShiftKeyEvent(ev) {
|
||||
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
|
||||
if (isMac) {
|
||||
return ev.metaKey && !ev.altKey && !ev.ctrlKey;
|
||||
} else {
|
315
src/accessibility/KeyboardShortcuts.tsx
Normal file
315
src/accessibility/KeyboardShortcuts.tsx
Normal file
|
@ -0,0 +1,315 @@
|
|||
/*
|
||||
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 * 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";
|
||||
|
||||
// TS: once languageHandler is TS we can probably inline this into the enum
|
||||
_td("Navigation");
|
||||
_td("Calls");
|
||||
_td("Composer");
|
||||
_td("Room List");
|
||||
_td("Autocomplete");
|
||||
|
||||
export enum Categories {
|
||||
NAVIGATION = "Navigation",
|
||||
CALLS = "Calls",
|
||||
COMPOSER = "Composer",
|
||||
ROOM_LIST = "Room List",
|
||||
AUTOCOMPLETE = "Autocomplete",
|
||||
}
|
||||
|
||||
// TS: once languageHandler is TS we can probably inline this into the enum
|
||||
_td("Alt");
|
||||
_td("Alt Gr");
|
||||
_td("Shift");
|
||||
_td("Super");
|
||||
_td("Ctrl");
|
||||
|
||||
export enum Modifiers {
|
||||
ALT = "Alt", // Option on Mac and displayed as an Icon
|
||||
ALT_GR = "Alt Gr",
|
||||
SHIFT = "Shift",
|
||||
SUPER = "Super", // should this be "Windows"?
|
||||
// Instead of using below, consider CMD_OR_CTRL
|
||||
COMMAND = "Command", // This gets displayed as an Icon
|
||||
CONTROL = "Ctrl",
|
||||
}
|
||||
|
||||
// Meta-modifier: isMac ? CMD : CONTROL
|
||||
export const CMD_OR_CTRL = isMac ? Modifiers.COMMAND : Modifiers.CONTROL;
|
||||
|
||||
interface IKeybind {
|
||||
modifiers?: Modifiers[];
|
||||
key: string; // TS: fix this once Key is an enum
|
||||
}
|
||||
|
||||
interface IShortcut {
|
||||
keybinds: IKeybind[];
|
||||
description: string;
|
||||
}
|
||||
|
||||
const shortcuts: Record<Categories, IShortcut[]> = {
|
||||
[Categories.COMPOSER]: [
|
||||
{
|
||||
keybinds: [{
|
||||
modifiers: [CMD_OR_CTRL],
|
||||
key: Key.B,
|
||||
}],
|
||||
description: _td("Toggle Bold"),
|
||||
}, {
|
||||
keybinds: [{
|
||||
modifiers: [CMD_OR_CTRL],
|
||||
key: Key.I,
|
||||
}],
|
||||
description: _td("Toggle Italics"),
|
||||
}, {
|
||||
keybinds: [{
|
||||
modifiers: [CMD_OR_CTRL],
|
||||
key: Key.GREATER_THAN,
|
||||
}],
|
||||
description: _td("Toggle Quote"),
|
||||
}, {
|
||||
keybinds: [{
|
||||
modifiers: [CMD_OR_CTRL],
|
||||
key: Key.M,
|
||||
}],
|
||||
description: _td("Toggle Markdown"),
|
||||
}, {
|
||||
keybinds: [{
|
||||
modifiers: [Modifiers.SHIFT],
|
||||
key: Key.ENTER,
|
||||
}],
|
||||
description: _td("New line"),
|
||||
}, {
|
||||
keybinds: [{
|
||||
key: Key.ARROW_UP,
|
||||
}, {
|
||||
key: Key.ARROW_DOWN,
|
||||
}],
|
||||
description: _td("Navigate recent messages to edit"),
|
||||
}, {
|
||||
keybinds: [{
|
||||
modifiers: [CMD_OR_CTRL],
|
||||
key: Key.HOME,
|
||||
}, {
|
||||
modifiers: [CMD_OR_CTRL],
|
||||
key: Key.END,
|
||||
}],
|
||||
description: _td("Jump to start/end of the composer"),
|
||||
},
|
||||
],
|
||||
|
||||
[Categories.CALLS]: [
|
||||
{
|
||||
keybinds: [{
|
||||
modifiers: [CMD_OR_CTRL],
|
||||
key: Key.D,
|
||||
}],
|
||||
description: _td("Toggle microphone mute"),
|
||||
}, {
|
||||
keybinds: [{
|
||||
modifiers: [CMD_OR_CTRL],
|
||||
key: Key.E,
|
||||
}],
|
||||
description: _td("Toggle video on/off"),
|
||||
},
|
||||
],
|
||||
|
||||
[Categories.ROOM_LIST]: [
|
||||
{
|
||||
keybinds: [{
|
||||
modifiers: [CMD_OR_CTRL],
|
||||
key: Key.K,
|
||||
}],
|
||||
description: _td("Jump to room search"),
|
||||
}, {
|
||||
keybinds: [{
|
||||
key: Key.ARROW_UP,
|
||||
}, {
|
||||
key: Key.ARROW_DOWN,
|
||||
}],
|
||||
description: _td("Navigate up/down in the room list"),
|
||||
}, {
|
||||
keybinds: [{
|
||||
key: Key.ENTER,
|
||||
}],
|
||||
description: _td("Select room from the room list"),
|
||||
}, {
|
||||
keybinds: [{
|
||||
key: Key.ARROW_LEFT,
|
||||
}],
|
||||
description: _td("Collapse room list section"),
|
||||
}, {
|
||||
keybinds: [{
|
||||
key: Key.ARROW_RIGHT,
|
||||
}],
|
||||
description: _td("Expand room list section"),
|
||||
}, {
|
||||
keybinds: [{
|
||||
key: Key.ESCAPE,
|
||||
}],
|
||||
description: _td("Clear room list filter field"),
|
||||
},
|
||||
],
|
||||
|
||||
[Categories.NAVIGATION]: [
|
||||
{
|
||||
keybinds: [{
|
||||
key: Key.PAGE_UP,
|
||||
}, {
|
||||
key: Key.PAGE_DOWN,
|
||||
}],
|
||||
description: _td("Scroll up/down in the timeline"),
|
||||
}, {
|
||||
keybinds: [{
|
||||
modifiers: [CMD_OR_CTRL],
|
||||
key: Key.BACKTICK,
|
||||
}],
|
||||
description: _td("Toggle the top left menu"),
|
||||
}, {
|
||||
keybinds: [{
|
||||
key: Key.ESCAPE,
|
||||
}],
|
||||
description: _td("Close dialog or context menu"),
|
||||
}, {
|
||||
keybinds: [{
|
||||
key: Key.ENTER,
|
||||
}, {
|
||||
key: Key.SPACE,
|
||||
}],
|
||||
description: _td("Activate selected button"),
|
||||
}, {
|
||||
keybinds: [{
|
||||
modifiers: [CMD_OR_CTRL],
|
||||
key: Key.SLASH,
|
||||
}],
|
||||
description: _td("Toggle this dialog"),
|
||||
},
|
||||
],
|
||||
|
||||
[Categories.AUTOCOMPLETE]: [
|
||||
{
|
||||
keybinds: [{
|
||||
key: Key.ARROW_UP,
|
||||
}, {
|
||||
key: Key.ARROW_DOWN,
|
||||
}],
|
||||
description: _td("Move autocomplete selection up/down"),
|
||||
}, {
|
||||
keybinds: [{
|
||||
key: Key.ESCAPE,
|
||||
}],
|
||||
description: _td("Cancel autocomplete"),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
interface IModal {
|
||||
close: () => void;
|
||||
finished: Promise<any[]>;
|
||||
}
|
||||
|
||||
const modifierIcon: Record<string, string> = {
|
||||
[Modifiers.COMMAND]: "⌘",
|
||||
};
|
||||
|
||||
if (isMac) {
|
||||
modifierIcon[Modifiers.ALT] = "⌥";
|
||||
}
|
||||
|
||||
const alternateKeyName: Record<string, string> = {
|
||||
[Key.PAGE_UP]: _td("Page Up"),
|
||||
[Key.PAGE_DOWN]: _td("Page Down"),
|
||||
[Key.ESCAPE]: _td("Esc"),
|
||||
[Key.ENTER]: _td("Enter"),
|
||||
[Key.SPACE]: _td("Space"),
|
||||
[Key.HOME]: _td("Home"),
|
||||
[Key.END]: _td("End"),
|
||||
};
|
||||
const keyIcon: Record<string, string> = {
|
||||
[Key.ARROW_UP]: "↑",
|
||||
[Key.ARROW_DOWN]: "↓",
|
||||
[Key.ARROW_LEFT]: "←",
|
||||
[Key.ARROW_RIGHT]: "→",
|
||||
};
|
||||
|
||||
const Shortcut: React.FC<{
|
||||
shortcut: IShortcut;
|
||||
}> = ({shortcut}) => {
|
||||
const classes = classNames({
|
||||
"mx_KeyboardShortcutsDialog_inline": shortcut.keybinds.every(k => !k.modifiers || k.modifiers.length === 0),
|
||||
});
|
||||
|
||||
return <div className={classes}>
|
||||
<h5>{ _t(shortcut.description) }</h5>
|
||||
{ shortcut.keybinds.map(s => {
|
||||
let text = s.key;
|
||||
if (alternateKeyName[s.key]) {
|
||||
text = _t(alternateKeyName[s.key]);
|
||||
} else if (keyIcon[s.key]) {
|
||||
text = keyIcon[s.key];
|
||||
}
|
||||
|
||||
return <div key={s.key}>
|
||||
{ s.modifiers && s.modifiers.map(m => {
|
||||
return <React.Fragment key={m}>
|
||||
<kbd>{ modifierIcon[m] || _t(m) }</kbd>+
|
||||
</React.Fragment>;
|
||||
}) }
|
||||
<kbd>{ text }</kbd>
|
||||
</div>;
|
||||
}) }
|
||||
</div>;
|
||||
};
|
||||
|
||||
let activeModal: IModal = null;
|
||||
export const toggleDialog = () => {
|
||||
if (activeModal) {
|
||||
activeModal.close();
|
||||
activeModal = null;
|
||||
return;
|
||||
}
|
||||
|
||||
const sections = Object.entries(shortcuts).map(([category, list]) => {
|
||||
return <div className="mx_KeyboardShortcutsDialog_category" key={category}>
|
||||
<h3>{_t(category)}</h3>
|
||||
<div>{list.map(shortcut => <Shortcut key={shortcut.description} shortcut={shortcut} />)}</div>
|
||||
</div>;
|
||||
});
|
||||
|
||||
const InfoDialog = sdk.getComponent('dialogs.InfoDialog');
|
||||
activeModal = Modal.createTrackedDialog("Keyboard Shortcuts", "", InfoDialog, {
|
||||
className: "mx_KeyboardShortcutsDialog",
|
||||
title: _t("Keyboard Shortcuts"),
|
||||
description: sections,
|
||||
hasCloseButton: true,
|
||||
onKeyDown: (ev) => {
|
||||
if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey && ev.key === Key.SLASH) { // Ctrl + /
|
||||
ev.stopPropagation();
|
||||
activeModal.close();
|
||||
}
|
||||
},
|
||||
onFinished: () => {
|
||||
activeModal = null;
|
||||
},
|
||||
});
|
||||
};
|
|
@ -350,7 +350,7 @@ export const ContextMenuButton = ({ label, isExpanded, children, ...props }) =>
|
|||
};
|
||||
ContextMenuButton.propTypes = {
|
||||
...AccessibleButton.propTypes,
|
||||
label: PropTypes.string.isRequired,
|
||||
label: PropTypes.string,
|
||||
isExpanded: PropTypes.bool.isRequired, // whether or not the context menu is currently open
|
||||
};
|
||||
|
||||
|
@ -377,7 +377,6 @@ export const MenuGroup = ({children, label, ...props}) => {
|
|||
</div>;
|
||||
};
|
||||
MenuGroup.propTypes = {
|
||||
...AccessibleButton.propTypes,
|
||||
label: PropTypes.string.isRequired,
|
||||
className: PropTypes.string, // optional
|
||||
};
|
||||
|
|
|
@ -23,11 +23,11 @@ import PropTypes from 'prop-types';
|
|||
import request from 'browser-request';
|
||||
import { _t } from '../../languageHandler';
|
||||
import sanitizeHtml from 'sanitize-html';
|
||||
import * as sdk from '../../index';
|
||||
import dis from '../../dispatcher';
|
||||
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
||||
import classnames from 'classnames';
|
||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||
import AutoHideScrollbar from "./AutoHideScrollbar";
|
||||
|
||||
export default class EmbeddedPage extends React.PureComponent {
|
||||
static propTypes = {
|
||||
|
@ -117,10 +117,9 @@ export default class EmbeddedPage extends React.PureComponent {
|
|||
</div>;
|
||||
|
||||
if (this.props.scrollbar) {
|
||||
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
|
||||
return <GeminiScrollbarWrapper autoshow={true} className={classes}>
|
||||
return <AutoHideScrollbar className={classes}>
|
||||
{content}
|
||||
</GeminiScrollbarWrapper>;
|
||||
</AutoHideScrollbar>;
|
||||
} else {
|
||||
return <div className={classes}>
|
||||
{content}
|
||||
|
|
|
@ -39,6 +39,7 @@ import {makeGroupPermalink, makeUserPermalink} from "../../utils/permalinks/Perm
|
|||
import {Group} from "matrix-js-sdk";
|
||||
import {allSettled, sleep} from "../../utils/promise";
|
||||
import RightPanelStore from "../../stores/RightPanelStore";
|
||||
import AutoHideScrollbar from "./AutoHideScrollbar";
|
||||
|
||||
const LONG_DESC_PLACEHOLDER = _td(
|
||||
`<h1>HTML for your community's page</h1>
|
||||
|
@ -554,10 +555,6 @@ export default createReactClass({
|
|||
GROUP_JOINPOLICY_INVITE,
|
||||
},
|
||||
});
|
||||
dis.dispatch({
|
||||
action: 'panel_disable',
|
||||
sideDisabled: true,
|
||||
});
|
||||
},
|
||||
|
||||
_onShareClick: function() {
|
||||
|
@ -1173,7 +1170,6 @@ export default createReactClass({
|
|||
render: function() {
|
||||
const GroupAvatar = sdk.getComponent("avatars.GroupAvatar");
|
||||
const Spinner = sdk.getComponent("elements.Spinner");
|
||||
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
|
||||
|
||||
if (this.state.summaryLoading && this.state.error === null || this.state.saving) {
|
||||
return <Spinner />;
|
||||
|
@ -1332,10 +1328,10 @@ export default createReactClass({
|
|||
<GroupHeaderButtons />
|
||||
</div>
|
||||
<MainSplit panel={rightPanel}>
|
||||
<GeminiScrollbarWrapper className="mx_GroupView_body">
|
||||
<AutoHideScrollbar className="mx_GroupView_body">
|
||||
{ this._getMembershipSection() }
|
||||
{ this._getGroupSection() }
|
||||
</GeminiScrollbarWrapper>
|
||||
</AutoHideScrollbar>
|
||||
</MainSplit>
|
||||
</main>
|
||||
);
|
||||
|
|
|
@ -39,6 +39,7 @@ import RoomListActions from '../../actions/RoomListActions';
|
|||
import ResizeHandle from '../views/elements/ResizeHandle';
|
||||
import {Resizer, CollapseDistributor} from '../../resizer';
|
||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||
import * as KeyboardShortcuts from "../../accessibility/KeyboardShortcuts";
|
||||
// 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.
|
||||
// NB. this is just for server notices rather than pinned messages in general.
|
||||
|
@ -337,13 +338,13 @@ const LoggedInView = createReactClass({
|
|||
|
||||
let handled = false;
|
||||
const ctrlCmdOnly = isOnlyCtrlOrCmdKeyEvent(ev);
|
||||
const hasModifier = ev.altKey || ev.ctrlKey || ev.metaKey || ev.shiftKey ||
|
||||
ev.key === Key.ALT || ev.key === Key.CONTROL || ev.key === Key.META || ev.key === Key.SHIFT;
|
||||
const hasModifier = ev.altKey || ev.ctrlKey || ev.metaKey || ev.shiftKey;
|
||||
const isModifier = ev.key === Key.ALT || ev.key === Key.CONTROL || ev.key === Key.META || ev.key === Key.SHIFT;
|
||||
|
||||
switch (ev.key) {
|
||||
case Key.PAGE_UP:
|
||||
case Key.PAGE_DOWN:
|
||||
if (!hasModifier) {
|
||||
if (!hasModifier && !isModifier) {
|
||||
this._onScrollKeyPressed(ev);
|
||||
handled = true;
|
||||
}
|
||||
|
@ -365,8 +366,6 @@ const LoggedInView = createReactClass({
|
|||
}
|
||||
break;
|
||||
case Key.BACKTICK:
|
||||
if (ev.key !== "`") break;
|
||||
|
||||
// Ideally this would be CTRL+P for "Profile", but that's
|
||||
// taken by the print dialog. CTRL+I for "Information"
|
||||
// was previously chosen but conflicted with italics in
|
||||
|
@ -379,12 +378,22 @@ const LoggedInView = createReactClass({
|
|||
handled = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case Key.SLASH:
|
||||
if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) {
|
||||
KeyboardShortcuts.toggleDialog();
|
||||
handled = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
} else if (!hasModifier) {
|
||||
} else if (!isModifier && !ev.altKey && !ev.ctrlKey && !ev.metaKey) {
|
||||
// The above condition is crafted to _allow_ characters with Shift
|
||||
// already pressed (but not the Shift key down itself).
|
||||
|
||||
const isClickShortcut = ev.target !== document.body &&
|
||||
(ev.key === Key.SPACE || ev.key === Key.ENTER);
|
||||
|
||||
|
|
|
@ -600,9 +600,8 @@ export default createReactClass({
|
|||
break;
|
||||
case 'view_room_directory': {
|
||||
const RoomDirectory = sdk.getComponent("structures.RoomDirectory");
|
||||
Modal.createTrackedDialog('Room directory', '', RoomDirectory, {
|
||||
config: this.props.config,
|
||||
}, 'mx_RoomDirectory_dialogWrapper');
|
||||
Modal.createTrackedDialog('Room directory', '', RoomDirectory, {},
|
||||
'mx_RoomDirectory_dialogWrapper', false, true);
|
||||
|
||||
// View the welcome or home page if we need something to look at
|
||||
this._viewSomethingBehindModal();
|
||||
|
@ -1911,7 +1910,10 @@ export default createReactClass({
|
|||
// secret storage.
|
||||
SettingsStore.setFeatureEnabled("feature_cross_signing", true);
|
||||
this.setStateForNewView({ view: VIEWS.COMPLETE_SECURITY });
|
||||
} else if (SettingsStore.isFeatureEnabled("feature_cross_signing")) {
|
||||
} else if (
|
||||
SettingsStore.isFeatureEnabled("feature_cross_signing") &&
|
||||
await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")
|
||||
) {
|
||||
// This will only work if the feature is set to 'enable' in the config,
|
||||
// since it's too early in the lifecycle for users to have turned the
|
||||
// labs flag on.
|
||||
|
|
|
@ -22,6 +22,7 @@ import { _t } from '../../languageHandler';
|
|||
import dis from '../../dispatcher';
|
||||
import AccessibleButton from '../views/elements/AccessibleButton';
|
||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||
import AutoHideScrollbar from "./AutoHideScrollbar";
|
||||
|
||||
export default createReactClass({
|
||||
displayName: 'MyGroups',
|
||||
|
@ -62,8 +63,6 @@ export default createReactClass({
|
|||
const Loader = sdk.getComponent("elements.Spinner");
|
||||
const SimpleRoomHeader = sdk.getComponent('rooms.SimpleRoomHeader');
|
||||
const GroupTile = sdk.getComponent("groups.GroupTile");
|
||||
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
|
||||
|
||||
|
||||
let content;
|
||||
let contentHeader;
|
||||
|
@ -74,7 +73,7 @@ export default createReactClass({
|
|||
});
|
||||
contentHeader = groupNodes.length > 0 ? <h3>{ _t('Your Communities') }</h3> : <div />;
|
||||
content = groupNodes.length > 0 ?
|
||||
<GeminiScrollbarWrapper>
|
||||
<AutoHideScrollbar className="mx_MyGroups_scrollable">
|
||||
<div className="mx_MyGroups_microcopy">
|
||||
<p>
|
||||
{ _t(
|
||||
|
@ -93,7 +92,7 @@ export default createReactClass({
|
|||
<div className="mx_MyGroups_joinedGroups">
|
||||
{ groupNodes }
|
||||
</div>
|
||||
</GeminiScrollbarWrapper> :
|
||||
</AutoHideScrollbar> :
|
||||
<div className="mx_MyGroups_placeholder">
|
||||
{ _t(
|
||||
"You're not currently a member of any communities.",
|
||||
|
|
|
@ -28,6 +28,7 @@ import { _t } from '../../languageHandler';
|
|||
import { instanceForInstanceId, protocolNameForInstanceId } from '../../utils/DirectoryUtils';
|
||||
import Analytics from '../../Analytics';
|
||||
import {getHttpUriForMxc} from "matrix-js-sdk/src/content-repo";
|
||||
import {ALL_ROOMS} from "../views/directory/NetworkDropdown";
|
||||
|
||||
const MAX_NAME_LENGTH = 80;
|
||||
const MAX_TOPIC_LENGTH = 160;
|
||||
|
@ -40,25 +41,17 @@ export default createReactClass({
|
|||
displayName: 'RoomDirectory',
|
||||
|
||||
propTypes: {
|
||||
config: PropTypes.object,
|
||||
onFinished: PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
config: {},
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
publicRooms: [],
|
||||
loading: true,
|
||||
protocolsLoading: true,
|
||||
error: null,
|
||||
instanceId: null,
|
||||
includeAll: false,
|
||||
roomServer: null,
|
||||
instanceId: undefined,
|
||||
roomServer: MatrixClientPeg.getHomeserverName(),
|
||||
filterString: null,
|
||||
};
|
||||
},
|
||||
|
@ -98,6 +91,10 @@ export default createReactClass({
|
|||
});
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
this.refreshRoomList();
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
if (this.filterTimeout) {
|
||||
clearTimeout(this.filterTimeout);
|
||||
|
@ -130,10 +127,10 @@ export default createReactClass({
|
|||
if (my_server != MatrixClientPeg.getHomeserverName()) {
|
||||
opts.server = my_server;
|
||||
}
|
||||
if (this.state.instanceId) {
|
||||
opts.third_party_instance_id = this.state.instanceId;
|
||||
} else if (this.state.includeAll) {
|
||||
if (this.state.instanceId === ALL_ROOMS) {
|
||||
opts.include_all_networks = true;
|
||||
} else if (this.state.instanceId) {
|
||||
opts.third_party_instance_id = this.state.instanceId;
|
||||
}
|
||||
if (this.nextBatch) opts.since = this.nextBatch;
|
||||
if (my_filter_string) opts.filter = { generic_search_term: my_filter_string };
|
||||
|
@ -247,7 +244,7 @@ export default createReactClass({
|
|||
}
|
||||
},
|
||||
|
||||
onOptionChange: function(server, instanceId, includeAll) {
|
||||
onOptionChange: function(server, instanceId) {
|
||||
// clear next batch so we don't try to load more rooms
|
||||
this.nextBatch = null;
|
||||
this.setState({
|
||||
|
@ -257,7 +254,6 @@ export default createReactClass({
|
|||
publicRooms: [],
|
||||
roomServer: server,
|
||||
instanceId: instanceId,
|
||||
includeAll: includeAll,
|
||||
error: null,
|
||||
}, this.refreshRoomList);
|
||||
// We also refresh the room list each time even though this
|
||||
|
@ -305,7 +301,7 @@ export default createReactClass({
|
|||
|
||||
onJoinFromSearchClick: function(alias) {
|
||||
// If we don't have a particular instance id selected, just show that rooms alias
|
||||
if (!this.state.instanceId) {
|
||||
if (!this.state.instanceId || this.state.instanceId === ALL_ROOMS) {
|
||||
// If the user specified an alias without a domain, add on whichever server is selected
|
||||
// in the dropdown
|
||||
if (alias.indexOf(':') == -1) {
|
||||
|
@ -406,6 +402,12 @@ export default createReactClass({
|
|||
// would normally decide what the name is.
|
||||
name: room.name || room_alias || _t('Unnamed room'),
|
||||
};
|
||||
|
||||
if (this.state.roomServer) {
|
||||
payload.opts = {
|
||||
viaServers: [this.state.roomServer],
|
||||
};
|
||||
}
|
||||
}
|
||||
// It's not really possible to join Matrix rooms by ID because the HS has no way to know
|
||||
// which servers to start querying. However, there's no other way to join rooms in
|
||||
|
@ -587,7 +589,7 @@ export default createReactClass({
|
|||
}
|
||||
|
||||
let placeholder = _t('Find a room…');
|
||||
if (!this.state.instanceId) {
|
||||
if (!this.state.instanceId || this.state.instanceId === ALL_ROOMS) {
|
||||
placeholder = _t("Find a room… (e.g. %(exampleRoom)s)", {exampleRoom: "#example:" + this.state.roomServer});
|
||||
} else if (instance_expected_field_type) {
|
||||
placeholder = instance_expected_field_type.placeholder;
|
||||
|
@ -604,10 +606,18 @@ export default createReactClass({
|
|||
listHeader = <div className="mx_RoomDirectory_listheader">
|
||||
<DirectorySearchBox
|
||||
className="mx_RoomDirectory_searchbox"
|
||||
onChange={this.onFilterChange} onClear={this.onFilterClear} onJoinClick={this.onJoinFromSearchClick}
|
||||
placeholder={placeholder} showJoinButton={showJoinButton}
|
||||
onChange={this.onFilterChange}
|
||||
onClear={this.onFilterClear}
|
||||
onJoinClick={this.onJoinFromSearchClick}
|
||||
placeholder={placeholder}
|
||||
showJoinButton={showJoinButton}
|
||||
/>
|
||||
<NetworkDropdown
|
||||
protocols={this.protocols}
|
||||
onOptionChange={this.onOptionChange}
|
||||
selectedServerName={this.state.roomServer}
|
||||
selectedInstanceId={this.state.instanceId}
|
||||
/>
|
||||
<NetworkDropdown config={this.props.config} protocols={this.protocols} onOptionChange={this.onOptionChange} />
|
||||
</div>;
|
||||
}
|
||||
const explanation =
|
||||
|
@ -628,7 +638,7 @@ export default createReactClass({
|
|||
title={_t("Explore rooms")}
|
||||
>
|
||||
<div className="mx_RoomDirectory">
|
||||
<p>{explanation}</p>
|
||||
{explanation}
|
||||
<div className="mx_RoomDirectory_list">
|
||||
{listHeader}
|
||||
{content}
|
||||
|
|
|
@ -405,21 +405,6 @@ export default createReactClass({
|
|||
this.onResize();
|
||||
|
||||
document.addEventListener("keydown", this.onKeyDown);
|
||||
|
||||
// XXX: EVIL HACK to autofocus inviting on empty rooms.
|
||||
// We use the setTimeout to avoid racing with focus_composer.
|
||||
if (this.state.room &&
|
||||
this.state.room.getJoinedMemberCount() == 1 &&
|
||||
this.state.room.getLiveTimeline() &&
|
||||
this.state.room.getLiveTimeline().getEvents() &&
|
||||
this.state.room.getLiveTimeline().getEvents().length <= 6) {
|
||||
const inviteBox = document.getElementById("mx_SearchableEntityList_query");
|
||||
setTimeout(function() {
|
||||
if (inviteBox) {
|
||||
inviteBox.focus();
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
},
|
||||
|
||||
shouldComponentUpdate: function(nextProps, nextState) {
|
||||
|
|
|
@ -782,7 +782,7 @@ export default createReactClass({
|
|||
if (!this._divScroll) {
|
||||
// Likewise, we should have the ref by this point, but if not
|
||||
// turn the NPE into something meaningful.
|
||||
throw new Error("ScrollPanel._getScrollNode called before gemini ref collected");
|
||||
throw new Error("ScrollPanel._getScrollNode called before AutoHideScrollbar ref collected");
|
||||
}
|
||||
|
||||
return this._divScroll;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
Copyright 2017 Travis Ralston
|
||||
Copyright 2019 New Vector Ltd
|
||||
Copyright 2019 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2019, 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.
|
||||
|
@ -18,41 +18,54 @@ limitations under the License.
|
|||
|
||||
import * as React from "react";
|
||||
import {_t} from '../../languageHandler';
|
||||
import PropTypes from "prop-types";
|
||||
import * as PropTypes from "prop-types";
|
||||
import * as sdk from "../../index";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
/**
|
||||
* Represents a tab for the TabbedView.
|
||||
*/
|
||||
export class Tab {
|
||||
public label: string;
|
||||
public icon: string;
|
||||
public body: React.ReactNode;
|
||||
|
||||
/**
|
||||
* Creates a new tab.
|
||||
* @param {string} tabLabel The untranslated tab label.
|
||||
* @param {string} tabIconClass The class for the tab icon. This should be a simple mask.
|
||||
* @param {string} tabJsx The JSX for the tab container.
|
||||
* @param {React.ReactNode} tabJsx The JSX for the tab container.
|
||||
*/
|
||||
constructor(tabLabel, tabIconClass, tabJsx) {
|
||||
constructor(tabLabel: string, tabIconClass: string, tabJsx: React.ReactNode) {
|
||||
this.label = tabLabel;
|
||||
this.icon = tabIconClass;
|
||||
this.body = tabJsx;
|
||||
}
|
||||
}
|
||||
|
||||
export default class TabbedView extends React.Component {
|
||||
interface IProps {
|
||||
tabs: Tab[];
|
||||
}
|
||||
|
||||
interface IState {
|
||||
activeTabIndex: number;
|
||||
}
|
||||
|
||||
export default class TabbedView extends React.Component<IProps, IState> {
|
||||
static propTypes = {
|
||||
// The tabs to show
|
||||
tabs: PropTypes.arrayOf(PropTypes.instanceOf(Tab)).isRequired,
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
activeTabIndex: 0,
|
||||
};
|
||||
}
|
||||
|
||||
_getActiveTabIndex() {
|
||||
private _getActiveTabIndex() {
|
||||
if (!this.state || !this.state.activeTabIndex) return 0;
|
||||
return this.state.activeTabIndex;
|
||||
}
|
||||
|
@ -62,7 +75,7 @@ export default class TabbedView extends React.Component {
|
|||
* @param {Tab} tab the tab to show
|
||||
* @private
|
||||
*/
|
||||
_setActiveTab(tab) {
|
||||
private _setActiveTab(tab: Tab) {
|
||||
const idx = this.props.tabs.indexOf(tab);
|
||||
if (idx !== -1) {
|
||||
this.setState({activeTabIndex: idx});
|
||||
|
@ -71,7 +84,7 @@ export default class TabbedView extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
_renderTabLabel(tab) {
|
||||
private _renderTabLabel(tab: Tab) {
|
||||
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
||||
|
||||
let classes = "mx_TabbedView_tabLabel ";
|
||||
|
@ -97,7 +110,7 @@ export default class TabbedView extends React.Component {
|
|||
);
|
||||
}
|
||||
|
||||
_renderTabPanel(tab) {
|
||||
private _renderTabPanel(tab: Tab): React.ReactNode {
|
||||
return (
|
||||
<div className="mx_TabbedView_tabPanel" key={"mx_tabpanel_" + tab.label}>
|
||||
<div className='mx_TabbedView_tabPanelContent'>
|
||||
|
@ -107,7 +120,7 @@ export default class TabbedView extends React.Component {
|
|||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
public render(): React.ReactNode {
|
||||
const labels = this.props.tabs.map(tab => this._renderTabLabel(tab));
|
||||
const panel = this._renderTabPanel(this.props.tabs[this._getActiveTabIndex()]);
|
||||
|
|
@ -28,6 +28,7 @@ import { _t } from '../../languageHandler';
|
|||
import { Droppable } from 'react-beautiful-dnd';
|
||||
import classNames from 'classnames';
|
||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||
import AutoHideScrollbar from "./AutoHideScrollbar";
|
||||
|
||||
const TagPanel = createReactClass({
|
||||
displayName: 'TagPanel',
|
||||
|
@ -106,7 +107,6 @@ const TagPanel = createReactClass({
|
|||
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
||||
const ActionButton = sdk.getComponent('elements.ActionButton');
|
||||
const TintableSvg = sdk.getComponent('elements.TintableSvg');
|
||||
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
|
||||
|
||||
const tags = this.state.orderedTags.map((tag, index) => {
|
||||
return <DNDTagTile
|
||||
|
@ -138,9 +138,8 @@ const TagPanel = createReactClass({
|
|||
{ clearButton }
|
||||
</div>
|
||||
<div className="mx_TagPanel_divider" />
|
||||
<GeminiScrollbarWrapper
|
||||
<AutoHideScrollbar
|
||||
className="mx_TagPanel_scroller"
|
||||
autoshow={true}
|
||||
// XXX: Use onMouseDown as a workaround for https://github.com/atlassian/react-beautiful-dnd/issues/273
|
||||
// instead of onClick. Otherwise we experience https://github.com/vector-im/riot-web/issues/6253
|
||||
onMouseDown={this.onMouseDown}
|
||||
|
@ -166,7 +165,7 @@ const TagPanel = createReactClass({
|
|||
</div>
|
||||
) }
|
||||
</Droppable>
|
||||
</GeminiScrollbarWrapper>
|
||||
</AutoHideScrollbar>
|
||||
</div>;
|
||||
},
|
||||
});
|
||||
|
|
|
@ -54,17 +54,39 @@ export default class CompleteSecurity extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
onStartClick = async () => {
|
||||
_onUsePassphraseClick = async () => {
|
||||
this.setState({
|
||||
phase: PHASE_BUSY,
|
||||
});
|
||||
const cli = MatrixClientPeg.get();
|
||||
const backupInfo = await cli.getKeyBackupVersion();
|
||||
this.setState({backupInfo});
|
||||
try {
|
||||
await accessSecretStorage(async () => {
|
||||
await cli.checkOwnCrossSigningTrust();
|
||||
if (backupInfo) await cli.restoreKeyBackupWithSecretStorage(backupInfo);
|
||||
const backupInfo = await cli.getKeyBackupVersion();
|
||||
this.setState({backupInfo});
|
||||
|
||||
// The control flow is fairly twisted here...
|
||||
// For the purposes of completing security, we only wait on getting
|
||||
// as far as the trust check and then show a green shield.
|
||||
// We also begin the key backup restore as well, which we're
|
||||
// awaiting inside `accessSecretStorage` only so that it keeps your
|
||||
// passphase cached for that work. This dialog itself will only wait
|
||||
// on the first trust check, and the key backup restore will happen
|
||||
// in the background.
|
||||
await new Promise((resolve, reject) => {
|
||||
try {
|
||||
accessSecretStorage(async () => {
|
||||
await cli.checkOwnCrossSigningTrust();
|
||||
resolve();
|
||||
if (backupInfo) {
|
||||
// A complete restore can take many minutes for large
|
||||
// accounts / slow servers, so we allow the dialog
|
||||
// to advance before this.
|
||||
await cli.restoreKeyBackupWithSecretStorage(backupInfo);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
|
||||
if (cli.getCrossSigningId()) {
|
||||
|
@ -147,13 +169,27 @@ export default class CompleteSecurity extends React.Component {
|
|||
member={MatrixClientPeg.get().getUser(this.state.verificationRequest.otherUserId)}
|
||||
/>;
|
||||
} else if (phase === PHASE_INTRO) {
|
||||
const InlineSpinner = sdk.getComponent('elements.InlineSpinner');
|
||||
|
||||
icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_warning"></span>;
|
||||
title = _t("Complete security");
|
||||
body = (
|
||||
<div>
|
||||
<p>{_t(
|
||||
"Verify this session to grant it access to encrypted messages.",
|
||||
"Open an existing session & use it to verify this one, " +
|
||||
"granting it access to encrypted messages.",
|
||||
)}</p>
|
||||
<p className="mx_CompleteSecurity_waiting"><InlineSpinner />{_t("Waiting…")}</p>
|
||||
<p>{_t(
|
||||
"If you can’t access one, <button>use your recovery key or passphrase.</button>",
|
||||
{}, {
|
||||
button: sub => <AccessibleButton element="span"
|
||||
className="mx_linkButton"
|
||||
onClick={this._onUsePassphraseClick}
|
||||
>
|
||||
{sub}
|
||||
</AccessibleButton>,
|
||||
})}</p>
|
||||
<div className="mx_CompleteSecurity_actionRow">
|
||||
<AccessibleButton
|
||||
kind="danger"
|
||||
|
@ -161,12 +197,6 @@ export default class CompleteSecurity extends React.Component {
|
|||
>
|
||||
{_t("Skip")}
|
||||
</AccessibleButton>
|
||||
<AccessibleButton
|
||||
kind="primary"
|
||||
onClick={this.onStartClick}
|
||||
>
|
||||
{_t("Start")}
|
||||
</AccessibleButton>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -32,6 +32,7 @@ export default createReactClass({
|
|||
button: PropTypes.string,
|
||||
onFinished: PropTypes.func,
|
||||
hasCloseButton: PropTypes.bool,
|
||||
onKeyDown: PropTypes.func,
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
|
@ -50,10 +51,13 @@ export default createReactClass({
|
|||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||
return (
|
||||
<BaseDialog className="mx_InfoDialog" onFinished={this.props.onFinished}
|
||||
<BaseDialog
|
||||
className="mx_InfoDialog"
|
||||
onFinished={this.props.onFinished}
|
||||
title={this.props.title}
|
||||
contentId='mx_Dialog_content'
|
||||
hasCancel={this.props.hasCloseButton}
|
||||
onKeyDown={this.props.onKeyDown}
|
||||
>
|
||||
<div className={classNames("mx_Dialog_content", this.props.className)} id="mx_Dialog_content">
|
||||
{ this.props.description }
|
||||
|
|
|
@ -33,6 +33,7 @@ export default createReactClass({
|
|||
onFinished: PropTypes.func.isRequired,
|
||||
headerImage: PropTypes.string,
|
||||
quitOnly: PropTypes.bool, // quitOnly doesn't show the cancel button just the quit [x].
|
||||
fixedWidth: PropTypes.bool,
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
|
@ -63,11 +64,14 @@ export default createReactClass({
|
|||
primaryButtonClass = "danger";
|
||||
}
|
||||
return (
|
||||
<BaseDialog className="mx_QuestionDialog" onFinished={this.props.onFinished}
|
||||
<BaseDialog
|
||||
className="mx_QuestionDialog"
|
||||
onFinished={this.props.onFinished}
|
||||
title={this.props.title}
|
||||
contentId='mx_Dialog_content'
|
||||
headerImage={this.props.headerImage}
|
||||
hasCancel={this.props.hasCancelButton}
|
||||
fixedWidth={this.props.fixedWidth}
|
||||
>
|
||||
<div className="mx_Dialog_content" id='mx_Dialog_content'>
|
||||
{ this.props.description }
|
||||
|
|
|
@ -18,6 +18,7 @@ import React, {createRef} from 'react';
|
|||
import createReactClass from 'create-react-class';
|
||||
import PropTypes from 'prop-types';
|
||||
import * as sdk from '../../../index';
|
||||
import Field from "../elements/Field";
|
||||
|
||||
export default createReactClass({
|
||||
displayName: 'TextInputDialog',
|
||||
|
@ -28,9 +29,13 @@ export default createReactClass({
|
|||
PropTypes.string,
|
||||
]),
|
||||
value: PropTypes.string,
|
||||
placeholder: PropTypes.string,
|
||||
button: PropTypes.string,
|
||||
focus: PropTypes.bool,
|
||||
onFinished: PropTypes.func.isRequired,
|
||||
hasCancel: PropTypes.bool,
|
||||
validator: PropTypes.func, // result of withValidation
|
||||
fixedWidth: PropTypes.bool,
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
|
@ -39,34 +44,70 @@ export default createReactClass({
|
|||
value: "",
|
||||
description: "",
|
||||
focus: true,
|
||||
hasCancel: true,
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
value: this.props.value,
|
||||
valid: false,
|
||||
};
|
||||
},
|
||||
|
||||
UNSAFE_componentWillMount: function() {
|
||||
this._textinput = createRef();
|
||||
this._field = createRef();
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
if (this.props.focus) {
|
||||
// Set the cursor at the end of the text input
|
||||
this._textinput.current.value = this.props.value;
|
||||
// this._field.current.value = this.props.value;
|
||||
this._field.current.focus();
|
||||
}
|
||||
},
|
||||
|
||||
onOk: function() {
|
||||
this.props.onFinished(true, this._textinput.current.value);
|
||||
onOk: async function(ev) {
|
||||
ev.preventDefault();
|
||||
if (this.props.validator) {
|
||||
await this._field.current.validate({ allowEmpty: false });
|
||||
|
||||
if (!this._field.current.state.valid) {
|
||||
this._field.current.focus();
|
||||
this._field.current.validate({ allowEmpty: false, focused: true });
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.props.onFinished(true, this.state.value);
|
||||
},
|
||||
|
||||
onCancel: function() {
|
||||
this.props.onFinished(false);
|
||||
},
|
||||
|
||||
onChange: function(ev) {
|
||||
this.setState({
|
||||
value: ev.target.value,
|
||||
});
|
||||
},
|
||||
|
||||
onValidate: async function(fieldState) {
|
||||
const result = await this.props.validator(fieldState);
|
||||
this.setState({
|
||||
valid: result.valid,
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||
return (
|
||||
<BaseDialog className="mx_TextInputDialog" onFinished={this.props.onFinished}
|
||||
<BaseDialog
|
||||
className="mx_TextInputDialog"
|
||||
onFinished={this.props.onFinished}
|
||||
title={this.props.title}
|
||||
fixedWidth={this.props.fixedWidth}
|
||||
>
|
||||
<form onSubmit={this.onOk}>
|
||||
<div className="mx_Dialog_content">
|
||||
|
@ -74,19 +115,26 @@ export default createReactClass({
|
|||
<label htmlFor="textinput"> { this.props.description } </label>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
id="textinput"
|
||||
ref={this._textinput}
|
||||
<Field
|
||||
id="mx_TextInputDialog_field"
|
||||
className="mx_TextInputDialog_input"
|
||||
defaultValue={this.props.value}
|
||||
autoFocus={this.props.focus}
|
||||
size="64" />
|
||||
ref={this._field}
|
||||
type="text"
|
||||
label={this.props.placeholder}
|
||||
value={this.state.value}
|
||||
onChange={this.onChange}
|
||||
onValidate={this.props.validator ? this.onValidate : undefined}
|
||||
size="64"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<DialogButtons primaryButton={this.props.button}
|
||||
<DialogButtons
|
||||
primaryButton={this.props.button}
|
||||
onPrimaryButtonClick={this.onOk}
|
||||
onCancel={this.onCancel} />
|
||||
onCancel={this.onCancel}
|
||||
hasCancel={this.props.hasCancel}
|
||||
/>
|
||||
</BaseDialog>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -122,7 +122,6 @@ export default createReactClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
|
||||
if (this.props.devices === null) {
|
||||
const Spinner = sdk.getComponent("elements.Spinner");
|
||||
return <Spinner />;
|
||||
|
@ -168,7 +167,7 @@ export default createReactClass({
|
|||
title={_t('Room contains unknown sessions')}
|
||||
contentId='mx_Dialog_content'
|
||||
>
|
||||
<GeminiScrollbarWrapper autoshow={false} className="mx_Dialog_content" id='mx_Dialog_content'>
|
||||
<div className="mx_Dialog_content" id='mx_Dialog_content'>
|
||||
<h4>
|
||||
{ _t('"%(RoomName)s" contains sessions that you haven\'t seen before.', {RoomName: this.props.room.name}) }
|
||||
</h4>
|
||||
|
@ -176,7 +175,7 @@ export default createReactClass({
|
|||
{ _t("Unknown sessions") }:
|
||||
|
||||
<UnknownDeviceList devices={this.props.devices} />
|
||||
</GeminiScrollbarWrapper>
|
||||
</div>
|
||||
<DialogButtons primaryButton={sendButtonLabel}
|
||||
onPrimaryButtonClick={sendButtonOnClick}
|
||||
onCancel={this._onDismissClicked} />
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
Copyright 2016 OpenMarket Ltd
|
||||
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
|
||||
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.
|
||||
|
@ -15,241 +16,275 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, {useEffect, useState} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||
import {instanceForInstanceId} from '../../../utils/DirectoryUtils';
|
||||
import {
|
||||
ContextMenu,
|
||||
useContextMenu,
|
||||
ContextMenuButton,
|
||||
MenuItemRadio,
|
||||
MenuItem,
|
||||
MenuGroup,
|
||||
} from "../../structures/ContextMenu";
|
||||
import {_t} from "../../../languageHandler";
|
||||
import SdkConfig from "../../../SdkConfig";
|
||||
import {useSettingValue} from "../../../hooks/useSettings";
|
||||
import * as sdk from "../../../index";
|
||||
import Modal from "../../../Modal";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import withValidation from "../elements/Validation";
|
||||
|
||||
const DEFAULT_ICON_URL = require("../../../../res/img/network-matrix.svg");
|
||||
export const ALL_ROOMS = Symbol("ALL_ROOMS");
|
||||
|
||||
export default class NetworkDropdown extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const SETTING_NAME = "room_directory_servers";
|
||||
|
||||
this.dropdownRootElement = null;
|
||||
this.ignoreEvent = null;
|
||||
const inPlaceOf = (elementRect) => ({
|
||||
right: window.innerWidth - elementRect.right,
|
||||
top: elementRect.top,
|
||||
chevronOffset: 0,
|
||||
chevronFace: "none",
|
||||
});
|
||||
|
||||
this.onInputClick = this.onInputClick.bind(this);
|
||||
this.onRootClick = this.onRootClick.bind(this);
|
||||
this.onDocumentClick = this.onDocumentClick.bind(this);
|
||||
this.onMenuOptionClick = this.onMenuOptionClick.bind(this);
|
||||
this.onInputKeyUp = this.onInputKeyUp.bind(this);
|
||||
this.collectRoot = this.collectRoot.bind(this);
|
||||
this.collectInputTextBox = this.collectInputTextBox.bind(this);
|
||||
const validServer = withValidation({
|
||||
rules: [
|
||||
{
|
||||
key: "required",
|
||||
test: async ({ value }) => !!value,
|
||||
invalid: () => _t("Enter a server name"),
|
||||
}, {
|
||||
key: "available",
|
||||
final: true,
|
||||
test: async ({ value }) => {
|
||||
try {
|
||||
const opts = {
|
||||
limit: 1,
|
||||
server: value,
|
||||
};
|
||||
// check if we can successfully load this server's room directory
|
||||
await MatrixClientPeg.get().publicRooms(opts);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
valid: () => _t("Looks good"),
|
||||
invalid: () => _t("Can't find this server or its room list"),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
this.inputTextBox = null;
|
||||
// This dropdown sources homeservers from three places:
|
||||
// + your currently connected homeserver
|
||||
// + homeservers in config.json["roomDirectory"]
|
||||
// + homeservers in SettingsStore["room_directory_servers"]
|
||||
// if a server exists in multiple, only keep the top-most entry.
|
||||
|
||||
const server = MatrixClientPeg.getHomeserverName();
|
||||
this.state = {
|
||||
expanded: false,
|
||||
selectedServer: server,
|
||||
selectedInstanceId: null,
|
||||
includeAllNetworks: false,
|
||||
const NetworkDropdown = ({onOptionChange, protocols = {}, selectedServerName, selectedInstanceId}) => {
|
||||
const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu();
|
||||
const _userDefinedServers = useSettingValue(SETTING_NAME);
|
||||
const [userDefinedServers, _setUserDefinedServers] = useState(_userDefinedServers);
|
||||
|
||||
const handlerFactory = (server, instanceId) => {
|
||||
return () => {
|
||||
onOptionChange(server, instanceId);
|
||||
closeMenu();
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
componentWillMount() {
|
||||
// Listen for all clicks on the document so we can close the
|
||||
// menu when the user clicks somewhere else
|
||||
document.addEventListener('click', this.onDocumentClick, false);
|
||||
const setUserDefinedServers = servers => {
|
||||
_setUserDefinedServers(servers);
|
||||
SettingsStore.setValue(SETTING_NAME, null, "account", servers);
|
||||
};
|
||||
// keep local echo up to date with external changes
|
||||
useEffect(() => {
|
||||
_setUserDefinedServers(_userDefinedServers);
|
||||
}, [_userDefinedServers]);
|
||||
|
||||
// fire this now so the defaults can be set up
|
||||
const {selectedServer, selectedInstanceId, includeAllNetworks} = this.state;
|
||||
this.props.onOptionChange(selectedServer, selectedInstanceId, includeAllNetworks);
|
||||
}
|
||||
// we either show the button or the dropdown in its place.
|
||||
let content;
|
||||
if (menuDisplayed) {
|
||||
const config = SdkConfig.get();
|
||||
const roomDirectory = config.roomDirectory || {};
|
||||
|
||||
componentWillUnmount() {
|
||||
document.removeEventListener('click', this.onDocumentClick, false);
|
||||
}
|
||||
const hsName = MatrixClientPeg.getHomeserverName();
|
||||
const configServers = new Set(roomDirectory.servers);
|
||||
|
||||
componentDidUpdate() {
|
||||
if (this.state.expanded && this.inputTextBox) {
|
||||
this.inputTextBox.focus();
|
||||
}
|
||||
}
|
||||
|
||||
onDocumentClick(ev) {
|
||||
// Close the dropdown if the user clicks anywhere that isn't
|
||||
// within our root element
|
||||
if (ev !== this.ignoreEvent) {
|
||||
this.setState({
|
||||
expanded: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onRootClick(ev) {
|
||||
// This captures any clicks that happen within our elements,
|
||||
// such that we can then ignore them when they're seen by the
|
||||
// click listener on the document handler, ie. not close the
|
||||
// dropdown immediately after opening it.
|
||||
// NB. We can't just stopPropagation() because then the event
|
||||
// doesn't reach the React onClick().
|
||||
this.ignoreEvent = ev;
|
||||
}
|
||||
|
||||
onInputClick(ev) {
|
||||
this.setState({
|
||||
expanded: !this.state.expanded,
|
||||
});
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
onMenuOptionClick(server, instance, includeAll) {
|
||||
this.setState({
|
||||
expanded: false,
|
||||
selectedServer: server,
|
||||
selectedInstanceId: instance ? instance.instance_id : null,
|
||||
includeAllNetworks: includeAll,
|
||||
});
|
||||
this.props.onOptionChange(server, instance ? instance.instance_id : null, includeAll);
|
||||
}
|
||||
|
||||
onInputKeyUp(e) {
|
||||
if (e.key === 'Enter') {
|
||||
this.setState({
|
||||
expanded: false,
|
||||
selectedServer: e.target.value,
|
||||
selectedNetwork: null,
|
||||
includeAllNetworks: false,
|
||||
});
|
||||
this.props.onOptionChange(e.target.value, null);
|
||||
}
|
||||
}
|
||||
|
||||
collectRoot(e) {
|
||||
if (this.dropdownRootElement) {
|
||||
this.dropdownRootElement.removeEventListener('click', this.onRootClick, false);
|
||||
}
|
||||
if (e) {
|
||||
e.addEventListener('click', this.onRootClick, false);
|
||||
}
|
||||
this.dropdownRootElement = e;
|
||||
}
|
||||
|
||||
collectInputTextBox(e) {
|
||||
this.inputTextBox = e;
|
||||
}
|
||||
|
||||
_getMenuOptions() {
|
||||
const options = [];
|
||||
const roomDirectory = this.props.config.roomDirectory || {};
|
||||
|
||||
let servers = [];
|
||||
if (roomDirectory.servers) {
|
||||
servers = servers.concat(roomDirectory.servers);
|
||||
}
|
||||
|
||||
if (!servers.includes(MatrixClientPeg.getHomeserverName())) {
|
||||
servers.unshift(MatrixClientPeg.getHomeserverName());
|
||||
}
|
||||
// configured servers take preference over user-defined ones, if one occurs in both ignore the latter one.
|
||||
const removableServers = new Set(userDefinedServers.filter(s => !configServers.has(s) && s !== hsName));
|
||||
const servers = [
|
||||
// we always show our connected HS, this takes precedence over it being configured or user-defined
|
||||
hsName,
|
||||
...Array.from(configServers).filter(s => s !== hsName).sort(),
|
||||
...Array.from(removableServers).sort(),
|
||||
];
|
||||
|
||||
// For our own HS, we can use the instance_ids given in the third party protocols
|
||||
// response to get the server to filter the room list by network for us.
|
||||
// We can't get thirdparty protocols for remote server yet though, so for those
|
||||
// we can only show the default room list.
|
||||
for (const server of servers) {
|
||||
options.push(this._makeMenuOption(server, null, true));
|
||||
if (server === MatrixClientPeg.getHomeserverName()) {
|
||||
options.push(this._makeMenuOption(server, null, false));
|
||||
if (this.props.protocols) {
|
||||
for (const proto of Object.keys(this.props.protocols)) {
|
||||
if (!this.props.protocols[proto].instances) continue;
|
||||
const options = servers.map(server => {
|
||||
const serverSelected = server === selectedServerName;
|
||||
const entries = [];
|
||||
|
||||
const sortedInstances = this.props.protocols[proto].instances;
|
||||
sortedInstances.sort(function(x, y) {
|
||||
const a = x.desc;
|
||||
const b = y.desc;
|
||||
if (a < b) {
|
||||
return -1;
|
||||
} else if (a > b) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
for (const instance of sortedInstances) {
|
||||
if (!instance.instance_id) continue;
|
||||
options.push(this._makeMenuOption(server, instance, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
const protocolsList = server === hsName ? Object.values(protocols) : [];
|
||||
if (protocolsList.length > 0) {
|
||||
// add a fake protocol with the ALL_ROOMS symbol
|
||||
protocolsList.push({
|
||||
instances: [{
|
||||
instance_id: ALL_ROOMS,
|
||||
desc: _t("All rooms"),
|
||||
}],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
protocolsList.forEach(({instances=[]}) => {
|
||||
[...instances].sort((b, a) => {
|
||||
return a.desc.localeCompare(b.desc);
|
||||
}).forEach(({desc, instance_id: instanceId}) => {
|
||||
entries.push(
|
||||
<MenuItemRadio
|
||||
key={String(instanceId)}
|
||||
active={serverSelected && instanceId === selectedInstanceId}
|
||||
onClick={handlerFactory(server, instanceId)}
|
||||
label={desc}
|
||||
className="mx_NetworkDropdown_server_network"
|
||||
>
|
||||
{ desc }
|
||||
</MenuItemRadio>);
|
||||
});
|
||||
});
|
||||
|
||||
_makeMenuOption(server, instance, includeAll, handleClicks) {
|
||||
if (handleClicks === undefined) handleClicks = true;
|
||||
let subtitle;
|
||||
if (server === hsName) {
|
||||
subtitle = (
|
||||
<div className="mx_NetworkDropdown_server_subtitle">
|
||||
{_t("Your server")}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
let icon;
|
||||
let name;
|
||||
let key;
|
||||
let removeButton;
|
||||
if (removableServers.has(server)) {
|
||||
const onClick = async () => {
|
||||
closeMenu();
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
const {finished} = Modal.createTrackedDialog("Network Dropdown", "Remove server", QuestionDialog, {
|
||||
title: _t("Are you sure?"),
|
||||
description: _t("Are you sure you want to remove <b>%(serverName)s</b>", {
|
||||
serverName: server,
|
||||
}, {
|
||||
b: serverName => <b>{ serverName }</b>,
|
||||
}),
|
||||
button: _t("Remove"),
|
||||
fixedWidth: false,
|
||||
}, "mx_NetworkDropdown_dialog");
|
||||
|
||||
if (!instance && includeAll) {
|
||||
key = server;
|
||||
name = server;
|
||||
} else if (!instance) {
|
||||
key = server + '_all';
|
||||
name = 'Matrix';
|
||||
icon = <img src={require("../../../../res/img/network-matrix.svg")} />;
|
||||
} else {
|
||||
key = server + '_inst_' + instance.instance_id;
|
||||
const imgUrl = instance.icon ?
|
||||
MatrixClientPeg.get().mxcUrlToHttp(instance.icon, 25, 25, 'crop', true) :
|
||||
DEFAULT_ICON_URL;
|
||||
icon = <img src={imgUrl} />;
|
||||
name = instance.desc;
|
||||
}
|
||||
const [ok] = await finished;
|
||||
if (!ok) return;
|
||||
|
||||
const clickHandler = handleClicks ? this.onMenuOptionClick.bind(this, server, instance, includeAll) : null;
|
||||
// delete from setting
|
||||
setUserDefinedServers(servers.filter(s => s !== server));
|
||||
|
||||
return <div key={key} className="mx_NetworkDropdown_networkoption" onClick={clickHandler}>
|
||||
{icon}
|
||||
<span className="mx_NetworkDropdown_menu_network">{name}</span>
|
||||
</div>;
|
||||
}
|
||||
// the selected server is being removed, reset to our HS
|
||||
if (serverSelected === server) {
|
||||
onOptionChange(hsName, undefined);
|
||||
}
|
||||
};
|
||||
removeButton = <MenuItem onClick={onClick} label={_t("Remove server")} />;
|
||||
}
|
||||
|
||||
render() {
|
||||
let currentValue;
|
||||
// ARIA: in actual fact the entire menu is one large radio group but for better screen reader support
|
||||
// we use group to notate server wrongly.
|
||||
return (
|
||||
<MenuGroup label={server} className="mx_NetworkDropdown_server" key={server}>
|
||||
<div className="mx_NetworkDropdown_server_title">
|
||||
{ server }
|
||||
{ removeButton }
|
||||
</div>
|
||||
{ subtitle }
|
||||
|
||||
let menu;
|
||||
if (this.state.expanded) {
|
||||
const menuOptions = this._getMenuOptions();
|
||||
menu = <div className="mx_NetworkDropdown_menu">
|
||||
{menuOptions}
|
||||
</div>;
|
||||
currentValue = <input type="text" className="mx_NetworkDropdown_networkoption"
|
||||
ref={this.collectInputTextBox} onKeyUp={this.onInputKeyUp}
|
||||
placeholder="matrix.org" // 'matrix.org' as an example of an HS name
|
||||
/>;
|
||||
} else {
|
||||
const instance = instanceForInstanceId(this.props.protocols, this.state.selectedInstanceId);
|
||||
currentValue = this._makeMenuOption(
|
||||
this.state.selectedServer, instance, this.state.includeAllNetworks, false,
|
||||
<MenuItemRadio
|
||||
active={serverSelected && !selectedInstanceId}
|
||||
onClick={handlerFactory(server, undefined)}
|
||||
label={_t("Matrix")}
|
||||
className="mx_NetworkDropdown_server_network"
|
||||
>
|
||||
{_t("Matrix")}
|
||||
</MenuItemRadio>
|
||||
{ entries }
|
||||
</MenuGroup>
|
||||
);
|
||||
});
|
||||
|
||||
const onClick = async () => {
|
||||
closeMenu();
|
||||
const TextInputDialog = sdk.getComponent("dialogs.TextInputDialog");
|
||||
const { finished } = Modal.createTrackedDialog("Network Dropdown", "Add a new server", TextInputDialog, {
|
||||
title: _t("Add a new server"),
|
||||
description: _t("Enter the name of a new server you want to explore."),
|
||||
button: _t("Add"),
|
||||
hasCancel: false,
|
||||
placeholder: _t("Server name"),
|
||||
validator: validServer,
|
||||
fixedWidth: false,
|
||||
}, "mx_NetworkDropdown_dialog");
|
||||
|
||||
const [ok, newServer] = await finished;
|
||||
if (!ok) return;
|
||||
|
||||
if (!userDefinedServers.includes(newServer)) {
|
||||
setUserDefinedServers([...userDefinedServers, newServer]);
|
||||
}
|
||||
|
||||
onOptionChange(newServer); // change filter to the new server
|
||||
};
|
||||
|
||||
const buttonRect = handle.current.getBoundingClientRect();
|
||||
content = <ContextMenu {...inPlaceOf(buttonRect)} onFinished={closeMenu}>
|
||||
<div className="mx_NetworkDropdown_menu">
|
||||
{options}
|
||||
<MenuItem className="mx_NetworkDropdown_server_add" label={undefined} onClick={onClick}>
|
||||
{_t("Add a new server...")}
|
||||
</MenuItem>
|
||||
</div>
|
||||
</ContextMenu>;
|
||||
} else {
|
||||
let currentValue;
|
||||
if (selectedInstanceId === ALL_ROOMS) {
|
||||
currentValue = _t("All rooms");
|
||||
} else if (selectedInstanceId) {
|
||||
const instance = instanceForInstanceId(protocols, selectedInstanceId);
|
||||
currentValue = _t("%(networkName)s rooms", {
|
||||
networkName: instance.desc,
|
||||
});
|
||||
} else {
|
||||
currentValue = _t("Matrix rooms");
|
||||
}
|
||||
|
||||
return <div className="mx_NetworkDropdown" ref={this.collectRoot}>
|
||||
<div className="mx_NetworkDropdown_input mx_no_textinput" onClick={this.onInputClick}>
|
||||
content = <ContextMenuButton
|
||||
className="mx_NetworkDropdown_handle"
|
||||
onClick={openMenu}
|
||||
isExpanded={menuDisplayed}
|
||||
>
|
||||
<span>
|
||||
{currentValue}
|
||||
<span className="mx_NetworkDropdown_arrow" />
|
||||
{menu}
|
||||
</div>
|
||||
</div>;
|
||||
</span> <span className="mx_NetworkDropdown_handle_server">
|
||||
({selectedServerName})
|
||||
</span>
|
||||
</ContextMenuButton>;
|
||||
}
|
||||
}
|
||||
|
||||
return <div className="mx_NetworkDropdown" ref={handle}>
|
||||
{content}
|
||||
</div>;
|
||||
};
|
||||
|
||||
NetworkDropdown.propTypes = {
|
||||
onOptionChange: PropTypes.func.isRequired,
|
||||
protocols: PropTypes.object,
|
||||
// The room directory config. May have a 'servers' key that is a list of server names to include in the dropdown
|
||||
config: PropTypes.object,
|
||||
};
|
||||
|
||||
NetworkDropdown.defaultProps = {
|
||||
protocols: {},
|
||||
config: {},
|
||||
};
|
||||
export default NetworkDropdown;
|
||||
|
|
|
@ -78,8 +78,7 @@ export class EditableItem extends React.Component {
|
|||
|
||||
return (
|
||||
<div className="mx_EditableItem">
|
||||
<img src={require("../../../../res/img/feather-customised/cancel.svg")} width={14} height={14}
|
||||
onClick={this._onRemove} className="mx_EditableItem_delete" alt={_t("Remove")} />
|
||||
<div onClick={this._onRemove} className="mx_EditableItem_delete" title={_t("Remove")} role="button" />
|
||||
<span className="mx_EditableItem_item">{this.props.value}</span>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 New Vector Ltd.
|
||||
|
||||
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 GeminiScrollbar from 'react-gemini-scrollbar';
|
||||
|
||||
function GeminiScrollbarWrapper(props) {
|
||||
const {wrappedRef, ...wrappedProps} = props;
|
||||
|
||||
// Enable forceGemini so that gemini is always enabled. This is
|
||||
// to avoid future issues where a feature is implemented without
|
||||
// doing QA on every OS/browser combination.
|
||||
//
|
||||
// By default GeminiScrollbar allows native scrollbars to be used
|
||||
// on macOS. Use forceGemini to enable Gemini's non-native
|
||||
// scrollbars on all OSs.
|
||||
return <GeminiScrollbar ref={wrappedRef} forceGemini={true} {...wrappedProps}>
|
||||
{ props.children }
|
||||
</GeminiScrollbar>;
|
||||
}
|
||||
export default GeminiScrollbarWrapper;
|
||||
|
|
@ -27,6 +27,7 @@ import { GroupMemberType } from '../../../groups';
|
|||
import GroupStore from '../../../stores/GroupStore';
|
||||
import AccessibleButton from '../elements/AccessibleButton';
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
|
||||
|
||||
export default createReactClass({
|
||||
displayName: 'GroupMemberInfo',
|
||||
|
@ -182,10 +183,9 @@ export default createReactClass({
|
|||
this.props.groupMember.displayname || this.props.groupMember.userId
|
||||
);
|
||||
|
||||
const GeminiScrollbarWrapper = sdk.getComponent('elements.GeminiScrollbarWrapper');
|
||||
return (
|
||||
<div className="mx_MemberInfo" role="tabpanel">
|
||||
<GeminiScrollbarWrapper autoshow={true}>
|
||||
<AutoHideScrollbar>
|
||||
<AccessibleButton className="mx_MemberInfo_cancel" onClick={this._onCancel}>
|
||||
<img src={require("../../../../res/img/cancel.svg")} width="18" height="18" className="mx_filterFlipColor" />
|
||||
</AccessibleButton>
|
||||
|
@ -199,7 +199,7 @@ export default createReactClass({
|
|||
</div>
|
||||
|
||||
{ adminTools }
|
||||
</GeminiScrollbarWrapper>
|
||||
</AutoHideScrollbar>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -26,6 +26,7 @@ import { showGroupInviteDialog } from '../../../GroupAddressPicker';
|
|||
import AccessibleButton from '../elements/AccessibleButton';
|
||||
import TintableSvg from '../elements/TintableSvg';
|
||||
import {RIGHT_PANEL_PHASES} from "../../../stores/RightPanelStorePhases";
|
||||
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
|
||||
|
||||
const INITIAL_LOAD_NUM_MEMBERS = 30;
|
||||
|
||||
|
@ -172,7 +173,6 @@ export default createReactClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
|
||||
if (this.state.fetching || this.state.fetchingInvitedMembers) {
|
||||
const Spinner = sdk.getComponent("elements.Spinner");
|
||||
return (<div className="mx_MemberList">
|
||||
|
@ -225,10 +225,10 @@ export default createReactClass({
|
|||
return (
|
||||
<div className="mx_MemberList" role="tabpanel">
|
||||
{ inviteButton }
|
||||
<GeminiScrollbarWrapper autoshow={true}>
|
||||
<AutoHideScrollbar>
|
||||
{ joined }
|
||||
{ invited }
|
||||
</GeminiScrollbarWrapper>
|
||||
</AutoHideScrollbar>
|
||||
{ inputBox }
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -24,6 +24,7 @@ import * as sdk from '../../../index';
|
|||
import { _t } from '../../../languageHandler';
|
||||
import GroupStore from '../../../stores/GroupStore';
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
|
||||
|
||||
export default createReactClass({
|
||||
displayName: 'GroupRoomInfo',
|
||||
|
@ -153,7 +154,6 @@ export default createReactClass({
|
|||
render: function() {
|
||||
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
||||
const InlineSpinner = sdk.getComponent('elements.InlineSpinner');
|
||||
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
|
||||
if (this.state.groupRoomRemoveLoading || !this.state.groupRoom) {
|
||||
const Spinner = sdk.getComponent("elements.Spinner");
|
||||
return <div className="mx_MemberInfo">
|
||||
|
@ -216,7 +216,7 @@ export default createReactClass({
|
|||
const groupRoomName = this.state.groupRoom.displayname;
|
||||
return (
|
||||
<div className="mx_MemberInfo" role="tabpanel">
|
||||
<GeminiScrollbarWrapper autoshow={true}>
|
||||
<AutoHideScrollbar>
|
||||
<AccessibleButton className="mx_MemberInfo_cancel" onClick={this._onCancel}>
|
||||
<img src={require("../../../../res/img/cancel.svg")} width="18" height="18" className="mx_filterFlipColor" />
|
||||
</AccessibleButton>
|
||||
|
@ -231,7 +231,7 @@ export default createReactClass({
|
|||
</div>
|
||||
|
||||
{ adminTools }
|
||||
</GeminiScrollbarWrapper>
|
||||
</AutoHideScrollbar>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -22,6 +22,7 @@ import PropTypes from 'prop-types';
|
|||
import { showGroupAddRoomDialog } from '../../../GroupAddressPicker';
|
||||
import AccessibleButton from '../elements/AccessibleButton';
|
||||
import TintableSvg from '../elements/TintableSvg';
|
||||
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
|
||||
|
||||
const INITIAL_LOAD_NUM_ROOMS = 30;
|
||||
|
||||
|
@ -150,17 +151,16 @@ export default createReactClass({
|
|||
placeholder={_t('Filter community rooms')} autoComplete="off" />
|
||||
);
|
||||
|
||||
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
|
||||
const TruncatedList = sdk.getComponent("elements.TruncatedList");
|
||||
return (
|
||||
<div className="mx_GroupRoomList" role="tabpanel">
|
||||
{ inviteButton }
|
||||
<GeminiScrollbarWrapper autoshow={true} className="mx_GroupRoomList_joined mx_GroupRoomList_outerWrapper">
|
||||
<AutoHideScrollbar className="mx_GroupRoomList_joined mx_GroupRoomList_outerWrapper">
|
||||
<TruncatedList className="mx_GroupRoomList_wrapper" truncateAt={this.state.truncateAt}
|
||||
createOverflowElement={this._createOverflowTile}>
|
||||
{ this.makeGroupRoomTiles(this.state.searchQuery) }
|
||||
</TruncatedList>
|
||||
</GeminiScrollbarWrapper>
|
||||
</AutoHideScrollbar>
|
||||
{ inputBox }
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -25,6 +25,7 @@ import Field from "../elements/Field";
|
|||
import ErrorDialog from "../dialogs/ErrorDialog";
|
||||
import AccessibleButton from "../elements/AccessibleButton";
|
||||
import Modal from "../../../Modal";
|
||||
import RoomPublishSetting from "./RoomPublishSetting";
|
||||
|
||||
class EditableAliasesList extends EditableItemList {
|
||||
constructor(props) {
|
||||
|
@ -97,6 +98,7 @@ export default class AliasSettings extends React.Component {
|
|||
canonicalAlias: null, // #canonical:domain.tld
|
||||
updatingCanonicalAlias: false,
|
||||
localAliasesLoading: false,
|
||||
detailsOpen: false,
|
||||
};
|
||||
|
||||
if (props.canonicalAliasEvent) {
|
||||
|
@ -234,8 +236,7 @@ export default class AliasSettings extends React.Component {
|
|||
// TODO: In future, we should probably be making sure that the alias actually belongs
|
||||
// to this room. See https://github.com/vector-im/riot-web/issues/7353
|
||||
MatrixClientPeg.get().deleteAlias(alias).then(() => {
|
||||
const localAliases = this.state.localAliases.slice();
|
||||
localAliases.splice(index);
|
||||
const localAliases = this.state.localAliases.filter(a => a !== alias);
|
||||
this.setState({localAliases});
|
||||
|
||||
if (this.state.canonicalAlias === alias) {
|
||||
|
@ -243,12 +244,18 @@ export default class AliasSettings extends React.Component {
|
|||
}
|
||||
}).catch((err) => {
|
||||
console.error(err);
|
||||
Modal.createTrackedDialog('Error removing alias', '', ErrorDialog, {
|
||||
title: _t("Error removing alias"),
|
||||
description: _t(
|
||||
let description;
|
||||
if (err.errcode === "M_FORBIDDEN") {
|
||||
description = _t("You don't have permission to delete the alias.");
|
||||
} else {
|
||||
description = _t(
|
||||
"There was an error removing that alias. It may no longer exist or a temporary " +
|
||||
"error occurred.",
|
||||
),
|
||||
);
|
||||
}
|
||||
Modal.createTrackedDialog('Error removing alias', '', ErrorDialog, {
|
||||
title: _t("Error removing alias"),
|
||||
description,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -261,6 +268,7 @@ export default class AliasSettings extends React.Component {
|
|||
this.loadLocalAliases();
|
||||
}
|
||||
}
|
||||
this.setState({detailsOpen: event.target.open});
|
||||
};
|
||||
|
||||
onCanonicalAliasChange = (event) => {
|
||||
|
@ -340,16 +348,18 @@ export default class AliasSettings extends React.Component {
|
|||
onItemAdded={this.onLocalAliasAdded}
|
||||
onItemRemoved={this.onLocalAliasDeleted}
|
||||
noItemsLabel={_t('This room has no local addresses')}
|
||||
placeholder={_t(
|
||||
'New address (e.g. #foo:%(localDomain)s)', {localDomain: localDomain},
|
||||
)}
|
||||
placeholder={_t('Local address')}
|
||||
domain={localDomain}
|
||||
/>);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='mx_AliasSettings'>
|
||||
<span className='mx_SettingsTab_subheading'>{_t("Published Addresses")}</span>
|
||||
<p>{_t("Published addresses can be used by anyone on any server to join your room. " +
|
||||
"To publish an address, it needs to be set as a local address first.")}</p>
|
||||
{canonicalAliasSection}
|
||||
<RoomPublishSetting roomId={this.props.roomId} canSetCanonicalAlias={this.props.canSetCanonicalAlias} />
|
||||
<datalist id="mx_AliasSettings_altRecommendations">
|
||||
{this._getLocalNonAltAliases().map(alias => {
|
||||
return <option value={alias} key={alias} />;
|
||||
|
@ -366,14 +376,14 @@ export default class AliasSettings extends React.Component {
|
|||
onItemAdded={this.onAltAliasAdded}
|
||||
onItemRemoved={this.onAltAliasDeleted}
|
||||
suggestionsListId="mx_AliasSettings_altRecommendations"
|
||||
itemsLabel={_t('Alternative addresses for this room:')}
|
||||
noItemsLabel={_t('This room has no alternative addresses')}
|
||||
placeholder={_t(
|
||||
'New address (e.g. #foo:domain)',
|
||||
)}
|
||||
itemsLabel={_t('Other published addresses:')}
|
||||
noItemsLabel={_t('No other published addresses yet, add one below')}
|
||||
placeholder={_t('New published address (e.g. #alias:server)')}
|
||||
/>
|
||||
<span className='mx_SettingsTab_subheading mx_AliasSettings_localAliasHeader'>{_t("Local Addresses")}</span>
|
||||
<p>{_t("Set addresses for this room so users can find this room through your homeserver (%(localDomain)s)", {localDomain})}</p>
|
||||
<details onToggle={this.onLocalAliasesToggled}>
|
||||
<summary>{_t('Local addresses (unmoderated content)')}</summary>
|
||||
<summary>{ this.state.detailsOpen ? _t('Show less') : _t("Show more")}</summary>
|
||||
{localAliasesList}
|
||||
</details>
|
||||
</div>
|
||||
|
|
60
src/components/views/room_settings/RoomPublishSetting.js
Normal file
60
src/components/views/room_settings/RoomPublishSetting.js
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
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 LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
|
||||
import {_t} from "../../../languageHandler";
|
||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||
|
||||
export default class RoomPublishSetting extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {isRoomPublished: false};
|
||||
}
|
||||
|
||||
onRoomPublishChange = (e) => {
|
||||
const valueBefore = this.state.isRoomPublished;
|
||||
const newValue = !valueBefore;
|
||||
this.setState({isRoomPublished: newValue});
|
||||
const client = MatrixClientPeg.get();
|
||||
|
||||
client.setRoomDirectoryVisibility(
|
||||
this.props.roomId,
|
||||
newValue ? 'public' : 'private',
|
||||
).catch(() => {
|
||||
// Roll back the local echo on the change
|
||||
this.setState({isRoomPublished: valueBefore});
|
||||
});
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const client = MatrixClientPeg.get();
|
||||
client.getRoomDirectoryVisibility(this.props.roomId).then((result => {
|
||||
this.setState({isRoomPublished: result.visibility === 'public'});
|
||||
}));
|
||||
}
|
||||
|
||||
render() {
|
||||
const client = MatrixClientPeg.get();
|
||||
|
||||
return (<LabelledToggleSwitch value={this.state.isRoomPublished}
|
||||
onChange={this.onRoomPublishChange}
|
||||
disabled={!this.props.canSetCanonicalAlias}
|
||||
label={_t("Publish this room to the public in %(domain)s's room directory?", {
|
||||
domain: client.getDomain(),
|
||||
})} />);
|
||||
}
|
||||
}
|
|
@ -370,6 +370,16 @@ export default class BasicMessageEditor extends React.Component {
|
|||
} else if (modKey && event.key === Key.GREATER_THAN) {
|
||||
this._onFormatAction("quote");
|
||||
handled = true;
|
||||
// redo
|
||||
} else if ((!IS_MAC && modKey && event.key === Key.Y) ||
|
||||
(IS_MAC && modKey && event.shiftKey && event.key === Key.Z)) {
|
||||
if (this.historyManager.canRedo()) {
|
||||
const {parts, caret} = this.historyManager.redo();
|
||||
// pass matching inputType so historyManager doesn't push echo
|
||||
// when invoked from rerender callback.
|
||||
model.reset(parts, caret, "historyRedo");
|
||||
}
|
||||
handled = true;
|
||||
// undo
|
||||
} else if (modKey && event.key === Key.Z) {
|
||||
if (this.historyManager.canUndo()) {
|
||||
|
@ -379,15 +389,6 @@ export default class BasicMessageEditor extends React.Component {
|
|||
model.reset(parts, caret, "historyUndo");
|
||||
}
|
||||
handled = true;
|
||||
// redo
|
||||
} else if (modKey && event.key === Key.Y) {
|
||||
if (this.historyManager.canRedo()) {
|
||||
const {parts, caret} = this.historyManager.redo();
|
||||
// pass matching inputType so historyManager doesn't push echo
|
||||
// when invoked from rerender callback.
|
||||
model.reset(parts, caret, "historyRedo");
|
||||
}
|
||||
handled = true;
|
||||
// insert newline on Shift+Enter
|
||||
} else if (event.key === Key.ENTER && (event.shiftKey || (IS_MAC && event.altKey))) {
|
||||
this._insertText("\n");
|
||||
|
|
|
@ -33,7 +33,6 @@ export default createReactClass({
|
|||
componentWillMount: function() {
|
||||
dis.dispatch({
|
||||
action: 'panel_disable',
|
||||
rightDisabled: true,
|
||||
middleDisabled: true,
|
||||
});
|
||||
},
|
||||
|
@ -45,7 +44,6 @@ export default createReactClass({
|
|||
componentWillUnmount: function() {
|
||||
dis.dispatch({
|
||||
action: 'panel_disable',
|
||||
sideDisabled: false,
|
||||
middleDisabled: false,
|
||||
});
|
||||
document.removeEventListener('keydown', this._onKeyDown);
|
||||
|
|
|
@ -24,7 +24,7 @@ export default (props) => {
|
|||
}
|
||||
return (<div className="mx_JumpToBottomButton">
|
||||
<AccessibleButton className="mx_JumpToBottomButton_scrollDown"
|
||||
title={_t("Scroll to bottom of page")}
|
||||
title={_t("Scroll to most recent messages")}
|
||||
onClick={props.onScrollToBottomClick}>
|
||||
</AccessibleButton>
|
||||
{ badge }
|
||||
|
|
|
@ -178,6 +178,7 @@ export default class MessageComposer extends React.Component {
|
|||
isQuoting: Boolean(RoomViewStore.getQuotingEvent()),
|
||||
tombstone: this._getRoomTombstone(),
|
||||
canSendMessages: this.props.room.maySendMessage(),
|
||||
showCallButtons: SettingsStore.getValue("showCallButtonsInComposer"),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -325,10 +326,20 @@ export default class MessageComposer extends React.Component {
|
|||
permalinkCreator={this.props.permalinkCreator} />,
|
||||
<Stickerpicker key='stickerpicker_controls_button' room={this.props.room} />,
|
||||
<UploadButton key="controls_upload" roomId={this.props.room.roomId} />,
|
||||
callInProgress ? <HangupButton key="controls_hangup" roomId={this.props.room.roomId} /> : null,
|
||||
callInProgress ? null : <CallButton key="controls_call" roomId={this.props.room.roomId} />,
|
||||
callInProgress ? null : <VideoCallButton key="controls_videocall" roomId={this.props.room.roomId} />,
|
||||
);
|
||||
|
||||
if (this.state.showCallButtons) {
|
||||
if (callInProgress) {
|
||||
controls.push(
|
||||
<HangupButton key="controls_hangup" roomId={this.props.room.roomId} />,
|
||||
);
|
||||
} else {
|
||||
controls.push(
|
||||
<CallButton key="controls_call" roomId={this.props.room.roomId} />,
|
||||
<VideoCallButton key="controls_videocall" roomId={this.props.room.roomId} />,
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if (this.state.tombstone) {
|
||||
const replacementRoomId = this.state.tombstone.getContent()['replacement_room'];
|
||||
|
||||
|
|
|
@ -780,7 +780,7 @@ export default createReactClass({
|
|||
aria-label={_t("Rooms")}
|
||||
// Firefox sometimes makes this element focusable due to
|
||||
// overflow:scroll;, so force it out of tab order.
|
||||
tabindex="-1"
|
||||
tabIndex="-1"
|
||||
onMouseMove={this.onMouseMove}
|
||||
onMouseLeave={this.onMouseLeave}
|
||||
>
|
||||
|
|
|
@ -1,186 +0,0 @@
|
|||
/*
|
||||
Copyright 2015, 2016 OpenMarket Ltd
|
||||
Copyright 2019 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
import * as sdk from "../../../index";
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
||||
// A list capable of displaying entities which conform to the SearchableEntity
|
||||
// interface which is an object containing getJsx(): Jsx and matches(query: string): boolean
|
||||
const SearchableEntityList = createReactClass({
|
||||
displayName: 'SearchableEntityList',
|
||||
|
||||
propTypes: {
|
||||
emptyQueryShowsAll: PropTypes.bool,
|
||||
showInputBox: PropTypes.bool,
|
||||
onQueryChanged: PropTypes.func, // fn(inputText)
|
||||
onSubmit: PropTypes.func, // fn(inputText)
|
||||
entities: PropTypes.array,
|
||||
truncateAt: PropTypes.number,
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
showInputBox: true,
|
||||
entities: [],
|
||||
emptyQueryShowsAll: false,
|
||||
onSubmit: function() {},
|
||||
onQueryChanged: function(input) {},
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
query: "",
|
||||
focused: false,
|
||||
truncateAt: this.props.truncateAt,
|
||||
results: this.getSearchResults("", this.props.entities),
|
||||
};
|
||||
},
|
||||
|
||||
componentWillReceiveProps: function(newProps) {
|
||||
// recalculate the search results in case we got new entities
|
||||
this.setState({
|
||||
results: this.getSearchResults(this.state.query, newProps.entities),
|
||||
});
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
// pretend the query box was blanked out else filters could still be
|
||||
// applied to other components which rely on onQueryChanged.
|
||||
this.props.onQueryChanged("");
|
||||
},
|
||||
|
||||
/**
|
||||
* Public-facing method to set the input query text to the given input.
|
||||
* @param {string} input
|
||||
*/
|
||||
setQuery: function(input) {
|
||||
this.setState({
|
||||
query: input,
|
||||
results: this.getSearchResults(input, this.props.entities),
|
||||
});
|
||||
},
|
||||
|
||||
onQueryChanged: function(ev) {
|
||||
const q = ev.target.value;
|
||||
this.setState({
|
||||
query: q,
|
||||
// reset truncation if they back out the entire text
|
||||
truncateAt: (q.length === 0 ? this.props.truncateAt : this.state.truncateAt),
|
||||
results: this.getSearchResults(q, this.props.entities),
|
||||
}, () => {
|
||||
// invoke the callback AFTER we've flushed the new state. We need to
|
||||
// do this because onQueryChanged can result in new props being passed
|
||||
// to this component, which will then try to recalculate the search
|
||||
// list. If we do this without flushing, we'll recalc with the last
|
||||
// search term and not the current one!
|
||||
this.props.onQueryChanged(q);
|
||||
});
|
||||
},
|
||||
|
||||
onQuerySubmit: function(ev) {
|
||||
ev.preventDefault();
|
||||
this.props.onSubmit(this.state.query);
|
||||
},
|
||||
|
||||
getSearchResults: function(query, entities) {
|
||||
if (!query || query.length === 0) {
|
||||
return this.props.emptyQueryShowsAll ? entities : [];
|
||||
}
|
||||
return entities.filter(function(e) {
|
||||
return e.matches(query);
|
||||
});
|
||||
},
|
||||
|
||||
_showAll: function() {
|
||||
this.setState({
|
||||
truncateAt: -1,
|
||||
});
|
||||
},
|
||||
|
||||
_createOverflowEntity: function(overflowCount, totalCount) {
|
||||
const EntityTile = sdk.getComponent("rooms.EntityTile");
|
||||
const BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
|
||||
const text = _t("and %(count)s others...", { count: overflowCount });
|
||||
return (
|
||||
<EntityTile className="mx_EntityTile_ellipsis" avatarJsx={
|
||||
<BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} />
|
||||
} name={text} presenceState="online" suppressOnHover={true}
|
||||
onClick={this._showAll} />
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
let inputBox;
|
||||
|
||||
if (this.props.showInputBox) {
|
||||
inputBox = (
|
||||
<form onSubmit={this.onQuerySubmit} autoComplete="off">
|
||||
<input className="mx_SearchableEntityList_query" id="mx_SearchableEntityList_query" type="text"
|
||||
onChange={this.onQueryChanged} value={this.state.query}
|
||||
onFocus= {() => { this.setState({ focused: true }); }}
|
||||
onBlur= {() => { this.setState({ focused: false }); }}
|
||||
placeholder={_t("Search")} />
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
let list;
|
||||
if (this.state.results.length > 1 || this.state.focused) {
|
||||
if (this.props.truncateAt) { // caller wants list truncated
|
||||
const TruncatedList = sdk.getComponent("elements.TruncatedList");
|
||||
list = (
|
||||
<TruncatedList className="mx_SearchableEntityList_list"
|
||||
truncateAt={this.state.truncateAt} // use state truncation as it may be expanded
|
||||
createOverflowElement={this._createOverflowEntity}>
|
||||
{ this.state.results.map((entity) => {
|
||||
return entity.getJsx();
|
||||
}) }
|
||||
</TruncatedList>
|
||||
);
|
||||
} else {
|
||||
list = (
|
||||
<div className="mx_SearchableEntityList_list">
|
||||
{ this.state.results.map((entity) => {
|
||||
return entity.getJsx();
|
||||
}) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
|
||||
list = (
|
||||
<GeminiScrollbarWrapper autoshow={true}
|
||||
className="mx_SearchableEntityList_listWrapper">
|
||||
{ list }
|
||||
</GeminiScrollbarWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={"mx_SearchableEntityList " + (list ? "mx_SearchableEntityList_expanded" : "")}>
|
||||
{ inputBox }
|
||||
{ list }
|
||||
{ list ? <div className="mx_SearchableEntityList_hrWrapper"><hr /></div> : '' }
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
export default SearchableEntityList;
|
|
@ -277,25 +277,25 @@ export default class KeyBackupPanel extends React.PureComponent {
|
|||
"Backup has an <validity>invalid</validity> signature from this session",
|
||||
{}, { validity },
|
||||
);
|
||||
} else if (sig.valid && sig.device.isVerified()) {
|
||||
} else if (sig.valid && sig.deviceTrust.isVerified()) {
|
||||
sigStatus = _t(
|
||||
"Backup has a <validity>valid</validity> signature from " +
|
||||
"<verify>verified</verify> session <device></device>",
|
||||
{}, { validity, verify, device },
|
||||
);
|
||||
} else if (sig.valid && !sig.device.isVerified()) {
|
||||
} else if (sig.valid && !sig.deviceTrust.isVerified()) {
|
||||
sigStatus = _t(
|
||||
"Backup has a <validity>valid</validity> signature from " +
|
||||
"<verify>unverified</verify> session <device></device>",
|
||||
{}, { validity, verify, device },
|
||||
);
|
||||
} else if (!sig.valid && sig.device.isVerified()) {
|
||||
} else if (!sig.valid && sig.deviceTrust.isVerified()) {
|
||||
sigStatus = _t(
|
||||
"Backup has an <validity>invalid</validity> signature from " +
|
||||
"<verify>verified</verify> session <device></device>",
|
||||
{}, { validity, verify, device },
|
||||
);
|
||||
} else if (!sig.valid && !sig.device.isVerified()) {
|
||||
} else if (!sig.valid && !sig.deviceTrust.isVerified()) {
|
||||
sigStatus = _t(
|
||||
"Backup has an <validity>invalid</validity> signature from " +
|
||||
"<verify>unverified</verify> session <device></device>",
|
||||
|
|
|
@ -21,7 +21,6 @@ import RoomProfileSettings from "../../../room_settings/RoomProfileSettings";
|
|||
import * as sdk from "../../../../..";
|
||||
import AccessibleButton from "../../../elements/AccessibleButton";
|
||||
import dis from "../../../../../dispatcher";
|
||||
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
|
||||
import MatrixClientContext from "../../../../../contexts/MatrixClientContext";
|
||||
|
||||
export default class GeneralRoomSettingsTab extends React.Component {
|
||||
|
@ -39,26 +38,6 @@ export default class GeneralRoomSettingsTab extends React.Component {
|
|||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.context.getRoomDirectoryVisibility(this.props.roomId).then((result => {
|
||||
this.setState({isRoomPublished: result.visibility === 'public'});
|
||||
}));
|
||||
}
|
||||
|
||||
onRoomPublishChange = (e) => {
|
||||
const valueBefore = this.state.isRoomPublished;
|
||||
const newValue = !valueBefore;
|
||||
this.setState({isRoomPublished: newValue});
|
||||
|
||||
this.context.setRoomDirectoryVisibility(
|
||||
this.props.roomId,
|
||||
newValue ? 'public' : 'private',
|
||||
).catch(() => {
|
||||
// Roll back the local echo on the change
|
||||
this.setState({isRoomPublished: valueBefore});
|
||||
});
|
||||
};
|
||||
|
||||
_onLeaveClick = () => {
|
||||
dis.dispatch({
|
||||
action: 'leave_room',
|
||||
|
@ -75,7 +54,6 @@ export default class GeneralRoomSettingsTab extends React.Component {
|
|||
const room = client.getRoom(this.props.roomId);
|
||||
|
||||
const canSetAliases = true; // Previously, we arbitrarily only allowed admins to do this
|
||||
const canActuallySetAliases = room.currentState.mayClientSendStateEvent("m.room.aliases", client);
|
||||
const canSetCanonical = room.currentState.mayClientSendStateEvent("m.room.canonical_alias", client);
|
||||
const canonicalAliasEv = room.currentState.getStateEvents("m.room.canonical_alias", '');
|
||||
const aliasEvents = room.currentState.getStateEvents("m.room.aliases");
|
||||
|
@ -90,21 +68,13 @@ export default class GeneralRoomSettingsTab extends React.Component {
|
|||
<RoomProfileSettings roomId={this.props.roomId} />
|
||||
</div>
|
||||
|
||||
<span className='mx_SettingsTab_subheading'>{_t("Room Addresses")}</span>
|
||||
<div className="mx_SettingsTab_heading">{_t("Room Addresses")}</div>
|
||||
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
|
||||
<AliasSettings roomId={this.props.roomId}
|
||||
canSetCanonicalAlias={canSetCanonical} canSetAliases={canSetAliases}
|
||||
canonicalAliasEvent={canonicalAliasEv} aliasEvents={aliasEvents} />
|
||||
</div>
|
||||
<div className='mx_SettingsTab_section'>
|
||||
<LabelledToggleSwitch value={this.state.isRoomPublished}
|
||||
onChange={this.onRoomPublishChange}
|
||||
disabled={!canActuallySetAliases}
|
||||
label={_t("Publish this room to the public in %(domain)s's room directory?", {
|
||||
domain: client.getDomain(),
|
||||
})} />
|
||||
</div>
|
||||
|
||||
<div className="mx_SettingsTab_heading">{_t("Other")}</div>
|
||||
<span className='mx_SettingsTab_subheading'>{_t("Flair")}</span>
|
||||
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
|
||||
<RelatedGroupSettings roomId={room.roomId}
|
||||
|
|
|
@ -61,6 +61,8 @@ export default class GeneralUserSettingsTab extends React.Component {
|
|||
emails: [],
|
||||
msisdns: [],
|
||||
...this._calculateThemeState(),
|
||||
customThemeUrl: "",
|
||||
customThemeMessage: {isError: false, text: ""},
|
||||
};
|
||||
|
||||
this.dispatcherRef = dis.register(this._onAction);
|
||||
|
@ -274,6 +276,41 @@ export default class GeneralUserSettingsTab extends React.Component {
|
|||
});
|
||||
};
|
||||
|
||||
_onAddCustomTheme = async () => {
|
||||
let currentThemes = SettingsStore.getValue("custom_themes");
|
||||
if (!currentThemes) currentThemes = [];
|
||||
currentThemes = currentThemes.map(c => c); // cheap clone
|
||||
|
||||
if (this._themeTimer) {
|
||||
clearTimeout(this._themeTimer);
|
||||
}
|
||||
|
||||
try {
|
||||
const r = await fetch(this.state.customThemeUrl);
|
||||
const themeInfo = await r.json();
|
||||
if (!themeInfo || typeof(themeInfo['name']) !== 'string' || typeof(themeInfo['colors']) !== 'object') {
|
||||
this.setState({customThemeMessage: {text: _t("Invalid theme schema."), isError: true}});
|
||||
return;
|
||||
}
|
||||
currentThemes.push(themeInfo);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
this.setState({customThemeMessage: {text: _t("Error downloading theme information."), isError: true}});
|
||||
return; // Don't continue on error
|
||||
}
|
||||
|
||||
await SettingsStore.setValue("custom_themes", null, SettingLevel.ACCOUNT, currentThemes);
|
||||
this.setState({customThemeUrl: "", customThemeMessage: {text: _t("Theme added!"), isError: false}});
|
||||
|
||||
this._themeTimer = setTimeout(() => {
|
||||
this.setState({customThemeMessage: {text: "", isError: false}});
|
||||
}, 3000);
|
||||
};
|
||||
|
||||
_onCustomThemeChange = (e) => {
|
||||
this.setState({customThemeUrl: e.target.value});
|
||||
};
|
||||
|
||||
_renderProfileSection() {
|
||||
return (
|
||||
<div className="mx_SettingsTab_section">
|
||||
|
@ -368,6 +405,45 @@ export default class GeneralUserSettingsTab extends React.Component {
|
|||
/>
|
||||
</div>;
|
||||
}
|
||||
|
||||
let customThemeForm;
|
||||
if (SettingsStore.isFeatureEnabled("feature_custom_themes")) {
|
||||
let messageElement = null;
|
||||
if (this.state.customThemeMessage.text) {
|
||||
if (this.state.customThemeMessage.isError) {
|
||||
messageElement = <div className='text-error'>{this.state.customThemeMessage.text}</div>;
|
||||
} else {
|
||||
messageElement = <div className='text-success'>{this.state.customThemeMessage.text}</div>;
|
||||
}
|
||||
}
|
||||
customThemeForm = (
|
||||
<div className='mx_SettingsTab_section'>
|
||||
<form onSubmit={this._onAddCustomTheme}>
|
||||
<Field
|
||||
label={_t("Custom theme URL")}
|
||||
type='text'
|
||||
id='mx_GeneralUserSettingsTab_customThemeInput'
|
||||
autoComplete="off"
|
||||
onChange={this._onCustomThemeChange}
|
||||
value={this.state.customThemeUrl}
|
||||
/>
|
||||
<AccessibleButton
|
||||
onClick={this._onAddCustomTheme}
|
||||
type="submit" kind="primary_sm"
|
||||
disabled={!this.state.customThemeUrl.trim()}
|
||||
>{_t("Add theme")}</AccessibleButton>
|
||||
{messageElement}
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const themes = Object.entries(enumerateThemes())
|
||||
.map(p => ({id: p[0], name: p[1]})); // convert pairs to objects for code readability
|
||||
const builtInThemes = themes.filter(p => !p.id.startsWith("custom-"));
|
||||
const customThemes = themes.filter(p => !builtInThemes.includes(p))
|
||||
.sort((a, b) => a.name.localeCompare(b.name));
|
||||
const orderedThemes = [...builtInThemes, ...customThemes];
|
||||
return (
|
||||
<div className="mx_SettingsTab_section mx_GeneralUserSettingsTab_themeSection">
|
||||
<span className="mx_SettingsTab_subheading">{_t("Theme")}</span>
|
||||
|
@ -376,10 +452,11 @@ export default class GeneralUserSettingsTab extends React.Component {
|
|||
value={this.state.theme} onChange={this._onThemeChange}
|
||||
disabled={this.state.useSystemTheme}
|
||||
>
|
||||
{Object.entries(enumerateThemes()).map(([theme, text]) => {
|
||||
return <option key={theme} value={theme}>{text}</option>;
|
||||
{orderedThemes.map(theme => {
|
||||
return <option key={theme.id} value={theme.id}>{theme.name}</option>;
|
||||
})}
|
||||
</Field>
|
||||
{customThemeForm}
|
||||
<SettingsFlag name="useCompactLayout" level={SettingLevel.ACCOUNT} />
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -24,6 +24,7 @@ import createRoom from "../../../../../createRoom";
|
|||
import Modal from "../../../../../Modal";
|
||||
import * as sdk from "../../../../../";
|
||||
import PlatformPeg from "../../../../../PlatformPeg";
|
||||
import * as KeyboardShortcuts from "../../../../../accessibility/KeyboardShortcuts";
|
||||
|
||||
export default class HelpUserSettingsTab extends React.Component {
|
||||
static propTypes = {
|
||||
|
@ -224,6 +225,9 @@ export default class HelpUserSettingsTab extends React.Component {
|
|||
<div className='mx_SettingsTab_subsectionText'>
|
||||
{faqText}
|
||||
</div>
|
||||
<AccessibleButton kind="primary" onClick={KeyboardShortcuts.toggleDialog}>
|
||||
{ _t("Keyboard Shortcuts") }
|
||||
</AccessibleButton>
|
||||
</div>
|
||||
<div className='mx_SettingsTab_section mx_HelpUserSettingsTab_versions'>
|
||||
<span className='mx_SettingsTab_subheading'>{_t("Versions")}</span>
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
"Dismiss": "Dismiss",
|
||||
"Call Failed": "Call Failed",
|
||||
"There are unknown sessions in this room: if you proceed without verifying them, it will be possible for someone to eavesdrop on your call.": "There are unknown sessions in this room: if you proceed without verifying them, it will be possible for someone to eavesdrop on your call.",
|
||||
"Review Devices": "Review Devices",
|
||||
"Review Sessions": "Review Sessions",
|
||||
"Call Anyway": "Call Anyway",
|
||||
"Answer Anyway": "Answer Anyway",
|
||||
"Call": "Call",
|
||||
|
@ -385,6 +385,7 @@
|
|||
"Multiple integration managers": "Multiple integration managers",
|
||||
"Try out new ways to ignore people (experimental)": "Try out new ways to ignore people (experimental)",
|
||||
"Show a presence dot next to DMs in the room list": "Show a presence dot next to DMs in the room list",
|
||||
"Support adding custom themes": "Support adding custom themes",
|
||||
"Enable cross-signing to verify per-user instead of per-session (in development)": "Enable cross-signing to verify per-user instead of per-session (in development)",
|
||||
"Enable local event indexing and E2EE search (requires restart)": "Enable local event indexing and E2EE search (requires restart)",
|
||||
"Show info about bridges in room settings": "Show info about bridges in room settings",
|
||||
|
@ -708,12 +709,17 @@
|
|||
"Failed to change password. Is your password correct?": "Failed to change password. Is your password correct?",
|
||||
"Success": "Success",
|
||||
"Your password was successfully changed. You will not receive push notifications on other sessions until you log back in to them": "Your password was successfully changed. You will not receive push notifications on other sessions until you log back in to them",
|
||||
"Invalid theme schema.": "Invalid theme schema.",
|
||||
"Error downloading theme information.": "Error downloading theme information.",
|
||||
"Theme added!": "Theme added!",
|
||||
"Profile": "Profile",
|
||||
"Email addresses": "Email addresses",
|
||||
"Phone numbers": "Phone numbers",
|
||||
"Set a new account password...": "Set a new account password...",
|
||||
"Account": "Account",
|
||||
"Language and region": "Language and region",
|
||||
"Custom theme URL": "Custom theme URL",
|
||||
"Add theme": "Add theme",
|
||||
"Theme": "Theme",
|
||||
"Agree to the identity server (%(serverName)s) Terms of Service to allow yourself to be discoverable by email address or phone number.": "Agree to the identity server (%(serverName)s) Terms of Service to allow yourself to be discoverable by email address or phone number.",
|
||||
"Account management": "Account management",
|
||||
|
@ -736,6 +742,7 @@
|
|||
"Clear cache and reload": "Clear cache and reload",
|
||||
"To report a Matrix-related security issue, please read the Matrix.org <a>Security Disclosure Policy</a>.": "To report a Matrix-related security issue, please read the Matrix.org <a>Security Disclosure Policy</a>.",
|
||||
"FAQ": "FAQ",
|
||||
"Keyboard Shortcuts": "Keyboard Shortcuts",
|
||||
"Versions": "Versions",
|
||||
"riot-web version:": "riot-web version:",
|
||||
"olm version:": "olm version:",
|
||||
|
@ -834,7 +841,6 @@
|
|||
"This room isn’t bridging messages to any platforms. <a>Learn more.</a>": "This room isn’t bridging messages to any platforms. <a>Learn more.</a>",
|
||||
"Bridges": "Bridges",
|
||||
"Room Addresses": "Room Addresses",
|
||||
"Publish this room to the public in %(domain)s's room directory?": "Publish this room to the public in %(domain)s's room directory?",
|
||||
"URL Previews": "URL Previews",
|
||||
"Uploaded sound": "Uploaded sound",
|
||||
"Sounds": "Sounds",
|
||||
|
@ -955,7 +961,7 @@
|
|||
"Encrypted by a deleted session": "Encrypted by a deleted session",
|
||||
"Please select the destination room for this message": "Please select the destination room for this message",
|
||||
"Invite only": "Invite only",
|
||||
"Scroll to bottom of page": "Scroll to bottom of page",
|
||||
"Scroll to most recent messages": "Scroll to most recent messages",
|
||||
"Close preview": "Close preview",
|
||||
"device id: ": "device id: ",
|
||||
"Disinvite": "Disinvite",
|
||||
|
@ -1151,16 +1157,20 @@
|
|||
"There was an error updating the room's alternative addresses. It may not be allowed by the server or a temporary failure occurred.": "There was an error updating the room's alternative addresses. It may not be allowed by the server or a temporary failure occurred.",
|
||||
"Error creating alias": "Error creating alias",
|
||||
"There was an error creating that alias. It may not be allowed by the server or a temporary failure occurred.": "There was an error creating that alias. It may not be allowed by the server or a temporary failure occurred.",
|
||||
"Error removing alias": "Error removing alias",
|
||||
"You don't have permission to delete the alias.": "You don't have permission to delete the alias.",
|
||||
"There was an error removing that alias. It may no longer exist or a temporary error occurred.": "There was an error removing that alias. It may no longer exist or a temporary error occurred.",
|
||||
"Error removing alias": "Error removing alias",
|
||||
"Main address": "Main address",
|
||||
"not specified": "not specified",
|
||||
"This room has no local addresses": "This room has no local addresses",
|
||||
"New address (e.g. #foo:%(localDomain)s)": "New address (e.g. #foo:%(localDomain)s)",
|
||||
"Alternative addresses for this room:": "Alternative addresses for this room:",
|
||||
"This room has no alternative addresses": "This room has no alternative addresses",
|
||||
"New address (e.g. #foo:domain)": "New address (e.g. #foo:domain)",
|
||||
"Local addresses (unmoderated content)": "Local addresses (unmoderated content)",
|
||||
"Local address": "Local address",
|
||||
"Published Addresses": "Published Addresses",
|
||||
"Published addresses can be used by anyone on any server to join your room. To publish an address, it needs to be set as a local address first.": "Published addresses can be used by anyone on any server to join your room. To publish an address, it needs to be set as a local address first.",
|
||||
"Other published addresses:": "Other published addresses:",
|
||||
"No other published addresses yet, add one below": "No other published addresses yet, add one below",
|
||||
"New published address (e.g. #alias:server)": "New published address (e.g. #alias:server)",
|
||||
"Local Addresses": "Local Addresses",
|
||||
"Set addresses for this room so users can find this room through your homeserver (%(localDomain)s)": "Set addresses for this room so users can find this room through your homeserver (%(localDomain)s)",
|
||||
"Error updating flair": "Error updating flair",
|
||||
"There was an error updating the flair for this room. The server may not allow it or a temporary error occurred.": "There was an error updating the flair for this room. The server may not allow it or a temporary error occurred.",
|
||||
"Invalid community ID": "Invalid community ID",
|
||||
|
@ -1171,6 +1181,7 @@
|
|||
"Room Name": "Room Name",
|
||||
"Room Topic": "Room Topic",
|
||||
"Room avatar": "Room avatar",
|
||||
"Publish this room to the public in %(domain)s's room directory?": "Publish this room to the public in %(domain)s's room directory?",
|
||||
"You have <a>enabled</a> URL previews by default.": "You have <a>enabled</a> URL previews by default.",
|
||||
"You have <a>disabled</a> URL previews by default.": "You have <a>disabled</a> URL previews by default.",
|
||||
"URL previews are enabled by default for participants in this room.": "URL previews are enabled by default for participants in this room.",
|
||||
|
@ -1439,6 +1450,20 @@
|
|||
"And %(count)s more...|other": "And %(count)s more...",
|
||||
"ex. @bob:example.com": "ex. @bob:example.com",
|
||||
"Add User": "Add User",
|
||||
"Enter a server name": "Enter a server name",
|
||||
"Looks good": "Looks good",
|
||||
"Can't find this server or its room list": "Can't find this server or its room list",
|
||||
"All rooms": "All rooms",
|
||||
"Your server": "Your server",
|
||||
"Are you sure you want to remove <b>%(serverName)s</b>": "Are you sure you want to remove <b>%(serverName)s</b>",
|
||||
"Remove server": "Remove server",
|
||||
"Matrix": "Matrix",
|
||||
"Add a new server": "Add a new server",
|
||||
"Enter the name of a new server you want to explore.": "Enter the name of a new server you want to explore.",
|
||||
"Server name": "Server name",
|
||||
"Add a new server...": "Add a new server...",
|
||||
"%(networkName)s rooms": "%(networkName)s rooms",
|
||||
"Matrix rooms": "Matrix rooms",
|
||||
"Matrix ID": "Matrix ID",
|
||||
"Matrix Room ID": "Matrix Room ID",
|
||||
"email address": "email address",
|
||||
|
@ -1966,7 +1991,9 @@
|
|||
"Uploading %(filename)s and %(count)s others|one": "Uploading %(filename)s and %(count)s other",
|
||||
"Could not load user profile": "Could not load user profile",
|
||||
"Complete security": "Complete security",
|
||||
"Verify this session to grant it access to encrypted messages.": "Verify this session to grant it access to encrypted messages.",
|
||||
"Open an existing session & use it to verify this one, granting it access to encrypted messages.": "Open an existing session & use it to verify this one, granting it access to encrypted messages.",
|
||||
"Waiting…": "Waiting…",
|
||||
"If you can’t access one, <button>use your recovery key or passphrase.</button>": "If you can’t access one, <button>use your recovery key or passphrase.</button>",
|
||||
"Session verified": "Session verified",
|
||||
"Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.": "Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.",
|
||||
"Your new session is now verified. Other users will see it as trusted.": "Your new session is now verified. Other users will see it as trusted.",
|
||||
|
@ -2143,5 +2170,42 @@
|
|||
"Message downloading sleep time(ms)": "Message downloading sleep time(ms)",
|
||||
"Failed to set direct chat tag": "Failed to set direct chat tag",
|
||||
"Failed to remove tag %(tagName)s from room": "Failed to remove tag %(tagName)s from room",
|
||||
"Failed to add tag %(tagName)s to room": "Failed to add tag %(tagName)s to room"
|
||||
"Failed to add tag %(tagName)s to room": "Failed to add tag %(tagName)s to room",
|
||||
"Navigation": "Navigation",
|
||||
"Calls": "Calls",
|
||||
"Room List": "Room List",
|
||||
"Autocomplete": "Autocomplete",
|
||||
"Alt": "Alt",
|
||||
"Alt Gr": "Alt Gr",
|
||||
"Shift": "Shift",
|
||||
"Super": "Super",
|
||||
"Ctrl": "Ctrl",
|
||||
"Toggle Bold": "Toggle Bold",
|
||||
"Toggle Italics": "Toggle Italics",
|
||||
"Toggle Quote": "Toggle Quote",
|
||||
"Toggle Markdown": "Toggle Markdown",
|
||||
"New line": "New line",
|
||||
"Navigate recent messages to edit": "Navigate recent messages to edit",
|
||||
"Jump to start/end of the composer": "Jump to start/end of the composer",
|
||||
"Toggle microphone mute": "Toggle microphone mute",
|
||||
"Toggle video on/off": "Toggle video on/off",
|
||||
"Jump to room search": "Jump to room search",
|
||||
"Navigate up/down in the room list": "Navigate up/down in the room list",
|
||||
"Select room from the room list": "Select room from the room list",
|
||||
"Collapse room list section": "Collapse room list section",
|
||||
"Expand room list section": "Expand room list section",
|
||||
"Clear room list filter field": "Clear room list filter field",
|
||||
"Scroll up/down in the timeline": "Scroll up/down in the timeline",
|
||||
"Toggle the top left menu": "Toggle the top left menu",
|
||||
"Close dialog or context menu": "Close dialog or context menu",
|
||||
"Activate selected button": "Activate selected button",
|
||||
"Toggle this dialog": "Toggle this dialog",
|
||||
"Move autocomplete selection up/down": "Move autocomplete selection up/down",
|
||||
"Cancel autocomplete": "Cancel autocomplete",
|
||||
"Page Up": "Page Up",
|
||||
"Page Down": "Page Down",
|
||||
"Esc": "Esc",
|
||||
"Enter": "Enter",
|
||||
"Space": "Space",
|
||||
"End": "End"
|
||||
}
|
||||
|
|
|
@ -123,6 +123,10 @@ export default class BaseEventIndexManager {
|
|||
throw new Error("Unimplemented");
|
||||
}
|
||||
|
||||
async deleteEvent(eventId: string): Promise<boolean> {
|
||||
throw new Error("Unimplemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if our event index is empty.
|
||||
*/
|
||||
|
|
|
@ -61,6 +61,7 @@ export default class EventIndex extends EventEmitter {
|
|||
client.on('Room.timeline', this.onRoomTimeline);
|
||||
client.on('Event.decrypted', this.onEventDecrypted);
|
||||
client.on('Room.timelineReset', this.onTimelineReset);
|
||||
client.on('Room.redaction', this.onRedaction);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -74,6 +75,7 @@ export default class EventIndex extends EventEmitter {
|
|||
client.removeListener('Room.timeline', this.onRoomTimeline);
|
||||
client.removeListener('Event.decrypted', this.onEventDecrypted);
|
||||
client.removeListener('Room.timelineReset', this.onTimelineReset);
|
||||
client.removeListener('Room.redaction', this.onRedaction);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -210,6 +212,23 @@ export default class EventIndex extends EventEmitter {
|
|||
await this.addLiveEventToIndex(ev);
|
||||
}
|
||||
|
||||
/*
|
||||
* The Room.redaction listener.
|
||||
*
|
||||
* Removes a redacted event from our event index.
|
||||
*/
|
||||
onRedaction = async (ev, room) => {
|
||||
// We only index encrypted rooms locally.
|
||||
if (!MatrixClientPeg.get().isRoomEncrypted(room.roomId)) return;
|
||||
const indexManager = PlatformPeg.get().getEventIndexingManager();
|
||||
|
||||
try {
|
||||
await indexManager.deleteEvent(ev.getAssociatedId());
|
||||
} catch (e) {
|
||||
console.log("EventIndex: Error deleting event from index", e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The Room.timelineReset listener.
|
||||
*
|
||||
|
@ -373,6 +392,21 @@ export default class EventIndex extends EventEmitter {
|
|||
checkpoint.roomId, checkpoint.token, this._eventsPerCrawl,
|
||||
checkpoint.direction);
|
||||
} catch (e) {
|
||||
if (e.httpStatus === 403) {
|
||||
console.log("EventIndex: Removing checkpoint as we don't have ",
|
||||
"permissions to fetch messages from this room.", checkpoint);
|
||||
try {
|
||||
await indexManager.removeCrawlerCheckpoint(checkpoint);
|
||||
} catch (e) {
|
||||
console.log("EventIndex: Error removing checkpoint", checkpoint, e);
|
||||
// We don't push the checkpoint here back, it will
|
||||
// hopefully be removed after a restart. But let us
|
||||
// ignore it for now as we don't want to hammer the
|
||||
// endpoint.
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
console.log("EventIndex: Error crawling events:", e);
|
||||
this.crawlerCheckpoints.push(checkpoint);
|
||||
continue;
|
||||
|
@ -431,12 +465,17 @@ export default class EventIndex extends EventEmitter {
|
|||
// Let us wait for all the events to get decrypted.
|
||||
await Promise.all(decryptionPromises);
|
||||
|
||||
|
||||
// TODO if there are no events at this point we're missing a lot
|
||||
// decryption keys, do we want to retry this checkpoint at a later
|
||||
// stage?
|
||||
const filteredEvents = matrixEvents.filter(this.isValidEvent);
|
||||
|
||||
// Collect the redaction events so we can delete the redacted events
|
||||
// from the index.
|
||||
const redactionEvents = matrixEvents.filter((ev) => {
|
||||
return ev.getType() === "m.room.redaction";
|
||||
});
|
||||
|
||||
// Let us convert the events back into a format that EventIndex can
|
||||
// consume.
|
||||
const events = filteredEvents.map((ev) => {
|
||||
|
@ -468,6 +507,11 @@ export default class EventIndex extends EventEmitter {
|
|||
);
|
||||
|
||||
try {
|
||||
for (let i = 0; i < redactionEvents.length; i++) {
|
||||
const ev = redactionEvents[i];
|
||||
await indexManager.deleteEvent(ev.getAssociatedId());
|
||||
}
|
||||
|
||||
const eventsAlreadyAdded = await indexManager.addHistoricEvents(
|
||||
events, newCheckpoint, checkpoint);
|
||||
// If all events were already indexed we assume that we catched
|
||||
|
@ -520,7 +564,8 @@ export default class EventIndex extends EventEmitter {
|
|||
const indexManager = PlatformPeg.get().getEventIndexingManager();
|
||||
this.removeListeners();
|
||||
this.stopCrawler();
|
||||
return indexManager.closeEventIndex();
|
||||
await indexManager.closeEventIndex();
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -135,7 +135,7 @@ class EventIndexPeg {
|
|||
*/
|
||||
async unset() {
|
||||
if (this.index === null) return;
|
||||
this.index.close();
|
||||
await this.index.close();
|
||||
this.index = null;
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,7 @@ class EventIndexPeg {
|
|||
const indexManager = PlatformPeg.get().getEventIndexingManager();
|
||||
|
||||
if (indexManager !== null) {
|
||||
this.unset();
|
||||
await this.unset();
|
||||
console.log("EventIndex: Deleting event index.");
|
||||
await indexManager.deleteEventIndex();
|
||||
}
|
||||
|
|
|
@ -134,6 +134,12 @@ export const SETTINGS = {
|
|||
supportedLevels: LEVELS_FEATURE,
|
||||
default: false,
|
||||
},
|
||||
"feature_custom_themes": {
|
||||
isFeature: true,
|
||||
displayName: _td("Support adding custom themes"),
|
||||
supportedLevels: LEVELS_FEATURE,
|
||||
default: false,
|
||||
},
|
||||
"mjolnirRooms": {
|
||||
supportedLevels: ['account'],
|
||||
default: [],
|
||||
|
@ -324,6 +330,10 @@ export const SETTINGS = {
|
|||
supportedLevels: ['account'],
|
||||
default: [],
|
||||
},
|
||||
"room_directory_servers": {
|
||||
supportedLevels: ['account'],
|
||||
default: [],
|
||||
},
|
||||
"integrationProvisioning": {
|
||||
supportedLevels: ['account'],
|
||||
default: true,
|
||||
|
@ -511,4 +521,8 @@ export const SETTINGS = {
|
|||
displayName: _td("How fast should messages be downloaded."),
|
||||
default: 3000,
|
||||
},
|
||||
"showCallButtonsInComposer": {
|
||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
|
||||
default: true,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -42,8 +42,6 @@ const GROUP_PHASES = Object.keys(RIGHT_PANEL_PHASES).filter(k => k.startsWith("G
|
|||
export default class RightPanelStore extends Store {
|
||||
static _instance;
|
||||
|
||||
_inhibitUpdates = false;
|
||||
|
||||
constructor() {
|
||||
super(dis);
|
||||
|
||||
|
@ -116,11 +114,6 @@ export default class RightPanelStore extends Store {
|
|||
}
|
||||
|
||||
__onDispatch(payload) {
|
||||
if (payload.action === 'panel_disable') {
|
||||
this._inhibitUpdates = payload.rightDisabled || payload.sideDisabled || false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (payload.action === 'view_room' || payload.action === 'view_group') {
|
||||
// Reset to the member list if we're viewing member info
|
||||
const memberInfoPhases = [
|
||||
|
@ -138,7 +131,7 @@ export default class RightPanelStore extends Store {
|
|||
}
|
||||
}
|
||||
|
||||
if (payload.action !== 'set_right_panel_phase' || this._inhibitUpdates) return;
|
||||
if (payload.action !== 'set_right_panel_phase') return;
|
||||
|
||||
const targetPhase = payload.phase;
|
||||
if (!RIGHT_PANEL_PHASES[targetPhase]) {
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import * as React from 'react';
|
||||
import * as sdk from '../index';
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,6 +23,7 @@ import {RIGHT_PANEL_PHASES} from "./stores/RightPanelStorePhases";
|
|||
import {findDMForUser} from './createRoom';
|
||||
import {accessSecretStorage} from './CrossSigningManager';
|
||||
import SettingsStore from './settings/SettingsStore';
|
||||
import {verificationMethods} from 'matrix-js-sdk/src/crypto';
|
||||
|
||||
async function enable4SIfNeeded() {
|
||||
const cli = MatrixClientPeg.get();
|
||||
|
@ -57,9 +58,10 @@ export async function verifyDevice(user, device) {
|
|||
return;
|
||||
}
|
||||
const cli = MatrixClientPeg.get();
|
||||
const verificationRequestPromise = cli.requestVerification(
|
||||
const verificationRequestPromise = cli.legacyDeviceVerification(
|
||||
user.userId,
|
||||
[device.deviceId],
|
||||
device.deviceId,
|
||||
verificationMethods.SAS,
|
||||
);
|
||||
dis.dispatch({
|
||||
action: "set_right_panel_phase",
|
||||
|
@ -77,7 +79,7 @@ export async function legacyVerifyUser(user) {
|
|||
return;
|
||||
}
|
||||
const cli = MatrixClientPeg.get();
|
||||
const verificationRequestPromise = cli.requestVerification(user.userId);
|
||||
const verificationRequestPromise = cli.beginKeyVerification(user.userId);
|
||||
dis.dispatch({
|
||||
action: "set_right_panel_phase",
|
||||
phase: RIGHT_PANEL_PHASES.EncryptionPanel,
|
||||
|
|
|
@ -9,11 +9,14 @@
|
|||
"sourceMap": false,
|
||||
"outDir": "./lib",
|
||||
"declaration": true,
|
||||
"jsx": "react",
|
||||
"types": [
|
||||
"node"
|
||||
"node",
|
||||
"react"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*.ts"
|
||||
"./src/**/*.ts",
|
||||
"./src/**/*.tsx"
|
||||
]
|
||||
}
|
||||
|
|
535
yarn.lock
535
yarn.lock
|
@ -25,27 +25,27 @@
|
|||
dependencies:
|
||||
"@babel/highlight" "^7.8.3"
|
||||
|
||||
"@babel/compat-data@^7.8.4":
|
||||
version "7.8.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.8.5.tgz#d28ce872778c23551cbb9432fc68d28495b613b9"
|
||||
integrity sha512-jWYUqQX/ObOhG1UiEkbH5SANsE/8oKXiQWjj7p7xgj9Zmnt//aUvyz4dBkK0HNsS8/cbyC5NmmH87VekW+mXFg==
|
||||
"@babel/compat-data@^7.8.6":
|
||||
version "7.8.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.8.6.tgz#7eeaa0dfa17e50c7d9c0832515eee09b56f04e35"
|
||||
integrity sha512-CurCIKPTkS25Mb8mz267vU95vy+TyUpnctEX2lV33xWNmHAfjruztgiPBbXZRh3xZZy1CYvGx6XfxyTVS+sk7Q==
|
||||
dependencies:
|
||||
browserslist "^4.8.5"
|
||||
invariant "^2.2.4"
|
||||
semver "^5.5.0"
|
||||
|
||||
"@babel/core@>=7.2.2", "@babel/core@^7.1.0", "@babel/core@^7.7.5":
|
||||
version "7.8.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.4.tgz#d496799e5c12195b3602d0fddd77294e3e38e80e"
|
||||
integrity sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA==
|
||||
version "7.8.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.7.tgz#b69017d221ccdeb203145ae9da269d72cf102f3b"
|
||||
integrity sha512-rBlqF3Yko9cynC5CCFy6+K/w2N+Sq/ff2BPy+Krp7rHlABIr5epbA7OxVeKoMHB39LZOp1UY5SuLjy6uWi35yA==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.8.3"
|
||||
"@babel/generator" "^7.8.4"
|
||||
"@babel/generator" "^7.8.7"
|
||||
"@babel/helpers" "^7.8.4"
|
||||
"@babel/parser" "^7.8.4"
|
||||
"@babel/template" "^7.8.3"
|
||||
"@babel/traverse" "^7.8.4"
|
||||
"@babel/types" "^7.8.3"
|
||||
"@babel/parser" "^7.8.7"
|
||||
"@babel/template" "^7.8.6"
|
||||
"@babel/traverse" "^7.8.6"
|
||||
"@babel/types" "^7.8.7"
|
||||
convert-source-map "^1.7.0"
|
||||
debug "^4.1.0"
|
||||
gensync "^1.0.0-beta.1"
|
||||
|
@ -55,12 +55,12 @@
|
|||
semver "^5.4.1"
|
||||
source-map "^0.5.0"
|
||||
|
||||
"@babel/generator@^7.4.0", "@babel/generator@^7.8.3", "@babel/generator@^7.8.4":
|
||||
version "7.8.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.4.tgz#35bbc74486956fe4251829f9f6c48330e8d0985e"
|
||||
integrity sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==
|
||||
"@babel/generator@^7.4.0", "@babel/generator@^7.8.3", "@babel/generator@^7.8.6", "@babel/generator@^7.8.7":
|
||||
version "7.8.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.7.tgz#870b3cf7984f5297998152af625c4f3e341400f7"
|
||||
integrity sha512-DQwjiKJqH4C3qGiyQCAExJHoZssn49JTMJgZ8SANGgVFdkupcUhLOdkAeoC6kmHZCPfoDG5M0b6cFlSN5wW7Ew==
|
||||
dependencies:
|
||||
"@babel/types" "^7.8.3"
|
||||
"@babel/types" "^7.8.7"
|
||||
jsesc "^2.5.1"
|
||||
lodash "^4.17.13"
|
||||
source-map "^0.5.0"
|
||||
|
@ -88,43 +88,44 @@
|
|||
"@babel/types" "^7.8.3"
|
||||
esutils "^2.0.0"
|
||||
|
||||
"@babel/helper-call-delegate@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.8.3.tgz#de82619898aa605d409c42be6ffb8d7204579692"
|
||||
integrity sha512-6Q05px0Eb+N4/GTyKPPvnkig7Lylw+QzihMpws9iiZQv7ZImf84ZsZpQH7QoWN4n4tm81SnSzPgHw2qtO0Zf3A==
|
||||
"@babel/helper-call-delegate@^7.8.7":
|
||||
version "7.8.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.8.7.tgz#28a279c2e6c622a6233da548127f980751324cab"
|
||||
integrity sha512-doAA5LAKhsFCR0LAFIf+r2RSMmC+m8f/oQ+URnUET/rWeEzC0yTRmAGyWkD4sSu3xwbS7MYQ2u+xlt1V5R56KQ==
|
||||
dependencies:
|
||||
"@babel/helper-hoist-variables" "^7.8.3"
|
||||
"@babel/traverse" "^7.8.3"
|
||||
"@babel/types" "^7.8.3"
|
||||
"@babel/types" "^7.8.7"
|
||||
|
||||
"@babel/helper-compilation-targets@^7.8.4":
|
||||
version "7.8.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.4.tgz#03d7ecd454b7ebe19a254f76617e61770aed2c88"
|
||||
integrity sha512-3k3BsKMvPp5bjxgMdrFyq0UaEO48HciVrOVF0+lon8pp95cyJ2ujAh0TrBHNMnJGT2rr0iKOJPFFbSqjDyf/Pg==
|
||||
"@babel/helper-compilation-targets@^7.8.7":
|
||||
version "7.8.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz#dac1eea159c0e4bd46e309b5a1b04a66b53c1dde"
|
||||
integrity sha512-4mWm8DCK2LugIS+p1yArqvG1Pf162upsIsjE7cNBjez+NjliQpVhj20obE520nao0o14DaTnFJv+Fw5a0JpoUw==
|
||||
dependencies:
|
||||
"@babel/compat-data" "^7.8.4"
|
||||
browserslist "^4.8.5"
|
||||
"@babel/compat-data" "^7.8.6"
|
||||
browserslist "^4.9.1"
|
||||
invariant "^2.2.4"
|
||||
levenary "^1.1.1"
|
||||
semver "^5.5.0"
|
||||
|
||||
"@babel/helper-create-class-features-plugin@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.3.tgz#5b94be88c255f140fd2c10dd151e7f98f4bff397"
|
||||
integrity sha512-qmp4pD7zeTxsv0JNecSBsEmG1ei2MqwJq4YQcK3ZWm/0t07QstWfvuV/vm3Qt5xNMFETn2SZqpMx2MQzbtq+KA==
|
||||
version "7.8.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.6.tgz#243a5b46e2f8f0f674dc1387631eb6b28b851de0"
|
||||
integrity sha512-klTBDdsr+VFFqaDHm5rR69OpEQtO2Qv8ECxHS1mNhJJvaHArR6a1xTf5K/eZW7eZpJbhCx3NW1Yt/sKsLXLblg==
|
||||
dependencies:
|
||||
"@babel/helper-function-name" "^7.8.3"
|
||||
"@babel/helper-member-expression-to-functions" "^7.8.3"
|
||||
"@babel/helper-optimise-call-expression" "^7.8.3"
|
||||
"@babel/helper-plugin-utils" "^7.8.3"
|
||||
"@babel/helper-replace-supers" "^7.8.3"
|
||||
"@babel/helper-replace-supers" "^7.8.6"
|
||||
"@babel/helper-split-export-declaration" "^7.8.3"
|
||||
|
||||
"@babel/helper-create-regexp-features-plugin@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.3.tgz#c774268c95ec07ee92476a3862b75cc2839beb79"
|
||||
integrity sha512-Gcsm1OHCUr9o9TcJln57xhWHtdXbA2pgQ58S0Lxlks0WMGNXuki4+GLfX0p+L2ZkINUGZvfkz8rzoqJQSthI+Q==
|
||||
version "7.8.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.6.tgz#7fa040c97fb8aebe1247a5c645330c32d083066b"
|
||||
integrity sha512-bPyujWfsHhV/ztUkwGHz/RPV1T1TDEsSZDsN42JPehndA+p1KKTh3npvTadux0ZhCrytx9tvjpWNowKby3tM6A==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.8.3"
|
||||
"@babel/helper-regex" "^7.8.3"
|
||||
regexpu-core "^4.6.0"
|
||||
|
||||
|
@ -183,15 +184,16 @@
|
|||
"@babel/types" "^7.8.3"
|
||||
|
||||
"@babel/helper-module-transforms@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.8.3.tgz#d305e35d02bee720fbc2c3c3623aa0c316c01590"
|
||||
integrity sha512-C7NG6B7vfBa/pwCOshpMbOYUmrYQDfCpVL/JCRu0ek8B5p8kue1+BCXpg2vOYs7w5ACB9GTOBYQ5U6NwrMg+3Q==
|
||||
version "7.8.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.8.6.tgz#6a13b5eecadc35692047073a64e42977b97654a4"
|
||||
integrity sha512-RDnGJSR5EFBJjG3deY0NiL0K9TO8SXxS9n/MPsbPK/s9LbQymuLNtlzvDiNS7IpecuL45cMeLVkA+HfmlrnkRg==
|
||||
dependencies:
|
||||
"@babel/helper-module-imports" "^7.8.3"
|
||||
"@babel/helper-replace-supers" "^7.8.6"
|
||||
"@babel/helper-simple-access" "^7.8.3"
|
||||
"@babel/helper-split-export-declaration" "^7.8.3"
|
||||
"@babel/template" "^7.8.3"
|
||||
"@babel/types" "^7.8.3"
|
||||
"@babel/template" "^7.8.6"
|
||||
"@babel/types" "^7.8.6"
|
||||
lodash "^4.17.13"
|
||||
|
||||
"@babel/helper-optimise-call-expression@^7.8.3":
|
||||
|
@ -224,15 +226,15 @@
|
|||
"@babel/traverse" "^7.8.3"
|
||||
"@babel/types" "^7.8.3"
|
||||
|
||||
"@babel/helper-replace-supers@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz#91192d25f6abbcd41da8a989d4492574fb1530bc"
|
||||
integrity sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA==
|
||||
"@babel/helper-replace-supers@^7.8.3", "@babel/helper-replace-supers@^7.8.6":
|
||||
version "7.8.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz#5ada744fd5ad73203bf1d67459a27dcba67effc8"
|
||||
integrity sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA==
|
||||
dependencies:
|
||||
"@babel/helper-member-expression-to-functions" "^7.8.3"
|
||||
"@babel/helper-optimise-call-expression" "^7.8.3"
|
||||
"@babel/traverse" "^7.8.3"
|
||||
"@babel/types" "^7.8.3"
|
||||
"@babel/traverse" "^7.8.6"
|
||||
"@babel/types" "^7.8.6"
|
||||
|
||||
"@babel/helper-simple-access@^7.8.3":
|
||||
version "7.8.3"
|
||||
|
@ -277,10 +279,10 @@
|
|||
esutils "^2.0.2"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.8.3", "@babel/parser@^7.8.4":
|
||||
version "7.8.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.4.tgz#d1dbe64691d60358a974295fa53da074dd2ce8e8"
|
||||
integrity sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==
|
||||
"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.8.6", "@babel/parser@^7.8.7":
|
||||
version "7.8.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.7.tgz#7b8facf95d25fef9534aad51c4ffecde1a61e26a"
|
||||
integrity sha512-9JWls8WilDXFGxs0phaXAZgpxTZhSk/yOYH2hTHC0X1yC7Z78IJfvR1vJ+rmJKq3I35td2XzXzN6ZLYlna+r/A==
|
||||
|
||||
"@babel/plugin-proposal-async-generator-functions@^7.8.3":
|
||||
version "7.8.3"
|
||||
|
@ -509,17 +511,17 @@
|
|||
"@babel/helper-plugin-utils" "^7.8.3"
|
||||
lodash "^4.17.13"
|
||||
|
||||
"@babel/plugin-transform-classes@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.8.3.tgz#46fd7a9d2bb9ea89ce88720477979fe0d71b21b8"
|
||||
integrity sha512-SjT0cwFJ+7Rbr1vQsvphAHwUHvSUPmMjMU/0P59G8U2HLFqSa082JO7zkbDNWs9kH/IUqpHI6xWNesGf8haF1w==
|
||||
"@babel/plugin-transform-classes@^7.8.6":
|
||||
version "7.8.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.8.6.tgz#77534447a477cbe5995ae4aee3e39fbc8090c46d"
|
||||
integrity sha512-k9r8qRay/R6v5aWZkrEclEhKO6mc1CCQr2dLsVHBmOQiMpN6I2bpjX3vgnldUWeEI1GHVNByULVxZ4BdP4Hmdg==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.8.3"
|
||||
"@babel/helper-define-map" "^7.8.3"
|
||||
"@babel/helper-function-name" "^7.8.3"
|
||||
"@babel/helper-optimise-call-expression" "^7.8.3"
|
||||
"@babel/helper-plugin-utils" "^7.8.3"
|
||||
"@babel/helper-replace-supers" "^7.8.3"
|
||||
"@babel/helper-replace-supers" "^7.8.6"
|
||||
"@babel/helper-split-export-declaration" "^7.8.3"
|
||||
globals "^11.1.0"
|
||||
|
||||
|
@ -577,10 +579,10 @@
|
|||
"@babel/helper-plugin-utils" "^7.8.3"
|
||||
"@babel/plugin-syntax-flow" "^7.8.3"
|
||||
|
||||
"@babel/plugin-transform-for-of@^7.8.4":
|
||||
version "7.8.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.4.tgz#6fe8eae5d6875086ee185dd0b098a8513783b47d"
|
||||
integrity sha512-iAXNlOWvcYUYoV8YIxwS7TxGRJcxyl8eQCfT+A5j8sKUzRFvJdcyjp97jL2IghWSRDaL2PU2O2tX8Cu9dTBq5A==
|
||||
"@babel/plugin-transform-for-of@^7.8.6":
|
||||
version "7.8.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.6.tgz#a051bd1b402c61af97a27ff51b468321c7c2a085"
|
||||
integrity sha512-M0pw4/1/KI5WAxPsdcUL/w2LJ7o89YHN3yLkzNjg7Yl15GlVGgzHyCU+FMeAxevHGsLVmUqbirlUIKTafPmzdw==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.8.3"
|
||||
|
||||
|
@ -665,12 +667,12 @@
|
|||
"@babel/helper-plugin-utils" "^7.8.3"
|
||||
"@babel/helper-replace-supers" "^7.8.3"
|
||||
|
||||
"@babel/plugin-transform-parameters@^7.8.4":
|
||||
version "7.8.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.4.tgz#1d5155de0b65db0ccf9971165745d3bb990d77d3"
|
||||
integrity sha512-IsS3oTxeTsZlE5KqzTbcC2sV0P9pXdec53SU+Yxv7o/6dvGM5AkTotQKhoSffhNgZ/dftsSiOoxy7evCYJXzVA==
|
||||
"@babel/plugin-transform-parameters@^7.8.7":
|
||||
version "7.8.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.7.tgz#66fa2f1de4129b4e0447509223ac71bda4955395"
|
||||
integrity sha512-brYWaEPTRimOctz2NDA3jnBbDi7SVN2T4wYuu0aqSzxC3nozFZngGaw29CJ9ZPweB7k+iFmZuoG3IVPIcXmD2g==
|
||||
dependencies:
|
||||
"@babel/helper-call-delegate" "^7.8.3"
|
||||
"@babel/helper-call-delegate" "^7.8.7"
|
||||
"@babel/helper-get-function-arity" "^7.8.3"
|
||||
"@babel/helper-plugin-utils" "^7.8.3"
|
||||
|
||||
|
@ -713,12 +715,12 @@
|
|||
"@babel/helper-plugin-utils" "^7.8.3"
|
||||
"@babel/plugin-syntax-jsx" "^7.8.3"
|
||||
|
||||
"@babel/plugin-transform-regenerator@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.3.tgz#b31031e8059c07495bf23614c97f3d9698bc6ec8"
|
||||
integrity sha512-qt/kcur/FxrQrzFR432FGZznkVAjiyFtCOANjkAKwCbt465L6ZCiUQh2oMYGU3Wo8LRFJxNDFwWn106S5wVUNA==
|
||||
"@babel/plugin-transform-regenerator@^7.8.7":
|
||||
version "7.8.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz#5e46a0dca2bee1ad8285eb0527e6abc9c37672f8"
|
||||
integrity sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA==
|
||||
dependencies:
|
||||
regenerator-transform "^0.14.0"
|
||||
regenerator-transform "^0.14.2"
|
||||
|
||||
"@babel/plugin-transform-reserved-words@^7.8.3":
|
||||
version "7.8.3"
|
||||
|
@ -775,9 +777,9 @@
|
|||
"@babel/helper-plugin-utils" "^7.8.3"
|
||||
|
||||
"@babel/plugin-transform-typescript@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.8.3.tgz#be6f01a7ef423be68e65ace1f04fc407e6d88917"
|
||||
integrity sha512-Ebj230AxcrKGZPKIp4g4TdQLrqX95TobLUWKd/CwG7X1XHUH1ZpkpFvXuXqWbtGRWb7uuEWNlrl681wsOArAdQ==
|
||||
version "7.8.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.8.7.tgz#48bccff331108a7b3a28c3a4adc89e036dc3efda"
|
||||
integrity sha512-7O0UsPQVNKqpHeHLpfvOG4uXmlw+MOxYvUv6Otc9uH5SYMIxvF6eBdjkWvC3f9G+VXe0RsNExyAQBeTRug/wqQ==
|
||||
dependencies:
|
||||
"@babel/helper-create-class-features-plugin" "^7.8.3"
|
||||
"@babel/helper-plugin-utils" "^7.8.3"
|
||||
|
@ -792,12 +794,12 @@
|
|||
"@babel/helper-plugin-utils" "^7.8.3"
|
||||
|
||||
"@babel/preset-env@^7.7.6":
|
||||
version "7.8.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.8.4.tgz#9dac6df5f423015d3d49b6e9e5fa3413e4a72c4e"
|
||||
integrity sha512-HihCgpr45AnSOHRbS5cWNTINs0TwaR8BS8xIIH+QwiW8cKL0llV91njQMpeMReEPVs+1Ao0x3RLEBLtt1hOq4w==
|
||||
version "7.8.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.8.7.tgz#1fc7d89c7f75d2d70c2b6768de6c2e049b3cb9db"
|
||||
integrity sha512-BYftCVOdAYJk5ASsznKAUl53EMhfBbr8CJ1X+AJLfGPscQkwJFiaV/Wn9DPH/7fzm2v6iRYJKYHSqyynTGw0nw==
|
||||
dependencies:
|
||||
"@babel/compat-data" "^7.8.4"
|
||||
"@babel/helper-compilation-targets" "^7.8.4"
|
||||
"@babel/compat-data" "^7.8.6"
|
||||
"@babel/helper-compilation-targets" "^7.8.7"
|
||||
"@babel/helper-module-imports" "^7.8.3"
|
||||
"@babel/helper-plugin-utils" "^7.8.3"
|
||||
"@babel/plugin-proposal-async-generator-functions" "^7.8.3"
|
||||
|
@ -820,13 +822,13 @@
|
|||
"@babel/plugin-transform-async-to-generator" "^7.8.3"
|
||||
"@babel/plugin-transform-block-scoped-functions" "^7.8.3"
|
||||
"@babel/plugin-transform-block-scoping" "^7.8.3"
|
||||
"@babel/plugin-transform-classes" "^7.8.3"
|
||||
"@babel/plugin-transform-classes" "^7.8.6"
|
||||
"@babel/plugin-transform-computed-properties" "^7.8.3"
|
||||
"@babel/plugin-transform-destructuring" "^7.8.3"
|
||||
"@babel/plugin-transform-dotall-regex" "^7.8.3"
|
||||
"@babel/plugin-transform-duplicate-keys" "^7.8.3"
|
||||
"@babel/plugin-transform-exponentiation-operator" "^7.8.3"
|
||||
"@babel/plugin-transform-for-of" "^7.8.4"
|
||||
"@babel/plugin-transform-for-of" "^7.8.6"
|
||||
"@babel/plugin-transform-function-name" "^7.8.3"
|
||||
"@babel/plugin-transform-literals" "^7.8.3"
|
||||
"@babel/plugin-transform-member-expression-literals" "^7.8.3"
|
||||
|
@ -837,9 +839,9 @@
|
|||
"@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3"
|
||||
"@babel/plugin-transform-new-target" "^7.8.3"
|
||||
"@babel/plugin-transform-object-super" "^7.8.3"
|
||||
"@babel/plugin-transform-parameters" "^7.8.4"
|
||||
"@babel/plugin-transform-parameters" "^7.8.7"
|
||||
"@babel/plugin-transform-property-literals" "^7.8.3"
|
||||
"@babel/plugin-transform-regenerator" "^7.8.3"
|
||||
"@babel/plugin-transform-regenerator" "^7.8.7"
|
||||
"@babel/plugin-transform-reserved-words" "^7.8.3"
|
||||
"@babel/plugin-transform-shorthand-properties" "^7.8.3"
|
||||
"@babel/plugin-transform-spread" "^7.8.3"
|
||||
|
@ -847,7 +849,7 @@
|
|||
"@babel/plugin-transform-template-literals" "^7.8.3"
|
||||
"@babel/plugin-transform-typeof-symbol" "^7.8.4"
|
||||
"@babel/plugin-transform-unicode-regex" "^7.8.3"
|
||||
"@babel/types" "^7.8.3"
|
||||
"@babel/types" "^7.8.7"
|
||||
browserslist "^4.8.5"
|
||||
core-js-compat "^3.6.2"
|
||||
invariant "^2.2.2"
|
||||
|
@ -882,9 +884,9 @@
|
|||
"@babel/plugin-transform-typescript" "^7.8.3"
|
||||
|
||||
"@babel/register@^7.7.4":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.8.3.tgz#5d5d30cfcc918437535d724b8ac1e4a60c5db1f8"
|
||||
integrity sha512-t7UqebaWwo9nXWClIPLPloa5pN33A2leVs8Hf0e9g9YwUP8/H9NeR7DJU+4CXo23QtjChQv5a3DjEtT83ih1rg==
|
||||
version "7.8.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.8.6.tgz#a1066aa6168a73a70c35ef28cc5865ccc087ea69"
|
||||
integrity sha512-7IDO93fuRsbyml7bAafBQb3RcBGlCpU4hh5wADA2LJEEcYk92WkwFZ0pHyIi2fb5Auoz1714abETdZKCOxN0CQ==
|
||||
dependencies:
|
||||
find-cache-dir "^2.0.0"
|
||||
lodash "^4.17.13"
|
||||
|
@ -892,41 +894,49 @@
|
|||
pirates "^4.0.0"
|
||||
source-map-support "^0.5.16"
|
||||
|
||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.8.3":
|
||||
version "7.8.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.4.tgz#d79f5a2040f7caa24d53e563aad49cbc05581308"
|
||||
integrity sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ==
|
||||
"@babel/runtime-corejs3@^7.8.3":
|
||||
version "7.8.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.8.7.tgz#8209d9dff2f33aa2616cb319c83fe159ffb07b8c"
|
||||
integrity sha512-sc7A+H4I8kTd7S61dgB9RomXu/C+F4IrRr4Ytze4dnfx7AXEpCrejSNpjx7vq6y/Bak9S6Kbk65a/WgMLtg43Q==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.2"
|
||||
core-js-pure "^3.0.0"
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/template@^7.4.0", "@babel/template@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.3.tgz#e02ad04fe262a657809327f578056ca15fd4d1b8"
|
||||
integrity sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==
|
||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4":
|
||||
version "7.8.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.7.tgz#8fefce9802db54881ba59f90bb28719b4996324d"
|
||||
integrity sha512-+AATMUFppJDw6aiR5NVPHqIQBlV/Pj8wY/EZH+lmvRdUo9xBaz/rF3alAwFJQavvKfeOlPE7oaaDHVbcySbCsg==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/template@^7.4.0", "@babel/template@^7.8.3", "@babel/template@^7.8.6":
|
||||
version "7.8.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b"
|
||||
integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.8.3"
|
||||
"@babel/parser" "^7.8.3"
|
||||
"@babel/types" "^7.8.3"
|
||||
"@babel/parser" "^7.8.6"
|
||||
"@babel/types" "^7.8.6"
|
||||
|
||||
"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.4":
|
||||
version "7.8.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.4.tgz#f0845822365f9d5b0e312ed3959d3f827f869e3c"
|
||||
integrity sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==
|
||||
"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.4", "@babel/traverse@^7.8.6":
|
||||
version "7.8.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.6.tgz#acfe0c64e1cd991b3e32eae813a6eb564954b5ff"
|
||||
integrity sha512-2B8l0db/DPi8iinITKuo7cbPznLCEk0kCxDoB9/N6gGNg/gxOXiR/IcymAFPiBwk5w6TtQ27w4wpElgp9btR9A==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.8.3"
|
||||
"@babel/generator" "^7.8.4"
|
||||
"@babel/generator" "^7.8.6"
|
||||
"@babel/helper-function-name" "^7.8.3"
|
||||
"@babel/helper-split-export-declaration" "^7.8.3"
|
||||
"@babel/parser" "^7.8.4"
|
||||
"@babel/types" "^7.8.3"
|
||||
"@babel/parser" "^7.8.6"
|
||||
"@babel/types" "^7.8.6"
|
||||
debug "^4.1.0"
|
||||
globals "^11.1.0"
|
||||
lodash "^4.17.13"
|
||||
|
||||
"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.7.0", "@babel/types@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c"
|
||||
integrity sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==
|
||||
"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.7.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.8.7":
|
||||
version "7.8.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.7.tgz#1fc9729e1acbb2337d5b6977a63979b4819f5d1d"
|
||||
integrity sha512-k2TreEHxFA4CjGkL+GYjRyx35W0Mr7DP5+9q6WMkyKXB+904bYmG40syjMFV0oLlhhFCwWl0vA0DyzTDkwAiJw==
|
||||
dependencies:
|
||||
esutils "^2.0.2"
|
||||
lodash "^4.17.13"
|
||||
|
@ -1109,7 +1119,7 @@
|
|||
asn1js "^2.0.22"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@peculiar/json-schema@^1.1.6":
|
||||
"@peculiar/json-schema@^1.1.9":
|
||||
version "1.1.9"
|
||||
resolved "https://registry.yarnpkg.com/@peculiar/json-schema/-/json-schema-1.1.9.tgz#b746e046b787607a1b2804f64437fda2527b3e62"
|
||||
integrity sha512-F2ST2y/IQPgY+1QMw1Q33sqJbGDCeO3lGqI69SL3Hgo0++7iHqprUB1QyxB/A7bN3tuM65MBxoM2JLbwh42lsQ==
|
||||
|
@ -1117,15 +1127,15 @@
|
|||
tslib "^1.10.0"
|
||||
|
||||
"@peculiar/webcrypto@^1.0.22":
|
||||
version "1.0.22"
|
||||
resolved "https://registry.yarnpkg.com/@peculiar/webcrypto/-/webcrypto-1.0.22.tgz#9dae652fce6bacd9df15bc91965797cee33adf67"
|
||||
integrity sha512-NP6H6ZGXUvJnQJCWzUgnRcQv+9nMCNwLUDhTwOxRUwPFvtHauMOl0oPTKUjbhInCMaE55gJqB4yc0YKbde6Exw==
|
||||
version "1.0.23"
|
||||
resolved "https://registry.yarnpkg.com/@peculiar/webcrypto/-/webcrypto-1.0.23.tgz#5519b839fba2cf8603bbbd6764dc41b108093dad"
|
||||
integrity sha512-Ssb4xpQI3BJ0itAtT9y9jyeeiWNjcFvP6Wt/ehITxRYrEnlSfnrP7Ytc7BwN8XtnKmXDS2cWvppPldw5QsFCcw==
|
||||
dependencies:
|
||||
"@peculiar/asn1-schema" "^1.0.3"
|
||||
"@peculiar/json-schema" "^1.1.6"
|
||||
"@peculiar/json-schema" "^1.1.9"
|
||||
asn1js "^2.0.26"
|
||||
pvtsutils "^1.0.9"
|
||||
tslib "^1.10.0"
|
||||
tslib "^1.11.1"
|
||||
webcrypto-core "^1.0.17"
|
||||
|
||||
"@sinonjs/commons@^1.7.0":
|
||||
|
@ -1168,6 +1178,11 @@
|
|||
dependencies:
|
||||
"@babel/types" "^7.3.0"
|
||||
|
||||
"@types/classnames@^2.2.10":
|
||||
version "2.2.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.10.tgz#cc658ca319b6355399efc1f5b9e818f1a24bf999"
|
||||
integrity sha512-1UzDldn9GfYYEsWWnn/P4wkTlkZDH7lDb0wBMGbtIQc9zXEQq7FlKBdZUn6OBqD8sKZZ2RQO2mAjGpXiDGoRmQ==
|
||||
|
||||
"@types/events@*":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
|
||||
|
@ -1213,9 +1228,22 @@
|
|||
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
|
||||
|
||||
"@types/node@*":
|
||||
version "13.7.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.7.6.tgz#cb734a7c191472ae6a2b3a502b4dfffcea974113"
|
||||
integrity sha512-eyK7MWD0R1HqVTp+PtwRgFeIsemzuj4gBFSQxfPHY5iMjS7474e5wq+VFgTcdpyHeNxyKSaetYAjdMLJlKoWqA==
|
||||
version "13.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.9.0.tgz#5b6ee7a77faacddd7de719017d0bc12f52f81589"
|
||||
integrity sha512-0ARSQootUG1RljH2HncpsY2TJBfGQIKOOi7kxzUY6z54ePu/ZD+wJA8zI2Q6v8rol2qpG/rvqsReco8zNMPvhQ==
|
||||
|
||||
"@types/prop-types@*":
|
||||
version "15.7.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
|
||||
integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
|
||||
|
||||
"@types/react@16.9":
|
||||
version "16.9.23"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.23.tgz#1a66c6d468ba11a8943ad958a8cb3e737568271c"
|
||||
integrity sha512-SsGVT4E7L2wLN3tPYLiF20hmZTPGuzaayVunfgXzUn1x4uHVsKH6QDJQ/TdpHqwsTLd4CwrmQ2vOgxN7gE24gw==
|
||||
dependencies:
|
||||
"@types/prop-types" "*"
|
||||
csstype "^2.2.0"
|
||||
|
||||
"@types/stack-utils@^1.0.1":
|
||||
version "1.0.1"
|
||||
|
@ -1256,18 +1284,18 @@
|
|||
"@types/yargs-parser" "*"
|
||||
|
||||
"@typescript-eslint/experimental-utils@^2.5.0":
|
||||
version "2.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.21.0.tgz#71de390a3ec00b280b69138d80733406e6e86bfa"
|
||||
integrity sha512-olKw9JP/XUkav4lq0I7S1mhGgONJF9rHNhKFn9wJlpfRVjNo3PPjSvybxEldvCXnvD+WAshSzqH5cEjPp9CsBA==
|
||||
version "2.23.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.23.0.tgz#5d2261c8038ec1698ca4435a8da479c661dc9242"
|
||||
integrity sha512-OswxY59RcXH3NNPmq+4Kis2CYZPurRU6mG5xPcn24CjFyfdVli5mySwZz/g/xDbJXgDsYqNGq7enV0IziWGXVQ==
|
||||
dependencies:
|
||||
"@types/json-schema" "^7.0.3"
|
||||
"@typescript-eslint/typescript-estree" "2.21.0"
|
||||
"@typescript-eslint/typescript-estree" "2.23.0"
|
||||
eslint-scope "^5.0.0"
|
||||
|
||||
"@typescript-eslint/typescript-estree@2.21.0":
|
||||
version "2.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.21.0.tgz#7e4be29f2e338195a2e8c818949ed0ff727cc943"
|
||||
integrity sha512-NC/nogZNb9IK2MEFQqyDBAciOT8Lp8O3KgAfvHx2Skx6WBo+KmDqlU3R9KxHONaijfTIKtojRe3SZQyMjr3wBw==
|
||||
"@typescript-eslint/typescript-estree@2.23.0":
|
||||
version "2.23.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.23.0.tgz#d355960fab96bd550855488dcc34b9a4acac8d36"
|
||||
integrity sha512-pmf7IlmvXdlEXvE/JWNNJpEvwBV59wtJqA8MLAxMKLXNKVRC3HZBXR/SlZLPWTCcwOSg9IM7GeRSV3SIerGVqw==
|
||||
dependencies:
|
||||
debug "^4.1.1"
|
||||
eslint-visitor-keys "^1.1.0"
|
||||
|
@ -1457,14 +1485,14 @@ acorn-walk@^6.0.1:
|
|||
integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==
|
||||
|
||||
acorn@^5.5.3:
|
||||
version "5.7.3"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279"
|
||||
integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==
|
||||
version "5.7.4"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e"
|
||||
integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==
|
||||
|
||||
acorn@^6.0.1, acorn@^6.0.7, acorn@^6.2.1:
|
||||
version "6.4.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784"
|
||||
integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==
|
||||
version "6.4.1"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474"
|
||||
integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==
|
||||
|
||||
agent-base@4, agent-base@^4.3.0:
|
||||
version "4.3.0"
|
||||
|
@ -1951,10 +1979,10 @@ browser-encrypt-attachment@^0.3.0:
|
|||
resolved "https://registry.yarnpkg.com/browser-encrypt-attachment/-/browser-encrypt-attachment-0.3.0.tgz#205a94caadf0dc7e81413941812f655bd190ff1c"
|
||||
integrity sha1-IFqUyq3w3H6BQTlBgS9lW9GQ/xw=
|
||||
|
||||
browser-process-hrtime@^0.1.2:
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz#616f00faef1df7ec1b5bf9cfe2bdc3170f26c7b4"
|
||||
integrity sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==
|
||||
browser-process-hrtime@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626"
|
||||
integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==
|
||||
|
||||
browser-request@^0.3.3:
|
||||
version "0.3.3"
|
||||
|
@ -2027,14 +2055,14 @@ browserify-zlib@^0.2.0:
|
|||
dependencies:
|
||||
pako "~1.0.5"
|
||||
|
||||
browserslist@^4.8.3, browserslist@^4.8.5:
|
||||
version "4.8.7"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.7.tgz#ec8301ff415e6a42c949d0e66b405eb539c532d0"
|
||||
integrity sha512-gFOnZNYBHrEyUML0xr5NJ6edFaaKbTFX9S9kQHlYfCP0Rit/boRIz4G+Avq6/4haEKJXdGGUnoolx+5MWW2BoA==
|
||||
browserslist@^4.8.3, browserslist@^4.8.5, browserslist@^4.9.1:
|
||||
version "4.9.1"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.9.1.tgz#01ffb9ca31a1aef7678128fc6a2253316aa7287c"
|
||||
integrity sha512-Q0DnKq20End3raFulq6Vfp1ecB9fh8yUNV55s8sekaDDeqBaCtWlRHCUdaWyUeSSBJM7IbM6HcsyaeYqgeDhnw==
|
||||
dependencies:
|
||||
caniuse-lite "^1.0.30001027"
|
||||
electron-to-chromium "^1.3.349"
|
||||
node-releases "^1.1.49"
|
||||
caniuse-lite "^1.0.30001030"
|
||||
electron-to-chromium "^1.3.363"
|
||||
node-releases "^1.1.50"
|
||||
|
||||
bs58@^4.0.1:
|
||||
version "4.0.1"
|
||||
|
@ -2088,9 +2116,9 @@ buffer@^4.3.0:
|
|||
isarray "^1.0.0"
|
||||
|
||||
buffer@^5.4.3:
|
||||
version "5.4.3"
|
||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.4.3.tgz#3fbc9c69eb713d323e3fc1a895eee0710c072115"
|
||||
integrity sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==
|
||||
version "5.5.0"
|
||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.5.0.tgz#9c3caa3d623c33dd1c7ef584b89b88bf9c9bc1ce"
|
||||
integrity sha512-9FTEDjLjwoAkEwyMGDjYJQN2gfRgOKBKRfiglhvibGbpeeU/pQn1bJxQqm32OD/AIeEuHxU9roxXxg34Byp/Ww==
|
||||
dependencies:
|
||||
base64-js "^1.0.2"
|
||||
ieee754 "^1.1.4"
|
||||
|
@ -2189,10 +2217,10 @@ camelcase@^5.0.0, camelcase@^5.3.1:
|
|||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
|
||||
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
|
||||
|
||||
caniuse-lite@^1.0.30001020, caniuse-lite@^1.0.30001027:
|
||||
version "1.0.30001030"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001030.tgz#78076c4c6d67d3e41d6eb9399853fb27fe6e44ee"
|
||||
integrity sha512-QGK0W4Ft/Ac+zTjEiRJfwDNATvS3fodDczBXrH42784kcfqcDKpEPfN08N0HQjrAp8He/Jw8QiSS9QRn7XAbUw==
|
||||
caniuse-lite@^1.0.30001020, caniuse-lite@^1.0.30001030:
|
||||
version "1.0.30001033"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001033.tgz#60c328fb56860de60f9a2cb419c31fb80587cba0"
|
||||
integrity sha512-8Ibzxee6ibc5q88cM1usPsMpJOG5CTq0s/dKOmlekPbDGKt+UrnOOTPSjQz3kVo6yL7N4SB5xd+FGLHQmbzh6A==
|
||||
|
||||
capture-exit@^2.0.0:
|
||||
version "2.0.0"
|
||||
|
@ -2523,6 +2551,11 @@ core-js-compat@^3.6.2:
|
|||
browserslist "^4.8.3"
|
||||
semver "7.0.0"
|
||||
|
||||
core-js-pure@^3.0.0:
|
||||
version "3.6.4"
|
||||
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.4.tgz#4bf1ba866e25814f149d4e9aaa08c36173506e3a"
|
||||
integrity sha512-epIhRLkXdgv32xIUFaaAry2wdxZYBi6bgM7cB136dzzXXa+dFyRLTZeLUJxnd8ShrmyVXBub63n2NHo2JAt8Cw==
|
||||
|
||||
core-js@^1.0.0:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
|
||||
|
@ -2664,6 +2697,11 @@ cssstyle@^1.0.0:
|
|||
dependencies:
|
||||
cssom "0.3.x"
|
||||
|
||||
csstype@^2.2.0:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.9.tgz#05141d0cd557a56b8891394c1911c40c8a98d098"
|
||||
integrity sha512-xz39Sb4+OaTsULgUERcCk+TJj8ylkL4aSVDQiX/ksxbELSqwkgt4d4RD7fovIdgJGSuNYqwZEiVjYY5l0ask+Q==
|
||||
|
||||
currently-unhandled@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
|
||||
|
@ -2987,10 +3025,10 @@ ecc-jsbn@~0.1.1:
|
|||
jsbn "~0.1.0"
|
||||
safer-buffer "^2.1.0"
|
||||
|
||||
electron-to-chromium@^1.3.349:
|
||||
version "1.3.361"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.361.tgz#a820bf52da171c0024314745462cfe0dc944373e"
|
||||
integrity sha512-OzSVjWpsRhJyr9PSAXkeloSe6e9viU2ToGt1wXlXFsGcxuI9vlsnalL+V/AM59Z2pEo3wRxIddtOGsT7Y6x/sQ==
|
||||
electron-to-chromium@^1.3.363:
|
||||
version "1.3.375"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.375.tgz#e290d59d316024e5499057944c10d05c518b7a24"
|
||||
integrity sha512-zmaFnYVBtfpF8bGRYxgPeVAlXB7N3On8rjBE2ROc6wOpTPpzRWaiHo6KkbJMvlH07CH33uks/TEb6kuMMn8q6A==
|
||||
|
||||
elliptic@^6.0.0:
|
||||
version "6.5.2"
|
||||
|
@ -3252,21 +3290,21 @@ eslint-plugin-flowtype@^2.30.0:
|
|||
lodash "^4.17.10"
|
||||
|
||||
eslint-plugin-jest@^23.0.4:
|
||||
version "23.8.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.8.0.tgz#c978f959fa8395801742d13c5a3125a986d2661e"
|
||||
integrity sha512-DKXmLxguZ1Lru4u5YM12ko3WLq6gqo7dhV2b63K731+/PNyZ/Ff6NGONQsGUtPLG9zU3kdz/N+2LTbweNZifeg==
|
||||
version "23.8.2"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.8.2.tgz#6f28b41c67ef635f803ebd9e168f6b73858eb8d4"
|
||||
integrity sha512-xwbnvOsotSV27MtAe7s8uGWOori0nUsrXh2f1EnpmXua8sDfY6VZhHAhHg2sqK7HBNycRQExF074XSZ7DvfoFg==
|
||||
dependencies:
|
||||
"@typescript-eslint/experimental-utils" "^2.5.0"
|
||||
|
||||
eslint-plugin-react-hooks@^2.0.1:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-2.4.0.tgz#db6ee1cc953e3a217035da3d4e9d4356d3c672a4"
|
||||
integrity sha512-bH5DOCP6WpuOqNaux2BlaDCrSgv8s5BitP90bTgtZ1ZsRn2bdIfeMDY5F2RnJVnyKDy6KRQRDbipPLZ1y77QtQ==
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-2.5.0.tgz#c50ab7ca5945ce6d1cf8248d9e185c80b54171b6"
|
||||
integrity sha512-bzvdX47Jx847bgAYf0FPX3u1oxU+mKU8tqrpj4UX9A96SbAmj/HVEefEy6rJUog5u8QIlOPTKZcBpGn5kkKfAQ==
|
||||
|
||||
eslint-plugin-react@^7.7.0:
|
||||
version "7.18.3"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.18.3.tgz#8be671b7f6be095098e79d27ac32f9580f599bc8"
|
||||
integrity sha512-Bt56LNHAQCoou88s8ViKRjMB2+36XRejCQ1VoLj716KI1MoE99HpTVvIThJ0rvFmG4E4Gsq+UgToEjn+j044Bg==
|
||||
version "7.19.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.19.0.tgz#6d08f9673628aa69c5559d33489e855d83551666"
|
||||
integrity sha512-SPT8j72CGuAP+JFbT0sJHOB80TX/pu44gQ4vXH/cq+hQTiY2PuZ6IHkqXJV6x1b28GDdo1lbInjKUrrdUf0LOQ==
|
||||
dependencies:
|
||||
array-includes "^3.1.1"
|
||||
doctrine "^2.1.0"
|
||||
|
@ -3276,8 +3314,10 @@ eslint-plugin-react@^7.7.0:
|
|||
object.fromentries "^2.0.2"
|
||||
object.values "^1.1.1"
|
||||
prop-types "^15.7.2"
|
||||
resolve "^1.14.2"
|
||||
resolve "^1.15.1"
|
||||
semver "^6.3.0"
|
||||
string.prototype.matchall "^4.0.2"
|
||||
xregexp "^4.3.0"
|
||||
|
||||
eslint-rule-composer@^0.3.0:
|
||||
version "0.3.0"
|
||||
|
@ -3867,10 +3907,6 @@ fuse.js@^2.2.0:
|
|||
resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-2.7.4.tgz#96e420fde7ef011ac49c258a621314fe576536f9"
|
||||
integrity sha1-luQg/efvARrEnCWKYhMU/ldlNvk=
|
||||
|
||||
"gemini-scrollbar@github:matrix-org/gemini-scrollbar#91e1e566", gemini-scrollbar@matrix-org/gemini-scrollbar#91e1e566:
|
||||
version "1.4.3"
|
||||
resolved "https://codeload.github.com/matrix-org/gemini-scrollbar/tar.gz/91e1e566fa33324188f278801baf4a79f9f554ab"
|
||||
|
||||
gensync@^1.0.0-beta.1:
|
||||
version "1.0.0-beta.1"
|
||||
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269"
|
||||
|
@ -4158,9 +4194,9 @@ hosted-git-info@3.0.0:
|
|||
lru-cache "^5.1.1"
|
||||
|
||||
hosted-git-info@^2.1.4:
|
||||
version "2.8.6"
|
||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.6.tgz#3a6e6d0324c5371fc8c7ba7175e1e5d14578724d"
|
||||
integrity sha512-Kp6rShEsCHhF5dD3EWKdkgVA8ix90oSUJ0VY4g9goxxa0+f4lx63muTftn0mlJ/+8IESGWyKnP//V2D7S4ZbIQ==
|
||||
version "2.8.8"
|
||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
|
||||
integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
|
||||
|
||||
html-element-map@^1.2.0:
|
||||
version "1.2.0"
|
||||
|
@ -5654,8 +5690,8 @@ mathml-tag-names@^2.0.1:
|
|||
integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==
|
||||
|
||||
"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop":
|
||||
version "5.1.0"
|
||||
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/86304fd037ac43a493000fa42f393eaafc0480ac"
|
||||
version "5.1.1"
|
||||
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/b2e154377a4268441a3b27b183dd7f7018187035"
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.8.3"
|
||||
another-json "^0.2.0"
|
||||
|
@ -5840,11 +5876,16 @@ minimist@1.1.x:
|
|||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8"
|
||||
integrity sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag=
|
||||
|
||||
minimist@1.2.0, minimist@^1.1.1, minimist@^1.2.0, "minimist@~ 1.2.0":
|
||||
minimist@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
|
||||
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
|
||||
|
||||
minimist@^1.1.1, minimist@^1.2.0, "minimist@~ 1.2.0":
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.3.tgz#3db5c0765545ab8637be71f333a104a965a9ca3f"
|
||||
integrity sha512-+bMdgqjMN/Z77a6NlY/I3U5LlRDbnmaAk6lDveAPKwSpcPM4tKAuYsvYF8xjhOPXhOYGe/73vVLVez5PW+jqhw==
|
||||
|
||||
mississippi@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022"
|
||||
|
@ -6023,10 +6064,10 @@ node-notifier@^5.4.2:
|
|||
shellwords "^0.1.1"
|
||||
which "^1.3.0"
|
||||
|
||||
node-releases@^1.1.49:
|
||||
version "1.1.50"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.50.tgz#803c40d2c45db172d0410e4efec83aa8c6ad0592"
|
||||
integrity sha512-lgAmPv9eYZ0bGwUYAKlr8MG6K4CvWliWqnkcT2P8mMAgVrH3lqfBPorFlxiG1pHQnqmavJZ9vbMXUTNyMLbrgQ==
|
||||
node-releases@^1.1.50:
|
||||
version "1.1.51"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.51.tgz#70d0e054221343d2966006bfbd4d98622cc00bd0"
|
||||
integrity sha512-1eQEs6HFYY1kMXQPOLzCf7HdjReErmvn85tZESMczdCNVWP3Y7URYLBAyYynuI7yef1zj4HN5q+oB2x67QU0lw==
|
||||
dependencies:
|
||||
semver "^6.3.0"
|
||||
|
||||
|
@ -6631,7 +6672,7 @@ pretty-format@^24.9.0:
|
|||
ansi-styles "^3.2.0"
|
||||
react-is "^16.8.4"
|
||||
|
||||
private@^0.1.6:
|
||||
private@^0.1.8:
|
||||
version "0.1.8"
|
||||
resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
|
||||
integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==
|
||||
|
@ -6902,14 +6943,14 @@ react-clientside-effect@^1.2.2:
|
|||
"@babel/runtime" "^7.0.0"
|
||||
|
||||
react-dom@^16.9.0:
|
||||
version "16.12.0"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.12.0.tgz#0da4b714b8d13c2038c9396b54a92baea633fe11"
|
||||
integrity sha512-LMxFfAGrcS3kETtQaCkTKjMiifahaMySFDn71fZUNpPHZQEzmk/GiAeIT8JSOrHB23fnuCOMruL2a8NYlw+8Gw==
|
||||
version "16.13.0"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.0.tgz#cdde54b48eb9e8a0ca1b3dc9943d9bb409b81866"
|
||||
integrity sha512-y09d2c4cG220DzdlFkPTnVvGTszVvNpC73v+AaLGLHbkpy3SSgvYq8x0rNwPJ/Rk/CicTNgk0hbHNw1gMEZAXg==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
prop-types "^15.6.2"
|
||||
scheduler "^0.18.0"
|
||||
scheduler "^0.19.0"
|
||||
|
||||
react-focus-lock@^2.2.1:
|
||||
version "2.2.1"
|
||||
|
@ -6923,16 +6964,10 @@ react-focus-lock@^2.2.1:
|
|||
use-callback-ref "^1.2.1"
|
||||
use-sidecar "^1.0.1"
|
||||
|
||||
"react-gemini-scrollbar@github:matrix-org/react-gemini-scrollbar#9cf17f63b7c0b0ec5f31df27da0f82f7238dc594":
|
||||
version "2.1.5"
|
||||
resolved "https://codeload.github.com/matrix-org/react-gemini-scrollbar/tar.gz/9cf17f63b7c0b0ec5f31df27da0f82f7238dc594"
|
||||
dependencies:
|
||||
gemini-scrollbar matrix-org/gemini-scrollbar#91e1e566
|
||||
|
||||
react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0:
|
||||
version "16.12.0"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c"
|
||||
integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==
|
||||
version "16.13.0"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.0.tgz#0f37c3613c34fe6b37cd7f763a0d6293ab15c527"
|
||||
integrity sha512-GFMtL0vHkiBv9HluwNZTggSn/sCyEt9n02aM0dSAjGGyqyNlAyftYm4phPxdvCigG15JreC5biwxCgTAJZ7yAA==
|
||||
|
||||
react-lifecycles-compat@^3.0.0:
|
||||
version "3.0.4"
|
||||
|
@ -6962,14 +6997,14 @@ react-redux@^5.0.6:
|
|||
react-lifecycles-compat "^3.0.0"
|
||||
|
||||
react-test-renderer@^16.0.0-0, react-test-renderer@^16.9.0:
|
||||
version "16.12.0"
|
||||
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.12.0.tgz#11417ffda579306d4e841a794d32140f3da1b43f"
|
||||
integrity sha512-Vj/teSqt2oayaWxkbhQ6gKis+t5JrknXfPVo+aIJ8QwYAqMPH77uptOdrlphyxl8eQI/rtkOYg86i/UWkpFu0w==
|
||||
version "16.13.0"
|
||||
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.13.0.tgz#39ba3bf72cedc8210c3f81983f0bb061b14a3014"
|
||||
integrity sha512-NQ2S9gdMUa7rgPGpKGyMcwl1d6D9MCF0lftdI3kts6kkiX+qvpC955jNjAZXlIDTjnN9jwFI8A8XhRh/9v0spA==
|
||||
dependencies:
|
||||
object-assign "^4.1.1"
|
||||
prop-types "^15.6.2"
|
||||
react-is "^16.8.6"
|
||||
scheduler "^0.18.0"
|
||||
scheduler "^0.19.0"
|
||||
|
||||
react-transition-group@^1.2.0:
|
||||
version "1.2.1"
|
||||
|
@ -6983,9 +7018,9 @@ react-transition-group@^1.2.0:
|
|||
warning "^3.0.0"
|
||||
|
||||
react@^16.9.0:
|
||||
version "16.12.0"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-16.12.0.tgz#0c0a9c6a142429e3614834d5a778e18aa78a0b83"
|
||||
integrity sha512-fglqy3k5E+81pA8s+7K0/T3DBCF0ZDOher1elBFzF7O6arXJgzyu/FW+COxFvAWXJoJN9KIZbT2LXlukwphYTA==
|
||||
version "16.13.0"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-16.13.0.tgz#d046eabcdf64e457bbeed1e792e235e1b9934cf7"
|
||||
integrity sha512-TSavZz2iSLkq5/oiE7gnFzmURKZMltmi193rm5HEoUDAXpzT9Kzw6oNZnGoai/4+fUnm7FqS5dwgUL34TujcWQ==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
@ -7115,17 +7150,18 @@ regenerator-runtime@^0.11.0:
|
|||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
|
||||
integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
|
||||
|
||||
regenerator-runtime@^0.13.2:
|
||||
version "0.13.3"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5"
|
||||
integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==
|
||||
regenerator-runtime@^0.13.4:
|
||||
version "0.13.4"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.4.tgz#e96bf612a3362d12bb69f7e8f74ffeab25c7ac91"
|
||||
integrity sha512-plpwicqEzfEyTQohIKktWigcLzmNStMGwbOUbykx51/29Z3JOGYldaaNGK7ngNXV+UcoqvIMmloZ48Sr74sd+g==
|
||||
|
||||
regenerator-transform@^0.14.0:
|
||||
version "0.14.1"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb"
|
||||
integrity sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==
|
||||
regenerator-transform@^0.14.2:
|
||||
version "0.14.2"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.2.tgz#949d9d87468ff88d5a7e4734ebb994a892de1ff2"
|
||||
integrity sha512-V4+lGplCM/ikqi5/mkkpJ06e9Bujq1NFmNLvsCs56zg3ZbzrnUzAtizZ24TXxtRX/W2jcdScwQCnbL0CICTFkQ==
|
||||
dependencies:
|
||||
private "^0.1.6"
|
||||
"@babel/runtime" "^7.8.4"
|
||||
private "^0.1.8"
|
||||
|
||||
regex-not@^1.0.0, regex-not@^1.0.2:
|
||||
version "1.0.2"
|
||||
|
@ -7174,9 +7210,9 @@ regjsgen@^0.5.0:
|
|||
integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==
|
||||
|
||||
regjsparser@^0.6.0:
|
||||
version "0.6.3"
|
||||
resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.3.tgz#74192c5805d35e9f5ebe3c1fb5b40d40a8a38460"
|
||||
integrity sha512-8uZvYbnfAtEm9Ab8NTb3hdLwL4g/LQzEYP7Xs27T96abJCCE2d6r3cPZPQEsLKy0vRSGVNG+/zVGtLr86HQduA==
|
||||
version "0.6.4"
|
||||
resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.4.tgz#a769f8684308401a66e9b529d2436ff4d0666272"
|
||||
integrity sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==
|
||||
dependencies:
|
||||
jsesc "~0.5.0"
|
||||
|
||||
|
@ -7352,7 +7388,7 @@ resolve@1.1.7:
|
|||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
|
||||
integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
|
||||
|
||||
resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.3.2, resolve@^1.8.1:
|
||||
resolve@^1.10.0, resolve@^1.12.0, resolve@^1.15.1, resolve@^1.3.2, resolve@^1.8.1:
|
||||
version "1.15.1"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8"
|
||||
integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==
|
||||
|
@ -7400,9 +7436,9 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
|
|||
inherits "^2.0.1"
|
||||
|
||||
rollup-plugin-terser@^5.1.1:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-5.2.0.tgz#ba758adf769347b7f1eaf9ef35978d2e207dccc7"
|
||||
integrity sha512-jQI+nYhtDBc9HFRBz8iGttQg7li9klmzR62RG2W2nN6hJ/FI2K2ItYQ7kJ7/zn+vs+BP1AEccmVRjRN989I+Nw==
|
||||
version "5.3.0"
|
||||
resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-5.3.0.tgz#9c0dd33d5771df9630cd027d6a2559187f65885e"
|
||||
integrity sha512-XGMJihTIO3eIBsVGq7jiNYOdDMb3pVxuzY0uhOE/FM4x/u9nQgr3+McsjzqBn3QfHIpNSZmFnpoKAwHBEcsT7g==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.5.5"
|
||||
jest-worker "^24.9.0"
|
||||
|
@ -7509,10 +7545,10 @@ sax@^1.2.4:
|
|||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
|
||||
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
|
||||
|
||||
scheduler@^0.18.0:
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.18.0.tgz#5901ad6659bc1d8f3fdaf36eb7a67b0d6746b1c4"
|
||||
integrity sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ==
|
||||
scheduler@^0.19.0:
|
||||
version "0.19.0"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.0.tgz#a715d56302de403df742f4a9be11975b32f5698d"
|
||||
integrity sha512-xowbVaTPe9r7y7RUejcK73/j8tt2jfiyTednOvHbA8JoClvMYCp+r8QegLwK/n8zWQAtZb1fFnER4XLBZXrCxA==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
@ -8161,9 +8197,9 @@ terser-webpack-plugin@^1.4.3:
|
|||
worker-farm "^1.7.0"
|
||||
|
||||
terser@^4.1.2, terser@^4.6.2:
|
||||
version "4.6.4"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.4.tgz#40a0b37afbe5b57e494536815efa68326840fc00"
|
||||
integrity sha512-5fqgBPLgVHZ/fVvqRhhUp9YUiGXhFJ9ZkrZWD9vQtFBR4QIGTnbsb+/kKqSqfgp3WnBwGWAFnedGTtmX1YTn0w==
|
||||
version "4.6.6"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.6.tgz#da2382e6cafbdf86205e82fb9a115bd664d54863"
|
||||
integrity sha512-4lYPyeNmstjIIESr/ysHg2vUPRGf2tzF9z2yYwnowXVuVzLEamPN1Gfrz7f8I9uEPuHcbFlW4PLIAsJoxXyJ1g==
|
||||
dependencies:
|
||||
commander "^2.20.0"
|
||||
source-map "~0.6.1"
|
||||
|
@ -8313,10 +8349,10 @@ trough@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406"
|
||||
integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==
|
||||
|
||||
tslib@^1.10.0, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
|
||||
version "1.11.0"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.0.tgz#f1f3528301621a53220d58373ae510ff747a66bc"
|
||||
integrity sha512-BmndXUtiTn/VDDrJzQE7Mm22Ix3PxgLltW9bSNLoeCY31gnG2OPx0QqJnuc9oMIKioYrz487i6K9o4Pdn0j+Kg==
|
||||
tslib@^1.10.0, tslib@^1.11.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
|
||||
version "1.11.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35"
|
||||
integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==
|
||||
|
||||
tslint@^5.20.1:
|
||||
version "5.20.1"
|
||||
|
@ -8386,9 +8422,9 @@ typedarray@^0.0.6:
|
|||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||
|
||||
typescript@^3.7.3:
|
||||
version "3.8.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.2.tgz#91d6868aaead7da74f493c553aeff76c0c0b1d5a"
|
||||
integrity sha512-EgOVgL/4xfVrCMbhYKUQTdF37SQn4Iw73H5BgCrF1Abdun7Kwy/QZsE/ssAy0y4LxBbvua3PIbFsbRczWWnDdQ==
|
||||
version "3.8.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061"
|
||||
integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==
|
||||
|
||||
ua-parser-js@^0.7.18:
|
||||
version "0.7.21"
|
||||
|
@ -8404,9 +8440,9 @@ unherit@^1.0.4:
|
|||
xtend "^4.0.0"
|
||||
|
||||
unhomoglyph@^1.0.2:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/unhomoglyph/-/unhomoglyph-1.0.4.tgz#38d2ec9de84ab921623ebd9fb60f710963c601f4"
|
||||
integrity sha512-+y+QeEXwm4f0H8Tmy9fFUWHM95YcFjJLlv83/p3+EARUkeJBxnSOBADVyeuSq0TsRJ/UexxCXBKXo40ksu715w==
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/unhomoglyph/-/unhomoglyph-1.0.5.tgz#a68c6244f0ec140bfe58293a1f66a9bd2a244343"
|
||||
integrity sha512-rNAw2rGogjq4BVhsCX8K6qXrCcHmUaMCHETlUG0ujGZ3OHwnzJHwdMyzy3n/c9Y7lvlbckOd9nkW33grUVE3bg==
|
||||
|
||||
unicode-canonical-property-names-ecmascript@^1.0.4:
|
||||
version "1.0.4"
|
||||
|
@ -8499,9 +8535,9 @@ unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1:
|
|||
integrity sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==
|
||||
|
||||
unist-util-stringify-position@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.2.tgz#5a3866e7138d55974b640ec69a94bc19e0f3fa12"
|
||||
integrity sha512-nK5n8OGhZ7ZgUwoUbL8uiVRwAbZyzBsB/Ddrlbu6jwwubFza4oe15KlyEaLNMXQW1svOQq4xesUeqA85YrIUQA==
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da"
|
||||
integrity sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==
|
||||
dependencies:
|
||||
"@types/unist" "^2.0.2"
|
||||
|
||||
|
@ -8653,9 +8689,9 @@ vfile-location@^2.0.0:
|
|||
integrity sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==
|
||||
|
||||
vfile-message@*:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.2.tgz#75ba05090ec758fa8420f2c11ce049bcddd8cf3e"
|
||||
integrity sha512-gNV2Y2fDvDOOqq8bEe7cF3DXU6QgV4uA9zMR2P8tix11l1r7zju3zry3wZ8sx+BEfuO6WQ7z2QzfWTvqHQiwsA==
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.3.tgz#0dd4f6879fb240a8099b22bd3755536c92e59ba5"
|
||||
integrity sha512-qQg/2z8qnnBHL0psXyF72kCjb9YioIynvyltuNKFaUhRtqTIcIMP3xnBaPzirVZNuBrUe1qwFciSx2yApa4byw==
|
||||
dependencies:
|
||||
"@types/unist" "^2.0.0"
|
||||
unist-util-stringify-position "^2.0.0"
|
||||
|
@ -8683,11 +8719,11 @@ vm-browserify@^1.0.1:
|
|||
integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
|
||||
|
||||
w3c-hr-time@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045"
|
||||
integrity sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd"
|
||||
integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==
|
||||
dependencies:
|
||||
browser-process-hrtime "^0.1.2"
|
||||
browser-process-hrtime "^1.0.0"
|
||||
|
||||
walk@^2.3.9:
|
||||
version "2.3.14"
|
||||
|
@ -8758,9 +8794,9 @@ webpack-sources@^1.4.0, webpack-sources@^1.4.1:
|
|||
source-map "~0.6.1"
|
||||
|
||||
webpack@^4.20.2:
|
||||
version "4.41.6"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.41.6.tgz#12f2f804bf6542ef166755050d4afbc8f66ba7e1"
|
||||
integrity sha512-yxXfV0Zv9WMGRD+QexkZzmGIh54bsvEs+9aRWxnN8erLWEOehAKUTeNBoUbA6HPEZPlRo7KDi2ZcNveoZgK9MA==
|
||||
version "4.42.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.42.0.tgz#b901635dd6179391d90740a63c93f76f39883eb8"
|
||||
integrity sha512-EzJRHvwQyBiYrYqhyjW9AqM90dE4+s1/XtCfn7uWg6cS72zH+2VPFAlsnW0+W0cDi0XRjNKUMoJtpSi50+Ph6w==
|
||||
dependencies:
|
||||
"@webassemblyjs/ast" "1.8.5"
|
||||
"@webassemblyjs/helper-module-context" "1.8.5"
|
||||
|
@ -8787,9 +8823,9 @@ webpack@^4.20.2:
|
|||
webpack-sources "^1.4.1"
|
||||
|
||||
what-input@^5.2.6:
|
||||
version "5.2.6"
|
||||
resolved "https://registry.yarnpkg.com/what-input/-/what-input-5.2.6.tgz#ac6f003bf8d3592a0031dea7a03565469b00020b"
|
||||
integrity sha512-a0BcI5YR7xp87vSzGcbN0IszJKpUQuTmrZaTSQBl7TLDIdKj6rDhluQ7b/7lYGG81gWDvkySsEvwv4BW5an9kg==
|
||||
version "5.2.7"
|
||||
resolved "https://registry.yarnpkg.com/what-input/-/what-input-5.2.7.tgz#81afbb6b82882cff8c43fa7ff1054aa46f288ffa"
|
||||
integrity sha512-ruCP2skyygi0ZHnMicHuZP7vXnJh8uJXs9R7RX488HlWigSdzngdmKo5Ti11Iatp1dnYp55VfioP/WevPaK+xQ==
|
||||
|
||||
whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3:
|
||||
version "1.0.5"
|
||||
|
@ -8931,6 +8967,13 @@ xml-name-validator@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
|
||||
integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
|
||||
|
||||
xregexp@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.3.0.tgz#7e92e73d9174a99a59743f67a4ce879a04b5ae50"
|
||||
integrity sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g==
|
||||
dependencies:
|
||||
"@babel/runtime-corejs3" "^7.8.3"
|
||||
|
||||
xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||
|
|
Loading…
Reference in a new issue