mirror of
https://github.com/element-hq/element-web
synced 2024-11-22 09:15:41 +03:00
Unified room context menus (#7072)
This commit is contained in:
parent
720b092844
commit
27c3153947
23 changed files with 660 additions and 133 deletions
|
@ -266,6 +266,7 @@
|
|||
@import "./views/settings/_UpdateCheckButton.scss";
|
||||
@import "./views/settings/tabs/_SettingsTab.scss";
|
||||
@import "./views/settings/tabs/room/_GeneralRoomSettingsTab.scss";
|
||||
@import "./views/settings/tabs/room/_NotificationSettingsTab.scss";
|
||||
@import "./views/settings/tabs/room/_RolesRoomSettingsTab.scss";
|
||||
@import "./views/settings/tabs/room/_SecurityRoomSettingsTab.scss";
|
||||
@import "./views/settings/tabs/user/_AppearanceUserSettingsTab.scss";
|
||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
// A context menu that largely fits the | [icon] [label] | format.
|
||||
.mx_IconizedContextMenu {
|
||||
min-width: 146px;
|
||||
width: max-content;
|
||||
|
||||
.mx_IconizedContextMenu_optionList {
|
||||
& > * {
|
||||
|
@ -119,7 +120,7 @@ limitations under the License.
|
|||
mask-position: center;
|
||||
mask-size: contain;
|
||||
mask-repeat: no-repeat;
|
||||
background: $primary-content;
|
||||
background-color: $secondary-content;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,6 +134,14 @@ limitations under the License.
|
|||
}
|
||||
}
|
||||
|
||||
.mx_IconizedContextMenu_option_red {
|
||||
color: $alert !important;
|
||||
|
||||
.mx_IconizedContextMenu_icon::before {
|
||||
background-color: $alert;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_IconizedContextMenu_active {
|
||||
&.mx_AccessibleButton, .mx_AccessibleButton {
|
||||
color: $accent !important;
|
||||
|
@ -162,4 +171,9 @@ limitations under the License.
|
|||
.mx_IconizedContextMenu_unchecked::before {
|
||||
content: unset;
|
||||
}
|
||||
|
||||
.mx_IconizedContextMenu_sublabel {
|
||||
margin-left: 20px;
|
||||
color: $tertiary-content;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ limitations under the License.
|
|||
}
|
||||
|
||||
.mx_BaseCard_Button {
|
||||
padding: 10px 38px 10px 12px;
|
||||
padding: 10px 32px 10px 12px;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
font-size: $font-13px;
|
||||
|
@ -109,6 +109,12 @@ limitations under the License.
|
|||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
display: flex;
|
||||
|
||||
.mx_BaseCard_Button_sublabel {
|
||||
color: $tertiary-content;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(141, 151, 165, 0.1);
|
||||
|
|
|
@ -33,12 +33,13 @@ limitations under the License.
|
|||
}
|
||||
|
||||
.mx_RoomHeader_wrapper {
|
||||
margin: auto;
|
||||
height: 50px;
|
||||
height: 44px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
padding: 0 10px 0 18px;
|
||||
margin: 0 20px 0 16px;
|
||||
padding-top: 8px;
|
||||
border-bottom: 1px solid $system;
|
||||
|
||||
.mx_InviteOnlyIcon_large {
|
||||
margin: 0;
|
||||
|
@ -85,40 +86,65 @@ limitations under the License.
|
|||
|
||||
.mx_RoomHeader_simpleHeader {
|
||||
line-height: $font-52px;
|
||||
color: $roomheader-color;
|
||||
color: $primary-content;
|
||||
font-size: $font-18px;
|
||||
font-weight: 600;
|
||||
font-weight: $font-semi-bold;
|
||||
overflow: hidden;
|
||||
margin-left: 63px;
|
||||
text-overflow: ellipsis;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_simpleHeader .mx_RoomHeader_cancelButton {
|
||||
float: right;
|
||||
}
|
||||
.mx_RoomHeader_cancelButton {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_simpleHeader .mx_RoomHeader_icon {
|
||||
margin-left: 14px;
|
||||
margin-right: 24px;
|
||||
vertical-align: -4px;
|
||||
.mx_RoomHeader_icon {
|
||||
margin-left: 14px;
|
||||
margin-right: 24px;
|
||||
vertical-align: -4px;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_RoomHeader_name {
|
||||
flex: 0 1 auto;
|
||||
overflow: hidden;
|
||||
color: $roomheader-color;
|
||||
font-weight: 600;
|
||||
color: $primary-content;
|
||||
font-weight: $font-semi-bold;
|
||||
font-size: $font-18px;
|
||||
border-radius: 6px;
|
||||
margin: 0 7px;
|
||||
border-bottom: 1px solid transparent;
|
||||
padding: 1px 4px;
|
||||
display: flex;
|
||||
}
|
||||
user-select: none;
|
||||
|
||||
.mx_RoomHeader_nametext {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
&:hover {
|
||||
background-color: $quinary-content;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_nametext {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_chevron {
|
||||
align-self: center;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
mask-position: center;
|
||||
mask-size: contain;
|
||||
mask-repeat: no-repeat;
|
||||
mask-image: url('$(res)/img/feather-customised/chevron-down.svg');
|
||||
background-color: $tertiary-content;
|
||||
}
|
||||
|
||||
&[aria-expanded=true] {
|
||||
background-color: $quinary-content;
|
||||
|
||||
.mx_RoomHeader_chevron {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mx_RoomHeader_settingsHint {
|
||||
|
@ -131,46 +157,17 @@ limitations under the License.
|
|||
}
|
||||
|
||||
.mx_RoomHeader_name,
|
||||
.mx_RoomHeader_avatar,
|
||||
.mx_RoomHeader_avatarPicker,
|
||||
.mx_RoomHeader_avatarPicker_edit,
|
||||
.mx_RoomHeader_avatarPicker_remove {
|
||||
.mx_RoomHeader_avatar {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_avatarPicker_remove {
|
||||
position: absolute;
|
||||
top: -11px;
|
||||
right: -9px;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_name:hover div:not(.mx_RoomHeader_editable) {
|
||||
color: $accent;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_placeholder {
|
||||
color: $settings-grey-fg-color !important;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_editable {
|
||||
border-bottom: 1px solid $strong-input-border-color !important;
|
||||
min-width: 150px;
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_editable:focus {
|
||||
border-bottom: 1px solid $accent !important;
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_topic {
|
||||
flex: 1;
|
||||
color: $roomtopic-color;
|
||||
font-weight: 400;
|
||||
font-size: $font-13px;
|
||||
margin: 0 7px;
|
||||
margin-top: 4px; // to align baseline of topic with room name
|
||||
// to align baseline of topic with room name
|
||||
margin: 4px 7px 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
border-bottom: 1px solid transparent;
|
||||
|
@ -188,24 +185,6 @@ limitations under the License.
|
|||
object-fit: cover;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_avatarPicker {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_avatarPicker_edit {
|
||||
position: absolute;
|
||||
left: 16px;
|
||||
top: 18px;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_avatarPicker_edit > label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_avatarPicker_edit > input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_button {
|
||||
position: relative;
|
||||
margin-left: 1px;
|
||||
|
@ -265,21 +244,10 @@ limitations under the License.
|
|||
mask-image: url('$(res)/img/element-icons/call/video-call.svg');
|
||||
}
|
||||
|
||||
.mx_RoomHeader_showPanel {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_voipButton {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_voipButtons {
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 480px) {
|
||||
.mx_RoomHeader_wrapper {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.mx_RoomHeader {
|
||||
overflow: hidden;
|
||||
|
|
|
@ -189,10 +189,42 @@ limitations under the License.
|
|||
mask-image: url('$(res)/img/element-icons/roomlist/low-priority.svg');
|
||||
}
|
||||
|
||||
.mx_RoomTile_iconNotificationsDefault::before {
|
||||
mask-image: url('$(res)/img/element-icons/notifications.svg');
|
||||
}
|
||||
|
||||
.mx_RoomTile_iconNotificationsAllMessages::before {
|
||||
mask-image: url('$(res)/img/element-icons/roomlist/notifications-default.svg');
|
||||
}
|
||||
|
||||
.mx_RoomTile_iconNotificationsMentionsKeywords::before {
|
||||
mask-image: url('$(res)/img/element-icons/roomlist/notifications-dm.svg');
|
||||
}
|
||||
|
||||
.mx_RoomTile_iconNotificationsNone::before {
|
||||
mask-image: url('$(res)/img/element-icons/roomlist/notifications-off.svg');
|
||||
}
|
||||
|
||||
.mx_RoomTile_iconPeople::before {
|
||||
mask-image: url('$(res)/img/element-icons/room/members.svg');
|
||||
}
|
||||
|
||||
.mx_RoomTile_iconFiles::before {
|
||||
mask-image: url('$(res)/img/element-icons/room/files.svg');
|
||||
}
|
||||
|
||||
.mx_RoomTile_iconWidgets::before {
|
||||
mask-image: url('$(res)/img/element-icons/room/apps.svg');
|
||||
}
|
||||
|
||||
.mx_RoomTile_iconSettings::before {
|
||||
mask-image: url('$(res)/img/element-icons/settings.svg');
|
||||
}
|
||||
|
||||
.mx_RoomTile_iconExport::before {
|
||||
mask-image: url('$(res)/img/element-icons/export.svg');
|
||||
}
|
||||
|
||||
.mx_RoomTile_iconCopyLink::before {
|
||||
mask-image: url('$(res)/img/element-icons/link.svg');
|
||||
}
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
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_NotificationSettingsTab_notificationsSection {
|
||||
width: 360px;
|
||||
|
||||
.mx_StyledRadioButton {
|
||||
flex-direction: row-reverse;
|
||||
color: $primary-content;
|
||||
font-size: $font-15px;
|
||||
line-height: $font-18px;
|
||||
font-weight: $font-semi-bold;
|
||||
margin-top: 16px;
|
||||
position: relative;
|
||||
padding-left: 8px;
|
||||
align-items: center;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
left: 0;
|
||||
mask-repeat: no-repeat;
|
||||
mask-position: center;
|
||||
mask-size: contain;
|
||||
background-color: $secondary-content;
|
||||
}
|
||||
|
||||
input + div {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.mx_NotificationSettingsTab_microCopy {
|
||||
color: $secondary-content;
|
||||
font-weight: normal;
|
||||
font-size: $font-12px;
|
||||
line-height: $font-15px;
|
||||
margin-right: 32px;
|
||||
|
||||
.mx_AccessibleButton_kind_link {
|
||||
padding: 0;
|
||||
font-size: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mx_NotificationSettingsTab_defaultEntry::before {
|
||||
mask-image: url('$(res)/img/element-icons/notifications.svg');
|
||||
}
|
||||
|
||||
.mx_NotificationSettingsTab_allMessagesEntry::before {
|
||||
mask-image: url('$(res)/img/element-icons/roomlist/notifications-default.svg');
|
||||
}
|
||||
|
||||
.mx_NotificationSettingsTab_mentionsKeywordsEntry::before {
|
||||
mask-image: url('$(res)/img/element-icons/roomlist/notifications-dm.svg');
|
||||
}
|
||||
|
||||
.mx_NotificationSettingsTab_noneEntry::before {
|
||||
mask-image: url('$(res)/img/element-icons/roomlist/notifications-off.svg');
|
||||
}
|
||||
}
|
|
@ -1,14 +1,8 @@
|
|||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47716 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22ZM12.7071 17.7071C12.6112 17.803 12.5007 17.8753 12.3828 17.9241L11.2929 17.7071L11.2925 17.7067L7.2929 13.7071C6.90237 13.3166 6.90237 12.6834 7.2929 12.2929C7.68342 11.9024 8.31658 11.9024 8.70711 12.2929L11 14.5858L11 7C11 6.44771 11.4477 6 12 6C12.5523 6 13 6.44771 13 7L13 14.5858L15.2929 12.2929C15.6834 11.9024 16.3166 11.9024 16.7071 12.2929C17.0976 12.6834 17.0976 13.3166 16.7071 13.7071L12.7071 17.7071ZM12.3828 17.9241L11.295 17.7092C11.4758 17.8889 11.7249 18 12 18C12.1356 18 12.2649 17.973 12.3828 17.9241Z"
|
||||
fill="#C1C6CD"
|
||||
/>
|
||||
<svg width="18" height="16" viewBox="0 0 18 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="hole">
|
||||
<rect width="100%" height="100%" fill="white"/>
|
||||
<circle cx="13" cy="11" r="5" fill="black"/>
|
||||
</mask>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.20757 14.9221C12.1427 14.9221 15.3327 11.7309 15.3327 7.79434C15.3327 3.85781 12.1427 0.666626 8.20757 0.666626C4.27246 0.666626 1.08243 3.85781 1.08243 7.79434C1.08243 8.89706 1.33275 9.9413 1.77965 10.8733L0.90483 13.7175C0.644577 14.5636 1.43951 15.3549 2.28444 15.0908L5.10044 14.2104C6.03948 14.6664 7.09367 14.9221 8.20757 14.9221Z" fill="#737D8C" mask="url(#hole)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.6 8.19998C13.6 7.8686 13.3314 7.59998 13 7.59998C12.6686 7.59998 12.4 7.8686 12.4 8.19998L12.4 12.3514L10.8243 10.7757C10.59 10.5414 10.2101 10.5414 9.97574 10.7757C9.74142 11.01 9.74142 11.3899 9.97574 11.6242L12.5757 14.2242C12.8101 14.4585 13.19 14.4585 13.4243 14.2242L16.0243 11.6242C16.2586 11.3899 16.2586 11.01 16.0243 10.7757C15.79 10.5414 15.4101 10.5414 15.1757 10.7757L13.6 12.3514L13.6 8.19998Z" fill="#7C7C7C"/>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 821 B After Width: | Height: | Size: 1.1 KiB |
|
@ -43,7 +43,6 @@ $panel-gradient: rgba(34, 38, 46, 0), rgba(34, 38, 46, 1);
|
|||
$event-selected-color: $system;
|
||||
$progressbar-bg-color: $system;
|
||||
$topleftmenu-color: $primary-content;
|
||||
$roomheader-color: $primary-content;
|
||||
$roomheader-addroom-fg-color: $primary-content;
|
||||
$h3-color: $primary-content;
|
||||
$focus-bg-color: $room-highlight-color;
|
||||
|
|
|
@ -84,7 +84,6 @@ $settings-profile-button-bg-color: #e7e7e7;
|
|||
$settings-subsection-fg-color: $text-secondary-color;
|
||||
|
||||
$topleftmenu-color: $text-primary-color;
|
||||
$roomheader-color: $text-primary-color;
|
||||
$roomheader-addroom-bg-color: #3c4556;
|
||||
$roomheader-addroom-fg-color: $text-primary-color;
|
||||
$groupFilterPanel-button-color: $header-panel-text-primary-color;
|
||||
|
|
|
@ -125,7 +125,6 @@ $rte-room-pill-color: #aaa;
|
|||
$rte-group-pill-color: #aaa;
|
||||
|
||||
$topleftmenu-color: #212121;
|
||||
$roomheader-color: #45474a;
|
||||
$roomheader-bg-color: $primary-bg-color;
|
||||
$roomheader-addroom-bg-color: #91a1c0;
|
||||
$roomheader-addroom-fg-color: $accent-fg-color;
|
||||
|
|
|
@ -83,7 +83,6 @@ $dialog-title-fg-color: var(--timeline-text-color);
|
|||
$tab-label-fg-color: var(--timeline-text-color);
|
||||
// was #4e5054
|
||||
$authpage-lang-color: var(--timeline-text-color);
|
||||
$roomheader-color: var(--timeline-text-color);
|
||||
// was #232f32
|
||||
$authpage-primary-color: var(--timeline-text-color);
|
||||
// --roomlist-text-secondary-color
|
||||
|
|
|
@ -124,7 +124,6 @@ $settings-subsection-fg-color: #61708b;
|
|||
|
||||
// RoomHeader
|
||||
// ********************
|
||||
$roomheader-color: #45474a;
|
||||
$roomheader-addroom-bg-color: rgba(92, 100, 112, 0.2);
|
||||
$roomheader-addroom-fg-color: #5c6470;
|
||||
// ********************
|
||||
|
|
|
@ -40,6 +40,7 @@ export const ContextMenuTooltipButton: React.FC<IProps> = ({
|
|||
onContextMenu={onContextMenu || onClick}
|
||||
aria-haspopup={true}
|
||||
aria-expanded={isExpanded}
|
||||
forceHide={isExpanded}
|
||||
>
|
||||
{ children }
|
||||
</AccessibleTooltipButton>
|
||||
|
|
|
@ -1486,10 +1486,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
});
|
||||
};
|
||||
|
||||
private onSettingsClick = () => {
|
||||
dis.dispatch({ action: "open_room_settings" });
|
||||
};
|
||||
|
||||
private onAppsClick = () => {
|
||||
dis.dispatch({
|
||||
action: "appsDrawer",
|
||||
|
@ -2111,7 +2107,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
oobData={this.props.oobData}
|
||||
inRoom={myMembership === 'join'}
|
||||
onSearchClick={this.onSearchClick}
|
||||
onSettingsClick={this.onSettingsClick}
|
||||
onForgetClick={(myMembership === "leave") ? this.onForgetClick : null}
|
||||
e2eStatus={this.state.e2eStatus}
|
||||
onAppsClick={this.state.hasPinnedWidgets ? this.onAppsClick : null}
|
||||
|
|
308
src/components/views/context_menus/RoomContextMenu.tsx
Normal file
308
src/components/views/context_menus/RoomContextMenu.tsx
Normal file
|
@ -0,0 +1,308 @@
|
|||
/*
|
||||
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 React, { useContext } from "react";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import { IProps as IContextMenuProps } from "../../structures/ContextMenu";
|
||||
import IconizedContextMenu, {
|
||||
IconizedContextMenuCheckbox,
|
||||
IconizedContextMenuOption,
|
||||
IconizedContextMenuOptionList,
|
||||
} from "./IconizedContextMenu";
|
||||
import { _t } from "../../../languageHandler";
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import { ButtonEvent } from "../elements/AccessibleButton";
|
||||
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
||||
import RoomListStore from "../../../stores/room-list/RoomListStore";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import RoomListActions from "../../../actions/RoomListActions";
|
||||
import { Key } from "../../../Keyboard";
|
||||
import { EchoChamber } from "../../../stores/local-echo/EchoChamber";
|
||||
import { RoomNotifState } from "../../../RoomNotifs";
|
||||
import Modal from "../../../Modal";
|
||||
import ExportDialog from "../dialogs/ExportDialog";
|
||||
import { onRoomFilesClick, onRoomMembersClick } from "../right_panel/RoomSummaryCard";
|
||||
import RoomViewStore from "../../../stores/RoomViewStore";
|
||||
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
||||
import { SetRightPanelPhasePayload } from "../../../dispatcher/payloads/SetRightPanelPhasePayload";
|
||||
import { Action } from "../../../dispatcher/actions";
|
||||
import { RightPanelPhases } from "../../../stores/RightPanelStorePhases";
|
||||
import { ROOM_NOTIFICATIONS_TAB } from "../dialogs/RoomSettingsDialog";
|
||||
|
||||
interface IProps extends IContextMenuProps {
|
||||
room: Room;
|
||||
}
|
||||
|
||||
const RoomContextMenu = ({ room, onFinished, ...props }: IProps) => {
|
||||
const cli = useContext(MatrixClientContext);
|
||||
const roomTags = RoomListStore.instance.getTagsForRoom(room);
|
||||
|
||||
let leaveOption: JSX.Element;
|
||||
if (roomTags.includes(DefaultTagID.Archived)) {
|
||||
const onForgetRoomClick = (ev: ButtonEvent) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
dis.dispatch({
|
||||
action: "forget_room",
|
||||
room_id: room.roomId,
|
||||
});
|
||||
onFinished();
|
||||
};
|
||||
|
||||
leaveOption = <IconizedContextMenuOption
|
||||
iconClassName="mx_RoomTile_iconSignOut"
|
||||
label={_t("Forget")}
|
||||
className="mx_IconizedContextMenu_option_red"
|
||||
onClick={onForgetRoomClick}
|
||||
/>;
|
||||
} else {
|
||||
const onLeaveRoomClick = (ev: ButtonEvent) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
dis.dispatch({
|
||||
action: "leave_room",
|
||||
room_id: room.roomId,
|
||||
});
|
||||
onFinished();
|
||||
};
|
||||
|
||||
leaveOption = <IconizedContextMenuOption
|
||||
onClick={onLeaveRoomClick}
|
||||
label={_t("Leave")}
|
||||
className="mx_IconizedContextMenu_option_red"
|
||||
iconClassName="mx_RoomTile_iconSignOut"
|
||||
/>;
|
||||
}
|
||||
|
||||
let inviteOption: JSX.Element;
|
||||
if (room.canInvite(cli.getUserId())) {
|
||||
const onInviteClick = (ev: ButtonEvent) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
dis.dispatch({
|
||||
action: "view_invite",
|
||||
roomId: room.roomId,
|
||||
});
|
||||
onFinished();
|
||||
};
|
||||
|
||||
inviteOption = <IconizedContextMenuOption
|
||||
onClick={onInviteClick}
|
||||
label={_t("Invite")}
|
||||
iconClassName="mx_RoomTile_iconInvite"
|
||||
/>;
|
||||
}
|
||||
|
||||
let favouriteOption: JSX.Element;
|
||||
let lowPriorityOption: JSX.Element;
|
||||
let notificationOption: JSX.Element;
|
||||
if (room.getMyMembership() === "join") {
|
||||
const isFavorite = roomTags.includes(DefaultTagID.Favourite);
|
||||
favouriteOption = <IconizedContextMenuCheckbox
|
||||
onClick={(e) => onTagRoom(e, DefaultTagID.Favourite)}
|
||||
active={isFavorite}
|
||||
label={isFavorite ? _t("Favourited") : _t("Favourite")}
|
||||
iconClassName="mx_RoomTile_iconStar"
|
||||
/>;
|
||||
|
||||
const isLowPriority = roomTags.includes(DefaultTagID.LowPriority);
|
||||
lowPriorityOption = <IconizedContextMenuCheckbox
|
||||
onClick={(e) => onTagRoom(e, DefaultTagID.LowPriority)}
|
||||
active={isLowPriority}
|
||||
label={_t("Low priority")}
|
||||
iconClassName="mx_RoomTile_iconArrowDown"
|
||||
/>;
|
||||
|
||||
const echoChamber = EchoChamber.forRoom(room);
|
||||
let notificationLabel: string;
|
||||
let iconClassName: string;
|
||||
switch (echoChamber.notificationVolume) {
|
||||
case RoomNotifState.AllMessages:
|
||||
notificationLabel = _t("Default");
|
||||
iconClassName = "mx_RoomTile_iconNotificationsDefault";
|
||||
break;
|
||||
case RoomNotifState.AllMessagesLoud:
|
||||
notificationLabel = _t("All messages");
|
||||
iconClassName = "mx_RoomTile_iconNotificationsAllMessages";
|
||||
break;
|
||||
case RoomNotifState.MentionsOnly:
|
||||
notificationLabel = _t("Mentions only");
|
||||
iconClassName = "mx_RoomTile_iconNotificationsMentionsKeywords";
|
||||
break;
|
||||
case RoomNotifState.Mute:
|
||||
notificationLabel = _t("Mute");
|
||||
iconClassName = "mx_RoomTile_iconNotificationsNone";
|
||||
break;
|
||||
}
|
||||
|
||||
notificationOption = <IconizedContextMenuOption
|
||||
onClick={(ev: ButtonEvent) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
dis.dispatch({
|
||||
action: "open_room_settings",
|
||||
room_id: room.roomId,
|
||||
initial_tab_id: ROOM_NOTIFICATIONS_TAB,
|
||||
});
|
||||
onFinished();
|
||||
}}
|
||||
label={_t("Notifications")}
|
||||
iconClassName={iconClassName}
|
||||
>
|
||||
<span className="mx_IconizedContextMenu_sublabel">
|
||||
{ notificationLabel }
|
||||
</span>
|
||||
</IconizedContextMenuOption>;
|
||||
}
|
||||
|
||||
const onTagRoom = (ev: ButtonEvent, tagId: TagID) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
if (tagId === DefaultTagID.Favourite || tagId === DefaultTagID.LowPriority) {
|
||||
const inverseTag = tagId === DefaultTagID.Favourite ? DefaultTagID.LowPriority : DefaultTagID.Favourite;
|
||||
const isApplied = RoomListStore.instance.getTagsForRoom(room).includes(tagId);
|
||||
const removeTag = isApplied ? tagId : inverseTag;
|
||||
const addTag = isApplied ? null : tagId;
|
||||
dis.dispatch(RoomListActions.tagRoom(cli, room, removeTag, addTag, undefined, 0));
|
||||
} else {
|
||||
logger.warn(`Unexpected tag ${tagId} applied to ${room.roomId}`);
|
||||
}
|
||||
|
||||
if ((ev as React.KeyboardEvent).key === Key.ENTER) {
|
||||
// Implements https://www.w3.org/TR/wai-aria-practices/#keyboard-interaction-12
|
||||
onFinished();
|
||||
}
|
||||
};
|
||||
|
||||
const ensureViewingRoom = () => {
|
||||
if (RoomViewStore.getRoomId() === room.roomId) return;
|
||||
dis.dispatch({
|
||||
action: "view_room",
|
||||
room_id: room.roomId,
|
||||
}, true);
|
||||
};
|
||||
|
||||
return <IconizedContextMenu {...props} onFinished={onFinished} className="mx_RoomTile_contextMenu" compact>
|
||||
<IconizedContextMenuOptionList>
|
||||
{ inviteOption }
|
||||
{ notificationOption }
|
||||
{ favouriteOption }
|
||||
|
||||
<IconizedContextMenuOption
|
||||
onClick={(ev: ButtonEvent) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
ensureViewingRoom();
|
||||
onRoomMembersClick(false);
|
||||
onFinished();
|
||||
}}
|
||||
label={_t("People")}
|
||||
iconClassName="mx_RoomTile_iconPeople"
|
||||
>
|
||||
<span className="mx_IconizedContextMenu_sublabel">
|
||||
{ room.getJoinedMemberCount() }
|
||||
</span>
|
||||
</IconizedContextMenuOption>
|
||||
|
||||
<IconizedContextMenuOption
|
||||
onClick={(ev: ButtonEvent) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
ensureViewingRoom();
|
||||
onRoomFilesClick(false);
|
||||
onFinished();
|
||||
}}
|
||||
label={_t("Files")}
|
||||
iconClassName="mx_RoomTile_iconFiles"
|
||||
/>
|
||||
|
||||
<IconizedContextMenuOption
|
||||
onClick={(ev: ButtonEvent) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
ensureViewingRoom();
|
||||
defaultDispatcher.dispatch<SetRightPanelPhasePayload>({
|
||||
action: Action.SetRightPanelPhase,
|
||||
phase: RightPanelPhases.RoomSummary,
|
||||
allowClose: false,
|
||||
});
|
||||
onFinished();
|
||||
}}
|
||||
label={_t("Widgets")}
|
||||
iconClassName="mx_RoomTile_iconWidgets"
|
||||
/>
|
||||
|
||||
{ lowPriorityOption }
|
||||
|
||||
<IconizedContextMenuOption
|
||||
onClick={(ev: ButtonEvent) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
dis.dispatch({
|
||||
action: "copy_room",
|
||||
room_id: room.roomId,
|
||||
});
|
||||
onFinished();
|
||||
}}
|
||||
label={_t("Copy link")}
|
||||
iconClassName="mx_RoomTile_iconCopyLink"
|
||||
/>
|
||||
|
||||
<IconizedContextMenuOption
|
||||
onClick={(ev: ButtonEvent) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
dis.dispatch({
|
||||
action: "open_room_settings",
|
||||
room_id: room.roomId,
|
||||
});
|
||||
onFinished();
|
||||
}}
|
||||
label={_t("Settings")}
|
||||
iconClassName="mx_RoomTile_iconSettings"
|
||||
/>
|
||||
|
||||
<IconizedContextMenuOption
|
||||
onClick={(ev: ButtonEvent) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
Modal.createTrackedDialog('Export room dialog', '', ExportDialog, { room });
|
||||
onFinished();
|
||||
}}
|
||||
label={_t("Export chat")}
|
||||
iconClassName="mx_RoomTile_iconExport"
|
||||
/>
|
||||
|
||||
{ leaveOption }
|
||||
</IconizedContextMenuOptionList>
|
||||
</IconizedContextMenu>;
|
||||
};
|
||||
|
||||
export default RoomContextMenu;
|
||||
|
|
@ -113,7 +113,7 @@ export default class RoomSettingsDialog extends React.Component<IProps, IState>
|
|||
ROOM_NOTIFICATIONS_TAB,
|
||||
_td("Notifications"),
|
||||
"mx_RoomSettingsDialog_notificationsIcon",
|
||||
<NotificationSettingsTab roomId={this.props.roomId} />,
|
||||
<NotificationSettingsTab roomId={this.props.roomId} closeSettingsFn={() => this.props.onFinished(true)} />,
|
||||
));
|
||||
|
||||
if (SettingsStore.getValue("feature_bridge_state")) {
|
||||
|
|
|
@ -207,17 +207,19 @@ const AppsSection: React.FC<IAppsSectionProps> = ({ room }) => {
|
|||
</Group>;
|
||||
};
|
||||
|
||||
const onRoomMembersClick = () => {
|
||||
export const onRoomMembersClick = (allowClose = true) => {
|
||||
defaultDispatcher.dispatch<SetRightPanelPhasePayload>({
|
||||
action: Action.SetRightPanelPhase,
|
||||
phase: RightPanelPhases.RoomMemberList,
|
||||
allowClose,
|
||||
});
|
||||
};
|
||||
|
||||
const onRoomFilesClick = () => {
|
||||
export const onRoomFilesClick = (allowClose = true) => {
|
||||
defaultDispatcher.dispatch<SetRightPanelPhasePayload>({
|
||||
action: Action.SetRightPanelPhase,
|
||||
phase: RightPanelPhases.FilePanel,
|
||||
allowClose,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -275,10 +277,13 @@ const RoomSummaryCard: React.FC<IProps> = ({ room, onClose }) => {
|
|||
return <BaseCard header={header} className="mx_RoomSummaryCard" onClose={onClose}>
|
||||
<Group title={_t("About")} className="mx_RoomSummaryCard_aboutGroup">
|
||||
<Button className="mx_RoomSummaryCard_icon_people" onClick={onRoomMembersClick}>
|
||||
{ _t("%(count)s people", { count: memberCount }) }
|
||||
{ _t("People") }
|
||||
<span className="mx_BaseCard_Button_sublabel">
|
||||
{ memberCount }
|
||||
</span>
|
||||
</Button>
|
||||
<Button className="mx_RoomSummaryCard_icon_files" onClick={onRoomFilesClick}>
|
||||
{ _t("Show files") }
|
||||
{ _t("Files") }
|
||||
</Button>
|
||||
<Button className="mx_RoomSummaryCard_icon_export" onClick={onRoomExportClick}>
|
||||
{ _t("Export chat") }
|
||||
|
|
|
@ -36,6 +36,9 @@ import { MatrixEvent, Room, RoomState } from 'matrix-js-sdk/src';
|
|||
import { E2EStatus } from '../../../utils/ShieldUtils';
|
||||
import { IOOBData } from '../../../stores/ThreepidInviteStore';
|
||||
import { SearchScope } from './SearchBar';
|
||||
import { ContextMenuTooltipButton } from '../../structures/ContextMenu';
|
||||
import RoomContextMenu from "../context_menus/RoomContextMenu";
|
||||
import { contextMenuBelow } from './RoomTile';
|
||||
|
||||
export interface ISearchInfo {
|
||||
searchTerm: string;
|
||||
|
@ -47,7 +50,6 @@ interface IProps {
|
|||
room: Room;
|
||||
oobData?: IOOBData;
|
||||
inRoom: boolean;
|
||||
onSettingsClick: () => void;
|
||||
onSearchClick: () => void;
|
||||
onForgetClick: () => void;
|
||||
onCallPlaced: (type: PlaceCallType) => void;
|
||||
|
@ -57,13 +59,23 @@ interface IProps {
|
|||
searchInfo: ISearchInfo;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
contextMenuPosition?: DOMRect;
|
||||
}
|
||||
|
||||
@replaceableComponent("views.rooms.RoomHeader")
|
||||
export default class RoomHeader extends React.Component<IProps> {
|
||||
export default class RoomHeader extends React.Component<IProps, IState> {
|
||||
static defaultProps = {
|
||||
editing: false,
|
||||
inRoom: false,
|
||||
};
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
const cli = MatrixClientPeg.get();
|
||||
cli.on("RoomState.events", this.onRoomStateEvents);
|
||||
|
@ -97,6 +109,17 @@ export default class RoomHeader extends React.Component<IProps> {
|
|||
});
|
||||
}
|
||||
|
||||
private onContextMenuOpenClick = (ev: React.MouseEvent) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
const target = ev.target as HTMLButtonElement;
|
||||
this.setState({ contextMenuPosition: target.getBoundingClientRect() });
|
||||
};
|
||||
|
||||
private onContextMenuCloseClick = () => {
|
||||
this.setState({ contextMenuPosition: null });
|
||||
};
|
||||
|
||||
public render() {
|
||||
let searchStatus = null;
|
||||
|
||||
|
@ -127,17 +150,35 @@ export default class RoomHeader extends React.Component<IProps> {
|
|||
oobName = this.props.oobData.name;
|
||||
}
|
||||
|
||||
let contextMenu: JSX.Element;
|
||||
if (this.state.contextMenuPosition && this.props.room) {
|
||||
contextMenu = (
|
||||
<RoomContextMenu
|
||||
{...contextMenuBelow(this.state.contextMenuPosition)}
|
||||
room={this.props.room}
|
||||
onFinished={this.onContextMenuCloseClick}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const textClasses = classNames('mx_RoomHeader_nametext', { mx_RoomHeader_settingsHint: settingsHint });
|
||||
const name =
|
||||
<div className="mx_RoomHeader_name" onClick={this.props.onSettingsClick}>
|
||||
const name = (
|
||||
<ContextMenuTooltipButton
|
||||
className="mx_RoomHeader_name"
|
||||
onClick={this.onContextMenuOpenClick}
|
||||
isExpanded={!!this.state.contextMenuPosition}
|
||||
title={_t("Room options")}
|
||||
>
|
||||
<RoomName room={this.props.room}>
|
||||
{ (name) => {
|
||||
const roomName = name || oobName;
|
||||
return <div dir="auto" className={textClasses} title={roomName}>{ roomName }</div>;
|
||||
} }
|
||||
</RoomName>
|
||||
{ searchStatus }
|
||||
</div>;
|
||||
{ this.props.room && <div className="mx_RoomHeader_chevron" /> }
|
||||
{ contextMenu }
|
||||
</ContextMenuTooltipButton>
|
||||
);
|
||||
|
||||
const topicElement = <RoomTopic room={this.props.room}>
|
||||
{ (topic, ref) => <div className="mx_RoomHeader_topic" ref={ref} title={topic} dir="auto">
|
||||
|
@ -149,7 +190,7 @@ export default class RoomHeader extends React.Component<IProps> {
|
|||
if (this.props.room) {
|
||||
roomAvatar = <DecoratedRoomAvatar
|
||||
room={this.props.room}
|
||||
avatarSize={32}
|
||||
avatarSize={24}
|
||||
oobData={this.props.oobData}
|
||||
viewAvatarOnClick={true}
|
||||
/>;
|
||||
|
@ -219,6 +260,7 @@ export default class RoomHeader extends React.Component<IProps> {
|
|||
<div className="mx_RoomHeader_avatar">{ roomAvatar }</div>
|
||||
<div className="mx_RoomHeader_e2eIcon">{ e2eIcon }</div>
|
||||
{ name }
|
||||
{ searchStatus }
|
||||
{ topicElement }
|
||||
{ rightRow }
|
||||
<RoomHeaderButtons room={this.props.room} />
|
||||
|
|
|
@ -70,7 +70,7 @@ interface IState {
|
|||
|
||||
const messagePreviewId = (roomId: string) => `mx_RoomTile_messagePreview_${roomId}`;
|
||||
|
||||
const contextMenuBelow = (elementRect: PartialDOMRect) => {
|
||||
export const contextMenuBelow = (elementRect: PartialDOMRect) => {
|
||||
// align the context menu's icons with the icon which opened the context menu
|
||||
const left = elementRect.left + window.pageXOffset - 9;
|
||||
const top = elementRect.bottom + window.pageYOffset + 17;
|
||||
|
@ -189,7 +189,6 @@ export default class RoomTile extends React.PureComponent<IProps, IState> {
|
|||
defaultDispatcher.unregister(this.dispatcherRef);
|
||||
this.notificationState.off(NOTIFICATION_STATE_UPDATE, this.onNotificationUpdate);
|
||||
this.roomProps.off(PROPERTY_UPDATED, this.onRoomPropertyUpdate);
|
||||
this.roomProps.off("Room.name", this.onRoomNameUpdate);
|
||||
CommunityPrototypeStore.instance.off(
|
||||
CommunityPrototypeStore.getUpdateEventName(this.props.room.roomId),
|
||||
this.onCommunityUpdate,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2019 New Vector Ltd
|
||||
Copyright 2019 - 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.
|
||||
|
@ -24,9 +24,18 @@ import { SettingLevel } from "../../../../../settings/SettingLevel";
|
|||
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
|
||||
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { RoomEchoChamber } from "../../../../../stores/local-echo/RoomEchoChamber";
|
||||
import { EchoChamber } from '../../../../../stores/local-echo/EchoChamber';
|
||||
import MatrixClientContext from "../../../../../contexts/MatrixClientContext";
|
||||
import StyledRadioGroup from "../../../elements/StyledRadioGroup";
|
||||
import { RoomNotifState } from '../../../../../RoomNotifs';
|
||||
import defaultDispatcher from "../../../../../dispatcher/dispatcher";
|
||||
import { Action } from "../../../../../dispatcher/actions";
|
||||
import { UserTab } from "../../../dialogs/UserSettingsDialog";
|
||||
|
||||
interface IProps {
|
||||
roomId: string;
|
||||
closeSettingsFn(): void;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
|
@ -36,10 +45,16 @@ interface IState {
|
|||
|
||||
@replaceableComponent("views.settings.tabs.room.NotificationsSettingsTab")
|
||||
export default class NotificationsSettingsTab extends React.Component<IProps, IState> {
|
||||
private readonly roomProps: RoomEchoChamber;
|
||||
private soundUpload = createRef<HTMLInputElement>();
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
static contextType = MatrixClientContext;
|
||||
public context!: React.ContextType<typeof MatrixClientContext>;
|
||||
|
||||
constructor(props: IProps, context: React.ContextType<typeof MatrixClientContext>) {
|
||||
super(props, context);
|
||||
|
||||
this.roomProps = EchoChamber.forRoom(context.getRoom(this.props.roomId));
|
||||
|
||||
this.state = {
|
||||
currentSound: "default",
|
||||
|
@ -144,6 +159,19 @@ export default class NotificationsSettingsTab extends React.Component<IProps, IS
|
|||
});
|
||||
};
|
||||
|
||||
private onRoomNotificationChange = (value: RoomNotifState) => {
|
||||
this.roomProps.notificationVolume = value;
|
||||
this.forceUpdate();
|
||||
};
|
||||
|
||||
private onOpenSettingsClick = () => {
|
||||
this.props.closeSettingsFn();
|
||||
defaultDispatcher.dispatch({
|
||||
action: Action.ViewUserSettings,
|
||||
initialTabId: UserTab.Notifications,
|
||||
});
|
||||
};
|
||||
|
||||
public render(): JSX.Element {
|
||||
let currentUploadedFile = null;
|
||||
if (this.state.uploadedFile) {
|
||||
|
@ -157,6 +185,63 @@ export default class NotificationsSettingsTab extends React.Component<IProps, IS
|
|||
return (
|
||||
<div className="mx_SettingsTab">
|
||||
<div className="mx_SettingsTab_heading">{ _t("Notifications") }</div>
|
||||
|
||||
<div className="mx_SettingsTab_section mx_NotificationSettingsTab_notificationsSection">
|
||||
<StyledRadioGroup
|
||||
name="roomNotificationSetting"
|
||||
definitions={[
|
||||
{
|
||||
value: RoomNotifState.AllMessages,
|
||||
className: "mx_NotificationSettingsTab_defaultEntry",
|
||||
label: <>
|
||||
{ _t("Default") }
|
||||
<div className="mx_NotificationSettingsTab_microCopy">
|
||||
{ _t("Get notifications as set up in your <a>settings</a>", {}, {
|
||||
a: sub => <AccessibleButton kind="link" onClick={this.onOpenSettingsClick}>
|
||||
{ sub }
|
||||
</AccessibleButton>,
|
||||
}) }
|
||||
</div>
|
||||
</>,
|
||||
}, {
|
||||
value: RoomNotifState.AllMessagesLoud,
|
||||
className: "mx_NotificationSettingsTab_allMessagesEntry",
|
||||
label: <>
|
||||
{ _t("All messages") }
|
||||
<div className="mx_NotificationSettingsTab_microCopy">
|
||||
{ _t("Get notified for every message") }
|
||||
</div>
|
||||
</>,
|
||||
}, {
|
||||
value: RoomNotifState.MentionsOnly,
|
||||
className: "mx_NotificationSettingsTab_mentionsKeywordsEntry",
|
||||
label: <>
|
||||
{ _t("@mentions & keywords") }
|
||||
<div className="mx_NotificationSettingsTab_microCopy">
|
||||
{ _t("Get notified only with mentions and keywords " +
|
||||
"as set up in your <a>settings</a>", {}, {
|
||||
a: sub => <AccessibleButton kind="link" onClick={this.onOpenSettingsClick}>
|
||||
{ sub }
|
||||
</AccessibleButton>,
|
||||
}) }
|
||||
</div>
|
||||
</>,
|
||||
}, {
|
||||
value: RoomNotifState.Mute,
|
||||
className: "mx_NotificationSettingsTab_noneEntry",
|
||||
label: <>
|
||||
{ _t("Off") }
|
||||
<div className="mx_NotificationSettingsTab_microCopy">
|
||||
{ _t("You won't get any notifications") }
|
||||
</div>
|
||||
</>,
|
||||
},
|
||||
]}
|
||||
onChange={this.onRoomNotificationChange}
|
||||
value={this.roomProps.notificationVolume}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
|
||||
<span className='mx_SettingsTab_subheading'>{ _t("Sounds") }</span>
|
||||
<div>
|
||||
|
|
|
@ -1470,6 +1470,12 @@
|
|||
"URL Previews": "URL Previews",
|
||||
"Room Addresses": "Room Addresses",
|
||||
"Uploaded sound": "Uploaded sound",
|
||||
"Get notifications as set up in your <a>settings</a>": "Get notifications as set up in your <a>settings</a>",
|
||||
"All messages": "All messages",
|
||||
"Get notified for every message": "Get notified for every message",
|
||||
"@mentions & keywords": "@mentions & keywords",
|
||||
"Get notified only with mentions and keywords as set up in your <a>settings</a>": "Get notified only with mentions and keywords as set up in your <a>settings</a>",
|
||||
"You won't get any notifications": "You won't get any notifications",
|
||||
"Sounds": "Sounds",
|
||||
"Notification sound": "Notification sound",
|
||||
"Set a new custom sound": "Set a new custom sound",
|
||||
|
@ -1680,6 +1686,7 @@
|
|||
"(~%(count)s results)|other": "(~%(count)s results)",
|
||||
"(~%(count)s results)|one": "(~%(count)s result)",
|
||||
"Join Room": "Join Room",
|
||||
"Room options": "Room options",
|
||||
"Forget room": "Forget room",
|
||||
"Hide Widgets": "Hide Widgets",
|
||||
"Show Widgets": "Show Widgets",
|
||||
|
@ -1761,7 +1768,6 @@
|
|||
"Show %(count)s more|one": "Show %(count)s more",
|
||||
"Show less": "Show less",
|
||||
"Use default": "Use default",
|
||||
"All messages": "All messages",
|
||||
"Mentions & Keywords": "Mentions & Keywords",
|
||||
"Notification options": "Notification options",
|
||||
"Forget Room": "Forget Room",
|
||||
|
@ -1772,7 +1778,6 @@
|
|||
"Copy Room Link": "Copy Room Link",
|
||||
"Settings": "Settings",
|
||||
"Leave Room": "Leave Room",
|
||||
"Room options": "Room options",
|
||||
"%(count)s unread messages including mentions.|other": "%(count)s unread messages including mentions.",
|
||||
"%(count)s unread messages including mentions.|one": "1 unread mention.",
|
||||
"%(count)s unread messages.|other": "%(count)s unread messages.",
|
||||
|
@ -1873,9 +1878,7 @@
|
|||
"Add widgets, bridges & bots": "Add widgets, bridges & bots",
|
||||
"Not encrypted": "Not encrypted",
|
||||
"About": "About",
|
||||
"%(count)s people|other": "%(count)s people",
|
||||
"%(count)s people|one": "%(count)s person",
|
||||
"Show files": "Show files",
|
||||
"Files": "Files",
|
||||
"Export chat": "Export chat",
|
||||
"Share room": "Share room",
|
||||
"Room settings": "Room settings",
|
||||
|
@ -2738,6 +2741,10 @@
|
|||
"Collapse reply thread": "Collapse reply thread",
|
||||
"Report": "Report",
|
||||
"View in room": "View in room",
|
||||
"Forget": "Forget",
|
||||
"Leave": "Leave",
|
||||
"Mentions only": "Mentions only",
|
||||
"Copy link": "Copy link",
|
||||
"See room timeline (devtools)": "See room timeline (devtools)",
|
||||
"Add space": "Add space",
|
||||
"Manage & explore rooms": "Manage & explore rooms",
|
||||
|
@ -2845,7 +2852,6 @@
|
|||
"You are an administrator of this community. You will not be able to rejoin without an invite from another administrator.": "You are an administrator of this community. You will not be able to rejoin without an invite from another administrator.",
|
||||
"Leave Community": "Leave Community",
|
||||
"Leave %(groupName)s?": "Leave %(groupName)s?",
|
||||
"Leave": "Leave",
|
||||
"Unable to leave community": "Unable to leave community",
|
||||
"Community Settings": "Community Settings",
|
||||
"Want more than a community? <a>Get your own server</a>": "Want more than a community? <a>Get your own server</a>",
|
||||
|
|
|
@ -19,6 +19,7 @@ import { getRoomNotifsState, RoomNotifState, setRoomNotifsState } from "../../Ro
|
|||
import { RoomEchoContext } from "./RoomEchoContext";
|
||||
import { _t } from "../../languageHandler";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { EventType } from "matrix-js-sdk/src/@types/event";
|
||||
|
||||
export enum CachedRoomKey {
|
||||
NotificationVolume,
|
||||
|
@ -46,7 +47,7 @@ export class RoomEchoChamber extends GenericEchoChamber<RoomEchoContext, CachedR
|
|||
}
|
||||
|
||||
private onAccountData = (event: MatrixEvent) => {
|
||||
if (event.getType() === "m.push_rules") {
|
||||
if (event.getType() === EventType.PushRules) {
|
||||
const currentVolume = this.properties.get(CachedRoomKey.NotificationVolume) as RoomNotifState;
|
||||
const newVolume = getRoomNotifsState(this.context.room.roomId) as RoomNotifState;
|
||||
if (currentVolume !== newVolume) {
|
||||
|
|
|
@ -159,7 +159,6 @@ function render(room: Room): HTMLDivElement {
|
|||
<RoomHeader
|
||||
room={room}
|
||||
inRoom={true}
|
||||
onSettingsClick={() => {}}
|
||||
onSearchClick={() => {}}
|
||||
onForgetClick={() => {}}
|
||||
onCallPlaced={(_type: PlaceCallType) => {}}
|
||||
|
|
Loading…
Reference in a new issue