Merge pull request #8521 from matrix-org/travis/remove-unused-labs-1

Remove some labs features which don't get used or create maintenance burden: custom status, multiple integration managers, and do not disturb
This commit is contained in:
Travis Ralston 2022-05-06 13:21:07 -06:00 committed by GitHub
commit d39d332f54
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 17 additions and 624 deletions

View file

@ -126,7 +126,6 @@
@import "./views/dialogs/_SpacePreferencesDialog.scss"; @import "./views/dialogs/_SpacePreferencesDialog.scss";
@import "./views/dialogs/_SpaceSettingsDialog.scss"; @import "./views/dialogs/_SpaceSettingsDialog.scss";
@import "./views/dialogs/_SpotlightDialog.scss"; @import "./views/dialogs/_SpotlightDialog.scss";
@import "./views/dialogs/_TabbedIntegrationManagerDialog.scss";
@import "./views/dialogs/_TermsDialog.scss"; @import "./views/dialogs/_TermsDialog.scss";
@import "./views/dialogs/_UntrustedDeviceDialog.scss"; @import "./views/dialogs/_UntrustedDeviceDialog.scss";
@import "./views/dialogs/_UploadConfirmDialog.scss"; @import "./views/dialogs/_UploadConfirmDialog.scss";

View file

@ -1,62 +0,0 @@
/*
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_TabbedIntegrationManagerDialog .mx_Dialog {
width: 60%;
height: 70%;
overflow: hidden;
padding: 0;
max-width: initial;
max-height: initial;
position: relative;
}
.mx_TabbedIntegrationManagerDialog_container {
// Full size of the dialog, whatever it is
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
.mx_TabbedIntegrationManagerDialog_currentManager {
width: 100%;
height: 100%;
border-top: 1px solid $accent;
iframe {
background-color: #fff;
border: 0;
width: 100%;
height: 100%;
}
}
}
.mx_TabbedIntegrationManagerDialog_tab {
display: inline-block;
border: 1px solid $accent;
border-bottom: 0;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
padding: 10px 8px;
margin-right: 5px;
}
.mx_TabbedIntegrationManagerDialog_currentTab {
background-color: $accent;
color: $accent-fg-color;
}

View file

@ -408,10 +408,6 @@ export const Notifier = {
// don't bother notifying as user was recently active in this room // don't bother notifying as user was recently active in this room
return; return;
} }
if (SettingsStore.getValue("doNotDisturb")) {
// Don't bother the user if they didn't ask to be bothered
return;
}
if (this.isEnabled()) { if (this.isEnabled()) {
this._displayPopupNotification(ev, room); this._displayPopupNotification(ev, room);

View file

@ -14,9 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React, { createRef, useContext, useRef, useState } from "react"; import React, { createRef } from "react";
import { Room } from "matrix-js-sdk/src/models/room"; import { Room } from "matrix-js-sdk/src/models/room";
import classNames from "classnames";
import { MatrixClientPeg } from "../../MatrixClientPeg"; import { MatrixClientPeg } from "../../MatrixClientPeg";
import defaultDispatcher from "../../dispatcher/dispatcher"; import defaultDispatcher from "../../dispatcher/dispatcher";
@ -32,9 +31,7 @@ import LogoutDialog from "../views/dialogs/LogoutDialog";
import SettingsStore from "../../settings/SettingsStore"; import SettingsStore from "../../settings/SettingsStore";
import { findHighContrastTheme, getCustomTheme, isHighContrastTheme } from "../../theme"; import { findHighContrastTheme, getCustomTheme, isHighContrastTheme } from "../../theme";
import { import {
RovingAccessibleButton,
RovingAccessibleTooltipButton, RovingAccessibleTooltipButton,
useRovingTabIndex,
} from "../../accessibility/RovingTabIndex"; } from "../../accessibility/RovingTabIndex";
import AccessibleButton, { ButtonEvent } from "../views/elements/AccessibleButton"; import AccessibleButton, { ButtonEvent } from "../views/elements/AccessibleButton";
import SdkConfig from "../../SdkConfig"; import SdkConfig from "../../SdkConfig";
@ -44,7 +41,6 @@ import { UPDATE_EVENT } from "../../stores/AsyncStore";
import BaseAvatar from '../views/avatars/BaseAvatar'; import BaseAvatar from '../views/avatars/BaseAvatar';
import { SettingLevel } from "../../settings/SettingLevel"; import { SettingLevel } from "../../settings/SettingLevel";
import IconizedContextMenu, { import IconizedContextMenu, {
IconizedContextMenuCheckbox,
IconizedContextMenuOption, IconizedContextMenuOption,
IconizedContextMenuOptionList, IconizedContextMenuOptionList,
} from "../views/context_menus/IconizedContextMenu"; } from "../views/context_menus/IconizedContextMenu";
@ -52,65 +48,10 @@ import { UIFeature } from "../../settings/UIFeature";
import HostSignupAction from "./HostSignupAction"; import HostSignupAction from "./HostSignupAction";
import SpaceStore from "../../stores/spaces/SpaceStore"; import SpaceStore from "../../stores/spaces/SpaceStore";
import { UPDATE_SELECTED_SPACE } from "../../stores/spaces"; import { UPDATE_SELECTED_SPACE } from "../../stores/spaces";
import MatrixClientContext from "../../contexts/MatrixClientContext";
import { SettingUpdatedPayload } from "../../dispatcher/payloads/SettingUpdatedPayload";
import UserIdentifierCustomisations from "../../customisations/UserIdentifier"; import UserIdentifierCustomisations from "../../customisations/UserIdentifier";
import PosthogTrackers from "../../PosthogTrackers"; import PosthogTrackers from "../../PosthogTrackers";
import { ViewHomePagePayload } from "../../dispatcher/payloads/ViewHomePagePayload"; import { ViewHomePagePayload } from "../../dispatcher/payloads/ViewHomePagePayload";
const CustomStatusSection = () => {
const cli = useContext(MatrixClientContext);
const setStatus = cli.getUser(cli.getUserId()).unstable_statusMessage || "";
const [value, setValue] = useState(setStatus);
const ref = useRef<HTMLInputElement>(null);
const [onFocus, isActive] = useRovingTabIndex(ref);
const classes = classNames({
'mx_UserMenu_CustomStatusSection_field': true,
'mx_UserMenu_CustomStatusSection_field_hasQuery': value,
});
let details: JSX.Element;
if (value !== setStatus) {
details = <>
<p>{ _t("Your status will be shown to people you have a DM with.") }</p>
<RovingAccessibleButton
onClick={() => cli._unstable_setStatusMessage(value)}
kind="primary_outline"
>
{ value ? _t("Set status") : _t("Clear status") }
</RovingAccessibleButton>
</>;
}
return <form className="mx_UserMenu_CustomStatusSection">
<div className={classes}>
<input
type="text"
value={value}
className="mx_UserMenu_CustomStatusSection_input"
onChange={e => setValue(e.target.value)}
placeholder={_t("Set a new status")}
autoComplete="off"
onFocus={onFocus}
ref={ref}
tabIndex={isActive ? 0 : -1}
/>
<AccessibleButton
// The clear button is only for mouse users
tabIndex={-1}
title={_t("Clear")}
className="mx_UserMenu_CustomStatusSection_clear"
onClick={() => setValue("")}
/>
</div>
{ details }
</form>;
};
interface IProps { interface IProps {
isPanelCollapsed: boolean; isPanelCollapsed: boolean;
} }
@ -122,7 +63,6 @@ interface IState {
isDarkTheme: boolean; isDarkTheme: boolean;
isHighContrast: boolean; isHighContrast: boolean;
selectedSpace?: Room; selectedSpace?: Room;
dndEnabled: boolean;
} }
const toRightOf = (rect: PartialDOMRect) => { const toRightOf = (rect: PartialDOMRect) => {
@ -154,19 +94,11 @@ export default class UserMenu extends React.Component<IProps, IState> {
contextMenuPosition: null, contextMenuPosition: null,
isDarkTheme: this.isUserOnDarkTheme(), isDarkTheme: this.isUserOnDarkTheme(),
isHighContrast: this.isUserOnHighContrastTheme(), isHighContrast: this.isUserOnHighContrastTheme(),
dndEnabled: this.doNotDisturb,
selectedSpace: SpaceStore.instance.activeSpaceRoom, selectedSpace: SpaceStore.instance.activeSpaceRoom,
}; };
OwnProfileStore.instance.on(UPDATE_EVENT, this.onProfileUpdate); OwnProfileStore.instance.on(UPDATE_EVENT, this.onProfileUpdate);
SpaceStore.instance.on(UPDATE_SELECTED_SPACE, this.onSelectedSpaceUpdate); SpaceStore.instance.on(UPDATE_SELECTED_SPACE, this.onSelectedSpaceUpdate);
SettingsStore.monitorSetting("feature_dnd", null);
SettingsStore.monitorSetting("doNotDisturb", null);
}
private get doNotDisturb(): boolean {
return SettingsStore.getValue("doNotDisturb");
} }
private get hasHomePage(): boolean { private get hasHomePage(): boolean {
@ -239,20 +171,6 @@ export default class UserMenu extends React.Component<IProps, IState> {
if (this.buttonRef.current) this.buttonRef.current.click(); if (this.buttonRef.current) this.buttonRef.current.click();
} }
break; break;
case Action.SettingUpdated: {
const settingUpdatedPayload = payload as SettingUpdatedPayload;
switch (settingUpdatedPayload.settingName) {
case "feature_dnd":
case "doNotDisturb": {
const dndEnabled = this.doNotDisturb;
if (this.state.dndEnabled !== dndEnabled) {
this.setState({ dndEnabled });
}
break;
}
}
}
} }
}; };
@ -348,12 +266,6 @@ export default class UserMenu extends React.Component<IProps, IState> {
this.setState({ contextMenuPosition: null }); // also close the menu this.setState({ contextMenuPosition: null }); // also close the menu
}; };
private onDndToggle = (ev: ButtonEvent) => {
ev.stopPropagation();
const current = SettingsStore.getValue("doNotDisturb");
SettingsStore.setValue("doNotDisturb", null, SettingLevel.DEVICE, !current);
};
private renderContextMenu = (): React.ReactNode => { private renderContextMenu = (): React.ReactNode => {
if (!this.state.contextMenuPosition) return null; if (!this.state.contextMenuPosition) return null;
@ -400,24 +312,6 @@ export default class UserMenu extends React.Component<IProps, IState> {
); );
} }
let customStatusSection: JSX.Element;
if (SettingsStore.getValue("feature_custom_status")) {
customStatusSection = <CustomStatusSection />;
}
let dndButton: JSX.Element;
if (SettingsStore.getValue("feature_dnd")) {
dndButton = (
<IconizedContextMenuCheckbox
iconClassName={this.state.dndEnabled ? "mx_UserMenu_iconDnd" : "mx_UserMenu_iconDndOff"}
label={_t("Do not disturb")}
onClick={this.onDndToggle}
active={this.state.dndEnabled}
words
/>
);
}
let feedbackButton; let feedbackButton;
if (SettingsStore.getValue(UIFeature.Feedback)) { if (SettingsStore.getValue(UIFeature.Feedback)) {
feedbackButton = <IconizedContextMenuOption feedbackButton = <IconizedContextMenuOption
@ -430,7 +324,6 @@ export default class UserMenu extends React.Component<IProps, IState> {
let primaryOptionList = ( let primaryOptionList = (
<IconizedContextMenuOptionList> <IconizedContextMenuOptionList>
{ homeButton } { homeButton }
{ dndButton }
<IconizedContextMenuOption <IconizedContextMenuOption
iconClassName="mx_UserMenu_iconBell" iconClassName="mx_UserMenu_iconBell"
label={_t("Notifications")} label={_t("Notifications")}
@ -502,7 +395,6 @@ export default class UserMenu extends React.Component<IProps, IState> {
/> />
</RovingAccessibleTooltipButton> </RovingAccessibleTooltipButton>
</div> </div>
{ customStatusSection }
{ topSection } { topSection }
{ primaryOptionList } { primaryOptionList }
</IconizedContextMenu>; </IconizedContextMenu>;
@ -515,11 +407,6 @@ export default class UserMenu extends React.Component<IProps, IState> {
const displayName = OwnProfileStore.instance.displayName || userId; const displayName = OwnProfileStore.instance.displayName || userId;
const avatarUrl = OwnProfileStore.instance.getHttpAvatarUrl(avatarSize); const avatarUrl = OwnProfileStore.instance.getHttpAvatarUrl(avatarSize);
let badge: JSX.Element;
if (this.state.dndEnabled) {
badge = <div className="mx_UserMenu_dndBadge" />;
}
let name: JSX.Element; let name: JSX.Element;
if (!this.props.isPanelCollapsed) { if (!this.props.isPanelCollapsed) {
name = <div className="mx_UserMenu_name"> name = <div className="mx_UserMenu_name">
@ -534,9 +421,6 @@ export default class UserMenu extends React.Component<IProps, IState> {
label={_t("User menu")} label={_t("User menu")}
isExpanded={!!this.state.contextMenuPosition} isExpanded={!!this.state.contextMenuPosition}
onContextMenu={this.onContextMenu} onContextMenu={this.onContextMenu}
className={classNames({
mx_UserMenu_cutout: badge,
})}
> >
<div className="mx_UserMenu_userAvatar"> <div className="mx_UserMenu_userAvatar">
<BaseAvatar <BaseAvatar
@ -548,7 +432,6 @@ export default class UserMenu extends React.Component<IProps, IState> {
resizeMethod="crop" resizeMethod="crop"
className="mx_UserMenu_userAvatar_BaseAvatar" className="mx_UserMenu_userAvatar_BaseAvatar"
/> />
{ badge }
</div> </div>
{ name } { name }

View file

@ -1,176 +0,0 @@
/*
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import { Room } from "matrix-js-sdk/src/models/room";
import classNames from 'classnames';
import { logger } from "matrix-js-sdk/src/logger";
import { IntegrationManagers } from "../../../integrations/IntegrationManagers";
import { dialogTermsInteractionCallback, TermsNotSignedError } from "../../../Terms";
import * as ScalarMessaging from "../../../ScalarMessaging";
import { IntegrationManagerInstance } from "../../../integrations/IntegrationManagerInstance";
import ScalarAuthClient from "../../../ScalarAuthClient";
import AccessibleButton from "../elements/AccessibleButton";
import IntegrationManager from "../settings/IntegrationManager";
import { IDialogProps } from "./IDialogProps";
interface IProps extends IDialogProps {
/**
* Optional room where the integration manager should be open to
*/
room?: Room;
/**
* Optional screen to open on the integration manager
*/
screen?: string;
/**
* Optional integration ID to open in the integration manager
*/
integrationId?: string;
}
interface IState {
managers: IntegrationManagerInstance[];
busy: boolean;
currentIndex: number;
currentConnected: boolean;
currentLoading: boolean;
currentScalarClient: ScalarAuthClient;
}
export default class TabbedIntegrationManagerDialog extends React.Component<IProps, IState> {
constructor(props: IProps) {
super(props);
this.state = {
managers: IntegrationManagers.sharedInstance().getOrderedManagers(),
busy: true,
currentIndex: 0,
currentConnected: false,
currentLoading: true,
currentScalarClient: null,
};
}
public componentDidMount(): void {
this.openManager(0, true);
}
private openManager = async (i: number, force = false): Promise<void> => {
if (i === this.state.currentIndex && !force) return;
const manager = this.state.managers[i];
const client = manager.getScalarClient();
this.setState({
busy: true,
currentIndex: i,
currentLoading: true,
currentConnected: false,
currentScalarClient: client,
});
ScalarMessaging.setOpenManagerUrl(manager.uiUrl);
client.setTermsInteractionCallback((policyInfo, agreedUrls) => {
// To avoid visual glitching of two modals stacking briefly, we customise the
// terms dialog sizing when it will appear for the integration manager so that
// it gets the same basic size as the IM's own modal.
return dialogTermsInteractionCallback(
policyInfo, agreedUrls, 'mx_TermsDialog_forIntegrationManager',
);
});
try {
await client.connect();
if (!client.hasCredentials()) {
this.setState({
busy: false,
currentLoading: false,
currentConnected: false,
});
} else {
this.setState({
busy: false,
currentLoading: false,
currentConnected: true,
});
}
} catch (e) {
if (e instanceof TermsNotSignedError) {
return;
}
logger.error(e);
this.setState({
busy: false,
currentLoading: false,
currentConnected: false,
});
}
};
private renderTabs(): JSX.Element[] {
return this.state.managers.map((m, i) => {
const classes = classNames({
'mx_TabbedIntegrationManagerDialog_tab': true,
'mx_TabbedIntegrationManagerDialog_currentTab': this.state.currentIndex === i,
});
return (
<AccessibleButton
className={classes}
onClick={() => this.openManager(i)}
key={`tab_${i}`}
disabled={this.state.busy}
>
{ m.name }
</AccessibleButton>
);
});
}
public renderTab(): JSX.Element {
let uiUrl = null;
if (this.state.currentScalarClient) {
uiUrl = this.state.currentScalarClient.getScalarInterfaceUrlForRoom(
this.props.room,
this.props.screen,
this.props.integrationId,
);
}
return <IntegrationManager
loading={this.state.currentLoading}
connected={this.state.currentConnected}
url={uiUrl}
onFinished={() => {/* no-op */}}
/>;
}
public render(): JSX.Element {
return (
<div className='mx_TabbedIntegrationManagerDialog_container'>
<div className='mx_TabbedIntegrationManagerDialog_tabs'>
{ this.renderTabs() }
</div>
<div className='mx_TabbedIntegrationManagerDialog_currentManager'>
{ this.renderTab() }
</div>
</div>
);
}
}

