Merge remote-tracking branch 'upstream/develop' into feature/remember-server/17739

This commit is contained in:
Šimon Brandner 2021-07-09 10:33:24 +02:00
commit f78ede9324
No known key found for this signature in database
GPG key ID: 9760693FDD98A790
112 changed files with 568 additions and 674 deletions

View file

@ -54,7 +54,6 @@
}, },
"dependencies": { "dependencies": {
"@babel/runtime": "^7.12.5", "@babel/runtime": "^7.12.5",
"@types/commonmark": "^0.27.4",
"await-lock": "^2.1.0", "await-lock": "^2.1.0",
"blurhash": "^1.1.3", "blurhash": "^1.1.3",
"browser-encrypt-attachment": "^0.3.0", "browser-encrypt-attachment": "^0.3.0",
@ -92,6 +91,7 @@
"re-resizable": "^6.9.0", "re-resizable": "^6.9.0",
"react": "^17.0.2", "react": "^17.0.2",
"react-beautiful-dnd": "^13.1.0", "react-beautiful-dnd": "^13.1.0",
"react-blurhash": "^0.1.3",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-focus-lock": "^2.5.0", "react-focus-lock": "^2.5.0",
"react-transition-group": "^4.4.1", "react-transition-group": "^4.4.1",
@ -124,6 +124,7 @@
"@peculiar/webcrypto": "^1.1.4", "@peculiar/webcrypto": "^1.1.4",
"@sinonjs/fake-timers": "^7.0.2", "@sinonjs/fake-timers": "^7.0.2",
"@types/classnames": "^2.2.11", "@types/classnames": "^2.2.11",
"@types/commonmark": "^0.27.4",
"@types/counterpart": "^0.18.1", "@types/counterpart": "^0.18.1",
"@types/diff-match-patch": "^1.0.32", "@types/diff-match-patch": "^1.0.32",
"@types/flux": "^3.1.9", "@types/flux": "^3.1.9",

View file

@ -201,6 +201,7 @@
@import "./views/rooms/_GroupLayout.scss"; @import "./views/rooms/_GroupLayout.scss";
@import "./views/rooms/_IRCLayout.scss"; @import "./views/rooms/_IRCLayout.scss";
@import "./views/rooms/_JumpToBottomButton.scss"; @import "./views/rooms/_JumpToBottomButton.scss";
@import "./views/rooms/_LinkPreviewGroup.scss";
@import "./views/rooms/_LinkPreviewWidget.scss"; @import "./views/rooms/_LinkPreviewWidget.scss";
@import "./views/rooms/_MemberInfo.scss"; @import "./views/rooms/_MemberInfo.scss";
@import "./views/rooms/_MemberList.scss"; @import "./views/rooms/_MemberList.scss";

View file

@ -477,8 +477,7 @@ $hover-select-border: 4px;
pre, code { pre, code {
font-family: $monospace-font-family !important; font-family: $monospace-font-family !important;
// deliberate constants as we're behind an invert filter background-color: $header-panel-bg-color;
color: #333;
} }
pre { pre {
@ -488,11 +487,6 @@ $hover-select-border: 4px;
overflow-x: overlay; overflow-x: overlay;
overflow-y: visible; overflow-y: visible;
} }
code {
// deliberate constants as we're behind an invert filter
background-color: #f8f8f8;
}
} }
.mx_EventTile_lineNumbers { .mx_EventTile_lineNumbers {

View file

@ -0,0 +1,38 @@
/*
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_LinkPreviewGroup {
.mx_LinkPreviewGroup_hide {
cursor: pointer;
width: 18px;
height: 18px;
img {
flex: 0 0 40px;
visibility: hidden;
}
}
&:hover .mx_LinkPreviewGroup_hide img,
.mx_LinkPreviewGroup_hide.focus-visible:focus img {
visibility: visible;
}
> .mx_AccessibleButton {
color: $accent-color;
text-align: center;
}
}

View file

@ -33,12 +33,16 @@ limitations under the License.
.mx_LinkPreviewWidget_caption { .mx_LinkPreviewWidget_caption {
margin-left: 15px; margin-left: 15px;
flex: 1 1 auto; flex: 1 1 auto;
overflow-x: hidden; // cause it to wrap rather than clip
} }
.mx_LinkPreviewWidget_title { .mx_LinkPreviewWidget_title {
display: inline;
font-weight: bold; font-weight: bold;
white-space: normal; white-space: normal;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
} }
.mx_LinkPreviewWidget_siteName { .mx_LinkPreviewWidget_siteName {
@ -49,22 +53,9 @@ limitations under the License.
margin-top: 8px; margin-top: 8px;
white-space: normal; white-space: normal;
word-wrap: break-word; word-wrap: break-word;
} display: -webkit-box;
-webkit-line-clamp: 3;
.mx_LinkPreviewWidget_cancel { -webkit-box-orient: vertical;
cursor: pointer;
width: 18px;
height: 18px;
img {
flex: 0 0 40px;
visibility: hidden;
}
}
.mx_LinkPreviewWidget:hover .mx_LinkPreviewWidget_cancel img,
.mx_LinkPreviewWidget_cancel.focus-visible:focus img {
visibility: visible;
} }
.mx_MatrixChat_useCompactLayout { .mx_MatrixChat_useCompactLayout {

View file

@ -119,8 +119,6 @@ $voipcall-plinth-color: #394049;
$theme-button-bg-color: #e3e8f0; $theme-button-bg-color: #e3e8f0;
$dialpad-button-bg-color: #6F7882; $dialpad-button-bg-color: #6F7882;
;
$roomlist-button-bg-color: rgba(141, 151, 165, 0.2); // Buttons include the filter box, explore button, and sublist buttons $roomlist-button-bg-color: rgba(141, 151, 165, 0.2); // Buttons include the filter box, explore button, and sublist buttons
$roomlist-filter-active-bg-color: $bg-color; $roomlist-filter-active-bg-color: $bg-color;
@ -274,24 +272,7 @@ $composer-shadow-color: rgba(0, 0, 0, 0.28);
} }
// markdown overrides: // markdown overrides:
.mx_EventTile_content .markdown-body pre:hover {
border-color: #808080 !important; // inverted due to rules below
scrollbar-color: rgba(0, 0, 0, 0.2) transparent; // copied from light theme due to inversion below
// the code above works only in Firefox, this is for other browsers
// see https://developer.mozilla.org/en-US/docs/Web/CSS/scrollbar-color
&::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0.2); // copied from light theme due to inversion below
}
}
.mx_EventTile_content .markdown-body { .mx_EventTile_content .markdown-body {
pre, code {
filter: invert(1);
}
pre code {
filter: none;
}
table { table {
tr { tr {
background-color: #000000; background-color: #000000;
@ -301,18 +282,9 @@ $composer-shadow-color: rgba(0, 0, 0, 0.28);
background-color: #080808; background-color: #080808;
} }
} }
blockquote {
color: #919191;
}
} }
// diff highlight colors // highlight.js overrides
// intentionally swapped to avoid inversion .hljs-tag {
.hljs-addition { color: inherit; // Without this they'd be weirdly blue which doesn't match the theme
background: #fdd;
}
.hljs-deletion {
background: #dfd;
} }

View file

@ -9,3 +9,4 @@
@import "_dark.scss"; @import "_dark.scss";
@import "../../light/css/_mods.scss"; @import "../../light/css/_mods.scss";
@import "../../../../res/css/_components.scss"; @import "../../../../res/css/_components.scss";
@import url("highlight.js/styles/atom-one-dark.css");

View file

@ -118,7 +118,7 @@ $voipcall-plinth-color: #394049;
$theme-button-bg-color: #e3e8f0; $theme-button-bg-color: #e3e8f0;
$dialpad-button-bg-color: #6F7882; $dialpad-button-bg-color: #6F7882;
;
$roomlist-button-bg-color: #1A1D23; // Buttons include the filter box, explore button, and sublist buttons $roomlist-button-bg-color: #1A1D23; // Buttons include the filter box, explore button, and sublist buttons
$roomlist-filter-active-bg-color: $roomlist-button-bg-color; $roomlist-filter-active-bg-color: $roomlist-button-bg-color;
@ -249,7 +249,7 @@ $composer-shadow-color: tranparent;
@define-mixin mx_DialogButton_secondary { @define-mixin mx_DialogButton_secondary {
// flip colours for the secondary ones // flip colours for the secondary ones
font-weight: 600; font-weight: 600;
border: 1px solid $accent-color ! important; border: 1px solid $accent-color !important;
color: $accent-color; color: $accent-color;
background-color: $button-secondary-bg-color; background-color: $button-secondary-bg-color;
} }
@ -267,18 +267,7 @@ $composer-shadow-color: tranparent;
} }
// markdown overrides: // markdown overrides:
.mx_EventTile_content .markdown-body pre:hover {
border-color: #808080 !important; // inverted due to rules below
}
.mx_EventTile_content .markdown-body { .mx_EventTile_content .markdown-body {
pre, code {
filter: invert(1);
}
pre code {
filter: none;
}
table { table {
tr { tr {
background-color: #000000; background-color: #000000;
@ -290,12 +279,7 @@ $composer-shadow-color: tranparent;
} }
} }
// diff highlight colors // highlight.js overrides:
// intentionally swapped to avoid inversion .hljs-tag {
.hljs-addition { color: inherit; // Without this they'd be weirdly blue which doesn't match the theme
background: #fdd;
}
.hljs-deletion {
background: #dfd;
} }

View file

@ -4,3 +4,4 @@
@import "../../legacy-light/css/_legacy-light.scss"; @import "../../legacy-light/css/_legacy-light.scss";
@import "_legacy-dark.scss"; @import "_legacy-dark.scss";
@import "../../../../res/css/_components.scss"; @import "../../../../res/css/_components.scss";
@import url("highlight.js/styles/atom-one-dark.css");

View file

@ -3,3 +3,4 @@
@import "_fonts.scss"; @import "_fonts.scss";
@import "_legacy-light.scss"; @import "_legacy-light.scss";
@import "../../../../res/css/_components.scss"; @import "../../../../res/css/_components.scss";
@import url("highlight.js/styles/atom-one-light.css");

View file

@ -4,3 +4,4 @@
@import "_light.scss"; @import "_light.scss";
@import "_mods.scss"; @import "_mods.scss";
@import "../../../../res/css/_components.scss"; @import "../../../../res/css/_components.scss";
@import url("highlight.js/styles/atom-one-light.css");

View file

@ -6,8 +6,8 @@ scripts/fetchdep.sh matrix-org matrix-js-sdk
pushd matrix-js-sdk pushd matrix-js-sdk
yarn link yarn link
yarn install $@ yarn install --pure-lockfile $@
popd popd
yarn link matrix-js-sdk yarn link matrix-js-sdk
yarn install $@ yarn install --pure-lockfile $@

View file

@ -13,13 +13,13 @@
scripts/fetchdep.sh matrix-org matrix-js-sdk scripts/fetchdep.sh matrix-org matrix-js-sdk
pushd matrix-js-sdk pushd matrix-js-sdk
yarn link yarn link
yarn install yarn install --pure-lockfile
popd popd
# Now set up the react-sdk # Now set up the react-sdk
yarn link matrix-js-sdk yarn link matrix-js-sdk
yarn link yarn link
yarn install yarn install --pure-lockfile
yarn reskindex yarn reskindex
# Finally, set up element-web # Finally, set up element-web
@ -27,6 +27,6 @@ scripts/fetchdep.sh vector-im element-web
pushd element-web pushd element-web
yarn link matrix-js-sdk yarn link matrix-js-sdk
yarn link matrix-react-sdk yarn link matrix-react-sdk
yarn install yarn install --pure-lockfile
yarn build:res yarn build:res
popd popd

View file

@ -390,6 +390,7 @@ export class Analytics {
{ expl: _td('Your device resolution'), value: resolution }, { expl: _td('Your device resolution'), value: resolution },
]; ];
// FIXME: Using an import will result in test failures
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog'); const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
Modal.createTrackedDialog('Analytics Details', '', ErrorDialog, { Modal.createTrackedDialog('Analytics Details', '', ErrorDialog, {
title: _t('Analytics'), title: _t('Analytics'),

View file

@ -77,6 +77,7 @@ export default class AsyncWrapper extends React.Component<IProps, IState> {
const Component = this.state.component; const Component = this.state.component;
return <Component {...this.props} />; return <Component {...this.props} />;
} else if (this.state.error) { } else if (this.state.error) {
// FIXME: Using an import will result in test failures
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
return <BaseDialog onFinished={this.props.onFinished} title={_t("Error")}> return <BaseDialog onFinished={this.props.onFinished} title={_t("Error")}>

View file

@ -49,8 +49,6 @@ const MAX_HEIGHT = 600;
const PHYS_HIDPI = [0x00, 0x00, 0x16, 0x25, 0x00, 0x00, 0x16, 0x25, 0x01]; const PHYS_HIDPI = [0x00, 0x00, 0x16, 0x25, 0x00, 0x00, 0x16, 0x25, 0x01];
export const BLURHASH_FIELD = "xyz.amorgan.blurhash"; // MSC2448 export const BLURHASH_FIELD = "xyz.amorgan.blurhash"; // MSC2448
const BLURHASH_X_COMPONENTS = 6;
const BLURHASH_Y_COMPONENTS = 6;
export class UploadCanceledError extends Error {} export class UploadCanceledError extends Error {}
@ -137,8 +135,9 @@ function createThumbnail(
imageData.data, imageData.data,
imageData.width, imageData.width,
imageData.height, imageData.height,
BLURHASH_X_COMPONENTS, // use 4 components on the longer dimension, if square then both
BLURHASH_Y_COMPONENTS, imageData.width >= imageData.height ? 4 : 3,
imageData.height >= imageData.width ? 4 : 3,
); );
canvas.toBlob(function(thumbnail) { canvas.toBlob(function(thumbnail) {
resolve({ resolve({
@ -419,6 +418,7 @@ export default class ContentMessages {
const isQuoting = Boolean(RoomViewStore.getQuotingEvent()); const isQuoting = Boolean(RoomViewStore.getQuotingEvent());
if (isQuoting) { if (isQuoting) {
// FIXME: Using an import will result in Element crashing
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
const { finished } = Modal.createTrackedDialog<[boolean]>('Upload Reply Warning', '', QuestionDialog, { const { finished } = Modal.createTrackedDialog<[boolean]>('Upload Reply Warning', '', QuestionDialog, {
title: _t('Replying With Files'), title: _t('Replying With Files'),
@ -453,6 +453,7 @@ export default class ContentMessages {
} }
if (tooBigFiles.length > 0) { if (tooBigFiles.length > 0) {
// FIXME: Using an import will result in Element crashing
const UploadFailureDialog = sdk.getComponent("dialogs.UploadFailureDialog"); const UploadFailureDialog = sdk.getComponent("dialogs.UploadFailureDialog");
const { finished } = Modal.createTrackedDialog<[boolean]>('Upload Failure', '', UploadFailureDialog, { const { finished } = Modal.createTrackedDialog<[boolean]>('Upload Failure', '', UploadFailureDialog, {
badFiles: tooBigFiles, badFiles: tooBigFiles,
@ -463,7 +464,6 @@ export default class ContentMessages {
if (!shouldContinue) return; if (!shouldContinue) return;
} }
const UploadConfirmDialog = sdk.getComponent("dialogs.UploadConfirmDialog");
let uploadAll = false; let uploadAll = false;
// Promise to complete before sending next file into room, used for synchronisation of file-sending // Promise to complete before sending next file into room, used for synchronisation of file-sending
// to match the order the files were specified in // to match the order the files were specified in
@ -471,6 +471,8 @@ export default class ContentMessages {
for (let i = 0; i < okFiles.length; ++i) { for (let i = 0; i < okFiles.length; ++i) {
const file = okFiles[i]; const file = okFiles[i];
if (!uploadAll) { if (!uploadAll) {
// FIXME: Using an import will result in Element crashing
const UploadConfirmDialog = sdk.getComponent("dialogs.UploadConfirmDialog");
const { finished } = Modal.createTrackedDialog<[boolean, boolean]>('Upload Files confirmation', const { finished } = Modal.createTrackedDialog<[boolean, boolean]>('Upload Files confirmation',
'', UploadConfirmDialog, { '', UploadConfirmDialog, {
file, file,
@ -606,6 +608,7 @@ export default class ContentMessages {
{ fileName: upload.fileName }, { fileName: upload.fileName },
); );
} }
// FIXME: Using an import will result in Element crashing
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Upload failed', '', ErrorDialog, { Modal.createTrackedDialog('Upload failed', '', ErrorDialog, {
title: _t('Upload Failed'), title: _t('Upload Failed'),

View file

@ -160,7 +160,8 @@ export default class DeviceListener {
// which result in account data changes affecting checks below. // which result in account data changes affecting checks below.
if ( if (
ev.getType().startsWith('m.secret_storage.') || ev.getType().startsWith('m.secret_storage.') ||
ev.getType().startsWith('m.cross_signing.') ev.getType().startsWith('m.cross_signing.') ||
ev.getType() === 'm.megolm_backup.v1'
) { ) {
this._recheck(); this._recheck();
} }

View file

@ -33,7 +33,6 @@ import Presence from './Presence';
import dis from './dispatcher/dispatcher'; import dis from './dispatcher/dispatcher';
import DMRoomMap from './utils/DMRoomMap'; import DMRoomMap from './utils/DMRoomMap';
import Modal from './Modal'; import Modal from './Modal';
import * as sdk from './index';
import ActiveWidgetStore from './stores/ActiveWidgetStore'; import ActiveWidgetStore from './stores/ActiveWidgetStore';
import PlatformPeg from "./PlatformPeg"; import PlatformPeg from "./PlatformPeg";
import { sendLoginRequest } from "./Login"; import { sendLoginRequest } from "./Login";
@ -52,6 +51,10 @@ import CallHandler from './CallHandler';
import LifecycleCustomisations from "./customisations/Lifecycle"; import LifecycleCustomisations from "./customisations/Lifecycle";
import ErrorDialog from "./components/views/dialogs/ErrorDialog"; import ErrorDialog from "./components/views/dialogs/ErrorDialog";
import { _t } from "./languageHandler"; import { _t } from "./languageHandler";
import LazyLoadingResyncDialog from "./components/views/dialogs/LazyLoadingResyncDialog";
import LazyLoadingDisabledDialog from "./components/views/dialogs/LazyLoadingDisabledDialog";
import SessionRestoreErrorDialog from "./components/views/dialogs/SessionRestoreErrorDialog";
import StorageEvictedDialog from "./components/views/dialogs/StorageEvictedDialog";
const HOMESERVER_URL_KEY = "mx_hs_url"; const HOMESERVER_URL_KEY = "mx_hs_url";
const ID_SERVER_URL_KEY = "mx_is_url"; const ID_SERVER_URL_KEY = "mx_is_url";
@ -238,8 +241,6 @@ export function handleInvalidStoreError(e: InvalidStoreError): Promise<void> {
return Promise.resolve().then(() => { return Promise.resolve().then(() => {
const lazyLoadEnabled = e.value; const lazyLoadEnabled = e.value;
if (lazyLoadEnabled) { if (lazyLoadEnabled) {
const LazyLoadingResyncDialog =
sdk.getComponent("views.dialogs.LazyLoadingResyncDialog");
return new Promise((resolve) => { return new Promise((resolve) => {
Modal.createDialog(LazyLoadingResyncDialog, { Modal.createDialog(LazyLoadingResyncDialog, {
onFinished: resolve, onFinished: resolve,
@ -250,8 +251,6 @@ export function handleInvalidStoreError(e: InvalidStoreError): Promise<void> {
// between LL/non-LL version on same host. // between LL/non-LL version on same host.
// as disabling LL when previously enabled // as disabling LL when previously enabled
// is a strong indicator of this (/develop & /app) // is a strong indicator of this (/develop & /app)
const LazyLoadingDisabledDialog =
sdk.getComponent("views.dialogs.LazyLoadingDisabledDialog");
return new Promise((resolve) => { return new Promise((resolve) => {
Modal.createDialog(LazyLoadingDisabledDialog, { Modal.createDialog(LazyLoadingDisabledDialog, {
onFinished: resolve, onFinished: resolve,
@ -451,9 +450,6 @@ export async function restoreFromLocalStorage(opts?: { ignoreGuest?: boolean }):
async function handleLoadSessionFailure(e: Error): Promise<boolean> { async function handleLoadSessionFailure(e: Error): Promise<boolean> {
console.error("Unable to load session", e); console.error("Unable to load session", e);
const SessionRestoreErrorDialog =
sdk.getComponent('views.dialogs.SessionRestoreErrorDialog');
const modal = Modal.createTrackedDialog('Session Restore Error', '', SessionRestoreErrorDialog, { const modal = Modal.createTrackedDialog('Session Restore Error', '', SessionRestoreErrorDialog, {
error: e.message, error: e.message,
}); });
@ -612,7 +608,6 @@ async function doSetLoggedIn(
} }
function showStorageEvictedDialog(): Promise<boolean> { function showStorageEvictedDialog(): Promise<boolean> {
const StorageEvictedDialog = sdk.getComponent('views.dialogs.StorageEvictedDialog');
return new Promise(resolve => { return new Promise(resolve => {
Modal.createTrackedDialog('Storage evicted', '', StorageEvictedDialog, { Modal.createTrackedDialog('Storage evicted', '', StorageEvictedDialog, {
onFinished: resolve, onFinished: resolve,

View file

@ -219,6 +219,7 @@ class _MatrixClientPeg implements IMatrixClientPeg {
} catch (e) { } catch (e) {
if (e && e.name === 'InvalidCryptoStoreError') { if (e && e.name === 'InvalidCryptoStoreError') {
// The js-sdk found a crypto DB too new for it to use // The js-sdk found a crypto DB too new for it to use
// FIXME: Using an import will result in test failures
const CryptoStoreTooNewDialog = const CryptoStoreTooNewDialog =
sdk.getComponent("views.dialogs.CryptoStoreTooNewDialog"); sdk.getComponent("views.dialogs.CryptoStoreTooNewDialog");
Modal.createDialog(CryptoStoreTooNewDialog); Modal.createDialog(CryptoStoreTooNewDialog);

View file

@ -27,7 +27,6 @@ import * as TextForEvent from './TextForEvent';
import Analytics from './Analytics'; import Analytics from './Analytics';
import * as Avatar from './Avatar'; import * as Avatar from './Avatar';
import dis from './dispatcher/dispatcher'; import dis from './dispatcher/dispatcher';
import * as sdk from './index';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
import Modal from './Modal'; import Modal from './Modal';
import SettingsStore from "./settings/SettingsStore"; import SettingsStore from "./settings/SettingsStore";
@ -37,6 +36,7 @@ import { isPushNotifyDisabled } from "./settings/controllers/NotificationControl
import RoomViewStore from "./stores/RoomViewStore"; import RoomViewStore from "./stores/RoomViewStore";
import UserActivity from "./UserActivity"; import UserActivity from "./UserActivity";
import { mediaFromMxc } from "./customisations/Media"; import { mediaFromMxc } from "./customisations/Media";
import ErrorDialog from "./components/views/dialogs/ErrorDialog";
/* /*
* Dispatches: * Dispatches:
@ -240,7 +240,6 @@ export const Notifier = {
? _t('%(brand)s does not have permission to send you notifications - ' + ? _t('%(brand)s does not have permission to send you notifications - ' +
'please check your browser settings', { brand }) 'please check your browser settings', { brand })
: _t('%(brand)s was not given permission to send notifications - please try again', { brand }); : _t('%(brand)s was not given permission to send notifications - please try again', { brand });
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
Modal.createTrackedDialog('Unable to enable Notifications', result, ErrorDialog, { Modal.createTrackedDialog('Unable to enable Notifications', result, ErrorDialog, {
title: _t('Unable to enable Notifications'), title: _t('Unable to enable Notifications'),
description, description,

View file

@ -22,13 +22,13 @@ import { User } from "matrix-js-sdk/src/models/user";
import { MatrixClientPeg } from './MatrixClientPeg'; import { MatrixClientPeg } from './MatrixClientPeg';
import MultiInviter, { CompletionStates } from './utils/MultiInviter'; import MultiInviter, { CompletionStates } from './utils/MultiInviter';
import Modal from './Modal'; import Modal from './Modal';
import * as sdk from './';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
import InviteDialog, { KIND_DM, KIND_INVITE, Member } from "./components/views/dialogs/InviteDialog"; import InviteDialog, { KIND_DM, KIND_INVITE, Member } from "./components/views/dialogs/InviteDialog";
import CommunityPrototypeInviteDialog from "./components/views/dialogs/CommunityPrototypeInviteDialog"; import CommunityPrototypeInviteDialog from "./components/views/dialogs/CommunityPrototypeInviteDialog";
import { CommunityPrototypeStore } from "./stores/CommunityPrototypeStore"; import { CommunityPrototypeStore } from "./stores/CommunityPrototypeStore";
import BaseAvatar from "./components/views/avatars/BaseAvatar"; import BaseAvatar from "./components/views/avatars/BaseAvatar";
import { mediaFromMxc } from "./customisations/Media"; import { mediaFromMxc } from "./customisations/Media";
import ErrorDialog from "./components/views/dialogs/ErrorDialog";
export interface IInviteResult { export interface IInviteResult {
states: CompletionStates; states: CompletionStates;
@ -51,7 +51,6 @@ export function inviteMultipleToRoom(roomId: string, addresses: string[]): Promi
export function showStartChatInviteDialog(initialText = ""): void { export function showStartChatInviteDialog(initialText = ""): void {
// This dialog handles the room creation internally - we don't need to worry about it. // This dialog handles the room creation internally - we don't need to worry about it.
const InviteDialog = sdk.getComponent("dialogs.InviteDialog");
Modal.createTrackedDialog( Modal.createTrackedDialog(
'Start DM', '', InviteDialog, { kind: KIND_DM, initialText }, 'Start DM', '', InviteDialog, { kind: KIND_DM, initialText },
/*className=*/null, /*isPriority=*/false, /*isStatic=*/true, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true,
@ -111,7 +110,6 @@ export function inviteUsersToRoom(roomId: string, userIds: string[]): Promise<vo
showAnyInviteErrors(result.states, room, result.inviter); showAnyInviteErrors(result.states, room, result.inviter);
}).catch((err) => { }).catch((err) => {
console.error(err.stack); console.error(err.stack);
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to invite', '', ErrorDialog, { Modal.createTrackedDialog('Failed to invite', '', ErrorDialog, {
title: _t("Failed to invite"), title: _t("Failed to invite"),
description: ((err && err.message) ? err.message : _t("Operation failed")), description: ((err && err.message) ? err.message : _t("Operation failed")),
@ -131,7 +129,6 @@ export function showAnyInviteErrors(
// Just get the first message because there was a fatal problem on the first // Just get the first message because there was a fatal problem on the first
// user. This usually means that no other users were attempted, making it // user. This usually means that no other users were attempted, making it
// pointless for us to list who failed exactly. // pointless for us to list who failed exactly.
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to invite users to the room', '', ErrorDialog, { Modal.createTrackedDialog('Failed to invite users to the room', '', ErrorDialog, {
title: _t("Failed to invite users to the room:", { roomName: room.name }), title: _t("Failed to invite users to the room:", { roomName: room.name }),
description: inviter.getErrorText(failedUsers[0]), description: inviter.getErrorText(failedUsers[0]),
@ -178,7 +175,6 @@ export function showAnyInviteErrors(
</div> </div>
</div>; </div>;
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog("Some invites could not be sent", "", ErrorDialog, { Modal.createTrackedDialog("Some invites could not be sent", "", ErrorDialog, {
title: _t("Some invites couldn't be sent"), title: _t("Some invites couldn't be sent"),
description, description,

View file

@ -14,7 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import { ICryptoCallbacks, ISecretStorageKeyInfo } from 'matrix-js-sdk/src/matrix'; import { ICryptoCallbacks } from 'matrix-js-sdk/src/matrix';
import { ISecretStorageKeyInfo } from 'matrix-js-sdk/src/crypto/api';
import { MatrixClient } from 'matrix-js-sdk/src/client'; import { MatrixClient } from 'matrix-js-sdk/src/client';
import Modal from './Modal'; import Modal from './Modal';
import * as sdk from './index'; import * as sdk from './index';
@ -354,6 +355,7 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f
throw new Error("Secret storage creation canceled"); throw new Error("Secret storage creation canceled");
} }
} else { } else {
// FIXME: Using an import will result in test failures
const InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog"); const InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog");
await cli.bootstrapCrossSigning({ await cli.bootstrapCrossSigning({
authUploadDeviceSigningKeys: async (makeRequest) => { authUploadDeviceSigningKeys: async (makeRequest) => {

View file

@ -23,7 +23,6 @@ import { User } from "matrix-js-sdk/src/models/user";
import * as ContentHelpers from 'matrix-js-sdk/src/content-helpers'; import * as ContentHelpers from 'matrix-js-sdk/src/content-helpers';
import { MatrixClientPeg } from './MatrixClientPeg'; import { MatrixClientPeg } from './MatrixClientPeg';
import dis from './dispatcher/dispatcher'; import dis from './dispatcher/dispatcher';
import * as sdk from './index';
import { _t, _td } from './languageHandler'; import { _t, _td } from './languageHandler';
import Modal from './Modal'; import Modal from './Modal';
import MultiInviter from './utils/MultiInviter'; import MultiInviter from './utils/MultiInviter';
@ -50,6 +49,12 @@ import { UIFeature } from "./settings/UIFeature";
import { CHAT_EFFECTS } from "./effects"; import { CHAT_EFFECTS } from "./effects";
import CallHandler from "./CallHandler"; import CallHandler from "./CallHandler";
import { guessAndSetDMRoom } from "./Rooms"; import { guessAndSetDMRoom } from "./Rooms";
import UploadConfirmDialog from './components/views/dialogs/UploadConfirmDialog';
import ErrorDialog from './components/views/dialogs/ErrorDialog';
import DevtoolsDialog from './components/views/dialogs/DevtoolsDialog';
import RoomUpgradeWarningDialog from "./components/views/dialogs/RoomUpgradeWarningDialog";
import InfoDialog from "./components/views/dialogs/InfoDialog";
import SlashCommandHelpDialog from "./components/views/dialogs/SlashCommandHelpDialog";
// XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816 // XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816
interface HTMLInputEvent extends Event { interface HTMLInputEvent extends Event {
@ -63,7 +68,6 @@ const singleMxcUpload = async (): Promise<any> => {
fileSelector.onchange = (ev: HTMLInputEvent) => { fileSelector.onchange = (ev: HTMLInputEvent) => {
const file = ev.target.files[0]; const file = ev.target.files[0];
const UploadConfirmDialog = sdk.getComponent("dialogs.UploadConfirmDialog");
Modal.createTrackedDialog('Upload Files confirmation', '', UploadConfirmDialog, { Modal.createTrackedDialog('Upload Files confirmation', '', UploadConfirmDialog, {
file, file,
onFinished: (shouldContinue) => { onFinished: (shouldContinue) => {
@ -246,7 +250,6 @@ export const Commands = [
args: '<query>', args: '<query>',
description: _td('Searches DuckDuckGo for results'), description: _td('Searches DuckDuckGo for results'),
runFn: function() { runFn: function() {
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
// TODO Don't explain this away, actually show a search UI here. // TODO Don't explain this away, actually show a search UI here.
Modal.createTrackedDialog('Slash Commands', '/ddg is not a command', ErrorDialog, { Modal.createTrackedDialog('Slash Commands', '/ddg is not a command', ErrorDialog, {
title: _t('/ddg is not a command'), title: _t('/ddg is not a command'),
@ -269,8 +272,6 @@ export const Commands = [
return reject(_t("You do not have the required permissions to use this command.")); return reject(_t("You do not have the required permissions to use this command."));
} }
const RoomUpgradeWarningDialog = sdk.getComponent("dialogs.RoomUpgradeWarningDialog");
const { finished } = Modal.createTrackedDialog('Slash Commands', 'upgrade room confirmation', const { finished } = Modal.createTrackedDialog('Slash Commands', 'upgrade room confirmation',
RoomUpgradeWarningDialog, { roomId: roomId, targetVersion: args }, /*className=*/null, RoomUpgradeWarningDialog, { roomId: roomId, targetVersion: args }, /*className=*/null,
/*isPriority=*/false, /*isStatic=*/true); /*isPriority=*/false, /*isStatic=*/true);
@ -314,7 +315,6 @@ export const Commands = [
if (checkForUpgradeFn) cli.removeListener('Room', checkForUpgradeFn); if (checkForUpgradeFn) cli.removeListener('Room', checkForUpgradeFn);
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
Modal.createTrackedDialog('Slash Commands', 'room upgrade error', ErrorDialog, { Modal.createTrackedDialog('Slash Commands', 'room upgrade error', ErrorDialog, {
title: _t('Error upgrading room'), title: _t('Error upgrading room'),
description: _t( description: _t(
@ -434,7 +434,6 @@ export const Commands = [
const topic = topicEvents && topicEvents.getContent().topic; const topic = topicEvents && topicEvents.getContent().topic;
const topicHtml = topic ? linkifyAndSanitizeHtml(topic) : _t('This room has no topic.'); const topicHtml = topic ? linkifyAndSanitizeHtml(topic) : _t('This room has no topic.');
const InfoDialog = sdk.getComponent('dialogs.InfoDialog');
Modal.createTrackedDialog('Slash Commands', 'Topic', InfoDialog, { Modal.createTrackedDialog('Slash Commands', 'Topic', InfoDialog, {
title: room.name, title: room.name,
description: <div dangerouslySetInnerHTML={{ __html: topicHtml }} />, description: <div dangerouslySetInnerHTML={{ __html: topicHtml }} />,
@ -737,7 +736,6 @@ export const Commands = [
ignoredUsers.push(userId); // de-duped internally in the js-sdk ignoredUsers.push(userId); // de-duped internally in the js-sdk
return success( return success(
cli.setIgnoredUsers(ignoredUsers).then(() => { cli.setIgnoredUsers(ignoredUsers).then(() => {
const InfoDialog = sdk.getComponent('dialogs.InfoDialog');
Modal.createTrackedDialog('Slash Commands', 'User ignored', InfoDialog, { Modal.createTrackedDialog('Slash Commands', 'User ignored', InfoDialog, {
title: _t('Ignored user'), title: _t('Ignored user'),
description: <div> description: <div>
@ -768,7 +766,6 @@ export const Commands = [
if (index !== -1) ignoredUsers.splice(index, 1); if (index !== -1) ignoredUsers.splice(index, 1);
return success( return success(
cli.setIgnoredUsers(ignoredUsers).then(() => { cli.setIgnoredUsers(ignoredUsers).then(() => {
const InfoDialog = sdk.getComponent('dialogs.InfoDialog');
Modal.createTrackedDialog('Slash Commands', 'User unignored', InfoDialog, { Modal.createTrackedDialog('Slash Commands', 'User unignored', InfoDialog, {
title: _t('Unignored user'), title: _t('Unignored user'),
description: <div> description: <div>
@ -838,7 +835,6 @@ export const Commands = [
command: 'devtools', command: 'devtools',
description: _td('Opens the Developer Tools dialog'), description: _td('Opens the Developer Tools dialog'),
runFn: function(roomId) { runFn: function(roomId) {
const DevtoolsDialog = sdk.getComponent('dialogs.DevtoolsDialog');
Modal.createDialog(DevtoolsDialog, { roomId }); Modal.createDialog(DevtoolsDialog, { roomId });
return success(); return success();
}, },
@ -943,7 +939,6 @@ export const Commands = [
await cli.setDeviceVerified(userId, deviceId, true); await cli.setDeviceVerified(userId, deviceId, true);
// Tell the user we verified everything // Tell the user we verified everything
const InfoDialog = sdk.getComponent('dialogs.InfoDialog');
Modal.createTrackedDialog('Slash Commands', 'Verified key', InfoDialog, { Modal.createTrackedDialog('Slash Commands', 'Verified key', InfoDialog, {
title: _t('Verified key'), title: _t('Verified key'),
description: <div> description: <div>
@ -1000,8 +995,6 @@ export const Commands = [
command: "help", command: "help",
description: _td("Displays list of commands with usages and descriptions"), description: _td("Displays list of commands with usages and descriptions"),
runFn: function() { runFn: function() {
const SlashCommandHelpDialog = sdk.getComponent('dialogs.SlashCommandHelpDialog');
Modal.createTrackedDialog('Slash Commands', 'Help', SlashCommandHelpDialog); Modal.createTrackedDialog('Slash Commands', 'Help', SlashCommandHelpDialog);
return success(); return success();
}, },

View file

@ -189,6 +189,7 @@ export function dialogTermsInteractionCallback(
): Promise<string[]> { ): Promise<string[]> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
console.log("Terms that need agreement", policiesAndServicePairs); console.log("Terms that need agreement", policiesAndServicePairs);
// FIXME: Using an import will result in test failures
const TermsDialog = sdk.getComponent("views.dialogs.TermsDialog"); const TermsDialog = sdk.getComponent("views.dialogs.TermsDialog");
Modal.createTrackedDialog('Terms of Service', '', TermsDialog, { Modal.createTrackedDialog('Terms of Service', '', TermsDialog, {

View file

@ -17,10 +17,10 @@ limitations under the License.
import * as React from "react"; import * as React from "react";
import classNames from "classnames"; import classNames from "classnames";
import * as sdk from "../index";
import Modal from "../Modal"; import Modal from "../Modal";
import { _t, _td } from "../languageHandler"; import { _t, _td } from "../languageHandler";
import { isMac, Key } from "../Keyboard"; import { isMac, Key } from "../Keyboard";
import InfoDialog from "../components/views/dialogs/InfoDialog";
// TS: once languageHandler is TS we can probably inline this into the enum // TS: once languageHandler is TS we can probably inline this into the enum
_td("Navigation"); _td("Navigation");
@ -375,7 +375,6 @@ export const toggleDialog = () => {
</div>; </div>;
}); });
const InfoDialog = sdk.getComponent('dialogs.InfoDialog');
activeModal = Modal.createTrackedDialog("Keyboard Shortcuts", "", InfoDialog, { activeModal = Modal.createTrackedDialog("Keyboard Shortcuts", "", InfoDialog, {
className: "mx_KeyboardShortcutsDialog", className: "mx_KeyboardShortcutsDialog",
title: _t("Keyboard Shortcuts"), title: _t("Keyboard Shortcuts"),

View file

@ -19,13 +19,13 @@ import { asyncAction } from './actionCreators';
import Modal from '../Modal'; import Modal from '../Modal';
import * as Rooms from '../Rooms'; import * as Rooms from '../Rooms';
import { _t } from '../languageHandler'; import { _t } from '../languageHandler';
import * as sdk from '../index';
import { MatrixClient } from "matrix-js-sdk/src/client"; import { MatrixClient } from "matrix-js-sdk/src/client";
import { Room } from "matrix-js-sdk/src/models/room"; import { Room } from "matrix-js-sdk/src/models/room";
import { AsyncActionPayload } from "../dispatcher/payloads"; import { AsyncActionPayload } from "../dispatcher/payloads";
import RoomListStore from "../stores/room-list/RoomListStore"; import RoomListStore from "../stores/room-list/RoomListStore";
import { SortAlgorithm } from "../stores/room-list/algorithms/models"; import { SortAlgorithm } from "../stores/room-list/algorithms/models";
import { DefaultTagID } from "../stores/room-list/models"; import { DefaultTagID } from "../stores/room-list/models";
import ErrorDialog from '../components/views/dialogs/ErrorDialog';
export default class RoomListActions { export default class RoomListActions {
/** /**
@ -88,7 +88,6 @@ export default class RoomListActions {
return Rooms.guessAndSetDMRoom( return Rooms.guessAndSetDMRoom(
room, newTag === DefaultTagID.DM, room, newTag === DefaultTagID.DM,
).catch((err) => { ).catch((err) => {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Failed to set direct chat tag " + err); console.error("Failed to set direct chat tag " + err);
Modal.createTrackedDialog('Failed to set direct chat tag', '', ErrorDialog, { Modal.createTrackedDialog('Failed to set direct chat tag', '', ErrorDialog, {
title: _t('Failed to set direct chat tag'), title: _t('Failed to set direct chat tag'),
@ -109,7 +108,6 @@ export default class RoomListActions {
const promiseToDelete = matrixClient.deleteRoomTag( const promiseToDelete = matrixClient.deleteRoomTag(
roomId, oldTag, roomId, oldTag,
).catch(function(err) { ).catch(function(err) {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Failed to remove tag " + oldTag + " from room: " + err); console.error("Failed to remove tag " + oldTag + " from room: " + err);
Modal.createTrackedDialog('Failed to remove tag from room', '', ErrorDialog, { Modal.createTrackedDialog('Failed to remove tag from room', '', ErrorDialog, {
title: _t('Failed to remove tag %(tagName)s from room', { tagName: oldTag }), title: _t('Failed to remove tag %(tagName)s from room', { tagName: oldTag }),
@ -129,7 +127,6 @@ export default class RoomListActions {
metaData = metaData || {}; metaData = metaData || {};
const promiseToAdd = matrixClient.setRoomTag(roomId, newTag, metaData).catch(function(err) { const promiseToAdd = matrixClient.setRoomTag(roomId, newTag, metaData).catch(function(err) {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Failed to add tag " + newTag + " to room: " + err); console.error("Failed to add tag " + newTag + " to room: " + err);
Modal.createTrackedDialog('Failed to add tag to room', '', ErrorDialog, { Modal.createTrackedDialog('Failed to add tag to room', '', ErrorDialog, {
title: _t('Failed to add tag %(tagName)s to room', { tagName: newTag }), title: _t('Failed to add tag %(tagName)s to room', { tagName: newTag }),

View file

@ -15,7 +15,6 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import * as sdk from '../../../../index';
import { _t } from '../../../../languageHandler'; import { _t } from '../../../../languageHandler';
import SdkConfig from '../../../../SdkConfig'; import SdkConfig from '../../../../SdkConfig';
import SettingsStore from "../../../../settings/SettingsStore"; import SettingsStore from "../../../../settings/SettingsStore";
@ -24,6 +23,9 @@ import Modal from '../../../../Modal';
import { formatBytes, formatCountLong } from "../../../../utils/FormattingUtils"; import { formatBytes, formatCountLong } from "../../../../utils/FormattingUtils";
import EventIndexPeg from "../../../../indexing/EventIndexPeg"; import EventIndexPeg from "../../../../indexing/EventIndexPeg";
import { SettingLevel } from "../../../../settings/SettingLevel"; import { SettingLevel } from "../../../../settings/SettingLevel";
import Field from '../../../../components/views/elements/Field';
import BaseDialog from "../../../../components/views/dialogs/BaseDialog";
import DialogButtons from "../../../../components/views/elements/DialogButtons";
interface IProps { interface IProps {
onFinished: (confirmed: boolean) => void; onFinished: (confirmed: boolean) => void;
@ -145,7 +147,6 @@ export default class ManageEventIndexDialog extends React.Component<IProps, ISta
render() { render() {
const brand = SdkConfig.get().brand; const brand = SdkConfig.get().brand;
const Field = sdk.getComponent('views.elements.Field');
let crawlerState; let crawlerState;
if (this.state.currentRoom === null) { if (this.state.currentRoom === null) {
@ -176,15 +177,12 @@ export default class ManageEventIndexDialog extends React.Component<IProps, ISta
<Field <Field
label={_t('Message downloading sleep time(ms)')} label={_t('Message downloading sleep time(ms)')}
type='number' type='number'
value={this.state.crawlerSleepTime} value={this.state.crawlerSleepTime.toString()}
onChange={this.onCrawlerSleepTimeChange} /> onChange={this.onCrawlerSleepTimeChange} />
</div> </div>
</div> </div>
); );
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
return ( return (
<BaseDialog className='mx_ManageEventIndexDialog' <BaseDialog className='mx_ManageEventIndexDialog'
onFinished={this.props.onFinished} onFinished={this.props.onFinished}

View file

@ -22,12 +22,12 @@ import AutocompleteProvider from './AutocompleteProvider';
import { MatrixClientPeg } from '../MatrixClientPeg'; import { MatrixClientPeg } from '../MatrixClientPeg';
import QueryMatcher from './QueryMatcher'; import QueryMatcher from './QueryMatcher';
import { PillCompletion } from './Components'; import { PillCompletion } from './Components';
import * as sdk from '../index';
import { sortBy } from "lodash"; import { sortBy } from "lodash";
import { makeGroupPermalink } from "../utils/permalinks/Permalinks"; import { makeGroupPermalink } from "../utils/permalinks/Permalinks";
import { ICompletion, ISelectionRange } from "./Autocompleter"; import { ICompletion, ISelectionRange } from "./Autocompleter";
import FlairStore from "../stores/FlairStore"; import FlairStore from "../stores/FlairStore";
import { mediaFromMxc } from "../customisations/Media"; import { mediaFromMxc } from "../customisations/Media";
import BaseAvatar from '../components/views/avatars/BaseAvatar';
const COMMUNITY_REGEX = /\B\+\S*/g; const COMMUNITY_REGEX = /\B\+\S*/g;
@ -56,8 +56,6 @@ export default class CommunityProvider extends AutocompleteProvider {
force = false, force = false,
limit = -1, limit = -1,
): Promise<ICompletion[]> { ): Promise<ICompletion[]> {
const BaseAvatar = sdk.getComponent('views.avatars.BaseAvatar');
// Disable autocompletions when composing commands because of various issues // Disable autocompletions when composing commands because of various issues
// (see https://github.com/vector-im/element-web/issues/4762) // (see https://github.com/vector-im/element-web/issues/4762)
if (/^(\/join|\/leave)/.test(query)) { if (/^(\/join|\/leave)/.test(query)) {

View file

@ -21,8 +21,8 @@ import AutocompleteProvider from './AutocompleteProvider';
import { _t } from '../languageHandler'; import { _t } from '../languageHandler';
import { MatrixClientPeg } from '../MatrixClientPeg'; import { MatrixClientPeg } from '../MatrixClientPeg';
import { PillCompletion } from './Components'; import { PillCompletion } from './Components';
import * as sdk from '../index';
import { ICompletion, ISelectionRange } from "./Autocompleter"; import { ICompletion, ISelectionRange } from "./Autocompleter";
import RoomAvatar from '../components/views/avatars/RoomAvatar';
const AT_ROOM_REGEX = /@\S*/g; const AT_ROOM_REGEX = /@\S*/g;
@ -40,8 +40,6 @@ export default class NotifProvider extends AutocompleteProvider {
force = false, force = false,
limit = -1, limit = -1,
): Promise<ICompletion[]> { ): Promise<ICompletion[]> {
const RoomAvatar = sdk.getComponent('views.avatars.RoomAvatar');
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.get();
if (!this.room.currentState.mayTriggerNotifOfType('room', client.credentials.userId)) return []; if (!this.room.currentState.mayTriggerNotifOfType('room', client.credentials.userId)) return [];

View file

@ -21,7 +21,6 @@ import React from 'react';
import { _t } from '../languageHandler'; import { _t } from '../languageHandler';
import AutocompleteProvider from './AutocompleteProvider'; import AutocompleteProvider from './AutocompleteProvider';
import { PillCompletion } from './Components'; import { PillCompletion } from './Components';
import * as sdk from '../index';
import QueryMatcher from './QueryMatcher'; import QueryMatcher from './QueryMatcher';
import { sortBy } from 'lodash'; import { sortBy } from 'lodash';
import { MatrixClientPeg } from '../MatrixClientPeg'; import { MatrixClientPeg } from '../MatrixClientPeg';
@ -33,6 +32,7 @@ import { RoomState } from "matrix-js-sdk/src/models/room-state";
import { EventTimeline } from "matrix-js-sdk/src/models/event-timeline"; import { EventTimeline } from "matrix-js-sdk/src/models/event-timeline";
import { makeUserPermalink } from "../utils/permalinks/Permalinks"; import { makeUserPermalink } from "../utils/permalinks/Permalinks";
import { ICompletion, ISelectionRange } from "./Autocompleter"; import { ICompletion, ISelectionRange } from "./Autocompleter";
import MemberAvatar from '../components/views/avatars/MemberAvatar';
const USER_REGEX = /\B@\S*/g; const USER_REGEX = /\B@\S*/g;
@ -108,8 +108,6 @@ export default class UserProvider extends AutocompleteProvider {
force = false, force = false,
limit = -1, limit = -1,
): Promise<ICompletion[]> { ): Promise<ICompletion[]> {
const MemberAvatar = sdk.getComponent('views.avatars.MemberAvatar');
// lazy-load user list into matcher // lazy-load user list into matcher
if (!this.users) this._makeUsers(); if (!this.users) this._makeUsers();

View file

@ -24,7 +24,6 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { Room } from 'matrix-js-sdk/src/models/room'; import { Room } from 'matrix-js-sdk/src/models/room';
import { TimelineWindow } from 'matrix-js-sdk/src/timeline-window'; import { TimelineWindow } from 'matrix-js-sdk/src/timeline-window';
import * as sdk from '../../index';
import { MatrixClientPeg } from '../../MatrixClientPeg'; import { MatrixClientPeg } from '../../MatrixClientPeg';
import EventIndexPeg from "../../indexing/EventIndexPeg"; import EventIndexPeg from "../../indexing/EventIndexPeg";
import { _t } from '../../languageHandler'; import { _t } from '../../languageHandler';
@ -34,6 +33,9 @@ import DesktopBuildsNotice, { WarningKind } from "../views/elements/DesktopBuild
import { replaceableComponent } from "../../utils/replaceableComponent"; import { replaceableComponent } from "../../utils/replaceableComponent";
import ResizeNotifier from '../../utils/ResizeNotifier'; import ResizeNotifier from '../../utils/ResizeNotifier';
import TimelinePanel from "./TimelinePanel";
import Spinner from "../views/elements/Spinner";
import { TileShape } from '../views/rooms/EventTile';
interface IProps { interface IProps {
roomId: string; roomId: string;
@ -237,8 +239,6 @@ class FilePanel extends React.Component<IProps, IState> {
} }
// wrap a TimelinePanel with the jump-to-event bits turned off. // wrap a TimelinePanel with the jump-to-event bits turned off.
const TimelinePanel = sdk.getComponent("structures.TimelinePanel");
const Loader = sdk.getComponent("elements.Spinner");
const emptyState = (<div className="mx_RightPanel_empty mx_FilePanel_empty"> const emptyState = (<div className="mx_RightPanel_empty mx_FilePanel_empty">
<h2>{_t('No files visible in this room')}</h2> <h2>{_t('No files visible in this room')}</h2>
@ -264,7 +264,7 @@ class FilePanel extends React.Component<IProps, IState> {
timelineSet={this.state.timelineSet} timelineSet={this.state.timelineSet}
showUrlPreview = {false} showUrlPreview = {false}
onPaginationRequest={this.onPaginationRequest} onPaginationRequest={this.onPaginationRequest}
tileShape="file_grid" tileShape={TileShape.FileGrid}
resizeNotifier={this.props.resizeNotifier} resizeNotifier={this.props.resizeNotifier}
empty={emptyState} empty={emptyState}
/> />
@ -277,7 +277,7 @@ class FilePanel extends React.Component<IProps, IState> {
onClose={this.props.onClose} onClose={this.props.onClose}
previousPhase={RightPanelPhases.RoomSummary} previousPhase={RightPanelPhases.RoomSummary}
> >
<Loader /> <Spinner />
</BaseCard> </BaseCard>
); );
} }

View file

@ -96,6 +96,7 @@ const HomePage: React.FC<IProps> = ({ justRegistered = false }) => {
const pageUrl = getHomePageUrl(config); const pageUrl = getHomePageUrl(config);
if (pageUrl) { if (pageUrl) {
// FIXME: Using an import will result in wrench-element-tests failures
const EmbeddedPage = sdk.getComponent('structures.EmbeddedPage'); const EmbeddedPage = sdk.getComponent('structures.EmbeddedPage');
return <EmbeddedPage className="mx_HomePage" url={pageUrl} scrollbar={true} />; return <EmbeddedPage className="mx_HomePage" url={pageUrl} scrollbar={true} />;
} }

View file

@ -24,7 +24,6 @@ import { Key } from '../../Keyboard';
import PageTypes from '../../PageTypes'; import PageTypes from '../../PageTypes';
import MediaDeviceHandler from '../../MediaDeviceHandler'; import MediaDeviceHandler from '../../MediaDeviceHandler';
import { fixupColorFonts } from '../../utils/FontManager'; import { fixupColorFonts } from '../../utils/FontManager';
import * as sdk from '../../index';
import dis from '../../dispatcher/dispatcher'; import dis from '../../dispatcher/dispatcher';
import { IMatrixClientCreds } from '../../MatrixClientPeg'; import { IMatrixClientCreds } from '../../MatrixClientPeg';
import SettingsStore from "../../settings/SettingsStore"; import SettingsStore from "../../settings/SettingsStore";
@ -59,6 +58,11 @@ import { replaceableComponent } from "../../utils/replaceableComponent";
import CallHandler, { CallHandlerEvent } from '../../CallHandler'; import CallHandler, { CallHandlerEvent } from '../../CallHandler';
import { MatrixCall } from 'matrix-js-sdk/src/webrtc/call'; import { MatrixCall } from 'matrix-js-sdk/src/webrtc/call';
import AudioFeedArrayForCall from '../views/voip/AudioFeedArrayForCall'; import AudioFeedArrayForCall from '../views/voip/AudioFeedArrayForCall';
import RoomView from './RoomView';
import ToastContainer from './ToastContainer';
import MyGroups from "./MyGroups";
import UserView from "./UserView";
import GroupView from "./GroupView";
// We need to fetch each pinned message individually (if we don't already have it) // We need to fetch each pinned message individually (if we don't already have it)
// so each pinned message may trigger a request. Limit the number per room for sanity. // so each pinned message may trigger a request. Limit the number per room for sanity.
@ -78,8 +82,8 @@ interface IProps {
hideToSRUsers: boolean; hideToSRUsers: boolean;
resizeNotifier: ResizeNotifier; resizeNotifier: ResizeNotifier;
// eslint-disable-next-line camelcase // eslint-disable-next-line camelcase
page_type: string; page_type?: string;
autoJoin: boolean; autoJoin?: boolean;
threepidInvite?: IThreepidInvite; threepidInvite?: IThreepidInvite;
roomOobData?: IOOBData; roomOobData?: IOOBData;
currentRoomId: string; currentRoomId: string;
@ -567,12 +571,6 @@ class LoggedInView extends React.Component<IProps, IState> {
}; };
render() { render() {
const RoomView = sdk.getComponent('structures.RoomView');
const UserView = sdk.getComponent('structures.UserView');
const GroupView = sdk.getComponent('structures.GroupView');
const MyGroups = sdk.getComponent('structures.MyGroups');
const ToastContainer = sdk.getComponent('structures.ToastContainer');
let pageElement; let pageElement;
switch (this.props.page_type) { switch (this.props.page_type) {

View file

@ -36,7 +36,6 @@ import dis from "../../dispatcher/dispatcher";
import Notifier from '../../Notifier'; import Notifier from '../../Notifier';
import Modal from "../../Modal"; import Modal from "../../Modal";
import * as sdk from '../../index';
import { showRoomInviteDialog, showStartChatInviteDialog } from '../../RoomInvite'; import { showRoomInviteDialog, showStartChatInviteDialog } from '../../RoomInvite';
import * as Rooms from '../../Rooms'; import * as Rooms from '../../Rooms';
import linkifyMatrix from "../../linkify-matrix"; import linkifyMatrix from "../../linkify-matrix";
@ -85,9 +84,27 @@ import RoomListStore from "../../stores/room-list/RoomListStore";
import { RoomUpdateCause } from "../../stores/room-list/models"; import { RoomUpdateCause } from "../../stores/room-list/models";
import defaultDispatcher from "../../dispatcher/dispatcher"; import defaultDispatcher from "../../dispatcher/dispatcher";
import SecurityCustomisations from "../../customisations/Security"; import SecurityCustomisations from "../../customisations/Security";
import Spinner from "../views/elements/Spinner";
import QuestionDialog from "../views/dialogs/QuestionDialog";
import UserSettingsDialog from '../views/dialogs/UserSettingsDialog';
import CreateGroupDialog from '../views/dialogs/CreateGroupDialog';
import CreateRoomDialog from '../views/dialogs/CreateRoomDialog';
import RoomDirectory from './RoomDirectory';
import KeySignatureUploadFailedDialog from "../views/dialogs/KeySignatureUploadFailedDialog";
import IncomingSasDialog from "../views/dialogs/IncomingSasDialog";
import CompleteSecurity from "./auth/CompleteSecurity";
import LoggedInView from './LoggedInView';
import Welcome from "../views/auth/Welcome";
import ForgotPassword from "./auth/ForgotPassword";
import E2eSetup from "./auth/E2eSetup";
import Registration from './auth/Registration';
import Login from "./auth/Login";
import ErrorBoundary from '../views/elements/ErrorBoundary';
import VerificationRequestToast from '../views/toasts/VerificationRequestToast';
import PerformanceMonitor, { PerformanceEntryNames } from "../../performance"; import PerformanceMonitor, { PerformanceEntryNames } from "../../performance";
import UIStore, { UI_EVENTS } from "../../stores/UIStore"; import UIStore, { UI_EVENTS } from "../../stores/UIStore";
import SoftLogout from './auth/SoftLogout';
/** constants for MatrixChat.state.view */ /** constants for MatrixChat.state.view */
export enum Views { export enum Views {
@ -156,7 +173,12 @@ interface IRoomInfo {
/* eslint-enable camelcase */ /* eslint-enable camelcase */
interface IProps { // TODO type things better interface IProps { // TODO type things better
config: Record<string, any>; config: {
piwik: {
policyUrl: string;
};
[key: string]: any;
};
serverConfig?: ValidatedServerConfig; serverConfig?: ValidatedServerConfig;
onNewScreen: (screen: string, replaceLast: boolean) => void; onNewScreen: (screen: string, replaceLast: boolean) => void;
enableGuest?: boolean; enableGuest?: boolean;
@ -519,7 +541,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
onAction = (payload) => { onAction = (payload) => {
// console.log(`MatrixClientPeg.onAction: ${payload.action}`); // console.log(`MatrixClientPeg.onAction: ${payload.action}`);
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
// Start the onboarding process for certain actions // Start the onboarding process for certain actions
if (MatrixClientPeg.get() && MatrixClientPeg.get().isGuest() && if (MatrixClientPeg.get() && MatrixClientPeg.get().isGuest() &&
@ -613,8 +634,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
onFinished: (confirm) => { onFinished: (confirm) => {
if (confirm) { if (confirm) {
// FIXME: controller shouldn't be loading a view :( // FIXME: controller shouldn't be loading a view :(
const Loader = sdk.getComponent("elements.Spinner"); const modal = Modal.createDialog(Spinner, null, 'mx_Dialog_spinner');
const modal = Modal.createDialog(Loader, null, 'mx_Dialog_spinner');
MatrixClientPeg.get().leave(payload.room_id).then(() => { MatrixClientPeg.get().leave(payload.room_id).then(() => {
modal.close(); modal.close();
@ -650,7 +670,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
} }
case Action.ViewUserSettings: { case Action.ViewUserSettings: {
const tabPayload = payload as OpenToTabPayload; const tabPayload = payload as OpenToTabPayload;
const UserSettingsDialog = sdk.getComponent("dialogs.UserSettingsDialog");
Modal.createTrackedDialog('User settings', '', UserSettingsDialog, Modal.createTrackedDialog('User settings', '', UserSettingsDialog,
{ initialTabId: tabPayload.initialTabId }, { initialTabId: tabPayload.initialTabId },
/*className=*/null, /*isPriority=*/false, /*isStatic=*/true); /*className=*/null, /*isPriority=*/false, /*isStatic=*/true);
@ -663,11 +682,12 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
this.createRoom(payload.public, payload.defaultName); this.createRoom(payload.public, payload.defaultName);
break; break;
case 'view_create_group': { case 'view_create_group': {
let CreateGroupDialog = sdk.getComponent("dialogs.CreateGroupDialog"); const prototype = SettingsStore.getValue("feature_communities_v2_prototypes");
if (SettingsStore.getValue("feature_communities_v2_prototypes")) { Modal.createTrackedDialog(
CreateGroupDialog = CreateCommunityPrototypeDialog; 'Create Community',
} '',
Modal.createTrackedDialog('Create Community', '', CreateGroupDialog); prototype ? CreateCommunityPrototypeDialog : CreateGroupDialog,
);
break; break;
} }
case Action.ViewRoomDirectory: { case Action.ViewRoomDirectory: {
@ -677,7 +697,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
room_id: SpaceStore.instance.activeSpace.roomId, room_id: SpaceStore.instance.activeSpace.roomId,
}); });
} else { } else {
const RoomDirectory = sdk.getComponent("structures.RoomDirectory");
Modal.createTrackedDialog('Room directory', '', RoomDirectory, { Modal.createTrackedDialog('Room directory', '', RoomDirectory, {
initialText: payload.initialText, initialText: payload.initialText,
}, 'mx_RoomDirectory_dialogWrapper', false, true); }, 'mx_RoomDirectory_dialogWrapper', false, true);
@ -1019,7 +1038,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
} }
} }
const CreateRoomDialog = sdk.getComponent('dialogs.CreateRoomDialog');
const modal = Modal.createTrackedDialog('Create Room', '', CreateRoomDialog, { const modal = Modal.createTrackedDialog('Create Room', '', CreateRoomDialog, {
defaultPublic, defaultPublic,
defaultName, defaultName,
@ -1116,7 +1134,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
} }
private leaveRoom(roomId: string) { private leaveRoom(roomId: string) {
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
const roomToLeave = MatrixClientPeg.get().getRoom(roomId); const roomToLeave = MatrixClientPeg.get().getRoom(roomId);
const warnings = this.leaveRoomWarnings(roomId); const warnings = this.leaveRoomWarnings(roomId);
@ -1143,8 +1160,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
const d = leaveRoomBehaviour(roomId); const d = leaveRoomBehaviour(roomId);
// FIXME: controller shouldn't be loading a view :( // FIXME: controller shouldn't be loading a view :(
const Loader = sdk.getComponent("elements.Spinner"); const modal = Modal.createDialog(Spinner, null, 'mx_Dialog_spinner');
const modal = Modal.createDialog(Loader, null, 'mx_Dialog_spinner');
d.finally(() => modal.close()); d.finally(() => modal.close());
dis.dispatch({ dis.dispatch({
@ -1439,7 +1455,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
}); });
}); });
cli.on('no_consent', function(message, consentUri) { cli.on('no_consent', function(message, consentUri) {
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
Modal.createTrackedDialog('No Consent Dialog', '', QuestionDialog, { Modal.createTrackedDialog('No Consent Dialog', '', QuestionDialog, {
title: _t('Terms and Conditions'), title: _t('Terms and Conditions'),
description: <div> description: <div>
@ -1548,8 +1563,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
}); });
cli.on("crypto.keySignatureUploadFailure", (failures, source, continuation) => { cli.on("crypto.keySignatureUploadFailure", (failures, source, continuation) => {
const KeySignatureUploadFailedDialog =
sdk.getComponent('views.dialogs.KeySignatureUploadFailedDialog');
Modal.createTrackedDialog( Modal.createTrackedDialog(
'Failed to upload key signatures', 'Failed to upload key signatures',
'Failed to upload key signatures', 'Failed to upload key signatures',
@ -1559,7 +1572,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
cli.on("crypto.verification.request", request => { cli.on("crypto.verification.request", request => {
if (request.verifier) { if (request.verifier) {
const IncomingSasDialog = sdk.getComponent("views.dialogs.IncomingSasDialog");
Modal.createTrackedDialog('Incoming Verification', '', IncomingSasDialog, { Modal.createTrackedDialog('Incoming Verification', '', IncomingSasDialog, {
verifier: request.verifier, verifier: request.verifier,
}, null, /* priority = */ false, /* static = */ true); }, null, /* priority = */ false, /* static = */ true);
@ -1569,7 +1581,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
title: _t("Verification requested"), title: _t("Verification requested"),
icon: "verification", icon: "verification",
props: { request }, props: { request },
component: sdk.getComponent("toasts.VerificationRequestToast"), component: VerificationRequestToast,
priority: 90, priority: 90,
}); });
} }
@ -1977,21 +1989,18 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
let view = null; let view = null;
if (this.state.view === Views.LOADING) { if (this.state.view === Views.LOADING) {
const Spinner = sdk.getComponent('elements.Spinner');
view = ( view = (
<div className="mx_MatrixChat_splash"> <div className="mx_MatrixChat_splash">
<Spinner /> <Spinner />
</div> </div>
); );
} else if (this.state.view === Views.COMPLETE_SECURITY) { } else if (this.state.view === Views.COMPLETE_SECURITY) {
const CompleteSecurity = sdk.getComponent('structures.auth.CompleteSecurity');
view = ( view = (
<CompleteSecurity <CompleteSecurity
onFinished={this.onCompleteSecurityE2eSetupFinished} onFinished={this.onCompleteSecurityE2eSetupFinished}
/> />
); );
} else if (this.state.view === Views.E2E_SETUP) { } else if (this.state.view === Views.E2E_SETUP) {
const E2eSetup = sdk.getComponent('structures.auth.E2eSetup');
view = ( view = (
<E2eSetup <E2eSetup
onFinished={this.onCompleteSecurityE2eSetupFinished} onFinished={this.onCompleteSecurityE2eSetupFinished}
@ -2012,7 +2021,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
* we should go through and figure out what we actually need to pass down, as well * we should go through and figure out what we actually need to pass down, as well
* as using something like redux to avoid having a billion bits of state kicking around. * as using something like redux to avoid having a billion bits of state kicking around.
*/ */
const LoggedInView = sdk.getComponent('structures.LoggedInView');
view = ( view = (
<LoggedInView <LoggedInView
{...this.props} {...this.props}
@ -2020,14 +2028,12 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
ref={this.loggedInView} ref={this.loggedInView}
matrixClient={MatrixClientPeg.get()} matrixClient={MatrixClientPeg.get()}
onRoomCreated={this.onRoomCreated} onRoomCreated={this.onRoomCreated}
onCloseAllSettings={this.onCloseAllSettings}
onRegistered={this.onRegistered} onRegistered={this.onRegistered}
currentRoomId={this.state.currentRoomId} currentRoomId={this.state.currentRoomId}
/> />
); );
} else { } else {
// we think we are logged in, but are still waiting for the /sync to complete // we think we are logged in, but are still waiting for the /sync to complete
const Spinner = sdk.getComponent('elements.Spinner');
let errorBox; let errorBox;
if (this.state.syncError && !isStoreError) { if (this.state.syncError && !isStoreError) {
errorBox = <div className="mx_MatrixChat_syncError"> errorBox = <div className="mx_MatrixChat_syncError">
@ -2045,10 +2051,8 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
); );
} }
} else if (this.state.view === Views.WELCOME) { } else if (this.state.view === Views.WELCOME) {
const Welcome = sdk.getComponent('auth.Welcome');
view = <Welcome />; view = <Welcome />;
} else if (this.state.view === Views.REGISTER && SettingsStore.getValue(UIFeature.Registration)) { } else if (this.state.view === Views.REGISTER && SettingsStore.getValue(UIFeature.Registration)) {
const Registration = sdk.getComponent('structures.auth.Registration');
const email = ThreepidInviteStore.instance.pickBestInvite()?.toEmail; const email = ThreepidInviteStore.instance.pickBestInvite()?.toEmail;
view = ( view = (
<Registration <Registration
@ -2067,7 +2071,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
/> />
); );
} else if (this.state.view === Views.FORGOT_PASSWORD && SettingsStore.getValue(UIFeature.PasswordReset)) { } else if (this.state.view === Views.FORGOT_PASSWORD && SettingsStore.getValue(UIFeature.PasswordReset)) {
const ForgotPassword = sdk.getComponent('structures.auth.ForgotPassword');
view = ( view = (
<ForgotPassword <ForgotPassword
onComplete={this.onLoginClick} onComplete={this.onLoginClick}
@ -2078,7 +2081,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
); );
} else if (this.state.view === Views.LOGIN) { } else if (this.state.view === Views.LOGIN) {
const showPasswordReset = SettingsStore.getValue(UIFeature.PasswordReset); const showPasswordReset = SettingsStore.getValue(UIFeature.PasswordReset);
const Login = sdk.getComponent('structures.auth.Login');
view = ( view = (
<Login <Login
isSyncing={this.state.pendingInitialSync} isSyncing={this.state.pendingInitialSync}
@ -2094,7 +2096,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
/> />
); );
} else if (this.state.view === Views.SOFT_LOGOUT) { } else if (this.state.view === Views.SOFT_LOGOUT) {
const SoftLogout = sdk.getComponent('structures.auth.SoftLogout');
view = ( view = (
<SoftLogout <SoftLogout
realQueryParams={this.props.realQueryParams} realQueryParams={this.props.realQueryParams}
@ -2106,7 +2107,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
console.error(`Unknown view ${this.state.view}`); console.error(`Unknown view ${this.state.view}`);
} }
const ErrorBoundary = sdk.getComponent('elements.ErrorBoundary');
return <ErrorBoundary> return <ErrorBoundary>
{view} {view}
</ErrorBoundary>; </ErrorBoundary>;

View file

@ -34,7 +34,6 @@ import { RoomPermalinkCreator } from '../../utils/permalinks/Permalinks';
import ResizeNotifier from '../../utils/ResizeNotifier'; import ResizeNotifier from '../../utils/ResizeNotifier';
import ContentMessages from '../../ContentMessages'; import ContentMessages from '../../ContentMessages';
import Modal from '../../Modal'; import Modal from '../../Modal';
import * as sdk from '../../index';
import CallHandler, { PlaceCallType } from '../../CallHandler'; import CallHandler, { PlaceCallType } from '../../CallHandler';
import dis from '../../dispatcher/dispatcher'; import dis from '../../dispatcher/dispatcher';
import * as Rooms from '../../Rooms'; import * as Rooms from '../../Rooms';
@ -82,6 +81,14 @@ import { replaceableComponent } from "../../utils/replaceableComponent";
import UIStore from "../../stores/UIStore"; import UIStore from "../../stores/UIStore";
import EditorStateTransfer from "../../utils/EditorStateTransfer"; import EditorStateTransfer from "../../utils/EditorStateTransfer";
import { throttle } from "lodash"; import { throttle } from "lodash";
import ErrorDialog from '../views/dialogs/ErrorDialog';
import SearchResultTile from '../views/rooms/SearchResultTile';
import Spinner from "../views/elements/Spinner";
import UploadBar from './UploadBar';
import RoomStatusBar from "./RoomStatusBar";
import MessageComposer from '../views/rooms/MessageComposer';
import JumpToBottomButton from "../views/rooms/JumpToBottomButton";
import TopUnreadMessagesBar from "../views/rooms/TopUnreadMessagesBar";
const DEBUG = false; const DEBUG = false;
let debuglog = function(msg: string) {}; let debuglog = function(msg: string) {};
@ -1328,7 +1335,6 @@ export default class RoomView extends React.Component<IProps, IState> {
searchResults: results, searchResults: results,
}); });
}, (error) => { }, (error) => {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Search failed", error); console.error("Search failed", error);
Modal.createTrackedDialog('Search failed', '', ErrorDialog, { Modal.createTrackedDialog('Search failed', '', ErrorDialog, {
title: _t("Search failed"), title: _t("Search failed"),
@ -1344,9 +1350,6 @@ export default class RoomView extends React.Component<IProps, IState> {
} }
private getSearchResultTiles() { private getSearchResultTiles() {
const SearchResultTile = sdk.getComponent('rooms.SearchResultTile');
const Spinner = sdk.getComponent("elements.Spinner");
// XXX: todo: merge overlapping results somehow? // XXX: todo: merge overlapping results somehow?
// XXX: why doesn't searching on name work? // XXX: why doesn't searching on name work?
@ -1466,7 +1469,6 @@ export default class RoomView extends React.Component<IProps, IState> {
console.error("Failed to reject invite: %s", error); console.error("Failed to reject invite: %s", error);
const msg = error.message ? error.message : JSON.stringify(error); const msg = error.message ? error.message : JSON.stringify(error);
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to reject invite', '', ErrorDialog, { Modal.createTrackedDialog('Failed to reject invite', '', ErrorDialog, {
title: _t("Failed to reject invite"), title: _t("Failed to reject invite"),
description: msg, description: msg,
@ -1500,7 +1502,6 @@ export default class RoomView extends React.Component<IProps, IState> {
console.error("Failed to reject invite: %s", error); console.error("Failed to reject invite: %s", error);
const msg = error.message ? error.message : JSON.stringify(error); const msg = error.message ? error.message : JSON.stringify(error);
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to reject invite', '', ErrorDialog, { Modal.createTrackedDialog('Failed to reject invite', '', ErrorDialog, {
title: _t("Failed to reject invite"), title: _t("Failed to reject invite"),
description: msg, description: msg,
@ -1834,10 +1835,8 @@ export default class RoomView extends React.Component<IProps, IState> {
let isStatusAreaExpanded = true; let isStatusAreaExpanded = true;
if (ContentMessages.sharedInstance().getCurrentUploads().length > 0) { if (ContentMessages.sharedInstance().getCurrentUploads().length > 0) {
const UploadBar = sdk.getComponent('structures.UploadBar');
statusBar = <UploadBar room={this.state.room} />; statusBar = <UploadBar room={this.state.room} />;
} else if (!this.state.searchResults) { } else if (!this.state.searchResults) {
const RoomStatusBar = sdk.getComponent('structures.RoomStatusBar');
isStatusAreaExpanded = this.state.statusBarVisible; isStatusAreaExpanded = this.state.statusBarVisible;
statusBar = <RoomStatusBar statusBar = <RoomStatusBar
room={this.state.room} room={this.state.room}
@ -1943,12 +1942,9 @@ export default class RoomView extends React.Component<IProps, IState> {
myMembership === 'join' && !this.state.searchResults myMembership === 'join' && !this.state.searchResults
); );
if (canSpeak) { if (canSpeak) {
const MessageComposer = sdk.getComponent('rooms.MessageComposer');
messageComposer = messageComposer =
<MessageComposer <MessageComposer
room={this.state.room} room={this.state.room}
callState={this.state.callState}
showApps={this.state.showApps}
e2eStatus={this.state.e2eStatus} e2eStatus={this.state.e2eStatus}
resizeNotifier={this.props.resizeNotifier} resizeNotifier={this.props.resizeNotifier}
replyToEvent={this.state.replyToEvent} replyToEvent={this.state.replyToEvent}
@ -2034,7 +2030,6 @@ export default class RoomView extends React.Component<IProps, IState> {
let topUnreadMessagesBar = null; let topUnreadMessagesBar = null;
// Do not show TopUnreadMessagesBar if we have search results showing, it makes no sense // Do not show TopUnreadMessagesBar if we have search results showing, it makes no sense
if (this.state.showTopUnreadMessagesBar && !this.state.searchResults) { if (this.state.showTopUnreadMessagesBar && !this.state.searchResults) {
const TopUnreadMessagesBar = sdk.getComponent('rooms.TopUnreadMessagesBar');
topUnreadMessagesBar = ( topUnreadMessagesBar = (
<TopUnreadMessagesBar onScrollUpClick={this.jumpToReadMarker} onCloseClick={this.forgetReadMarker} /> <TopUnreadMessagesBar onScrollUpClick={this.jumpToReadMarker} onCloseClick={this.forgetReadMarker} />
); );
@ -2042,7 +2037,6 @@ export default class RoomView extends React.Component<IProps, IState> {
let jumpToBottom; let jumpToBottom;
// Do not show JumpToBottomButton if we have search results showing, it makes no sense // Do not show JumpToBottomButton if we have search results showing, it makes no sense
if (!this.state.atEndOfLiveTimeline && !this.state.searchResults) { if (!this.state.atEndOfLiveTimeline && !this.state.searchResults) {
const JumpToBottomButton = sdk.getComponent('rooms.JumpToBottomButton');
jumpToBottom = (<JumpToBottomButton jumpToBottom = (<JumpToBottomButton
highlight={this.state.room.getUnreadNotificationCount(NotificationCountType.Highlight) > 0} highlight={this.state.room.getUnreadNotificationCount(NotificationCountType.Highlight) > 0}
numUnreadMessages={this.state.numUnreadMessages} numUnreadMessages={this.state.numUnreadMessages}

View file

@ -18,9 +18,9 @@ limitations under the License.
import * as React from "react"; import * as React from "react";
import { _t } from '../../languageHandler'; import { _t } from '../../languageHandler';
import * as sdk from "../../index";
import AutoHideScrollbar from './AutoHideScrollbar'; import AutoHideScrollbar from './AutoHideScrollbar';
import { replaceableComponent } from "../../utils/replaceableComponent"; import { replaceableComponent } from "../../utils/replaceableComponent";
import AccessibleButton from "../views/elements/AccessibleButton";
/** /**
* Represents a tab for the TabbedView. * Represents a tab for the TabbedView.
@ -82,8 +82,6 @@ export default class TabbedView extends React.Component<IProps, IState> {
} }
private _renderTabLabel(tab: Tab) { private _renderTabLabel(tab: Tab) {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
let classes = "mx_TabbedView_tabLabel "; let classes = "mx_TabbedView_tabLabel ";
const idx = this.props.tabs.indexOf(tab); const idx = this.props.tabs.indexOf(tab);

View file

@ -32,7 +32,6 @@ import RoomContext from "../../contexts/RoomContext";
import UserActivity from "../../UserActivity"; import UserActivity from "../../UserActivity";
import Modal from "../../Modal"; import Modal from "../../Modal";
import dis from "../../dispatcher/dispatcher"; import dis from "../../dispatcher/dispatcher";
import * as sdk from "../../index";
import { Key } from '../../Keyboard'; import { Key } from '../../Keyboard';
import Timer from '../../utils/Timer'; import Timer from '../../utils/Timer';
import shouldHideEvent from '../../shouldHideEvent'; import shouldHideEvent from '../../shouldHideEvent';
@ -47,6 +46,7 @@ import ResizeNotifier from "../../utils/ResizeNotifier";
import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks"; import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks";
import Spinner from "../views/elements/Spinner"; import Spinner from "../views/elements/Spinner";
import EditorStateTransfer from '../../utils/EditorStateTransfer'; import EditorStateTransfer from '../../utils/EditorStateTransfer';
import ErrorDialog from '../views/dialogs/ErrorDialog';
const PAGINATE_SIZE = 20; const PAGINATE_SIZE = 20;
const INITIAL_SIZE = 20; const INITIAL_SIZE = 20;
@ -1096,7 +1096,6 @@ class TimelinePanel extends React.Component<IProps, IState> {
console.error( console.error(
`Error loading timeline panel at ${eventId}: ${error}`, `Error loading timeline panel at ${eventId}: ${error}`,
); );
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
let onFinished; let onFinished;

View file

@ -45,7 +45,7 @@ enum Phase {
interface IProps { interface IProps {
serverConfig: ValidatedServerConfig; serverConfig: ValidatedServerConfig;
onServerConfigChange: () => void; onServerConfigChange: (serverConfig: ValidatedServerConfig) => void;
onLoginClick?: () => void; onLoginClick?: () => void;
onComplete: () => void; onComplete: () => void;
} }

View file

@ -18,7 +18,6 @@ import React, { ReactNode } from 'react';
import { MatrixError } from "matrix-js-sdk/src/http-api"; import { MatrixError } from "matrix-js-sdk/src/http-api";
import { _t, _td } from '../../../languageHandler'; import { _t, _td } from '../../../languageHandler';
import * as sdk from '../../../index';
import Login, { ISSOFlow, LoginFlow } from '../../../Login'; import Login, { ISSOFlow, LoginFlow } from '../../../Login';
import SdkConfig from '../../../SdkConfig'; import SdkConfig from '../../../SdkConfig';
import { messageForResourceLimitError } from '../../../utils/ErrorUtils'; import { messageForResourceLimitError } from '../../../utils/ErrorUtils';
@ -36,6 +35,8 @@ import Spinner from "../../views/elements/Spinner";
import SSOButtons from "../../views/elements/SSOButtons"; import SSOButtons from "../../views/elements/SSOButtons";
import ServerPicker from "../../views/elements/ServerPicker"; import ServerPicker from "../../views/elements/ServerPicker";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import AuthBody from "../../views/auth/AuthBody";
import AuthHeader from "../../views/auth/AuthHeader";
// These are used in several places, and come from the js-sdk's autodiscovery // These are used in several places, and come from the js-sdk's autodiscovery
// stuff. We define them here so that they'll be picked up by i18n. // stuff. We define them here so that they'll be picked up by i18n.
@ -541,8 +542,6 @@ export default class LoginComponent extends React.PureComponent<IProps, IState>
}; };
render() { render() {
const AuthHeader = sdk.getComponent("auth.AuthHeader");
const AuthBody = sdk.getComponent("auth.AuthBody");
const loader = this.isBusy() && !this.state.busyLoggingIn ? const loader = this.isBusy() && !this.state.busyLoggingIn ?
<div className="mx_Login_loader"><Spinner /></div> : null; <div className="mx_Login_loader"><Spinner /></div> : null;

View file

@ -18,19 +18,24 @@ import { createClient } from 'matrix-js-sdk/src/matrix';
import React, { ReactNode } from 'react'; import React, { ReactNode } from 'react';
import { MatrixClient } from "matrix-js-sdk/src/client"; import { MatrixClient } from "matrix-js-sdk/src/client";
import * as sdk from '../../../index';
import { _t, _td } from '../../../languageHandler'; import { _t, _td } from '../../../languageHandler';
import { messageForResourceLimitError } from '../../../utils/ErrorUtils'; import { messageForResourceLimitError } from '../../../utils/ErrorUtils';
import AutoDiscoveryUtils, { ValidatedServerConfig } from "../../../utils/AutoDiscoveryUtils"; import AutoDiscoveryUtils, { ValidatedServerConfig } from "../../../utils/AutoDiscoveryUtils";
import classNames from "classnames"; import classNames from "classnames";
import * as Lifecycle from '../../../Lifecycle'; import * as Lifecycle from '../../../Lifecycle';
import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { IMatrixClientCreds, MatrixClientPeg } from "../../../MatrixClientPeg";
import AuthPage from "../../views/auth/AuthPage"; import AuthPage from "../../views/auth/AuthPage";
import Login, { ISSOFlow } from "../../../Login"; import Login, { ISSOFlow } from "../../../Login";
import dis from "../../../dispatcher/dispatcher"; import dis from "../../../dispatcher/dispatcher";
import SSOButtons from "../../views/elements/SSOButtons"; import SSOButtons from "../../views/elements/SSOButtons";
import ServerPicker from '../../views/elements/ServerPicker'; import ServerPicker from '../../views/elements/ServerPicker';
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import RegistrationForm from '../../views/auth/RegistrationForm';
import AccessibleButton from '../../views/elements/AccessibleButton';
import AuthBody from "../../views/auth/AuthBody";
import AuthHeader from "../../views/auth/AuthHeader";
import InteractiveAuth from "../InteractiveAuth";
import Spinner from "../../views/elements/Spinner";
interface IProps { interface IProps {
serverConfig: ValidatedServerConfig; serverConfig: ValidatedServerConfig;
@ -47,13 +52,7 @@ interface IProps {
// - The user's password, if available and applicable (may be cached in memory // - The user's password, if available and applicable (may be cached in memory
// for a short time so the user is not required to re-enter their password // for a short time so the user is not required to re-enter their password
// for operations like uploading cross-signing keys). // for operations like uploading cross-signing keys).
onLoggedIn(params: { onLoggedIn(params: IMatrixClientCreds, password: string): void;
userId: string;
deviceId: string;
homeserverUrl: string;
identityServerUrl?: string;
accessToken: string;
}, password: string): void;
makeRegistrationUrl(params: { makeRegistrationUrl(params: {
/* eslint-disable camelcase */ /* eslint-disable camelcase */
client_secret: string; client_secret: string;
@ -246,7 +245,7 @@ export default class Registration extends React.Component<IProps, IState> {
} }
} }
private onFormSubmit = formVals => { private onFormSubmit = async (formVals): Promise<void> => {
this.setState({ this.setState({
errorText: "", errorText: "",
busy: true, busy: true,
@ -442,10 +441,6 @@ export default class Registration extends React.Component<IProps, IState> {
}; };
private renderRegisterComponent() { private renderRegisterComponent() {
const InteractiveAuth = sdk.getComponent('structures.InteractiveAuth');
const Spinner = sdk.getComponent('elements.Spinner');
const RegistrationForm = sdk.getComponent('auth.RegistrationForm');
if (this.state.matrixClient && this.state.doingUIAuth) { if (this.state.matrixClient && this.state.doingUIAuth) {
return <InteractiveAuth return <InteractiveAuth
matrixClient={this.state.matrixClient} matrixClient={this.state.matrixClient}
@ -516,10 +511,6 @@ export default class Registration extends React.Component<IProps, IState> {
} }
render() { render() {
const AuthHeader = sdk.getComponent('auth.AuthHeader');
const AuthBody = sdk.getComponent("auth.AuthBody");
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
let errorText; let errorText;
const err = this.state.errorText; const err = this.state.errorText;
if (err) { if (err) {

View file

@ -21,7 +21,7 @@ import Modal from '../../../Modal';
import VerificationRequestDialog from '../../views/dialogs/VerificationRequestDialog'; import VerificationRequestDialog from '../../views/dialogs/VerificationRequestDialog';
import { SetupEncryptionStore, Phase } from '../../../stores/SetupEncryptionStore'; import { SetupEncryptionStore, Phase } from '../../../stores/SetupEncryptionStore';
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import { ISecretStorageKeyInfo } from 'matrix-js-sdk'; import { ISecretStorageKeyInfo } from 'matrix-js-sdk/src/crypto/api';
import EncryptionPanel from "../../views/right_panel/EncryptionPanel"; import EncryptionPanel from "../../views/right_panel/EncryptionPanel";
import AccessibleButton from '../../views/elements/AccessibleButton'; import AccessibleButton from '../../views/elements/AccessibleButton';
import Spinner from '../../views/elements/Spinner'; import Spinner from '../../views/elements/Spinner';

View file

@ -16,7 +16,6 @@ limitations under the License.
import React from 'react'; import React from 'react';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import * as sdk from '../../../index';
import dis from '../../../dispatcher/dispatcher'; import dis from '../../../dispatcher/dispatcher';
import * as Lifecycle from '../../../Lifecycle'; import * as Lifecycle from '../../../Lifecycle';
import Modal from '../../../Modal'; import Modal from '../../../Modal';
@ -26,6 +25,12 @@ import AuthPage from "../../views/auth/AuthPage";
import { SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY } from "../../../BasePlatform"; import { SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY } from "../../../BasePlatform";
import SSOButtons from "../../views/elements/SSOButtons"; import SSOButtons from "../../views/elements/SSOButtons";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import ConfirmWipeDeviceDialog from '../../views/dialogs/ConfirmWipeDeviceDialog';
import Field from '../../views/elements/Field';
import AccessibleButton from '../../views/elements/AccessibleButton';
import Spinner from "../../views/elements/Spinner";
import AuthHeader from "../../views/auth/AuthHeader";
import AuthBody from "../../views/auth/AuthBody";
const LOGIN_VIEW = { const LOGIN_VIEW = {
LOADING: 1, LOADING: 1,
@ -94,7 +99,6 @@ export default class SoftLogout extends React.Component<IProps, IState> {
} }
onClearAll = () => { onClearAll = () => {
const ConfirmWipeDeviceDialog = sdk.getComponent('dialogs.ConfirmWipeDeviceDialog');
Modal.createTrackedDialog('Clear Data', 'Soft Logout', ConfirmWipeDeviceDialog, { Modal.createTrackedDialog('Clear Data', 'Soft Logout', ConfirmWipeDeviceDialog, {
onFinished: (wipeData) => { onFinished: (wipeData) => {
if (!wipeData) return; if (!wipeData) return;
@ -202,7 +206,6 @@ export default class SoftLogout extends React.Component<IProps, IState> {
private renderSignInSection() { private renderSignInSection() {
if (this.state.loginView === LOGIN_VIEW.LOADING) { if (this.state.loginView === LOGIN_VIEW.LOADING) {
const Spinner = sdk.getComponent("elements.Spinner");
return <Spinner />; return <Spinner />;
} }
@ -214,9 +217,6 @@ export default class SoftLogout extends React.Component<IProps, IState> {
} }
if (this.state.loginView === LOGIN_VIEW.PASSWORD) { if (this.state.loginView === LOGIN_VIEW.PASSWORD) {
const Field = sdk.getComponent("elements.Field");
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
let error = null; let error = null;
if (this.state.errorText) { if (this.state.errorText) {
error = <span className='mx_Login_error'>{this.state.errorText}</span>; error = <span className='mx_Login_error'>{this.state.errorText}</span>;
@ -286,10 +286,6 @@ export default class SoftLogout extends React.Component<IProps, IState> {
} }
render() { render() {
const AuthHeader = sdk.getComponent("auth.AuthHeader");
const AuthBody = sdk.getComponent("auth.AuthBody");
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
return ( return (
<AuthPage> <AuthPage>
<AuthHeader /> <AuthHeader />

View file

@ -18,7 +18,6 @@ import React, { ChangeEvent, createRef, FormEvent, MouseEvent } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { MatrixClient } from "matrix-js-sdk/src/client"; import { MatrixClient } from "matrix-js-sdk/src/client";
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import AccessibleButton from "../elements/AccessibleButton"; import AccessibleButton from "../elements/AccessibleButton";
@ -26,6 +25,8 @@ import Spinner from "../elements/Spinner";
import CountlyAnalytics from "../../../CountlyAnalytics"; import CountlyAnalytics from "../../../CountlyAnalytics";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import { LocalisedPolicy, Policies } from '../../../Terms'; import { LocalisedPolicy, Policies } from '../../../Terms';
import Field from '../elements/Field';
import CaptchaForm from "./CaptchaForm";
/* This file contains a collection of components which are used by the /* This file contains a collection of components which are used by the
* InteractiveAuth to prompt the user to enter the information needed * InteractiveAuth to prompt the user to enter the information needed
@ -164,8 +165,7 @@ export class PasswordAuthEntry extends React.Component<IAuthEntryProps, IPasswor
let submitButtonOrSpinner; let submitButtonOrSpinner;
if (this.props.busy) { if (this.props.busy) {
const Loader = sdk.getComponent("elements.Spinner"); submitButtonOrSpinner = <Spinner />;
submitButtonOrSpinner = <Loader />;
} else { } else {
submitButtonOrSpinner = ( submitButtonOrSpinner = (
<input type="submit" <input type="submit"
@ -185,8 +185,6 @@ export class PasswordAuthEntry extends React.Component<IAuthEntryProps, IPasswor
); );
} }
const Field = sdk.getComponent('elements.Field');
return ( return (
<div> <div>
<p>{ _t("Confirm your identity by entering your account password below.") }</p> <p>{ _t("Confirm your identity by entering your account password below.") }</p>
@ -236,13 +234,11 @@ export class RecaptchaAuthEntry extends React.Component<IRecaptchaAuthEntryProps
render() { render() {
if (this.props.busy) { if (this.props.busy) {
const Loader = sdk.getComponent("elements.Spinner"); return <Spinner />;
return <Loader />;
} }
let errorText = this.props.errorText; let errorText = this.props.errorText;
const CaptchaForm = sdk.getComponent("views.auth.CaptchaForm");
let sitePublicKey; let sitePublicKey;
if (!this.props.stageParams || !this.props.stageParams.public_key) { if (!this.props.stageParams || !this.props.stageParams.public_key) {
errorText = _t( errorText = _t(
@ -390,8 +386,7 @@ export class TermsAuthEntry extends React.Component<ITermsAuthEntryProps, ITerms
render() { render() {
if (this.props.busy) { if (this.props.busy) {
const Loader = sdk.getComponent("elements.Spinner"); return <Spinner />;
return <Loader />;
} }
const checkboxes = []; const checkboxes = [];
@ -590,8 +585,7 @@ export class MsisdnAuthEntry extends React.Component<IMsisdnAuthEntryProps, IMsi
render() { render() {
if (this.state.requestingToken) { if (this.state.requestingToken) {
const Loader = sdk.getComponent("elements.Spinner"); return <Spinner />;
return <Loader />;
} else { } else {
const enableSubmit = Boolean(this.state.token); const enableSubmit = Boolean(this.state.token);
const submitClasses = classNames({ const submitClasses = classNames({

View file

@ -17,7 +17,6 @@ limitations under the License.
import React from 'react'; import React from 'react';
import * as sdk from '../../../index';
import * as Email from '../../../email'; import * as Email from '../../../email';
import { looksValid as phoneNumberLooksValid } from '../../../phonenumber'; import { looksValid as phoneNumberLooksValid } from '../../../phonenumber';
import Modal from '../../../Modal'; import Modal from '../../../Modal';
@ -31,6 +30,7 @@ import CountlyAnalytics from "../../../CountlyAnalytics";
import Field from '../elements/Field'; import Field from '../elements/Field';
import RegistrationEmailPromptDialog from '../dialogs/RegistrationEmailPromptDialog'; import RegistrationEmailPromptDialog from '../dialogs/RegistrationEmailPromptDialog';
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import CountryDropdown from "./CountryDropdown";
enum RegistrationField { enum RegistrationField {
Email = "field_email", Email = "field_email",
@ -471,7 +471,6 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
if (!this.showPhoneNumber()) { if (!this.showPhoneNumber()) {
return null; return null;
} }
const CountryDropdown = sdk.getComponent('views.auth.CountryDropdown');
const phoneLabel = this.authStepIsRequired('m.login.msisdn') ? const phoneLabel = this.authStepIsRequired('m.login.msisdn') ?
_t("Phone") : _t("Phone") :
_t("Phone (optional)"); _t("Phone (optional)");

View file

@ -1,6 +1,6 @@
/* /*
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
Copyright 2015, 2016, 2018, 2019, 2021 The Matrix.org Foundation C.I.C. Copyright 2015 - 2021 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -16,12 +16,11 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import { EventStatus, MatrixEvent } from 'matrix-js-sdk/src/models/event';
import { EventStatus } from 'matrix-js-sdk/src/models/event'; import { EventType, RelationType } from "matrix-js-sdk/src/@types/event";
import { MatrixClientPeg } from '../../../MatrixClientPeg'; import { MatrixClientPeg } from '../../../MatrixClientPeg';
import dis from '../../../dispatcher/dispatcher'; import dis from '../../../dispatcher/dispatcher';
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import Modal from '../../../Modal'; import Modal from '../../../Modal';
import Resend from '../../../Resend'; import Resend from '../../../Resend';
@ -29,53 +28,65 @@ import SettingsStore from '../../../settings/SettingsStore';
import { isUrlPermitted } from '../../../HtmlUtils'; import { isUrlPermitted } from '../../../HtmlUtils';
import { isContentActionable } from '../../../utils/EventUtils'; import { isContentActionable } from '../../../utils/EventUtils';
import IconizedContextMenu, { IconizedContextMenuOption, IconizedContextMenuOptionList } from './IconizedContextMenu'; import IconizedContextMenu, { IconizedContextMenuOption, IconizedContextMenuOptionList } from './IconizedContextMenu';
import { EventType } from "matrix-js-sdk/src/@types/event";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import { ReadPinsEventId } from "../right_panel/PinnedMessagesCard"; import { ReadPinsEventId } from "../right_panel/PinnedMessagesCard";
import ForwardDialog from "../dialogs/ForwardDialog"; import ForwardDialog from "../dialogs/ForwardDialog";
import { Action } from "../../../dispatcher/actions"; import { Action } from "../../../dispatcher/actions";
import ReportEventDialog from '../dialogs/ReportEventDialog';
import ViewSource from '../../structures/ViewSource';
import ConfirmRedactDialog from '../dialogs/ConfirmRedactDialog';
import ErrorDialog from '../dialogs/ErrorDialog';
import ShareDialog from '../dialogs/ShareDialog';
import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks";
export function canCancel(eventStatus) { export function canCancel(eventStatus: EventStatus): boolean {
return eventStatus === EventStatus.QUEUED || eventStatus === EventStatus.NOT_SENT; return eventStatus === EventStatus.QUEUED || eventStatus === EventStatus.NOT_SENT;
} }
@replaceableComponent("views.context_menus.MessageContextMenu") interface IEventTileOps {
export default class MessageContextMenu extends React.Component { isWidgetHidden(): boolean;
static propTypes = { unhideWidget(): void;
}
interface IProps {
/* the MatrixEvent associated with the context menu */ /* the MatrixEvent associated with the context menu */
mxEvent: PropTypes.object.isRequired, mxEvent: MatrixEvent;
/* an optional EventTileOps implementation that can be used to unhide preview widgets */ /* an optional EventTileOps implementation that can be used to unhide preview widgets */
eventTileOps: PropTypes.object, eventTileOps?: IEventTileOps;
permalinkCreator?: RoomPermalinkCreator;
/* an optional function to be called when the user clicks collapse thread, if not provided hide button */ /* an optional function to be called when the user clicks collapse thread, if not provided hide button */
collapseReplyThread: PropTypes.func, collapseReplyThread?(): void;
/* callback called when the menu is dismissed */ /* callback called when the menu is dismissed */
onFinished: PropTypes.func, onFinished(): void;
/* if the menu is inside a dialog, we sometimes need to close that dialog after click (forwarding) */ /* if the menu is inside a dialog, we sometimes need to close that dialog after click (forwarding) */
onCloseDialog: PropTypes.func, onCloseDialog?(): void;
}; }
interface IState {
canRedact: boolean;
canPin: boolean;
}
@replaceableComponent("views.context_menus.MessageContextMenu")
export default class MessageContextMenu extends React.Component<IProps, IState> {
state = { state = {
canRedact: false, canRedact: false,
canPin: false, canPin: false,
}; };
componentDidMount() { componentDidMount() {
MatrixClientPeg.get().on('RoomMember.powerLevel', this._checkPermissions); MatrixClientPeg.get().on('RoomMember.powerLevel', this.checkPermissions);
this._checkPermissions(); this.checkPermissions();
} }
componentWillUnmount() { componentWillUnmount() {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
if (cli) { if (cli) {
cli.removeListener('RoomMember.powerLevel', this._checkPermissions); cli.removeListener('RoomMember.powerLevel', this.checkPermissions);
} }
} }
_checkPermissions = () => { private checkPermissions = (): void => {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
const room = cli.getRoom(this.props.mxEvent.getRoomId()); const room = cli.getRoom(this.props.mxEvent.getRoomId());
@ -93,7 +104,7 @@ export default class MessageContextMenu extends React.Component {
this.setState({ canRedact, canPin }); this.setState({ canRedact, canPin });
}; };
_isPinned() { private isPinned(): boolean {
const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId()); const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId());
const pinnedEvent = room.currentState.getStateEvents(EventType.RoomPinnedEvents, ''); const pinnedEvent = room.currentState.getStateEvents(EventType.RoomPinnedEvents, '');
if (!pinnedEvent) return false; if (!pinnedEvent) return false;
@ -101,38 +112,35 @@ export default class MessageContextMenu extends React.Component {
return content.pinned && Array.isArray(content.pinned) && content.pinned.includes(this.props.mxEvent.getId()); return content.pinned && Array.isArray(content.pinned) && content.pinned.includes(this.props.mxEvent.getId());
} }
onResendReactionsClick = () => { private onResendReactionsClick = (): void => {
for (const reaction of this._getUnsentReactions()) { for (const reaction of this.getUnsentReactions()) {
Resend.resend(reaction); Resend.resend(reaction);
} }
this.closeMenu(); this.closeMenu();
}; };
onReportEventClick = () => { private onReportEventClick = (): void => {
const ReportEventDialog = sdk.getComponent("dialogs.ReportEventDialog");
Modal.createTrackedDialog('Report Event', '', ReportEventDialog, { Modal.createTrackedDialog('Report Event', '', ReportEventDialog, {
mxEvent: this.props.mxEvent, mxEvent: this.props.mxEvent,
}, 'mx_Dialog_reportEvent'); }, 'mx_Dialog_reportEvent');
this.closeMenu(); this.closeMenu();
}; };
onViewSourceClick = () => { private onViewSourceClick = (): void => {
const ViewSource = sdk.getComponent('structures.ViewSource');
Modal.createTrackedDialog('View Event Source', '', ViewSource, { Modal.createTrackedDialog('View Event Source', '', ViewSource, {
mxEvent: this.props.mxEvent, mxEvent: this.props.mxEvent,
}, 'mx_Dialog_viewsource'); }, 'mx_Dialog_viewsource');
this.closeMenu(); this.closeMenu();
}; };
onRedactClick = () => { private onRedactClick = (): void => {
const ConfirmRedactDialog = sdk.getComponent("dialogs.ConfirmRedactDialog");
Modal.createTrackedDialog('Confirm Redact Dialog', '', ConfirmRedactDialog, { Modal.createTrackedDialog('Confirm Redact Dialog', '', ConfirmRedactDialog, {
onFinished: async (proceed, reason) => { onFinished: async (proceed: boolean, reason?: string) => {
if (!proceed) return; if (!proceed) return;
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
try { try {
if (this.props.onCloseDialog) this.props.onCloseDialog(); this.props.onCloseDialog?.();
await cli.redactEvent( await cli.redactEvent(
this.props.mxEvent.getRoomId(), this.props.mxEvent.getRoomId(),
this.props.mxEvent.getId(), this.props.mxEvent.getId(),
@ -145,7 +153,6 @@ export default class MessageContextMenu extends React.Component {
// (e.g. no errcode or statusCode) as in that case the redactions end up in the // (e.g. no errcode or statusCode) as in that case the redactions end up in the
// detached queue and we show the room status bar to allow retry // detached queue and we show the room status bar to allow retry
if (typeof code !== "undefined") { if (typeof code !== "undefined") {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
// display error message stating you couldn't delete this. // display error message stating you couldn't delete this.
Modal.createTrackedDialog('You cannot delete this message', '', ErrorDialog, { Modal.createTrackedDialog('You cannot delete this message', '', ErrorDialog, {
title: _t('Error'), title: _t('Error'),
@ -158,7 +165,7 @@ export default class MessageContextMenu extends React.Component {
this.closeMenu(); this.closeMenu();
}; };
onForwardClick = () => { private onForwardClick = (): void => {
Modal.createTrackedDialog('Forward Message', '', ForwardDialog, { Modal.createTrackedDialog('Forward Message', '', ForwardDialog, {
matrixClient: MatrixClientPeg.get(), matrixClient: MatrixClientPeg.get(),
event: this.props.mxEvent, event: this.props.mxEvent,
@ -167,12 +174,12 @@ export default class MessageContextMenu extends React.Component {
this.closeMenu(); this.closeMenu();
}; };
onPinClick = () => { private onPinClick = (): void => {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
const room = cli.getRoom(this.props.mxEvent.getRoomId()); const room = cli.getRoom(this.props.mxEvent.getRoomId());
const eventId = this.props.mxEvent.getId(); const eventId = this.props.mxEvent.getId();
const pinnedIds = room?.currentState?.getStateEvents(EventType.RoomPinnedEvents, "")?.pinned || []; const pinnedIds = room?.currentState?.getStateEvents(EventType.RoomPinnedEvents, "")?.getContent().pinned || [];
if (pinnedIds.includes(eventId)) { if (pinnedIds.includes(eventId)) {
pinnedIds.splice(pinnedIds.indexOf(eventId), 1); pinnedIds.splice(pinnedIds.indexOf(eventId), 1);
} else { } else {
@ -188,18 +195,16 @@ export default class MessageContextMenu extends React.Component {
this.closeMenu(); this.closeMenu();
}; };
closeMenu = () => { private closeMenu = (): void => {
if (this.props.onFinished) this.props.onFinished(); this.props.onFinished();
}; };
onUnhidePreviewClick = () => { private onUnhidePreviewClick = (): void => {
if (this.props.eventTileOps) { this.props.eventTileOps?.unhideWidget();
this.props.eventTileOps.unhideWidget();
}
this.closeMenu(); this.closeMenu();
}; };
onQuoteClick = () => { private onQuoteClick = (): void => {
dis.dispatch({ dis.dispatch({
action: Action.ComposerInsert, action: Action.ComposerInsert,
event: this.props.mxEvent, event: this.props.mxEvent,
@ -207,9 +212,8 @@ export default class MessageContextMenu extends React.Component {
this.closeMenu(); this.closeMenu();
}; };
onPermalinkClick = (e) => { private onPermalinkClick = (e: React.MouseEvent): void => {
e.preventDefault(); e.preventDefault();
const ShareDialog = sdk.getComponent("dialogs.ShareDialog");
Modal.createTrackedDialog('share room message dialog', '', ShareDialog, { Modal.createTrackedDialog('share room message dialog', '', ShareDialog, {
target: this.props.mxEvent, target: this.props.mxEvent,
permalinkCreator: this.props.permalinkCreator, permalinkCreator: this.props.permalinkCreator,
@ -217,30 +221,27 @@ export default class MessageContextMenu extends React.Component {
this.closeMenu(); this.closeMenu();
}; };
onCollapseReplyThreadClick = () => { private onCollapseReplyThreadClick = (): void => {
this.props.collapseReplyThread(); this.props.collapseReplyThread();
this.closeMenu(); this.closeMenu();
}; };
_getReactions(filter) { private getReactions(filter: (e: MatrixEvent) => boolean): MatrixEvent[] {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
const room = cli.getRoom(this.props.mxEvent.getRoomId()); const room = cli.getRoom(this.props.mxEvent.getRoomId());
const eventId = this.props.mxEvent.getId(); const eventId = this.props.mxEvent.getId();
return room.getPendingEvents().filter(e => { return room.getPendingEvents().filter(e => {
const relation = e.getRelation(); const relation = e.getRelation();
return relation && return relation?.rel_type === RelationType.Annotation && relation.event_id === eventId && filter(e);
relation.rel_type === "m.annotation" &&
relation.event_id === eventId &&
filter(e);
}); });
} }
_getPendingReactions() { private getPendingReactions(): MatrixEvent[] {
return this._getReactions(e => canCancel(e.status)); return this.getReactions(e => canCancel(e.status));
} }
_getUnsentReactions() { private getUnsentReactions(): MatrixEvent[] {
return this._getReactions(e => e.status === EventStatus.NOT_SENT); return this.getReactions(e => e.status === EventStatus.NOT_SENT);
} }
render() { render() {
@ -248,16 +249,17 @@ export default class MessageContextMenu extends React.Component {
const me = cli.getUserId(); const me = cli.getUserId();
const mxEvent = this.props.mxEvent; const mxEvent = this.props.mxEvent;
const eventStatus = mxEvent.status; const eventStatus = mxEvent.status;
const unsentReactionsCount = this._getUnsentReactions().length; const unsentReactionsCount = this.getUnsentReactions().length;
let resendReactionsButton;
let redactButton; let resendReactionsButton: JSX.Element;
let forwardButton; let redactButton: JSX.Element;
let pinButton; let forwardButton: JSX.Element;
let unhidePreviewButton; let pinButton: JSX.Element;
let externalURLButton; let unhidePreviewButton: JSX.Element;
let quoteButton; let externalURLButton: JSX.Element;
let collapseReplyThread; let quoteButton: JSX.Element;
let redactItemList; let collapseReplyThread: JSX.Element;
let redactItemList: JSX.Element;
// status is SENT before remote-echo, null after // status is SENT before remote-echo, null after
const isSent = !eventStatus || eventStatus === EventStatus.SENT; const isSent = !eventStatus || eventStatus === EventStatus.SENT;
@ -296,7 +298,7 @@ export default class MessageContextMenu extends React.Component {
pinButton = ( pinButton = (
<IconizedContextMenuOption <IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_iconPin" iconClassName="mx_MessageContextMenu_iconPin"
label={ this._isPinned() ? _t('Unpin') : _t('Pin') } label={ this.isPinned() ? _t('Unpin') : _t('Pin') }
onClick={this.onPinClick} onClick={this.onPinClick}
/> />
); );
@ -327,16 +329,20 @@ export default class MessageContextMenu extends React.Component {
if (this.props.permalinkCreator) { if (this.props.permalinkCreator) {
permalink = this.props.permalinkCreator.forEvent(this.props.mxEvent.getId()); permalink = this.props.permalinkCreator.forEvent(this.props.mxEvent.getId());
} }
// XXX: if we use room ID, we should also include a server where the event can be found (other than in the domain of the event ID)
const permalinkButton = ( const permalinkButton = (
<IconizedContextMenuOption <IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_iconPermalink" iconClassName="mx_MessageContextMenu_iconPermalink"
onClick={this.onPermalinkClick} onClick={this.onPermalinkClick}
label= {_t('Share')} label= {_t('Share')}
element="a" element="a"
href={permalink} {
target="_blank" // XXX: Typescript signature for AccessibleButton doesn't work properly for non-inputs like `a`
rel="noreferrer noopener" ...{
href: permalink,
target: "_blank",
rel: "noreferrer noopener",
}
}
/> />
); );
@ -351,8 +357,8 @@ export default class MessageContextMenu extends React.Component {
} }
// Bridges can provide a 'external_url' to link back to the source. // Bridges can provide a 'external_url' to link back to the source.
if (typeof (mxEvent.event.content.external_url) === "string" && if (typeof (mxEvent.getContent().external_url) === "string" &&
isUrlPermitted(mxEvent.event.content.external_url) isUrlPermitted(mxEvent.getContent().external_url)
) { ) {
externalURLButton = ( externalURLButton = (
<IconizedContextMenuOption <IconizedContextMenuOption
@ -360,9 +366,14 @@ export default class MessageContextMenu extends React.Component {
onClick={this.closeMenu} onClick={this.closeMenu}
label={ _t('Source URL') } label={ _t('Source URL') }
element="a" element="a"
target="_blank" {
rel="noreferrer noopener" // XXX: Typescript signature for AccessibleButton doesn't work properly for non-inputs like `a`
href={mxEvent.event.content.external_url} ...{
target: "_blank",
rel: "noreferrer noopener",
href: mxEvent.getContent().external_url,
}
}
/> />
); );
} }
@ -377,7 +388,7 @@ export default class MessageContextMenu extends React.Component {
); );
} }
let reportEventButton; let reportEventButton: JSX.Element;
if (mxEvent.getSender() !== me) { if (mxEvent.getSender() !== me) {
reportEventButton = ( reportEventButton = (
<IconizedContextMenuOption <IconizedContextMenuOption

View file

@ -15,11 +15,11 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import { SettingLevel } from "../../../settings/SettingLevel"; import { SettingLevel } from "../../../settings/SettingLevel";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import BaseDialog from "./BaseDialog";
interface IProps { interface IProps {
unknownProfileUsers: Array<{ unknownProfileUsers: Array<{
@ -50,8 +50,6 @@ export default class AskInviteAnywayDialog extends React.Component<IProps> {
}; };
public render() { public render() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const errorList = this.props.unknownProfileUsers const errorList = this.props.unknownProfileUsers
.map(address => <li key={address.userId}>{address.userId}: {address.errorText}</li>); .map(address => <li key={address.userId}>{address.userId}: {address.errorText}</li>);

View file

@ -18,13 +18,17 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import * as sdk from '../../../index';
import SdkConfig from '../../../SdkConfig'; import SdkConfig from '../../../SdkConfig';
import Modal from '../../../Modal'; import Modal from '../../../Modal';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import sendBugReport, { downloadBugReport } from '../../../rageshake/submit-rageshake'; import sendBugReport, { downloadBugReport } from '../../../rageshake/submit-rageshake';
import AccessibleButton from "../elements/AccessibleButton"; import AccessibleButton from "../elements/AccessibleButton";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import QuestionDialog from "./QuestionDialog";
import BaseDialog from "./BaseDialog";
import Field from '../elements/Field';
import Spinner from "../elements/Spinner";
import DialogButtons from "../elements/DialogButtons";
interface IProps { interface IProps {
onFinished: (success: boolean) => void; onFinished: (success: boolean) => void;
@ -93,7 +97,6 @@ export default class BugReportDialog extends React.Component<IProps, IState> {
}).then(() => { }).then(() => {
if (!this.unmounted) { if (!this.unmounted) {
this.props.onFinished(false); this.props.onFinished(false);
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
// N.B. first param is passed to piwik and so doesn't want i18n // N.B. first param is passed to piwik and so doesn't want i18n
Modal.createTrackedDialog('Bug report sent', '', QuestionDialog, { Modal.createTrackedDialog('Bug report sent', '', QuestionDialog, {
title: _t('Logs sent'), title: _t('Logs sent'),
@ -160,11 +163,6 @@ export default class BugReportDialog extends React.Component<IProps, IState> {
}; };
public render() { public render() {
const Loader = sdk.getComponent("elements.Spinner");
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
const Field = sdk.getComponent('elements.Field');
let error = null; let error = null;
if (this.state.err) { if (this.state.err) {
error = <div className="error"> error = <div className="error">
@ -176,7 +174,7 @@ export default class BugReportDialog extends React.Component<IProps, IState> {
if (this.state.busy) { if (this.state.busy) {
progress = ( progress = (
<div className="progress"> <div className="progress">
<Loader /> <Spinner />
{this.state.progress} ... {this.state.progress} ...
</div> </div>
); );

View file

@ -16,9 +16,10 @@ Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
*/ */
import React from 'react'; import React from 'react';
import * as sdk from '../../../index';
import request from 'browser-request'; import request from 'browser-request';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import QuestionDialog from "./QuestionDialog";
import Spinner from "../elements/Spinner";
interface IProps { interface IProps {
newVersion: string; newVersion: string;
@ -65,9 +66,6 @@ export default class ChangelogDialog extends React.Component<IProps> {
} }
public render() { public render() {
const Spinner = sdk.getComponent('views.elements.Spinner');
const QuestionDialog = sdk.getComponent('dialogs.QuestionDialog');
const logs = REPOS.map(repo => { const logs = REPOS.map(repo => {
let content; let content;
if (this.state[repo] == null) { if (this.state[repo] == null) {

View file

@ -15,9 +15,12 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import ConfirmRedactDialog from './ConfirmRedactDialog';
import ErrorDialog from './ErrorDialog';
import BaseDialog from "./BaseDialog";
import Spinner from "../elements/Spinner";
interface IProps { interface IProps {
redact: () => Promise<void>; redact: () => Promise<void>;
@ -73,7 +76,6 @@ export default class ConfirmAndWaitRedactDialog extends React.PureComponent<IPro
public render() { public render() {
if (this.state.isRedacting) { if (this.state.isRedacting) {
if (this.state.redactionErrorCode) { if (this.state.redactionErrorCode) {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
const code = this.state.redactionErrorCode; const code = this.state.redactionErrorCode;
return ( return (
<ErrorDialog <ErrorDialog
@ -83,8 +85,6 @@ export default class ConfirmAndWaitRedactDialog extends React.PureComponent<IPro
/> />
); );
} else { } else {
const BaseDialog = sdk.getComponent("dialogs.BaseDialog");
const Spinner = sdk.getComponent('elements.Spinner');
return ( return (
<BaseDialog <BaseDialog
onFinished={this.props.onFinished} onFinished={this.props.onFinished}
@ -95,7 +95,6 @@ export default class ConfirmAndWaitRedactDialog extends React.PureComponent<IPro
); );
} }
} else { } else {
const ConfirmRedactDialog = sdk.getComponent("dialogs.ConfirmRedactDialog");
return <ConfirmRedactDialog onFinished={this.onParentFinished} />; return <ConfirmRedactDialog onFinished={this.onParentFinished} />;
} }
} }

View file

@ -15,9 +15,9 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import TextInputDialog from "./TextInputDialog";
interface IProps { interface IProps {
onFinished: (success: boolean) => void; onFinished: (success: boolean) => void;
@ -29,7 +29,6 @@ interface IProps {
@replaceableComponent("views.dialogs.ConfirmRedactDialog") @replaceableComponent("views.dialogs.ConfirmRedactDialog")
export default class ConfirmRedactDialog extends React.Component<IProps> { export default class ConfirmRedactDialog extends React.Component<IProps> {
render() { render() {
const TextInputDialog = sdk.getComponent('views.dialogs.TextInputDialog');
return ( return (
<TextInputDialog onFinished={this.props.onFinished} <TextInputDialog onFinished={this.props.onFinished}
title={_t("Confirm Removal")} title={_t("Confirm Removal")}

View file

@ -17,11 +17,14 @@ limitations under the License.
import React from 'react'; import React from 'react';
import { MatrixClient } from 'matrix-js-sdk/src/client'; import { MatrixClient } from 'matrix-js-sdk/src/client';
import { RoomMember } from "matrix-js-sdk/src/models/room-member"; import { RoomMember } from "matrix-js-sdk/src/models/room-member";
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import { GroupMemberType } from '../../../groups'; import { GroupMemberType } from '../../../groups';
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import { mediaFromMxc } from "../../../customisations/Media"; import { mediaFromMxc } from "../../../customisations/Media";
import MemberAvatar from '../avatars/MemberAvatar';
import BaseAvatar from '../avatars/BaseAvatar';
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
interface IProps { interface IProps {
// matrix-js-sdk (room) member object. Supply either this or 'groupMember' // matrix-js-sdk (room) member object. Supply either this or 'groupMember'
@ -67,11 +70,6 @@ export default class ConfirmUserActionDialog extends React.Component<IProps> {
}; };
public render() { public render() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
const MemberAvatar = sdk.getComponent("views.avatars.MemberAvatar");
const BaseAvatar = sdk.getComponent("views.avatars.BaseAvatar");
const confirmButtonClass = this.props.danger ? 'danger' : ''; const confirmButtonClass = this.props.danger ? 'danger' : '';
let reasonBox; let reasonBox;

View file

@ -16,8 +16,9 @@ limitations under the License.
import React from 'react'; import React from 'react';
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
import * as sdk from "../../../index";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
interface IProps { interface IProps {
onFinished: (success: boolean) => void; onFinished: (success: boolean) => void;
@ -34,9 +35,6 @@ export default class ConfirmWipeDeviceDialog extends React.Component<IProps> {
}; };
render() { render() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
return ( return (
<BaseDialog <BaseDialog
className='mx_ConfirmWipeDeviceDialog' className='mx_ConfirmWipeDeviceDialog'

View file

@ -15,11 +15,12 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import * as sdk from '../../../index';
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';
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import BaseDialog from "./BaseDialog";
import Spinner from "../elements/Spinner";
interface IProps { interface IProps {
onFinished: (success: boolean) => void; onFinished: (success: boolean) => void;
@ -106,9 +107,6 @@ export default class CreateGroupDialog extends React.Component<IProps, IState> {
}; };
render() { render() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const Spinner = sdk.getComponent('elements.Spinner');
if (this.state.creating) { if (this.state.creating) {
return <Spinner />; return <Spinner />;
} }

View file

@ -16,21 +16,22 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import * as sdk from '../../../index';
import dis from '../../../dispatcher/dispatcher'; import dis from '../../../dispatcher/dispatcher';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import SdkConfig from '../../../SdkConfig'; import SdkConfig from '../../../SdkConfig';
import Modal from '../../../Modal'; import Modal from '../../../Modal';
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
import QuestionDialog from "./QuestionDialog";
interface IProps { interface IProps {
onFinished: (success: boolean) => void; onFinished: (success: boolean) => void;
} }
export default (props: IProps) => { const CryptoStoreTooNewDialog: React.FC<IProps> = (props: IProps) => {
const brand = SdkConfig.get().brand; const brand = SdkConfig.get().brand;
const _onLogoutClicked = () => { const _onLogoutClicked = () => {
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
Modal.createTrackedDialog('Logout e2e db too new', '', QuestionDialog, { Modal.createTrackedDialog('Logout e2e db too new', '', QuestionDialog, {
title: _t("Sign out"), title: _t("Sign out"),
description: _t( description: _t(
@ -58,8 +59,6 @@ export default (props: IProps) => {
{ brand }, { brand },
); );
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
return (<BaseDialog className="mx_CryptoStoreTooNewDialog" return (<BaseDialog className="mx_CryptoStoreTooNewDialog"
contentId='mx_Dialog_content' contentId='mx_Dialog_content'
title={_t("Incompatible Database")} title={_t("Incompatible Database")}
@ -79,3 +78,5 @@ export default (props: IProps) => {
</DialogButtons> </DialogButtons>
</BaseDialog>); </BaseDialog>);
}; };
export default CryptoStoreTooNewDialog;

View file

@ -17,7 +17,6 @@ limitations under the License.
import React from 'react'; import React from 'react';
import * as sdk from '../../../index';
import Analytics from '../../../Analytics'; import Analytics from '../../../Analytics';
import { MatrixClientPeg } from '../../../MatrixClientPeg'; import { MatrixClientPeg } from '../../../MatrixClientPeg';
import * as Lifecycle from '../../../Lifecycle'; import * as Lifecycle from '../../../Lifecycle';
@ -26,6 +25,7 @@ import InteractiveAuth, { ERROR_USER_CANCELLED } from "../../structures/Interact
import { DEFAULT_PHASE, PasswordAuthEntry, SSOAuthEntry } from "../auth/InteractiveAuthEntryComponents"; import { DEFAULT_PHASE, PasswordAuthEntry, SSOAuthEntry } from "../auth/InteractiveAuthEntryComponents";
import StyledCheckbox from "../elements/StyledCheckbox"; import StyledCheckbox from "../elements/StyledCheckbox";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import BaseDialog from "./BaseDialog";
interface IProps { interface IProps {
onFinished: (success: boolean) => void; onFinished: (success: boolean) => void;
@ -165,8 +165,6 @@ export default class DeactivateAccountDialog extends React.Component<IProps, ISt
} }
public render() { public render() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
let error = null; let error = null;
if (this.state.errStr) { if (this.state.errStr) {
error = <div className="error"> error = <div className="error">

View file

@ -16,7 +16,6 @@ limitations under the License.
*/ */
import React, { useState, useEffect, ChangeEvent, MouseEvent } from 'react'; import React, { useState, useEffect, ChangeEvent, MouseEvent } from 'react';
import * as sdk from '../../../index';
import SyntaxHighlight from '../elements/SyntaxHighlight'; import SyntaxHighlight from '../elements/SyntaxHighlight';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import Field from "../elements/Field"; import Field from "../elements/Field";
@ -42,6 +41,8 @@ import { replaceableComponent } from "../../../utils/replaceableComponent";
import { Room } from "matrix-js-sdk/src/models/room"; import { Room } from "matrix-js-sdk/src/models/room";
import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { SettingLevel } from '../../../settings/SettingLevel'; import { SettingLevel } from '../../../settings/SettingLevel';
import BaseDialog from "./BaseDialog";
import TruncatedList from "../elements/TruncatedList";
interface IGenericEditorProps { interface IGenericEditorProps {
onBack: () => void; onBack: () => void;
@ -369,7 +370,6 @@ class FilteredList extends React.PureComponent<IFilteredListProps, IFilteredList
}; };
render() { render() {
const TruncatedList = sdk.getComponent("elements.TruncatedList");
return <div> return <div>
<Field label={_t('Filter results')} autoFocus={true} size={64} <Field label={_t('Filter results')} autoFocus={true} size={64}
type="text" autoComplete="off" value={this.props.query} onChange={this.onQuery} type="text" autoComplete="off" value={this.props.query} onChange={this.onQuery}
@ -1261,7 +1261,6 @@ export default class DevtoolsDialog extends React.PureComponent<IProps, IState>
</React.Fragment>; </React.Fragment>;
} }
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
return ( return (
<BaseDialog className="mx_QuestionDialog" onFinished={this.props.onFinished} title={_t('Developer Tools')}> <BaseDialog className="mx_QuestionDialog" onFinished={this.props.onFinished} title={_t('Developer Tools')}>
{ body } { body }

View file

@ -26,9 +26,9 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import BaseDialog from "./BaseDialog";
interface IProps { interface IProps {
onFinished: (success: boolean) => void; onFinished: (success: boolean) => void;
@ -57,7 +57,6 @@ export default class ErrorDialog extends React.Component<IProps, IState> {
}; };
public render() { public render() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
return ( return (
<BaseDialog <BaseDialog
className="mx_ErrorDialog" className="mx_ErrorDialog"

View file

@ -18,7 +18,6 @@ import React, { createRef } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { _t, _td } from "../../../languageHandler"; import { _t, _td } from "../../../languageHandler";
import * as sdk from "../../../index";
import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { MatrixClientPeg } from "../../../MatrixClientPeg";
import { makeRoomPermalink, makeUserPermalink } from "../../../utils/permalinks/Permalinks"; import { makeRoomPermalink, makeUserPermalink } from "../../../utils/permalinks/Permalinks";
import DMRoomMap from "../../../utils/DMRoomMap"; import DMRoomMap from "../../../utils/DMRoomMap";
@ -65,6 +64,9 @@ import { copyPlaintext, selectText } from "../../../utils/strings";
import * as ContextMenu from "../../structures/ContextMenu"; import * as ContextMenu from "../../structures/ContextMenu";
import { toRightOf } from "../../structures/ContextMenu"; import { toRightOf } from "../../structures/ContextMenu";
import GenericTextContextMenu from "../context_menus/GenericTextContextMenu"; import GenericTextContextMenu from "../context_menus/GenericTextContextMenu";
import QuestionDialog from "./QuestionDialog";
import Spinner from "../elements/Spinner";
import BaseDialog from "./BaseDialog";
// we have a number of types defined from the Matrix spec which can't reasonably be altered here. // we have a number of types defined from the Matrix spec which can't reasonably be altered here.
/* eslint-disable camelcase */ /* eslint-disable camelcase */
@ -1046,7 +1048,6 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
if (this.unmounted) return; if (this.unmounted) return;
if (failed.length > 0) { if (failed.length > 0) {
const QuestionDialog = sdk.getComponent('dialogs.QuestionDialog');
Modal.createTrackedDialog('Invite Paste Fail', '', QuestionDialog, { Modal.createTrackedDialog('Invite Paste Fail', '', QuestionDialog, {
title: _t('Failed to find the following users'), title: _t('Failed to find the following users'),
description: _t( description: _t(
@ -1158,7 +1159,6 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
const toRender = sourceMembers.slice(0, showNum); const toRender = sourceMembers.slice(0, showNum);
const hasMore = toRender.length < sourceMembers.length; const hasMore = toRender.length < sourceMembers.length;
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
let showMore = null; let showMore = null;
if (hasMore) { if (hasMore) {
showMore = ( showMore = (
@ -1269,10 +1269,6 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
}; };
render() { render() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
const Spinner = sdk.getComponent("elements.Spinner");
let spinner = null; let spinner = null;
if (this.state.busy) { if (this.state.busy) {
spinner = <Spinner w={20} h={20} />; spinner = <Spinner w={20} h={20} />;

View file

@ -15,7 +15,6 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import { ensureDMExists } from "../../../createRoom"; import { ensureDMExists } from "../../../createRoom";
import { IDialogProps } from "./IDialogProps"; import { IDialogProps } from "./IDialogProps";
@ -26,6 +25,10 @@ import Markdown from '../../../Markdown';
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import StyledRadioButton from "../elements/StyledRadioButton"; import StyledRadioButton from "../elements/StyledRadioButton";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
import Field from "../elements/Field";
import Spinner from "../elements/Spinner";
interface IProps extends IDialogProps { interface IProps extends IDialogProps {
mxEvent: MatrixEvent; mxEvent: MatrixEvent;
@ -239,11 +242,6 @@ export default class ReportEventDialog extends React.Component<IProps, IState> {
}; };
render() { render() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
const Loader = sdk.getComponent('elements.Spinner');
const Field = sdk.getComponent('elements.Field');
let error = null; let error = null;
if (this.state.err) { if (this.state.err) {
error = <div className="error"> error = <div className="error">
@ -255,7 +253,7 @@ export default class ReportEventDialog extends React.Component<IProps, IState> {
if (this.state.busy) { if (this.state.busy) {
progress = ( progress = (
<div className="progress"> <div className="progress">
<Loader /> <Spinner />
</div> </div>
); );
} }

View file

@ -24,12 +24,12 @@ import GeneralRoomSettingsTab from "../settings/tabs/room/GeneralRoomSettingsTab
import SecurityRoomSettingsTab from "../settings/tabs/room/SecurityRoomSettingsTab"; import SecurityRoomSettingsTab from "../settings/tabs/room/SecurityRoomSettingsTab";
import NotificationSettingsTab from "../settings/tabs/room/NotificationSettingsTab"; import NotificationSettingsTab from "../settings/tabs/room/NotificationSettingsTab";
import BridgeSettingsTab from "../settings/tabs/room/BridgeSettingsTab"; import BridgeSettingsTab from "../settings/tabs/room/BridgeSettingsTab";
import * as sdk from "../../../index";
import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { MatrixClientPeg } from "../../../MatrixClientPeg";
import dis from "../../../dispatcher/dispatcher"; import dis from "../../../dispatcher/dispatcher";
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import { UIFeature } from "../../../settings/UIFeature"; import { UIFeature } from "../../../settings/UIFeature";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import BaseDialog from "./BaseDialog";
export const ROOM_GENERAL_TAB = "ROOM_GENERAL_TAB"; export const ROOM_GENERAL_TAB = "ROOM_GENERAL_TAB";
export const ROOM_SECURITY_TAB = "ROOM_SECURITY_TAB"; export const ROOM_SECURITY_TAB = "ROOM_SECURITY_TAB";
@ -119,8 +119,6 @@ export default class RoomSettingsDialog extends React.Component<IProps> {
} }
render() { render() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const roomName = MatrixClientPeg.get().getRoom(this.props.roomId).name; const roomName = MatrixClientPeg.get().getRoom(this.props.roomId).name;
return ( return (
<BaseDialog <BaseDialog

View file

@ -22,7 +22,6 @@ import { User } from "matrix-js-sdk/src/models/user";
import { Group } from "matrix-js-sdk/src/models/group"; import { Group } from "matrix-js-sdk/src/models/group";
import { RoomMember } from "matrix-js-sdk/src/models/room-member"; 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 * as sdk from '../../../index';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import QRCode from "../elements/QRCode"; import QRCode from "../elements/QRCode";
import { RoomPermalinkCreator, makeGroupPermalink, makeUserPermalink } from "../../../utils/permalinks/Permalinks"; import { RoomPermalinkCreator, makeGroupPermalink, makeUserPermalink } from "../../../utils/permalinks/Permalinks";
@ -35,6 +34,8 @@ import { IDialogProps } from "./IDialogProps";
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import { UIFeature } from "../../../settings/UIFeature"; import { UIFeature } from "../../../settings/UIFeature";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import BaseDialog from "./BaseDialog";
import GenericTextContextMenu from "../context_menus/GenericTextContextMenu.js";
const socials = [ const socials = [
{ {
@ -119,7 +120,6 @@ export default class ShareDialog extends React.PureComponent<IProps, IState> {
const successful = await copyPlaintext(this.getUrl()); const successful = await copyPlaintext(this.getUrl());
const buttonRect = target.getBoundingClientRect(); const buttonRect = target.getBoundingClientRect();
const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu');
const { close } = ContextMenu.createMenu(GenericTextContextMenu, { const { close } = ContextMenu.createMenu(GenericTextContextMenu, {
...toRightOf(buttonRect, 2), ...toRightOf(buttonRect, 2),
message: successful ? _t('Copied!') : _t('Failed to copy'), message: successful ? _t('Copied!') : _t('Failed to copy'),
@ -230,7 +230,6 @@ export default class ShareDialog extends React.PureComponent<IProps, IState> {
</>; </>;
} }
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
return <BaseDialog return <BaseDialog
title={title} title={title}
className='mx_ShareDialog' className='mx_ShareDialog'

View file

@ -16,11 +16,12 @@ limitations under the License.
import url from 'url'; import url from 'url';
import React from 'react'; import React from 'react';
import * as sdk from '../../../index';
import { _t, pickBestLanguage } from '../../../languageHandler'; import { _t, pickBestLanguage } from '../../../languageHandler';
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import { SERVICE_TYPES } from "matrix-js-sdk/src/service-types"; import { SERVICE_TYPES } from "matrix-js-sdk/src/service-types";
import DialogButtons from "../elements/DialogButtons";
import BaseDialog from "./BaseDialog";
interface ITermsCheckboxProps { interface ITermsCheckboxProps {
onChange: (url: string, checked: boolean) => void; onChange: (url: string, checked: boolean) => void;
@ -117,9 +118,6 @@ export default class TermsDialog extends React.PureComponent<ITermsDialogProps,
}; };
public render() { public render() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
const rows = []; const rows = [];
for (const policiesAndService of this.props.policiesAndServicePairs) { for (const policiesAndService of this.props.policiesAndServicePairs) {
const parsedBaseUrl = url.parse(policiesAndService.service.baseUrl); const parsedBaseUrl = url.parse(policiesAndService.service.baseUrl);

View file

@ -16,11 +16,12 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import filesize from "filesize"; import filesize from "filesize";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import { getBlobSafeMimeType } from '../../../utils/blobs'; import { getBlobSafeMimeType } from '../../../utils/blobs';
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
interface IProps { interface IProps {
file: File; file: File;
@ -67,9 +68,6 @@ export default class UploadConfirmDialog extends React.Component<IProps> {
}; };
render() { render() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
let title; let title;
if (this.props.totalFiles > 1 && this.props.currentIndex !== undefined) { if (this.props.totalFiles > 1 && this.props.currentIndex !== undefined) {
title = _t( title = _t(

View file

@ -28,11 +28,11 @@ import PreferencesUserSettingsTab from "../settings/tabs/user/PreferencesUserSet
import VoiceUserSettingsTab from "../settings/tabs/user/VoiceUserSettingsTab"; import VoiceUserSettingsTab from "../settings/tabs/user/VoiceUserSettingsTab";
import HelpUserSettingsTab from "../settings/tabs/user/HelpUserSettingsTab"; import HelpUserSettingsTab from "../settings/tabs/user/HelpUserSettingsTab";
import FlairUserSettingsTab from "../settings/tabs/user/FlairUserSettingsTab"; import FlairUserSettingsTab from "../settings/tabs/user/FlairUserSettingsTab";
import * as sdk from "../../../index";
import SdkConfig from "../../../SdkConfig"; import SdkConfig from "../../../SdkConfig";
import MjolnirUserSettingsTab from "../settings/tabs/user/MjolnirUserSettingsTab"; import MjolnirUserSettingsTab from "../settings/tabs/user/MjolnirUserSettingsTab";
import { UIFeature } from "../../../settings/UIFeature"; import { UIFeature } from "../../../settings/UIFeature";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import BaseDialog from "./BaseDialog";
export enum UserTab { export enum UserTab {
General = "USER_GENERAL_TAB", General = "USER_GENERAL_TAB",
@ -162,8 +162,6 @@ export default class UserSettingsDialog extends React.Component<IProps, IState>
} }
render() { render() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
return ( return (
<BaseDialog <BaseDialog
className='mx_UserSettingsDialog' className='mx_UserSettingsDialog'

View file

@ -17,7 +17,7 @@ limitations under the License.
import { debounce } from "lodash"; import { debounce } from "lodash";
import classNames from 'classnames'; import classNames from 'classnames';
import React, { ChangeEvent, FormEvent } from 'react'; import React, { ChangeEvent, FormEvent } from 'react';
import { ISecretStorageKeyInfo } from "matrix-js-sdk/src"; import { ISecretStorageKeyInfo } from "matrix-js-sdk/src/crypto/api";
import * as sdk from '../../../../index'; import * as sdk from '../../../../index';
import { MatrixClientPeg } from '../../../../MatrixClientPeg'; import { MatrixClientPeg } from '../../../../MatrixClientPeg';

View file

@ -16,8 +16,9 @@ limitations under the License.
import React from 'react'; import React from 'react';
import { _t } from "../../../../languageHandler"; import { _t } from "../../../../languageHandler";
import * as sdk from "../../../../index";
import { replaceableComponent } from "../../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../../utils/replaceableComponent";
import BaseDialog from "../BaseDialog";
import DialogButtons from "../../elements/DialogButtons";
interface IProps { interface IProps {
onFinished: (success: boolean) => void; onFinished: (success: boolean) => void;
@ -34,9 +35,6 @@ export default class ConfirmDestroyCrossSigningDialog extends React.Component<IP
}; };
render() { render() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
return ( return (
<BaseDialog <BaseDialog
className='mx_ConfirmDestroyCrossSigningDialog' className='mx_ConfirmDestroyCrossSigningDialog'

View file

@ -14,7 +14,7 @@
limitations under the License. limitations under the License.
*/ */
import React from 'react'; import React, { ReactHTML } from 'react';
import { Key } from '../../../Keyboard'; import { Key } from '../../../Keyboard';
import classnames from 'classnames'; import classnames from 'classnames';
@ -29,7 +29,7 @@ export type ButtonEvent = React.MouseEvent<Element> | React.KeyboardEvent<Elemen
*/ */
interface IProps extends React.InputHTMLAttributes<Element> { interface IProps extends React.InputHTMLAttributes<Element> {
inputRef?: React.Ref<Element>; inputRef?: React.Ref<Element>;
element?: string; element?: keyof ReactHTML;
// The kind of button, similar to how Bootstrap works. // The kind of button, similar to how Bootstrap works.
// See available classes for AccessibleButton for options. // See available classes for AccessibleButton for options.
kind?: string; kind?: string;
@ -122,7 +122,7 @@ export default function AccessibleButton({
} }
AccessibleButton.defaultProps = { AccessibleButton.defaultProps = {
element: 'div', element: 'div' as keyof ReactHTML,
role: 'button', role: 'button',
tabIndex: 0, tabIndex: 0,
}; };

View file

@ -1,56 +0,0 @@
/*
Copyright 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 React from 'react';
import { decode } from "blurhash";
interface IProps {
blurhash: string;
width: number;
height: number;
}
export default class BlurhashPlaceholder extends React.PureComponent<IProps> {
private canvas: React.RefObject<HTMLCanvasElement> = React.createRef();
public componentDidMount() {
this.draw();
}
public componentDidUpdate() {
this.draw();
}
private draw() {
if (!this.canvas.current) return;
try {
const { width, height } = this.props;
const pixels = decode(this.props.blurhash, Math.ceil(width), Math.ceil(height));
const ctx = this.canvas.current.getContext("2d");
const imgData = ctx.createImageData(width, height);
imgData.data.set(pixels);
ctx.putImageData(imgData, 0, 0);
} catch (e) {
console.error("Error rendering blurhash: ", e);
}
}
public render() {
return <canvas height={this.props.height} width={this.props.width} ref={this.canvas} />;
}
}

View file

@ -260,6 +260,7 @@ export default class Field extends React.PureComponent<PropShapes, IState> {
}); });
// Handle displaying feedback on validity // Handle displaying feedback on validity
// FIXME: Using an import will result in test failures
const Tooltip = sdk.getComponent("elements.Tooltip"); const Tooltip = sdk.getComponent("elements.Tooltip");
let fieldTooltip; let fieldTooltip;
if (tooltipContent || this.state.feedback) { if (tooltipContent || this.state.feedback) {

View file

@ -24,7 +24,7 @@ import FocusLock from "react-focus-lock";
import MemberAvatar from "../avatars/MemberAvatar"; import MemberAvatar from "../avatars/MemberAvatar";
import { ContextMenuTooltipButton } from "../../../accessibility/context_menu/ContextMenuTooltipButton"; import { ContextMenuTooltipButton } from "../../../accessibility/context_menu/ContextMenuTooltipButton";
import MessageContextMenu from "../context_menus/MessageContextMenu"; import MessageContextMenu from "../context_menus/MessageContextMenu";
import { aboveLeftOf, ContextMenu } from '../../structures/ContextMenu'; import { aboveLeftOf } from '../../structures/ContextMenu';
import MessageTimestamp from "../messages/MessageTimestamp"; import MessageTimestamp from "../messages/MessageTimestamp";
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import { formatFullDate } from "../../../DateUtils"; import { formatFullDate } from "../../../DateUtils";
@ -304,17 +304,13 @@ export default class ImageView extends React.Component<IProps, IState> {
let contextMenu = null; let contextMenu = null;
if (this.state.contextMenuDisplayed) { if (this.state.contextMenuDisplayed) {
contextMenu = ( contextMenu = (
<ContextMenu
{...aboveLeftOf(this.contextMenuButton.current.getBoundingClientRect())}
onFinished={this.onCloseContextMenu}
>
<MessageContextMenu <MessageContextMenu
{...aboveLeftOf(this.contextMenuButton.current.getBoundingClientRect())}
mxEvent={this.props.mxEvent} mxEvent={this.props.mxEvent}
permalinkCreator={this.props.permalinkCreator} permalinkCreator={this.props.permalinkCreator}
onFinished={this.onCloseContextMenu} onFinished={this.onCloseContextMenu}
onCloseDialog={this.props.onFinished} onCloseDialog={this.props.onFinished}
/> />
</ContextMenu>
); );
} }

View file

@ -27,6 +27,7 @@ interface IProps {
value: string; value: string;
label?: string; label?: string;
placeholder?: string; placeholder?: string;
disabled?: boolean;
onChange?(value: string): void; onChange?(value: string): void;
} }
@ -68,6 +69,7 @@ export default class RoomAliasField extends React.PureComponent<IProps, IState>
onChange={this.onChange} onChange={this.onChange}
value={this.props.value.substring(1, this.props.value.length - this.props.domain.length - 1)} value={this.props.value.substring(1, this.props.value.length - this.props.domain.length - 1)}
maxLength={maxlength} maxLength={maxlength}
disabled={this.props.disabled}
/> />
); );
} }

View file

@ -17,11 +17,11 @@ limitations under the License.
import React from 'react'; import React from 'react';
import Dropdown from "../../views/elements/Dropdown"; import Dropdown from "../../views/elements/Dropdown";
import * as sdk from '../../../index';
import PlatformPeg from "../../../PlatformPeg"; import PlatformPeg from "../../../PlatformPeg";
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import Spinner from "./Spinner";
function languageMatchesSearchQuery(query, language) { function languageMatchesSearchQuery(query, language) {
if (language.label.toUpperCase().includes(query.toUpperCase())) return true; if (language.label.toUpperCase().includes(query.toUpperCase())) return true;
@ -84,7 +84,6 @@ export default class SpellCheckLanguagesDropdown extends React.Component<SpellCh
render() { render() {
if (this.state.languages === null) { if (this.state.languages === null) {
const Spinner = sdk.getComponent('elements.Spinner');
return <Spinner />; return <Spinner />;
} }

View file

@ -17,7 +17,7 @@ limitations under the License.
import React from "react"; import React from "react";
import classNames from "classnames"; import classNames from "classnames";
import * as sdk from "../../../index"; import AccessibleButton from "./AccessibleButton";
interface IProps { interface IProps {
// Whether or not this toggle is in the 'on' position. // Whether or not this toggle is in the 'on' position.
@ -43,7 +43,6 @@ export default ({ checked, disabled = false, onChange, ...props }: IProps) => {
"mx_ToggleSwitch_enabled": !disabled, "mx_ToggleSwitch_enabled": !disabled,
}); });
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
return ( return (
<AccessibleButton {...props} <AccessibleButton {...props}
className={classes} className={classes}

View file

@ -16,11 +16,11 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import * as sdk from '../../../index';
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import Tooltip from './Tooltip';
interface IProps { interface IProps {
helpText: string; helpText: React.ReactNode | string;
} }
interface IState { interface IState {
@ -49,7 +49,6 @@ export default class TooltipButton extends React.Component<IProps, IState> {
}; };
render() { render() {
const Tooltip = sdk.getComponent("elements.Tooltip");
const tip = this.state.hover ? <Tooltip const tip = this.state.hover ? <Tooltip
className="mx_TooltipButton_container" className="mx_TooltipButton_container"
tooltipClassName="mx_TooltipButton_helpText" tooltipClassName="mx_TooltipButton_helpText"

View file

@ -33,7 +33,7 @@ export const EMOJI_HEIGHT = 37;
export const EMOJIS_PER_ROW = 8; export const EMOJIS_PER_ROW = 8;
interface IProps { interface IProps {
selectedEmojis: Set<string>; selectedEmojis?: Set<string>;
showQuickReactions?: boolean; showQuickReactions?: boolean;
onChoose(unicode: string): boolean; onChoose(unicode: string): boolean;
} }

View file

@ -18,6 +18,7 @@ limitations under the License.
import React, { createRef } from 'react'; import React, { createRef } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Blurhash } from "react-blurhash";
import MFileBody from './MFileBody'; import MFileBody from './MFileBody';
import Modal from '../../../Modal'; import Modal from '../../../Modal';
@ -29,7 +30,6 @@ import MatrixClientContext from "../../../contexts/MatrixClientContext";
import InlineSpinner from '../elements/InlineSpinner'; import InlineSpinner from '../elements/InlineSpinner';
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import { mediaFromContent } from "../../../customisations/Media"; import { mediaFromContent } from "../../../customisations/Media";
import BlurhashPlaceholder from "../elements/BlurhashPlaceholder";
import { BLURHASH_FIELD } from "../../../ContentMessages"; import { BLURHASH_FIELD } from "../../../ContentMessages";
@replaceableComponent("views.messages.MImageBody") @replaceableComponent("views.messages.MImageBody")
@ -436,7 +436,7 @@ export default class MImageBody extends React.Component {
// Overidden by MStickerBody // Overidden by MStickerBody
getPlaceholder(width, height) { getPlaceholder(width, height) {
const blurhash = this.props.mxEvent.getContent().info[BLURHASH_FIELD]; const blurhash = this.props.mxEvent.getContent().info[BLURHASH_FIELD];
if (blurhash) return <BlurhashPlaceholder blurhash={blurhash} width={width} height={height} />; if (blurhash) return <Blurhash hash={blurhash} width={width} height={height} />;
return <div className="mx_MImageBody_thumbnail_spinner"> return <div className="mx_MImageBody_thumbnail_spinner">
<InlineSpinner w={32} h={32} /> <InlineSpinner w={32} h={32} />
</div>; </div>;

View file

@ -17,7 +17,6 @@ limitations under the License.
import React from 'react'; import React from 'react';
import { MatrixEvent } from 'matrix-js-sdk/src'; import { MatrixEvent } from 'matrix-js-sdk/src';
import { MatrixClientPeg } from '../../../MatrixClientPeg'; import { MatrixClientPeg } from '../../../MatrixClientPeg';
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import { getNameForEventRoom, userLabelForEventRoom } import { getNameForEventRoom, userLabelForEventRoom }
from '../../../utils/KeyVerificationStateObserver'; from '../../../utils/KeyVerificationStateObserver';
@ -26,6 +25,7 @@ import { RightPanelPhases } from "../../../stores/RightPanelStorePhases";
import { Action } from "../../../dispatcher/actions"; import { Action } from "../../../dispatcher/actions";
import EventTileBubble from "./EventTileBubble"; import EventTileBubble from "./EventTileBubble";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import AccessibleButton from '../elements/AccessibleButton';
interface IProps { interface IProps {
mxEvent: MatrixEvent; mxEvent: MatrixEvent;
@ -115,8 +115,6 @@ export default class MKeyVerificationRequest extends React.Component<IProps> {
} }
public render() { public render() {
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
const { mxEvent } = this.props; const { mxEvent } = this.props;
const request = mxEvent.verificationRequest; const request = mxEvent.verificationRequest;

View file

@ -24,7 +24,7 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
interface IProps { interface IProps {
mxEvent: MatrixEvent; mxEvent: MatrixEvent;
onClick(): void; onClick?(): void;
enableFlair: boolean; enableFlair: boolean;
} }

View file

@ -45,7 +45,7 @@ import Spoiler from "../elements/Spoiler";
import QuestionDialog from "../dialogs/QuestionDialog"; import QuestionDialog from "../dialogs/QuestionDialog";
import MessageEditHistoryDialog from "../dialogs/MessageEditHistoryDialog"; import MessageEditHistoryDialog from "../dialogs/MessageEditHistoryDialog";
import EditMessageComposer from '../rooms/EditMessageComposer'; import EditMessageComposer from '../rooms/EditMessageComposer';
import LinkPreviewWidget from '../rooms/LinkPreviewWidget'; import LinkPreviewGroup from '../rooms/LinkPreviewGroup';
interface IProps { interface IProps {
/* the MatrixEvent to show */ /* the MatrixEvent to show */
@ -294,14 +294,8 @@ export default class TextualBody extends React.Component<IProps, IState> {
// pass only the first child which is the event tile otherwise this recurses on edited events // pass only the first child which is the event tile otherwise this recurses on edited events
let links = this.findLinks([this.contentRef.current]); let links = this.findLinks([this.contentRef.current]);
if (links.length) { if (links.length) {
// de-duplicate the links after stripping hashes as they don't affect the preview // de-duplicate the links using a set here maintains the order
// using a set here maintains the order links = Array.from(new Set(links));
links = Array.from(new Set(links.map(link => {
const url = new URL(link);
url.hash = "";
return url.toString();
})));
this.setState({ links }); this.setState({ links });
// lazy-load the hidden state of the preview widget from localstorage // lazy-load the hidden state of the preview widget from localstorage
@ -530,15 +524,12 @@ export default class TextualBody extends React.Component<IProps, IState> {
let widgets; let widgets;
if (this.state.links.length && !this.state.widgetHidden && this.props.showUrlPreview) { if (this.state.links.length && !this.state.widgetHidden && this.props.showUrlPreview) {
widgets = this.state.links.map((link)=>{ widgets = <LinkPreviewGroup
return <LinkPreviewWidget links={this.state.links}
key={link}
link={link}
mxEvent={this.props.mxEvent} mxEvent={this.props.mxEvent}
onCancelClick={this.onCancelClick} onCancelClick={this.onCancelClick}
onHeightChanged={this.props.onHeightChanged} onHeightChanged={this.props.onHeightChanged}
/>; />;
});
} }
switch (content.msgtype) { switch (content.msgtype) {

View file

@ -16,13 +16,13 @@ limitations under the License.
import React from "react"; import React from "react";
import * as sdk from "../../../index";
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
import { RoomMember } from "matrix-js-sdk/src/models/room-member"; import { RoomMember } from "matrix-js-sdk/src/models/room-member";
import { User } from "matrix-js-sdk/src/models/user"; import { User } from "matrix-js-sdk/src/models/user";
import AccessibleButton from "../elements/AccessibleButton";
import Spinner from "../elements/Spinner";
export const PendingActionSpinner = ({ text }) => { export const PendingActionSpinner = ({ text }) => {
const Spinner = sdk.getComponent('elements.Spinner');
return <div className="mx_EncryptionInfo_spinner"> return <div className="mx_EncryptionInfo_spinner">
<Spinner /> <Spinner />
{ text } { text }
@ -64,7 +64,6 @@ const EncryptionInfo: React.FC<IProps> = ({
} }
content = <PendingActionSpinner text={text} />; content = <PendingActionSpinner text={text} />;
} else { } else {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
content = ( content = (
<AccessibleButton kind="primary" className="mx_UserInfo_wideButton" onClick={onStartVerification}> <AccessibleButton kind="primary" className="mx_UserInfo_wideButton" onClick={onStartVerification}>
{_t("Start Verification")} {_t("Start Verification")}

View file

@ -81,6 +81,7 @@ const EncryptionPanel: React.FC<IProps> = (props: IProps) => {
const changeHandler = useCallback(() => { const changeHandler = useCallback(() => {
// handle transitions -> cancelled for mismatches which fire a modal instead of showing a card // handle transitions -> cancelled for mismatches which fire a modal instead of showing a card
if (request && request.cancelled && MISMATCHES.includes(request.cancellationCode)) { if (request && request.cancelled && MISMATCHES.includes(request.cancellationCode)) {
// FIXME: Using an import will result in test failures
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog("Verification failed", "insecure", ErrorDialog, { Modal.createTrackedDialog("Verification failed", "insecure", ErrorDialog, {
headerImage: require("../../../../res/img/e2e/warning.svg"), headerImage: require("../../../../res/img/e2e/warning.svg"),

View file

@ -17,7 +17,6 @@ limitations under the License.
import React from "react"; import React from "react";
import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { MatrixClientPeg } from "../../../MatrixClientPeg";
import * as sdk from '../../../index';
import { verificationMethods } from 'matrix-js-sdk/src/crypto'; import { verificationMethods } from 'matrix-js-sdk/src/crypto';
import { SCAN_QR_CODE_METHOD } from "matrix-js-sdk/src/crypto/verification/QRCode"; import { SCAN_QR_CODE_METHOD } from "matrix-js-sdk/src/crypto/verification/QRCode";
import { VerificationRequest } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest"; import { VerificationRequest } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest";
@ -38,6 +37,8 @@ import {
} from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest"; } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest";
import Spinner from "../elements/Spinner"; import Spinner from "../elements/Spinner";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import AccessibleButton from "../elements/AccessibleButton";
import VerificationShowSas from "../verification/VerificationShowSas";
// XXX: Should be defined in matrix-js-sdk // XXX: Should be defined in matrix-js-sdk
enum VerificationPhase { enum VerificationPhase {
@ -81,7 +82,6 @@ export default class VerificationPanel extends React.PureComponent<IProps, IStat
const { member, request } = this.props; const { member, request } = this.props;
const showSAS: boolean = request.otherPartySupportsMethod(verificationMethods.SAS); const showSAS: boolean = request.otherPartySupportsMethod(verificationMethods.SAS);
const showQR: boolean = request.otherPartySupportsMethod(SCAN_QR_CODE_METHOD); const showQR: boolean = request.otherPartySupportsMethod(SCAN_QR_CODE_METHOD);
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const brand = SdkConfig.get().brand; const brand = SdkConfig.get().brand;
const noCommonMethodError: JSX.Element = !showSAS && !showQR ? const noCommonMethodError: JSX.Element = !showSAS && !showQR ?
@ -195,7 +195,6 @@ export default class VerificationPanel extends React.PureComponent<IProps, IStat
private renderQRReciprocatePhase() { private renderQRReciprocatePhase() {
const { member, request } = this.props; const { member, request } = this.props;
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
const description = request.isSelfVerification ? const description = request.isSelfVerification ?
_t("Almost there! Is your other session showing the same shield?") : _t("Almost there! Is your other session showing the same shield?") :
_t("Almost there! Is %(displayName)s showing the same shield?", { _t("Almost there! Is %(displayName)s showing the same shield?", {
@ -265,7 +264,6 @@ export default class VerificationPanel extends React.PureComponent<IProps, IStat
}); });
} }
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
return ( return (
<div className="mx_UserInfo_container mx_VerificationPanel_verified_section"> <div className="mx_UserInfo_container mx_VerificationPanel_verified_section">
<h3>{_t("Verified")}</h3> <h3>{_t("Verified")}</h3>
@ -282,8 +280,6 @@ export default class VerificationPanel extends React.PureComponent<IProps, IStat
private renderCancelledPhase() { private renderCancelledPhase() {
const { member, request } = this.props; const { member, request } = this.props;
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
let startAgainInstruction: string; let startAgainInstruction: string;
if (request.isSelfVerification) { if (request.isSelfVerification) {
startAgainInstruction = _t("Start verification again from the notification."); startAgainInstruction = _t("Start verification again from the notification.");
@ -332,7 +328,6 @@ export default class VerificationPanel extends React.PureComponent<IProps, IStat
case verificationMethods.RECIPROCATE_QR_CODE: case verificationMethods.RECIPROCATE_QR_CODE:
return this.renderQRReciprocatePhase(); return this.renderQRReciprocatePhase();
case verificationMethods.SAS: { case verificationMethods.SAS: {
const VerificationShowSas = sdk.getComponent('views.verification.VerificationShowSas');
const emojis = this.state.sasEvent ? const emojis = this.state.sasEvent ?
<VerificationShowSas <VerificationShowSas
displayName={displayName} displayName={displayName}

View file

@ -711,6 +711,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
} }
public insertMention(userId: string): void { public insertMention(userId: string): void {
this.modifiedFlag = true;
const { model } = this.props; const { model } = this.props;
const { partCreator } = model; const { partCreator } = model;
const member = this.props.room.getMember(userId); const member = this.props.room.getMember(userId);
@ -729,6 +730,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
} }
public insertQuotedMessage(event: MatrixEvent): void { public insertQuotedMessage(event: MatrixEvent): void {
this.modifiedFlag = true;
const { model } = this.props; const { model } = this.props;
const { partCreator } = model; const { partCreator } = model;
const quoteParts = parseEvent(event, partCreator, { isQuotedMessage: true }); const quoteParts = parseEvent(event, partCreator, { isQuotedMessage: true });
@ -744,6 +746,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
} }
public insertPlaintext(text: string): void { public insertPlaintext(text: string): void {
this.modifiedFlag = true;
const { model } = this.props; const { model } = this.props;
const { partCreator } = model; const { partCreator } = model;
const caret = this.getCaret(); const caret = this.getCaret();

View file

@ -131,11 +131,12 @@ export default class EditMessageComposer extends React.Component<IProps, IState>
super(props); super(props);
this.context = context; // otherwise React will only set it prior to render due to type def above this.context = context; // otherwise React will only set it prior to render due to type def above
const isRestored = this.createEditorModel();
const ev = this.props.editState.getEvent();
this.state = { this.state = {
saveDisabled: true, saveDisabled: !isRestored || !this.isContentModified(createEditContent(this.model, ev)["m.new_content"]),
}; };
this.createEditorModel();
window.addEventListener("beforeunload", this.saveStoredEditorState); window.addEventListener("beforeunload", this.saveStoredEditorState);
this.dispatcherRef = dis.register(this.onAction); this.dispatcherRef = dis.register(this.onAction);
} }
@ -230,12 +231,12 @@ export default class EditMessageComposer extends React.Component<IProps, IState>
} }
} }
private saveStoredEditorState(): void { private saveStoredEditorState = (): void => {
const item = SendHistoryManager.createItem(this.model); const item = SendHistoryManager.createItem(this.model);
this.clearPreviousEdit(); this.clearPreviousEdit();
localStorage.setItem(this.editorRoomKey, this.props.editState.getEvent().getId()); localStorage.setItem(this.editorRoomKey, this.props.editState.getEvent().getId());
localStorage.setItem(this.editorStateKey, JSON.stringify(item)); localStorage.setItem(this.editorStateKey, JSON.stringify(item));
} };
private isSlashCommand(): boolean { private isSlashCommand(): boolean {
const parts = this.model.parts; const parts = this.model.parts;
@ -256,10 +257,9 @@ export default class EditMessageComposer extends React.Component<IProps, IState>
private isContentModified(newContent: IContent): boolean { private isContentModified(newContent: IContent): boolean {
// if nothing has changed then bail // if nothing has changed then bail
const oldContent = this.props.editState.getEvent().getContent(); const oldContent = this.props.editState.getEvent().getContent();
if (!this.editorRef.current?.isModified() || if (oldContent["msgtype"] === newContent["msgtype"] && oldContent["body"] === newContent["body"] &&
(oldContent["msgtype"] === newContent["msgtype"] && oldContent["body"] === newContent["body"] &&
oldContent["format"] === newContent["format"] && oldContent["format"] === newContent["format"] &&
oldContent["formatted_body"] === newContent["formatted_body"])) { oldContent["formatted_body"] === newContent["formatted_body"]) {
return false; return false;
} }
return true; return true;
@ -410,36 +410,27 @@ export default class EditMessageComposer extends React.Component<IProps, IState>
dis.unregister(this.dispatcherRef); dis.unregister(this.dispatcherRef);
} }
private createEditorModel(): void { private createEditorModel(): boolean {
const { editState } = this.props; const { editState } = this.props;
const room = this.getRoom(); const room = this.getRoom();
const partCreator = new CommandPartCreator(room, this.context); const partCreator = new CommandPartCreator(room, this.context);
let parts; let parts;
let isRestored = false;
if (editState.hasEditorState()) { if (editState.hasEditorState()) {
// if restoring state from a previous editor, // if restoring state from a previous editor,
// restore serialized parts from the state // restore serialized parts from the state
parts = editState.getSerializedParts().map(p => partCreator.deserializePart(p)); parts = editState.getSerializedParts().map(p => partCreator.deserializePart(p));
} else { } else {
//otherwise, either restore serialized parts from localStorage or parse the body of the event // otherwise, either restore serialized parts from localStorage or parse the body of the event
parts = this.restoreStoredEditorState(partCreator) || parseEvent(editState.getEvent(), partCreator); const restoredParts = this.restoreStoredEditorState(partCreator);
parts = restoredParts || parseEvent(editState.getEvent(), partCreator);
isRestored = !!restoredParts;
} }
this.model = new EditorModel(parts, partCreator); this.model = new EditorModel(parts, partCreator);
this.saveStoredEditorState(); this.saveStoredEditorState();
}
private getInitialCaretPosition(): CaretPosition { return isRestored;
const { editState } = this.props;
let caretPosition;
if (editState.hasEditorState() && editState.getCaret()) {
// if restoring state from a previous editor,
// restore caret position from the state
const caret = editState.getCaret();
caretPosition = this.model.positionForOffset(caret.offset, caret.atNodeEnd);
} else {
// otherwise, set it at the end
caretPosition = this.model.getPositionAtEnd();
}
return caretPosition;
} }
private onChange = (): void => { private onChange = (): void => {

View file

@ -47,6 +47,13 @@ import { StaticNotificationState } from "../../../stores/notifications/StaticNot
import NotificationBadge from "./NotificationBadge"; import NotificationBadge from "./NotificationBadge";
import { ComposerInsertPayload } from "../../../dispatcher/payloads/ComposerInsertPayload"; import { ComposerInsertPayload } from "../../../dispatcher/payloads/ComposerInsertPayload";
import { Action } from '../../../dispatcher/actions'; import { Action } from '../../../dispatcher/actions';
import MemberAvatar from '../avatars/MemberAvatar';
import SenderProfile from '../messages/SenderProfile';
import MessageTimestamp from '../messages/MessageTimestamp';
import TooltipButton from '../elements/TooltipButton';
import ReadReceiptMarker from "./ReadReceiptMarker";
import MessageActionBar from "../messages/MessageActionBar";
import ReactionsRow from '../messages/ReactionsRow';
const eventTileTypes = { const eventTileTypes = {
[EventType.RoomMessage]: 'messages.MessageEvent', [EventType.RoomMessage]: 'messages.MessageEvent',
@ -666,7 +673,6 @@ export default class EventTile extends React.Component<IProps, IState> {
); );
} }
const ReadReceiptMarker = sdk.getComponent('rooms.ReadReceiptMarker');
const avatars = []; const avatars = [];
const receiptOffset = 15; const receiptOffset = 15;
let left = 0; let left = 0;
@ -733,7 +739,7 @@ export default class EventTile extends React.Component<IProps, IState> {
); );
} }
onSenderProfileClick = event => { onSenderProfileClick = () => {
const mxEvent = this.props.mxEvent; const mxEvent = this.props.mxEvent;
dis.dispatch<ComposerInsertPayload>({ dis.dispatch<ComposerInsertPayload>({
action: Action.ComposerInsert, action: Action.ComposerInsert,
@ -841,10 +847,6 @@ export default class EventTile extends React.Component<IProps, IState> {
}; };
render() { render() {
const MessageTimestamp = sdk.getComponent('messages.MessageTimestamp');
const SenderProfile = sdk.getComponent('messages.SenderProfile');
const MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
//console.info("EventTile showUrlPreview for %s is %s", this.props.mxEvent.getId(), this.props.showUrlPreview); //console.info("EventTile showUrlPreview for %s is %s", this.props.mxEvent.getId(), this.props.showUrlPreview);
const content = this.props.mxEvent.getContent(); const content = this.props.mxEvent.getContent();
@ -987,7 +989,6 @@ export default class EventTile extends React.Component<IProps, IState> {
} }
} }
const MessageActionBar = sdk.getComponent('messages.MessageActionBar');
const actionBar = !isEditing ? <MessageActionBar const actionBar = !isEditing ? <MessageActionBar
mxEvent={this.props.mxEvent} mxEvent={this.props.mxEvent}
reactions={this.state.reactions} reactions={this.state.reactions}
@ -1027,7 +1028,6 @@ export default class EventTile extends React.Component<IProps, IState> {
{ 'requestLink': (sub) => <a onClick={this.onRequestKeysClick}>{ sub }</a> }, { 'requestLink': (sub) => <a onClick={this.onRequestKeysClick}>{ sub }</a> },
); );
const TooltipButton = sdk.getComponent('elements.TooltipButton');
const keyRequestInfo = isEncryptionFailure && !isRedacted ? const keyRequestInfo = isEncryptionFailure && !isRedacted ?
<div className="mx_EventTile_keyRequestInfo"> <div className="mx_EventTile_keyRequestInfo">
<span className="mx_EventTile_keyRequestInfo_text"> <span className="mx_EventTile_keyRequestInfo_text">
@ -1038,7 +1038,6 @@ export default class EventTile extends React.Component<IProps, IState> {
let reactionsRow; let reactionsRow;
if (!isRedacted) { if (!isRedacted) {
const ReactionsRow = sdk.getComponent('messages.ReactionsRow');
reactionsRow = <ReactionsRow reactionsRow = <ReactionsRow
mxEvent={this.props.mxEvent} mxEvent={this.props.mxEvent}
reactions={this.state.reactions} reactions={this.state.reactions}

View file

@ -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.
*/
import React, { useEffect } from "react";
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { useStateToggle } from "../../../hooks/useStateToggle";
import LinkPreviewWidget from "./LinkPreviewWidget";
import AccessibleButton from "../elements/AccessibleButton";
import { _t } from "../../../languageHandler";
const INITIAL_NUM_PREVIEWS = 2;
interface IProps {
links: string[]; // the URLs to be previewed
mxEvent: MatrixEvent; // the Event associated with the preview
onCancelClick?(): void; // called when the preview's cancel ('hide') button is clicked
onHeightChanged?(): void; // called when the preview's contents has loaded
}
const LinkPreviewGroup: React.FC<IProps> = ({ links, mxEvent, onCancelClick, onHeightChanged }) => {
const [expanded, toggleExpanded] = useStateToggle();
useEffect(() => {
onHeightChanged();
}, [onHeightChanged, expanded]);
const shownLinks = expanded ? links : links.slice(0, INITIAL_NUM_PREVIEWS);
let toggleButton;
if (links.length > INITIAL_NUM_PREVIEWS) {
toggleButton = <AccessibleButton onClick={toggleExpanded}>
{ expanded
? _t("Collapse")
: _t("Show %(count)s other previews", { count: links.length - shownLinks.length }) }
</AccessibleButton>;
}
return <div className="mx_LinkPreviewGroup">
{ shownLinks.map((link, i) => (
<LinkPreviewWidget key={link} link={link} mxEvent={mxEvent} onHeightChanged={onHeightChanged}>
{ i === 0 ? (
<AccessibleButton
className="mx_LinkPreviewGroup_hide"
onClick={onCancelClick}
aria-label={_t("Close preview")}
>
<img
className="mx_filterFlipColor"
alt=""
role="presentation"
src={require("../../../../res/img/cancel.svg")}
width="18"
height="18"
/>
</AccessibleButton>
): undefined }
</LinkPreviewWidget>
)) }
{ toggleButton }
</div>;
};
export default LinkPreviewGroup;

View file

@ -1,6 +1,5 @@
/* /*
Copyright 2016 OpenMarket Ltd Copyright 2016 - 2021 The Matrix.org Foundation C.I.C.
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -16,26 +15,33 @@ limitations under the License.
*/ */
import React, { createRef } from 'react'; import React, { createRef } from 'react';
import PropTypes from 'prop-types';
import { AllHtmlEntities } from 'html-entities'; import { AllHtmlEntities } from 'html-entities';
import { MatrixEvent } from 'matrix-js-sdk/src/models/event';
import { IPreviewUrlResponse } from 'matrix-js-sdk/src/client';
import { linkifyElement } from '../../../HtmlUtils'; import { linkifyElement } from '../../../HtmlUtils';
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { MatrixClientPeg } from "../../../MatrixClientPeg";
import * as sdk from "../../../index";
import Modal from "../../../Modal"; import Modal from "../../../Modal";
import * as ImageUtils from "../../../ImageUtils"; import * as ImageUtils from "../../../ImageUtils";
import { _t } from "../../../languageHandler";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import { mediaFromMxc } from "../../../customisations/Media"; import { mediaFromMxc } from "../../../customisations/Media";
import ImageView from '../elements/ImageView';
interface IProps {
link: string; // the URL being previewed
mxEvent: MatrixEvent; // the Event associated with the preview
onHeightChanged(): void; // called when the preview's contents has loaded
}
interface IState {
preview?: IPreviewUrlResponse;
}
@replaceableComponent("views.rooms.LinkPreviewWidget") @replaceableComponent("views.rooms.LinkPreviewWidget")
export default class LinkPreviewWidget extends React.Component { export default class LinkPreviewWidget extends React.Component<IProps, IState> {
static propTypes = { private unmounted = false;
link: PropTypes.string.isRequired, // the URL being previewed private readonly description = createRef<HTMLDivElement>();
mxEvent: PropTypes.object.isRequired, // the Event associated with the preview
onCancelClick: PropTypes.func, // called when the preview's cancel ('hide') button is clicked
onHeightChanged: PropTypes.func, // called when the preview's contents has loaded
};
constructor(props) { constructor(props) {
super(props); super(props);
@ -44,31 +50,25 @@ export default class LinkPreviewWidget extends React.Component {
preview: null, preview: null,
}; };
this.unmounted = false; MatrixClientPeg.get().getUrlPreview(this.props.link, this.props.mxEvent.getTs()).then((preview) => {
MatrixClientPeg.get().getUrlPreview(this.props.link, this.props.mxEvent.getTs()).then((res)=>{
if (this.unmounted) { if (this.unmounted) {
return; return;
} }
this.setState( this.setState({ preview }, this.props.onHeightChanged);
{ preview: res }, }, (error) => {
this.props.onHeightChanged,
);
}, (error)=>{
console.error("Failed to get URL preview: " + error); console.error("Failed to get URL preview: " + error);
}); });
this._description = createRef();
} }
componentDidMount() { componentDidMount() {
if (this._description.current) { if (this.description.current) {
linkifyElement(this._description.current); linkifyElement(this.description.current);
} }
} }
componentDidUpdate() { componentDidUpdate() {
if (this._description.current) { if (this.description.current) {
linkifyElement(this._description.current); linkifyElement(this.description.current);
} }
} }
@ -76,11 +76,10 @@ export default class LinkPreviewWidget extends React.Component {
this.unmounted = true; this.unmounted = true;
} }
onImageClick = ev => { private onImageClick = ev => {
const p = this.state.preview; const p = this.state.preview;
if (ev.button != 0 || ev.metaKey) return; if (ev.button != 0 || ev.metaKey) return;
ev.preventDefault(); ev.preventDefault();
const ImageView = sdk.getComponent("elements.ImageView");
let src = p["og:image"]; let src = p["og:image"];
if (src && src.startsWith("mxc://")) { if (src && src.startsWith("mxc://")) {
@ -136,21 +135,17 @@ export default class LinkPreviewWidget extends React.Component {
// opaque string. This does not allow any HTML to be injected into the DOM. // opaque string. This does not allow any HTML to be injected into the DOM.
const description = AllHtmlEntities.decode(p["og:description"] || ""); const description = AllHtmlEntities.decode(p["og:description"] || "");
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
return ( return (
<div className="mx_LinkPreviewWidget"> <div className="mx_LinkPreviewWidget">
{ img } { img }
<div className="mx_LinkPreviewWidget_caption"> <div className="mx_LinkPreviewWidget_caption">
<div className="mx_LinkPreviewWidget_title"><a href={this.props.link} target="_blank" rel="noreferrer noopener">{ p["og:title"] }</a></div> <div className="mx_LinkPreviewWidget_title"><a href={this.props.link} target="_blank" rel="noreferrer noopener">{ p["og:title"] }</a></div>
<div className="mx_LinkPreviewWidget_siteName">{ p["og:site_name"] ? (" - " + p["og:site_name"]) : null }</div> <div className="mx_LinkPreviewWidget_siteName">{ p["og:site_name"] ? (" - " + p["og:site_name"]) : null }</div>
<div className="mx_LinkPreviewWidget_description" ref={this._description}> <div className="mx_LinkPreviewWidget_description" ref={this.description}>
{ description } { description }
</div> </div>
</div> </div>
<AccessibleButton className="mx_LinkPreviewWidget_cancel" onClick={this.props.onCancelClick} aria-label={_t("Close preview")}> { this.props.children }
<img className="mx_filterFlipColor" alt="" role="presentation"
src={require("../../../../res/img/cancel.svg")} width="18" height="18" />
</AccessibleButton>
</div> </div>
); );
} }

View file

@ -17,7 +17,6 @@ import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import { MatrixClientPeg } from '../../../MatrixClientPeg'; import { MatrixClientPeg } from '../../../MatrixClientPeg';
import * as sdk from '../../../index';
import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { Room } from "matrix-js-sdk/src/models/room"; import { Room } from "matrix-js-sdk/src/models/room";
import { RoomMember } from "matrix-js-sdk/src/models/room-member"; import { RoomMember } from "matrix-js-sdk/src/models/room-member";
@ -44,13 +43,14 @@ import SendMessageComposer from "./SendMessageComposer";
import { ComposerInsertPayload } from "../../../dispatcher/payloads/ComposerInsertPayload"; import { ComposerInsertPayload } from "../../../dispatcher/payloads/ComposerInsertPayload";
import { Action } from "../../../dispatcher/actions"; import { Action } from "../../../dispatcher/actions";
import EditorModel from "../../../editor/model"; import EditorModel from "../../../editor/model";
import EmojiPicker from '../emojipicker/EmojiPicker';
import MemberStatusMessageAvatar from "../avatars/MemberStatusMessageAvatar";
interface IComposerAvatarProps { interface IComposerAvatarProps {
me: object; me: object;
} }
function ComposerAvatar(props: IComposerAvatarProps) { function ComposerAvatar(props: IComposerAvatarProps) {
const MemberStatusMessageAvatar = sdk.getComponent('avatars.MemberStatusMessageAvatar');
return <div className="mx_MessageComposer_avatar"> return <div className="mx_MessageComposer_avatar">
<MemberStatusMessageAvatar member={props.me} width={24} height={24} /> <MemberStatusMessageAvatar member={props.me} width={24} height={24} />
</div>; </div>;
@ -76,7 +76,6 @@ const EmojiButton = ({ addEmoji }) => {
let contextMenu; let contextMenu;
if (menuDisplayed) { if (menuDisplayed) {
const buttonRect = button.current.getBoundingClientRect(); const buttonRect = button.current.getBoundingClientRect();
const EmojiPicker = sdk.getComponent('emojipicker.EmojiPicker');
contextMenu = <ContextMenu {...aboveLeftOf(buttonRect)} onFinished={closeMenu} managed={false}> contextMenu = <ContextMenu {...aboveLeftOf(buttonRect)} onFinished={closeMenu} managed={false}>
<EmojiPicker onChoose={addEmoji} showQuickReactions={true} /> <EmojiPicker onChoose={addEmoji} showQuickReactions={true} />
</ContextMenu>; </ContextMenu>;
@ -366,15 +365,12 @@ export default class MessageComposer extends React.Component<IProps, IState> {
]; ];
if (!this.state.tombstone && this.state.canSendMessages) { if (!this.state.tombstone && this.state.canSendMessages) {
const SendMessageComposer = sdk.getComponent("rooms.SendMessageComposer");
controls.push( controls.push(
<SendMessageComposer <SendMessageComposer
ref={(c) => this.messageComposerInput = c} ref={(c) => this.messageComposerInput = c}
key="controls_input" key="controls_input"
room={this.props.room} room={this.props.room}
placeholder={this.renderPlaceholderText()} placeholder={this.renderPlaceholderText()}
resizeNotifier={this.props.resizeNotifier}
permalinkCreator={this.props.permalinkCreator} permalinkCreator={this.props.permalinkCreator}
replyToEvent={this.props.replyToEvent} replyToEvent={this.props.replyToEvent}
onChange={this.onChange} onChange={this.onChange}

View file

@ -20,13 +20,14 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { Room } from "matrix-js-sdk/src/models/room"; import { Room } from "matrix-js-sdk/src/models/room";
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
import dis from "../../../dispatcher/dispatcher"; import dis from "../../../dispatcher/dispatcher";
import * as sdk from "../../../index";
import Modal from "../../../Modal"; import Modal from "../../../Modal";
import { isValid3pidInvite } from "../../../RoomInvite"; import { isValid3pidInvite } from "../../../RoomInvite";
import RoomAvatar from "../avatars/RoomAvatar"; import RoomAvatar from "../avatars/RoomAvatar";
import RoomName from "../elements/RoomName"; import RoomName from "../elements/RoomName";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import ErrorDialog from '../dialogs/ErrorDialog';
import AccessibleButton from '../elements/AccessibleButton';
interface IProps { interface IProps {
event: MatrixEvent; event: MatrixEvent;
@ -104,7 +105,6 @@ export default class ThirdPartyMemberInfo extends React.Component<IProps, IState
// Revert echo because of error // Revert echo because of error
this.setState({ invited: true }); this.setState({ invited: true });
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Revoke 3pid invite failed', '', ErrorDialog, { Modal.createTrackedDialog('Revoke 3pid invite failed', '', ErrorDialog, {
title: _t("Failed to revoke invite"), title: _t("Failed to revoke invite"),
description: _t( description: _t(
@ -119,8 +119,6 @@ export default class ThirdPartyMemberInfo extends React.Component<IProps, IState
}; };
render() { render() {
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
let adminTools = null; let adminTools = null;
if (this.state.canKick && this.state.invited) { if (this.state.canKick && this.state.invited) {
adminTools = ( adminTools = (

View file

@ -16,15 +16,14 @@ limitations under the License.
import React from 'react'; import React from 'react';
import * as sdk from '../../../index';
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
import { SettingLevel } from "../../../settings/SettingLevel"; import { SettingLevel } from "../../../settings/SettingLevel";
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import SettingsFlag from '../elements/SettingsFlag';
const SETTING_MANUALLY_VERIFY_ALL_SESSIONS = "e2ee.manuallyVerifyAllSessions"; const SETTING_MANUALLY_VERIFY_ALL_SESSIONS = "e2ee.manuallyVerifyAllSessions";
const E2eAdvancedPanel = props => { const E2eAdvancedPanel = props => {
const SettingsFlag = sdk.getComponent('views.elements.SettingsFlag');
return <div className="mx_SettingsTab_section"> return <div className="mx_SettingsTab_section">
<span className="mx_SettingsTab_subheading">{_t("Encryption")}</span> <span className="mx_SettingsTab_subheading">{_t("Encryption")}</span>

View file

@ -18,7 +18,6 @@ import React from 'react';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import SdkConfig from "../../../SdkConfig"; import SdkConfig from "../../../SdkConfig";
import * as sdk from '../../../index';
import Modal from '../../../Modal'; import Modal from '../../../Modal';
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import AccessibleButton from "../elements/AccessibleButton"; import AccessibleButton from "../elements/AccessibleButton";
@ -27,6 +26,7 @@ import EventIndexPeg from "../../../indexing/EventIndexPeg";
import { SettingLevel } from "../../../settings/SettingLevel"; import { SettingLevel } from "../../../settings/SettingLevel";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import SeshatResetDialog from '../dialogs/SeshatResetDialog'; import SeshatResetDialog from '../dialogs/SeshatResetDialog';
import InlineSpinner from '../elements/InlineSpinner';
interface IState { interface IState {
enabling: boolean; enabling: boolean;
@ -147,7 +147,6 @@ export default class EventIndexPanel extends React.Component<{}, IState> {
render() { render() {
let eventIndexingSettings = null; let eventIndexingSettings = null;
const InlineSpinner = sdk.getComponent('elements.InlineSpinner');
const brand = SdkConfig.get().brand; const brand = SdkConfig.get().brand;
if (EventIndexPeg.get() !== null) { if (EventIndexPeg.get() !== null) {

View file

@ -17,7 +17,6 @@ limitations under the License.
import url from 'url'; import url from 'url';
import React from 'react'; import React from 'react';
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
import * as sdk from '../../../index';
import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { MatrixClientPeg } from "../../../MatrixClientPeg";
import Modal from '../../../Modal'; import Modal from '../../../Modal';
import dis from "../../../dispatcher/dispatcher"; import dis from "../../../dispatcher/dispatcher";
@ -28,6 +27,10 @@ import { getDefaultIdentityServerUrl, doesIdentityServerHaveTerms } from '../../
import { timeout } from "../../../utils/promise"; import { timeout } from "../../../utils/promise";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import { ActionPayload } from '../../../dispatcher/payloads'; import { ActionPayload } from '../../../dispatcher/payloads';
import InlineSpinner from '../elements/InlineSpinner';
import AccessibleButton from '../elements/AccessibleButton';
import Field from '../elements/Field';
import QuestionDialog from "../dialogs/QuestionDialog";
// We'll wait up to this long when checking for 3PID bindings on the IS. // We'll wait up to this long when checking for 3PID bindings on the IS.
const REACHABILITY_TIMEOUT = 10000; // ms const REACHABILITY_TIMEOUT = 10000; // ms
@ -126,7 +129,6 @@ export default class SetIdServer extends React.Component<IProps, IState> {
private getTooltip = () => { private getTooltip = () => {
if (this.state.checking) { if (this.state.checking) {
const InlineSpinner = sdk.getComponent('views.elements.InlineSpinner');
return <div> return <div>
<InlineSpinner /> <InlineSpinner />
{ _t("Checking server") } { _t("Checking server") }
@ -217,7 +219,6 @@ export default class SetIdServer extends React.Component<IProps, IState> {
}; };
private showNoTermsWarning(fullUrl) { private showNoTermsWarning(fullUrl) {
const QuestionDialog = sdk.getComponent("views.dialogs.QuestionDialog");
const { finished } = Modal.createTrackedDialog('No Terms Warning', '', QuestionDialog, { const { finished } = Modal.createTrackedDialog('No Terms Warning', '', QuestionDialog, {
title: _t("Identity server has no terms of service"), title: _t("Identity server has no terms of service"),
description: ( description: (
@ -319,7 +320,6 @@ export default class SetIdServer extends React.Component<IProps, IState> {
message = unboundMessage; message = unboundMessage;
} }
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
const { finished } = Modal.createTrackedDialog('Identity Server Bound Warning', '', QuestionDialog, { const { finished } = Modal.createTrackedDialog('Identity Server Bound Warning', '', QuestionDialog, {
title, title,
description: message, description: message,
@ -352,8 +352,6 @@ export default class SetIdServer extends React.Component<IProps, IState> {
}; };
render() { render() {
const AccessibleButton = sdk.getComponent('views.elements.AccessibleButton');
const Field = sdk.getComponent('elements.Field');
const idServerUrl = this.state.currentClientIdServer; const idServerUrl = this.state.currentClientIdServer;
let sectionTitle; let sectionTitle;
let bodyText; let bodyText;
@ -398,7 +396,6 @@ export default class SetIdServer extends React.Component<IProps, IState> {
discoButtonContent = _t("Do not use an identity server"); discoButtonContent = _t("Do not use an identity server");
} }
if (this.state.disconnectBusy) { if (this.state.disconnectBusy) {
const InlineSpinner = sdk.getComponent('views.elements.InlineSpinner');
discoButtonContent = <InlineSpinner />; discoButtonContent = <InlineSpinner />;
} }
discoSection = <div> discoSection = <div>

View file

@ -17,7 +17,6 @@ limitations under the License.
import React from 'react'; import React from 'react';
import { _t, _td } from "../../../../../languageHandler"; import { _t, _td } from "../../../../../languageHandler";
import { MatrixClientPeg } from "../../../../../MatrixClientPeg"; import { MatrixClientPeg } from "../../../../../MatrixClientPeg";
import * as sdk from "../../../../..";
import AccessibleButton from "../../../elements/AccessibleButton"; import AccessibleButton from "../../../elements/AccessibleButton";
import Modal from "../../../../../Modal"; import Modal from "../../../../../Modal";
import { replaceableComponent } from "../../../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../../../utils/replaceableComponent";
@ -26,6 +25,8 @@ 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 { RoomState } from "matrix-js-sdk/src/models/room-state"; import { RoomState } from "matrix-js-sdk/src/models/room-state";
import { compare } from "../../../../../utils/strings"; import { compare } from "../../../../../utils/strings";
import ErrorDialog from '../../../dialogs/ErrorDialog';
import PowerSelector from "../../../elements/PowerSelector";
const plEventsToLabels = { const plEventsToLabels = {
// These will be translated for us later. // These will be translated for us later.
@ -76,7 +77,6 @@ interface IBannedUserProps {
export class BannedUser extends React.Component<IBannedUserProps> { export class BannedUser extends React.Component<IBannedUserProps> {
private onUnbanClick = (e) => { private onUnbanClick = (e) => {
MatrixClientPeg.get().unban(this.props.member.roomId, this.props.member.userId).catch((err) => { MatrixClientPeg.get().unban(this.props.member.roomId, this.props.member.userId).catch((err) => {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Failed to unban: " + err); console.error("Failed to unban: " + err);
Modal.createTrackedDialog('Failed to unban', '', ErrorDialog, { Modal.createTrackedDialog('Failed to unban', '', ErrorDialog, {
title: _t('Error'), title: _t('Error'),
@ -176,7 +176,6 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
client.sendStateEvent(this.props.roomId, "m.room.power_levels", plContent).catch(e => { client.sendStateEvent(this.props.roomId, "m.room.power_levels", plContent).catch(e => {
console.error(e); console.error(e);
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Power level requirement change failed', '', ErrorDialog, { Modal.createTrackedDialog('Power level requirement change failed', '', ErrorDialog, {
title: _t('Error changing power level requirement'), title: _t('Error changing power level requirement'),
description: _t( description: _t(
@ -203,7 +202,6 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
client.sendStateEvent(this.props.roomId, "m.room.power_levels", plContent).catch(e => { client.sendStateEvent(this.props.roomId, "m.room.power_levels", plContent).catch(e => {
console.error(e); console.error(e);
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Power level change failed', '', ErrorDialog, { Modal.createTrackedDialog('Power level change failed', '', ErrorDialog, {
title: _t('Error changing power level'), title: _t('Error changing power level'),
description: _t( description: _t(
@ -215,8 +213,6 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
}; };
render() { render() {
const PowerSelector = sdk.getComponent('elements.PowerSelector');
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.get();
const room = client.getRoom(this.props.roomId); const room = client.getRoom(this.props.roomId);
const plEvent = room.currentState.getStateEvents('m.room.power_levels', ''); const plEvent = room.currentState.getStateEvents('m.room.power_levels', '');

View file

@ -18,7 +18,6 @@ import React from 'react';
import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { _t } from "../../../../../languageHandler"; import { _t } from "../../../../../languageHandler";
import { MatrixClientPeg } from "../../../../../MatrixClientPeg"; import { MatrixClientPeg } from "../../../../../MatrixClientPeg";
import * as sdk from "../../../../..";
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch"; import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
import Modal from "../../../../../Modal"; import Modal from "../../../../../Modal";
import QuestionDialog from "../../../dialogs/QuestionDialog"; import QuestionDialog from "../../../dialogs/QuestionDialog";
@ -27,6 +26,7 @@ import { SettingLevel } from "../../../../../settings/SettingLevel";
import SettingsStore from "../../../../../settings/SettingsStore"; import SettingsStore from "../../../../../settings/SettingsStore";
import { UIFeature } from "../../../../../settings/UIFeature"; import { UIFeature } from "../../../../../settings/UIFeature";
import { replaceableComponent } from "../../../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../../../utils/replaceableComponent";
import SettingsFlag from '../../../elements/SettingsFlag';
// Knock and private are reserved keywords which are not yet implemented. // Knock and private are reserved keywords which are not yet implemented.
export enum JoinRule { export enum JoinRule {
@ -385,8 +385,6 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
} }
render() { render() {
const SettingsFlag = sdk.getComponent("elements.SettingsFlag");
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.get();
const room = client.getRoom(this.props.roomId); const room = client.getRoom(this.props.roomId);
const isEncrypted = this.state.encrypted; const isEncrypted = this.state.encrypted;

View file

@ -22,7 +22,6 @@ import AccessibleTooltipButton from '../../../elements/AccessibleTooltipButton';
import SdkConfig from "../../../../../SdkConfig"; import SdkConfig from "../../../../../SdkConfig";
import createRoom from "../../../../../createRoom"; import createRoom from "../../../../../createRoom";
import Modal from "../../../../../Modal"; import Modal from "../../../../../Modal";
import * as sdk from "../../../../..";
import PlatformPeg from "../../../../../PlatformPeg"; import PlatformPeg from "../../../../../PlatformPeg";
import * as KeyboardShortcuts from "../../../../../accessibility/KeyboardShortcuts"; import * as KeyboardShortcuts from "../../../../../accessibility/KeyboardShortcuts";
import UpdateCheckButton from "../../UpdateCheckButton"; import UpdateCheckButton from "../../UpdateCheckButton";
@ -30,6 +29,8 @@ import { replaceableComponent } from "../../../../../utils/replaceableComponent"
import { copyPlaintext } from "../../../../../utils/strings"; import { copyPlaintext } from "../../../../../utils/strings";
import * as ContextMenu from "../../../../structures/ContextMenu"; import * as ContextMenu from "../../../../structures/ContextMenu";
import { toRightOf } from "../../../../structures/ContextMenu"; import { toRightOf } from "../../../../structures/ContextMenu";
import BugReportDialog from '../../../dialogs/BugReportDialog';
import GenericTextContextMenu from "../../../context_menus/GenericTextContextMenu";
interface IProps { interface IProps {
closeSettingsFn: () => void; closeSettingsFn: () => void;
@ -81,10 +82,6 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
}; };
private onBugReport = (e) => { private onBugReport = (e) => {
const BugReportDialog = sdk.getComponent("dialogs.BugReportDialog");
if (!BugReportDialog) {
return;
}
Modal.createTrackedDialog('Bug Report Dialog', '', BugReportDialog, {}); Modal.createTrackedDialog('Bug Report Dialog', '', BugReportDialog, {});
}; };
@ -171,7 +168,6 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
const successful = await copyPlaintext(MatrixClientPeg.get().getAccessToken()); const successful = await copyPlaintext(MatrixClientPeg.get().getAccessToken());
const buttonRect = target.getBoundingClientRect(); const buttonRect = target.getBoundingClientRect();
const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu');
const { close } = ContextMenu.createMenu(GenericTextContextMenu, { const { close } = ContextMenu.createMenu(GenericTextContextMenu, {
...toRightOf(buttonRect, 2), ...toRightOf(buttonRect, 2),
message: successful ? _t('Copied!') : _t('Failed to copy'), message: successful ? _t('Copied!') : _t('Failed to copy'),

View file

@ -22,8 +22,11 @@ import { ListRule } from "../../../../../mjolnir/ListRule";
import { BanList, RULE_SERVER, RULE_USER } from "../../../../../mjolnir/BanList"; import { BanList, RULE_SERVER, RULE_USER } from "../../../../../mjolnir/BanList";
import Modal from "../../../../../Modal"; import Modal from "../../../../../Modal";
import { MatrixClientPeg } from "../../../../../MatrixClientPeg"; import { MatrixClientPeg } from "../../../../../MatrixClientPeg";
import * as sdk from "../../../../../index";
import { replaceableComponent } from "../../../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../../../utils/replaceableComponent";
import ErrorDialog from "../../../dialogs/ErrorDialog";
import QuestionDialog from "../../../dialogs/QuestionDialog";
import AccessibleButton from "../../../elements/AccessibleButton";
import Field from "../../../elements/Field";
interface IState { interface IState {
busy: boolean; busy: boolean;
@ -68,7 +71,6 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
} catch (e) { } catch (e) {
console.error(e); console.error(e);
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to add Mjolnir rule', '', ErrorDialog, { Modal.createTrackedDialog('Failed to add Mjolnir rule', '', ErrorDialog, {
title: _t('Error adding ignored user/server'), title: _t('Error adding ignored user/server'),
description: _t('Something went wrong. Please try again or view your console for hints.'), description: _t('Something went wrong. Please try again or view your console for hints.'),
@ -90,7 +92,6 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
} catch (e) { } catch (e) {
console.error(e); console.error(e);
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to subscribe to Mjolnir list', '', ErrorDialog, { Modal.createTrackedDialog('Failed to subscribe to Mjolnir list', '', ErrorDialog, {
title: _t('Error subscribing to list'), title: _t('Error subscribing to list'),
description: _t('Please verify the room ID or address and try again.'), description: _t('Please verify the room ID or address and try again.'),
@ -108,7 +109,6 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
} catch (e) { } catch (e) {
console.error(e); console.error(e);
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to remove Mjolnir rule', '', ErrorDialog, { Modal.createTrackedDialog('Failed to remove Mjolnir rule', '', ErrorDialog, {
title: _t('Error removing ignored user/server'), title: _t('Error removing ignored user/server'),
description: _t('Something went wrong. Please try again or view your console for hints.'), description: _t('Something went wrong. Please try again or view your console for hints.'),
@ -126,7 +126,6 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
} catch (e) { } catch (e) {
console.error(e); console.error(e);
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to unsubscribe from Mjolnir list', '', ErrorDialog, { Modal.createTrackedDialog('Failed to unsubscribe from Mjolnir list', '', ErrorDialog, {
title: _t('Error unsubscribing from list'), title: _t('Error unsubscribing from list'),
description: _t('Please try again or view your console for hints.'), description: _t('Please try again or view your console for hints.'),
@ -137,8 +136,6 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
} }
private viewListRules(list: BanList) { private viewListRules(list: BanList) {
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
const room = MatrixClientPeg.get().getRoom(list.roomId); const room = MatrixClientPeg.get().getRoom(list.roomId);
const name = room ? room.name : list.roomId; const name = room ? room.name : list.roomId;
@ -168,8 +165,6 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
} }
private renderPersonalBanListRules() { private renderPersonalBanListRules() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const list = Mjolnir.sharedInstance().getPersonalList(); const list = Mjolnir.sharedInstance().getPersonalList();
const rules = list ? [...list.userRules, ...list.serverRules] : []; const rules = list ? [...list.userRules, ...list.serverRules] : [];
if (!list || rules.length <= 0) return <i>{_t("You have not ignored anyone.")}</i>; if (!list || rules.length <= 0) return <i>{_t("You have not ignored anyone.")}</i>;
@ -199,8 +194,6 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
} }
private renderSubscribedBanLists() { private renderSubscribedBanLists() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const personalList = Mjolnir.sharedInstance().getPersonalList(); const personalList = Mjolnir.sharedInstance().getPersonalList();
const lists = Mjolnir.sharedInstance().lists.filter(b => { const lists = Mjolnir.sharedInstance().lists.filter(b => {
return personalList? personalList.roomId !== b.roomId : true; return personalList? personalList.roomId !== b.roomId : true;
@ -241,8 +234,6 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
} }
render() { render() {
const Field = sdk.getComponent('elements.Field');
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const brand = SdkConfig.get().brand; const brand = SdkConfig.get().brand;
return ( return (

View file

@ -20,10 +20,10 @@ import { _t } from "../../../../../languageHandler";
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch"; import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
import SettingsStore from "../../../../../settings/SettingsStore"; import SettingsStore from "../../../../../settings/SettingsStore";
import Field from "../../../elements/Field"; import Field from "../../../elements/Field";
import * as sdk from "../../../../..";
import PlatformPeg from "../../../../../PlatformPeg"; import PlatformPeg from "../../../../../PlatformPeg";
import { SettingLevel } from "../../../../../settings/SettingLevel"; import { SettingLevel } from "../../../../../settings/SettingLevel";
import { replaceableComponent } from "../../../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../../../utils/replaceableComponent";
import SettingsFlag from '../../../elements/SettingsFlag';
import * as KeyboardShortcuts from "../../../../../accessibility/KeyboardShortcuts"; import * as KeyboardShortcuts from "../../../../../accessibility/KeyboardShortcuts";
import AccessibleButton from "../../../elements/AccessibleButton"; import AccessibleButton from "../../../elements/AccessibleButton";
@ -184,7 +184,6 @@ export default class PreferencesUserSettingsTab extends React.Component<{}, ISta
}; };
private renderGroup(settingIds: string[]): React.ReactNodeArray { private renderGroup(settingIds: string[]): React.ReactNodeArray {
const SettingsFlag = sdk.getComponent("views.elements.SettingsFlag");
return settingIds.filter(SettingsStore.isEnabled).map(i => { return settingIds.filter(SettingsStore.isEnabled).map(i => {
return <SettingsFlag key={i} name={i} level={SettingLevel.ACCOUNT} />; return <SettingsFlag key={i} name={i} level={SettingLevel.ACCOUNT} />;
}); });

View file

@ -220,6 +220,7 @@ const SpaceCreateMenu = ({ onFinished }) => {
value={alias} value={alias}
placeholder={name ? nameToAlias(name, domain) : _t("e.g. my-space")} placeholder={name ? nameToAlias(name, domain) : _t("e.g. my-space")}
label={_t("Address")} label={_t("Address")}
disabled={busy}
/> />
: null : null
} }

View file

@ -96,7 +96,7 @@ const SpaceSettingsGeneralTab = ({ matrixClient: cli, space, onFinished }: IProp
{ error && <div className="mx_SpaceRoomView_errorText">{ error }</div> } { error && <div className="mx_SpaceRoomView_errorText">{ error }</div> }
<SpaceFeedbackPrompt onClick={() => onFinished(false)} /> <SpaceFeedbackPrompt />
<div className="mx_SettingsTab_section"> <div className="mx_SettingsTab_section">
<SpaceBasicSettings <SpaceBasicSettings

View file

@ -21,7 +21,6 @@ import { EventType } from "matrix-js-sdk/src/@types/event";
import { MatrixClientPeg } from './MatrixClientPeg'; import { MatrixClientPeg } from './MatrixClientPeg';
import Modal from './Modal'; import Modal from './Modal';
import * as sdk from './index';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
import dis from "./dispatcher/dispatcher"; import dis from "./dispatcher/dispatcher";
import * as Rooms from "./Rooms"; import * as Rooms from "./Rooms";
@ -37,6 +36,8 @@ import { makeSpaceParentEvent } from "./utils/space";
import { Action } from "./dispatcher/actions"; import { Action } from "./dispatcher/actions";
import { ICreateRoomOpts } from "matrix-js-sdk/src/@types/requests"; import { ICreateRoomOpts } from "matrix-js-sdk/src/@types/requests";
import { Preset, Visibility } from "matrix-js-sdk/src/@types/partials"; import { Preset, Visibility } from "matrix-js-sdk/src/@types/partials";
import ErrorDialog from "./components/views/dialogs/ErrorDialog";
import Spinner from "./components/views/elements/Spinner";
// we define a number of interfaces which take their names from the js-sdk // we define a number of interfaces which take their names from the js-sdk
/* eslint-disable camelcase */ /* eslint-disable camelcase */
@ -80,9 +81,6 @@ export default function createRoom(opts: IOpts): Promise<string | null> {
const startTime = CountlyAnalytics.getTimestamp(); const startTime = CountlyAnalytics.getTimestamp();
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
const Loader = sdk.getComponent("elements.Spinner");
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.get();
if (client.isGuest()) { if (client.isGuest()) {
dis.dispatch({ action: 'require_registration' }); dis.dispatch({ action: 'require_registration' });
@ -153,7 +151,7 @@ export default function createRoom(opts: IOpts): Promise<string | null> {
} }
let modal; let modal;
if (opts.spinner) modal = Modal.createDialog(Loader, null, 'mx_Dialog_spinner'); if (opts.spinner) modal = Modal.createDialog(Spinner, null, 'mx_Dialog_spinner');
let roomId; let roomId;
return client.createRoom(createOpts).finally(function() { return client.createRoom(createOpts).finally(function() {

Some files were not shown because too many files have changed in this diff Show more