diff --git a/package.json b/package.json
index 6e10bafaea..4e2e933a52 100644
--- a/package.json
+++ b/package.json
@@ -46,6 +46,7 @@
"start:build": "babel src -w -s -d lib --verbose --extensions \".ts,.js\"",
"lint": "yarn lint:types && yarn lint:js && yarn lint:style",
"lint:js": "eslint --max-warnings 0 src test",
+ "lint:js-fix": "eslint --fix src test",
"lint:types": "tsc --noEmit --jsx react",
"lint:style": "stylelint 'res/css/**/*.scss'",
"test": "jest",
diff --git a/res/css/_components.scss b/res/css/_components.scss
index 1146a100b5..7df45b857e 100644
--- a/res/css/_components.scss
+++ b/res/css/_components.scss
@@ -201,6 +201,7 @@
@import "./views/rooms/_EditMessageComposer.scss";
@import "./views/rooms/_EntityTile.scss";
@import "./views/rooms/_EventTile.scss";
+@import "./views/rooms/_EventBubbleTile.scss";
@import "./views/rooms/_GroupLayout.scss";
@import "./views/rooms/_IRCLayout.scss";
@import "./views/rooms/_JumpToBottomButton.scss";
diff --git a/res/css/views/avatars/_BaseAvatar.scss b/res/css/views/avatars/_BaseAvatar.scss
index cbddd97e18..65e4493f19 100644
--- a/res/css/views/avatars/_BaseAvatar.scss
+++ b/res/css/views/avatars/_BaseAvatar.scss
@@ -27,6 +27,7 @@ limitations under the License.
// https://bugzilla.mozilla.org/show_bug.cgi?id=255139
display: inline-block;
user-select: none;
+ line-height: 1;
}
.mx_BaseAvatar_initial {
diff --git a/res/css/views/messages/_MImageBody.scss b/res/css/views/messages/_MImageBody.scss
index ee813a08e7..0a199c1f45 100644
--- a/res/css/views/messages/_MImageBody.scss
+++ b/res/css/views/messages/_MImageBody.scss
@@ -18,7 +18,6 @@ $timelineImageBorderRadius: 4px;
.mx_MImageBody {
display: block;
- margin-right: 34px;
}
.mx_MImageBody_thumbnail {
diff --git a/res/css/views/messages/_ReactionsRow.scss b/res/css/views/messages/_ReactionsRow.scss
index e05065eb02..b2bca6dfb3 100644
--- a/res/css/views/messages/_ReactionsRow.scss
+++ b/res/css/views/messages/_ReactionsRow.scss
@@ -26,6 +26,7 @@ limitations under the License.
height: 24px;
vertical-align: middle;
margin-left: 4px;
+ margin-right: 4px;
&::before {
content: '';
diff --git a/res/css/views/rooms/_EventBubbleTile.scss b/res/css/views/rooms/_EventBubbleTile.scss
new file mode 100644
index 0000000000..c66f635ffe
--- /dev/null
+++ b/res/css/views/rooms/_EventBubbleTile.scss
@@ -0,0 +1,323 @@
+/*
+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_EventTile[data-layout=bubble],
+.mx_EventTile[data-layout=bubble] ~ .mx_EventListSummary {
+ --avatarSize: 32px;
+ --gutterSize: 11px;
+ --cornerRadius: 12px;
+ --maxWidth: 70%;
+}
+
+.mx_EventTile[data-layout=bubble] {
+
+ position: relative;
+ margin-top: var(--gutterSize);
+ margin-left: 50px;
+ margin-right: 100px;
+
+ &.mx_EventTile_continuation {
+ margin-top: 2px;
+ }
+
+ /* For replies */
+ .mx_EventTile {
+ padding-top: 0;
+ }
+
+ &:hover {
+ &::before {
+ content: '';
+ position: absolute;
+ top: -1px;
+ bottom: -1px;
+ left: -60px;
+ right: -60px;
+ z-index: -1;
+ background: $eventbubble-bg-hover;
+ border-radius: 4px;
+ }
+
+ .mx_EventTile_avatar {
+ img {
+ box-shadow: 0 0 0 3px $eventbubble-bg-hover;
+ }
+ }
+ }
+
+ .mx_SenderProfile,
+ .mx_EventTile_line {
+ width: fit-content;
+ max-width: 70%;
+ }
+
+ .mx_SenderProfile {
+ position: relative;
+ top: -2px;
+ left: 2px;
+ }
+
+ &[data-self=false] {
+ .mx_EventTile_line {
+ border-bottom-right-radius: var(--cornerRadius);
+ }
+ .mx_EventTile_avatar {
+ left: -34px;
+ }
+
+ .mx_MessageActionBar {
+ right: 0;
+ transform: translate3d(50%, 50%, 0);
+ }
+
+ --backgroundColor: $eventbubble-others-bg;
+ }
+ &[data-self=true] {
+ .mx_EventTile_line {
+ border-bottom-left-radius: var(--cornerRadius);
+ float: right;
+ > a {
+ left: auto;
+ right: -48px;
+ }
+ }
+ .mx_SenderProfile {
+ display: none;
+ }
+ .mx_ReactionsRow {
+ float: right;
+ clear: right;
+ display: flex;
+
+ /* Moving the "add reaction button" before the reactions */
+ > :last-child {
+ order: -1;
+ }
+ }
+ .mx_EventTile_avatar {
+ top: -19px; // height of the sender block
+ right: -35px;
+ }
+
+ --backgroundColor: $eventbubble-self-bg;
+ }
+
+ .mx_EventTile_line {
+ position: relative;
+ padding: var(--gutterSize);
+ border-top-left-radius: var(--cornerRadius);
+ border-top-right-radius: var(--cornerRadius);
+ background: var(--backgroundColor);
+ display: flex;
+ gap: 5px;
+ margin: 0 -12px 0 -9px;
+ > a {
+ position: absolute;
+ left: -48px;
+ }
+ }
+
+ &.mx_EventTile_continuation[data-self=false] .mx_EventTile_line {
+ border-top-left-radius: 0;
+ }
+ &.mx_EventTile_lastInSection[data-self=false] .mx_EventTile_line {
+ border-bottom-left-radius: var(--cornerRadius);
+ }
+
+ &.mx_EventTile_continuation[data-self=true] .mx_EventTile_line {
+ border-top-right-radius: 0;
+ }
+ &.mx_EventTile_lastInSection[data-self=true] .mx_EventTile_line {
+ border-bottom-right-radius: var(--cornerRadius);
+ }
+
+ .mx_EventTile_avatar {
+ position: absolute;
+ top: 0;
+ line-height: 1;
+ img {
+ box-shadow: 0 0 0 3px $eventbubble-avatar-outline;
+ border-radius: 50%;
+ }
+ }
+
+ &[data-has-reply=true] {
+ > .mx_EventTile_line {
+ flex-direction: column;
+ }
+
+ .mx_ReplyThread_show {
+ order: 99999;
+ }
+
+ .mx_ReplyThread {
+ margin: 0 calc(-1 * var(--gutterSize));
+
+ .mx_EventTile_reply {
+ max-width: 90%;
+ padding: 0;
+ > a {
+ display: none !important;
+ }
+ }
+
+ .mx_EventTile {
+ display: flex;
+ gap: var(--gutterSize);
+ .mx_EventTile_avatar {
+ position: static;
+ }
+ .mx_SenderProfile {
+ display: none;
+ }
+ }
+ }
+ }
+
+ .mx_EditMessageComposer_buttons {
+ position: static;
+ padding: 0;
+ margin: 0;
+ background: transparent;
+ }
+
+ .mx_ReactionsRow {
+ margin-right: -18px;
+ margin-left: -9px;
+ }
+
+ .mx_ReplyThread {
+ border-left-width: 2px;
+ border-left-color: $eventbubble-reply-color;
+ }
+
+ &.mx_EventTile_bubbleContainer,
+ &.mx_EventTile_info,
+ & ~ .mx_EventListSummary[data-expanded=false] {
+ --backgroundColor: transparent;
+ --gutterSize: 0;
+
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ .mx_EventTile_avatar {
+ position: static;
+ order: -1;
+ margin-right: 5px;
+ }
+ }
+
+ & ~ .mx_EventListSummary {
+ --maxWidth: 80%;
+ margin-left: calc(var(--avatarSize) + var(--gutterSize));
+ margin-right: calc(var(--gutterSize) + var(--avatarSize));
+ .mx_EventListSummary_toggle {
+ float: none;
+ margin: 0;
+ order: 9;
+ margin-left: 5px;
+ }
+ .mx_EventListSummary_avatars {
+ padding-top: 0;
+ }
+
+ &::after {
+ content: "";
+ clear: both;
+ }
+
+ .mx_EventTile {
+ margin: 0 6px;
+ }
+
+ .mx_EventTile_line {
+ margin: 0 5px;
+ > a {
+ left: auto;
+ right: 0;
+ transform: translateX(calc(100% + 5px));
+ }
+ }
+
+ .mx_MessageActionBar {
+ transform: translate3d(50%, 0, 0);
+ }
+ }
+
+ & ~ .mx_EventListSummary[data-expanded=false] {
+ padding: 0 34px;
+ }
+
+ /* events that do not require bubble layout */
+ & ~ .mx_EventListSummary,
+ &.mx_EventTile_bad {
+ .mx_EventTile_line {
+ background: transparent;
+ }
+
+ &:hover {
+ &::before {
+ background: transparent;
+ }
+ }
+ }
+
+ & + .mx_EventListSummary {
+ .mx_EventTile {
+ margin-top: 0;
+ padding: 0;
+ }
+ }
+
+ .mx_EventListSummary_toggle {
+ margin-right: 55px;
+ }
+
+ /* Special layout scenario for "Unable To Decrypt (UTD)" events */
+ &.mx_EventTile_bad > .mx_EventTile_line {
+ display: grid;
+ grid-template:
+ "reply reply" auto
+ "shield body" auto
+ "shield link" auto
+ / auto 1fr;
+ .mx_EventTile_e2eIcon {
+ grid-area: shield;
+ }
+ .mx_UnknownBody {
+ grid-area: body;
+ }
+ .mx_EventTile_keyRequestInfo {
+ grid-area: link;
+ }
+ .mx_ReplyThread_wrapper {
+ grid-area: reply;
+ }
+ }
+
+
+ .mx_EventTile_readAvatars {
+ position: absolute;
+ right: -110px;
+ bottom: 0;
+ top: auto;
+ }
+
+ .mx_MTextBody {
+ max-width: 100%;
+ }
+}
diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss
index 55f73c0315..d6ad37f6bb 100644
--- a/res/css/views/rooms/_EventTile.scss
+++ b/res/css/views/rooms/_EventTile.scss
@@ -1,6 +1,6 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
-Copyright 2020 The Matrix.org Foundation C.I.C.
+Copyright 2020-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.
@@ -18,102 +18,305 @@ limitations under the License.
$left-gutter: 64px;
$hover-select-border: 4px;
-.mx_EventTile {
+.mx_EventTile:not([data-layout=bubble]) {
max-width: 100%;
clear: both;
padding-top: 18px;
font-size: $font-14px;
position: relative;
-}
-.mx_EventTile.mx_EventTile_info {
- padding-top: 1px;
-}
+ &.mx_EventTile_info {
+ padding-top: 1px;
+ }
-.mx_EventTile_avatar {
- top: 14px;
- left: 8px;
- cursor: pointer;
- user-select: none;
-}
+ .mx_EventTile_avatar {
+ top: 14px;
+ left: 8px;
+ cursor: pointer;
+ user-select: none;
+ }
-.mx_EventTile.mx_EventTile_info .mx_EventTile_avatar {
- top: $font-6px;
- left: $left-gutter;
-}
+ &.mx_EventTile_info .mx_EventTile_avatar {
+ top: $font-6px;
+ left: $left-gutter;
+ }
-.mx_EventTile_continuation {
- padding-top: 0px !important;
+ &.mx_EventTile_continuation {
+ padding-top: 0px !important;
+
+ &.mx_EventTile_isEditing {
+ padding-top: 5px !important;
+ margin-top: -5px;
+ }
+ }
&.mx_EventTile_isEditing {
- padding-top: 5px !important;
- margin-top: -5px;
+ background-color: $header-panel-bg-color;
}
-}
-.mx_EventTile_isEditing {
- background-color: $header-panel-bg-color;
-}
+ .mx_SenderProfile {
+ color: $primary-fg-color;
+ font-size: $font-14px;
+ display: inline-block; /* anti-zalgo, with overflow hidden */
+ overflow: hidden;
+ cursor: pointer;
+ padding-bottom: 0px;
+ padding-top: 0px;
+ margin: 0px;
+ /* the next three lines, along with overflow hidden, truncate long display names */
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ max-width: calc(100% - $left-gutter);
+ }
-.mx_EventTile .mx_SenderProfile {
- color: $primary-fg-color;
- font-size: $font-14px;
- display: inline-block; /* anti-zalgo, with overflow hidden */
- overflow: hidden;
- cursor: pointer;
- padding-bottom: 0px;
- padding-top: 0px;
- margin: 0px;
- /* the next three lines, along with overflow hidden, truncate long display names */
- white-space: nowrap;
- text-overflow: ellipsis;
- max-width: calc(100% - $left-gutter);
-}
+ .mx_SenderProfile .mx_Flair {
+ opacity: 0.7;
+ margin-left: 5px;
+ display: inline-block;
+ vertical-align: top;
+ overflow: hidden;
+ user-select: none;
-.mx_EventTile .mx_SenderProfile .mx_Flair {
- opacity: 0.7;
- margin-left: 5px;
- display: inline-block;
- vertical-align: top;
- overflow: hidden;
- user-select: none;
+ img {
+ vertical-align: -2px;
+ margin-right: 2px;
+ border-radius: 8px;
+ }
+ }
- img {
- vertical-align: -2px;
- margin-right: 2px;
+ &.mx_EventTile_isEditing .mx_MessageTimestamp {
+ visibility: hidden;
+ }
+
+ .mx_MessageTimestamp {
+ display: block;
+ white-space: nowrap;
+ left: 0px;
+ text-align: center;
+ user-select: none;
+ }
+
+ &.mx_EventTile_continuation .mx_EventTile_line {
+ clear: both;
+ }
+
+ .mx_EventTile_line, .mx_EventTile_reply {
+ position: relative;
+ padding-left: $left-gutter;
border-radius: 8px;
}
-}
-.mx_EventTile_isEditing .mx_MessageTimestamp {
- visibility: hidden;
-}
-
-.mx_EventTile .mx_MessageTimestamp {
- display: block;
- white-space: nowrap;
- left: 0px;
- text-align: center;
- user-select: none;
-}
-
-.mx_EventTile_continuation .mx_EventTile_line {
- clear: both;
-}
-
-.mx_EventTile_line, .mx_EventTile_reply {
- position: relative;
- padding-left: $left-gutter;
- border-radius: 8px;
-}
-
-.mx_RoomView_timeline_rr_enabled,
-// on ELS we need the margin to allow interaction with the expand/collapse button which is normally in the RR gutter
-.mx_EventListSummary {
- .mx_EventTile_line {
- /* ideally should be 100px, but 95px gives us a max thumbnail size of 800x600, which is nice */
- margin-right: 110px;
+ .mx_EventTile_reply {
+ margin-right: 10px;
}
+
+ &.mx_EventTile_selected > div > a > .mx_MessageTimestamp {
+ left: calc(-$hover-select-border);
+ }
+
+ /* this is used for the tile for the event which is selected via the URL.
+ * TODO: ultimately we probably want some transition on here.
+ */
+ &.mx_EventTile_selected > .mx_EventTile_line {
+ border-left: $accent-color 4px solid;
+ padding-left: calc($left-gutter - $hover-select-border);
+ background-color: $event-selected-color;
+ }
+
+ &.mx_EventTile_highlight,
+ &.mx_EventTile_highlight .markdown-body {
+ color: $event-highlight-fg-color;
+
+ .mx_EventTile_line {
+ background-color: $event-highlight-bg-color;
+ }
+ }
+
+ &.mx_EventTile_info .mx_EventTile_line {
+ padding-left: calc($left-gutter + 18px);
+ }
+
+ &.mx_EventTile_selected.mx_EventTile_info .mx_EventTile_line {
+ padding-left: calc($left-gutter + 18px - $hover-select-border);
+ }
+
+ &.mx_EventTile:hover .mx_EventTile_line,
+ &.mx_EventTile.mx_EventTile_actionBarFocused .mx_EventTile_line,
+ &.mx_EventTile.focus-visible:focus-within .mx_EventTile_line {
+ background-color: $event-selected-color;
+ }
+
+ .mx_EventTile_searchHighlight {
+ background-color: $accent-color;
+ color: $accent-fg-color;
+ border-radius: 5px;
+ padding-left: 2px;
+ padding-right: 2px;
+ cursor: pointer;
+ }
+
+ .mx_EventTile_searchHighlight a {
+ background-color: $accent-color;
+ color: $accent-fg-color;
+ }
+
+ .mx_EventTile_receiptSent,
+ .mx_EventTile_receiptSending {
+ // We don't use `position: relative` on the element because then it won't line
+ // up with the other read receipts
+
+ &::before {
+ background-color: $tertiary-fg-color;
+ mask-repeat: no-repeat;
+ mask-position: center;
+ mask-size: 14px;
+ width: 14px;
+ height: 14px;
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ }
+ }
+ .mx_EventTile_receiptSent::before {
+ mask-image: url('$(res)/img/element-icons/circle-sent.svg');
+ }
+ .mx_EventTile_receiptSending::before {
+ mask-image: url('$(res)/img/element-icons/circle-sending.svg');
+ }
+
+ &.mx_EventTile_contextual {
+ opacity: 0.4;
+ }
+
+ .mx_EventTile_msgOption {
+ float: right;
+ text-align: right;
+ position: relative;
+ width: 90px;
+
+ /* Hack to stop the height of this pushing the messages apart.
+ Replaces margin-top: -6px. This interacts better with a read
+ marker being in between. Content overflows. */
+ height: 1px;
+
+ margin-right: 10px;
+ }
+
+ .mx_EventTile_msgOption a {
+ text-decoration: none;
+ }
+
+ /* all the overflow-y: hidden; are to trap Zalgos -
+ but they introduce an implicit overflow-x: auto.
+ so make that explicitly hidden too to avoid random
+ horizontal scrollbars occasionally appearing, like in
+ https://github.com/vector-im/vector-web/issues/1154
+ */
+ .mx_EventTile_content {
+ display: block;
+ overflow-y: hidden;
+ overflow-x: hidden;
+ margin-right: 34px;
+ }
+
+ /* De-zalgoing */
+ .mx_EventTile_body {
+ overflow-y: hidden;
+ }
+
+ /* Spoiler stuff */
+ .mx_EventTile_spoiler {
+ cursor: pointer;
+ }
+
+ .mx_EventTile_spoiler_reason {
+ color: $event-timestamp-color;
+ font-size: $font-11px;
+ }
+
+ .mx_EventTile_spoiler_content {
+ filter: blur(5px) saturate(0.1) sepia(1);
+ transition-duration: 0.5s;
+ }
+
+ .mx_EventTile_spoiler.visible > .mx_EventTile_spoiler_content {
+ filter: none;
+ }
+
+ &:hover.mx_EventTile_verified .mx_EventTile_line,
+ &:hover.mx_EventTile_unverified .mx_EventTile_line,
+ &:hover.mx_EventTile_unknown .mx_EventTile_line {
+ padding-left: calc($left-gutter - $hover-select-border);
+ }
+
+ &:hover.mx_EventTile_verified .mx_EventTile_line {
+ border-left: $e2e-verified-color $EventTile_e2e_state_indicator_width solid;
+ }
+
+ &:hover.mx_EventTile_unverified .mx_EventTile_line {
+ border-left: $e2e-unverified-color $EventTile_e2e_state_indicator_width solid;
+ }
+
+ &:hover.mx_EventTile_unknown .mx_EventTile_line {
+ border-left: $e2e-unknown-color $EventTile_e2e_state_indicator_width solid;
+ }
+
+ &:hover.mx_EventTile_verified.mx_EventTile_info .mx_EventTile_line,
+ &:hover.mx_EventTile_unverified.mx_EventTile_info .mx_EventTile_line,
+ &:hover.mx_EventTile_unknown.mx_EventTile_info .mx_EventTile_line {
+ padding-left: calc($left-gutter + 18px - $hover-select-border);
+ }
+
+ /* End to end encryption stuff */
+ &:hover .mx_EventTile_e2eIcon {
+ opacity: 1;
+ }
+
+ // Explicit relationships so that it doesn't apply to nested EventTile components (e.g in Replies)
+ &:hover.mx_EventTile_verified .mx_EventTile_line > a > .mx_MessageTimestamp,
+ &:hover.mx_EventTile_unverified .mx_EventTile_line > a > .mx_MessageTimestamp,
+ &:hover.mx_EventTile_unknown .mx_EventTile_line > a > .mx_MessageTimestamp {
+ left: calc(-$hover-select-border);
+ }
+
+ // Explicit relationships so that it doesn't apply to nested EventTile components (e.g in Replies)
+ &:hover.mx_EventTile_verified .mx_EventTile_line > .mx_EventTile_e2eIcon,
+ &:hover.mx_EventTile_unverified .mx_EventTile_line > .mx_EventTile_e2eIcon,
+ &:hover.mx_EventTile_unknown .mx_EventTile_line > .mx_EventTile_e2eIcon {
+ display: block;
+ left: 41px;
+ }
+
+ .mx_MImageBody {
+ margin-right: 34px;
+ }
+
+ .mx_EventTile_e2eIcon {
+ position: absolute;
+ top: 6px;
+ left: 44px;
+ bottom: 0;
+ right: 0;
+ }
+
+ .mx_ReactionsRow {
+ margin: 0;
+ padding: 6px 60px;
+ }
+}
+
+.mx_RoomView_timeline_rr_enabled {
+
+ .mx_EventTile:not([data-layout=bubble]) {
+ .mx_EventTile_line {
+ /* ideally should be 100px, but 95px gives us a max thumbnail size of 800x600, which is nice */
+ margin-right: 110px;
+ }
+ }
+
+ // on ELS we need the margin to allow interaction with the expand/collapse button which is normally in the RR gutter
}
.mx_EventTile_bubbleContainer {
@@ -132,121 +335,6 @@ $hover-select-border: 4px;
}
}
-.mx_EventTile_reply {
- margin-right: 10px;
-}
-
-/* HACK to override line-height which is already marked important elsewhere */
-.mx_EventTile_bigEmoji.mx_EventTile_bigEmoji {
- font-size: 48px !important;
- line-height: 57px !important;
-}
-
-.mx_EventTile_selected > div > a > .mx_MessageTimestamp {
- left: calc(-$hover-select-border);
-}
-
-.mx_EventTile:hover .mx_MessageActionBar,
-.mx_EventTile.mx_EventTile_actionBarFocused .mx_MessageActionBar,
-[data-whatinput='keyboard'] .mx_EventTile:focus-within .mx_MessageActionBar,
-.mx_EventTile.focus-visible:focus-within .mx_MessageActionBar {
- visibility: visible;
-}
-
-/* this is used for the tile for the event which is selected via the URL.
- * TODO: ultimately we probably want some transition on here.
- */
-.mx_EventTile_selected > .mx_EventTile_line {
- border-left: $accent-color 4px solid;
- padding-left: calc($left-gutter - $hover-select-border);
- background-color: $event-selected-color;
-}
-
-.mx_EventTile_highlight,
-.mx_EventTile_highlight .markdown-body {
- color: $event-highlight-fg-color;
-
- .mx_EventTile_line {
- background-color: $event-highlight-bg-color;
- }
-}
-
-.mx_EventTile_info .mx_EventTile_line {
- padding-left: calc($left-gutter + 18px);
-}
-
-.mx_EventTile_selected.mx_EventTile_info .mx_EventTile_line {
- padding-left: calc($left-gutter + 18px - $hover-select-border);
-}
-
-.mx_EventTile:hover .mx_EventTile_line,
-.mx_EventTile.mx_EventTile_actionBarFocused .mx_EventTile_line,
-.mx_EventTile.focus-visible:focus-within .mx_EventTile_line {
- background-color: $event-selected-color;
-}
-
-.mx_EventTile_searchHighlight {
- background-color: $accent-color;
- color: $accent-fg-color;
- border-radius: 5px;
- padding-left: 2px;
- padding-right: 2px;
- cursor: pointer;
-}
-
-.mx_EventTile_searchHighlight a {
- background-color: $accent-color;
- color: $accent-fg-color;
-}
-
-.mx_EventTile_receiptSent,
-.mx_EventTile_receiptSending {
- // We don't use `position: relative` on the element because then it won't line
- // up with the other read receipts
-
- &::before {
- background-color: $tertiary-fg-color;
- mask-repeat: no-repeat;
- mask-position: center;
- mask-size: 14px;
- width: 14px;
- height: 14px;
- content: '';
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- }
-}
-.mx_EventTile_receiptSent::before {
- mask-image: url('$(res)/img/element-icons/circle-sent.svg');
-}
-.mx_EventTile_receiptSending::before {
- mask-image: url('$(res)/img/element-icons/circle-sending.svg');
-}
-
-.mx_EventTile_contextual {
- opacity: 0.4;
-}
-
-.mx_EventTile_msgOption {
- float: right;
- text-align: right;
- position: relative;
- width: 90px;
-
- /* Hack to stop the height of this pushing the messages apart.
- Replaces margin-top: -6px. This interacts better with a read
- marker being in between. Content overflows. */
- height: 1px;
-
- margin-right: 10px;
-}
-
-.mx_EventTile_msgOption a {
- text-decoration: none;
-}
-
.mx_EventTile_readAvatars {
position: relative;
display: inline-block;
@@ -277,52 +365,27 @@ $hover-select-border: 4px;
position: absolute;
}
-/* all the overflow-y: hidden; are to trap Zalgos -
- but they introduce an implicit overflow-x: auto.
- so make that explicitly hidden too to avoid random
- horizontal scrollbars occasionally appearing, like in
- https://github.com/vector-im/vector-web/issues/1154
- */
-.mx_EventTile_content {
- display: block;
- overflow-y: hidden;
- overflow-x: hidden;
- margin-right: 34px;
+/* HACK to override line-height which is already marked important elsewhere */
+.mx_EventTile_bigEmoji.mx_EventTile_bigEmoji {
+ font-size: 48px !important;
+ line-height: 57px !important;
}
-/* De-zalgoing */
-.mx_EventTile_body {
- overflow-y: hidden;
-}
-
-/* Spoiler stuff */
-.mx_EventTile_spoiler {
+.mx_EventTile_content .mx_EventTile_edited {
+ user-select: none;
+ font-size: $font-12px;
+ color: $roomtopic-color;
+ display: inline-block;
+ margin-left: 9px;
cursor: pointer;
}
-.mx_EventTile_spoiler_reason {
- color: $event-timestamp-color;
- font-size: $font-11px;
-}
-
-.mx_EventTile_spoiler_content {
- filter: blur(5px) saturate(0.1) sepia(1);
- transition-duration: 0.5s;
-}
-
-.mx_EventTile_spoiler.visible > .mx_EventTile_spoiler_content {
- filter: none;
-}
.mx_EventTile_e2eIcon {
- position: absolute;
- top: 6px;
- left: 44px;
+ position: relative;
width: 14px;
height: 14px;
display: block;
- bottom: 0;
- right: 0;
opacity: 0.2;
background-repeat: no-repeat;
background-size: contain;
@@ -381,87 +444,6 @@ $hover-select-border: 4px;
opacity: 1;
}
-.mx_EventTile_keyRequestInfo {
- font-size: $font-12px;
-}
-
-.mx_EventTile_keyRequestInfo_text {
- opacity: 0.5;
-}
-
-.mx_EventTile_keyRequestInfo_text a {
- color: $primary-fg-color;
- text-decoration: underline;
- cursor: pointer;
-}
-
-.mx_EventTile_keyRequestInfo_tooltip_contents p {
- text-align: auto;
- margin-left: 3px;
- margin-right: 3px;
-}
-
-.mx_EventTile_keyRequestInfo_tooltip_contents p:first-child {
- margin-top: 0px;
-}
-
-.mx_EventTile_keyRequestInfo_tooltip_contents p:last-child {
- margin-bottom: 0px;
-}
-
-.mx_EventTile:hover.mx_EventTile_verified .mx_EventTile_line,
-.mx_EventTile:hover.mx_EventTile_unverified .mx_EventTile_line,
-.mx_EventTile:hover.mx_EventTile_unknown .mx_EventTile_line {
- padding-left: calc($left-gutter - $hover-select-border);
-}
-
-.mx_EventTile:hover.mx_EventTile_verified .mx_EventTile_line {
- border-left: $e2e-verified-color $EventTile_e2e_state_indicator_width solid;
-}
-
-.mx_EventTile:hover.mx_EventTile_unverified .mx_EventTile_line {
- border-left: $e2e-unverified-color $EventTile_e2e_state_indicator_width solid;
-}
-
-.mx_EventTile:hover.mx_EventTile_unknown .mx_EventTile_line {
- border-left: $e2e-unknown-color $EventTile_e2e_state_indicator_width solid;
-}
-
-.mx_EventTile:hover.mx_EventTile_verified.mx_EventTile_info .mx_EventTile_line,
-.mx_EventTile:hover.mx_EventTile_unverified.mx_EventTile_info .mx_EventTile_line,
-.mx_EventTile:hover.mx_EventTile_unknown.mx_EventTile_info .mx_EventTile_line {
- padding-left: calc($left-gutter + 18px - $hover-select-border);
-}
-
-/* End to end encryption stuff */
-.mx_EventTile:hover .mx_EventTile_e2eIcon {
- opacity: 1;
-}
-
-// Explicit relationships so that it doesn't apply to nested EventTile components (e.g in Replies)
-.mx_EventTile:hover.mx_EventTile_verified .mx_EventTile_line > a > .mx_MessageTimestamp,
-.mx_EventTile:hover.mx_EventTile_unverified .mx_EventTile_line > a > .mx_MessageTimestamp,
-.mx_EventTile:hover.mx_EventTile_unknown .mx_EventTile_line > a > .mx_MessageTimestamp {
- left: calc(-$hover-select-border);
-}
-
-// Explicit relationships so that it doesn't apply to nested EventTile components (e.g in Replies)
-.mx_EventTile:hover.mx_EventTile_verified .mx_EventTile_line > .mx_EventTile_e2eIcon,
-.mx_EventTile:hover.mx_EventTile_unverified .mx_EventTile_line > .mx_EventTile_e2eIcon,
-.mx_EventTile:hover.mx_EventTile_unknown .mx_EventTile_line > .mx_EventTile_e2eIcon {
- display: block;
- left: 41px;
-}
-
-.mx_EventTile_content .mx_EventTile_edited {
- user-select: none;
- font-size: $font-12px;
- color: $roomtopic-color;
- display: inline-block;
- margin-left: 9px;
- cursor: pointer;
-}
-
/* Various markdown overrides */
.mx_EventTile_body pre {
@@ -595,6 +577,35 @@ $hover-select-border: 4px;
/* end of overrides */
+
+.mx_EventTile_keyRequestInfo {
+ font-size: $font-12px;
+}
+
+.mx_EventTile_keyRequestInfo_text {
+ opacity: 0.5;
+}
+
+.mx_EventTile_keyRequestInfo_text a {
+ color: $primary-fg-color;
+ text-decoration: underline;
+ cursor: pointer;
+}
+
+.mx_EventTile_keyRequestInfo_tooltip_contents p {
+ text-align: auto;
+ margin-left: 3px;
+ margin-right: 3px;
+}
+
+.mx_EventTile_keyRequestInfo_tooltip_contents p:first-child {
+ margin-top: 0px;
+}
+
+.mx_EventTile_keyRequestInfo_tooltip_contents p:last-child {
+ margin-bottom: 0px;
+}
+
.mx_EventTile_tileError {
color: red;
text-align: center;
@@ -615,6 +626,13 @@ $hover-select-border: 4px;
}
}
+.mx_EventTile:hover .mx_MessageActionBar,
+.mx_EventTile.mx_EventTile_actionBarFocused .mx_MessageActionBar,
+[data-whatinput='keyboard'] .mx_EventTile:focus-within .mx_MessageActionBar,
+.mx_EventTile.focus-visible:focus-within .mx_MessageActionBar {
+ visibility: visible;
+}
+
@media only screen and (max-width: 480px) {
.mx_EventTile_line, .mx_EventTile_reply {
padding-left: 0;
diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss
index 74b33fbd02..2a4ebff034 100644
--- a/res/themes/dark/css/_dark.scss
+++ b/res/themes/dark/css/_dark.scss
@@ -227,6 +227,13 @@ $groupFilterPanel-background-blur-amount: 30px;
$composer-shadow-color: rgba(0, 0, 0, 0.28);
+// Bubble tiles
+$eventbubble-self-bg: #143A34;
+$eventbubble-others-bg: #394049;
+$eventbubble-bg-hover: #433C23;
+$eventbubble-avatar-outline: $bg-color;
+$eventbubble-reply-color: #C1C6CD;
+
// ***** Mixins! *****
@define-mixin mx_DialogButton {
diff --git a/res/themes/legacy-light/css/_legacy-light.scss b/res/themes/legacy-light/css/_legacy-light.scss
index c7debcdabe..f349a804a8 100644
--- a/res/themes/legacy-light/css/_legacy-light.scss
+++ b/res/themes/legacy-light/css/_legacy-light.scss
@@ -347,6 +347,13 @@ $appearance-tab-border-color: $input-darker-bg-color;
$composer-shadow-color: tranparent;
+// Bubble tiles
+$eventbubble-self-bg: #F8FDFC;
+$eventbubble-others-bg: #F7F8F9;
+$eventbubble-bg-hover: rgb(242, 242, 242);
+$eventbubble-avatar-outline: #fff;
+$eventbubble-reply-color: #C1C6CD;
+
// ***** Mixins! *****
@define-mixin mx_DialogButton {
diff --git a/res/themes/light/css/_light.scss b/res/themes/light/css/_light.scss
index 7e958c2af6..ef5f4d8c86 100644
--- a/res/themes/light/css/_light.scss
+++ b/res/themes/light/css/_light.scss
@@ -349,6 +349,13 @@ $groupFilterPanel-background-blur-amount: 20px;
$composer-shadow-color: rgba(0, 0, 0, 0.04);
+// Bubble tiles
+$eventbubble-self-bg: #F8FDFC;
+$eventbubble-others-bg: #F7F8F9;
+$eventbubble-bg-hover: #FEFCF5;
+$eventbubble-avatar-outline: $primary-bg-color;
+$eventbubble-reply-color: #C1C6CD;
+
// ***** Mixins! *****
@define-mixin mx_DialogButton {
diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts
index 7192eb81cc..051e865464 100644
--- a/src/@types/global.d.ts
+++ b/src/@types/global.d.ts
@@ -50,6 +50,8 @@ import UIStore from "../stores/UIStore";
import { SetupEncryptionStore } from "../stores/SetupEncryptionStore";
import { RoomScrollStateStore } from "../stores/RoomScrollStateStore";
+/* eslint-disable @typescript-eslint/naming-convention */
+
declare global {
interface Window {
matrixChat: ReturnType {_t(
+ { _t(
"Please ask the administrator of your homeserver " +
"( {_t(
+ ) } { _t(
"Alternatively, you can try to use the public server at " +
" {_t(
+ { _t(
"This action requires accessing the default identity server " +
" {_t(
+ ) } { _t(
"Only continue if you trust the owner of the server.",
- )} {_t(
+ description: { _t(
"Use an identity server to invite by email. " +
"Click continue to use the default identity server " +
"(%(defaultIdentityServerName)s) or manage in Settings.",
{
defaultIdentityServerName: abbreviateUrl(defaultIdentityServerUrl),
},
- )} {_t(
+ { _t(
"Warning: You should only set up key backup from a trusted computer.", {},
- { b: sub => {sub} },
- )} {_t(
+ { b: sub => { sub } },
+ ) } { _t(
"We'll store an encrypted copy of your keys on our server. " +
"Secure your backup with a Security Phrase.",
- )} {_t("For maximum security, this should be different from your account password.")} { _t("For maximum security, this should be different from your account password.") } {_t("Unable to find profiles for the Matrix IDs listed below - would you like to invite them anyway?")} { _t("Unable to find profiles for the Matrix IDs listed below - " +
+ "would you like to invite them anyway?") }
- {_t(
+ { _t(
"Clearing all data from this session is permanent. Encrypted messages will be lost " +
"unless their keys have been backed up.",
- )}
+ ) }
{_t(
+ let publicPrivateLabel = { _t(
"Private rooms can be found and joined by invitation only. Public rooms can be " +
"found and joined by anyone.",
- )} {_t(
+ publicPrivateLabel = { _t(
"Private rooms can be found and joined by invitation only. Public rooms can be " +
"found and joined by anyone in this community.",
- )} {federateLabel} { federateLabel } {_t("Tell us below how you feel about %(brand)s so far.", { brand })} {_t("Please go into as much detail as you like, so we can track down the problem.")} { _t("Tell us below how you feel about %(brand)s so far.", { brand }) } { _t("Please go into as much detail as you like, so we can track down the problem.") } {
_t("Please view
- {_t("Continuing temporarily allows the %(hostSignupBrand)s setup process to access your " +
+ { _t("Continuing temporarily allows the %(hostSignupBrand)s setup process to access your " +
"account to fetch verified email addresses. This data is not stored.", {
hostSignupBrand: this.config.brand,
- })}
+ }) }
- {_t("Learn more in our {_t(
+ { _t(
"Verify this user to mark them as trusted. " +
"Trusting users gives you extra peace of mind when using " +
"end-to-end encrypted messages.",
- )} {_t(
+ ) } { _t(
// NB. Below wording adjusted to singular 'session' until we have
// cross-signing
"Verifying this user will mark their session as trusted, and " +
"also mark your session as trusted to them.",
- )}
{ rows.map((row) =>
- ) }
{ otherVariables.map((item, index) =>
diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx
index f90854ee64..489d28e26b 100644
--- a/src/CallHandler.tsx
+++ b/src/CallHandler.tsx
@@ -615,23 +615,23 @@ export default class CallHandler extends EventEmitter {
private showICEFallbackPrompt() {
const cli = MatrixClientPeg.get();
- const code = sub => {_t(
+ { _t(
customVariables[row[0]].expl,
customVariables[row[0]].getTextVariables ?
customVariables[row[0]].getTextVariables() :
null,
- )}
+ ) }
{ row[1] !== undefined && }
{ row[1] }
{sub}
;
+ const code = sub => { sub }
;
Modal.createTrackedDialog('No TURN servers', '', QuestionDialog, {
title: _t("Call failed due to misconfigured server"),
description: %(homeserverDomain)s
) to configure a TURN server in " +
"order for calls to work reliably.",
{ homeserverDomain: cli.getDomain() }, { code },
- )}turn.matrix.org
, but this will not be as reliable, and " +
"it will share your IP address with that server. You can also manage " +
"this in Settings.",
null, { code },
- )}
-
{_t(category)}
- { _t(category) }
+
- {_t("Space used:")} {formatBytes(this.state.eventIndexSize, 0)}
- {_t("Indexed messages:")} {formatCountLong(this.state.eventCount)}
- {_t("Indexed rooms:")} {_t("%(doneRooms)s out of %(totalRooms)s", {
+ { crawlerState }
+ { _t("Space used:") } { formatBytes(this.state.eventIndexSize, 0) }
+ { _t("Indexed messages:") } { formatCountLong(this.state.eventCount) }
+ { _t("Indexed rooms:") } { _t("%(doneRooms)s out of %(totalRooms)s", {
doneRooms: formatCountLong(doneRooms),
totalRooms: formatCountLong(this.state.roomCount),
- })}
+ }) }
{_t("Advanced")}
+ { _t("Advanced") }
{ errorList }
diff --git a/src/components/views/dialogs/BaseDialog.js b/src/components/views/dialogs/BaseDialog.js
index e92bd6315e..8ccc485d7c 100644
--- a/src/components/views/dialogs/BaseDialog.js
+++ b/src/components/views/dialogs/BaseDialog.js
@@ -149,7 +149,7 @@ export default class BaseDialog extends React.Component {
'mx_Dialog_headerWithCancel': !!cancelButton,
})}>
{repo}
- {content}
+ { repo }
+ { content }
{_t("Unavailable")}
: logs}
+ { this.props.version == null || this.props.newVersion == null ? { _t("Unavailable") }
: logs }
{canEdit.toString()}
;
+ return ;
}
render() {
@@ -1028,17 +1028,17 @@ class SettingsExplorer extends React.PureComponent{ canEdit.toString() }
-
- {allSettings.map(i => (
+ { allSettings.map(i => (
{_t("Setting ID")}
- {_t("Value")}
- {_t("Value in this room")}
+ { _t("Setting ID") }
+ { _t("Value") }
+ { _t("Value in this room") }
- ))}
+ )) }
this.onViewClick(e, i)}>
-
{i}
+ { i }
this.onEditClick(e, i)}
className='mx_DevTools_SettingsExplorer_edit'
@@ -1047,20 +1047,20 @@ class SettingsExplorer extends React.PureComponent
-
{this.renderSettingValue(SettingsStore.getValue(i))}
+ { this.renderSettingValue(SettingsStore.getValue(i)) }
- {this.renderSettingValue(SettingsStore.getValue(i, room.roomId))}
+ { this.renderSettingValue(SettingsStore.getValue(i, room.roomId)) }
{_t("Setting:")}
+ {this.state.editSetting}
{ _t("Setting:") }
{ this.state.editSetting }
+ { _t("Setting definition:") }
+ {JSON.stringify(SETTINGS[this.state.editSetting], null, 4)}
{ JSON.stringify(SETTINGS[this.state.editSetting], null, 4) }
-
- {LEVEL_ORDER.map(lvl => (
+ { LEVEL_ORDER.map(lvl => (
{_t("Level")}
- {_t("Settable at global")}
- {_t("Settable at room")}
+ { _t("Level") }
+ { _t("Settable at global") }
+ { _t("Settable at room") }
-
- ))}
+ )) }
- {this.renderCanEditLevel(null, lvl)}
- {this.renderCanEditLevel(room.roomId, lvl)}
+ {lvl}
+ { this.renderCanEditLevel(null, lvl) }
+ { this.renderCanEditLevel(room.roomId, lvl) }
{ lvl }
{_t("Setting:")}
+ {this.state.viewSetting}
{ _t("Setting:") }
{ this.state.viewSetting }
+ { _t("Setting definition:") }
+ {JSON.stringify(SETTINGS[this.state.viewSetting], null, 4)}
{ JSON.stringify(SETTINGS[this.state.viewSetting], null, 4) }
{this.renderSettingValue(
+ { _t("Value:") }
+
{ this.renderSettingValue(
SettingsStore.getValue(this.state.viewSetting),
- )}
+ ) }{this.renderSettingValue(
+ { _t("Value in this room:") }
+
{ this.renderSettingValue(
SettingsStore.getValue(this.state.viewSetting, room.roomId),
- )}
+ ) }{this.renderExplicitSettingValues(
+ { _t("Values at explicit levels:") }
+
+ ) }{ this.renderExplicitSettingValues(
this.state.viewSetting, null,
- )}
{this.renderExplicitSettingValues(
+ { _t("Values at explicit levels in this room:") }
+
+ ) }{ this.renderExplicitSettingValues(
this.state.viewSetting, room.roomId,
- )}
{_t("Rate %(brand)s", { brand })}
+ { _t("Rate %(brand)s", { brand }) }
- {_t("There are two ways you can provide feedback and help us improve %(brand)s.", { brand })}
+ { _t("There are two ways you can provide feedback and help us improve %(brand)s.", { brand }) }
);
}
@@ -106,7 +106,7 @@ export default (props) => {
_t("PRO TIP: If you start a bug, please submit {_t("Report a bug")}
+ { _t("Report a bug") }
{oppProfile.displayname}
+ { oppProfile.displayname }
{this.props.verifier.userId}
+ { this.props.verifier.userId }
{_t( +
{ _t( "Verify this device to mark it as trusted. " + "Trusting this device gives you and other users extra peace of mind when using " + "end-to-end encrypted messages.", - )}
, -{_t( + ) }
, +{ _t( "Verifying this device will mark it as trusted, and users who have verified with " + "you will trust this device.", - )}
, + ) }, ]; return ({_t("Waiting for partner to confirm...")}
+{ _t("Waiting for partner to confirm...") }
{_t("Enable 'Manage Integrations' in Settings to do this.")}
+{ _t("Enable 'Manage Integrations' in Settings to do this.") }
- {_t( + { _t( "Your %(brand)s doesn't allow you to use an integration manager to do this. " + "Please contact an admin.", { brand }, - )} + ) }
{_t("No results")}
+{ _t("No results") }
); } @@ -1175,7 +1175,7 @@ export default class InviteDialog extends React.PureComponent{sectionSubname}
: null} - {tiles} - {showMore} +{ sectionSubname }
: null } + { tiles } + { showMore } ); } @@ -1225,8 +1225,8 @@ export default class InviteDialog extends React.PureComponent{helpText}
+{ helpText }
{_t("%(brand)s encountered an error during upload of:", { brand })}
-{reason}
- {retrying &&{JSON.stringify(failures, null, 2)}+
{ _t("%(brand)s encountered an error during upload of:", { brand }) }
+{ reason }
+ { retrying &&{ JSON.stringify(failures, null, 2) }
{description1}
{description2}
{ description1 }
{ description2 }
{_t( +
{ _t( "Encrypted messages are secured with end-to-end encryption. " + "Only you and the recipient(s) have the keys to read these messages.", - )}
-{_t("Back up your keys before signing out to avoid losing them.")}
+ ) } +{ _t("Back up your keys before signing out to avoid losing them.") }
- {_t("Your homeserver doesn't seem to support this feature.")} + { _t("Your homeserver doesn't seem to support this feature.") }
); } else if (error.errcode) { // some kind of error from the homeserver content = (- {_t("Something went wrong!")} + { _t("Something went wrong!") }
); } else { content = (
- {_t("Cannot reach homeserver")}
+ { _t("Cannot reach homeserver") }
- {_t("Ensure you have a stable internet connection, or get in touch with the server admin")}
+ { _t("Ensure you have a stable internet connection, or get in touch with the server admin") }
{_t("To continue you need to accept the terms of this service.")}
+{ _t("To continue you need to accept the terms of this service.") }
{_t("Service")} | -{_t("Summary")} | -{_t("Document")} | -{_t("Accept")} | +{ _t("Service") } | +{ _t("Summary") } | +{ _t("Document") } | +{ _t("Accept") } |
---|
{newSessionText}
-{device.getDisplayName()} ({device.deviceId})
-{askToVerifyText}
+{ newSessionText }
+{ device.getDisplayName() } ({ device.deviceId })
+{ askToVerifyText }
- {_t("The widget will verify your user ID, but won't be able to perform actions for you:")} + { _t("The widget will verify your user ID, but won't be able to perform actions for you:") }
- {/* cheap trim to just get the path */} - {this.props.widget.templateUrl.split("?")[0].split("#")[0]} + { /* cheap trim to just get the path */ } + { this.props.widget.templateUrl.split("?")[0].split("#")[0] }
{_t("Only do this if you have no other device to complete verification with.")}
-{_t("If you reset everything, you will restart with no trusted sessions, no trusted users, and " - + "might not be able to see past messages.")}
+{ _t("Only do this if you have no other device to complete verification with.") }
+{ _t("If you reset everything, you will restart with no trusted sessions, no trusted users, and " + + "might not be able to see past messages.") }
{_t( +
{ _t(
"Enter your Security Phrase or
{_t("Use your Security Key to continue.")}
+{ _t("Use your Security Key to continue.") }
- {_t( + { _t( "Deleting cross-signing keys is permanent. " + "Anyone you have verified with will see security alerts. " + "You almost certainly don't want to do this, unless " + "you've lost every device you can cross-sign from.", - )} + ) }
{_t("Unable to set up keys")}
+{ _t("Unable to set up keys") }
{_t( +
{ _t( "Backup could not be decrypted with this Security Key: " + "please verify that you entered the correct Security Key.", - )}
+ ) }{_t( +
{ _t( "Backup could not be decrypted with this Security Phrase: " + "please verify that you entered the correct Security Phrase.", - )}
+ ) }{_t( + failedToDecrypt =
{ _t( "Failed to decrypt %(failedCount)s sessions!", { failedCount: this.state.recoverInfo.total - this.state.recoverInfo.imported }, - )}
; + ) }; } content ={_t("Successfully restored %(sessionCount)s keys", { sessionCount: this.state.recoverInfo.imported })}
- {failedToDecrypt} +{ _t("Successfully restored %(sessionCount)s keys", { sessionCount: this.state.recoverInfo.imported }) }
+ { failedToDecrypt }{_t( +
{ _t( "Warning: you should only set up key backup " + "from a trusted computer.", {}, - { b: sub => {sub} }, - )}
-{_t( + { b: sub => { sub } }, + ) }
+{ _t( "Access your secure message history and set up secure " + "messaging by entering your Security Phrase.", - )}
+ ) }{_t( +
{ _t( "Warning: You should only set up key backup " + "from a trusted computer.", {}, - { b: sub => {sub} }, - )}
-{_t( + { b: sub => { sub } }, + ) }
+{ _t( "Access your secure message history and set up secure " + "messaging by entering your Security Key.", - )}
+ ) } extends React.PureComponent {_t(
+ { _t(
"Please {_t(
+ ) } { _t(
"If you've submitted a bug via GitHub, debug logs can help " +
"us track down the problem. Debug logs contain application " +
"usage data including your username, the IDs or aliases of " +
"the rooms or groups you have visited and the usernames of " +
"other users. They do not contain messages.",
- )}{editableItems}
;
+ const editableItemsSection = this.props.canRemove ? editableItems : { editableItems }
;
const label = this.props.items.length > 0 ? this.props.itemsLabel : this.props.noItemsLabel;
return (
diff --git a/src/components/views/elements/ErrorBoundary.tsx b/src/components/views/elements/ErrorBoundary.tsx
index f967b8c594..334e569163 100644
--- a/src/components/views/elements/ErrorBoundary.tsx
+++ b/src/components/views/elements/ErrorBoundary.tsx
@@ -81,33 +81,33 @@ export default class ErrorBoundary extends React.PureComponent<{}, IState> {
let bugReportSection;
if (SdkConfig.get().bug_report_endpoint_url) {
bugReportSection =
✅ {_t("This session is backing up your keys. ")}
; + statusDescription =✅ { _t("This session is backing up your keys. ") }
; } else { statusDescription = <> -{_t( +
{ _t( "This session is not backing up your keys, " + "but you do have an existing backup you can restore from " + "and add to going forward.", {}, - { b: sub => {sub} }, - )}
-{_t( + { b: sub => { sub } }, + ) }
+{ _t( "Connect this session to key backup before signing out to avoid " + "losing any keys that may only be on this session.", - )}
+ ) } >; restoreButtonCaption = _t("Connect this session to Key Backup"); } @@ -253,11 +253,11 @@ export default class SecureBackupPanel extends React.PureComponent { uploadStatus = ""; } else if (sessionsRemaining > 0) { uploadStatus ={_t( +
{ _t( "Your keys are not being backed up from this session.", {}, - { b: sub => {sub} }, - )}
-{_t("Back up your keys before signing out to avoid losing them.")}
+ { b: sub => { sub } }, + ) } +{ _t("Back up your keys before signing out to avoid losing them.") }
>; actions.push({_t( +
{ _t( "Back up your encryption keys with your account data in case you " + "lose access to your sessions. Your keys will be secured with a " + "unique Security Key.", - )}
- {statusDescription} + ) } + { statusDescription }{_t("Backup key stored:")} | +{ _t("Backup key stored:") } | { backupKeyStored === true ? _t("in secret storage") : _t("not stored") } | |
{_t("Backup key cached:")} | +{ _t("Backup key cached:") } | - {backupKeyCached ? _t("cached locally") : _t("not found locally")} - {backupKeyWellFormedText} + { backupKeyCached ? _t("cached locally") : _t("not found locally") } + { backupKeyWellFormedText } | |
{_t("Secret storage public key:")} | -{secretStorageKeyInAccount ? _t("in account data") : _t("not found")} | +{ _t("Secret storage public key:") } | +{ secretStorageKeyInAccount ? _t("in account data") : _t("not found") } |
{_t("Secret storage:")} | -{secretStorageReady ? _t("ready") : _t("not ready")} | +{ _t("Secret storage:") } | +{ secretStorageReady ? _t("ready") : _t("not ready") } |
{_t( +
{ _t(
"You should remove your personal data from identity server " +
"
{_t("You should:")}
+ ) } +{ _t("You should:") }
{_t( +
{ _t(
"You are still sharing your personal data on the identity " +
"server
{_t( + ) }
+{ _t( "We recommend that you remove your email addresses and phone numbers " + "from the identity server before disconnecting.", - )}
+ ) }{_t( +
{ _t( "This room is bridging messages to the following platforms. " + "Learn more.", {}, { // TODO: We don't have this link yet: this will prevent the translators // having to re-translate the string when we do. - a: sub => {sub}, + a: sub => { sub }, }, - )}
+ ) }{_t( + content =
{ _t( "This room isn’t bridging messages to any platforms. " + "Learn more.", {}, { // TODO: We don't have this link yet: this will prevent the translators // having to re-translate the string when we do. - a: sub => {sub}, + a: sub => { sub }, }, - )}
; + ) }; } return ({this.state.uploadedFile.name}
+ { _t("Uploaded sound") }: { this.state.uploadedFile.name }
{this.state.currentSound}
{ this.state.currentSound }
{_t('Select the roles required to change various parts of the room')}
- {powerSelectors} - {eventPowerSelectors} + { _t("Permissions") } +{ _t('Select the roles required to change various parts of the room') }
+ { powerSelectors } + { eventPowerSelectors }- {passwordChangeText} + { passwordChangeText }
- {passwordChangeForm} - {threepidSection} + { passwordChangeForm } + { threepidSection }{MatrixClientPeg.get().getHomeserverUrl()}
{MatrixClientPeg.get().getIdentityServerUrl()}
{ MatrixClientPeg.get().getHomeserverUrl() }
{ MatrixClientPeg.get().getIdentityServerUrl() }
{MatrixClientPeg.get().getAccessToken()}
+ { MatrixClientPeg.get().getAccessToken() }
{rule.entity}
{ rule.entity }
{rule.entity}
+ { rule.entity }
,
);
}
return (
{_t("You are currently ignoring:")}
-{ _t("You are currently ignoring:") }
+{list.roomId}
) : list.roomId
;
+ const name = room ? { room.name } ({ list.roomId }
) : list.roomId
;
tiles.push(
{_t("You are currently subscribed to:")}
-{ _t("You are currently subscribed to:") }
+@bot:*
" +
"would ignore all users that have the name 'bot' on any server.",
- { brand }, { code: (s) => {s}
},
- )}{ s }
},
+ ) }{deviceId}
+ { deviceId }
{identityKey}
+ { identityKey }
{_t("Missing media permissions, click the button below to request.")}
+{ _t("Missing media permissions, click the button below to request.") }
{_t( +
{ _t( "The other party cancelled the verification.", - )}
+ ) }{_t("You've successfully verified this user.")}
-{_t( +
{ _t("You've successfully verified this user.") }
+{ _t( "Secure messages with this user are end-to-end encrypted and not able to be " + "read by third parties.", - )}
+ ) }{sasCaption}
- {sasDisplay} -{this.props.isSelf ? +
{ sasCaption }
+ { sasDisplay } +{ this.props.isSelf ? "": - _t("To be secure, do this in person or use a trusted way to communicate.")}
- {confirm} + _t("To be secure, do this in person or use a trusted way to communicate.") } + { confirm }{incomingCallText}
+{ incomingCallText }
{releaseNotes}, + description:
{ releaseNotes }, button: _t("Update"), onFinished: (update) => { if (update && PlatformPeg.get()) { diff --git a/src/utils/AutoDiscoveryUtils.tsx b/src/utils/AutoDiscoveryUtils.tsx index 6c0c8b2e13..bad87db2b9 100644 --- a/src/utils/AutoDiscoveryUtils.tsx +++ b/src/utils/AutoDiscoveryUtils.tsx @@ -90,7 +90,7 @@ export default class AutoDiscoveryUtils { href="https://github.com/vector-im/element-web/blob/master/docs/config.md" target="_blank" rel="noreferrer noopener" - >{sub}; + >{ sub }; }, }, ); @@ -130,8 +130,8 @@ export default class AutoDiscoveryUtils { serverErrorIsFatal: isFatalError, serverDeadError: (