View file

@ -207,11 +207,8 @@ const AppsSection: React.FC<IAppsSectionProps> = ({ room }) => {
if (!managers.hasManager()) { if (!managers.hasManager()) {
managers.openNoManagerDialog(); managers.openNoManagerDialog();
} else { } else {
if (SettingsStore.getValue("feature_many_integration_managers")) { // noinspection JSIgnoredPromiseFromCall
managers.openAll(room); managers.getPrimaryManager().open(room);
} else {
managers.getPrimaryManager().open(room);
}
} }
}; };

View file

@ -75,7 +75,6 @@ import { UIComponent } from "../../../settings/UIFeature";
import { TimelineRenderingType } from "../../../contexts/RoomContext"; import { TimelineRenderingType } from "../../../contexts/RoomContext";
import RightPanelStore from '../../../stores/right-panel/RightPanelStore'; import RightPanelStore from '../../../stores/right-panel/RightPanelStore';
import { IRightPanelCardState } from '../../../stores/right-panel/RightPanelStoreIPanelState'; import { IRightPanelCardState } from '../../../stores/right-panel/RightPanelStoreIPanelState';
import { useUserStatusMessage } from "../../../hooks/useUserStatusMessage";
import UserIdentifierCustomisations from '../../../customisations/UserIdentifier'; import UserIdentifierCustomisations from '../../../customisations/UserIdentifier';
import PosthogTrackers from "../../../PosthogTrackers"; import PosthogTrackers from "../../../PosthogTrackers";
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
@ -1411,7 +1410,6 @@ const UserInfoHeader: React.FC<{
roomId?: string; roomId?: string;
}> = ({ member, e2eStatus, roomId }) => { }> = ({ member, e2eStatus, roomId }) => {
const cli = useContext(MatrixClientContext); const cli = useContext(MatrixClientContext);
const statusMessage = useUserStatusMessage(member);
const onMemberAvatarClick = useCallback(() => { const onMemberAvatarClick = useCallback(() => {
const avatarUrl = (member as RoomMember).getMxcAvatarUrl const avatarUrl = (member as RoomMember).getMxcAvatarUrl
@ -1472,11 +1470,6 @@ const UserInfoHeader: React.FC<{
); );
} }
let statusLabel = null;
if (statusMessage) {
statusLabel = <span className="mx_UserInfo_statusMessage">{ statusMessage }</span>;
}
let e2eIcon; let e2eIcon;
if (e2eStatus) { if (e2eStatus) {
e2eIcon = <E2EIcon size={18} status={e2eStatus} isUser={true} />; e2eIcon = <E2EIcon size={18} status={e2eStatus} isUser={true} />;
@ -1499,7 +1492,6 @@ const UserInfoHeader: React.FC<{
<div>{ UserIdentifierCustomisations.getDisplayUserIdentifier(member.userId, { roomId, withDisplayName: true }) }</div> <div>{ UserIdentifierCustomisations.getDisplayUserIdentifier(member.userId, { roomId, withDisplayName: true }) }</div>
<div className="mx_UserInfo_profileStatus"> <div className="mx_UserInfo_profileStatus">
{ presenceLabel } { presenceLabel }
{ statusLabel }
</div> </div>
</div> </div>
</div> </div>

View file

@ -20,12 +20,10 @@ import { RoomMember } from "matrix-js-sdk/src/models/room-member";
import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { EventType } from "matrix-js-sdk/src/@types/event"; import { EventType } from "matrix-js-sdk/src/@types/event";
import { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo"; import { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo";
import { UserEvent } from "matrix-js-sdk/src/models/user";
import { CryptoEvent } from "matrix-js-sdk/src/crypto"; import { CryptoEvent } from "matrix-js-sdk/src/crypto";
import { RoomStateEvent } from "matrix-js-sdk/src/models/room-state"; import { RoomStateEvent } from "matrix-js-sdk/src/models/room-state";
import { UserTrustLevel } from 'matrix-js-sdk/src/crypto/CrossSigning'; import { UserTrustLevel } from 'matrix-js-sdk/src/crypto/CrossSigning';
import SettingsStore from "../../../settings/SettingsStore";
import dis from "../../../dispatcher/dispatcher"; import dis from "../../../dispatcher/dispatcher";
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { MatrixClientPeg } from "../../../MatrixClientPeg";
@ -41,7 +39,6 @@ interface IProps {
} }
interface IState { interface IState {
statusMessage: string;
isRoomEncrypted: boolean; isRoomEncrypted: boolean;
e2eStatus: string; e2eStatus: string;
} }
@ -58,7 +55,6 @@ export default class MemberTile extends React.Component<IProps, IState> {
super(props); super(props);
this.state = { this.state = {
statusMessage: this.getStatusMessage(),
isRoomEncrypted: false, isRoomEncrypted: false,
e2eStatus: null, e2eStatus: null,
}; };
@ -67,13 +63,6 @@ export default class MemberTile extends React.Component<IProps, IState> {
componentDidMount() { componentDidMount() {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
if (SettingsStore.getValue("feature_custom_status")) {
const { user } = this.props.member;
if (user) {
user.on(UserEvent._UnstableStatusMessage, this.onStatusMessageCommitted);
}
}
const { roomId } = this.props.member; const { roomId } = this.props.member;
if (roomId) { if (roomId) {
const isRoomEncrypted = cli.isRoomEncrypted(roomId); const isRoomEncrypted = cli.isRoomEncrypted(roomId);
@ -94,11 +83,6 @@ export default class MemberTile extends React.Component<IProps, IState> {
componentWillUnmount() { componentWillUnmount() {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
const { user } = this.props.member;
if (user) {
user.removeListener(UserEvent._UnstableStatusMessage, this.onStatusMessageCommitted);
}
if (cli) { if (cli) {
cli.removeListener(RoomStateEvent.Events, this.onRoomStateEvents); cli.removeListener(RoomStateEvent.Events, this.onRoomStateEvents);
cli.removeListener(CryptoEvent.UserTrustStatusChanged, this.onUserTrustStatusChanged); cli.removeListener(CryptoEvent.UserTrustStatusChanged, this.onUserTrustStatusChanged);
@ -158,21 +142,6 @@ export default class MemberTile extends React.Component<IProps, IState> {
}); });
} }
private getStatusMessage(): string {
const { user } = this.props.member;
if (!user) {
return "";
}
return user.unstable_statusMessage;
}
private onStatusMessageCommitted = (): void => {
// The `User` object has observed a status message change.
this.setState({
statusMessage: this.getStatusMessage(),
});
};
shouldComponentUpdate(nextProps: IProps, nextState: IState): boolean { shouldComponentUpdate(nextProps: IProps, nextState: IState): boolean {
if ( if (
this.memberLastModifiedTime === undefined || this.memberLastModifiedTime === undefined ||
@ -222,11 +191,6 @@ export default class MemberTile extends React.Component<IProps, IState> {
const name = this.getDisplayName(); const name = this.getDisplayName();
const presenceState = member.user ? member.user.presence : null; const presenceState = member.user ? member.user.presence : null;
let statusMessage = null;
if (member.user && SettingsStore.getValue("feature_custom_status")) {
statusMessage = this.state.statusMessage;
}
const av = ( const av = (
<MemberAvatar member={member} width={36} height={36} aria-hidden="true" /> <MemberAvatar member={member} width={36} height={36} aria-hidden="true" />
); );
@ -277,7 +241,6 @@ export default class MemberTile extends React.Component<IProps, IState> {
nameJSX={nameJSX} nameJSX={nameJSX}
powerStatus={powerStatus} powerStatus={powerStatus}
showPresence={this.props.showPresence} showPresence={this.props.showPresence}
subtextLabel={statusMessage}
e2eStatus={e2eStatus} e2eStatus={e2eStatus}
onClick={this.onClick} onClick={this.onClick}
/> />

View file

@ -26,7 +26,6 @@ import AccessibleButton from '../elements/AccessibleButton';
import WidgetUtils, { IWidgetEvent } from '../../../utils/WidgetUtils'; import WidgetUtils, { IWidgetEvent } from '../../../utils/WidgetUtils';
import PersistedElement from "../elements/PersistedElement"; import PersistedElement from "../elements/PersistedElement";
import { IntegrationManagers } from "../../../integrations/IntegrationManagers"; import { IntegrationManagers } from "../../../integrations/IntegrationManagers";
import SettingsStore from "../../../settings/SettingsStore";
import ContextMenu, { ChevronFace } from "../../structures/ContextMenu"; import ContextMenu, { ChevronFace } from "../../structures/ContextMenu";
import { WidgetType } from "../../../widgets/WidgetType"; import { WidgetType } from "../../../widgets/WidgetType";
import { WidgetMessagingStore } from "../../../stores/widgets/WidgetMessagingStore"; import { WidgetMessagingStore } from "../../../stores/widgets/WidgetMessagingStore";
@ -339,20 +338,12 @@ export default class Stickerpicker extends React.PureComponent<IProps, IState> {
* Launch the integration manager on the stickers integration page * Launch the integration manager on the stickers integration page
*/ */
private launchManageIntegrations = (): void => { private launchManageIntegrations = (): void => {
// TODO: Open the right integration manager for the widget // noinspection JSIgnoredPromiseFromCall
if (SettingsStore.getValue("feature_many_integration_managers")) { IntegrationManagers.sharedInstance().getPrimaryManager().open(
IntegrationManagers.sharedInstance().openAll( this.props.room,
this.props.room, `type_${WidgetType.STICKERPICKER.preferred}`,
`type_${WidgetType.STICKERPICKER.preferred}`, this.state.widgetId,
this.state.widgetId, );
);
} else {
IntegrationManagers.sharedInstance().getPrimaryManager().open(
this.props.room,
`type_${WidgetType.STICKERPICKER.preferred}`,
this.state.widgetId,
);
}
}; };
public render(): JSX.Element { public render(): JSX.Element {

View file

@ -278,12 +278,6 @@ export enum Action {
*/ */
OpenReportEventDialog = "open_report_event_dialog", OpenReportEventDialog = "open_report_event_dialog",
/**
* Fired when the tabbed integration manager dialog needs to be opened.
* Payload: OpenTabbedIntegrationManagerDialogPayload
*/
OpenTabbedIntegrationManagerDialog = "open_tabbed_imanager_dialog",
/** /**
* Fired when something within the application has determined that a logout, * Fired when something within the application has determined that a logout,
* or logout-like behaviour, needs to happen. Specifically meant to target * or logout-like behaviour, needs to happen. Specifically meant to target

View file

@ -1,29 +0,0 @@
/*
Copyright 2022 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 { Room } from "matrix-js-sdk/src/models/room";
import { Optional } from "matrix-events-sdk";
import { ActionPayload } from "../payloads";
import { Action } from "../actions";
export interface OpenTabbedIntegrationManagerDialogPayload extends ActionPayload {
action: Action.OpenTabbedIntegrationManagerDialog;
room: Optional<Room>;
screen: Optional<string>;
integrationId: Optional<string>;
}

View file

@ -1,39 +0,0 @@
/*
Copyright 2021 Šimon Brandner <simon.bra.ag@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import { MatrixClient } from "matrix-js-sdk/src/client";
import { User, UserEvent } from "matrix-js-sdk/src/models/user";
import { useContext } from "react";
import MatrixClientContext from "../contexts/MatrixClientContext";
import { useTypedEventEmitterState } from "./useEventEmitter";
import { Member } from "../components/views/right_panel/UserInfo";
import { useFeatureEnabled } from "./useSettings";
const getUser = (cli: MatrixClient, user: Member): User => cli.getUser(user?.userId);
const getStatusMessage = (cli: MatrixClient, user: Member): string => {
return getUser(cli, user)?.unstable_statusMessage;
};
// Hook to simplify handling Matrix User status
export const useUserStatusMessage = (member?: Member): string => {
const cli = useContext(MatrixClientContext);
const enabled = useFeatureEnabled("feature_custom_status");
const user = enabled ? getUser(cli, member) : undefined;
return useTypedEventEmitterState(user, UserEvent._UnstableStatusMessage, () => {
return getStatusMessage(cli, user);
});
};

View file

@ -869,7 +869,6 @@
"Developer": "Developer", "Developer": "Developer",
"Let moderators hide messages pending moderation.": "Let moderators hide messages pending moderation.", "Let moderators hide messages pending moderation.": "Let moderators hide messages pending moderation.",
"Report to moderators prototype. In rooms that support moderation, the `report` button will let you report abuse to room moderators": "Report to moderators prototype. In rooms that support moderation, the `report` button will let you report abuse to room moderators", "Report to moderators prototype. In rooms that support moderation, the `report` button will let you report abuse to room moderators": "Report to moderators prototype. In rooms that support moderation, the `report` button will let you report abuse to room moderators",
"Show options to enable 'Do not disturb' mode": "Show options to enable 'Do not disturb' mode",
"Render LaTeX maths in messages": "Render LaTeX maths in messages", "Render LaTeX maths in messages": "Render LaTeX maths in messages",
"Message Pinning": "Message Pinning", "Message Pinning": "Message Pinning",
"Threaded messaging": "Threaded messaging", "Threaded messaging": "Threaded messaging",
@ -882,10 +881,8 @@
"To leave, return to this page and use the “%(leaveTheBeta)s” button.": "To leave, return to this page and use the “%(leaveTheBeta)s” button.", "To leave, return to this page and use the “%(leaveTheBeta)s” button.": "To leave, return to this page and use the “%(leaveTheBeta)s” button.",
"Leave the beta": "Leave the beta", "Leave the beta": "Leave the beta",
"Thank you for trying the beta, please go into as much detail as you can so we can improve it.": "Thank you for trying the beta, please go into as much detail as you can so we can improve it.", "Thank you for trying the beta, please go into as much detail as you can so we can improve it.": "Thank you for trying the beta, please go into as much detail as you can so we can improve it.",
"Custom user status messages": "Custom user status messages",
"Video rooms (under active development)": "Video rooms (under active development)", "Video rooms (under active development)": "Video rooms (under active development)",
"Render simple counters in room header": "Render simple counters in room header", "Render simple counters in room header": "Render simple counters in room header",
"Multiple integration managers (requires manual setup)": "Multiple integration managers (requires manual setup)",
"Try out new ways to ignore people (experimental)": "Try out new ways to ignore people (experimental)", "Try out new ways to ignore people (experimental)": "Try out new ways to ignore people (experimental)",
"Support adding custom themes": "Support adding custom themes", "Support adding custom themes": "Support adding custom themes",
"Show message previews for reactions in DMs": "Show message previews for reactions in DMs", "Show message previews for reactions in DMs": "Show message previews for reactions in DMs",
@ -3167,13 +3164,8 @@
"Uploading %(filename)s and %(count)s others|other": "Uploading %(filename)s and %(count)s others", "Uploading %(filename)s and %(count)s others|other": "Uploading %(filename)s and %(count)s others",
"Uploading %(filename)s and %(count)s others|zero": "Uploading %(filename)s", "Uploading %(filename)s and %(count)s others|zero": "Uploading %(filename)s",
"Uploading %(filename)s and %(count)s others|one": "Uploading %(filename)s and %(count)s other", "Uploading %(filename)s and %(count)s others|one": "Uploading %(filename)s and %(count)s other",
"Your status will be shown to people you have a DM with.": "Your status will be shown to people you have a DM with.",
"Set status": "Set status",
"Clear status": "Clear status",
"Set a new status": "Set a new status",
"Got an account? <a>Sign in</a>": "Got an account? <a>Sign in</a>", "Got an account? <a>Sign in</a>": "Got an account? <a>Sign in</a>",
"New here? <a>Create an account</a>": "New here? <a>Create an account</a>", "New here? <a>Create an account</a>": "New here? <a>Create an account</a>",
"Do not disturb": "Do not disturb",
"Switch to light mode": "Switch to light mode", "Switch to light mode": "Switch to light mode",
"Switch to dark mode": "Switch to dark mode", "Switch to dark mode": "Switch to dark mode",
"Switch theme": "Switch theme", "Switch theme": "Switch theme",

View file

@ -19,7 +19,6 @@ import { logger } from "matrix-js-sdk/src/logger";
import { ClientEvent, MatrixClient } from "matrix-js-sdk/src/client"; import { ClientEvent, MatrixClient } from "matrix-js-sdk/src/client";
import type { MatrixEvent } from "matrix-js-sdk/src/models/event"; import type { MatrixEvent } from "matrix-js-sdk/src/models/event";
import type { Room } from "matrix-js-sdk/src/models/room";
import SdkConfig from '../SdkConfig'; import SdkConfig from '../SdkConfig';
import Modal from '../Modal'; import Modal from '../Modal';
import { IntegrationManagerInstance, Kind } from "./IntegrationManagerInstance"; import { IntegrationManagerInstance, Kind } from "./IntegrationManagerInstance";
@ -27,13 +26,7 @@ import IntegrationsImpossibleDialog from "../components/views/dialogs/Integratio
import IntegrationsDisabledDialog from "../components/views/dialogs/IntegrationsDisabledDialog"; import IntegrationsDisabledDialog from "../components/views/dialogs/IntegrationsDisabledDialog";
import WidgetUtils from "../utils/WidgetUtils"; import WidgetUtils from "../utils/WidgetUtils";
import { MatrixClientPeg } from "../MatrixClientPeg"; import { MatrixClientPeg } from "../MatrixClientPeg";
import SettingsStore from "../settings/SettingsStore";
import { compare } from "../utils/strings"; import { compare } from "../utils/strings";
import defaultDispatcher from "../dispatcher/dispatcher";
import {
OpenTabbedIntegrationManagerDialogPayload,
} from "../dispatcher/payloads/OpenTabbedIntegrationManagerDialogPayload";
import { Action } from "../dispatcher/actions";
const KIND_PREFERENCE = [ const KIND_PREFERENCE = [
// Ordered: first is most preferred, last is least preferred. // Ordered: first is most preferred, last is least preferred.
@ -181,23 +174,6 @@ export class IntegrationManagers {
Modal.createTrackedDialog('Integrations impossible', '', IntegrationsImpossibleDialog); Modal.createTrackedDialog('Integrations impossible', '', IntegrationsImpossibleDialog);
} }
openAll(room: Room = null, screen: string = null, integrationId: string = null): void {
if (!SettingsStore.getValue("integrationProvisioning")) {
return this.showDisabledDialog();
}
if (this.managers.length === 0) {
return this.openNoManagerDialog();
}
defaultDispatcher.dispatch(<OpenTabbedIntegrationManagerDialogPayload>{
action: Action.OpenTabbedIntegrationManagerDialog,
room,
screen,
integrationId,
});
}
showDisabledDialog(): void { showDisabledDialog(): void {
Modal.createTrackedDialog('Integrations disabled', '', IntegrationsDisabledDialog); Modal.createTrackedDialog('Integrations disabled', '', IntegrationsDisabledDialog);
} }

View file

@ -23,7 +23,6 @@ import {
NotificationBodyEnabledController, NotificationBodyEnabledController,
NotificationsEnabledController, NotificationsEnabledController,
} from "./controllers/NotificationControllers"; } from "./controllers/NotificationControllers";
import CustomStatusController from "./controllers/CustomStatusController";
import ThemeController from './controllers/ThemeController'; import ThemeController from './controllers/ThemeController';
import PushToMatrixClientController from './controllers/PushToMatrixClientController'; import PushToMatrixClientController from './controllers/PushToMatrixClientController';
import ReloadOnChangeController from "./controllers/ReloadOnChangeController"; import ReloadOnChangeController from "./controllers/ReloadOnChangeController";
@ -201,13 +200,6 @@ export const SETTINGS: {[setting: string]: ISetting} = {
supportedLevels: LEVELS_FEATURE, supportedLevels: LEVELS_FEATURE,
default: false, default: false,
}, },
"feature_dnd": {
isFeature: true,
labsGroup: LabGroup.Profile,
displayName: _td("Show options to enable 'Do not disturb' mode"),
supportedLevels: LEVELS_FEATURE,
default: false,
},
"feature_latex_maths": { "feature_latex_maths": {
isFeature: true, isFeature: true,
labsGroup: LabGroup.Messaging, labsGroup: LabGroup.Messaging,
@ -262,14 +254,6 @@ export const SETTINGS: {[setting: string]: ISetting} = {
}, },
}, },
"feature_custom_status": {
isFeature: true,
labsGroup: LabGroup.Profile,
displayName: _td("Custom user status messages"),
supportedLevels: LEVELS_FEATURE,
default: false,
controller: new CustomStatusController(),
},
"feature_video_rooms": { "feature_video_rooms": {
isFeature: true, isFeature: true,
labsGroup: LabGroup.Rooms, labsGroup: LabGroup.Rooms,
@ -286,13 +270,6 @@ export const SETTINGS: {[setting: string]: ISetting} = {
supportedLevels: LEVELS_FEATURE, supportedLevels: LEVELS_FEATURE,
default: false, default: false,
}, },
"feature_many_integration_managers": {
isFeature: true,
labsGroup: LabGroup.Experimental,
displayName: _td("Multiple integration managers (requires manual setup)"),
supportedLevels: LEVELS_FEATURE,
default: false,
},
"feature_mjolnir": { "feature_mjolnir": {
isFeature: true, isFeature: true,
labsGroup: LabGroup.Moderation, labsGroup: LabGroup.Moderation,
@ -344,11 +321,6 @@ export const SETTINGS: {[setting: string]: ISetting} = {
displayName: _td("Show current avatar and name for users in message history"), displayName: _td("Show current avatar and name for users in message history"),
default: false, default: false,
}, },
"doNotDisturb": {
supportedLevels: [SettingLevel.DEVICE],
default: false,
controller: new IncompatibleController("feature_dnd", false, false),
},
"mjolnirRooms": { "mjolnirRooms": {
supportedLevels: [SettingLevel.ACCOUNT], supportedLevels: [SettingLevel.ACCOUNT],
default: [], default: [],

View file

@ -1,29 +0,0 @@
/*
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
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 SettingController from "./SettingController";
import dis from "../../dispatcher/dispatcher";
import { SettingLevel } from "../SettingLevel";
export default class CustomStatusController extends SettingController {
public onChange(level: SettingLevel, roomId: string, newValue: any) {
// Dispatch setting change so that some components that are still visible when the
// Settings page is open (such as RoomTiles) can reflect the change.
dis.dispatch({
action: "feature_custom_status_changed",
});
}
}

View file

@ -32,9 +32,6 @@ export function shouldCauseReorder(event: MatrixEvent): boolean {
// Never ignore membership changes // Never ignore membership changes
if (type === EventType.RoomMember && prevContent.membership !== content.membership) return true; if (type === EventType.RoomMember && prevContent.membership !== content.membership) return true;
// Ignore status changes
// XXX: This should be an enum
if (type === "im.vector.user_status") return false;
// Ignore display name changes // Ignore display name changes
if (type === EventType.RoomMember && prevContent.displayname !== content.displayname) return false; if (type === EventType.RoomMember && prevContent.displayname !== content.displayname) return false;
// Ignore avatar changes // Ignore avatar changes

View file

@ -358,20 +358,12 @@ export class StopGapWidget extends EventEmitter {
const integType = data?.integType; const integType = data?.integType;
const integId = <string>data?.integId; const integId = <string>data?.integId;
// TODO: Open the right integration manager for the widget // noinspection JSIgnoredPromiseFromCall
if (SettingsStore.getValue("feature_many_integration_managers")) { IntegrationManagers.sharedInstance().getPrimaryManager().open(
IntegrationManagers.sharedInstance().openAll( MatrixClientPeg.get().getRoom(RoomViewStore.instance.getRoomId()),
MatrixClientPeg.get().getRoom(RoomViewStore.instance.getRoomId()), `type_${integType}`,
`type_${integType}`, integId,
integId, );
);
} else {
IntegrationManagers.sharedInstance().getPrimaryManager().open(
MatrixClientPeg.get().getRoom(RoomViewStore.instance.getRoomId()),
`type_${integType}`,
integId,
);
}
}, },
); );
} }

View file

@ -23,7 +23,6 @@ import ForwardDialog from "../components/views/dialogs/ForwardDialog";
import { MatrixClientPeg } from "../MatrixClientPeg"; import { MatrixClientPeg } from "../MatrixClientPeg";
import { Action } from "../dispatcher/actions"; import { Action } from "../dispatcher/actions";
import ReportEventDialog from "../components/views/dialogs/ReportEventDialog"; import ReportEventDialog from "../components/views/dialogs/ReportEventDialog";
import TabbedIntegrationManagerDialog from "../components/views/dialogs/TabbedIntegrationManagerDialog";
import SpacePreferencesDialog from "../components/views/dialogs/SpacePreferencesDialog"; import SpacePreferencesDialog from "../components/views/dialogs/SpacePreferencesDialog";
import SpaceSettingsDialog from "../components/views/dialogs/SpaceSettingsDialog"; import SpaceSettingsDialog from "../components/views/dialogs/SpaceSettingsDialog";
import InviteDialog from "../components/views/dialogs/InviteDialog"; import InviteDialog from "../components/views/dialogs/InviteDialog";
@ -73,17 +72,6 @@ export class DialogOpener {
mxEvent: payload.event, mxEvent: payload.event,
}, 'mx_Dialog_reportEvent'); }, 'mx_Dialog_reportEvent');
break; break;
case Action.OpenTabbedIntegrationManagerDialog:
Modal.createTrackedDialog(
'Tabbed Integration Manager', '', TabbedIntegrationManagerDialog,
{
room: payload.room,
screen: payload.screen,
integrationId: payload.integrationId,
},
'mx_TabbedIntegrationManagerDialog',
);
break;
case Action.OpenSpacePreferences: case Action.OpenSpacePreferences:
Modal.createTrackedDialog("Space preferences", "", SpacePreferencesDialog, { Modal.createTrackedDialog("Space preferences", "", SpacePreferencesDialog, {
initialTabId: payload.initalTabId, initialTabId: payload.initalTabId,

View file

@ -560,12 +560,8 @@ export default class WidgetUtils {
} }
static editWidget(room: Room, app: IApp): void { static editWidget(room: Room, app: IApp): void {
// TODO: Open the right manager for the widget // noinspection JSIgnoredPromiseFromCall
if (SettingsStore.getValue("feature_many_integration_managers")) { IntegrationManagers.sharedInstance().getPrimaryManager().open(room, 'type_' + app.type, app.id);
IntegrationManagers.sharedInstance().openAll(room, 'type_' + app.type, app.id);
} else {
IntegrationManagers.sharedInstance().getPrimaryManager().open(room, 'type_' + app.type, app.id);
}
} }
static isManagedByManager(app) { static isManagedByManager(app) {