mirror of
https://github.com/element-hq/element-web
synced 2024-11-27 11:47:23 +03:00
Merge branch 'develop' of github.com:matrix-org/matrix-react-sdk into develop
This commit is contained in:
commit
736507b812
48 changed files with 407 additions and 213 deletions
|
@ -123,6 +123,7 @@
|
||||||
@import "./views/elements/_ImageView.scss";
|
@import "./views/elements/_ImageView.scss";
|
||||||
@import "./views/elements/_InfoTooltip.scss";
|
@import "./views/elements/_InfoTooltip.scss";
|
||||||
@import "./views/elements/_InlineSpinner.scss";
|
@import "./views/elements/_InlineSpinner.scss";
|
||||||
|
@import "./views/elements/_InviteReason.scss";
|
||||||
@import "./views/elements/_ManageIntegsButton.scss";
|
@import "./views/elements/_ManageIntegsButton.scss";
|
||||||
@import "./views/elements/_MiniAvatarUploader.scss";
|
@import "./views/elements/_MiniAvatarUploader.scss";
|
||||||
@import "./views/elements/_PowerSelector.scss";
|
@import "./views/elements/_PowerSelector.scss";
|
||||||
|
@ -250,6 +251,7 @@
|
||||||
@import "./views/voice_messages/_Waveform.scss";
|
@import "./views/voice_messages/_Waveform.scss";
|
||||||
@import "./views/voip/_CallContainer.scss";
|
@import "./views/voip/_CallContainer.scss";
|
||||||
@import "./views/voip/_CallView.scss";
|
@import "./views/voip/_CallView.scss";
|
||||||
|
@import "./views/voip/_CallViewForRoom.scss";
|
||||||
@import "./views/voip/_DialPad.scss";
|
@import "./views/voip/_DialPad.scss";
|
||||||
@import "./views/voip/_DialPadContextMenu.scss";
|
@import "./views/voip/_DialPadContextMenu.scss";
|
||||||
@import "./views/voip/_DialPadModal.scss";
|
@import "./views/voip/_DialPadModal.scss";
|
||||||
|
|
|
@ -276,15 +276,17 @@ $activeBorderColor: $secondary-fg-color;
|
||||||
.mx_SpaceButton:hover,
|
.mx_SpaceButton:hover,
|
||||||
.mx_SpaceButton:focus-within,
|
.mx_SpaceButton:focus-within,
|
||||||
.mx_SpaceButton_hasMenuOpen {
|
.mx_SpaceButton_hasMenuOpen {
|
||||||
// Hide the badge container on hover because it'll be a menu button
|
&:not(.mx_SpaceButton_home) {
|
||||||
.mx_SpacePanel_badgeContainer {
|
// Hide the badge container on hover because it'll be a menu button
|
||||||
width: 0;
|
.mx_SpacePanel_badgeContainer {
|
||||||
height: 0;
|
width: 0;
|
||||||
display: none;
|
height: 0;
|
||||||
}
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_SpaceButton_menuButton {
|
.mx_SpaceButton_menuButton {
|
||||||
display: block;
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
54
res/css/views/elements/_InviteReason.scss
Normal file
54
res/css/views/elements/_InviteReason.scss
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.mx_InviteReason {
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
|
||||||
|
.mx_InviteReason_reason {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_InviteReason_view {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
color: $secondary-fg-color;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
margin-right: 8px;
|
||||||
|
background-color: $secondary-fg-color;
|
||||||
|
mask-image: url('$(res)/img/feather-customised/eye.svg');
|
||||||
|
display: inline-block;
|
||||||
|
width: 18px;
|
||||||
|
height: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_InviteReason_hidden {
|
||||||
|
.mx_InviteReason_reason {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_InviteReason_view {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
|
@ -40,35 +40,6 @@ limitations under the License.
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomPreviewBar_reason {
|
|
||||||
text-align: left;
|
|
||||||
background-color: $primary-bg-color;
|
|
||||||
border: 1px solid $invite-reason-border-color;
|
|
||||||
border-radius: 10px;
|
|
||||||
padding: 0 16px 12px 16px;
|
|
||||||
margin: 5px 0 20px 0;
|
|
||||||
|
|
||||||
div {
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_EventTile_msgOption {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_MatrixChat_useCompactLayout & {
|
|
||||||
padding-top: 9px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.mx_EventTilePreview_faded {
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
.mx_SenderProfile, .mx_EventTile_avatar {
|
|
||||||
opacity: 0.3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_Spinner {
|
.mx_Spinner {
|
||||||
width: auto;
|
width: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
|
|
|
@ -27,9 +27,12 @@ limitations under the License.
|
||||||
.mx_CallView_large {
|
.mx_CallView_large {
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
margin: 5px 5px 5px 18px;
|
margin: 5px 5px 5px 18px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
.mx_CallView_voice {
|
.mx_CallView_voice {
|
||||||
height: 360px;
|
flex: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,6 +107,7 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_CallView_video {
|
.mx_CallView_video {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 30;
|
z-index: 30;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
@ -177,6 +181,7 @@ limitations under the License.
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: left;
|
justify-content: left;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_CallView_header_callType {
|
.mx_CallView_header_callType {
|
||||||
|
|
46
res/css/views/voip/_CallViewForRoom.scss
Normal file
46
res/css/views/voip/_CallViewForRoom.scss
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 Šimon Brandner <simon.bra.ag@gmail.com>
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
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_CallViewForRoom {
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.mx_CallViewForRoom_ResizeWrapper {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
|
&:hover .mx_CallViewForRoom_ResizeHandle {
|
||||||
|
// Need to use important to override element style attributes
|
||||||
|
// set by re-resizable
|
||||||
|
width: 100% !important;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
margin-top: 3px;
|
||||||
|
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
height: 4px;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 64px;
|
||||||
|
|
||||||
|
background-color: $primary-fg-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_VideoFeed_remote {
|
.mx_VideoFeed_remote {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-height: 100%;
|
height: 100%;
|
||||||
background-color: #000;
|
background-color: #000;
|
||||||
z-index: 50;
|
z-index: 50;
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -209,8 +209,6 @@ $message-body-panel-fg-color: $primary-fg-color;
|
||||||
// Appearance tab colors
|
// Appearance tab colors
|
||||||
$appearance-tab-border-color: $room-highlight-color;
|
$appearance-tab-border-color: $room-highlight-color;
|
||||||
|
|
||||||
$invite-reason-border-color: $room-highlight-color;
|
|
||||||
|
|
||||||
// blur amounts for left left panel (only for element theme, used in _mods.scss)
|
// blur amounts for left left panel (only for element theme, used in _mods.scss)
|
||||||
$roomlist-background-blur-amount: 60px;
|
$roomlist-background-blur-amount: 60px;
|
||||||
$groupFilterPanel-background-blur-amount: 30px;
|
$groupFilterPanel-background-blur-amount: 30px;
|
||||||
|
|
|
@ -204,8 +204,6 @@ $message-body-panel-fg-color: $primary-fg-color;
|
||||||
// Appearance tab colors
|
// Appearance tab colors
|
||||||
$appearance-tab-border-color: $room-highlight-color;
|
$appearance-tab-border-color: $room-highlight-color;
|
||||||
|
|
||||||
$invite-reason-border-color: $room-highlight-color;
|
|
||||||
|
|
||||||
$composer-shadow-color: tranparent;
|
$composer-shadow-color: tranparent;
|
||||||
|
|
||||||
// ***** Mixins! *****
|
// ***** Mixins! *****
|
||||||
|
|
|
@ -333,8 +333,6 @@ $message-body-panel-fg-color: $muted-fg-color;
|
||||||
// FontSlider colors
|
// FontSlider colors
|
||||||
$appearance-tab-border-color: $input-darker-bg-color;
|
$appearance-tab-border-color: $input-darker-bg-color;
|
||||||
|
|
||||||
$invite-reason-border-color: $input-darker-bg-color;
|
|
||||||
|
|
||||||
$composer-shadow-color: tranparent;
|
$composer-shadow-color: tranparent;
|
||||||
|
|
||||||
// ***** Mixins! *****
|
// ***** Mixins! *****
|
||||||
|
|
|
@ -15,8 +15,8 @@ $inter-unicode-range: U+0000-20e2,U+20e4-23ce,U+23d0-24c1,U+24c3-259f,U+25c2-266
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
unicode-range: $inter-unicode-range;
|
unicode-range: $inter-unicode-range;
|
||||||
src: url("$(res)/fonts/Inter/Inter-Regular.woff2?v=3.13") format("woff2"),
|
src: url("$(res)/fonts/Inter/Inter-Regular.woff2?v=3.18") format("woff2"),
|
||||||
url("$(res)/fonts/Inter/Inter-Regular.woff?v=3.13") format("woff");
|
url("$(res)/fonts/Inter/Inter-Regular.woff?v=3.18") format("woff");
|
||||||
}
|
}
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: 'Inter';
|
||||||
|
@ -24,8 +24,8 @@ $inter-unicode-range: U+0000-20e2,U+20e4-23ce,U+23d0-24c1,U+24c3-259f,U+25c2-266
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
unicode-range: $inter-unicode-range;
|
unicode-range: $inter-unicode-range;
|
||||||
src: url("$(res)/fonts/Inter/Inter-Italic.woff2?v=3.13") format("woff2"),
|
src: url("$(res)/fonts/Inter/Inter-Italic.woff2?v=3.18") format("woff2"),
|
||||||
url("$(res)/fonts/Inter/Inter-Italic.woff?v=3.13") format("woff");
|
url("$(res)/fonts/Inter/Inter-Italic.woff?v=3.18") format("woff");
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
|
@ -34,8 +34,8 @@ $inter-unicode-range: U+0000-20e2,U+20e4-23ce,U+23d0-24c1,U+24c3-259f,U+25c2-266
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
unicode-range: $inter-unicode-range;
|
unicode-range: $inter-unicode-range;
|
||||||
src: url("$(res)/fonts/Inter/Inter-Medium.woff2?v=3.13") format("woff2"),
|
src: url("$(res)/fonts/Inter/Inter-Medium.woff2?v=3.18") format("woff2"),
|
||||||
url("$(res)/fonts/Inter/Inter-Medium.woff?v=3.13") format("woff");
|
url("$(res)/fonts/Inter/Inter-Medium.woff?v=3.18") format("woff");
|
||||||
}
|
}
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: 'Inter';
|
||||||
|
@ -43,8 +43,8 @@ $inter-unicode-range: U+0000-20e2,U+20e4-23ce,U+23d0-24c1,U+24c3-259f,U+25c2-266
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
unicode-range: $inter-unicode-range;
|
unicode-range: $inter-unicode-range;
|
||||||
src: url("$(res)/fonts/Inter/Inter-MediumItalic.woff2?v=3.13") format("woff2"),
|
src: url("$(res)/fonts/Inter/Inter-MediumItalic.woff2?v=3.18") format("woff2"),
|
||||||
url("$(res)/fonts/Inter/Inter-MediumItalic.woff?v=3.13") format("woff");
|
url("$(res)/fonts/Inter/Inter-MediumItalic.woff?v=3.18") format("woff");
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
|
@ -53,8 +53,8 @@ $inter-unicode-range: U+0000-20e2,U+20e4-23ce,U+23d0-24c1,U+24c3-259f,U+25c2-266
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
unicode-range: $inter-unicode-range;
|
unicode-range: $inter-unicode-range;
|
||||||
src: url("$(res)/fonts/Inter/Inter-SemiBold.woff2?v=3.13") format("woff2"),
|
src: url("$(res)/fonts/Inter/Inter-SemiBold.woff2?v=3.18") format("woff2"),
|
||||||
url("$(res)/fonts/Inter/Inter-SemiBold.woff?v=3.13") format("woff");
|
url("$(res)/fonts/Inter/Inter-SemiBold.woff?v=3.18") format("woff");
|
||||||
}
|
}
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: 'Inter';
|
||||||
|
@ -62,8 +62,8 @@ $inter-unicode-range: U+0000-20e2,U+20e4-23ce,U+23d0-24c1,U+24c3-259f,U+25c2-266
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
unicode-range: $inter-unicode-range;
|
unicode-range: $inter-unicode-range;
|
||||||
src: url("$(res)/fonts/Inter/Inter-SemiBoldItalic.woff2?v=3.13") format("woff2"),
|
src: url("$(res)/fonts/Inter/Inter-SemiBoldItalic.woff2?v=3.18") format("woff2"),
|
||||||
url("$(res)/fonts/Inter/Inter-SemiBoldItalic.woff?v=3.13") format("woff");
|
url("$(res)/fonts/Inter/Inter-SemiBoldItalic.woff?v=3.18") format("woff");
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
|
@ -72,8 +72,8 @@ $inter-unicode-range: U+0000-20e2,U+20e4-23ce,U+23d0-24c1,U+24c3-259f,U+25c2-266
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
unicode-range: $inter-unicode-range;
|
unicode-range: $inter-unicode-range;
|
||||||
src: url("$(res)/fonts/Inter/Inter-Bold.woff2?v=3.13") format("woff2"),
|
src: url("$(res)/fonts/Inter/Inter-Bold.woff2?v=3.18") format("woff2"),
|
||||||
url("$(res)/fonts/Inter/Inter-Bold.woff?v=3.13") format("woff");
|
url("$(res)/fonts/Inter/Inter-Bold.woff?v=3.18") format("woff");
|
||||||
}
|
}
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: 'Inter';
|
||||||
|
@ -81,8 +81,8 @@ $inter-unicode-range: U+0000-20e2,U+20e4-23ce,U+23d0-24c1,U+24c3-259f,U+25c2-266
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
unicode-range: $inter-unicode-range;
|
unicode-range: $inter-unicode-range;
|
||||||
src: url("$(res)/fonts/Inter/Inter-BoldItalic.woff2?v=3.13") format("woff2"),
|
src: url("$(res)/fonts/Inter/Inter-BoldItalic.woff2?v=3.18") format("woff2"),
|
||||||
url("$(res)/fonts/Inter/Inter-BoldItalic.woff?v=3.13") format("woff");
|
url("$(res)/fonts/Inter/Inter-BoldItalic.woff?v=3.18") format("woff");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* latin-ext */
|
/* latin-ext */
|
||||||
|
|
|
@ -331,8 +331,6 @@ $message-body-panel-fg-color: $muted-fg-color;
|
||||||
// FontSlider colors
|
// FontSlider colors
|
||||||
$appearance-tab-border-color: $input-darker-bg-color;
|
$appearance-tab-border-color: $input-darker-bg-color;
|
||||||
|
|
||||||
$invite-reason-border-color: $input-darker-bg-color;
|
|
||||||
|
|
||||||
// blur amounts for left left panel (only for element theme, used in _mods.scss)
|
// blur amounts for left left panel (only for element theme, used in _mods.scss)
|
||||||
$roomlist-background-blur-amount: 40px;
|
$roomlist-background-blur-amount: 40px;
|
||||||
$groupFilterPanel-background-blur-amount: 20px;
|
$groupFilterPanel-background-blur-amount: 20px;
|
||||||
|
|
|
@ -22,15 +22,26 @@ clone() {
|
||||||
}
|
}
|
||||||
|
|
||||||
# Try the PR author's branch in case it exists on the deps as well.
|
# Try the PR author's branch in case it exists on the deps as well.
|
||||||
# If BUILDKITE_BRANCH is set, it will contain either:
|
# First we check if BUILDKITE_BRANCH is defined,
|
||||||
|
# if it isn't we can assume this is a Netlify build
|
||||||
|
if [ -z ${BUILDKITE_BRANCH+x} ]; then
|
||||||
|
# Netlify doesn't give us info about the fork so we have to get it from GitHub API
|
||||||
|
apiEndpoint="https://api.github.com/repos/matrix-org/matrix-react-sdk/pulls/"
|
||||||
|
apiEndpoint+=$REVIEW_ID
|
||||||
|
head=$(curl $apiEndpoint | jq -r '.head.label')
|
||||||
|
else
|
||||||
|
head=$BUILDKITE_BRANCH
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If head is set, it will contain either:
|
||||||
# * "branch" when the author's branch and target branch are in the same repo
|
# * "branch" when the author's branch and target branch are in the same repo
|
||||||
# * "author:branch" when the author's branch is in their fork
|
# * "fork:branch" when the author's branch is in their fork or if this is a Netlify build
|
||||||
# We can split on `:` into an array to check.
|
# We can split on `:` into an array to check.
|
||||||
BUILDKITE_BRANCH_ARRAY=(${BUILDKITE_BRANCH//:/ })
|
BRANCH_ARRAY=(${head//:/ })
|
||||||
if [[ "${#BUILDKITE_BRANCH_ARRAY[@]}" == "1" ]]; then
|
if [[ "${#BRANCH_ARRAY[@]}" == "1" ]]; then
|
||||||
clone $deforg $defrepo $BUILDKITE_BRANCH
|
clone $deforg $defrepo $BUILDKITE_BRANCH
|
||||||
elif [[ "${#BUILDKITE_BRANCH_ARRAY[@]}" == "2" ]]; then
|
elif [[ "${#BRANCH_ARRAY[@]}" == "2" ]]; then
|
||||||
clone ${BUILDKITE_BRANCH_ARRAY[0]} $defrepo ${BUILDKITE_BRANCH_ARRAY[1]}
|
clone ${BRANCH_ARRAY[0]} $defrepo ${BRANCH_ARRAY[1]}
|
||||||
fi
|
fi
|
||||||
# Try the target branch of the push or PR.
|
# Try the target branch of the push or PR.
|
||||||
clone $deforg $defrepo $BUILDKITE_PULL_REQUEST_BASE_BRANCH
|
clone $deforg $defrepo $BUILDKITE_PULL_REQUEST_BASE_BRANCH
|
||||||
|
|
|
@ -95,9 +95,10 @@ function textForMemberEvent(ev) {
|
||||||
senderName,
|
senderName,
|
||||||
targetName,
|
targetName,
|
||||||
}) + ' ' + reason;
|
}) + ' ' + reason;
|
||||||
} else {
|
} else if (prevContent.membership === "join") {
|
||||||
// sender is not target and made the target leave, if not from invite/ban then this is a kick
|
|
||||||
return _t('%(senderName)s kicked %(targetName)s.', {senderName, targetName}) + ' ' + reason;
|
return _t('%(senderName)s kicked %(targetName)s.', {senderName, targetName}) + ' ' + reason;
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,6 +84,7 @@ import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||||
import RoomListStore from "../../stores/room-list/RoomListStore";
|
import RoomListStore from "../../stores/room-list/RoomListStore";
|
||||||
import {RoomUpdateCause} from "../../stores/room-list/models";
|
import {RoomUpdateCause} from "../../stores/room-list/models";
|
||||||
import defaultDispatcher from "../../dispatcher/dispatcher";
|
import defaultDispatcher from "../../dispatcher/dispatcher";
|
||||||
|
import SecurityCustomisations from "../../customisations/Security";
|
||||||
|
|
||||||
/** constants for MatrixChat.state.view */
|
/** constants for MatrixChat.state.view */
|
||||||
export enum Views {
|
export enum Views {
|
||||||
|
@ -395,7 +396,11 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
|
|
||||||
const crossSigningIsSetUp = cli.getStoredCrossSigningForUser(cli.getUserId());
|
const crossSigningIsSetUp = cli.getStoredCrossSigningForUser(cli.getUserId());
|
||||||
if (crossSigningIsSetUp) {
|
if (crossSigningIsSetUp) {
|
||||||
this.setStateForNewView({ view: Views.COMPLETE_SECURITY });
|
if (SecurityCustomisations.SHOW_ENCRYPTION_SETUP_UI === false) {
|
||||||
|
this.onLoggedIn();
|
||||||
|
} else {
|
||||||
|
this.setStateForNewView({view: Views.COMPLETE_SECURITY});
|
||||||
|
}
|
||||||
} else if (await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")) {
|
} else if (await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")) {
|
||||||
this.setStateForNewView({ view: Views.E2E_SETUP });
|
this.setStateForNewView({ view: Views.E2E_SETUP });
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1137,10 +1137,16 @@ export default class RoomView extends React.Component<IProps, IState> {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
this.setState({
|
// We always increment the counter no matter the types, because dragging is
|
||||||
dragCounter: this.state.dragCounter + 1,
|
// still happening. If we didn't, the drag counter would get out of sync.
|
||||||
draggingFile: true,
|
this.setState({dragCounter: this.state.dragCounter + 1});
|
||||||
});
|
|
||||||
|
// See:
|
||||||
|
// https://docs.w3cub.com/dom/datatransfer/types
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Recommended_drag_types#file
|
||||||
|
if (ev.dataTransfer.types.includes("Files") || ev.dataTransfer.types.includes("application/x-moz-file")) {
|
||||||
|
this.setState({draggingFile: true});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private onDragLeave = ev => {
|
private onDragLeave = ev => {
|
||||||
|
@ -1164,6 +1170,9 @@ export default class RoomView extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
ev.dataTransfer.dropEffect = 'none';
|
ev.dataTransfer.dropEffect = 'none';
|
||||||
|
|
||||||
|
// See:
|
||||||
|
// https://docs.w3cub.com/dom/datatransfer/types
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Recommended_drag_types#file
|
||||||
if (ev.dataTransfer.types.includes("Files") || ev.dataTransfer.types.includes("application/x-moz-file")) {
|
if (ev.dataTransfer.types.includes("Files") || ev.dataTransfer.types.includes("application/x-moz-file")) {
|
||||||
ev.dataTransfer.dropEffect = 'copy';
|
ev.dataTransfer.dropEffect = 'copy';
|
||||||
}
|
}
|
||||||
|
|
|
@ -712,8 +712,7 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
|
||||||
this.props.onFinished();
|
this.props.onFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cli.isRoomEncrypted(this.props.roomId) &&
|
if (cli.isRoomEncrypted(this.props.roomId)) {
|
||||||
SettingsStore.getValue("feature_room_history_key_sharing")) {
|
|
||||||
const visibilityEvent = room.currentState.getStateEvents(
|
const visibilityEvent = room.currentState.getStateEvents(
|
||||||
"m.room.history_visibility", "",
|
"m.room.history_visibility", "",
|
||||||
);
|
);
|
||||||
|
@ -1344,8 +1343,7 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
|
||||||
buttonText = _t("Invite");
|
buttonText = _t("Invite");
|
||||||
goButtonFn = this._inviteUsers;
|
goButtonFn = this._inviteUsers;
|
||||||
|
|
||||||
if (SettingsStore.getValue("feature_room_history_key_sharing") &&
|
if (cli.isRoomEncrypted(this.props.roomId)) {
|
||||||
cli.isRoomEncrypted(this.props.roomId)) {
|
|
||||||
const room = cli.getRoom(this.props.roomId);
|
const room = cli.getRoom(this.props.roomId);
|
||||||
const visibilityEvent = room.currentState.getStateEvents(
|
const visibilityEvent = room.currentState.getStateEvents(
|
||||||
"m.room.history_visibility", "",
|
"m.room.history_visibility", "",
|
||||||
|
|
|
@ -55,22 +55,10 @@ interface IProps {
|
||||||
* The mxc:// avatar URL of the displayed user
|
* The mxc:// avatar URL of the displayed user
|
||||||
*/
|
*/
|
||||||
avatarUrl?: string;
|
avatarUrl?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the EventTile should appear faded
|
|
||||||
*/
|
|
||||||
faded?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback for when the component is clicked
|
|
||||||
*/
|
|
||||||
onClick?: () => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
message: string;
|
message: string;
|
||||||
faded: boolean;
|
|
||||||
eventTileKey: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const AVATAR_SIZE = 32;
|
const AVATAR_SIZE = 32;
|
||||||
|
@ -81,23 +69,9 @@ export default class EventTilePreview extends React.Component<IProps, IState> {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
message: props.message,
|
message: props.message,
|
||||||
faded: !!props.faded,
|
|
||||||
eventTileKey: 0,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
changeMessage(message: string) {
|
|
||||||
this.setState({
|
|
||||||
message,
|
|
||||||
// Change the EventTile key to force React to create a new instance
|
|
||||||
eventTileKey: this.state.eventTileKey + 1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
unfade() {
|
|
||||||
this.setState({ faded: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
private fakeEvent({message}: IState) {
|
private fakeEvent({message}: IState) {
|
||||||
// Fake it till we make it
|
// Fake it till we make it
|
||||||
/* eslint-disable quote-props */
|
/* eslint-disable quote-props */
|
||||||
|
@ -147,12 +121,10 @@ export default class EventTilePreview extends React.Component<IProps, IState> {
|
||||||
const className = classnames(this.props.className, {
|
const className = classnames(this.props.className, {
|
||||||
"mx_IRCLayout": this.props.layout == Layout.IRC,
|
"mx_IRCLayout": this.props.layout == Layout.IRC,
|
||||||
"mx_GroupLayout": this.props.layout == Layout.Group,
|
"mx_GroupLayout": this.props.layout == Layout.Group,
|
||||||
"mx_EventTilePreview_faded": this.state.faded,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return <div className={className} onClick={this.props.onClick}>
|
return <div className={className}>
|
||||||
<EventTile
|
<EventTile
|
||||||
key={this.state.eventTileKey}
|
|
||||||
mxEvent={event}
|
mxEvent={event}
|
||||||
layout={this.props.layout}
|
layout={this.props.layout}
|
||||||
enableFlair={SettingsStore.getValue(UIFeature.Flair)}
|
enableFlair={SettingsStore.getValue(UIFeature.Flair)}
|
||||||
|
|
62
src/components/views/elements/InviteReason.tsx
Normal file
62
src/components/views/elements/InviteReason.tsx
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import classNames from "classnames";
|
||||||
|
import React from "react";
|
||||||
|
import { _t } from "../../../languageHandler";
|
||||||
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
reason: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IState {
|
||||||
|
hidden: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
@replaceableComponent("views.elements.InviteReason")
|
||||||
|
export default class InviteReason extends React.PureComponent<IProps, IState> {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
// We hide the reason for invitation by default, since it can be a
|
||||||
|
// vector for spam/harassment.
|
||||||
|
hidden: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
onViewClick = () => {
|
||||||
|
this.setState({
|
||||||
|
hidden: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const classes = classNames({
|
||||||
|
"mx_InviteReason": true,
|
||||||
|
"mx_InviteReason_hidden": this.state.hidden,
|
||||||
|
});
|
||||||
|
|
||||||
|
return <div className={classes}>
|
||||||
|
<div className="mx_InviteReason_reason">{this.props.reason}</div>
|
||||||
|
<div className="mx_InviteReason_view"
|
||||||
|
onClick={this.onViewClick}
|
||||||
|
>
|
||||||
|
{_t("View message")}
|
||||||
|
</div>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1494,7 +1494,7 @@ const UserInfoHeader: React.FC<{
|
||||||
e2eIcon = <E2EIcon size={18} status={e2eStatus} isUser={true} />;
|
e2eIcon = <E2EIcon size={18} status={e2eStatus} isUser={true} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const displayName = member.name || member.displayname;
|
const displayName = member.rawDisplayName || member.displayname;
|
||||||
return <React.Fragment>
|
return <React.Fragment>
|
||||||
{ avatarElement }
|
{ avatarElement }
|
||||||
|
|
||||||
|
|
|
@ -149,8 +149,8 @@ export default class AuxPanel extends React.Component<IProps, IState> {
|
||||||
const callView = (
|
const callView = (
|
||||||
<CallViewForRoom
|
<CallViewForRoom
|
||||||
roomId={this.props.room.roomId}
|
roomId={this.props.room.roomId}
|
||||||
onResize={this.props.onResize}
|
|
||||||
maxVideoHeight={this.props.maxHeight}
|
maxVideoHeight={this.props.maxHeight}
|
||||||
|
resizeNotifier={this.props.resizeNotifier}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2015, 2016 OpenMarket Ltd
|
Copyright 2015-2021 The Matrix.org Foundation C.I.C.
|
||||||
Copyright 2017 Vector Creations Ltd
|
|
||||||
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -25,10 +23,10 @@ import classNames from 'classnames';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import SdkConfig from "../../../SdkConfig";
|
import SdkConfig from "../../../SdkConfig";
|
||||||
import IdentityAuthClient from '../../../IdentityAuthClient';
|
import IdentityAuthClient from '../../../IdentityAuthClient';
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
|
||||||
import {CommunityPrototypeStore} from "../../../stores/CommunityPrototypeStore";
|
import {CommunityPrototypeStore} from "../../../stores/CommunityPrototypeStore";
|
||||||
import {UPDATE_EVENT} from "../../../stores/AsyncStore";
|
import {UPDATE_EVENT} from "../../../stores/AsyncStore";
|
||||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
|
import InviteReason from "../elements/InviteReason";
|
||||||
|
|
||||||
const MessageCase = Object.freeze({
|
const MessageCase = Object.freeze({
|
||||||
NotLoggedIn: "NotLoggedIn",
|
NotLoggedIn: "NotLoggedIn",
|
||||||
|
@ -303,7 +301,6 @@ export default class RoomPreviewBar extends React.Component {
|
||||||
const brand = SdkConfig.get().brand;
|
const brand = SdkConfig.get().brand;
|
||||||
const Spinner = sdk.getComponent('elements.Spinner');
|
const Spinner = sdk.getComponent('elements.Spinner');
|
||||||
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
||||||
const EventTilePreview = sdk.getComponent('elements.EventTilePreview');
|
|
||||||
|
|
||||||
let showSpinner = false;
|
let showSpinner = false;
|
||||||
let title;
|
let title;
|
||||||
|
@ -497,24 +494,7 @@ export default class RoomPreviewBar extends React.Component {
|
||||||
const myUserId = MatrixClientPeg.get().getUserId();
|
const myUserId = MatrixClientPeg.get().getUserId();
|
||||||
const reason = this.props.room.currentState.getMember(myUserId).events.member.event.content.reason;
|
const reason = this.props.room.currentState.getMember(myUserId).events.member.event.content.reason;
|
||||||
if (reason) {
|
if (reason) {
|
||||||
this.reasonElement = React.createRef();
|
reasonElement = <InviteReason reason={reason} />;
|
||||||
// We hide the reason for invitation by default, since it can be a
|
|
||||||
// vector for spam/harassment.
|
|
||||||
const showReason = () => {
|
|
||||||
this.reasonElement.current.unfade();
|
|
||||||
this.reasonElement.current.changeMessage(reason);
|
|
||||||
};
|
|
||||||
reasonElement = <EventTilePreview
|
|
||||||
ref={this.reasonElement}
|
|
||||||
onClick={showReason}
|
|
||||||
className="mx_RoomPreviewBar_reason"
|
|
||||||
message={_t("Invite messages are hidden by default. Click to show the message.")}
|
|
||||||
layout={SettingsStore.getValue("layout")}
|
|
||||||
userId={inviteMember.userId}
|
|
||||||
displayName={inviteMember.rawDisplayName}
|
|
||||||
avatarUrl={inviteMember.events.member.event.content.avatar_url}
|
|
||||||
faded={true}
|
|
||||||
/>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
primaryActionHandler = this.props.onJoinClick;
|
primaryActionHandler = this.props.onJoinClick;
|
||||||
|
|
|
@ -40,9 +40,6 @@ interface IProps {
|
||||||
// Another ongoing call to display information about
|
// Another ongoing call to display information about
|
||||||
secondaryCall?: MatrixCall,
|
secondaryCall?: MatrixCall,
|
||||||
|
|
||||||
// maxHeight style attribute for the video panel
|
|
||||||
maxVideoHeight?: number;
|
|
||||||
|
|
||||||
// a callback which is called when the content in the callview changes
|
// a callback which is called when the content in the callview changes
|
||||||
// in a way that is likely to cause a resize.
|
// in a way that is likely to cause a resize.
|
||||||
onResize?: any;
|
onResize?: any;
|
||||||
|
@ -96,9 +93,6 @@ function exitFullscreen() {
|
||||||
const CONTROLS_HIDE_DELAY = 1000;
|
const CONTROLS_HIDE_DELAY = 1000;
|
||||||
// Height of the header duplicated from CSS because we need to subtract it from our max
|
// Height of the header duplicated from CSS because we need to subtract it from our max
|
||||||
// height to get the max height of the video
|
// height to get the max height of the video
|
||||||
const HEADER_HEIGHT = 44;
|
|
||||||
const BOTTOM_PADDING = 10;
|
|
||||||
const BOTTOM_MARGIN_TOP_BOTTOM = 10; // top margin plus bottom margin
|
|
||||||
const CONTEXT_MENU_VPADDING = 8; // How far the context menu sits above the button (px)
|
const CONTEXT_MENU_VPADDING = 8; // How far the context menu sits above the button (px)
|
||||||
|
|
||||||
@replaceableComponent("views.voip.CallView")
|
@replaceableComponent("views.voip.CallView")
|
||||||
|
@ -548,20 +542,9 @@ export default class CallView extends React.Component<IProps, IState> {
|
||||||
localVideoFeed = <VideoFeed type={VideoFeedType.Local} call={this.props.call} />;
|
localVideoFeed = <VideoFeed type={VideoFeedType.Local} call={this.props.call} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we're fullscreen, we don't want to set a maxHeight on the video element.
|
contentView = <div className={containerClasses} ref={this.contentRef} onMouseMove={this.onMouseMove}>
|
||||||
const maxVideoHeight = getFullScreenElement() || !this.props.maxVideoHeight ? null : (
|
|
||||||
this.props.maxVideoHeight - (HEADER_HEIGHT + BOTTOM_PADDING + BOTTOM_MARGIN_TOP_BOTTOM)
|
|
||||||
);
|
|
||||||
contentView = <div className={containerClasses}
|
|
||||||
ref={this.contentRef} onMouseMove={this.onMouseMove}
|
|
||||||
// Put the max height on here too because this div is ended up 4px larger than the content
|
|
||||||
// and is causing it to scroll, and I am genuinely baffled as to why.
|
|
||||||
style={{maxHeight: maxVideoHeight}}
|
|
||||||
>
|
|
||||||
{onHoldBackground}
|
{onHoldBackground}
|
||||||
<VideoFeed type={VideoFeedType.Remote} call={this.props.call} onResize={this.props.onResize}
|
<VideoFeed type={VideoFeedType.Remote} call={this.props.call} onResize={this.props.onResize} />
|
||||||
maxHeight={maxVideoHeight}
|
|
||||||
/>
|
|
||||||
{localVideoFeed}
|
{localVideoFeed}
|
||||||
{holdTransferContent}
|
{holdTransferContent}
|
||||||
{callControls}
|
{callControls}
|
||||||
|
|
|
@ -19,6 +19,8 @@ import React from 'react';
|
||||||
import CallHandler from '../../../CallHandler';
|
import CallHandler from '../../../CallHandler';
|
||||||
import CallView from './CallView';
|
import CallView from './CallView';
|
||||||
import dis from '../../../dispatcher/dispatcher';
|
import dis from '../../../dispatcher/dispatcher';
|
||||||
|
import {Resizable} from "re-resizable";
|
||||||
|
import ResizeNotifier from "../../../utils/ResizeNotifier";
|
||||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
|
@ -28,9 +30,7 @@ interface IProps {
|
||||||
// maxHeight style attribute for the video panel
|
// maxHeight style attribute for the video panel
|
||||||
maxVideoHeight?: number;
|
maxVideoHeight?: number;
|
||||||
|
|
||||||
// a callback which is called when the content in the callview changes
|
resizeNotifier: ResizeNotifier,
|
||||||
// in a way that is likely to cause a resize.
|
|
||||||
onResize?: any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
|
@ -79,11 +79,50 @@ export default class CallViewForRoom extends React.Component<IProps, IState> {
|
||||||
return call;
|
return call;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private onResizeStart = () => {
|
||||||
|
this.props.resizeNotifier.startResizing();
|
||||||
|
};
|
||||||
|
|
||||||
|
private onResize = () => {
|
||||||
|
this.props.resizeNotifier.notifyTimelineHeightChanged();
|
||||||
|
};
|
||||||
|
|
||||||
|
private onResizeStop = () => {
|
||||||
|
this.props.resizeNotifier.stopResizing();
|
||||||
|
};
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
if (!this.state.call) return null;
|
if (!this.state.call) return null;
|
||||||
|
// We subtract 8 as it the margin-bottom of the mx_CallViewForRoom_ResizeWrapper
|
||||||
|
const maxHeight = this.props.maxVideoHeight - 8;
|
||||||
|
|
||||||
return <CallView call={this.state.call} pipMode={false}
|
return (
|
||||||
onResize={this.props.onResize} maxVideoHeight={this.props.maxVideoHeight}
|
<div className="mx_CallViewForRoom">
|
||||||
/>;
|
<Resizable
|
||||||
|
minHeight={380}
|
||||||
|
maxHeight={maxHeight}
|
||||||
|
enable={{
|
||||||
|
top: false,
|
||||||
|
right: false,
|
||||||
|
bottom: true,
|
||||||
|
left: false,
|
||||||
|
topRight: false,
|
||||||
|
bottomRight: false,
|
||||||
|
bottomLeft: false,
|
||||||
|
topLeft: false,
|
||||||
|
}}
|
||||||
|
onResizeStart={this.onResizeStart}
|
||||||
|
onResize={this.onResize}
|
||||||
|
onResizeStop={this.onResizeStop}
|
||||||
|
className="mx_CallViewForRoom_ResizeWrapper"
|
||||||
|
handleClasses={{bottom: "mx_CallViewForRoom_ResizeHandle"}}
|
||||||
|
>
|
||||||
|
<CallView
|
||||||
|
call={this.state.call}
|
||||||
|
pipMode={false}
|
||||||
|
/>
|
||||||
|
</Resizable>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,6 @@ interface IProps {
|
||||||
|
|
||||||
type: VideoFeedType,
|
type: VideoFeedType,
|
||||||
|
|
||||||
// maxHeight style attribute for the video element
|
|
||||||
maxHeight?: number,
|
|
||||||
|
|
||||||
// a callback which is called when the video element is resized
|
// a callback which is called when the video element is resized
|
||||||
// due to a change in video metadata
|
// due to a change in video metadata
|
||||||
onResize?: (e: Event) => void,
|
onResize?: (e: Event) => void,
|
||||||
|
@ -82,9 +79,6 @@ export default class VideoFeed extends React.Component<IProps> {
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
let videoStyle = {};
|
return <video className={classnames(videoClasses)} ref={this.vid} />;
|
||||||
if (this.props.maxHeight) videoStyle = { maxHeight: this.props.maxHeight };
|
|
||||||
|
|
||||||
return <video className={classnames(videoClasses)} ref={this.vid} style={videoStyle} />;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,8 +74,20 @@ export interface ISecurityCustomisations {
|
||||||
catchAccessSecretStorageError?: typeof catchAccessSecretStorageError,
|
catchAccessSecretStorageError?: typeof catchAccessSecretStorageError,
|
||||||
setupEncryptionNeeded?: typeof setupEncryptionNeeded,
|
setupEncryptionNeeded?: typeof setupEncryptionNeeded,
|
||||||
getDehydrationKey?: typeof getDehydrationKey,
|
getDehydrationKey?: typeof getDehydrationKey,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When false, disables the post-login UI from showing. If there's
|
||||||
|
* an error during setup, that will be shown to the user.
|
||||||
|
*
|
||||||
|
* Note: when this is set to false then the app will assume the user's
|
||||||
|
* encryption is set up some other way which would circumvent the default
|
||||||
|
* UI, such as by presenting alternative UI.
|
||||||
|
*/
|
||||||
|
SHOW_ENCRYPTION_SETUP_UI?: boolean, // default true
|
||||||
}
|
}
|
||||||
|
|
||||||
// A real customisation module will define and export one or more of the
|
// A real customisation module will define and export one or more of the
|
||||||
// customisation points that make up `ISecurityCustomisations`.
|
// customisation points that make up `ISecurityCustomisations`.
|
||||||
export default {} as ISecurityCustomisations;
|
export default {
|
||||||
|
SHOW_ENCRYPTION_SETUP_UI: true,
|
||||||
|
} as ISecurityCustomisations;
|
||||||
|
|
|
@ -143,11 +143,11 @@ function parseElement(n: HTMLElement, partCreator: PartCreator, lastNode: HTMLEl
|
||||||
// math nodes are translated back into delimited latex strings
|
// math nodes are translated back into delimited latex strings
|
||||||
if (n.hasAttribute("data-mx-maths")) {
|
if (n.hasAttribute("data-mx-maths")) {
|
||||||
const delimLeft = (n.nodeName == "SPAN") ?
|
const delimLeft = (n.nodeName == "SPAN") ?
|
||||||
(SdkConfig.get()['latex_maths_delims'] || {})['inline_left'] || "$" :
|
((SdkConfig.get()['latex_maths_delims'] || {})['inline'] || {})['left'] || "\\(" :
|
||||||
(SdkConfig.get()['latex_maths_delims'] || {})['display_left'] || "$$";
|
((SdkConfig.get()['latex_maths_delims'] || {})['display'] || {})['left'] || "\\[";
|
||||||
const delimRight = (n.nodeName == "SPAN") ?
|
const delimRight = (n.nodeName == "SPAN") ?
|
||||||
(SdkConfig.get()['latex_maths_delims'] || {})['inline_right'] || "$" :
|
((SdkConfig.get()['latex_maths_delims'] || {})['inline'] || {})['right'] || "\\)" :
|
||||||
(SdkConfig.get()['latex_maths_delims'] || {})['display_right'] || "$$";
|
((SdkConfig.get()['latex_maths_delims'] || {})['display'] || {})['right'] || "\\]";
|
||||||
const tex = n.getAttribute("data-mx-maths");
|
const tex = n.getAttribute("data-mx-maths");
|
||||||
return partCreator.plain(delimLeft + tex + delimRight);
|
return partCreator.plain(delimLeft + tex + delimRight);
|
||||||
} else if (!checkDescendInto(n)) {
|
} else if (!checkDescendInto(n)) {
|
||||||
|
|
|
@ -47,21 +47,65 @@ export function mdSerialize(model: EditorModel) {
|
||||||
|
|
||||||
export function htmlSerializeIfNeeded(model: EditorModel, {forceHTML = false} = {}) {
|
export function htmlSerializeIfNeeded(model: EditorModel, {forceHTML = false} = {}) {
|
||||||
let md = mdSerialize(model);
|
let md = mdSerialize(model);
|
||||||
|
// copy of raw input to remove unwanted math later
|
||||||
|
const orig = md;
|
||||||
|
|
||||||
if (SettingsStore.getValue("feature_latex_maths")) {
|
if (SettingsStore.getValue("feature_latex_maths")) {
|
||||||
const displayPattern = (SdkConfig.get()['latex_maths_delims'] || {})['display_pattern'] ||
|
const patternNames = ['tex', 'latex'];
|
||||||
"\\$\\$(([^$]|\\\\\\$)*)\\$\\$";
|
const patternTypes = ['display', 'inline'];
|
||||||
const inlinePattern = (SdkConfig.get()['latex_maths_delims'] || {})['inline_pattern'] ||
|
const patternDefaults = {
|
||||||
"\\$(([^$]|\\\\\\$)*)\\$";
|
"tex": {
|
||||||
|
// detect math with tex delimiters, inline: $...$, display $$...$$
|
||||||
|
// preferably use negative lookbehinds, not supported in all major browsers:
|
||||||
|
// const displayPattern = "^(?<!\\\\)\\$\\$(?![ \\t])(([^$]|\\\\\\$)+?)\\$\\$$";
|
||||||
|
// const inlinePattern = "(?:^|\\s)(?<!\\\\)\\$(?!\\s)(([^$]|\\\\\\$)+?)(?<!\\\\|\\s)\\$";
|
||||||
|
|
||||||
md = md.replace(RegExp(displayPattern, "gm"), function(m, p1) {
|
// conditions for display math detection $$...$$:
|
||||||
const p1e = AllHtmlEntities.encode(p1);
|
// - pattern starts at beginning of line or is not prefixed with backslash or dollar
|
||||||
return `<div data-mx-maths="${p1e}">\n\n</div>\n\n`;
|
// - left delimiter ($$) is not escaped by backslash
|
||||||
});
|
"display": "(^|[^\\\\$])\\$\\$(([^$]|\\\\\\$)+?)\\$\\$",
|
||||||
|
|
||||||
md = md.replace(RegExp(inlinePattern, "gm"), function(m, p1) {
|
// conditions for inline math detection $...$:
|
||||||
const p1e = AllHtmlEntities.encode(p1);
|
// - pattern starts at beginning of line, follows whitespace character or punctuation
|
||||||
return `<span data-mx-maths="${p1e}"></span>`;
|
// - pattern is on a single line
|
||||||
|
// - left and right delimiters ($) are not escaped by backslashes
|
||||||
|
// - left delimiter is not followed by whitespace character
|
||||||
|
// - right delimiter is not prefixed with whitespace character
|
||||||
|
"inline":
|
||||||
|
"(^|\\s|[.,!?:;])(?!\\\\)\\$(?!\\s)(([^$\\n]|\\\\\\$)*([^\\\\\\s\\$]|\\\\\\$)(?:\\\\\\$)?)\\$",
|
||||||
|
},
|
||||||
|
"latex": {
|
||||||
|
// detect math with latex delimiters, inline: \(...\), display \[...\]
|
||||||
|
|
||||||
|
// conditions for display math detection \[...\]:
|
||||||
|
// - pattern starts at beginning of line or is not prefixed with backslash
|
||||||
|
// - pattern is not empty
|
||||||
|
"display": "(^|[^\\\\])\\\\\\[(?!\\\\\\])(.*?)\\\\\\]",
|
||||||
|
|
||||||
|
// conditions for inline math detection \(...\):
|
||||||
|
// - pattern starts at beginning of line or is not prefixed with backslash
|
||||||
|
// - pattern is not empty
|
||||||
|
"inline": "(^|[^\\\\])\\\\\\((?!\\\\\\))(.*?)\\\\\\)",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
patternNames.forEach(function(patternName) {
|
||||||
|
patternTypes.forEach(function(patternType) {
|
||||||
|
// get the regex replace pattern from config or use the default
|
||||||
|
const pattern = (((SdkConfig.get()["latex_maths_delims"] ||
|
||||||
|
{})[patternType] || {})["pattern"] || {})[patternName] ||
|
||||||
|
patternDefaults[patternName][patternType];
|
||||||
|
|
||||||
|
md = md.replace(RegExp(pattern, "gms"), function(m, p1, p2) {
|
||||||
|
const p2e = AllHtmlEntities.encode(p2);
|
||||||
|
switch (patternType) {
|
||||||
|
case "display":
|
||||||
|
return `${p1}<div data-mx-maths="${p2e}">\n\n</div>\n\n`;
|
||||||
|
case "inline":
|
||||||
|
return `${p1}<span data-mx-maths="${p2e}"></span>`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// make sure div tags always start on a new line, otherwise it will confuse
|
// make sure div tags always start on a new line, otherwise it will confuse
|
||||||
|
@ -73,15 +117,29 @@ export function htmlSerializeIfNeeded(model: EditorModel, {forceHTML = false} =
|
||||||
if (!parser.isPlainText() || forceHTML) {
|
if (!parser.isPlainText() || forceHTML) {
|
||||||
// feed Markdown output to HTML parser
|
// feed Markdown output to HTML parser
|
||||||
const phtml = cheerio.load(parser.toHTML(),
|
const phtml = cheerio.load(parser.toHTML(),
|
||||||
{ _useHtmlParser2: true, decodeEntities: false })
|
{ _useHtmlParser2: true, decodeEntities: false });
|
||||||
|
|
||||||
// add fallback output for latex math, which should not be interpreted as markdown
|
if (SettingsStore.getValue("feature_latex_maths")) {
|
||||||
phtml('div, span').each(function(i, e) {
|
// original Markdown without LaTeX replacements
|
||||||
const tex = phtml(e).attr('data-mx-maths')
|
const parserOrig = new Markdown(orig);
|
||||||
if (tex) {
|
const phtmlOrig = cheerio.load(parserOrig.toHTML(),
|
||||||
phtml(e).html(`<code>${tex}</code>`)
|
{ _useHtmlParser2: true, decodeEntities: false });
|
||||||
}
|
|
||||||
});
|
// since maths delimiters are handled before Markdown,
|
||||||
|
// code blocks could contain mangled content.
|
||||||
|
// replace code blocks with original content
|
||||||
|
phtmlOrig('code').each(function(i) {
|
||||||
|
phtml('code').eq(i).text(phtmlOrig('code').eq(i).text());
|
||||||
|
});
|
||||||
|
|
||||||
|
// add fallback output for latex math, which should not be interpreted as markdown
|
||||||
|
phtml('div, span').each(function(i, e) {
|
||||||
|
const tex = phtml(e).attr('data-mx-maths')
|
||||||
|
if (tex) {
|
||||||
|
phtml(e).html(`<code>${tex}</code>`)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
return phtml.html();
|
return phtml.html();
|
||||||
}
|
}
|
||||||
// ensure removal of escape backslashes in non-Markdown messages
|
// ensure removal of escape backslashes in non-Markdown messages
|
||||||
|
|
|
@ -800,7 +800,6 @@
|
||||||
"Show message previews for reactions in DMs": "Show message previews for reactions in DMs",
|
"Show message previews for reactions in DMs": "Show message previews for reactions in DMs",
|
||||||
"Show message previews for reactions in all rooms": "Show message previews for reactions in all rooms",
|
"Show message previews for reactions in all rooms": "Show message previews for reactions in all rooms",
|
||||||
"Offline encrypted messaging using dehydrated devices": "Offline encrypted messaging using dehydrated devices",
|
"Offline encrypted messaging using dehydrated devices": "Offline encrypted messaging using dehydrated devices",
|
||||||
"Share decryption keys for room history when inviting users": "Share decryption keys for room history when inviting users",
|
|
||||||
"Enable advanced debugging for the room list": "Enable advanced debugging for the room list",
|
"Enable advanced debugging for the room list": "Enable advanced debugging for the room list",
|
||||||
"Show info about bridges in room settings": "Show info about bridges in room settings",
|
"Show info about bridges in room settings": "Show info about bridges in room settings",
|
||||||
"Font size": "Font size",
|
"Font size": "Font size",
|
||||||
|
@ -1578,7 +1577,6 @@
|
||||||
"Start chatting": "Start chatting",
|
"Start chatting": "Start chatting",
|
||||||
"Do you want to join %(roomName)s?": "Do you want to join %(roomName)s?",
|
"Do you want to join %(roomName)s?": "Do you want to join %(roomName)s?",
|
||||||
"<userName/> invited you": "<userName/> invited you",
|
"<userName/> invited you": "<userName/> invited you",
|
||||||
"Invite messages are hidden by default. Click to show the message.": "Invite messages are hidden by default. Click to show the message.",
|
|
||||||
"Reject": "Reject",
|
"Reject": "Reject",
|
||||||
"Reject & Ignore user": "Reject & Ignore user",
|
"Reject & Ignore user": "Reject & Ignore user",
|
||||||
"You're previewing %(roomName)s. Want to join it?": "You're previewing %(roomName)s. Want to join it?",
|
"You're previewing %(roomName)s. Want to join it?": "You're previewing %(roomName)s. Want to join it?",
|
||||||
|
@ -1925,6 +1923,7 @@
|
||||||
"Rotate clockwise": "Rotate clockwise",
|
"Rotate clockwise": "Rotate clockwise",
|
||||||
"Download this file": "Download this file",
|
"Download this file": "Download this file",
|
||||||
"Information": "Information",
|
"Information": "Information",
|
||||||
|
"View message": "View message",
|
||||||
"Language Dropdown": "Language Dropdown",
|
"Language Dropdown": "Language Dropdown",
|
||||||
"%(nameList)s %(transitionList)s": "%(nameList)s %(transitionList)s",
|
"%(nameList)s %(transitionList)s": "%(nameList)s %(transitionList)s",
|
||||||
"%(severalUsers)sjoined %(count)s times|other": "%(severalUsers)sjoined %(count)s times",
|
"%(severalUsers)sjoined %(count)s times|other": "%(severalUsers)sjoined %(count)s times",
|
||||||
|
|
|
@ -220,12 +220,6 @@ export const SETTINGS: {[setting: string]: ISetting} = {
|
||||||
supportedLevels: LEVELS_FEATURE,
|
supportedLevels: LEVELS_FEATURE,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
"feature_room_history_key_sharing": {
|
|
||||||
isFeature: true,
|
|
||||||
displayName: _td("Share decryption keys for room history when inviting users"),
|
|
||||||
supportedLevels: LEVELS_FEATURE,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
"advancedRoomListLogging": {
|
"advancedRoomListLogging": {
|
||||||
// TODO: Remove flag before launch: https://github.com/vector-im/element-web/issues/14231
|
// TODO: Remove flag before launch: https://github.com/vector-im/element-web/issues/14231
|
||||||
displayName: _td("Enable advanced debugging for the room list"),
|
displayName: _td("Enable advanced debugging for the room list"),
|
||||||
|
|
|
@ -376,16 +376,16 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
this.onRoomsUpdate();
|
this.onRoomsUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the user was looking at the room and then joined select that space
|
|
||||||
if (room.getMyMembership() === "join" && room.roomId === RoomViewStore.getRoomId()) {
|
|
||||||
this.setActiveSpace(room);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (room.getMyMembership() === "join") {
|
if (room.getMyMembership() === "join") {
|
||||||
const numSuggestedRooms = this._suggestedRooms.length;
|
if (!room.isSpaceRoom()) {
|
||||||
this._suggestedRooms = this._suggestedRooms.filter(r => r.room_id !== room.roomId);
|
const numSuggestedRooms = this._suggestedRooms.length;
|
||||||
if (numSuggestedRooms !== this._suggestedRooms.length) {
|
this._suggestedRooms = this._suggestedRooms.filter(r => r.room_id !== room.roomId);
|
||||||
this.emit(SUGGESTED_ROOMS, this._suggestedRooms);
|
if (numSuggestedRooms !== this._suggestedRooms.length) {
|
||||||
|
this.emit(SUGGESTED_ROOMS, this._suggestedRooms);
|
||||||
|
}
|
||||||
|
} else if (room.roomId === RoomViewStore.getRoomId()) {
|
||||||
|
// if the user was looking at the space and then joined: select that space
|
||||||
|
this.setActiveSpace(room);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -65,12 +65,17 @@ export class NameFilterCondition extends EventEmitter implements IFilterConditio
|
||||||
return this.matches(room.name);
|
return this.matches(room.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public matches(val: string): boolean {
|
private normalize(val: string): string {
|
||||||
// Note: we have to match the filter with the removeHiddenChars() room name because the
|
// Note: we have to match the filter with the removeHiddenChars() room name because the
|
||||||
// function strips spaces and other characters (M becomes RN for example, in lowercase).
|
// function strips spaces and other characters (M becomes RN for example, in lowercase).
|
||||||
// We also doubly convert to lowercase to work around oddities of the library.
|
return removeHiddenChars(val.toLowerCase())
|
||||||
const noSecretsFilter = removeHiddenChars(this.search.toLowerCase()).toLowerCase();
|
// Strip all punctuation
|
||||||
const noSecretsName = removeHiddenChars(val.toLowerCase()).toLowerCase();
|
.replace(/[\\'!"#$%&()*+,\-./:;<=>?@[\]^_`{|}~\u2000-\u206f\u2e00-\u2e7f]/g, "")
|
||||||
return noSecretsName.includes(noSecretsFilter);
|
// We also doubly convert to lowercase to work around oddities of the library.
|
||||||
|
.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
public matches(val: string): boolean {
|
||||||
|
return this.normalize(val).includes(this.normalize(this.search));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue