diff --git a/src/components/views/right_panel/GroupHeaderButtons.tsx b/src/components/views/right_panel/GroupHeaderButtons.tsx index dd4a82e645..f006975b08 100644 --- a/src/components/views/right_panel/GroupHeaderButtons.tsx +++ b/src/components/views/right_panel/GroupHeaderButtons.tsx @@ -26,6 +26,7 @@ import {RightPanelPhases} from "../../../stores/RightPanelStorePhases"; import {Action} from "../../../dispatcher/actions"; import {ActionPayload} from "../../../dispatcher/payloads"; import {ViewUserPayload} from "../../../dispatcher/payloads/ViewUserPayload"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; const GROUP_PHASES = [ RightPanelPhases.GroupMemberInfo, @@ -38,6 +39,7 @@ const ROOM_PHASES = [ interface IProps {} +@replaceableComponent("views.right_panel.GroupHeaderButtons") export default class GroupHeaderButtons extends HeaderButtons { constructor(props: IProps) { super(props, HeaderKind.Group); diff --git a/src/components/views/right_panel/HeaderButton.tsx b/src/components/views/right_panel/HeaderButton.tsx index 7f682e2d89..2bc360e380 100644 --- a/src/components/views/right_panel/HeaderButton.tsx +++ b/src/components/views/right_panel/HeaderButton.tsx @@ -22,6 +22,7 @@ import React from 'react'; import classNames from 'classnames'; import Analytics from '../../../Analytics'; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; interface IProps { // Whether this button is highlighted @@ -41,6 +42,7 @@ interface IProps { // TODO: replace this, the composer buttons and the right panel buttons with a unified // representation +@replaceableComponent("views.right_panel.HeaderButton") export default class HeaderButton extends React.Component { constructor(props: IProps) { super(props); diff --git a/src/components/views/right_panel/HeaderButtons.tsx b/src/components/views/right_panel/HeaderButtons.tsx index 543c7c067f..2144292679 100644 --- a/src/components/views/right_panel/HeaderButtons.tsx +++ b/src/components/views/right_panel/HeaderButtons.tsx @@ -28,6 +28,7 @@ import { SetRightPanelPhaseRefireParams, } from '../../../dispatcher/payloads/SetRightPanelPhasePayload'; import {EventSubscription} from "fbemitter"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; export enum HeaderKind { Room = "room", @@ -41,6 +42,7 @@ interface IState { interface IProps {} +@replaceableComponent("views.right_panel.HeaderButtons") export default abstract class HeaderButtons extends React.Component { private storeToken: EventSubscription; private dispatcherRef: string; diff --git a/src/components/views/right_panel/RoomHeaderButtons.tsx b/src/components/views/right_panel/RoomHeaderButtons.tsx index c2364546fd..0571622e64 100644 --- a/src/components/views/right_panel/RoomHeaderButtons.tsx +++ b/src/components/views/right_panel/RoomHeaderButtons.tsx @@ -26,6 +26,7 @@ import {RightPanelPhases} from "../../../stores/RightPanelStorePhases"; import {Action} from "../../../dispatcher/actions"; import {ActionPayload} from "../../../dispatcher/payloads"; import RightPanelStore from "../../../stores/RightPanelStore"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; const ROOM_INFO_PHASES = [ RightPanelPhases.RoomSummary, @@ -37,6 +38,7 @@ const ROOM_INFO_PHASES = [ RightPanelPhases.Room3pidMemberInfo, ]; +@replaceableComponent("views.right_panel.RoomHeaderButtons") export default class RoomHeaderButtons extends HeaderButtons { constructor(props) { super(props, HeaderKind.Room); diff --git a/src/components/views/right_panel/VerificationPanel.tsx b/src/components/views/right_panel/VerificationPanel.tsx index f584a63209..ac01c953b9 100644 --- a/src/components/views/right_panel/VerificationPanel.tsx +++ b/src/components/views/right_panel/VerificationPanel.tsx @@ -36,6 +36,7 @@ import { PHASE_CANCELLED, } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest"; import Spinner from "../elements/Spinner"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; // XXX: Should be defined in matrix-js-sdk enum VerificationPhase { @@ -65,6 +66,7 @@ interface IState { reciprocateQREvent?: ReciprocateQRCode; } +@replaceableComponent("views.right_panel.VerificationPanel") export default class VerificationPanel extends React.PureComponent { private hasVerifier: boolean; diff --git a/src/components/views/room_settings/AliasSettings.js b/src/components/views/room_settings/AliasSettings.js index eb9276b729..ee8232ebd7 100644 --- a/src/components/views/room_settings/AliasSettings.js +++ b/src/components/views/room_settings/AliasSettings.js @@ -26,6 +26,7 @@ import ErrorDialog from "../dialogs/ErrorDialog"; import AccessibleButton from "../elements/AccessibleButton"; import Modal from "../../../Modal"; import RoomPublishSetting from "./RoomPublishSetting"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; class EditableAliasesList extends EditableItemList { constructor(props) { @@ -74,6 +75,7 @@ class EditableAliasesList extends EditableItemList { } } +@replaceableComponent("views.room_settings.AliasSettings") export default class AliasSettings extends React.Component { static propTypes = { roomId: PropTypes.string.isRequired, diff --git a/src/components/views/room_settings/RelatedGroupSettings.js b/src/components/views/room_settings/RelatedGroupSettings.js index af3f58f9db..f82e238722 100644 --- a/src/components/views/room_settings/RelatedGroupSettings.js +++ b/src/components/views/room_settings/RelatedGroupSettings.js @@ -22,9 +22,11 @@ import { _t } from '../../../languageHandler'; import Modal from '../../../Modal'; import ErrorDialog from "../dialogs/ErrorDialog"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; const GROUP_ID_REGEX = /\+\S+:\S+/; +@replaceableComponent("views.room_settings.RelatedGroupSettings") export default class RelatedGroupSettings extends React.Component { static propTypes = { roomId: PropTypes.string.isRequired, diff --git a/src/components/views/room_settings/RoomProfileSettings.js b/src/components/views/room_settings/RoomProfileSettings.js index 65acc802dc..563368384b 100644 --- a/src/components/views/room_settings/RoomProfileSettings.js +++ b/src/components/views/room_settings/RoomProfileSettings.js @@ -20,8 +20,10 @@ import {_t} from "../../../languageHandler"; import {MatrixClientPeg} from "../../../MatrixClientPeg"; import Field from "../elements/Field"; import * as sdk from "../../../index"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; // TODO: Merge with ProfileSettings? +@replaceableComponent("views.room_settings.RoomProfileSettings") export default class RoomProfileSettings extends React.Component { static propTypes = { roomId: PropTypes.string.isRequired, diff --git a/src/components/views/room_settings/UrlPreviewSettings.js b/src/components/views/room_settings/UrlPreviewSettings.js index 114e9b2894..7b04e296e5 100644 --- a/src/components/views/room_settings/UrlPreviewSettings.js +++ b/src/components/views/room_settings/UrlPreviewSettings.js @@ -26,8 +26,9 @@ import dis from "../../../dispatcher/dispatcher"; import {MatrixClientPeg} from "../../../MatrixClientPeg"; import {Action} from "../../../dispatcher/actions"; import {SettingLevel} from "../../../settings/SettingLevel"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; - +@replaceableComponent("views.room_settings.UrlPreviewSettings") export default class UrlPreviewSettings extends React.Component { static propTypes = { room: PropTypes.object, diff --git a/src/components/views/rooms/AppsDrawer.js b/src/components/views/rooms/AppsDrawer.js index aa7120bbe6..3ef8d71682 100644 --- a/src/components/views/rooms/AppsDrawer.js +++ b/src/components/views/rooms/AppsDrawer.js @@ -35,7 +35,9 @@ import PercentageDistributor from "../../../resizer/distributors/percentage"; import {Container, WidgetLayoutStore} from "../../../stores/widgets/WidgetLayoutStore"; import {clamp, percentageOf, percentageWithin} from "../../../utils/numbers"; import {useStateCallback} from "../../../hooks/useStateCallback"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +@replaceableComponent("views.rooms.AppsDrawer") export default class AppsDrawer extends React.Component { static propTypes = { userId: PropTypes.string.isRequired, diff --git a/src/components/views/rooms/Autocomplete.tsx b/src/components/views/rooms/Autocomplete.tsx index 15af75084a..a4dcba11a3 100644 --- a/src/components/views/rooms/Autocomplete.tsx +++ b/src/components/views/rooms/Autocomplete.tsx @@ -23,6 +23,7 @@ import {Room} from 'matrix-js-sdk/src/models/room'; import SettingsStore from "../../../settings/SettingsStore"; import Autocompleter from '../../../autocomplete/Autocompleter'; +import {replaceableComponent} from "../../../utils/replaceableComponent"; const COMPOSER_SELECTED = 0; @@ -49,6 +50,7 @@ interface IState { forceComplete: boolean; } +@replaceableComponent("views.rooms.Autocomplete") export default class Autocomplete extends React.PureComponent { autocompleter: Autocompleter; queryRequested: string; diff --git a/src/components/views/rooms/AuxPanel.tsx b/src/components/views/rooms/AuxPanel.tsx index d193b98ec1..3d431f7c67 100644 --- a/src/components/views/rooms/AuxPanel.tsx +++ b/src/components/views/rooms/AuxPanel.tsx @@ -27,6 +27,7 @@ import {UIFeature} from "../../../settings/UIFeature"; import { ResizeNotifier } from "../../../utils/ResizeNotifier"; import CallViewForRoom from '../voip/CallViewForRoom'; import {objectHasDiff} from "../../../utils/objects"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; interface IProps { // js-sdk room object @@ -58,6 +59,7 @@ interface IState { counters: Counter[], } +@replaceableComponent("views.rooms.AuxPanel") export default class AuxPanel extends React.Component { static defaultProps = { showApps: true, diff --git a/src/components/views/rooms/BasicMessageComposer.tsx b/src/components/views/rooms/BasicMessageComposer.tsx index 017ce77166..829809ad49 100644 --- a/src/components/views/rooms/BasicMessageComposer.tsx +++ b/src/components/views/rooms/BasicMessageComposer.tsx @@ -46,6 +46,7 @@ import {IDiff} from "../../../editor/diff"; import AutocompleteWrapperModel from "../../../editor/autocomplete"; import DocumentPosition from "../../../editor/position"; import {ICompletion} from "../../../autocomplete/Autocompleter"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; // matches emoticons which follow the start of a line or whitespace const REGEX_EMOTICON_WHITESPACE = new RegExp('(?:^|\\s)(' + EMOTICON_REGEX.source + ')\\s$'); @@ -105,6 +106,7 @@ interface IState { completionIndex?: number; } +@replaceableComponent("views.rooms.BasixMessageEditor") export default class BasicMessageEditor extends React.Component { private editorRef = createRef(); private autocompleteRef = createRef(); diff --git a/src/components/views/rooms/EditMessageComposer.js b/src/components/views/rooms/EditMessageComposer.js index c59b3555b9..6ecb2bd549 100644 --- a/src/components/views/rooms/EditMessageComposer.js +++ b/src/components/views/rooms/EditMessageComposer.js @@ -34,6 +34,7 @@ import MatrixClientContext from "../../../contexts/MatrixClientContext"; import {Action} from "../../../dispatcher/actions"; import SettingsStore from "../../../settings/SettingsStore"; import CountlyAnalytics from "../../../CountlyAnalytics"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; function _isReply(mxEvent) { const relatesTo = mxEvent.getContent()["m.relates_to"]; @@ -102,6 +103,7 @@ function createEditContent(model, editedEvent) { }, contentBody); } +@replaceableComponent("views.rooms.EditMessageComposer") export default class EditMessageComposer extends React.Component { static propTypes = { // the message event being edited diff --git a/src/components/views/rooms/EntityTile.js b/src/components/views/rooms/EntityTile.js index 9017e4aa3e..75b03739b9 100644 --- a/src/components/views/rooms/EntityTile.js +++ b/src/components/views/rooms/EntityTile.js @@ -23,6 +23,7 @@ import AccessibleButton from '../elements/AccessibleButton'; import { _t } from '../../../languageHandler'; import classNames from "classnames"; import E2EIcon from './E2EIcon'; +import {replaceableComponent} from "../../../utils/replaceableComponent"; const PRESENCE_CLASS = { "offline": "mx_EntityTile_offline", @@ -50,6 +51,7 @@ function presenceClassForMember(presenceState, lastActiveAgo, showPresence) { } } +@replaceableComponent("views.rooms.EntityTile") class EntityTile extends React.Component { static propTypes = { name: PropTypes.string, diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index a705e92d9c..1366d9b603 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -39,6 +39,7 @@ import {WidgetType} from "../../../widgets/WidgetType"; import RoomAvatar from "../avatars/RoomAvatar"; import {WIDGET_LAYOUT_EVENT_TYPE} from "../../../stores/widgets/WidgetLayoutStore"; import {objectHasDiff} from "../../../utils/objects"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; const eventTileTypes = { 'm.room.message': 'messages.MessageEvent', @@ -146,6 +147,7 @@ const MAX_READ_AVATARS = 5; // | '--------------------------------------' | // '----------------------------------------------------------' +@replaceableComponent("views.rooms.EventTile") export default class EventTile extends React.Component { static propTypes = { /* the MatrixEvent to show */ diff --git a/src/components/views/rooms/ForwardMessage.js b/src/components/views/rooms/ForwardMessage.js index b85dd2c8df..222895ef04 100644 --- a/src/components/views/rooms/ForwardMessage.js +++ b/src/components/views/rooms/ForwardMessage.js @@ -19,8 +19,9 @@ import React from 'react'; import PropTypes from 'prop-types'; import { _t } from '../../../languageHandler'; import {Key} from '../../../Keyboard'; +import {replaceableComponent} from "../../../utils/replaceableComponent"; - +@replaceableComponent("views.rooms.FowardMessage") export default class ForwardMessage extends React.Component { static propTypes = { onCancelClick: PropTypes.func.isRequired, diff --git a/src/components/views/rooms/LinkPreviewWidget.js b/src/components/views/rooms/LinkPreviewWidget.js index 2a053bf467..39c9f0bcf7 100644 --- a/src/components/views/rooms/LinkPreviewWidget.js +++ b/src/components/views/rooms/LinkPreviewWidget.js @@ -25,7 +25,9 @@ import * as sdk from "../../../index"; import Modal from "../../../Modal"; import * as ImageUtils from "../../../ImageUtils"; import { _t } from "../../../languageHandler"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +@replaceableComponent("views.rooms.LinkPreviewWidget") export default class LinkPreviewWidget extends React.Component { static propTypes = { link: PropTypes.string.isRequired, // the URL being previewed diff --git a/src/components/views/rooms/MemberList.js b/src/components/views/rooms/MemberList.js index d4d618c821..593132a283 100644 --- a/src/components/views/rooms/MemberList.js +++ b/src/components/views/rooms/MemberList.js @@ -29,6 +29,7 @@ import BaseCard from "../right_panel/BaseCard"; import {RightPanelPhases} from "../../../stores/RightPanelStorePhases"; import RoomAvatar from "../avatars/RoomAvatar"; import RoomName from "../elements/RoomName"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; const INITIAL_LOAD_NUM_MEMBERS = 30; const INITIAL_LOAD_NUM_INVITED = 5; @@ -38,6 +39,7 @@ const SHOW_MORE_INCREMENT = 100; // matches all ASCII punctuation: !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ const SORT_REGEX = /[\x21-\x2F\x3A-\x40\x5B-\x60\x7B-\x7E]+/g; +@replaceableComponent("views.rooms.MemberList") export default class MemberList extends React.Component { constructor(props) { super(props); diff --git a/src/components/views/rooms/MemberTile.js b/src/components/views/rooms/MemberTile.js index a43b42b6d3..f8df7ed78f 100644 --- a/src/components/views/rooms/MemberTile.js +++ b/src/components/views/rooms/MemberTile.js @@ -23,7 +23,9 @@ import dis from "../../../dispatcher/dispatcher"; import { _t } from '../../../languageHandler'; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import {Action} from "../../../dispatcher/actions"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +@replaceableComponent("views.rooms.MemberTile") export default class MemberTile extends React.Component { static propTypes = { member: PropTypes.any.isRequired, // RoomMember diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index c03178cdf7..ccf097c4fd 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -32,6 +32,7 @@ import {UIFeature} from "../../../settings/UIFeature"; import WidgetStore from "../../../stores/WidgetStore"; import {UPDATE_EVENT} from "../../../stores/AsyncStore"; import ActiveWidgetStore from "../../../stores/ActiveWidgetStore"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; function ComposerAvatar(props) { const MemberStatusMessageAvatar = sdk.getComponent('avatars.MemberStatusMessageAvatar'); @@ -168,6 +169,7 @@ class UploadButton extends React.Component { } } +@replaceableComponent("views.rooms.MessageComposer") export default class MessageComposer extends React.Component { constructor(props) { super(props); diff --git a/src/components/views/rooms/MessageComposerFormatBar.js b/src/components/views/rooms/MessageComposerFormatBar.js index 71aef1e833..d2539b1ef4 100644 --- a/src/components/views/rooms/MessageComposerFormatBar.js +++ b/src/components/views/rooms/MessageComposerFormatBar.js @@ -19,7 +19,9 @@ import PropTypes from 'prop-types'; import { _t } from '../../../languageHandler'; import classNames from 'classnames'; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +@replaceableComponent("views.rooms.MessageComposerFormatBar") export default class MessageComposerFormatBar extends React.PureComponent { static propTypes = { onAction: PropTypes.func.isRequired, diff --git a/src/components/views/rooms/NotificationBadge.tsx b/src/components/views/rooms/NotificationBadge.tsx index 8b996d3238..36a52e260d 100644 --- a/src/components/views/rooms/NotificationBadge.tsx +++ b/src/components/views/rooms/NotificationBadge.tsx @@ -21,6 +21,7 @@ import SettingsStore from "../../../settings/SettingsStore"; import AccessibleButton from "../elements/AccessibleButton"; import { XOR } from "../../../@types/common"; import { NOTIFICATION_STATE_UPDATE, NotificationState } from "../../../stores/notifications/NotificationState"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; interface IProps { notification: NotificationState; @@ -48,6 +49,7 @@ interface IState { showCounts: boolean; // whether or not to show counts. Independent of props.forceCount } +@replaceableComponent("views.rooms.NotificationBadge") export default class NotificationBadge extends React.PureComponent, IState> { private countWatcherRef: string; diff --git a/src/components/views/rooms/PinnedEventTile.js b/src/components/views/rooms/PinnedEventTile.js index 9fad0c2391..2259cad7fb 100644 --- a/src/components/views/rooms/PinnedEventTile.js +++ b/src/components/views/rooms/PinnedEventTile.js @@ -23,7 +23,9 @@ import MessageEvent from "../messages/MessageEvent"; import MemberAvatar from "../avatars/MemberAvatar"; import { _t } from '../../../languageHandler'; import {formatFullDate} from '../../../DateUtils'; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +@replaceableComponent("views.rooms.PinnedEventTile") export default class PinnedEventTile extends React.Component { static propTypes = { mxRoom: PropTypes.object.isRequired, diff --git a/src/components/views/rooms/PinnedEventsPanel.js b/src/components/views/rooms/PinnedEventsPanel.js index 3ea0299976..285829bf63 100644 --- a/src/components/views/rooms/PinnedEventsPanel.js +++ b/src/components/views/rooms/PinnedEventsPanel.js @@ -22,7 +22,9 @@ import AccessibleButton from "../elements/AccessibleButton"; import PinnedEventTile from "./PinnedEventTile"; import { _t } from '../../../languageHandler'; import PinningUtils from "../../../utils/PinningUtils"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +@replaceableComponent("views.rooms.PinnedEventsPanel") export default class PinnedEventsPanel extends React.Component { static propTypes = { // The Room from the js-sdk we're going to show pinned events for diff --git a/src/components/views/rooms/PresenceLabel.js b/src/components/views/rooms/PresenceLabel.js index ff1460ca21..ca21afe63d 100644 --- a/src/components/views/rooms/PresenceLabel.js +++ b/src/components/views/rooms/PresenceLabel.js @@ -18,8 +18,9 @@ import React from 'react'; import PropTypes from 'prop-types'; import { _t } from '../../../languageHandler'; +import {replaceableComponent} from "../../../utils/replaceableComponent"; - +@replaceableComponent("views.rooms.PresenceLabel") export default class PresenceLabel extends React.Component { static propTypes = { // number of milliseconds ago this user was last active. diff --git a/src/components/views/rooms/ReadReceiptMarker.js b/src/components/views/rooms/ReadReceiptMarker.js index ba2b3064fd..ade84cbef3 100644 --- a/src/components/views/rooms/ReadReceiptMarker.js +++ b/src/components/views/rooms/ReadReceiptMarker.js @@ -23,6 +23,7 @@ import {formatDate} from '../../../DateUtils'; import Velociraptor from "../../../Velociraptor"; import * as sdk from "../../../index"; import {toPx} from "../../../utils/units"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; let bounce = false; try { @@ -32,6 +33,7 @@ try { } catch (e) { } +@replaceableComponent("views.rooms.ReadReceiptMarker") export default class ReadReceiptMarker extends React.PureComponent { static propTypes = { // the RoomMember to show the RR for diff --git a/src/components/views/rooms/ReplyPreview.js b/src/components/views/rooms/ReplyPreview.js index c7872d95ed..0d99be4f53 100644 --- a/src/components/views/rooms/ReplyPreview.js +++ b/src/components/views/rooms/ReplyPreview.js @@ -23,6 +23,7 @@ import SettingsStore from "../../../settings/SettingsStore"; import PropTypes from "prop-types"; import {RoomPermalinkCreator} from "../../../utils/permalinks/Permalinks"; import {UIFeature} from "../../../settings/UIFeature"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; function cancelQuoting() { dis.dispatch({ @@ -31,6 +32,7 @@ function cancelQuoting() { }); } +@replaceableComponent("views.rooms.ReplyPreview") export default class ReplyPreview extends React.Component { static propTypes = { permalinkCreator: PropTypes.instanceOf(RoomPermalinkCreator).isRequired, diff --git a/src/components/views/rooms/RoomBreadcrumbs.tsx b/src/components/views/rooms/RoomBreadcrumbs.tsx index ff60ab7779..ea0ff233da 100644 --- a/src/components/views/rooms/RoomBreadcrumbs.tsx +++ b/src/components/views/rooms/RoomBreadcrumbs.tsx @@ -27,6 +27,7 @@ import RoomListStore from "../../../stores/room-list/RoomListStore"; import { DefaultTagID } from "../../../stores/room-list/models"; import { RovingAccessibleTooltipButton } from "../../../accessibility/RovingTabIndex"; import Toolbar from "../../../accessibility/Toolbar"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; interface IProps { } @@ -42,6 +43,7 @@ interface IState { skipFirst: boolean; } +@replaceableComponent("views.rooms.RoomBreadcrumbs") export default class RoomBreadcrumbs extends React.PureComponent { private isMounted = true; diff --git a/src/components/views/rooms/RoomDetailList.js b/src/components/views/rooms/RoomDetailList.js index d8205aeb21..be22cda199 100644 --- a/src/components/views/rooms/RoomDetailList.js +++ b/src/components/views/rooms/RoomDetailList.js @@ -22,7 +22,9 @@ import PropTypes from 'prop-types'; import classNames from 'classnames'; import {roomShape} from './RoomDetailRow'; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +@replaceableComponent("views.rooms.RoomDetailList") export default class RoomDetailList extends React.Component { static propTypes = { rooms: PropTypes.arrayOf(roomShape), diff --git a/src/components/views/rooms/RoomDetailRow.js b/src/components/views/rooms/RoomDetailRow.js index 667f821922..e7c259cd98 100644 --- a/src/components/views/rooms/RoomDetailRow.js +++ b/src/components/views/rooms/RoomDetailRow.js @@ -21,6 +21,7 @@ import { linkifyElement } from '../../../HtmlUtils'; import {MatrixClientPeg} from '../../../MatrixClientPeg'; import PropTypes from 'prop-types'; import {getHttpUriForMxc} from "matrix-js-sdk/src/content-repo"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; export function getDisplayAliasForRoom(room) { return room.canonicalAlias || (room.aliases ? room.aliases[0] : ""); @@ -39,6 +40,7 @@ export const roomShape = PropTypes.shape({ guestCanJoin: PropTypes.bool, }); +@replaceableComponent("views.rooms.RoomDetailRow") export default class RoomDetailRow extends React.Component { static propTypes = { room: roomShape, diff --git a/src/components/views/rooms/RoomHeader.js b/src/components/views/rooms/RoomHeader.js index 6736600bc8..f856f7f6ef 100644 --- a/src/components/views/rooms/RoomHeader.js +++ b/src/components/views/rooms/RoomHeader.js @@ -32,7 +32,9 @@ import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; import RoomTopic from "../elements/RoomTopic"; import RoomName from "../elements/RoomName"; import {PlaceCallType} from "../../../CallHandler"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +@replaceableComponent("views.rooms.RoomHeader") export default class RoomHeader extends React.Component { static propTypes = { room: PropTypes.object, diff --git a/src/components/views/rooms/RoomList.tsx b/src/components/views/rooms/RoomList.tsx index f7da6571da..ff6e3793bf 100644 --- a/src/components/views/rooms/RoomList.tsx +++ b/src/components/views/rooms/RoomList.tsx @@ -50,6 +50,7 @@ import CallHandler from "../../../CallHandler"; import SpaceStore from "../../../stores/SpaceStore"; import { showAddExistingRooms, showCreateNewRoom } from "../../../utils/space"; import { EventType } from "matrix-js-sdk/src/@types/event"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; interface IProps { onKeyDown: (ev: React.KeyboardEvent) => void; @@ -256,6 +257,7 @@ function customTagAesthetics(tagId: TagID): ITagAesthetics { }; } +@replaceableComponent("views.rooms.RoomList") export default class RoomList extends React.PureComponent { private dispatcherRef; private customTagStoreRef; diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index dc68068157..36038da61c 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -27,6 +27,7 @@ import SdkConfig from "../../../SdkConfig"; import IdentityAuthClient from '../../../IdentityAuthClient'; import {CommunityPrototypeStore} from "../../../stores/CommunityPrototypeStore"; import {UPDATE_EVENT} from "../../../stores/AsyncStore"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; const MessageCase = Object.freeze({ NotLoggedIn: "NotLoggedIn", @@ -45,6 +46,7 @@ const MessageCase = Object.freeze({ OtherError: "OtherError", }); +@replaceableComponent("views.rooms.RoomPreviewBar") export default class RoomPreviewBar extends React.Component { static propTypes = { onJoinClick: PropTypes.func, diff --git a/src/components/views/rooms/RoomSublist.tsx b/src/components/views/rooms/RoomSublist.tsx index a2574bf60c..cb98ba85e4 100644 --- a/src/components/views/rooms/RoomSublist.tsx +++ b/src/components/views/rooms/RoomSublist.tsx @@ -51,6 +51,7 @@ import { objectExcluding, objectHasDiff } from "../../../utils/objects"; import TemporaryTile from "./TemporaryTile"; import { ListNotificationState } from "../../../stores/notifications/ListNotificationState"; import IconizedContextMenu from "../context_menus/IconizedContextMenu"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; const SHOW_N_BUTTON_HEIGHT = 28; // As defined by CSS const RESIZE_HANDLE_HEIGHT = 4; // As defined by CSS @@ -98,6 +99,7 @@ interface IState { filteredExtraTiles?: TemporaryTile[]; } +@replaceableComponent("views.rooms.RoomSublist") export default class RoomSublist extends React.Component { private headerButton = createRef(); private sublistRef = createRef(); diff --git a/src/components/views/rooms/RoomTile.tsx b/src/components/views/rooms/RoomTile.tsx index 835447dc18..07de70fe45 100644 --- a/src/components/views/rooms/RoomTile.tsx +++ b/src/components/views/rooms/RoomTile.tsx @@ -51,6 +51,7 @@ import IconizedContextMenu, { IconizedContextMenuRadio, } from "../context_menus/IconizedContextMenu"; import { CommunityPrototypeStore, IRoomProfile } from "../../../stores/CommunityPrototypeStore"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; interface IProps { room: Room; @@ -78,6 +79,7 @@ const contextMenuBelow = (elementRect: PartialDOMRect) => { return {left, top, chevronFace}; }; +@replaceableComponent("views.rooms.RoomTile") export default class RoomTile extends React.PureComponent { private dispatcherRef: string; private roomTileRef = createRef(); diff --git a/src/components/views/rooms/RoomUpgradeWarningBar.js b/src/components/views/rooms/RoomUpgradeWarningBar.js index 877cfb39d7..a2d4f92d35 100644 --- a/src/components/views/rooms/RoomUpgradeWarningBar.js +++ b/src/components/views/rooms/RoomUpgradeWarningBar.js @@ -21,7 +21,9 @@ import Modal from '../../../Modal'; import { _t } from '../../../languageHandler'; import {MatrixClientPeg} from "../../../MatrixClientPeg"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +@replaceableComponent("views.rooms.RoomUpgradeWarningBar") export default class RoomUpgradeWarningBar extends React.Component { static propTypes = { room: PropTypes.object.isRequired, diff --git a/src/components/views/rooms/SearchBar.js b/src/components/views/rooms/SearchBar.js index ac637673e4..029516c932 100644 --- a/src/components/views/rooms/SearchBar.js +++ b/src/components/views/rooms/SearchBar.js @@ -21,7 +21,9 @@ import classNames from "classnames"; import { _t } from '../../../languageHandler'; import {Key} from "../../../Keyboard"; import DesktopBuildsNotice, {WarningKind} from "../elements/DesktopBuildsNotice"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +@replaceableComponent("views.rooms.SearchBar") export default class SearchBar extends React.Component { constructor(props) { super(props); diff --git a/src/components/views/rooms/SearchResultTile.js b/src/components/views/rooms/SearchResultTile.js index 29def9e368..dcfd633e76 100644 --- a/src/components/views/rooms/SearchResultTile.js +++ b/src/components/views/rooms/SearchResultTile.js @@ -21,7 +21,9 @@ import * as sdk from '../../../index'; import {haveTileForEvent} from "./EventTile"; import SettingsStore from "../../../settings/SettingsStore"; import {UIFeature} from "../../../settings/UIFeature"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +@replaceableComponent("views.rooms.SearchResultTile") export default class SearchResultTile extends React.Component { static propTypes = { // a matrix-js-sdk SearchResult containing the details of this result diff --git a/src/components/views/rooms/SendMessageComposer.js b/src/components/views/rooms/SendMessageComposer.js index 673df949f7..ba3076c07d 100644 --- a/src/components/views/rooms/SendMessageComposer.js +++ b/src/components/views/rooms/SendMessageComposer.js @@ -48,6 +48,7 @@ import SettingsStore from "../../../settings/SettingsStore"; import CountlyAnalytics from "../../../CountlyAnalytics"; import {MatrixClientPeg} from "../../../MatrixClientPeg"; import EMOJI_REGEX from 'emojibase-regex'; +import {replaceableComponent} from "../../../utils/replaceableComponent"; function addReplyToMessageContent(content, repliedToEvent, permalinkCreator) { const replyContent = ReplyThread.makeReplyMixIn(repliedToEvent); @@ -111,6 +112,7 @@ export function isQuickReaction(model) { return false; } +@replaceableComponent("views.rooms.SendMessageComposer") export default class SendMessageComposer extends React.Component { static propTypes = { room: PropTypes.object.isRequired, diff --git a/src/components/views/rooms/SimpleRoomHeader.js b/src/components/views/rooms/SimpleRoomHeader.js index 1c78253eff..b2a66f6670 100644 --- a/src/components/views/rooms/SimpleRoomHeader.js +++ b/src/components/views/rooms/SimpleRoomHeader.js @@ -19,6 +19,7 @@ import PropTypes from 'prop-types'; import AccessibleButton from '../elements/AccessibleButton'; import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; +import {replaceableComponent} from "../../../utils/replaceableComponent"; // cancel button which is shared between room header and simple room header export function CancelButton(props) { @@ -36,6 +37,7 @@ export function CancelButton(props) { * A stripped-down room header used for things like the user settings * and room directory. */ +@replaceableComponent("views.rooms.SimpleRoomHeader") export default class SimpleRoomHeader extends React.Component { static propTypes = { title: PropTypes.string, diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 5446d15671..44d31d7146 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -30,6 +30,7 @@ import {WidgetType} from "../../../widgets/WidgetType"; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; import {Action} from "../../../dispatcher/actions"; import {WidgetMessagingStore} from "../../../stores/widgets/WidgetMessagingStore"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; // This should be below the dialog level (4000), but above the rest of the UI (1000-2000). // We sit in a context menu, so this should be given to the context menu. @@ -38,6 +39,7 @@ const STICKERPICKER_Z_INDEX = 3500; // Key to store the widget's AppTile under in PersistedElement const PERSISTED_ELEMENT_KEY = "stickerPicker"; +@replaceableComponent("views.rooms.Stickerpicker") export default class Stickerpicker extends React.Component { static currentWidget; diff --git a/src/components/views/rooms/TemporaryTile.tsx b/src/components/views/rooms/TemporaryTile.tsx index eec3105880..a9765faa5d 100644 --- a/src/components/views/rooms/TemporaryTile.tsx +++ b/src/components/views/rooms/TemporaryTile.tsx @@ -22,6 +22,7 @@ import { } from "../../../accessibility/RovingTabIndex"; import NotificationBadge from "./NotificationBadge"; import { NotificationState } from "../../../stores/notifications/NotificationState"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; interface IProps { isMinimized: boolean; @@ -37,6 +38,7 @@ interface IState { } // TODO: Remove with community invites in the room list: https://github.com/vector-im/element-web/issues/14456 +@replaceableComponent("views.rooms.TemporaryTile") export default class TemporaryTile extends React.Component { constructor(props: IProps) { super(props); diff --git a/src/components/views/rooms/ThirdPartyMemberInfo.js b/src/components/views/rooms/ThirdPartyMemberInfo.js index 73510c2b4f..5e2d82a1b2 100644 --- a/src/components/views/rooms/ThirdPartyMemberInfo.js +++ b/src/components/views/rooms/ThirdPartyMemberInfo.js @@ -25,7 +25,9 @@ import Modal from "../../../Modal"; import {isValid3pidInvite} from "../../../RoomInvite"; import RoomAvatar from "../avatars/RoomAvatar"; import RoomName from "../elements/RoomName"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +@replaceableComponent("views.rooms.ThirdPartyMemberInfo") export default class ThirdPartyMemberInfo extends React.Component { static propTypes = { event: PropTypes.instanceOf(MatrixEvent).isRequired, diff --git a/src/components/views/rooms/TopUnreadMessagesBar.js b/src/components/views/rooms/TopUnreadMessagesBar.js index 9ac3c49ef4..cba99ac913 100644 --- a/src/components/views/rooms/TopUnreadMessagesBar.js +++ b/src/components/views/rooms/TopUnreadMessagesBar.js @@ -20,7 +20,9 @@ import React from 'react'; import PropTypes from 'prop-types'; import { _t } from '../../../languageHandler'; import AccessibleButton from '../elements/AccessibleButton'; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +@replaceableComponent("views.rooms.TopUnreadMessagesBar") export default class TopUnreadMessagesBar extends React.Component { static propTypes = { onScrollUpClick: PropTypes.func, diff --git a/src/components/views/rooms/WhoIsTypingTile.js b/src/components/views/rooms/WhoIsTypingTile.js index 905cbe6d09..a25b43fc3a 100644 --- a/src/components/views/rooms/WhoIsTypingTile.js +++ b/src/components/views/rooms/WhoIsTypingTile.js @@ -21,7 +21,9 @@ import * as WhoIsTyping from '../../../WhoIsTyping'; import Timer from '../../../utils/Timer'; import {MatrixClientPeg} from '../../../MatrixClientPeg'; import MemberAvatar from '../avatars/MemberAvatar'; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +@replaceableComponent("views.rooms.WhoIsTypingTile") export default class WhoIsTypingTile extends React.Component { static propTypes = { // the room this statusbar is representing.