Merge pull request #6285 from matrix-org/jryans/rework-linting-2

Migrate to `eslint-plugin-matrix-org`
This commit is contained in:
J. Ryan Stinnett 2021-06-29 17:45:10 +01:00 committed by GitHub
commit 9d6d8fc666
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
636 changed files with 3460 additions and 3935 deletions

View file

@ -1,7 +1,9 @@
module.exports = { module.exports = {
extends: ["matrix-org", "matrix-org/react-legacy"], plugins: ["matrix-org"],
parser: "babel-eslint", extends: [
"plugin:matrix-org/babel",
"plugin:matrix-org/react",
],
env: { env: {
browser: true, browser: true,
node: true, node: true,
@ -15,12 +17,32 @@ module.exports = {
"prefer-promise-reject-errors": "off", "prefer-promise-reject-errors": "off",
"no-async-promise-executor": "off", "no-async-promise-executor": "off",
"quotes": "off", "quotes": "off",
}, "no-extra-boolean-cast": "off",
// Bind or arrow functions in props causes performance issues (but we
// currently use them in some places).
// It's disabled here, but we should using it sparingly.
"react/jsx-no-bind": "off",
"react/jsx-key": ["error"],
},
overrides: [{ overrides: [{
"files": ["src/**/*.{ts,tsx}", "test/**/*.{ts,tsx}"], files: [
"extends": ["matrix-org/ts"], "src/**/*.{ts,tsx}",
"rules": { "test/**/*.{ts,tsx}",
],
extends: [
"plugin:matrix-org/typescript",
"plugin:matrix-org/react",
],
rules: {
// Things we do that break the ideal style
"prefer-promise-reject-errors": "off",
"quotes": "off",
"no-extra-boolean-cast": "off",
// Remove Babel things manually due to override limitations
"@babel/no-invalid-this": ["off"],
// We're okay being explicit at the moment // We're okay being explicit at the moment
"@typescript-eslint/no-empty-interface": "off", "@typescript-eslint/no-empty-interface": "off",
// We disable this while we're transitioning // We disable this while we're transitioning
@ -28,8 +50,6 @@ module.exports = {
// We'd rather not do this but we do // We'd rather not do this but we do
"@typescript-eslint/ban-ts-comment": "off", "@typescript-eslint/ban-ts-comment": "off",
"quotes": "off",
"no-extra-boolean-cast": "off",
"no-restricted-properties": [ "no-restricted-properties": [
"error", "error",
...buildRestrictedPropertiesOptions( ...buildRestrictedPropertiesOptions(

View file

@ -1,6 +0,0 @@
[include]
src/**/*.js
test/**/*.js
[ignore]
node_modules/

View file

@ -10,7 +10,6 @@ module.exports = {
], ],
}], }],
"@babel/preset-typescript", "@babel/preset-typescript",
"@babel/preset-flow",
"@babel/preset-react", "@babel/preset-react",
], ],
"plugins": [ "plugins": [
@ -19,7 +18,6 @@ module.exports = {
"@babel/plugin-proposal-numeric-separator", "@babel/plugin-proposal-numeric-separator",
"@babel/plugin-proposal-class-properties", "@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-object-rest-spread", "@babel/plugin-proposal-object-rest-spread",
"@babel/plugin-transform-flow-comments",
"@babel/plugin-syntax-dynamic-import", "@babel/plugin-syntax-dynamic-import",
"@babel/plugin-transform-runtime", "@babel/plugin-transform-runtime",
], ],

View file

@ -104,16 +104,16 @@
"devDependencies": { "devDependencies": {
"@babel/cli": "^7.12.10", "@babel/cli": "^7.12.10",
"@babel/core": "^7.12.10", "@babel/core": "^7.12.10",
"@babel/eslint-parser": "^7.12.10",
"@babel/eslint-plugin": "^7.12.10",
"@babel/parser": "^7.12.11", "@babel/parser": "^7.12.11",
"@babel/plugin-proposal-class-properties": "^7.12.1", "@babel/plugin-proposal-class-properties": "^7.12.1",
"@babel/plugin-proposal-decorators": "^7.12.12", "@babel/plugin-proposal-decorators": "^7.12.12",
"@babel/plugin-proposal-export-default-from": "^7.12.1", "@babel/plugin-proposal-export-default-from": "^7.12.1",
"@babel/plugin-proposal-numeric-separator": "^7.12.7", "@babel/plugin-proposal-numeric-separator": "^7.12.7",
"@babel/plugin-proposal-object-rest-spread": "^7.12.1", "@babel/plugin-proposal-object-rest-spread": "^7.12.1",
"@babel/plugin-transform-flow-comments": "^7.12.1",
"@babel/plugin-transform-runtime": "^7.12.10", "@babel/plugin-transform-runtime": "^7.12.10",
"@babel/preset-env": "^7.12.11", "@babel/preset-env": "^7.12.11",
"@babel/preset-flow": "^7.12.1",
"@babel/preset-react": "^7.12.10", "@babel/preset-react": "^7.12.10",
"@babel/preset-typescript": "^7.12.7", "@babel/preset-typescript": "^7.12.7",
"@babel/register": "^7.12.10", "@babel/register": "^7.12.10",
@ -139,18 +139,16 @@
"@types/react-transition-group": "^4.4.0", "@types/react-transition-group": "^4.4.0",
"@types/sanitize-html": "^2.3.1", "@types/sanitize-html": "^2.3.1",
"@types/zxcvbn": "^4.4.0", "@types/zxcvbn": "^4.4.0",
"@typescript-eslint/eslint-plugin": "^4.14.0", "@typescript-eslint/eslint-plugin": "^4.17.0",
"@typescript-eslint/parser": "^4.14.0", "@typescript-eslint/parser": "^4.17.0",
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.1", "@wojtekmaj/enzyme-adapter-react-17": "^0.6.1",
"babel-eslint": "^10.1.0",
"babel-jest": "^26.6.3", "babel-jest": "^26.6.3",
"chokidar": "^3.5.1", "chokidar": "^3.5.1",
"concurrently": "^5.3.0", "concurrently": "^5.3.0",
"enzyme": "^3.11.0", "enzyme": "^3.11.0",
"eslint": "7.18.0", "eslint": "7.18.0",
"eslint-config-matrix-org": "^0.2.0", "eslint-config-google": "^0.14.0",
"eslint-plugin-babel": "^5.3.1", "eslint-plugin-matrix-org": "github:matrix-org/eslint-plugin-matrix-org#main",
"eslint-plugin-flowtype": "^5.2.0",
"eslint-plugin-react": "^7.22.0", "eslint-plugin-react": "^7.22.0",
"eslint-plugin-react-hooks": "^4.2.0", "eslint-plugin-react-hooks": "^4.2.0",
"glob": "^7.1.6", "glob": "^7.1.6",

View file

@ -17,7 +17,7 @@ limitations under the License.
import { JSXElementConstructor } from "react"; import { JSXElementConstructor } from "react";
// Based on https://stackoverflow.com/a/53229857/3532235 // Based on https://stackoverflow.com/a/53229857/3532235
export type Without<T, U> = {[P in Exclude<keyof T, keyof U>] ? : never}; export type Without<T, U> = {[P in Exclude<keyof T, keyof U>]?: never};
export type XOR<T, U> = (T | U) extends object ? (Without<T, U> & U) | (Without<U, T> & T) : T | U; export type XOR<T, U> = (T | U) extends object ? (Without<T, U> & U) | (Without<U, T> & T) : T | U;
export type Writeable<T> = { -readonly [P in keyof T]: T[P] }; export type Writeable<T> = { -readonly [P in keyof T]: T[P] };

View file

@ -23,25 +23,25 @@ import DeviceListener from "../DeviceListener";
import { RoomListStoreClass } from "../stores/room-list/RoomListStore"; import { RoomListStoreClass } from "../stores/room-list/RoomListStore";
import { PlatformPeg } from "../PlatformPeg"; import { PlatformPeg } from "../PlatformPeg";
import RoomListLayoutStore from "../stores/room-list/RoomListLayoutStore"; import RoomListLayoutStore from "../stores/room-list/RoomListLayoutStore";
import {IntegrationManagers} from "../integrations/IntegrationManagers"; import { IntegrationManagers } from "../integrations/IntegrationManagers";
import {ModalManager} from "../Modal"; import { ModalManager } from "../Modal";
import SettingsStore from "../settings/SettingsStore"; import SettingsStore from "../settings/SettingsStore";
import {ActiveRoomObserver} from "../ActiveRoomObserver"; import { ActiveRoomObserver } from "../ActiveRoomObserver";
import {Notifier} from "../Notifier"; import { Notifier } from "../Notifier";
import type {Renderer} from "react-dom"; import type { Renderer } from "react-dom";
import RightPanelStore from "../stores/RightPanelStore"; import RightPanelStore from "../stores/RightPanelStore";
import WidgetStore from "../stores/WidgetStore"; import WidgetStore from "../stores/WidgetStore";
import CallHandler from "../CallHandler"; import CallHandler from "../CallHandler";
import {Analytics} from "../Analytics"; import { Analytics } from "../Analytics";
import CountlyAnalytics from "../CountlyAnalytics"; import CountlyAnalytics from "../CountlyAnalytics";
import UserActivity from "../UserActivity"; import UserActivity from "../UserActivity";
import {ModalWidgetStore} from "../stores/ModalWidgetStore"; import { ModalWidgetStore } from "../stores/ModalWidgetStore";
import { WidgetLayoutStore } from "../stores/widgets/WidgetLayoutStore"; import { WidgetLayoutStore } from "../stores/widgets/WidgetLayoutStore";
import VoipUserMapper from "../VoipUserMapper"; import VoipUserMapper from "../VoipUserMapper";
import {SpaceStoreClass} from "../stores/SpaceStore"; import { SpaceStoreClass } from "../stores/SpaceStore";
import TypingStore from "../stores/TypingStore"; import TypingStore from "../stores/TypingStore";
import { EventIndexPeg } from "../indexing/EventIndexPeg"; import { EventIndexPeg } from "../indexing/EventIndexPeg";
import {VoiceRecordingStore} from "../stores/VoiceRecordingStore"; import { VoiceRecordingStore } from "../stores/VoiceRecordingStore";
import PerformanceMonitor from "../performance"; import PerformanceMonitor from "../performance";
import UIStore from "../stores/UIStore"; import UIStore from "../stores/UIStore";
import { SetupEncryptionStore } from "../stores/SetupEncryptionStore"; import { SetupEncryptionStore } from "../stores/SetupEncryptionStore";

View file

@ -16,12 +16,12 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {MatrixClientPeg} from './MatrixClientPeg'; import { MatrixClientPeg } from './MatrixClientPeg';
import * as sdk from './index'; import * as sdk from './index';
import Modal from './Modal'; import Modal from './Modal';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
import IdentityAuthClient from './IdentityAuthClient'; import IdentityAuthClient from './IdentityAuthClient';
import {SSOAuthEntry} from "./components/views/auth/InteractiveAuthEntryComponents"; import { SSOAuthEntry } from "./components/views/auth/InteractiveAuthEntryComponents";
function getIdServerDomain() { function getIdServerDomain() {
return MatrixClientPeg.get().idBaseUrl.split("://")[1]; return MatrixClientPeg.get().idBaseUrl.split("://")[1];
@ -189,7 +189,6 @@ export default class AddThreepid {
// pop up an interactive auth dialog // pop up an interactive auth dialog
const InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog"); const InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog");
const dialogAesthetics = { const dialogAesthetics = {
[SSOAuthEntry.PHASE_PREAUTH]: { [SSOAuthEntry.PHASE_PREAUTH]: {
title: _t("Use Single Sign On to continue"), title: _t("Use Single Sign On to continue"),

View file

@ -17,7 +17,7 @@ limitations under the License.
import React from 'react'; import React from 'react';
import {getCurrentLanguage, _t, _td, IVariables} from './languageHandler'; import { getCurrentLanguage, _t, _td, IVariables } from './languageHandler';
import PlatformPeg from './PlatformPeg'; import PlatformPeg from './PlatformPeg';
import SdkConfig from './SdkConfig'; import SdkConfig from './SdkConfig';
import Modal from './Modal'; import Modal from './Modal';

View file

@ -17,16 +17,16 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {MatrixClient} from "matrix-js-sdk/src/client"; import { MatrixClient } from "matrix-js-sdk/src/client";
import {encodeUnpaddedBase64} from "matrix-js-sdk/src/crypto/olmlib"; import { encodeUnpaddedBase64 } from "matrix-js-sdk/src/crypto/olmlib";
import dis from './dispatcher/dispatcher'; import dis from './dispatcher/dispatcher';
import BaseEventIndexManager from './indexing/BaseEventIndexManager'; import BaseEventIndexManager from './indexing/BaseEventIndexManager';
import {ActionPayload} from "./dispatcher/payloads"; import { ActionPayload } from "./dispatcher/payloads";
import {CheckUpdatesPayload} from "./dispatcher/payloads/CheckUpdatesPayload"; import { CheckUpdatesPayload } from "./dispatcher/payloads/CheckUpdatesPayload";
import {Action} from "./dispatcher/actions"; import { Action } from "./dispatcher/actions";
import {hideToast as hideUpdateToast} from "./toasts/UpdateToast"; import { hideToast as hideUpdateToast } from "./toasts/UpdateToast";
import {MatrixClientPeg} from "./MatrixClientPeg"; import { MatrixClientPeg } from "./MatrixClientPeg";
import {idbLoad, idbSave, idbDelete} from "./utils/StorageManager"; import { idbLoad, idbSave, idbDelete } from "./utils/StorageManager";
export const SSO_HOMESERVER_URL_KEY = "mx_sso_hs_url"; export const SSO_HOMESERVER_URL_KEY = "mx_sso_hs_url";
export const SSO_ID_SERVER_URL_KEY = "mx_sso_is_url"; export const SSO_ID_SERVER_URL_KEY = "mx_sso_is_url";
@ -335,7 +335,7 @@ export default abstract class BasePlatform {
try { try {
const key = await crypto.subtle.decrypt( const key = await crypto.subtle.decrypt(
{name: "AES-GCM", iv: data.iv, additionalData}, data.cryptoKey, { name: "AES-GCM", iv: data.iv, additionalData }, data.cryptoKey,
data.encrypted, data.encrypted,
); );
return encodeUnpaddedBase64(key); return encodeUnpaddedBase64(key);
@ -360,7 +360,7 @@ export default abstract class BasePlatform {
const randomArray = new Uint8Array(32); const randomArray = new Uint8Array(32);
crypto.getRandomValues(randomArray); crypto.getRandomValues(randomArray);
const cryptoKey = await crypto.subtle.generateKey( const cryptoKey = await crypto.subtle.generateKey(
{name: "AES-GCM", length: 256}, false, ["encrypt", "decrypt"], { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"],
); );
const iv = new Uint8Array(32); const iv = new Uint8Array(32);
crypto.getRandomValues(iv); crypto.getRandomValues(iv);
@ -375,11 +375,11 @@ export default abstract class BasePlatform {
} }
const encrypted = await crypto.subtle.encrypt( const encrypted = await crypto.subtle.encrypt(
{name: "AES-GCM", iv, additionalData}, cryptoKey, randomArray, { name: "AES-GCM", iv, additionalData }, cryptoKey, randomArray,
); );
try { try {
await idbSave("pickleKey", [userId, deviceId], {encrypted, iv, cryptoKey}); await idbSave("pickleKey", [userId, deviceId], { encrypted, iv, cryptoKey });
} catch (e) { } catch (e) {
return null; return null;
} }

View file

@ -55,7 +55,7 @@ limitations under the License.
import React from 'react'; import React from 'react';
import {MatrixClientPeg} from './MatrixClientPeg'; import { MatrixClientPeg } from './MatrixClientPeg';
import PlatformPeg from './PlatformPeg'; import PlatformPeg from './PlatformPeg';
import Modal from './Modal'; import Modal from './Modal';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
@ -63,11 +63,11 @@ import dis from './dispatcher/dispatcher';
import WidgetUtils from './utils/WidgetUtils'; import WidgetUtils from './utils/WidgetUtils';
import WidgetEchoStore from './stores/WidgetEchoStore'; import WidgetEchoStore from './stores/WidgetEchoStore';
import SettingsStore from './settings/SettingsStore'; import SettingsStore from './settings/SettingsStore';
import {Jitsi} from "./widgets/Jitsi"; import { Jitsi } from "./widgets/Jitsi";
import {WidgetType} from "./widgets/WidgetType"; import { WidgetType } from "./widgets/WidgetType";
import {SettingLevel} from "./settings/SettingLevel"; import { SettingLevel } from "./settings/SettingLevel";
import { ActionPayload } from "./dispatcher/payloads"; import { ActionPayload } from "./dispatcher/payloads";
import {base32} from "rfc4648"; import { base32 } from "rfc4648";
import QuestionDialog from "./components/views/dialogs/QuestionDialog"; import QuestionDialog from "./components/views/dialogs/QuestionDialog";
import ErrorDialog from "./components/views/dialogs/ErrorDialog"; import ErrorDialog from "./components/views/dialogs/ErrorDialog";
@ -77,10 +77,10 @@ import { ElementWidgetActions } from "./stores/widgets/ElementWidgetActions";
import { MatrixCall, CallErrorCode, CallState, CallEvent, CallParty, CallType } from "matrix-js-sdk/src/webrtc/call"; import { MatrixCall, CallErrorCode, CallState, CallEvent, CallParty, CallType } from "matrix-js-sdk/src/webrtc/call";
import Analytics from './Analytics'; import Analytics from './Analytics';
import CountlyAnalytics from "./CountlyAnalytics"; import CountlyAnalytics from "./CountlyAnalytics";
import {UIFeature} from "./settings/UIFeature"; import { UIFeature } from "./settings/UIFeature";
import { CallError } from "matrix-js-sdk/src/webrtc/call"; import { CallError } from "matrix-js-sdk/src/webrtc/call";
import { logger } from 'matrix-js-sdk/src/logger'; import { logger } from 'matrix-js-sdk/src/logger';
import DesktopCapturerSourcePicker from "./components/views/elements/DesktopCapturerSourcePicker" import DesktopCapturerSourcePicker from "./components/views/elements/DesktopCapturerSourcePicker";
import { Action } from './dispatcher/actions'; import { Action } from './dispatcher/actions';
import VoipUserMapper from './VoipUserMapper'; import VoipUserMapper from './VoipUserMapper';
import { addManagedHybridWidget, isManagedHybridWidgetEnabled } from './widgets/ManagedHybrid'; import { addManagedHybridWidget, isManagedHybridWidgetEnabled } from './widgets/ManagedHybrid';
@ -166,7 +166,7 @@ export default class CallHandler extends EventEmitter {
static sharedInstance() { static sharedInstance() {
if (!window.mxCallHandler) { if (!window.mxCallHandler) {
window.mxCallHandler = new CallHandler() window.mxCallHandler = new CallHandler();
} }
return window.mxCallHandler; return window.mxCallHandler;
@ -185,7 +185,7 @@ export default class CallHandler extends EventEmitter {
const nativeUser = this.assertedIdentityNativeUsers[call.callId]; const nativeUser = this.assertedIdentityNativeUsers[call.callId];
if (nativeUser) { if (nativeUser) {
const room = findDMForUser(MatrixClientPeg.get(), nativeUser); const room = findDMForUser(MatrixClientPeg.get(), nativeUser);
if (room) return room.roomId if (room) return room.roomId;
} }
} }
@ -238,7 +238,7 @@ export default class CallHandler extends EventEmitter {
this.supportsPstnProtocol = null; this.supportsPstnProtocol = null;
} }
dis.dispatch({action: Action.PstnSupportUpdated}); dis.dispatch({ action: Action.PstnSupportUpdated });
if (protocols[PROTOCOL_SIP_NATIVE] !== undefined && protocols[PROTOCOL_SIP_VIRTUAL] !== undefined) { if (protocols[PROTOCOL_SIP_NATIVE] !== undefined && protocols[PROTOCOL_SIP_VIRTUAL] !== undefined) {
this.supportsSipNativeVirtual = Boolean( this.supportsSipNativeVirtual = Boolean(
@ -246,7 +246,7 @@ export default class CallHandler extends EventEmitter {
); );
} }
dis.dispatch({action: Action.VirtualRoomSupportUpdated}); dis.dispatch({ action: Action.VirtualRoomSupportUpdated });
} catch (e) { } catch (e) {
if (maxTries === 1) { if (maxTries === 1) {
console.log("Failed to check for protocol support and no retries remain: assuming no support", e); console.log("Failed to check for protocol support and no retries remain: assuming no support", e);
@ -299,7 +299,7 @@ export default class CallHandler extends EventEmitter {
action: 'incoming_call', action: 'incoming_call',
call: call, call: call,
}, true); }, true);
} };
getCallForRoom(roomId: string): MatrixCall { getCallForRoom(roomId: string): MatrixCall {
return this.calls.get(roomId) || null; return this.calls.get(roomId) || null;
@ -711,7 +711,7 @@ export default class CallHandler extends EventEmitter {
call.placeScreenSharingCall( call.placeScreenSharingCall(
async (): Promise<DesktopCapturerSource> => { async (): Promise<DesktopCapturerSource> => {
const {finished} = Modal.createDialog(DesktopCapturerSourcePicker); const { finished } = Modal.createDialog(DesktopCapturerSourcePicker);
const [source] = await finished; const [source] = await finished;
return source; return source;
}, },
@ -816,7 +816,7 @@ export default class CallHandler extends EventEmitter {
Analytics.trackEvent('voip', 'receiveCall', 'type', call.type); Analytics.trackEvent('voip', 'receiveCall', 'type', call.type);
console.log("Adding call for room ", mappedRoomId); console.log("Adding call for room ", mappedRoomId);
this.calls.set(mappedRoomId, call) this.calls.set(mappedRoomId, call);
this.emit(CallHandlerEvent.CallsChanged, this.calls); this.emit(CallHandlerEvent.CallsChanged, this.calls);
this.setCallListeners(call); this.setCallListeners(call);
@ -872,7 +872,7 @@ export default class CallHandler extends EventEmitter {
this.dialNumber(payload.number); this.dialNumber(payload.number);
break; break;
} }
} };
private async dialNumber(number: string) { private async dialNumber(number: string) {
const results = await this.pstnLookup(number); const results = await this.pstnLookup(number);
@ -966,7 +966,7 @@ export default class CallHandler extends EventEmitter {
confId = 'Jitsi' + random; confId = 'Jitsi' + random;
} }
let widgetUrl = WidgetUtils.getLocalJitsiWrapperUrl({auth: jitsiAuth}); let widgetUrl = WidgetUtils.getLocalJitsiWrapperUrl({ auth: jitsiAuth });
// TODO: Remove URL hacks when the mobile clients eventually support v2 widgets // TODO: Remove URL hacks when the mobile clients eventually support v2 widgets
const parsedUrl = new URL(widgetUrl); const parsedUrl = new URL(widgetUrl);

View file

@ -18,8 +18,8 @@ limitations under the License.
import React from "react"; import React from "react";
import dis from './dispatcher/dispatcher'; import dis from './dispatcher/dispatcher';
import {MatrixClientPeg} from './MatrixClientPeg'; import { MatrixClientPeg } from './MatrixClientPeg';
import {MatrixClient} from "matrix-js-sdk/src/client"; import { MatrixClient } from "matrix-js-sdk/src/client";
import * as sdk from './index'; import * as sdk from './index';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
import Modal from './Modal'; import Modal from './Modal';
@ -37,7 +37,7 @@ import {
UploadProgressPayload, UploadProgressPayload,
UploadStartedPayload, UploadStartedPayload,
} from "./dispatcher/payloads/UploadPayload"; } from "./dispatcher/payloads/UploadPayload";
import {IUpload} from "./models/IUpload"; import { IUpload } from "./models/IUpload";
import { IImageInfo } from "matrix-js-sdk/src/@types/partials"; import { IImageInfo } from "matrix-js-sdk/src/@types/partials";
const MAX_WIDTH = 800; const MAX_WIDTH = 800;
@ -189,7 +189,7 @@ async function loadImageElement(imageFile: File) {
const [hidpi] = await Promise.all([parsePromise, imgPromise]); const [hidpi] = await Promise.all([parsePromise, imgPromise]);
const width = hidpi ? (img.width >> 1) : img.width; const width = hidpi ? (img.width >> 1) : img.width;
const height = hidpi ? (img.height >> 1) : img.height; const height = hidpi ? (img.height >> 1) : img.height;
return {width, height, img}; return { width, height, img };
} }
/** /**
@ -343,7 +343,7 @@ export function uploadFile(
if (file.type) { if (file.type) {
encryptInfo.mimetype = file.type; encryptInfo.mimetype = file.type;
} }
return {"file": encryptInfo}; return { "file": encryptInfo };
}); });
(prom as IAbortablePromise<any>).abort = () => { (prom as IAbortablePromise<any>).abort = () => {
canceled = true; canceled = true;
@ -357,7 +357,7 @@ export function uploadFile(
const promise1 = basePromise.then(function(url) { const promise1 = basePromise.then(function(url) {
if (canceled) throw new UploadCanceledError(); if (canceled) throw new UploadCanceledError();
// If the attachment isn't encrypted then include the URL directly. // If the attachment isn't encrypted then include the URL directly.
return {"url": url}; return { "url": url };
}); });
(promise1 as any).abort = () => { (promise1 as any).abort = () => {
canceled = true; canceled = true;
@ -377,7 +377,7 @@ export default class ContentMessages {
console.warn(`Failed to send content with URL ${url} to room ${roomId}`, e); console.warn(`Failed to send content with URL ${url} to room ${roomId}`, e);
throw e; throw e;
}); });
CountlyAnalytics.instance.trackSendMessage(startTime, prom, roomId, false, false, {msgtype: "m.sticker"}); CountlyAnalytics.instance.trackSendMessage(startTime, prom, roomId, false, false, { msgtype: "m.sticker" });
return prom; return prom;
} }
@ -391,14 +391,14 @@ export default class ContentMessages {
async sendContentListToRoom(files: File[], roomId: string, matrixClient: MatrixClient) { async sendContentListToRoom(files: File[], roomId: string, matrixClient: MatrixClient) {
if (matrixClient.isGuest()) { if (matrixClient.isGuest()) {
dis.dispatch({action: 'require_registration'}); dis.dispatch({ action: 'require_registration' });
return; return;
} }
const isQuoting = Boolean(RoomViewStore.getQuotingEvent()); const isQuoting = Boolean(RoomViewStore.getQuotingEvent());
if (isQuoting) { if (isQuoting) {
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'),
description: ( description: (
<div>{_t( <div>{_t(
@ -432,7 +432,7 @@ export default class ContentMessages {
if (tooBigFiles.length > 0) { if (tooBigFiles.length > 0) {
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,
totalFiles: files.length, totalFiles: files.length,
contentMessages: this, contentMessages: this,
@ -449,7 +449,7 @@ 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) {
const {finished} = Modal.createTrackedDialog<[boolean, boolean]>('Upload Files confirmation', const { finished } = Modal.createTrackedDialog<[boolean, boolean]>('Upload Files confirmation',
'', UploadConfirmDialog, { '', UploadConfirmDialog, {
file, file,
currentIndex: i, currentIndex: i,
@ -481,7 +481,7 @@ export default class ContentMessages {
if (upload) { if (upload) {
upload.canceled = true; upload.canceled = true;
MatrixClientPeg.get().cancelUpload(upload.promise); MatrixClientPeg.get().cancelUpload(upload.promise);
dis.dispatch<UploadCanceledPayload>({action: Action.UploadCanceled, upload}); dis.dispatch<UploadCanceledPayload>({ action: Action.UploadCanceled, upload });
} }
} }
@ -542,7 +542,7 @@ export default class ContentMessages {
promise: prom, promise: prom,
}; };
this.inprogress.push(upload); this.inprogress.push(upload);
dis.dispatch<UploadStartedPayload>({action: Action.UploadStarted, upload}); dis.dispatch<UploadStartedPayload>({ action: Action.UploadStarted, upload });
// Focus the composer view // Focus the composer view
dis.fire(Action.FocusComposer); dis.fire(Action.FocusComposer);
@ -550,7 +550,7 @@ export default class ContentMessages {
function onProgress(ev) { function onProgress(ev) {
upload.total = ev.total; upload.total = ev.total;
upload.loaded = ev.loaded; upload.loaded = ev.loaded;
dis.dispatch<UploadProgressPayload>({action: Action.UploadProgress, upload}); dis.dispatch<UploadProgressPayload>({ action: Action.UploadProgress, upload });
} }
let error; let error;
@ -577,11 +577,11 @@ export default class ContentMessages {
}, function(err) { }, function(err) {
error = err; error = err;
if (!upload.canceled) { if (!upload.canceled) {
let desc = _t("The file '%(fileName)s' failed to upload.", {fileName: upload.fileName}); let desc = _t("The file '%(fileName)s' failed to upload.", { fileName: upload.fileName });
if (err.http_status === 413) { if (err.http_status === 413) {
desc = _t( desc = _t(
"The file '%(fileName)s' exceeds this homeserver's size limit for uploads", "The file '%(fileName)s' exceeds this homeserver's size limit for uploads",
{fileName: upload.fileName}, { fileName: upload.fileName },
); );
} }
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
@ -604,10 +604,10 @@ export default class ContentMessages {
if (error && error.http_status === 413) { if (error && error.http_status === 413) {
this.mediaConfig = null; this.mediaConfig = null;
} }
dis.dispatch<UploadErrorPayload>({action: Action.UploadFailed, upload, error}); dis.dispatch<UploadErrorPayload>({ action: Action.UploadFailed, upload, error });
} else { } else {
dis.dispatch<UploadFinishedPayload>({action: Action.UploadFinished, upload}); dis.dispatch<UploadFinishedPayload>({ action: Action.UploadFinished, upload });
dis.dispatch({action: 'message_sent'}); dis.dispatch({ action: 'message_sent' });
} }
}); });
} }

View file

@ -14,13 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {randomString} from "matrix-js-sdk/src/randomstring"; import { randomString } from "matrix-js-sdk/src/randomstring";
import {getCurrentLanguage} from './languageHandler'; import { getCurrentLanguage } from './languageHandler';
import PlatformPeg from './PlatformPeg'; import PlatformPeg from './PlatformPeg';
import SdkConfig from './SdkConfig'; import SdkConfig from './SdkConfig';
import {MatrixClientPeg} from "./MatrixClientPeg"; import { MatrixClientPeg } from "./MatrixClientPeg";
import {sleep} from "./utils/promise"; import { sleep } from "./utils/promise";
import RoomViewStore from "./stores/RoomViewStore"; import RoomViewStore from "./stores/RoomViewStore";
import { Action } from "./dispatcher/actions"; import { Action } from "./dispatcher/actions";
@ -338,8 +338,8 @@ const getRoomStats = (roomId: string) => {
"is_encrypted": cli?.isRoomEncrypted(roomId), "is_encrypted": cli?.isRoomEncrypted(roomId),
// eslint-disable-next-line camelcase // eslint-disable-next-line camelcase
"is_public": room?.currentState.getStateEvents("m.room.join_rules", "")?.getContent()?.join_rule === "public", "is_public": room?.currentState.getStateEvents("m.room.join_rules", "")?.getContent()?.join_rule === "public",
} };
} };
// async wrapper for regex-powered String.prototype.replace // async wrapper for regex-powered String.prototype.replace
const strReplaceAsync = async (str: string, regex: RegExp, fn: (...args: string[]) => Promise<string>) => { const strReplaceAsync = async (str: string, regex: RegExp, fn: (...args: string[]) => Promise<string>) => {
@ -414,7 +414,7 @@ export default class CountlyAnalytics {
this.anonymous = anonymous; this.anonymous = anonymous;
if (anonymous) { if (anonymous) {
await this.changeUserKey(randomString(64)) await this.changeUserKey(randomString(64));
} else { } else {
await this.changeUserKey(await hashHex(MatrixClientPeg.get().getUserId()), true); await this.changeUserKey(await hashHex(MatrixClientPeg.get().getUserId()), true);
} }
@ -438,7 +438,7 @@ export default class CountlyAnalytics {
await this.track("Opt-Out" ); await this.track("Opt-Out" );
this.endSession(); this.endSession();
window.clearInterval(this.heartbeatIntervalId); window.clearInterval(this.heartbeatIntervalId);
window.clearTimeout(this.activityIntervalId) window.clearTimeout(this.activityIntervalId);
this.baseUrl = null; this.baseUrl = null;
// remove listeners bound in trackSessions() // remove listeners bound in trackSessions()
window.removeEventListener("beforeunload", this.endSession); window.removeEventListener("beforeunload", this.endSession);
@ -662,14 +662,14 @@ export default class CountlyAnalytics {
} }
private queue(args: Omit<IEvent, "timestamp" | "hour" | "dow" | "count"> & Partial<Pick<IEvent, "count">>) { private queue(args: Omit<IEvent, "timestamp" | "hour" | "dow" | "count"> & Partial<Pick<IEvent, "count">>) {
const {count = 1, ...rest} = args; const { count = 1, ...rest } = args;
const ev = { const ev = {
...this.getTimeParams(), ...this.getTimeParams(),
...rest, ...rest,
count, count,
platform: this.appPlatform, platform: this.appPlatform,
app_version: this.appVersion, app_version: this.appVersion,
} };
this.pendingEvents.push(ev); this.pendingEvents.push(ev);
if (this.pendingEvents.length > MAX_PENDING_EVENTS) { if (this.pendingEvents.length > MAX_PENDING_EVENTS) {
@ -680,7 +680,7 @@ export default class CountlyAnalytics {
private getOrientation = (): Orientation => { private getOrientation = (): Orientation => {
return window.matchMedia("(orientation: landscape)").matches return window.matchMedia("(orientation: landscape)").matches
? Orientation.Landscape ? Orientation.Landscape
: Orientation.Portrait : Orientation.Portrait;
}; };
private reportOrientation = () => { private reportOrientation = () => {
@ -749,7 +749,7 @@ export default class CountlyAnalytics {
const request: Parameters<typeof CountlyAnalytics.prototype.request>[0] = { const request: Parameters<typeof CountlyAnalytics.prototype.request>[0] = {
begin_session: 1, begin_session: 1,
user_details: JSON.stringify(userDetails), user_details: JSON.stringify(userDetails),
} };
const metrics = this.getMetrics(); const metrics = this.getMetrics();
if (metrics) { if (metrics) {
@ -773,7 +773,7 @@ export default class CountlyAnalytics {
private endSession = () => { private endSession = () => {
if (this.sessionStarted) { if (this.sessionStarted) {
window.removeEventListener("resize", this.reportOrientation) window.removeEventListener("resize", this.reportOrientation);
this.reportViewDuration(); this.reportViewDuration();
this.request({ this.request({

View file

@ -168,7 +168,7 @@ export class DecryptionFailureTracker {
const trackedEventIds = [...dedupedFailuresMap.keys()]; const trackedEventIds = [...dedupedFailuresMap.keys()];
this.trackedEventHashMap = trackedEventIds.reduce( this.trackedEventHashMap = trackedEventIds.reduce(
(result, eventId) => ({...result, [eventId]: true}), (result, eventId) => ({ ...result, [eventId]: true }),
this.trackedEventHashMap, this.trackedEventHashMap,
); );

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {MatrixClientPeg} from './MatrixClientPeg'; import { MatrixClientPeg } from './MatrixClientPeg';
import dis from "./dispatcher/dispatcher"; import dis from "./dispatcher/dispatcher";
import { import {
hideToast as hideBulkUnverifiedSessionsToast, hideToast as hideBulkUnverifiedSessionsToast,

View file

@ -19,7 +19,7 @@ import Modal from './Modal';
import * as sdk from './'; import * as sdk from './';
import MultiInviter from './utils/MultiInviter'; import MultiInviter from './utils/MultiInviter';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
import {MatrixClientPeg} from './MatrixClientPeg'; import { MatrixClientPeg } from './MatrixClientPeg';
import GroupStore from './stores/GroupStore'; import GroupStore from './stores/GroupStore';
import StyledCheckbox from './components/views/elements/StyledCheckbox'; import StyledCheckbox from './components/views/elements/StyledCheckbox';
@ -103,7 +103,7 @@ function _onGroupInviteFinished(groupId, addrs) {
if (errorList.length > 0) { if (errorList.length > 0) {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to invite the following users to the group', '', ErrorDialog, { Modal.createTrackedDialog('Failed to invite the following users to the group', '', ErrorDialog, {
title: _t("Failed to invite the following users to %(groupId)s:", {groupId: groupId}), title: _t("Failed to invite the following users to %(groupId)s:", { groupId: groupId }),
description: errorList.join(", "), description: errorList.join(", "),
}); });
} }
@ -111,7 +111,7 @@ function _onGroupInviteFinished(groupId, addrs) {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to invite users to group', '', ErrorDialog, { Modal.createTrackedDialog('Failed to invite users to group', '', ErrorDialog, {
title: _t("Failed to invite users to community"), title: _t("Failed to invite users to community"),
description: _t("Failed to invite users to %(groupId)s", {groupId: groupId}), description: _t("Failed to invite users to %(groupId)s", { groupId: groupId }),
}); });
}); });
} }
@ -137,7 +137,7 @@ function _onGroupAddRoomFinished(groupId, addrs, addRoomsPublicly) {
// Add this group as related // Add this group as related
if (!groups.includes(groupId)) { if (!groups.includes(groupId)) {
groups.push(groupId); groups.push(groupId);
return MatrixClientPeg.get().sendStateEvent(roomId, 'm.room.related_groups', {groups}, ''); return MatrixClientPeg.get().sendStateEvent(roomId, 'm.room.related_groups', { groups }, '');
} }
}); });
})).then(() => { })).then(() => {
@ -152,7 +152,7 @@ function _onGroupAddRoomFinished(groupId, addrs, addRoomsPublicly) {
{ {
title: _t( title: _t(
"Failed to add the following rooms to %(groupId)s:", "Failed to add the following rooms to %(groupId)s:",
{groupId}, { groupId },
), ),
description: errorList.join(", "), description: errorList.join(", "),
}, },

View file

@ -138,7 +138,7 @@ export function getHtmlText(insaneHtml: string): string {
selfClosing: [], selfClosing: [],
allowedSchemes: [], allowedSchemes: [],
disallowedTagsMode: 'discard', disallowedTagsMode: 'discard',
}) });
} }
/** /**
@ -183,7 +183,7 @@ const transformTags: IExtendedSanitizeOptions["transformTags"] = { // custom to
// images" preference is disabled. Future work might expose some UI to reveal them // images" preference is disabled. Future work might expose some UI to reveal them
// like standalone image events have. // like standalone image events have.
if (!attribs.src || !attribs.src.startsWith('mxc://') || !SettingsStore.getValue("showImages")) { if (!attribs.src || !attribs.src.startsWith('mxc://') || !SettingsStore.getValue("showImages")) {
return { tagName, attribs: {}}; return { tagName, attribs: {} };
} }
const width = Number(attribs.width) || 800; const width = Number(attribs.width) || 800;
const height = Number(attribs.height) || 600; const height = Number(attribs.height) || 600;

View file

@ -17,7 +17,7 @@ limitations under the License.
import { SERVICE_TYPES } from 'matrix-js-sdk/src/service-types'; import { SERVICE_TYPES } from 'matrix-js-sdk/src/service-types';
import { createClient } from 'matrix-js-sdk/src/matrix'; import { createClient } from 'matrix-js-sdk/src/matrix';
import {MatrixClientPeg} from './MatrixClientPeg'; import { MatrixClientPeg } from './MatrixClientPeg';
import Modal from './Modal'; import Modal from './Modal';
import * as sdk from './index'; import * as sdk from './index';
import { _t } from './languageHandler'; import { _t } from './languageHandler';

View file

@ -156,7 +156,7 @@ const messageComposerBindings = (): KeyBinding<MessageComposerAction>[] => {
} }
} }
return bindings; return bindings;
} };
const autocompleteBindings = (): KeyBinding<AutocompleteAction>[] => { const autocompleteBindings = (): KeyBinding<AutocompleteAction>[] => {
return [ return [
@ -207,7 +207,7 @@ const autocompleteBindings = (): KeyBinding<AutocompleteAction>[] => {
}, },
}, },
]; ];
} };
const roomListBindings = (): KeyBinding<RoomListAction>[] => { const roomListBindings = (): KeyBinding<RoomListAction>[] => {
return [ return [
@ -248,7 +248,7 @@ const roomListBindings = (): KeyBinding<RoomListAction>[] => {
}, },
}, },
]; ];
} };
const roomBindings = (): KeyBinding<RoomAction>[] => { const roomBindings = (): KeyBinding<RoomAction>[] => {
const bindings: KeyBinding<RoomAction>[] = [ const bindings: KeyBinding<RoomAction>[] = [
@ -312,7 +312,7 @@ const roomBindings = (): KeyBinding<RoomAction>[] => {
} }
return bindings; return bindings;
} };
const navigationBindings = (): KeyBinding<NavigationAction>[] => { const navigationBindings = (): KeyBinding<NavigationAction>[] => {
return [ return [
@ -396,7 +396,7 @@ const navigationBindings = (): KeyBinding<NavigationAction>[] => {
}, },
}, },
]; ];
} };
export const defaultBindingsProvider: IKeyBindingsProvider = { export const defaultBindingsProvider: IKeyBindingsProvider = {
getMessageComposerBindings: messageComposerBindings, getMessageComposerBindings: messageComposerBindings,
@ -404,4 +404,4 @@ export const defaultBindingsProvider: IKeyBindingsProvider = {
getRoomListBindings: roomListBindings, getRoomListBindings: roomListBindings,
getRoomBindings: roomBindings, getRoomBindings: roomBindings,
getNavigationBindings: navigationBindings, getNavigationBindings: navigationBindings,
} };

View file

@ -140,12 +140,12 @@ export type KeyCombo = {
ctrlKey?: boolean; ctrlKey?: boolean;
metaKey?: boolean; metaKey?: boolean;
shiftKey?: boolean; shiftKey?: boolean;
} };
export type KeyBinding<T extends string> = { export type KeyBinding<T extends string> = {
action: T; action: T;
keyCombo: KeyCombo; keyCombo: KeyCombo;
} };
/** /**
* Helper method to check if a KeyboardEvent matches a KeyCombo * Helper method to check if a KeyboardEvent matches a KeyCombo

View file

@ -20,9 +20,9 @@ limitations under the License.
import { createClient } from 'matrix-js-sdk/src/matrix'; import { createClient } from 'matrix-js-sdk/src/matrix';
import { InvalidStoreError } from "matrix-js-sdk/src/errors"; import { InvalidStoreError } from "matrix-js-sdk/src/errors";
import { MatrixClient } from "matrix-js-sdk/src/client"; import { MatrixClient } from "matrix-js-sdk/src/client";
import {decryptAES, encryptAES} from "matrix-js-sdk/src/crypto/aes"; import { decryptAES, encryptAES } from "matrix-js-sdk/src/crypto/aes";
import {IMatrixClientCreds, MatrixClientPeg} from './MatrixClientPeg'; import { IMatrixClientCreds, MatrixClientPeg } from './MatrixClientPeg';
import SecurityCustomisations from "./customisations/Security"; import SecurityCustomisations from "./customisations/Security";
import EventIndexPeg from './indexing/EventIndexPeg'; import EventIndexPeg from './indexing/EventIndexPeg';
import createMatrixClient from './utils/createMatrixClient'; import createMatrixClient from './utils/createMatrixClient';
@ -41,17 +41,17 @@ import * as StorageManager from './utils/StorageManager';
import SettingsStore from "./settings/SettingsStore"; import SettingsStore from "./settings/SettingsStore";
import TypingStore from "./stores/TypingStore"; import TypingStore from "./stores/TypingStore";
import ToastStore from "./stores/ToastStore"; import ToastStore from "./stores/ToastStore";
import {IntegrationManagers} from "./integrations/IntegrationManagers"; import { IntegrationManagers } from "./integrations/IntegrationManagers";
import {Mjolnir} from "./mjolnir/Mjolnir"; import { Mjolnir } from "./mjolnir/Mjolnir";
import DeviceListener from "./DeviceListener"; import DeviceListener from "./DeviceListener";
import {Jitsi} from "./widgets/Jitsi"; import { Jitsi } from "./widgets/Jitsi";
import {SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY, SSO_IDP_ID_KEY} from "./BasePlatform"; import { SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY, SSO_IDP_ID_KEY } from "./BasePlatform";
import ThreepidInviteStore from "./stores/ThreepidInviteStore"; import ThreepidInviteStore from "./stores/ThreepidInviteStore";
import CountlyAnalytics from "./CountlyAnalytics"; import CountlyAnalytics from "./CountlyAnalytics";
import CallHandler from './CallHandler'; 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";
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";
@ -154,7 +154,7 @@ export async function loadSession(opts: ILoadSessionOpts = {}): Promise<boolean>
* return [null, null]. * return [null, null].
*/ */
export async function getStoredSessionOwner(): Promise<[string, boolean]> { export async function getStoredSessionOwner(): Promise<[string, boolean]> {
const {hsUrl, userId, hasAccessToken, isGuest} = await getStoredSessionVars(); const { hsUrl, userId, hasAccessToken, isGuest } = await getStoredSessionVars();
return hsUrl && userId && hasAccessToken ? [userId, isGuest] : [null, null]; return hsUrl && userId && hasAccessToken ? [userId, isGuest] : [null, null];
} }
@ -346,7 +346,7 @@ export async function getStoredSessionVars(): Promise<IStoredSession> {
isGuest = localStorage.getItem("matrix-is-guest") === "true"; isGuest = localStorage.getItem("matrix-is-guest") === "true";
} }
return {hsUrl, isUrl, hasAccessToken, accessToken, userId, deviceId, isGuest}; return { hsUrl, isUrl, hasAccessToken, accessToken, userId, deviceId, isGuest };
} }
// The pickle key is a string of unspecified length and format. For AES, we // The pickle key is a string of unspecified length and format. For AES, we
@ -402,7 +402,7 @@ export async function restoreFromLocalStorage(opts?: { ignoreGuest?: boolean }):
return false; return false;
} }
const {hsUrl, isUrl, hasAccessToken, accessToken, userId, deviceId, isGuest} = await getStoredSessionVars(); const { hsUrl, isUrl, hasAccessToken, accessToken, userId, deviceId, isGuest } = await getStoredSessionVars();
if (hasAccessToken && !accessToken) { if (hasAccessToken && !accessToken) {
abortLogin(); abortLogin();
@ -495,7 +495,7 @@ export async function setLoggedIn(credentials: IMatrixClientCreds): Promise<Matr
console.log("Pickle key not created"); console.log("Pickle key not created");
} }
return doSetLoggedIn(Object.assign({}, credentials, {pickleKey}), true); return doSetLoggedIn(Object.assign({}, credentials, { pickleKey }), true);
} }
/** /**
@ -562,7 +562,7 @@ async function doSetLoggedIn(
// //
// we fire it *synchronously* to make sure it fires before on_logged_in. // we fire it *synchronously* to make sure it fires before on_logged_in.
// (dis.dispatch uses `setTimeout`, which does not guarantee ordering.) // (dis.dispatch uses `setTimeout`, which does not guarantee ordering.)
dis.dispatch({action: 'on_logging_in'}, true); dis.dispatch({ action: 'on_logging_in' }, true);
if (clearStorageEnabled) { if (clearStorageEnabled) {
await clearStorage(); await clearStorage();
@ -745,7 +745,7 @@ export function softLogout(): void {
// Ensure that we dispatch a view change **before** stopping the client so // Ensure that we dispatch a view change **before** stopping the client so
// so that React components unmount first. This avoids React soft crashes // so that React components unmount first. This avoids React soft crashes
// that can occur when components try to use a null client. // that can occur when components try to use a null client.
dis.dispatch({action: 'on_client_not_viable'}); // generic version of on_logged_out dis.dispatch({ action: 'on_client_not_viable' }); // generic version of on_logged_out
stopMatrixClient(/*unsetClient=*/false); stopMatrixClient(/*unsetClient=*/false);
// DO NOT CALL LOGOUT. A soft logout preserves data, logout does not. // DO NOT CALL LOGOUT. A soft logout preserves data, logout does not.
@ -772,7 +772,7 @@ async function startMatrixClient(startSyncing = true): Promise<void> {
// to add listeners for the 'sync' event so otherwise we'd have // to add listeners for the 'sync' event so otherwise we'd have
// a race condition (and we need to dispatch synchronously for this // a race condition (and we need to dispatch synchronously for this
// to work). // to work).
dis.dispatch({action: 'will_start_client'}, true); dis.dispatch({ action: 'will_start_client' }, true);
// reset things first just in case // reset things first just in case
TypingStore.sharedInstance().reset(); TypingStore.sharedInstance().reset();
@ -814,7 +814,7 @@ async function startMatrixClient(startSyncing = true): Promise<void> {
// dispatch that we finished starting up to wire up any other bits // dispatch that we finished starting up to wire up any other bits
// of the matrix client that cannot be set prior to starting up. // of the matrix client that cannot be set prior to starting up.
dis.dispatch({action: 'client_started'}); dis.dispatch({ action: 'client_started' });
if (isSoftLogout()) { if (isSoftLogout()) {
softLogout(); softLogout();
@ -830,9 +830,9 @@ export async function onLoggedOut(): Promise<void> {
// Ensure that we dispatch a view change **before** stopping the client so // Ensure that we dispatch a view change **before** stopping the client so
// so that React components unmount first. This avoids React soft crashes // so that React components unmount first. This avoids React soft crashes
// that can occur when components try to use a null client. // that can occur when components try to use a null client.
dis.dispatch({action: 'on_logged_out'}, true); dis.dispatch({ action: 'on_logged_out' }, true);
stopMatrixClient(); stopMatrixClient();
await clearStorage({deleteEverything: true}); await clearStorage({ deleteEverything: true });
LifecycleCustomisations.onLoggedOutAndStorageCleared?.(); LifecycleCustomisations.onLoggedOutAndStorageCleared?.();
} }

View file

@ -16,7 +16,7 @@ limitations under the License.
*/ */
// @ts-ignore - XXX: tsc doesn't like this: our js-sdk imports are complex so this isn't surprising // @ts-ignore - XXX: tsc doesn't like this: our js-sdk imports are complex so this isn't surprising
import {createClient} from "matrix-js-sdk/src/matrix"; import { createClient } from "matrix-js-sdk/src/matrix";
import { MatrixClient } from "matrix-js-sdk/src/client"; import { MatrixClient } from "matrix-js-sdk/src/client";
import { IMatrixClientCreds } from "./MatrixClientPeg"; import { IMatrixClientCreds } from "./MatrixClientPeg";
import SecurityCustomisations from "./customisations/Security"; import SecurityCustomisations from "./customisations/Security";
@ -190,7 +190,6 @@ export default class Login {
} }
} }
/** /**
* Send a login request to the given server, and format the response * Send a login request to the given server, and format the response
* as a MatrixClientCreds * as a MatrixClientCreds

View file

@ -18,22 +18,22 @@ limitations under the License.
*/ */
import { ICreateClientOpts } from 'matrix-js-sdk/src/matrix'; import { ICreateClientOpts } from 'matrix-js-sdk/src/matrix';
import {MatrixClient} from 'matrix-js-sdk/src/client'; import { MatrixClient } from 'matrix-js-sdk/src/client';
import {MemoryStore} from 'matrix-js-sdk/src/store/memory'; import { MemoryStore } from 'matrix-js-sdk/src/store/memory';
import * as utils from 'matrix-js-sdk/src/utils'; import * as utils from 'matrix-js-sdk/src/utils';
import {EventTimeline} from 'matrix-js-sdk/src/models/event-timeline'; import { EventTimeline } from 'matrix-js-sdk/src/models/event-timeline';
import {EventTimelineSet} from 'matrix-js-sdk/src/models/event-timeline-set'; import { EventTimelineSet } from 'matrix-js-sdk/src/models/event-timeline-set';
import * as sdk from './index'; import * as sdk from './index';
import createMatrixClient from './utils/createMatrixClient'; import createMatrixClient from './utils/createMatrixClient';
import SettingsStore from './settings/SettingsStore'; import SettingsStore from './settings/SettingsStore';
import MatrixActionCreators from './actions/MatrixActionCreators'; import MatrixActionCreators from './actions/MatrixActionCreators';
import Modal from './Modal'; import Modal from './Modal';
import {verificationMethods} from 'matrix-js-sdk/src/crypto'; import { verificationMethods } from 'matrix-js-sdk/src/crypto';
import MatrixClientBackedSettingsHandler from "./settings/handlers/MatrixClientBackedSettingsHandler"; import MatrixClientBackedSettingsHandler from "./settings/handlers/MatrixClientBackedSettingsHandler";
import * as StorageManager from './utils/StorageManager'; import * as StorageManager from './utils/StorageManager';
import IdentityAuthClient from './IdentityAuthClient'; import IdentityAuthClient from './IdentityAuthClient';
import { crossSigningCallbacks, tryToUnlockSecretStorageWithDehydrationKey } from './SecurityManager'; import { crossSigningCallbacks, tryToUnlockSecretStorageWithDehydrationKey } from './SecurityManager';
import {SHOW_QR_CODE_METHOD} from "matrix-js-sdk/src/crypto/verification/QRCode"; import { SHOW_QR_CODE_METHOD } from "matrix-js-sdk/src/crypto/verification/QRCode";
import SecurityCustomisations from "./customisations/Security"; import SecurityCustomisations from "./customisations/Security";
export interface IMatrixClientCreds { export interface IMatrixClientCreds {

View file

@ -15,14 +15,13 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import classNames from 'classnames'; import classNames from 'classnames';
import Analytics from './Analytics'; import Analytics from './Analytics';
import dis from './dispatcher/dispatcher'; import dis from './dispatcher/dispatcher';
import {defer} from './utils/promise'; import { defer } from './utils/promise';
import AsyncWrapper from './AsyncWrapper'; import AsyncWrapper from './AsyncWrapper';
const DIALOG_CONTAINER_ID = "mx_Dialog_Container"; const DIALOG_CONTAINER_ID = "mx_Dialog_Container";
@ -193,7 +192,7 @@ export class ModalManager {
modal.elem = <AsyncWrapper key={modalCount} prom={prom} {...props} onFinished={closeDialog} />; modal.elem = <AsyncWrapper key={modalCount} prom={prom} {...props} onFinished={closeDialog} />;
modal.close = closeDialog; modal.close = closeDialog;
return {modal, closeDialog, onFinishedProm}; return { modal, closeDialog, onFinishedProm };
} }
private getCloseFn<T extends any[]>( private getCloseFn<T extends any[]>(
@ -282,7 +281,7 @@ export class ModalManager {
isStaticModal = false, isStaticModal = false,
options: IOptions<T> = {}, options: IOptions<T> = {},
): IHandle<T> { ): IHandle<T> {
const {modal, closeDialog, onFinishedProm} = this.buildModal<T>(prom, props, className, options); const { modal, closeDialog, onFinishedProm } = this.buildModal<T>(prom, props, className, options);
if (isPriorityModal) { if (isPriorityModal) {
// XXX: This is destructive // XXX: This is destructive
this.priorityModal = modal; this.priorityModal = modal;
@ -305,7 +304,7 @@ export class ModalManager {
props?: IProps<T>, props?: IProps<T>,
className?: string, className?: string,
): IHandle<T> { ): IHandle<T> {
const {modal, closeDialog, onFinishedProm} = this.buildModal<T>(prom, props, className, {}); const { modal, closeDialog, onFinishedProm } = this.buildModal<T>(prom, props, className, {});
this.modals.push(modal); this.modals.push(modal);
this.reRender(); this.reRender();

View file

@ -32,11 +32,11 @@ import { _t } from './languageHandler';
import Modal from './Modal'; import Modal from './Modal';
import SettingsStore from "./settings/SettingsStore"; import SettingsStore from "./settings/SettingsStore";
import { hideToast as hideNotificationsToast } from "./toasts/DesktopNotificationsToast"; import { hideToast as hideNotificationsToast } from "./toasts/DesktopNotificationsToast";
import {SettingLevel} from "./settings/SettingLevel"; import { SettingLevel } from "./settings/SettingLevel";
import {isPushNotifyDisabled} from "./settings/controllers/NotificationControllers"; import { isPushNotifyDisabled } from "./settings/controllers/NotificationControllers";
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";
/* /*
* Dispatches: * Dispatches:

View file

@ -16,10 +16,10 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {MatrixClientPeg} from "./MatrixClientPeg"; import { MatrixClientPeg } from "./MatrixClientPeg";
import dis from "./dispatcher/dispatcher"; import dis from "./dispatcher/dispatcher";
import Timer from './utils/Timer'; import Timer from './utils/Timer';
import {ActionPayload} from "./dispatcher/payloads"; import { ActionPayload } from "./dispatcher/payloads";
// Time in ms after that a user is considered as unavailable/away // Time in ms after that a user is considered as unavailable/away
const UNAVAILABLE_TIME_MS = 3 * 60 * 1000; // 3 mins const UNAVAILABLE_TIME_MS = 3 * 60 * 1000; // 3 mins
@ -78,7 +78,7 @@ class Presence {
this.setState(State.Online); this.setState(State.Online);
this.unavailableTimer.restart(); this.unavailableTimer.restart();
} }
} };
/** /**
* Set the presence state. * Set the presence state.
@ -98,7 +98,7 @@ class Presence {
} }
try { try {
await MatrixClientPeg.get().setPresence({presence: this.state}); await MatrixClientPeg.get().setPresence({ presence: this.state });
console.info("Presence:", newState); console.info("Presence:", newState);
} catch (err) { } catch (err) {
console.error("Failed to set presence:", err); console.error("Failed to set presence:", err);

View file

@ -53,16 +53,16 @@ export async function startAnyRegistrationFlow(options) {
extraButtons: [ extraButtons: [
<button key="start_login" onClick={() => { <button key="start_login" onClick={() => {
modal.close(); modal.close();
dis.dispatch({action: 'start_login', screenAfterLogin: options.screen_after}); dis.dispatch({ action: 'start_login', screenAfterLogin: options.screen_after });
}}>{ _t('Sign In') }</button>, }}>{ _t('Sign In') }</button>,
], ],
onFinished: (proceed) => { onFinished: (proceed) => {
if (proceed) { if (proceed) {
dis.dispatch({action: 'start_registration', screenAfterLogin: options.screen_after}); dis.dispatch({ action: 'start_registration', screenAfterLogin: options.screen_after });
} else if (options.go_home_on_cancel) { } else if (options.go_home_on_cancel) {
dis.dispatch({action: 'view_home_page'}); dis.dispatch({ action: 'view_home_page' });
} else if (options.go_welcome_on_cancel) { } else if (options.go_welcome_on_cancel) {
dis.dispatch({action: 'view_welcome_page'}); dis.dispatch({ action: 'view_welcome_page' });
} }
}, },
}); });

View file

@ -31,6 +31,6 @@ export function textualPowerLevel(level: number, usersDefault: number): string {
if (LEVEL_ROLE_MAP[level]) { if (LEVEL_ROLE_MAP[level]) {
return LEVEL_ROLE_MAP[level]; return LEVEL_ROLE_MAP[level];
} else { } else {
return _t("Custom (%(level)s)", {level}); return _t("Custom (%(level)s)", { level });
} }
} }

View file

@ -53,7 +53,7 @@ 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"); 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,
); );
} }
@ -72,7 +72,7 @@ export function showRoomInviteDialog(roomId: string, initialText = ""): void {
export function showCommunityRoomInviteDialog(roomId: string, communityName: string): void { export function showCommunityRoomInviteDialog(roomId: string, communityName: string): void {
Modal.createTrackedDialog( Modal.createTrackedDialog(
'Invite Users to Community', '', CommunityPrototypeInviteDialog, {communityName, roomId}, 'Invite Users to Community', '', CommunityPrototypeInviteDialog, { communityName, roomId },
/*className=*/null, /*isPriority=*/false, /*isStatic=*/true, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true,
); );
} }
@ -133,7 +133,7 @@ export function showAnyInviteErrors(
// pointless for us to list who failed exactly. // pointless for us to list who failed exactly.
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); 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]),
}); });
return false; return false;

View file

@ -15,8 +15,8 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {MatrixClientPeg} from './MatrixClientPeg'; import { MatrixClientPeg } from './MatrixClientPeg';
import {PushProcessor} from 'matrix-js-sdk/src/pushprocessor'; import { PushProcessor } from 'matrix-js-sdk/src/pushprocessor';
export const ALL_MESSAGES_LOUD = 'all_messages_loud'; export const ALL_MESSAGES_LOUD = 'all_messages_loud';
export const ALL_MESSAGES = 'all_messages'; export const ALL_MESSAGES = 'all_messages';
@ -52,7 +52,7 @@ export function aggregateNotificationCount(rooms) {
} }
} }
return result; return result;
}, {count: 0, highlight: false}); }, { count: 0, highlight: false });
} }
export function getRoomHasBadge(room) { export function getRoomHasBadge(room) {

View file

@ -104,7 +104,6 @@ export function setDMRoom(roomId: string, userId: string): Promise<void> {
dmRoomMap[userId] = roomList; dmRoomMap[userId] = roomList;
} }
return MatrixClientPeg.get().setAccountData('m.direct', dmRoomMap); return MatrixClientPeg.get().setAccountData('m.direct', dmRoomMap);
} }

View file

@ -17,12 +17,12 @@ limitations under the License.
import url from 'url'; import url from 'url';
import SettingsStore from "./settings/SettingsStore"; import SettingsStore from "./settings/SettingsStore";
import { Service, startTermsFlow, TermsInteractionCallback, TermsNotSignedError } from './Terms'; import { Service, startTermsFlow, TermsInteractionCallback, TermsNotSignedError } from './Terms';
import {MatrixClientPeg} from "./MatrixClientPeg"; import { MatrixClientPeg } from "./MatrixClientPeg";
import request from "browser-request"; import request from "browser-request";
import SdkConfig from "./SdkConfig"; import SdkConfig from "./SdkConfig";
import {WidgetType} from "./widgets/WidgetType"; import { WidgetType } from "./widgets/WidgetType";
import {SERVICE_TYPES} from "matrix-js-sdk/src/service-types"; import { SERVICE_TYPES } from "matrix-js-sdk/src/service-types";
import { Room } from "matrix-js-sdk/src/models/room"; import { Room } from "matrix-js-sdk/src/models/room";
// The version of the integration manager API we're intending to work with // The version of the integration manager API we're intending to work with
@ -109,7 +109,7 @@ export default class ScalarAuthClient {
request({ request({
method: "GET", method: "GET",
uri: url, uri: url,
qs: {scalar_token: token, v: imApiVersion}, qs: { scalar_token: token, v: imApiVersion },
json: true, json: true,
}, (err, response, body) => { }, (err, response, body) => {
if (err) { if (err) {
@ -189,7 +189,7 @@ export default class ScalarAuthClient {
request({ request({
method: 'POST', method: 'POST',
uri: scalarRestUrl + '/register', uri: scalarRestUrl + '/register',
qs: {v: imApiVersion}, qs: { v: imApiVersion },
body: openidTokenObject, body: openidTokenObject,
json: true, json: true,
}, (err, response, body) => { }, (err, response, body) => {

View file

@ -208,7 +208,6 @@ Example:
] ]
} }
membership_state AND bot_options membership_state AND bot_options
-------------------------------- --------------------------------
Get the content of the "m.room.member" or "m.room.bot.options" state event respectively. Get the content of the "m.room.member" or "m.room.bot.options" state event respectively.
@ -236,15 +235,15 @@ Example:
} }
*/ */
import {MatrixClientPeg} from './MatrixClientPeg'; import { MatrixClientPeg } from './MatrixClientPeg';
import { MatrixEvent } from 'matrix-js-sdk/src/models/event'; import { MatrixEvent } from 'matrix-js-sdk/src/models/event';
import dis from './dispatcher/dispatcher'; import dis from './dispatcher/dispatcher';
import WidgetUtils from './utils/WidgetUtils'; import WidgetUtils from './utils/WidgetUtils';
import RoomViewStore from './stores/RoomViewStore'; import RoomViewStore from './stores/RoomViewStore';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
import {IntegrationManagers} from "./integrations/IntegrationManagers"; import { IntegrationManagers } from "./integrations/IntegrationManagers";
import {WidgetType} from "./widgets/WidgetType"; import { WidgetType } from "./widgets/WidgetType";
import {objectClone} from "./utils/objects"; import { objectClone } from "./utils/objects";
function sendResponse(event, res) { function sendResponse(event, res) {
const data = objectClone(event.data); const data = objectClone(event.data);
@ -608,7 +607,7 @@ const onMessage = function(event) {
} }
if (roomId !== RoomViewStore.getRoomId()) { if (roomId !== RoomViewStore.getRoomId()) {
sendError(event, _t('Room %(roomId)s not visible', {roomId: roomId})); sendError(event, _t('Room %(roomId)s not visible', { roomId: roomId }));
return; return;
} }

View file

@ -15,7 +15,7 @@ limitations under the License.
*/ */
import EventIndexPeg from "./indexing/EventIndexPeg"; import EventIndexPeg from "./indexing/EventIndexPeg";
import {MatrixClientPeg} from "./MatrixClientPeg"; import { MatrixClientPeg } from "./MatrixClientPeg";
const SEARCH_LIMIT = 10; const SEARCH_LIMIT = 10;
@ -43,7 +43,7 @@ async function serverSideSearch(term, roomId = undefined) {
}, },
}; };
const response = await client.search({body: body}); const response = await client.search({ body: body });
const result = { const result = {
response: response, response: response,
@ -498,7 +498,7 @@ async function combinedPagination(searchResult) {
// Fetch events from the server if we have a token for it and if it's the // Fetch events from the server if we have a token for it and if it's the
// local indexes turn or the local index has exhausted its results. // local indexes turn or the local index has exhausted its results.
if (searchResult.serverSideNextBatch && (oldestEventFrom === "local" || !searchArgs.next_batch)) { if (searchResult.serverSideNextBatch && (oldestEventFrom === "local" || !searchArgs.next_batch)) {
const body = {body: searchResult._query, next_batch: searchResult.serverSideNextBatch}; const body = { body: searchResult._query, next_batch: searchResult.serverSideNextBatch };
serverSideResult = await client.search(body); serverSideResult = await client.search(body);
} }

View file

@ -18,7 +18,7 @@ import { ICryptoCallbacks, ISecretStorageKeyInfo } from 'matrix-js-sdk/src/matri
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';
import {MatrixClientPeg} from './MatrixClientPeg'; import { MatrixClientPeg } from './MatrixClientPeg';
import { deriveKey } from 'matrix-js-sdk/src/crypto/key_passphrase'; import { deriveKey } from 'matrix-js-sdk/src/crypto/key_passphrase';
import { decodeRecoveryKey } from 'matrix-js-sdk/src/crypto/recoverykey'; import { decodeRecoveryKey } from 'matrix-js-sdk/src/crypto/recoverykey';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
@ -135,7 +135,7 @@ async function getSecretStorageKey(
const keyFromCustomisations = SecurityCustomisations.getSecretStorageKey?.(); const keyFromCustomisations = SecurityCustomisations.getSecretStorageKey?.();
if (keyFromCustomisations) { if (keyFromCustomisations) {
console.log("Using key from security customisations (secret storage)") console.log("Using key from security customisations (secret storage)");
cacheSecretStorageKey(keyId, keyInfo, keyFromCustomisations); cacheSecretStorageKey(keyId, keyInfo, keyFromCustomisations);
return [keyId, keyFromCustomisations]; return [keyId, keyFromCustomisations];
} }
@ -185,7 +185,7 @@ export async function getDehydrationKey(
): Promise<Uint8Array> { ): Promise<Uint8Array> {
const keyFromCustomisations = SecurityCustomisations.getSecretStorageKey?.(); const keyFromCustomisations = SecurityCustomisations.getSecretStorageKey?.();
if (keyFromCustomisations) { if (keyFromCustomisations) {
console.log("Using key from security customisations (dehydration)") console.log("Using key from security customisations (dehydration)");
return keyFromCustomisations; return keyFromCustomisations;
} }
@ -224,7 +224,7 @@ export async function getDehydrationKey(
const key = await inputToKey(input); const key = await inputToKey(input);
// need to copy the key because rehydration (unpickling) will clobber it // need to copy the key because rehydration (unpickling) will clobber it
dehydrationCache = {key: new Uint8Array(key), keyInfo}; dehydrationCache = { key: new Uint8Array(key), keyInfo };
return key; return key;
} }

View file

@ -1,4 +1,3 @@
//@flow
/* /*
Copyright 2017 Aviral Dasgupta Copyright 2017 Aviral Dasgupta
@ -15,10 +14,10 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {clamp} from "lodash"; import { clamp } from "lodash";
import {MatrixEvent} from "matrix-js-sdk/src/models/event"; import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import {SerializedPart} from "./editor/parts"; import { SerializedPart } from "./editor/parts";
import EditorModel from "./editor/model"; import EditorModel from "./editor/model";
interface IHistoryItem { interface IHistoryItem {

View file

@ -21,21 +21,21 @@ import * as React from 'react';
import { User } from "matrix-js-sdk/src/models/user"; 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 * 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';
import { linkifyAndSanitizeHtml } from './HtmlUtils'; import { linkifyAndSanitizeHtml } from './HtmlUtils';
import QuestionDialog from "./components/views/dialogs/QuestionDialog"; import QuestionDialog from "./components/views/dialogs/QuestionDialog";
import WidgetUtils from "./utils/WidgetUtils"; import WidgetUtils from "./utils/WidgetUtils";
import {textToHtmlRainbow} from "./utils/colour"; import { textToHtmlRainbow } from "./utils/colour";
import { getAddressType } from './UserAddress'; import { getAddressType } from './UserAddress';
import { abbreviateUrl } from './utils/UrlUtils'; import { abbreviateUrl } from './utils/UrlUtils';
import { getDefaultIdentityServerUrl, useDefaultIdentityServer } from './utils/IdentityServerUtils'; import { getDefaultIdentityServerUrl, useDefaultIdentityServer } from './utils/IdentityServerUtils';
import {isPermalinkHost, parsePermalink} from "./utils/permalinks/Permalinks"; import { isPermalinkHost, parsePermalink } from "./utils/permalinks/Permalinks";
import {inviteUsersToRoom} from "./RoomInvite"; import { inviteUsersToRoom } from "./RoomInvite";
import { WidgetType } from "./widgets/WidgetType"; import { WidgetType } from "./widgets/WidgetType";
import { Jitsi } from "./widgets/Jitsi"; import { Jitsi } from "./widgets/Jitsi";
import { parseFragment as parseHtml, Element as ChildElement } from "parse5"; import { parseFragment as parseHtml, Element as ChildElement } from "parse5";
@ -46,10 +46,10 @@ import { Action } from "./dispatcher/actions";
import { EffectiveMembership, getEffectiveMembership, leaveRoomBehaviour } from "./utils/membership"; import { EffectiveMembership, getEffectiveMembership, leaveRoomBehaviour } from "./utils/membership";
import SdkConfig from "./SdkConfig"; import SdkConfig from "./SdkConfig";
import SettingsStore from "./settings/SettingsStore"; import SettingsStore from "./settings/SettingsStore";
import {UIFeature} from "./settings/UIFeature"; 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";
// 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 {
@ -143,11 +143,11 @@ export class Command {
} }
function reject(error) { function reject(error) {
return {error}; return { error };
} }
function success(promise?: Promise<any>) { function success(promise?: Promise<any>) {
return {promise}; return { promise };
} }
function successSync(value: any) { function successSync(value: any) {
@ -271,8 +271,8 @@ export const Commands = [
const RoomUpgradeWarningDialog = sdk.getComponent("dialogs.RoomUpgradeWarningDialog"); 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);
return success(finished.then(async ([resp]) => { return success(finished.then(async ([resp]) => {
@ -288,7 +288,7 @@ export const Commands = [
if (resp.invite) { if (resp.invite) {
checkForUpgradeFn = async (newRoom) => { checkForUpgradeFn = async (newRoom) => {
// The upgradePromise should be done by the time we await it here. // The upgradePromise should be done by the time we await it here.
const {replacement_room: newRoomId} = await upgradePromise; const { replacement_room: newRoomId } = await upgradePromise;
if (newRoom.roomId !== newRoomId) return; if (newRoom.roomId !== newRoomId) return;
const toInvite = [ const toInvite = [
@ -370,7 +370,7 @@ export const Commands = [
return success(promise.then((url) => { return success(promise.then((url) => {
if (!url) return; if (!url) return;
return MatrixClientPeg.get().sendStateEvent(roomId, 'm.room.avatar', {url}, ''); return MatrixClientPeg.get().sendStateEvent(roomId, 'm.room.avatar', { url }, '');
})); }));
}, },
category: CommandCategories.actions, category: CommandCategories.actions,
@ -741,7 +741,7 @@ export const Commands = [
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>
<p>{ _t('You are now ignoring %(userId)s', {userId}) }</p> <p>{ _t('You are now ignoring %(userId)s', { userId }) }</p>
</div>, </div>,
}); });
}), }),
@ -772,7 +772,7 @@ export const Commands = [
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>
<p>{ _t('You are no longer ignoring %(userId)s', {userId}) }</p> <p>{ _t('You are no longer ignoring %(userId)s', { userId }) }</p>
</div>, </div>,
}); });
}), }),
@ -839,7 +839,7 @@ export const Commands = [
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'); const DevtoolsDialog = sdk.getComponent('dialogs.DevtoolsDialog');
Modal.createDialog(DevtoolsDialog, {roomId}); Modal.createDialog(DevtoolsDialog, { roomId });
return success(); return success();
}, },
category: CommandCategories.advanced, category: CommandCategories.advanced,
@ -951,7 +951,7 @@ export const Commands = [
{ {
_t('The signing key you provided matches the signing key you received ' + _t('The signing key you provided matches the signing key you received ' +
'from %(userId)s\'s session %(deviceId)s. Session marked as verified.', 'from %(userId)s\'s session %(deviceId)s. Session marked as verified.',
{userId, deviceId}) { userId, deviceId })
} }
</p> </p>
</div>, </div>,
@ -1172,11 +1172,11 @@ export const Commands = [
}; };
MatrixClientPeg.get().sendMessage(roomId, content); MatrixClientPeg.get().sendMessage(roomId, content);
} }
dis.dispatch({action: `effects.${effect.command}`}); dis.dispatch({ action: `effects.${effect.command}` });
})()); })());
}, },
category: CommandCategories.effects, category: CommandCategories.effects,
}) });
}), }),
]; ];
@ -1205,7 +1205,7 @@ export function parseCommandString(input: string) {
cmd = input; cmd = input;
} }
return {cmd, args}; return { cmd, args };
} }
/** /**
@ -1217,7 +1217,7 @@ export function parseCommandString(input: string) {
* Returns null if the input didn't match a command. * Returns null if the input didn't match a command.
*/ */
export function getCommand(input: string) { export function getCommand(input: string) {
const {cmd, args} = parseCommandString(input); const { cmd, args } = parseCommandString(input);
if (CommandMap.has(cmd) && CommandMap.get(cmd).isEnabled()) { if (CommandMap.has(cmd) && CommandMap.get(cmd).isEnabled()) {
return { return {

View file

@ -16,7 +16,7 @@ limitations under the License.
import classNames from 'classnames'; import classNames from 'classnames';
import {MatrixClientPeg} from './MatrixClientPeg'; import { MatrixClientPeg } from './MatrixClientPeg';
import * as sdk from '.'; import * as sdk from '.';
import Modal from './Modal'; import Modal from './Modal';
@ -117,7 +117,7 @@ export async function startTermsFlow(
// but that is not a thing the API supports, so probably best to just show // but that is not a thing the API supports, so probably best to just show
// things they've not agreed to yet. // things they've not agreed to yet.
const unagreedPoliciesAndServicePairs = []; const unagreedPoliciesAndServicePairs = [];
for (const {service, policies} of policiesAndServicePairs) { for (const { service, policies } of policiesAndServicePairs) {
const unagreedPolicies = {}; const unagreedPolicies = {};
for (const [policyName, policy] of Object.entries(policies)) { for (const [policyName, policy] of Object.entries(policies)) {
let policyAgreed = false; let policyAgreed = false;
@ -131,7 +131,7 @@ export async function startTermsFlow(
if (!policyAgreed) unagreedPolicies[policyName] = policy; if (!policyAgreed) unagreedPolicies[policyName] = policy;
} }
if (Object.keys(unagreedPolicies).length > 0) { if (Object.keys(unagreedPolicies).length > 0) {
unagreedPoliciesAndServicePairs.push({service, policies: unagreedPolicies}); unagreedPoliciesAndServicePairs.push({ service, policies: unagreedPolicies });
} }
} }
@ -148,7 +148,7 @@ export async function startTermsFlow(
// We only ever add to the set of URLs, so if anything has changed then we'd see a different length // We only ever add to the set of URLs, so if anything has changed then we'd see a different length
if (agreedUrlSet.size !== numAcceptedBeforeAgreement) { if (agreedUrlSet.size !== numAcceptedBeforeAgreement) {
const newAcceptedTerms = {accepted: Array.from(agreedUrlSet)}; const newAcceptedTerms = { accepted: Array.from(agreedUrlSet) };
await MatrixClientPeg.get().setAccountData('m.accepted_terms', newAcceptedTerms); await MatrixClientPeg.get().setAccountData('m.accepted_terms', newAcceptedTerms);
} }

View file

@ -15,13 +15,13 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import {MatrixClientPeg} from './MatrixClientPeg'; import { MatrixClientPeg } from './MatrixClientPeg';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
import * as Roles from './Roles'; import * as Roles from './Roles';
import {isValid3pidInvite} from "./RoomInvite"; import { isValid3pidInvite } from "./RoomInvite";
import SettingsStore from "./settings/SettingsStore"; import SettingsStore from "./settings/SettingsStore";
import {ALL_RULE_TYPES, ROOM_RULE_TYPES, SERVER_RULE_TYPES, USER_RULE_TYPES} from "./mjolnir/BanList"; import { ALL_RULE_TYPES, ROOM_RULE_TYPES, SERVER_RULE_TYPES, USER_RULE_TYPES } from "./mjolnir/BanList";
import {WIDGET_LAYOUT_EVENT_TYPE} from "./stores/widgets/WidgetLayoutStore"; import { WIDGET_LAYOUT_EVENT_TYPE } from "./stores/widgets/WidgetLayoutStore";
import { RightPanelPhases } from './stores/RightPanelStorePhases'; import { RightPanelPhases } from './stores/RightPanelStorePhases';
import { Action } from './dispatcher/actions'; import { Action } from './dispatcher/actions';
import defaultDispatcher from './dispatcher/dispatcher'; import defaultDispatcher from './dispatcher/dispatcher';
@ -112,7 +112,7 @@ function textForMemberEvent(ev): () => string | null {
targetName, targetName,
reason, reason,
}) })
: _t('%(senderName)s withdrew %(targetName)s\'s invitation', { senderName, targetName }) : _t('%(senderName)s withdrew %(targetName)s\'s invitation', { senderName, targetName });
} else if (prevContent.membership === "join") { } else if (prevContent.membership === "join") {
return () => reason return () => reason
? _t('%(senderName)s kicked %(targetName)s: %(reason)s', { ? _t('%(senderName)s kicked %(targetName)s: %(reason)s', {
@ -139,7 +139,7 @@ function textForRoomNameEvent(ev): () => string | null {
const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender(); const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
if (!ev.getContent().name || ev.getContent().name.trim().length === 0) { if (!ev.getContent().name || ev.getContent().name.trim().length === 0) {
return () => _t('%(senderDisplayName)s removed the room name.', {senderDisplayName}); return () => _t('%(senderDisplayName)s removed the room name.', { senderDisplayName });
} }
if (ev.getPrevContent().name) { if (ev.getPrevContent().name) {
return () => _t('%(senderDisplayName)s changed the room name from %(oldRoomName)s to %(newRoomName)s.', { return () => _t('%(senderDisplayName)s changed the room name from %(oldRoomName)s to %(newRoomName)s.', {
@ -156,7 +156,7 @@ function textForRoomNameEvent(ev): () => string | null {
function textForTombstoneEvent(ev): () => string | null { function textForTombstoneEvent(ev): () => string | null {
const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender(); const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
return () => _t('%(senderDisplayName)s upgraded this room.', {senderDisplayName}); return () => _t('%(senderDisplayName)s upgraded this room.', { senderDisplayName });
} }
function textForJoinRulesEvent(ev): () => string | null { function textForJoinRulesEvent(ev): () => string | null {
@ -183,9 +183,9 @@ function textForGuestAccessEvent(ev): () => string | null {
const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender(); const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
switch (ev.getContent().guest_access) { switch (ev.getContent().guest_access) {
case "can_join": case "can_join":
return () => _t('%(senderDisplayName)s has allowed guests to join the room.', {senderDisplayName}); return () => _t('%(senderDisplayName)s has allowed guests to join the room.', { senderDisplayName });
case "forbidden": case "forbidden":
return () => _t('%(senderDisplayName)s has prevented guests from joining the room.', {senderDisplayName}); return () => _t('%(senderDisplayName)s has prevented guests from joining the room.', { senderDisplayName });
default: default:
// There's no other options we can expect, however just for safety's sake we'll do this. // There's no other options we can expect, however just for safety's sake we'll do this.
return () => _t('%(senderDisplayName)s changed guest access to %(rule)s', { return () => _t('%(senderDisplayName)s changed guest access to %(rule)s', {
@ -237,9 +237,9 @@ function textForServerACLEvent(ev): () => string | null {
let getText = null; let getText = null;
if (prev.deny.length === 0 && prev.allow.length === 0) { if (prev.deny.length === 0 && prev.allow.length === 0) {
getText = () => _t("%(senderDisplayName)s set the server ACLs for this room.", {senderDisplayName}); getText = () => _t("%(senderDisplayName)s set the server ACLs for this room.", { senderDisplayName });
} else { } else {
getText = () => _t("%(senderDisplayName)s changed the server ACLs for this room.", {senderDisplayName}); getText = () => _t("%(senderDisplayName)s changed the server ACLs for this room.", { senderDisplayName });
} }
if (!Array.isArray(current.allow)) { if (!Array.isArray(current.allow)) {
@ -262,7 +262,7 @@ function textForMessageEvent(ev): () => string | null {
if (ev.getContent().msgtype === "m.emote") { if (ev.getContent().msgtype === "m.emote") {
message = "* " + senderDisplayName + " " + message; message = "* " + senderDisplayName + " " + message;
} else if (ev.getContent().msgtype === "m.image") { } else if (ev.getContent().msgtype === "m.image") {
message = _t('%(senderDisplayName)s sent an image.', {senderDisplayName}); message = _t('%(senderDisplayName)s sent an image.', { senderDisplayName });
} }
return message; return message;
}; };
@ -323,7 +323,7 @@ function textForCallAnswerEvent(event): () => string | null {
return () => { return () => {
const senderName = event.sender ? event.sender.name : _t('Someone'); const senderName = event.sender ? event.sender.name : _t('Someone');
const supported = MatrixClientPeg.get().supportsVoip() ? '' : _t('(not supported by this browser)'); const supported = MatrixClientPeg.get().supportsVoip() ? '' : _t('(not supported by this browser)');
return _t('%(senderName)s answered the call.', {senderName}) + ' ' + supported; return _t('%(senderName)s answered the call.', { senderName }) + ' ' + supported;
}; };
} }
@ -358,16 +358,16 @@ function textForCallHangupEvent(event): () => string | null {
// Also the correct hangup code as of VoIP v1 (with underscore) // Also the correct hangup code as of VoIP v1 (with underscore)
getReason = () => ''; getReason = () => '';
} else { } else {
getReason = () => _t('(unknown failure: %(reason)s)', {reason: eventContent.reason}); getReason = () => _t('(unknown failure: %(reason)s)', { reason: eventContent.reason });
} }
} }
return () => _t('%(senderName)s ended the call.', {senderName: getSenderName()}) + ' ' + getReason(); return () => _t('%(senderName)s ended the call.', { senderName: getSenderName() }) + ' ' + getReason();
} }
function textForCallRejectEvent(event): () => string | null { function textForCallRejectEvent(event): () => string | null {
return () => { return () => {
const senderName = event.sender ? event.sender.name : _t('Someone'); const senderName = event.sender ? event.sender.name : _t('Someone');
return _t('%(senderName)s declined the call.', {senderName}); return _t('%(senderName)s declined the call.', { senderName });
}; };
} }
@ -424,14 +424,14 @@ function textForHistoryVisibilityEvent(event): () => string | null {
switch (event.getContent().history_visibility) { switch (event.getContent().history_visibility) {
case 'invited': case 'invited':
return () => _t('%(senderName)s made future room history visible to all room members, ' return () => _t('%(senderName)s made future room history visible to all room members, '
+ 'from the point they are invited.', {senderName}); + 'from the point they are invited.', { senderName });
case 'joined': case 'joined':
return () => _t('%(senderName)s made future room history visible to all room members, ' return () => _t('%(senderName)s made future room history visible to all room members, '
+ 'from the point they joined.', {senderName}); + 'from the point they joined.', { senderName });
case 'shared': case 'shared':
return () => _t('%(senderName)s made future room history visible to all room members.', {senderName}); return () => _t('%(senderName)s made future room history visible to all room members.', { senderName });
case 'world_readable': case 'world_readable':
return () => _t('%(senderName)s made future room history visible to anyone.', {senderName}); return () => _t('%(senderName)s made future room history visible to anyone.', { senderName });
default: default:
return () => _t('%(senderName)s made future room history visible to unknown (%(visibility)s).', { return () => _t('%(senderName)s made future room history visible to unknown (%(visibility)s).', {
senderName, senderName,
@ -492,7 +492,7 @@ const onPinnedMessagesClick = (): void => {
phase: RightPanelPhases.PinnedMessages, phase: RightPanelPhases.PinnedMessages,
allowClose: false, allowClose: false,
}); });
} };
function textForPinnedEvent(event: MatrixEvent, allowJSX: boolean): () => string | JSX.Element | null { function textForPinnedEvent(event: MatrixEvent, allowJSX: boolean): () => string | JSX.Element | null {
if (!SettingsStore.getValue("feature_pinning")) return null; if (!SettingsStore.getValue("feature_pinning")) return null;
@ -517,8 +517,8 @@ function textForPinnedEvent(event: MatrixEvent, allowJSX: boolean): () => string
function textForWidgetEvent(event): () => string | null { function textForWidgetEvent(event): () => string | null {
const senderName = event.getSender(); const senderName = event.getSender();
const {name: prevName, type: prevType, url: prevUrl} = event.getPrevContent(); const { name: prevName, type: prevType, url: prevUrl } = event.getPrevContent();
const {name, type, url} = event.getContent() || {}; const { name, type, url } = event.getContent() || {};
let widgetName = name || prevName || type || prevType || ''; let widgetName = name || prevName || type || prevType || '';
// Apply sentence case to widget name // Apply sentence case to widget name
@ -547,68 +547,68 @@ function textForWidgetEvent(event): () => string | null {
function textForWidgetLayoutEvent(event): () => string | null { function textForWidgetLayoutEvent(event): () => string | null {
const senderName = event.sender?.name || event.getSender(); const senderName = event.sender?.name || event.getSender();
return () => _t("%(senderName)s has updated the widget layout", {senderName}); return () => _t("%(senderName)s has updated the widget layout", { senderName });
} }
function textForMjolnirEvent(event): () => string | null { function textForMjolnirEvent(event): () => string | null {
const senderName = event.getSender(); const senderName = event.getSender();
const {entity: prevEntity} = event.getPrevContent(); const { entity: prevEntity } = event.getPrevContent();
const {entity, recommendation, reason} = event.getContent(); const { entity, recommendation, reason } = event.getContent();
// Rule removed // Rule removed
if (!entity) { if (!entity) {
if (USER_RULE_TYPES.includes(event.getType())) { if (USER_RULE_TYPES.includes(event.getType())) {
return () => _t("%(senderName)s removed the rule banning users matching %(glob)s", return () => _t("%(senderName)s removed the rule banning users matching %(glob)s",
{senderName, glob: prevEntity}); { senderName, glob: prevEntity });
} else if (ROOM_RULE_TYPES.includes(event.getType())) { } else if (ROOM_RULE_TYPES.includes(event.getType())) {
return () => _t("%(senderName)s removed the rule banning rooms matching %(glob)s", return () => _t("%(senderName)s removed the rule banning rooms matching %(glob)s",
{senderName, glob: prevEntity}); { senderName, glob: prevEntity });
} else if (SERVER_RULE_TYPES.includes(event.getType())) { } else if (SERVER_RULE_TYPES.includes(event.getType())) {
return () => _t("%(senderName)s removed the rule banning servers matching %(glob)s", return () => _t("%(senderName)s removed the rule banning servers matching %(glob)s",
{senderName, glob: prevEntity}); { senderName, glob: prevEntity });
} }
// Unknown type. We'll say something, but we shouldn't end up here. // Unknown type. We'll say something, but we shouldn't end up here.
return () => _t("%(senderName)s removed a ban rule matching %(glob)s", {senderName, glob: prevEntity}); return () => _t("%(senderName)s removed a ban rule matching %(glob)s", { senderName, glob: prevEntity });
} }
// Invalid rule // Invalid rule
if (!recommendation || !reason) return () => _t(`%(senderName)s updated an invalid ban rule`, {senderName}); if (!recommendation || !reason) return () => _t(`%(senderName)s updated an invalid ban rule`, { senderName });
// Rule updated // Rule updated
if (entity === prevEntity) { if (entity === prevEntity) {
if (USER_RULE_TYPES.includes(event.getType())) { if (USER_RULE_TYPES.includes(event.getType())) {
return () => _t("%(senderName)s updated the rule banning users matching %(glob)s for %(reason)s", return () => _t("%(senderName)s updated the rule banning users matching %(glob)s for %(reason)s",
{senderName, glob: entity, reason}); { senderName, glob: entity, reason });
} else if (ROOM_RULE_TYPES.includes(event.getType())) { } else if (ROOM_RULE_TYPES.includes(event.getType())) {
return () => _t("%(senderName)s updated the rule banning rooms matching %(glob)s for %(reason)s", return () => _t("%(senderName)s updated the rule banning rooms matching %(glob)s for %(reason)s",
{senderName, glob: entity, reason}); { senderName, glob: entity, reason });
} else if (SERVER_RULE_TYPES.includes(event.getType())) { } else if (SERVER_RULE_TYPES.includes(event.getType())) {
return () => _t("%(senderName)s updated the rule banning servers matching %(glob)s for %(reason)s", return () => _t("%(senderName)s updated the rule banning servers matching %(glob)s for %(reason)s",
{senderName, glob: entity, reason}); { senderName, glob: entity, reason });
} }
// Unknown type. We'll say something but we shouldn't end up here. // Unknown type. We'll say something but we shouldn't end up here.
return () => _t("%(senderName)s updated a ban rule matching %(glob)s for %(reason)s", return () => _t("%(senderName)s updated a ban rule matching %(glob)s for %(reason)s",
{senderName, glob: entity, reason}); { senderName, glob: entity, reason });
} }
// New rule // New rule
if (!prevEntity) { if (!prevEntity) {
if (USER_RULE_TYPES.includes(event.getType())) { if (USER_RULE_TYPES.includes(event.getType())) {
return () => _t("%(senderName)s created a rule banning users matching %(glob)s for %(reason)s", return () => _t("%(senderName)s created a rule banning users matching %(glob)s for %(reason)s",
{senderName, glob: entity, reason}); { senderName, glob: entity, reason });
} else if (ROOM_RULE_TYPES.includes(event.getType())) { } else if (ROOM_RULE_TYPES.includes(event.getType())) {
return () => _t("%(senderName)s created a rule banning rooms matching %(glob)s for %(reason)s", return () => _t("%(senderName)s created a rule banning rooms matching %(glob)s for %(reason)s",
{senderName, glob: entity, reason}); { senderName, glob: entity, reason });
} else if (SERVER_RULE_TYPES.includes(event.getType())) { } else if (SERVER_RULE_TYPES.includes(event.getType())) {
return () => _t("%(senderName)s created a rule banning servers matching %(glob)s for %(reason)s", return () => _t("%(senderName)s created a rule banning servers matching %(glob)s for %(reason)s",
{senderName, glob: entity, reason}); { senderName, glob: entity, reason });
} }
// Unknown type. We'll say something but we shouldn't end up here. // Unknown type. We'll say something but we shouldn't end up here.
return () => _t("%(senderName)s created a ban rule matching %(glob)s for %(reason)s", return () => _t("%(senderName)s created a ban rule matching %(glob)s for %(reason)s",
{senderName, glob: entity, reason}); { senderName, glob: entity, reason });
} }
// else the entity !== prevEntity - count as a removal & add // else the entity !== prevEntity - count as a removal & add
@ -616,25 +616,25 @@ function textForMjolnirEvent(event): () => string | null {
return () => _t( return () => _t(
"%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching " + "%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching " +
"%(newGlob)s for %(reason)s", "%(newGlob)s for %(reason)s",
{senderName, oldGlob: prevEntity, newGlob: entity, reason}, { senderName, oldGlob: prevEntity, newGlob: entity, reason },
); );
} else if (ROOM_RULE_TYPES.includes(event.getType())) { } else if (ROOM_RULE_TYPES.includes(event.getType())) {
return () => _t( return () => _t(
"%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching " + "%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching " +
"%(newGlob)s for %(reason)s", "%(newGlob)s for %(reason)s",
{senderName, oldGlob: prevEntity, newGlob: entity, reason}, { senderName, oldGlob: prevEntity, newGlob: entity, reason },
); );
} else if (SERVER_RULE_TYPES.includes(event.getType())) { } else if (SERVER_RULE_TYPES.includes(event.getType())) {
return () => _t( return () => _t(
"%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching " + "%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching " +
"%(newGlob)s for %(reason)s", "%(newGlob)s for %(reason)s",
{senderName, oldGlob: prevEntity, newGlob: entity, reason}, { senderName, oldGlob: prevEntity, newGlob: entity, reason },
); );
} }
// Unknown type. We'll say something but we shouldn't end up here. // Unknown type. We'll say something but we shouldn't end up here.
return () => _t("%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s " + return () => _t("%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s " +
"for %(reason)s", {senderName, oldGlob: prevEntity, newGlob: entity, reason}); "for %(reason)s", { senderName, oldGlob: prevEntity, newGlob: entity, reason });
} }
interface IHandlers { interface IHandlers {

View file

@ -191,10 +191,10 @@ export default class UserActivity {
this.lastScreenY = event.screenY; this.lastScreenY = event.screenY;
} }
dis.dispatch({action: 'user_activity'}); dis.dispatch({ action: 'user_activity' });
if (!this.activeNowTimeout.isRunning()) { if (!this.activeNowTimeout.isRunning()) {
this.activeNowTimeout.start(); this.activeNowTimeout.start();
dis.dispatch({action: 'user_activity_start'}); dis.dispatch({ action: 'user_activity_start' });
UserActivity.runTimersUntilTimeout(this.attachedActiveNowTimers, this.activeNowTimeout); UserActivity.runTimersUntilTimeout(this.attachedActiveNowTimers, this.activeNowTimeout);
} else { } else {

View file

@ -14,10 +14,10 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
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";
import {MatrixClientPeg} from "./MatrixClientPeg"; import { MatrixClientPeg } from "./MatrixClientPeg";
import { _t } from './languageHandler'; import { _t } from './languageHandler';
export function usersTypingApartFromMeAndIgnored(room: Room): RoomMember[] { export function usersTypingApartFromMeAndIgnored(room: Room): RoomMember[] {
@ -61,7 +61,7 @@ export function whoIsTypingString(whoIsTyping: RoomMember[], limit: number): str
if (whoIsTyping.length === 0) { if (whoIsTyping.length === 0) {
return ''; return '';
} else if (whoIsTyping.length === 1) { } else if (whoIsTyping.length === 1) {
return _t('%(displayName)s is typing …', {displayName: whoIsTyping[0].name}); return _t('%(displayName)s is typing …', { displayName: whoIsTyping[0].name });
} }
const names = whoIsTyping.map(m => m.name); const names = whoIsTyping.map(m => m.name);
@ -73,6 +73,6 @@ export function whoIsTypingString(whoIsTyping: RoomMember[], limit: number): str
}); });
} else { } else {
const lastPerson = names.pop(); const lastPerson = names.pop();
return _t('%(names)s and %(lastPerson)s are typing …', {names: names.join(', '), lastPerson: lastPerson}); return _t('%(names)s and %(lastPerson)s are typing …', { names: names.join(', '), lastPerson: lastPerson });
} }
} }

View file

@ -20,7 +20,7 @@ import classNames from "classnames";
import * as sdk from "../index"; 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";
// 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");
@ -332,7 +332,7 @@ const keyIcon: Record<string, string> = {
const Shortcut: React.FC<{ const Shortcut: React.FC<{
shortcut: IShortcut; shortcut: IShortcut;
}> = ({shortcut}) => { }> = ({ shortcut }) => {
const classes = classNames({ const classes = classNames({
"mx_KeyboardShortcutsDialog_inline": shortcut.keybinds.every(k => !k.modifiers || k.modifiers.length === 0), "mx_KeyboardShortcutsDialog_inline": shortcut.keybinds.every(k => !k.modifiers || k.modifiers.length === 0),
}); });

View file

@ -26,8 +26,8 @@ import React, {
Dispatch, Dispatch,
} from "react"; } from "react";
import {Key} from "../Keyboard"; import { Key } from "../Keyboard";
import {FocusHandler, Ref} from "./roving/types"; import { FocusHandler, Ref } from "./roving/types";
/** /**
* Module to simplify implementing the Roving TabIndex accessibility technique * Module to simplify implementing the Roving TabIndex accessibility technique
@ -156,13 +156,13 @@ interface IProps {
onKeyDown?(ev: React.KeyboardEvent, state: IState); onKeyDown?(ev: React.KeyboardEvent, state: IState);
} }
export const RovingTabIndexProvider: React.FC<IProps> = ({children, handleHomeEnd, onKeyDown}) => { export const RovingTabIndexProvider: React.FC<IProps> = ({ children, handleHomeEnd, onKeyDown }) => {
const [state, dispatch] = useReducer<Reducer<IState, IAction>>(reducer, { const [state, dispatch] = useReducer<Reducer<IState, IAction>>(reducer, {
activeRef: null, activeRef: null,
refs: [], refs: [],
}); });
const context = useMemo<IContext>(() => ({state, dispatch}), [state]); const context = useMemo<IContext>(() => ({ state, dispatch }), [state]);
const onKeyDownHandler = useCallback((ev) => { const onKeyDownHandler = useCallback((ev) => {
let handled = false; let handled = false;
@ -196,7 +196,7 @@ export const RovingTabIndexProvider: React.FC<IProps> = ({children, handleHomeEn
}, [context.state, onKeyDown, handleHomeEnd]); }, [context.state, onKeyDown, handleHomeEnd]);
return <RovingTabIndexContext.Provider value={context}> return <RovingTabIndexContext.Provider value={context}>
{ children({onKeyDownHandler}) } { children({ onKeyDownHandler }) }
</RovingTabIndexContext.Provider>; </RovingTabIndexContext.Provider>;
}; };
@ -218,13 +218,13 @@ export const useRovingTabIndex = (inputRef?: Ref): [FocusHandler, boolean, Ref]
useLayoutEffect(() => { useLayoutEffect(() => {
context.dispatch({ context.dispatch({
type: Type.Register, type: Type.Register,
payload: {ref}, payload: { ref },
}); });
// teardown // teardown
return () => { return () => {
context.dispatch({ context.dispatch({
type: Type.Unregister, type: Type.Unregister,
payload: {ref}, payload: { ref },
}); });
}; };
}, []); // eslint-disable-line react-hooks/exhaustive-deps }, []); // eslint-disable-line react-hooks/exhaustive-deps
@ -232,7 +232,7 @@ export const useRovingTabIndex = (inputRef?: Ref): [FocusHandler, boolean, Ref]
const onFocus = useCallback(() => { const onFocus = useCallback(() => {
context.dispatch({ context.dispatch({
type: Type.SetFocus, type: Type.SetFocus,
payload: {ref}, payload: { ref },
}); });
}, [ref, context]); }, [ref, context]);
@ -241,6 +241,6 @@ export const useRovingTabIndex = (inputRef?: Ref): [FocusHandler, boolean, Ref]
}; };
// re-export the semantic helper components for simplicity // re-export the semantic helper components for simplicity
export {RovingTabIndexWrapper} from "./roving/RovingTabIndexWrapper"; export { RovingTabIndexWrapper } from "./roving/RovingTabIndexWrapper";
export {RovingAccessibleButton} from "./roving/RovingAccessibleButton"; export { RovingAccessibleButton } from "./roving/RovingAccessibleButton";
export {RovingAccessibleTooltipButton} from "./roving/RovingAccessibleTooltipButton"; export { RovingAccessibleTooltipButton } from "./roving/RovingAccessibleTooltipButton";

View file

@ -16,8 +16,8 @@ limitations under the License.
import React from "react"; import React from "react";
import {IState, RovingTabIndexProvider} from "./RovingTabIndex"; import { IState, RovingTabIndexProvider } from "./RovingTabIndex";
import {Key} from "../Keyboard"; import { Key } from "../Keyboard";
interface IProps extends Omit<React.HTMLProps<HTMLDivElement>, "onKeyDown"> { interface IProps extends Omit<React.HTMLProps<HTMLDivElement>, "onKeyDown"> {
} }
@ -25,7 +25,7 @@ interface IProps extends Omit<React.HTMLProps<HTMLDivElement>, "onKeyDown"> {
// This component implements the Toolbar design pattern from the WAI-ARIA Authoring Practices guidelines. // This component implements the Toolbar design pattern from the WAI-ARIA Authoring Practices guidelines.
// https://www.w3.org/TR/wai-aria-practices-1.1/#toolbar // https://www.w3.org/TR/wai-aria-practices-1.1/#toolbar
// All buttons passed in children must use RovingTabIndex to set `onFocus`, `isActive`, `ref` // All buttons passed in children must use RovingTabIndex to set `onFocus`, `isActive`, `ref`
const Toolbar: React.FC<IProps> = ({children, ...props}) => { const Toolbar: React.FC<IProps> = ({ children, ...props }) => {
const onKeyDown = (ev: React.KeyboardEvent, state: IState) => { const onKeyDown = (ev: React.KeyboardEvent, state: IState) => {
const target = ev.target as HTMLElement; const target = ev.target as HTMLElement;
// Don't interfere with input default keydown behaviour // Don't interfere with input default keydown behaviour
@ -62,7 +62,7 @@ const Toolbar: React.FC<IProps> = ({children, ...props}) => {
}; };
return <RovingTabIndexProvider handleHomeEnd={true} onKeyDown={onKeyDown}> return <RovingTabIndexProvider handleHomeEnd={true} onKeyDown={onKeyDown}>
{({onKeyDownHandler}) => <div {...props} onKeyDown={onKeyDownHandler} role="toolbar"> {({ onKeyDownHandler }) => <div {...props} onKeyDown={onKeyDownHandler} role="toolbar">
{ children } { children }
</div>} </div>}
</RovingTabIndexProvider>; </RovingTabIndexProvider>;

View file

@ -23,7 +23,7 @@ interface IProps extends React.HTMLAttributes<HTMLDivElement> {
} }
// Semantic component for representing a role=group for grouping menu radios/checkboxes // Semantic component for representing a role=group for grouping menu radios/checkboxes
export const MenuGroup: React.FC<IProps> = ({children, label, ...props}) => { export const MenuGroup: React.FC<IProps> = ({ children, label, ...props }) => {
return <div {...props} role="group" aria-label={label}> return <div {...props} role="group" aria-label={label}>
{ children } { children }
</div>; </div>;

View file

@ -27,7 +27,7 @@ interface IProps extends React.ComponentProps<typeof AccessibleButton> {
} }
// Semantic component for representing a role=menuitem // Semantic component for representing a role=menuitem
export const MenuItem: React.FC<IProps> = ({children, label, tooltip, ...props}) => { export const MenuItem: React.FC<IProps> = ({ children, label, tooltip, ...props }) => {
const ariaLabel = props["aria-label"] || label; const ariaLabel = props["aria-label"] || label;
if (tooltip) { if (tooltip) {

View file

@ -26,7 +26,7 @@ interface IProps extends React.ComponentProps<typeof AccessibleButton> {
} }
// Semantic component for representing a role=menuitemcheckbox // Semantic component for representing a role=menuitemcheckbox
export const MenuItemCheckbox: React.FC<IProps> = ({children, label, active, disabled, ...props}) => { export const MenuItemCheckbox: React.FC<IProps> = ({ children, label, active, disabled, ...props }) => {
return ( return (
<AccessibleButton <AccessibleButton
{...props} {...props}

View file

@ -26,7 +26,7 @@ interface IProps extends React.ComponentProps<typeof AccessibleButton> {
} }
// Semantic component for representing a role=menuitemradio // Semantic component for representing a role=menuitemradio
export const MenuItemRadio: React.FC<IProps> = ({children, label, active, disabled, ...props}) => { export const MenuItemRadio: React.FC<IProps> = ({ children, label, active, disabled, ...props }) => {
return ( return (
<AccessibleButton <AccessibleButton
{...props} {...props}

View file

@ -18,7 +18,7 @@ limitations under the License.
import React from "react"; import React from "react";
import {Key} from "../../Keyboard"; import { Key } from "../../Keyboard";
import StyledCheckbox from "../../components/views/elements/StyledCheckbox"; import StyledCheckbox from "../../components/views/elements/StyledCheckbox";
interface IProps extends React.ComponentProps<typeof StyledCheckbox> { interface IProps extends React.ComponentProps<typeof StyledCheckbox> {
@ -28,7 +28,7 @@ interface IProps extends React.ComponentProps<typeof StyledCheckbox> {
} }
// Semantic component for representing a styled role=menuitemcheckbox // Semantic component for representing a styled role=menuitemcheckbox
export const StyledMenuItemCheckbox: React.FC<IProps> = ({children, label, onChange, onClose, ...props}) => { export const StyledMenuItemCheckbox: React.FC<IProps> = ({ children, label, onChange, onClose, ...props }) => {
const onKeyDown = (e: React.KeyboardEvent) => { const onKeyDown = (e: React.KeyboardEvent) => {
if (e.key === Key.ENTER || e.key === Key.SPACE) { if (e.key === Key.ENTER || e.key === Key.SPACE) {
e.stopPropagation(); e.stopPropagation();

View file

@ -18,7 +18,7 @@ limitations under the License.
import React from "react"; import React from "react";
import {Key} from "../../Keyboard"; import { Key } from "../../Keyboard";
import StyledRadioButton from "../../components/views/elements/StyledRadioButton"; import StyledRadioButton from "../../components/views/elements/StyledRadioButton";
interface IProps extends React.ComponentProps<typeof StyledRadioButton> { interface IProps extends React.ComponentProps<typeof StyledRadioButton> {
@ -28,7 +28,7 @@ interface IProps extends React.ComponentProps<typeof StyledRadioButton> {
} }
// Semantic component for representing a styled role=menuitemradio // Semantic component for representing a styled role=menuitemradio
export const StyledMenuItemRadio: React.FC<IProps> = ({children, label, onChange, onClose, ...props}) => { export const StyledMenuItemRadio: React.FC<IProps> = ({ children, label, onChange, onClose, ...props }) => {
const onKeyDown = (e: React.KeyboardEvent) => { const onKeyDown = (e: React.KeyboardEvent) => {
if (e.key === Key.ENTER || e.key === Key.SPACE) { if (e.key === Key.ENTER || e.key === Key.SPACE) {
e.stopPropagation(); e.stopPropagation();

View file

@ -17,15 +17,15 @@ limitations under the License.
import React from "react"; import React from "react";
import AccessibleButton from "../../components/views/elements/AccessibleButton"; import AccessibleButton from "../../components/views/elements/AccessibleButton";
import {useRovingTabIndex} from "../RovingTabIndex"; import { useRovingTabIndex } from "../RovingTabIndex";
import {Ref} from "./types"; import { Ref } from "./types";
interface IProps extends Omit<React.ComponentProps<typeof AccessibleButton>, "onFocus" | "inputRef" | "tabIndex"> { interface IProps extends Omit<React.ComponentProps<typeof AccessibleButton>, "onFocus" | "inputRef" | "tabIndex"> {
inputRef?: Ref; inputRef?: Ref;
} }
// Wrapper to allow use of useRovingTabIndex for simple AccessibleButtons outside of React Functional Components. // Wrapper to allow use of useRovingTabIndex for simple AccessibleButtons outside of React Functional Components.
export const RovingAccessibleButton: React.FC<IProps> = ({inputRef, ...props}) => { export const RovingAccessibleButton: React.FC<IProps> = ({ inputRef, ...props }) => {
const [onFocus, isActive, ref] = useRovingTabIndex(inputRef); const [onFocus, isActive, ref] = useRovingTabIndex(inputRef);
return <AccessibleButton {...props} onFocus={onFocus} inputRef={ref} tabIndex={isActive ? 0 : -1} />; return <AccessibleButton {...props} onFocus={onFocus} inputRef={ref} tabIndex={isActive ? 0 : -1} />;
}; };

View file

@ -17,8 +17,8 @@ limitations under the License.
import React from "react"; import React from "react";
import AccessibleTooltipButton from "../../components/views/elements/AccessibleTooltipButton"; import AccessibleTooltipButton from "../../components/views/elements/AccessibleTooltipButton";
import {useRovingTabIndex} from "../RovingTabIndex"; import { useRovingTabIndex } from "../RovingTabIndex";
import {Ref} from "./types"; import { Ref } from "./types";
type ATBProps = React.ComponentProps<typeof AccessibleTooltipButton>; type ATBProps = React.ComponentProps<typeof AccessibleTooltipButton>;
interface IProps extends Omit<ATBProps, "onFocus" | "inputRef" | "tabIndex"> { interface IProps extends Omit<ATBProps, "onFocus" | "inputRef" | "tabIndex"> {
@ -26,7 +26,7 @@ interface IProps extends Omit<ATBProps, "onFocus" | "inputRef" | "tabIndex"> {
} }
// Wrapper to allow use of useRovingTabIndex for simple AccessibleTooltipButtons outside of React Functional Components. // Wrapper to allow use of useRovingTabIndex for simple AccessibleTooltipButtons outside of React Functional Components.
export const RovingAccessibleTooltipButton: React.FC<IProps> = ({inputRef, ...props}) => { export const RovingAccessibleTooltipButton: React.FC<IProps> = ({ inputRef, ...props }) => {
const [onFocus, isActive, ref] = useRovingTabIndex(inputRef); const [onFocus, isActive, ref] = useRovingTabIndex(inputRef);
return <AccessibleTooltipButton {...props} onFocus={onFocus} inputRef={ref} tabIndex={isActive ? 0 : -1} />; return <AccessibleTooltipButton {...props} onFocus={onFocus} inputRef={ref} tabIndex={isActive ? 0 : -1} />;
}; };

View file

@ -16,8 +16,8 @@ limitations under the License.
import React from "react"; import React from "react";
import {useRovingTabIndex} from "../RovingTabIndex"; import { useRovingTabIndex } from "../RovingTabIndex";
import {FocusHandler, Ref} from "./types"; import { FocusHandler, Ref } from "./types";
interface IProps { interface IProps {
inputRef?: Ref; inputRef?: Ref;
@ -29,7 +29,7 @@ interface IProps {
} }
// Wrapper to allow use of useRovingTabIndex outside of React Functional Components. // Wrapper to allow use of useRovingTabIndex outside of React Functional Components.
export const RovingTabIndexWrapper: React.FC<IProps> = ({children, inputRef}) => { export const RovingTabIndexWrapper: React.FC<IProps> = ({ children, inputRef }) => {
const [onFocus, isActive, ref] = useRovingTabIndex(inputRef); const [onFocus, isActive, ref] = useRovingTabIndex(inputRef);
return children({onFocus, isActive, ref}); return children({ onFocus, isActive, ref });
}; };

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {RefObject} from "react"; import { RefObject } from "react";
export type Ref = RefObject<HTMLElement>; export type Ref = RefObject<HTMLElement>;

View file

@ -20,7 +20,7 @@ import { Room } from "matrix-js-sdk/src/models/room";
import { EventTimeline } from "matrix-js-sdk/src/models/event-timeline"; import { EventTimeline } from "matrix-js-sdk/src/models/event-timeline";
import dis from "../dispatcher/dispatcher"; import dis from "../dispatcher/dispatcher";
import {ActionPayload} from "../dispatcher/payloads"; import { ActionPayload } from "../dispatcher/payloads";
// TODO: migrate from sync_state to MatrixActions.sync so that more js-sdk events // TODO: migrate from sync_state to MatrixActions.sync so that more js-sdk events
// become dispatches in the same place. // become dispatches in the same place.

View file

@ -112,7 +112,7 @@ export default class RoomListActions {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); 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 }),
description: ((err && err.message) ? err.message : _t('Operation failed')), description: ((err && err.message) ? err.message : _t('Operation failed')),
}); });
}); });
@ -132,7 +132,7 @@ export default class RoomListActions {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); 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 }),
description: ((err && err.message) ? err.message : _t('Operation failed')), description: ((err && err.message) ? err.message : _t('Operation failed')),
}); });

View file

@ -53,11 +53,11 @@ export default class TagOrderActions {
Analytics.trackEvent('TagOrderActions', 'commitTagOrdering'); Analytics.trackEvent('TagOrderActions', 'commitTagOrdering');
return matrixClient.setAccountData( return matrixClient.setAccountData(
'im.vector.web.tag_ordering', 'im.vector.web.tag_ordering',
{tags, removedTags, _storeId: storeId}, { tags, removedTags, _storeId: storeId },
); );
}, () => { }, () => {
// For an optimistic update // For an optimistic update
return {tags, removedTags}; return { tags, removedTags };
}); });
} }
@ -100,11 +100,11 @@ export default class TagOrderActions {
Analytics.trackEvent('TagOrderActions', 'removeTag'); Analytics.trackEvent('TagOrderActions', 'removeTag');
return matrixClient.setAccountData( return matrixClient.setAccountData(
'im.vector.web.tag_ordering', 'im.vector.web.tag_ordering',
{tags, removedTags, _storeId: storeId}, { tags, removedTags, _storeId: storeId },
); );
}, () => { }, () => {
// For an optimistic update // For an optimistic update
return {removedTags}; return { removedTags };
}); });
} }
} }

View file

@ -51,9 +51,9 @@ export function asyncAction(id: string, fn: () => Promise<any>, pendingFn: () =>
request: typeof pendingFn === 'function' ? pendingFn() : undefined, request: typeof pendingFn === 'function' ? pendingFn() : undefined,
}); });
fn().then((result) => { fn().then((result) => {
dispatch({action: id + '.success', result}); dispatch({ action: id + '.success', result });
}).catch((err) => { }).catch((err) => {
dispatch({action: id + '.failure', err}); dispatch({ action: id + '.failure', err });
}); });
}; };
return new AsyncActionPayload(helper); return new AsyncActionPayload(helper);

View file

@ -22,8 +22,8 @@ import { _t } from '../../../../languageHandler';
import SettingsStore from "../../../../settings/SettingsStore"; import SettingsStore from "../../../../settings/SettingsStore";
import EventIndexPeg from "../../../../indexing/EventIndexPeg"; import EventIndexPeg from "../../../../indexing/EventIndexPeg";
import {Action} from "../../../../dispatcher/actions"; import { Action } from "../../../../dispatcher/actions";
import {SettingLevel} from "../../../../settings/SettingLevel"; import { SettingLevel } from "../../../../settings/SettingLevel";
/* /*
* Allows the user to disable the Event Index. * Allows the user to disable the Event Index.

View file

@ -21,9 +21,9 @@ import SdkConfig from '../../../../SdkConfig';
import SettingsStore from "../../../../settings/SettingsStore"; import SettingsStore from "../../../../settings/SettingsStore";
import Modal from '../../../../Modal'; 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";
interface IProps { interface IProps {
onFinished: (confirmed: boolean) => void; onFinished: (confirmed: boolean) => void;
@ -139,7 +139,7 @@ export default class ManageEventIndexDialog extends React.Component<IProps, ISta
}; };
private onCrawlerSleepTimeChange = (e) => { private onCrawlerSleepTimeChange = (e) => {
this.setState({crawlerSleepTime: e.target.value}); this.setState({ crawlerSleepTime: e.target.value });
SettingsStore.setValue("crawlerSleepTime", null, SettingLevel.DEVICE, e.target.value); SettingsStore.setValue("crawlerSleepTime", null, SettingLevel.DEVICE, e.target.value);
}; };

View file

@ -15,15 +15,15 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React, {createRef} from 'react'; import React, { createRef } from 'react';
import FileSaver from 'file-saver'; import FileSaver from 'file-saver';
import * as sdk from '../../../../index'; import * as sdk from '../../../../index';
import {MatrixClientPeg} from '../../../../MatrixClientPeg'; import { MatrixClientPeg } from '../../../../MatrixClientPeg';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import {_t, _td} from '../../../../languageHandler'; import { _t, _td } from '../../../../languageHandler';
import { accessSecretStorage } from '../../../../SecurityManager'; import { accessSecretStorage } from '../../../../SecurityManager';
import AccessibleButton from "../../../../components/views/elements/AccessibleButton"; import AccessibleButton from "../../../../components/views/elements/AccessibleButton";
import {copyNode} from "../../../../utils/strings"; import { copyNode } from "../../../../utils/strings";
import PassphraseField from "../../../../components/views/auth/PassphraseField"; import PassphraseField from "../../../../components/views/auth/PassphraseField";
const PHASE_PASSPHRASE = 0; const PHASE_PASSPHRASE = 0;
@ -152,11 +152,11 @@ export default class CreateKeyBackupDialog extends React.PureComponent {
} }
_onOptOutClick = () => { _onOptOutClick = () => {
this.setState({phase: PHASE_OPTOUT_CONFIRM}); this.setState({ phase: PHASE_OPTOUT_CONFIRM });
} }
_onSetUpClick = () => { _onSetUpClick = () => {
this.setState({phase: PHASE_PASSPHRASE}); this.setState({ phase: PHASE_PASSPHRASE });
} }
_onSkipPassPhraseClick = async () => { _onSkipPassPhraseClick = async () => {
@ -179,7 +179,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent {
return; return;
} }
this.setState({phase: PHASE_PASSPHRASE_CONFIRM}); this.setState({ phase: PHASE_PASSPHRASE_CONFIRM });
}; };
_onPassPhraseConfirmNextClick = async (e) => { _onPassPhraseConfirmNextClick = async (e) => {
@ -370,21 +370,21 @@ export default class CreateKeyBackupDialog extends React.PureComponent {
if (this.state.copied) { if (this.state.copied) {
introText = _t( introText = _t(
"Your Security Key has been <b>copied to your clipboard</b>, paste it to:", "Your Security Key has been <b>copied to your clipboard</b>, paste it to:",
{}, {b: s => <b>{s}</b>}, {}, { b: s => <b>{s}</b> },
); );
} else if (this.state.downloaded) { } else if (this.state.downloaded) {
introText = _t( introText = _t(
"Your Security Key is in your <b>Downloads</b> folder.", "Your Security Key is in your <b>Downloads</b> folder.",
{}, {b: s => <b>{s}</b>}, {}, { b: s => <b>{s}</b> },
); );
} }
const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
return <div> return <div>
{introText} {introText}
<ul> <ul>
<li>{_t("<b>Print it</b> and store it somewhere safe", {}, {b: s => <b>{s}</b>})}</li> <li>{_t("<b>Print it</b> and store it somewhere safe", {}, { b: s => <b>{s}</b> })}</li>
<li>{_t("<b>Save it</b> on a USB key or backup drive", {}, {b: s => <b>{s}</b>})}</li> <li>{_t("<b>Save it</b> on a USB key or backup drive", {}, { b: s => <b>{s}</b> })}</li>
<li>{_t("<b>Copy it</b> to your personal cloud storage", {}, {b: s => <b>{s}</b>})}</li> <li>{_t("<b>Copy it</b> to your personal cloud storage", {}, { b: s => <b>{s}</b> })}</li>
</ul> </ul>
<DialogButtons primaryButton={_t("Continue")} <DialogButtons primaryButton={_t("Continue")}
onPrimaryButtonClick={this._createBackup} onPrimaryButtonClick={this._createBackup}

View file

@ -15,16 +15,16 @@ See the License for the specific language governing permissions and
limitations under the License. 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 * as sdk from '../../../../index'; import * as sdk from '../../../../index';
import {MatrixClientPeg} from '../../../../MatrixClientPeg'; import { MatrixClientPeg } from '../../../../MatrixClientPeg';
import FileSaver from 'file-saver'; import FileSaver from 'file-saver';
import {_t, _td} from '../../../../languageHandler'; import { _t, _td } from '../../../../languageHandler';
import Modal from '../../../../Modal'; import Modal from '../../../../Modal';
import { promptForBackupPassphrase } from '../../../../SecurityManager'; import { promptForBackupPassphrase } from '../../../../SecurityManager';
import {copyNode} from "../../../../utils/strings"; import { copyNode } from "../../../../utils/strings";
import {SSOAuthEntry} from "../../../../components/views/auth/InteractiveAuthEntryComponents"; import { SSOAuthEntry } from "../../../../components/views/auth/InteractiveAuthEntryComponents";
import PassphraseField from "../../../../components/views/auth/PassphraseField"; import PassphraseField from "../../../../components/views/auth/PassphraseField";
import StyledRadioButton from '../../../../components/views/elements/StyledRadioButton'; import StyledRadioButton from '../../../../components/views/elements/StyledRadioButton';
import AccessibleButton from "../../../../components/views/elements/AccessibleButton"; import AccessibleButton from "../../../../components/views/elements/AccessibleButton";
@ -155,7 +155,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
backupSigStatus, backupSigStatus,
}; };
} catch (e) { } catch (e) {
this.setState({phase: PHASE_LOADERROR}); this.setState({ phase: PHASE_LOADERROR });
} }
} }
@ -385,7 +385,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
} }
_onLoadRetryClick = () => { _onLoadRetryClick = () => {
this.setState({phase: PHASE_LOADING}); this.setState({ phase: PHASE_LOADING });
this._fetchBackupInfo(); this._fetchBackupInfo();
} }
@ -394,11 +394,11 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
} }
_onCancelClick = () => { _onCancelClick = () => {
this.setState({phase: PHASE_CONFIRM_SKIP}); this.setState({ phase: PHASE_CONFIRM_SKIP });
} }
_onGoBackClick = () => { _onGoBackClick = () => {
this.setState({phase: PHASE_CHOOSE_KEY_PASSPHRASE}); this.setState({ phase: PHASE_CHOOSE_KEY_PASSPHRASE });
} }
_onPassPhraseNextClick = async (e) => { _onPassPhraseNextClick = async (e) => {
@ -412,7 +412,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
return; return;
} }
this.setState({phase: PHASE_PASSPHRASE_CONFIRM}); this.setState({ phase: PHASE_PASSPHRASE_CONFIRM });
}; };
_onPassPhraseConfirmNextClick = async (e) => { _onPassPhraseConfirmNextClick = async (e) => {

View file

@ -15,7 +15,7 @@ limitations under the License.
*/ */
import FileSaver from 'file-saver'; import FileSaver from 'file-saver';
import React, {createRef} from 'react'; import React, { createRef } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { _t } from '../../../../languageHandler'; import { _t } from '../../../../languageHandler';
@ -55,11 +55,11 @@ export default class ExportE2eKeysDialog extends React.Component {
const passphrase = this._passphrase1.current.value; const passphrase = this._passphrase1.current.value;
if (passphrase !== this._passphrase2.current.value) { if (passphrase !== this._passphrase2.current.value) {
this.setState({errStr: _t('Passphrases must match')}); this.setState({ errStr: _t('Passphrases must match') });
return false; return false;
} }
if (!passphrase) { if (!passphrase) {
this.setState({errStr: _t('Passphrase must not be empty')}); this.setState({ errStr: _t('Passphrase must not be empty') });
return false; return false;
} }

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. 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 { MatrixClient } from 'matrix-js-sdk/src/client'; import { MatrixClient } from 'matrix-js-sdk/src/client';

View file

@ -18,12 +18,12 @@ limitations under the License.
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import * as sdk from "../../../../index"; import * as sdk from "../../../../index";
import {MatrixClientPeg} from '../../../../MatrixClientPeg'; import { MatrixClientPeg } from '../../../../MatrixClientPeg';
import dis from "../../../../dispatcher/dispatcher"; import dis from "../../../../dispatcher/dispatcher";
import { _t } from "../../../../languageHandler"; import { _t } from "../../../../languageHandler";
import Modal from "../../../../Modal"; import Modal from "../../../../Modal";
import RestoreKeyBackupDialog from "../../../../components/views/dialogs/security/RestoreKeyBackupDialog"; import RestoreKeyBackupDialog from "../../../../components/views/dialogs/security/RestoreKeyBackupDialog";
import {Action} from "../../../../dispatcher/actions"; import { Action } from "../../../../dispatcher/actions";
export default class NewRecoveryMethodDialog extends React.PureComponent { export default class NewRecoveryMethodDialog extends React.PureComponent {
static propTypes = { static propTypes = {

View file

@ -21,7 +21,7 @@ import * as sdk from "../../../../index";
import dis from "../../../../dispatcher/dispatcher"; import dis from "../../../../dispatcher/dispatcher";
import { _t } from "../../../../languageHandler"; import { _t } from "../../../../languageHandler";
import Modal from "../../../../Modal"; import Modal from "../../../../Modal";
import {Action} from "../../../../dispatcher/actions"; import { Action } from "../../../../dispatcher/actions";
export default class RecoveryMethodRemovedDialog extends React.PureComponent { export default class RecoveryMethodRemovedDialog extends React.PureComponent {
static propTypes = { static propTypes = {

View file

@ -17,7 +17,7 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import type {ICompletion, ISelectionRange} from './Autocompleter'; import type { ICompletion, ISelectionRange } from './Autocompleter';
export interface ICommand { export interface ICommand {
command: string | null; command: string | null;

View file

@ -26,7 +26,7 @@ import UserProvider from './UserProvider';
import EmojiProvider from './EmojiProvider'; import EmojiProvider from './EmojiProvider';
import NotifProvider from './NotifProvider'; import NotifProvider from './NotifProvider';
import { timeout } from "../utils/promise"; import { timeout } from "../utils/promise";
import AutocompleteProvider, {ICommand} from "./AutocompleteProvider"; import AutocompleteProvider, { ICommand } from "./AutocompleteProvider";
import SettingsStore from "../settings/SettingsStore"; import SettingsStore from "../settings/SettingsStore";
import SpaceProvider from "./SpaceProvider"; import SpaceProvider from "./SpaceProvider";

View file

@ -18,12 +18,12 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import {_t} from '../languageHandler'; import { _t } from '../languageHandler';
import AutocompleteProvider from './AutocompleteProvider'; import AutocompleteProvider from './AutocompleteProvider';
import QueryMatcher from './QueryMatcher'; import QueryMatcher from './QueryMatcher';
import {TextualCompletion} from './Components'; import { TextualCompletion } from './Components';
import {ICompletion, ISelectionRange} from "./Autocompleter"; import { ICompletion, ISelectionRange } from "./Autocompleter";
import {Command, Commands, CommandMap} from '../SlashCommands'; import { Command, Commands, CommandMap } from '../SlashCommands';
const COMMAND_RE = /(^\/\w*)(?: .*)?/g; const COMMAND_RE = /(^\/\w*)(?: .*)?/g;
@ -34,7 +34,7 @@ export default class CommandProvider extends AutocompleteProvider {
super(COMMAND_RE); super(COMMAND_RE);
this.matcher = new QueryMatcher(Commands, { this.matcher = new QueryMatcher(Commands, {
keys: ['command', 'args', 'description'], keys: ['command', 'args', 'description'],
funcs: [({aliases}) => aliases.join(" ")], // aliases funcs: [({ aliases }) => aliases.join(" ")], // aliases
}); });
} }
@ -44,7 +44,7 @@ export default class CommandProvider extends AutocompleteProvider {
force?: boolean, force?: boolean,
limit = -1, limit = -1,
): Promise<ICompletion[]> { ): Promise<ICompletion[]> {
const {command, range} = this.getCurrentCommand(query, selection); const { command, range } = this.getCurrentCommand(query, selection);
if (!command) return []; if (!command) return [];
let matches = []; let matches = [];
@ -68,7 +68,6 @@ export default class CommandProvider extends AutocompleteProvider {
} }
} }
return matches.filter(cmd => cmd.isEnabled()).map((result) => { return matches.filter(cmd => cmd.isEnabled()).map((result) => {
let completion = result.getCommand() + ' '; let completion = result.getCommand() + ' ';
const usedAlias = result.aliases.find(alias => `/${alias}` === command[1]); const usedAlias = result.aliases.find(alias => `/${alias}` === command[1]);

View file

@ -19,15 +19,15 @@ import React from 'react';
import Group from "matrix-js-sdk/src/models/group"; import Group from "matrix-js-sdk/src/models/group";
import { _t } from '../languageHandler'; import { _t } from '../languageHandler';
import AutocompleteProvider from './AutocompleteProvider'; 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 * 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";
const COMMUNITY_REGEX = /\B\+\S*/g; const COMMUNITY_REGEX = /\B\+\S*/g;
@ -66,11 +66,11 @@ export default class CommunityProvider extends AutocompleteProvider {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
let completions = []; let completions = [];
const {command, range} = this.getCurrentCommand(query, selection, force); const { command, range } = this.getCurrentCommand(query, selection, force);
if (command) { if (command) {
const joinedGroups = cli.getGroups().filter(({myMembership}) => myMembership === 'join'); const joinedGroups = cli.getGroups().filter(({ myMembership }) => myMembership === 'join');
const groups = (await Promise.all(joinedGroups.map(async ({groupId}) => { const groups = (await Promise.all(joinedGroups.map(async ({ groupId }) => {
try { try {
return FlairStore.getGroupProfileCached(cli, groupId); return FlairStore.getGroupProfileCached(cli, groupId);
} catch (e) { // if FlairStore failed, fall back to just groupId } catch (e) { // if FlairStore failed, fall back to just groupId
@ -90,7 +90,7 @@ export default class CommunityProvider extends AutocompleteProvider {
completions = sortBy(completions, [ completions = sortBy(completions, [
(c) => score(matchedString, c.groupId), (c) => score(matchedString, c.groupId),
(c) => c.groupId.length, (c) => c.groupId.length,
]).map(({avatarUrl, groupId, name}) => ({ ]).map(({ avatarUrl, groupId, name }) => ({
completion: groupId, completion: groupId,
suffix: ' ', suffix: ' ',
type: "community", type: "community",

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React, {forwardRef} from 'react'; import React, { forwardRef } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
/* These were earlier stateless functional components but had to be converted /* These were earlier stateless functional components but had to be converted
@ -31,7 +31,7 @@ interface ITextualCompletionProps {
} }
export const TextualCompletion = forwardRef<ITextualCompletionProps, any>((props, ref) => { export const TextualCompletion = forwardRef<ITextualCompletionProps, any>((props, ref) => {
const {title, subtitle, description, className, ...restProps} = props; const { title, subtitle, description, className, ...restProps } = props;
return ( return (
<div {...restProps} <div {...restProps}
className={classNames('mx_Autocomplete_Completion_block', className)} className={classNames('mx_Autocomplete_Completion_block', className)}
@ -50,7 +50,7 @@ interface IPillCompletionProps extends ITextualCompletionProps {
} }
export const PillCompletion = forwardRef<IPillCompletionProps, any>((props, ref) => { export const PillCompletion = forwardRef<IPillCompletionProps, any>((props, ref) => {
const {title, subtitle, description, className, children, ...restProps} = props; const { title, subtitle, description, className, children, ...restProps } = props;
return ( return (
<div {...restProps} <div {...restProps}
className={classNames('mx_Autocomplete_Completion_pill', className)} className={classNames('mx_Autocomplete_Completion_pill', className)}

View file

@ -20,8 +20,8 @@ import React from 'react';
import { _t } from '../languageHandler'; import { _t } from '../languageHandler';
import AutocompleteProvider from './AutocompleteProvider'; import AutocompleteProvider from './AutocompleteProvider';
import {TextualCompletion} from './Components'; import { TextualCompletion } from './Components';
import {ICompletion, ISelectionRange} from "./Autocompleter"; import { ICompletion, ISelectionRange } from "./Autocompleter";
const DDG_REGEX = /\/ddg\s+(.+)$/g; const DDG_REGEX = /\/ddg\s+(.+)$/g;
const REFERRER = 'vector'; const REFERRER = 'vector';
@ -42,7 +42,7 @@ export default class DuckDuckGoProvider extends AutocompleteProvider {
force = false, force = false,
limit = -1, limit = -1,
): Promise<ICompletion[]> { ): Promise<ICompletion[]> {
const {command, range} = this.getCurrentCommand(query, selection); const { command, range } = this.getCurrentCommand(query, selection);
if (!query || !command) { if (!query || !command) {
return []; return [];
} }

View file

@ -21,9 +21,9 @@ import React from 'react';
import { _t } from '../languageHandler'; import { _t } from '../languageHandler';
import AutocompleteProvider from './AutocompleteProvider'; import AutocompleteProvider from './AutocompleteProvider';
import QueryMatcher from './QueryMatcher'; import QueryMatcher from './QueryMatcher';
import {PillCompletion} from './Components'; import { PillCompletion } from './Components';
import {ICompletion, ISelectionRange} from './Autocompleter'; import { ICompletion, ISelectionRange } from './Autocompleter';
import {uniq, sortBy} from 'lodash'; import { uniq, sortBy } from 'lodash';
import SettingsStore from "../settings/SettingsStore"; import SettingsStore from "../settings/SettingsStore";
import { shortcodeToUnicode } from '../HtmlUtils'; import { shortcodeToUnicode } from '../HtmlUtils';
import { EMOJI, IEmoji } from '../emoji'; import { EMOJI, IEmoji } from '../emoji';
@ -95,7 +95,7 @@ export default class EmojiProvider extends AutocompleteProvider {
} }
let completions = []; let completions = [];
const {command, range} = this.getCurrentCommand(query, selection); const { command, range } = this.getCurrentCommand(query, selection);
if (command) { if (command) {
const matchedString = command[0]; const matchedString = command[0];
completions = this.matcher.match(matchedString, limit); completions = this.matcher.match(matchedString, limit);
@ -121,7 +121,7 @@ export default class EmojiProvider extends AutocompleteProvider {
sorters.push((c) => c._orderBy); sorters.push((c) => c._orderBy);
completions = sortBy(uniq(completions), sorters); completions = sortBy(uniq(completions), sorters);
completions = completions.map(({shortname}) => { completions = completions.map(({ shortname }) => {
const unicode = shortcodeToUnicode(shortname); const unicode = shortcodeToUnicode(shortname);
return { return {
completion: unicode, completion: unicode,

View file

@ -19,10 +19,10 @@ import { Room } from "matrix-js-sdk/src/models/room";
import AutocompleteProvider from './AutocompleteProvider'; 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 * as sdk from '../index';
import {ICompletion, ISelectionRange} from "./Autocompleter"; import { ICompletion, ISelectionRange } from "./Autocompleter";
const AT_ROOM_REGEX = /@\S*/g; const AT_ROOM_REGEX = /@\S*/g;
@ -46,7 +46,7 @@ export default class NotifProvider extends AutocompleteProvider {
if (!this.room.currentState.mayTriggerNotifOfType('room', client.credentials.userId)) return []; if (!this.room.currentState.mayTriggerNotifOfType('room', client.credentials.userId)) return [];
const {command, range} = this.getCurrentCommand(query, selection, force); const { command, range } = this.getCurrentCommand(query, selection, force);
if (command && command[0] && '@room'.startsWith(command[0]) && command[0].length > 1) { if (command && command[0] && '@room'.startsWith(command[0]) && command[0].length > 1) {
return [{ return [{
completion: '@room', completion: '@room',

View file

@ -16,8 +16,8 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {at, uniq} from 'lodash'; import { at, uniq } from 'lodash';
import {removeHiddenChars} from "matrix-js-sdk/src/utils"; import { removeHiddenChars } from "matrix-js-sdk/src/utils";
interface IOptions<T extends {}> { interface IOptions<T extends {}> {
keys: Array<string | keyof T>; keys: Array<string | keyof T>;
@ -112,7 +112,7 @@ export default class QueryMatcher<T extends Object> {
const index = resultKey.indexOf(query); const index = resultKey.indexOf(query);
if (index !== -1) { if (index !== -1) {
matches.push( matches.push(
...candidates.map((candidate) => ({index, ...candidate})), ...candidates.map((candidate) => ({ index, ...candidate })),
); );
} }
} }

View file

@ -73,7 +73,7 @@ export default class RoomProvider extends AutocompleteProvider {
limit = -1, limit = -1,
): Promise<ICompletion[]> { ): Promise<ICompletion[]> {
let completions = []; let completions = [];
const {command, range} = this.getCurrentCommand(query, selection, force); const { command, range } = this.getCurrentCommand(query, selection, force);
if (command) { if (command) {
// the only reason we need to do this is because Fuse only matches on properties // the only reason we need to do this is because Fuse only matches on properties
let matcherObjects = this.getRooms().reduce((aliases, room) => { let matcherObjects = this.getRooms().reduce((aliases, room) => {

View file

@ -17,7 +17,7 @@ limitations under the License.
import React from "react"; import React from "react";
import { _t } from '../languageHandler'; import { _t } from '../languageHandler';
import {MatrixClientPeg} from '../MatrixClientPeg'; import { MatrixClientPeg } from '../MatrixClientPeg';
import RoomProvider from "./RoomProvider"; import RoomProvider from "./RoomProvider";
export default class SpaceProvider extends RoomProvider { export default class SpaceProvider extends RoomProvider {

View file

@ -114,7 +114,7 @@ export default class UserProvider extends AutocompleteProvider {
if (!this.users) this._makeUsers(); if (!this.users) this._makeUsers();
let completions = []; let completions = [];
const {command, range} = this.getCurrentCommand(rawQuery, selection, force); const { command, range } = this.getCurrentCommand(rawQuery, selection, force);
if (!command) return completions; if (!command) return completions;
@ -158,7 +158,7 @@ export default class UserProvider extends AutocompleteProvider {
} }
const currentUserId = MatrixClientPeg.get().credentials.userId; const currentUserId = MatrixClientPeg.get().credentials.userId;
this.users = this.room.getJoinedMembers().filter(({userId}) => userId !== currentUserId); this.users = this.room.getJoinedMembers().filter(({ userId }) => userId !== currentUserId);
this.users = this.users.concat(this.room.getMembersWithMembership("invite")); this.users = this.users.concat(this.room.getMembersWithMembership("invite"));
this.users = sortBy(this.users, (member) => 1E20 - lastSpoken[member.userId] || 1E20); this.users = sortBy(this.users, (member) => 1E20 - lastSpoken[member.userId] || 1E20);

View file

@ -16,13 +16,13 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React, {CSSProperties, RefObject, useRef, useState} from "react"; import React, { CSSProperties, RefObject, useRef, useState } from "react";
import ReactDOM from "react-dom"; import ReactDOM from "react-dom";
import classNames from "classnames"; import classNames from "classnames";
import {Key} from "../../Keyboard"; import { Key } from "../../Keyboard";
import {Writeable} from "../../@types/common"; import { Writeable } from "../../@types/common";
import {replaceableComponent} from "../../utils/replaceableComponent"; import { replaceableComponent } from "../../utils/replaceableComponent";
import UIStore from "../../stores/UIStore"; import UIStore from "../../stores/UIStore";
// Shamelessly ripped off Modal.js. There's probably a better way // Shamelessly ripped off Modal.js. There's probably a better way
@ -371,7 +371,7 @@ export class ContextMenu extends React.PureComponent<IProps, IState> {
return ( return (
<div <div
className={classNames("mx_ContextualMenu_wrapper", this.props.wrapperClassName)} className={classNames("mx_ContextualMenu_wrapper", this.props.wrapperClassName)}
style={{...position, ...wrapperStyle}} style={{ ...position, ...wrapperStyle }}
onKeyDown={this.onKeyDown} onKeyDown={this.onKeyDown}
onContextMenu={this.onContextMenuPreventBubbling} onContextMenu={this.onContextMenuPreventBubbling}
> >
@ -399,7 +399,7 @@ export const toRightOf = (elementRect: Pick<DOMRect, "right" | "top" | "height">
const left = elementRect.right + window.pageXOffset + 3; const left = elementRect.right + window.pageXOffset + 3;
let top = elementRect.top + (elementRect.height / 2) + window.pageYOffset; let top = elementRect.top + (elementRect.height / 2) + window.pageYOffset;
top -= chevronOffset + 8; // where 8 is half the height of the chevron top -= chevronOffset + 8; // where 8 is half the height of the chevron
return {left, top, chevronOffset}; return { left, top, chevronOffset };
}; };
// Placement method for <ContextMenu /> to position context menu right-aligned and flowing to the left of elementRect, // Placement method for <ContextMenu /> to position context menu right-aligned and flowing to the left of elementRect,
@ -498,15 +498,15 @@ export function createMenu(ElementClass, props) {
ReactDOM.render(menu, getOrCreateContainer()); ReactDOM.render(menu, getOrCreateContainer());
return {close: onFinished}; return { close: onFinished };
} }
// re-export the semantic helper components for simplicity // re-export the semantic helper components for simplicity
export {ContextMenuButton} from "../../accessibility/context_menu/ContextMenuButton"; export { ContextMenuButton } from "../../accessibility/context_menu/ContextMenuButton";
export {ContextMenuTooltipButton} from "../../accessibility/context_menu/ContextMenuTooltipButton"; export { ContextMenuTooltipButton } from "../../accessibility/context_menu/ContextMenuTooltipButton";
export {MenuGroup} from "../../accessibility/context_menu/MenuGroup"; export { MenuGroup } from "../../accessibility/context_menu/MenuGroup";
export {MenuItem} from "../../accessibility/context_menu/MenuItem"; export { MenuItem } from "../../accessibility/context_menu/MenuItem";
export {MenuItemCheckbox} from "../../accessibility/context_menu/MenuItemCheckbox"; export { MenuItemCheckbox } from "../../accessibility/context_menu/MenuItemCheckbox";
export {MenuItemRadio} from "../../accessibility/context_menu/MenuItemRadio"; export { MenuItemRadio } from "../../accessibility/context_menu/MenuItemRadio";
export {StyledMenuItemCheckbox} from "../../accessibility/context_menu/StyledMenuItemCheckbox"; export { StyledMenuItemCheckbox } from "../../accessibility/context_menu/StyledMenuItemCheckbox";
export {StyledMenuItemRadio} from "../../accessibility/context_menu/StyledMenuItemRadio"; export { StyledMenuItemRadio } from "../../accessibility/context_menu/StyledMenuItemRadio";

View file

@ -21,7 +21,7 @@ import * as sdk from '../../index';
import dis from '../../dispatcher/dispatcher'; import dis from '../../dispatcher/dispatcher';
import classNames from 'classnames'; import classNames from 'classnames';
import * as FormattingUtils from '../../utils/FormattingUtils'; import * as FormattingUtils from '../../utils/FormattingUtils';
import {replaceableComponent} from "../../utils/replaceableComponent"; import { replaceableComponent } from "../../utils/replaceableComponent";
@replaceableComponent("structures.CustomRoomTagPanel") @replaceableComponent("structures.CustomRoomTagPanel")
class CustomRoomTagPanel extends React.Component { class CustomRoomTagPanel extends React.Component {
@ -34,7 +34,7 @@ class CustomRoomTagPanel extends React.Component {
componentDidMount() { componentDidMount() {
this._tagStoreToken = CustomRoomTagStore.addListener(() => { this._tagStoreToken = CustomRoomTagStore.addListener(() => {
this.setState({tags: CustomRoomTagStore.getSortedTags()}); this.setState({ tags: CustomRoomTagStore.getSortedTags() });
}); });
} }
@ -64,7 +64,7 @@ class CustomRoomTagPanel extends React.Component {
class CustomRoomTagTile extends React.Component { class CustomRoomTagTile extends React.Component {
onClick = () => { onClick = () => {
dis.dispatch({action: 'select_custom_room_tag', tag: this.props.tag.name}); dis.dispatch({ action: 'select_custom_room_tag', tag: this.props.tag.name });
}; };
render() { render() {

View file

@ -22,7 +22,7 @@ import request from 'browser-request';
import { _t } from '../../languageHandler'; import { _t } from '../../languageHandler';
import sanitizeHtml from 'sanitize-html'; import sanitizeHtml from 'sanitize-html';
import dis from '../../dispatcher/dispatcher'; import dis from '../../dispatcher/dispatcher';
import {MatrixClientPeg} from '../../MatrixClientPeg'; import { MatrixClientPeg } from '../../MatrixClientPeg';
import classnames from 'classnames'; import classnames from 'classnames';
import MatrixClientContext from "../../contexts/MatrixClientContext"; import MatrixClientContext from "../../contexts/MatrixClientContext";
import AutoHideScrollbar from "./AutoHideScrollbar"; import AutoHideScrollbar from "./AutoHideScrollbar";

View file

@ -28,7 +28,7 @@ import { MatrixClientPeg } from '../../MatrixClientPeg';
import EventIndexPeg from "../../indexing/EventIndexPeg"; import EventIndexPeg from "../../indexing/EventIndexPeg";
import { _t } from '../../languageHandler'; import { _t } from '../../languageHandler';
import BaseCard from "../views/right_panel/BaseCard"; import BaseCard from "../views/right_panel/BaseCard";
import {RightPanelPhases} from "../../stores/RightPanelStorePhases"; import { RightPanelPhases } from "../../stores/RightPanelStorePhases";
import DesktopBuildsNotice, { WarningKind } from "../views/elements/DesktopBuildsNotice"; import DesktopBuildsNotice, { WarningKind } from "../views/elements/DesktopBuildsNotice";
import { replaceableComponent } from "../../utils/replaceableComponent"; import { replaceableComponent } from "../../utils/replaceableComponent";

View file

@ -16,7 +16,7 @@ limitations under the License.
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import {replaceableComponent} from "../../utils/replaceableComponent"; import { replaceableComponent } from "../../utils/replaceableComponent";
@replaceableComponent("structures.GenericErrorPage") @replaceableComponent("structures.GenericErrorPage")
export default class GenericErrorPage extends React.PureComponent { export default class GenericErrorPage extends React.PureComponent {

View file

@ -29,7 +29,7 @@ import MatrixClientContext from "../../contexts/MatrixClientContext";
import AutoHideScrollbar from "./AutoHideScrollbar"; import AutoHideScrollbar from "./AutoHideScrollbar";
import SettingsStore from "../../settings/SettingsStore"; import SettingsStore from "../../settings/SettingsStore";
import UserTagTile from "../views/elements/UserTagTile"; import UserTagTile from "../views/elements/UserTagTile";
import {replaceableComponent} from "../../utils/replaceableComponent"; import { replaceableComponent } from "../../utils/replaceableComponent";
@replaceableComponent("structures.GroupFilterPanel") @replaceableComponent("structures.GroupFilterPanel")
class GroupFilterPanel extends React.Component { class GroupFilterPanel extends React.Component {
@ -85,12 +85,12 @@ class GroupFilterPanel extends React.Component {
onClick = e => { onClick = e => {
// only dispatch if its not a no-op // only dispatch if its not a no-op
if (this.state.selectedTags.length > 0) { if (this.state.selectedTags.length > 0) {
dis.dispatch({action: 'deselect_tags'}); dis.dispatch({ action: 'deselect_tags' });
} }
}; };
onClearFilterClick = ev => { onClearFilterClick = ev => {
dis.dispatch({action: 'deselect_tags'}); dis.dispatch({ action: 'deselect_tags' });
}; };
renderGlobalIcon() { renderGlobalIcon() {

View file

@ -18,7 +18,7 @@ limitations under the License.
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import {MatrixClientPeg} from '../../MatrixClientPeg'; import { MatrixClientPeg } from '../../MatrixClientPeg';
import * as sdk from '../../index'; import * as sdk from '../../index';
import dis from '../../dispatcher/dispatcher'; import dis from '../../dispatcher/dispatcher';
import { getHostingLink } from '../../utils/HostingLink'; import { getHostingLink } from '../../utils/HostingLink';
@ -34,13 +34,13 @@ import classnames from 'classnames';
import GroupStore from '../../stores/GroupStore'; import GroupStore from '../../stores/GroupStore';
import FlairStore from '../../stores/FlairStore'; import FlairStore from '../../stores/FlairStore';
import { showGroupAddRoomDialog } from '../../GroupAddressPicker'; import { showGroupAddRoomDialog } from '../../GroupAddressPicker';
import {makeGroupPermalink, makeUserPermalink} from "../../utils/permalinks/Permalinks"; import { makeGroupPermalink, makeUserPermalink } from "../../utils/permalinks/Permalinks";
import {Group} from "matrix-js-sdk/src/models/group"; import { Group } from "matrix-js-sdk/src/models/group";
import {sleep} from "../../utils/promise"; import { sleep } from "../../utils/promise";
import RightPanelStore from "../../stores/RightPanelStore"; import RightPanelStore from "../../stores/RightPanelStore";
import AutoHideScrollbar from "./AutoHideScrollbar"; import AutoHideScrollbar from "./AutoHideScrollbar";
import {mediaFromMxc} from "../../customisations/Media"; import { mediaFromMxc } from "../../customisations/Media";
import {replaceableComponent} from "../../utils/replaceableComponent"; import { replaceableComponent } from "../../utils/replaceableComponent";
const LONG_DESC_PLACEHOLDER = _td( const LONG_DESC_PLACEHOLDER = _td(
`<h1>HTML for your community's page</h1> `<h1>HTML for your community's page</h1>
@ -115,7 +115,7 @@ class CategoryRoomList extends React.Component {
{ {
title: _t( title: _t(
"Failed to add the following rooms to the summary of %(groupId)s:", "Failed to add the following rooms to the summary of %(groupId)s:",
{groupId: this.props.groupId}, { groupId: this.props.groupId },
), ),
description: errorList.join(", "), description: errorList.join(", "),
}, },
@ -194,9 +194,9 @@ class FeaturedRoom extends React.Component {
{ {
title: _t( title: _t(
"Failed to remove the room from the summary of %(groupId)s", "Failed to remove the room from the summary of %(groupId)s",
{groupId: this.props.groupId}, { groupId: this.props.groupId },
), ),
description: _t("The room '%(roomName)s' could not be removed from the summary.", {roomName}), description: _t("The room '%(roomName)s' could not be removed from the summary.", { roomName }),
}, },
); );
}); });
@ -288,7 +288,7 @@ class RoleUserList extends React.Component {
{ {
title: _t( title: _t(
"Failed to add the following users to the summary of %(groupId)s:", "Failed to add the following users to the summary of %(groupId)s:",
{groupId: this.props.groupId}, { groupId: this.props.groupId },
), ),
description: errorList.join(", "), description: errorList.join(", "),
}, },
@ -359,9 +359,12 @@ class FeaturedUser extends React.Component {
{ {
title: _t( title: _t(
"Failed to remove a user from the summary of %(groupId)s", "Failed to remove a user from the summary of %(groupId)s",
{groupId: this.props.groupId}, { groupId: this.props.groupId },
),
description: _t(
"The user '%(displayName)s' could not be removed from the summary.",
{ displayName },
), ),
description: _t("The user '%(displayName)s' could not be removed from the summary.", {displayName}),
}, },
); );
}); });
@ -468,7 +471,7 @@ export default class GroupView extends React.Component {
// Leave settings - the user might have clicked the "Leave" button // Leave settings - the user might have clicked the "Leave" button
this._closeSettings(); this._closeSettings();
} }
this.setState({membershipBusy: false}); this.setState({ membershipBusy: false });
}; };
_initGroupStore(groupId, firstInit) { _initGroupStore(groupId, firstInit) {
@ -489,7 +492,7 @@ export default class GroupView extends React.Component {
group_id: groupId, group_id: groupId,
}, },
}); });
dis.dispatch({action: 'require_registration', screen_after: {screen: `group/${groupId}`}}); dis.dispatch({ action: 'require_registration', screen_after: { screen: `group/${groupId}` } });
willDoOnboarding = true; willDoOnboarding = true;
} }
if (stateKey === GroupStore.STATE_KEY.Summary) { if (stateKey === GroupStore.STATE_KEY.Summary) {
@ -590,7 +593,7 @@ export default class GroupView extends React.Component {
}; };
_closeSettings = () => { _closeSettings = () => {
dis.dispatch({action: 'close_settings'}); dis.dispatch({ action: 'close_settings' });
}; };
_onNameChange = (value) => { _onNameChange = (value) => {
@ -618,7 +621,7 @@ export default class GroupView extends React.Component {
const file = ev.target.files[0]; const file = ev.target.files[0];
if (!file) return; if (!file) return;
this.setState({uploadingAvatar: true}); this.setState({ uploadingAvatar: true });
this._matrixClient.uploadContent(file).then((url) => { this._matrixClient.uploadContent(file).then((url) => {
const newProfileForm = Object.assign(this.state.profileForm, { avatar_url: url }); const newProfileForm = Object.assign(this.state.profileForm, { avatar_url: url });
this.setState({ this.setState({
@ -630,7 +633,7 @@ export default class GroupView extends React.Component {
avatarChanged: true, avatarChanged: true,
}); });
}).catch((e) => { }).catch((e) => {
this.setState({uploadingAvatar: false}); this.setState({ uploadingAvatar: false });
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Failed to upload avatar image", e); console.error("Failed to upload avatar image", e);
Modal.createTrackedDialog('Failed to upload image', '', ErrorDialog, { Modal.createTrackedDialog('Failed to upload image', '', ErrorDialog, {
@ -647,7 +650,7 @@ export default class GroupView extends React.Component {
}; };
_onSaveClick = () => { _onSaveClick = () => {
this.setState({saving: true}); this.setState({ saving: true });
const savePromise = this.state.isUserPrivileged ? this._saveGroup() : Promise.resolve(); const savePromise = this.state.isUserPrivileged ? this._saveGroup() : Promise.resolve();
savePromise.then((result) => { savePromise.then((result) => {
this.setState({ this.setState({
@ -686,7 +689,7 @@ export default class GroupView extends React.Component {
} }
_onAcceptInviteClick = async () => { _onAcceptInviteClick = async () => {
this.setState({membershipBusy: true}); this.setState({ membershipBusy: true });
// Wait 500ms to prevent flashing. Do this before sending a request otherwise we risk the // Wait 500ms to prevent flashing. Do this before sending a request otherwise we risk the
// spinner disappearing after we have fetched new group data. // spinner disappearing after we have fetched new group data.
@ -695,7 +698,7 @@ export default class GroupView extends React.Component {
GroupStore.acceptGroupInvite(this.props.groupId).then(() => { GroupStore.acceptGroupInvite(this.props.groupId).then(() => {
// don't reset membershipBusy here: wait for the membership change to come down the sync // don't reset membershipBusy here: wait for the membership change to come down the sync
}).catch((e) => { }).catch((e) => {
this.setState({membershipBusy: false}); this.setState({ membershipBusy: false });
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Error accepting invite', '', ErrorDialog, { Modal.createTrackedDialog('Error accepting invite', '', ErrorDialog, {
title: _t("Error"), title: _t("Error"),
@ -705,7 +708,7 @@ export default class GroupView extends React.Component {
}; };
_onRejectInviteClick = async () => { _onRejectInviteClick = async () => {
this.setState({membershipBusy: true}); this.setState({ membershipBusy: true });
// Wait 500ms to prevent flashing. Do this before sending a request otherwise we risk the // Wait 500ms to prevent flashing. Do this before sending a request otherwise we risk the
// spinner disappearing after we have fetched new group data. // spinner disappearing after we have fetched new group data.
@ -714,7 +717,7 @@ export default class GroupView extends React.Component {
GroupStore.leaveGroup(this.props.groupId).then(() => { GroupStore.leaveGroup(this.props.groupId).then(() => {
// don't reset membershipBusy here: wait for the membership change to come down the sync // don't reset membershipBusy here: wait for the membership change to come down the sync
}).catch((e) => { }).catch((e) => {
this.setState({membershipBusy: false}); this.setState({ membershipBusy: false });
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Error rejecting invite', '', ErrorDialog, { Modal.createTrackedDialog('Error rejecting invite', '', ErrorDialog, {
title: _t("Error"), title: _t("Error"),
@ -725,11 +728,11 @@ export default class GroupView extends React.Component {
_onJoinClick = async () => { _onJoinClick = async () => {
if (this._matrixClient.isGuest()) { if (this._matrixClient.isGuest()) {
dis.dispatch({action: 'require_registration', screen_after: {screen: `group/${this.props.groupId}`}}); dis.dispatch({ action: 'require_registration', screen_after: { screen: `group/${this.props.groupId}` } });
return; return;
} }
this.setState({membershipBusy: true}); this.setState({ membershipBusy: true });
// Wait 500ms to prevent flashing. Do this before sending a request otherwise we risk the // Wait 500ms to prevent flashing. Do this before sending a request otherwise we risk the
// spinner disappearing after we have fetched new group data. // spinner disappearing after we have fetched new group data.
@ -738,7 +741,7 @@ export default class GroupView extends React.Component {
GroupStore.joinGroup(this.props.groupId).then(() => { GroupStore.joinGroup(this.props.groupId).then(() => {
// don't reset membershipBusy here: wait for the membership change to come down the sync // don't reset membershipBusy here: wait for the membership change to come down the sync
}).catch((e) => { }).catch((e) => {
this.setState({membershipBusy: false}); this.setState({ membershipBusy: false });
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Error joining room', '', ErrorDialog, { Modal.createTrackedDialog('Error joining room', '', ErrorDialog, {
title: _t("Error"), title: _t("Error"),
@ -771,7 +774,7 @@ export default class GroupView extends React.Component {
title: _t("Leave Community"), title: _t("Leave Community"),
description: ( description: (
<span> <span>
{ _t("Leave %(groupName)s?", {groupName: this.props.groupId}) } { _t("Leave %(groupName)s?", { groupName: this.props.groupId }) }
{ warnings } { warnings }
</span> </span>
), ),
@ -780,7 +783,7 @@ export default class GroupView extends React.Component {
onFinished: async (confirmed) => { onFinished: async (confirmed) => {
if (!confirmed) return; if (!confirmed) return;
this.setState({membershipBusy: true}); this.setState({ membershipBusy: true });
// Wait 500ms to prevent flashing. Do this before sending a request otherwise we risk the // Wait 500ms to prevent flashing. Do this before sending a request otherwise we risk the
// spinner disappearing after we have fetched new group data. // spinner disappearing after we have fetched new group data.
@ -789,7 +792,7 @@ export default class GroupView extends React.Component {
GroupStore.leaveGroup(this.props.groupId).then(() => { GroupStore.leaveGroup(this.props.groupId).then(() => {
// don't reset membershipBusy here: wait for the membership change to come down the sync // don't reset membershipBusy here: wait for the membership change to come down the sync
}).catch((e) => { }).catch((e) => {
this.setState({membershipBusy: false}); this.setState({ membershipBusy: false });
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Error leaving community', '', ErrorDialog, { Modal.createTrackedDialog('Error leaving community', '', ErrorDialog, {
title: _t("Error"), title: _t("Error"),
@ -1333,7 +1336,7 @@ export default class GroupView extends React.Component {
if (this.state.error.httpStatus === 404) { if (this.state.error.httpStatus === 404) {
return ( return (
<div className="mx_GroupView_error"> <div className="mx_GroupView_error">
{ _t('Community %(groupId)s not found', {groupId: this.props.groupId}) } { _t('Community %(groupId)s not found', { groupId: this.props.groupId }) }
</div> </div>
); );
} else { } else {
@ -1343,7 +1346,7 @@ export default class GroupView extends React.Component {
} }
return ( return (
<div className="mx_GroupView_error"> <div className="mx_GroupView_error">
{ _t('Failed to load %(groupId)s', {groupId: this.props.groupId }) } { _t('Failed to load %(groupId)s', { groupId: this.props.groupId }) }
{ extraText } { extraText }
</div> </div>
); );

View file

@ -15,29 +15,29 @@ limitations under the License.
*/ */
import * as React from "react"; import * as React from "react";
import {useContext, useState} from "react"; import { useContext, useState } from "react";
import AutoHideScrollbar from './AutoHideScrollbar'; import AutoHideScrollbar from './AutoHideScrollbar';
import {getHomePageUrl} from "../../utils/pages"; import { getHomePageUrl } from "../../utils/pages";
import {_t} from "../../languageHandler"; import { _t } from "../../languageHandler";
import SdkConfig from "../../SdkConfig"; import SdkConfig from "../../SdkConfig";
import * as sdk from "../../index"; import * as sdk from "../../index";
import dis from "../../dispatcher/dispatcher"; import dis from "../../dispatcher/dispatcher";
import {Action} from "../../dispatcher/actions"; import { Action } from "../../dispatcher/actions";
import BaseAvatar from "../views/avatars/BaseAvatar"; import BaseAvatar from "../views/avatars/BaseAvatar";
import {OwnProfileStore} from "../../stores/OwnProfileStore"; import { OwnProfileStore } from "../../stores/OwnProfileStore";
import AccessibleButton from "../views/elements/AccessibleButton"; import AccessibleButton from "../views/elements/AccessibleButton";
import {UPDATE_EVENT} from "../../stores/AsyncStore"; import { UPDATE_EVENT } from "../../stores/AsyncStore";
import {useEventEmitter} from "../../hooks/useEventEmitter"; import { useEventEmitter } from "../../hooks/useEventEmitter";
import MatrixClientContext from "../../contexts/MatrixClientContext"; import MatrixClientContext from "../../contexts/MatrixClientContext";
import MiniAvatarUploader, {AVATAR_SIZE} from "../views/elements/MiniAvatarUploader"; import MiniAvatarUploader, { AVATAR_SIZE } from "../views/elements/MiniAvatarUploader";
import Analytics from "../../Analytics"; import Analytics from "../../Analytics";
import CountlyAnalytics from "../../CountlyAnalytics"; import CountlyAnalytics from "../../CountlyAnalytics";
const onClickSendDm = () => { const onClickSendDm = () => {
Analytics.trackEvent('home_page', 'button', 'dm'); Analytics.trackEvent('home_page', 'button', 'dm');
CountlyAnalytics.instance.track("home_page_button", { button: "dm" }); CountlyAnalytics.instance.track("home_page_button", { button: "dm" });
dis.dispatch({action: 'view_create_chat'}); dis.dispatch({ action: 'view_create_chat' });
}; };
const onClickExplore = () => { const onClickExplore = () => {
@ -49,7 +49,7 @@ const onClickExplore = () => {
const onClickNewRoom = () => { const onClickNewRoom = () => {
Analytics.trackEvent('home_page', 'button', 'create_room'); Analytics.trackEvent('home_page', 'button', 'create_room');
CountlyAnalytics.instance.track("home_page_button", { button: "create_room" }); CountlyAnalytics.instance.track("home_page_button", { button: "create_room" });
dis.dispatch({action: 'view_create_room'}); dis.dispatch({ action: 'view_create_room' });
}; };
interface IProps { interface IProps {
@ -117,7 +117,6 @@ const HomePage: React.FC<IProps> = ({ justRegistered = false }) => {
</React.Fragment>; </React.Fragment>;
} }
return <AutoHideScrollbar className="mx_HomePage mx_HomePage_default"> return <AutoHideScrollbar className="mx_HomePage mx_HomePage_default">
<div className="mx_HomePage_default_wrapper"> <div className="mx_HomePage_default_wrapper">
{ introSection } { introSection }

View file

@ -22,7 +22,7 @@ import {
import { _t } from "../../languageHandler"; import { _t } from "../../languageHandler";
import { HostSignupStore } from "../../stores/HostSignupStore"; import { HostSignupStore } from "../../stores/HostSignupStore";
import SdkConfig from "../../SdkConfig"; import SdkConfig from "../../SdkConfig";
import {replaceableComponent} from "../../utils/replaceableComponent"; import { replaceableComponent } from "../../utils/replaceableComponent";
interface IProps { interface IProps {
onClick?(): void; onClick?(): void;
@ -35,7 +35,7 @@ export default class HostSignupAction extends React.PureComponent<IProps, IState
private openDialog = async () => { private openDialog = async () => {
this.props.onClick?.(); this.props.onClick?.();
await HostSignupStore.instance.setHostSignupActive(true); await HostSignupStore.instance.setHostSignupActive(true);
} };
public render(): React.ReactNode { public render(): React.ReactNode {
const hostSignupConfig = SdkConfig.get().hostSignup; const hostSignupConfig = SdkConfig.get().hostSignup;

View file

@ -17,7 +17,7 @@ limitations under the License.
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import AutoHideScrollbar from "./AutoHideScrollbar"; import AutoHideScrollbar from "./AutoHideScrollbar";
import {replaceableComponent} from "../../utils/replaceableComponent"; import { replaceableComponent } from "../../utils/replaceableComponent";
@replaceableComponent("structures.IndicatorScrollbar") @replaceableComponent("structures.IndicatorScrollbar")
export default class IndicatorScrollbar extends React.Component { export default class IndicatorScrollbar extends React.Component {
@ -70,7 +70,6 @@ export default class IndicatorScrollbar extends React.Component {
this._autoHideScrollbar = autoHideScrollbar; this._autoHideScrollbar = autoHideScrollbar;
} }
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
const prevLen = prevProps && prevProps.children && prevProps.children.length || 0; const prevLen = prevProps && prevProps.children && prevProps.children.length || 0;
const curLen = this.props.children && this.props.children.length || 0; const curLen = this.props.children && this.props.children.length || 0;
@ -188,8 +187,8 @@ export default class IndicatorScrollbar extends React.Component {
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
const { children, trackHorizontalOverflow, verticalScrollsHorizontally, ...otherProps } = this.props; const { children, trackHorizontalOverflow, verticalScrollsHorizontally, ...otherProps } = this.props;
const leftIndicatorStyle = {left: this.state.leftIndicatorOffset}; const leftIndicatorStyle = { left: this.state.leftIndicatorOffset };
const rightIndicatorStyle = {right: this.state.rightIndicatorOffset}; const rightIndicatorStyle = { right: this.state.rightIndicatorOffset };
const leftOverflowIndicator = trackHorizontalOverflow const leftOverflowIndicator = trackHorizontalOverflow
? <div className="mx_IndicatorScrollbar_leftOverflowIndicator" style={leftIndicatorStyle} /> : null; ? <div className="mx_IndicatorScrollbar_leftOverflowIndicator" style={leftIndicatorStyle} /> : null;
const rightOverflowIndicator = trackHorizontalOverflow const rightOverflowIndicator = trackHorizontalOverflow

View file

@ -15,14 +15,14 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {InteractiveAuth} from "matrix-js-sdk/src/interactive-auth"; import { InteractiveAuth } from "matrix-js-sdk/src/interactive-auth";
import React, {createRef} from 'react'; import React, { createRef } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import getEntryComponentForLoginType from '../views/auth/InteractiveAuthEntryComponents'; import getEntryComponentForLoginType from '../views/auth/InteractiveAuthEntryComponents';
import * as sdk from '../../index'; import * as sdk from '../../index';
import {replaceableComponent} from "../../utils/replaceableComponent"; import { replaceableComponent } from "../../utils/replaceableComponent";
export const ERROR_USER_CANCELLED = new Error("User cancelled auth session"); export const ERROR_USER_CANCELLED = new Error("User cancelled auth session");

View file

@ -40,9 +40,9 @@ import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton";
import { OwnProfileStore } from "../../stores/OwnProfileStore"; import { OwnProfileStore } from "../../stores/OwnProfileStore";
import RoomListNumResults from "../views/rooms/RoomListNumResults"; import RoomListNumResults from "../views/rooms/RoomListNumResults";
import LeftPanelWidget from "./LeftPanelWidget"; import LeftPanelWidget from "./LeftPanelWidget";
import {replaceableComponent} from "../../utils/replaceableComponent"; import { replaceableComponent } from "../../utils/replaceableComponent";
import {mediaFromMxc} from "../../customisations/Media"; import { mediaFromMxc } from "../../customisations/Media";
import SpaceStore, {UPDATE_SELECTED_SPACE} from "../../stores/SpaceStore"; import SpaceStore, { UPDATE_SELECTED_SPACE } from "../../stores/SpaceStore";
import { getKeyBindingsManager, RoomListAction } from "../../KeyBindingsManager"; import { getKeyBindingsManager, RoomListAction } from "../../KeyBindingsManager";
import UIStore from "../../stores/UIStore"; import UIStore from "../../stores/UIStore";
@ -91,7 +91,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
this.bgImageWatcherRef = SettingsStore.watchSetting( this.bgImageWatcherRef = SettingsStore.watchSetting(
"RoomList.backgroundImage", null, this.onBackgroundImageUpdate); "RoomList.backgroundImage", null, this.onBackgroundImageUpdate);
this.groupFilterPanelWatcherRef = SettingsStore.watchSetting("TagPanel.enableTagPanel", null, () => { this.groupFilterPanelWatcherRef = SettingsStore.watchSetting("TagPanel.enableTagPanel", null, () => {
this.setState({showGroupFilterPanel: SettingsStore.getValue("TagPanel.enableTagPanel")}); this.setState({ showGroupFilterPanel: SettingsStore.getValue("TagPanel.enableTagPanel") });
}); });
} }
@ -127,7 +127,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
private onDialPad = () => { private onDialPad = () => {
dis.fire(Action.OpenDialPad); dis.fire(Action.OpenDialPad);
} };
private onExplore = () => { private onExplore = () => {
dis.fire(Action.ViewRoomDirectory); dis.fire(Action.ViewRoomDirectory);
@ -136,12 +136,12 @@ export default class LeftPanel extends React.Component<IProps, IState> {
private refreshStickyHeaders = () => { private refreshStickyHeaders = () => {
if (!this.listContainerRef.current) return; // ignore: no headers to sticky if (!this.listContainerRef.current) return; // ignore: no headers to sticky
this.handleStickyHeaders(this.listContainerRef.current); this.handleStickyHeaders(this.listContainerRef.current);
} };
private onBreadcrumbsUpdate = () => { private onBreadcrumbsUpdate = () => {
const newVal = BreadcrumbsStore.instance.visible; const newVal = BreadcrumbsStore.instance.visible;
if (newVal !== this.state.showBreadcrumbs) { if (newVal !== this.state.showBreadcrumbs) {
this.setState({showBreadcrumbs: newVal}); this.setState({ showBreadcrumbs: newVal });
// Update the sticky headers too as the breadcrumbs will be popping in or out. // Update the sticky headers too as the breadcrumbs will be popping in or out.
if (!this.listContainerRef.current) return; // ignore: no headers to sticky if (!this.listContainerRef.current) return; // ignore: no headers to sticky

View file

@ -14,19 +14,19 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React, {useContext, useMemo} from "react"; import React, { useContext, useMemo } from "react";
import {Resizable} from "re-resizable"; import { Resizable } from "re-resizable";
import classNames from "classnames"; import classNames from "classnames";
import AccessibleButton from "../views/elements/AccessibleButton"; import AccessibleButton from "../views/elements/AccessibleButton";
import {useRovingTabIndex} from "../../accessibility/RovingTabIndex"; import { useRovingTabIndex } from "../../accessibility/RovingTabIndex";
import {Key} from "../../Keyboard"; import { Key } from "../../Keyboard";
import {useLocalStorageState} from "../../hooks/useLocalStorageState"; import { useLocalStorageState } from "../../hooks/useLocalStorageState";
import MatrixClientContext from "../../contexts/MatrixClientContext"; import MatrixClientContext from "../../contexts/MatrixClientContext";
import WidgetUtils, {IWidgetEvent} from "../../utils/WidgetUtils"; import WidgetUtils, { IWidgetEvent } from "../../utils/WidgetUtils";
import {useAccountData} from "../../hooks/useAccountData"; import { useAccountData } from "../../hooks/useAccountData";
import AppTile from "../views/elements/AppTile"; import AppTile from "../views/elements/AppTile";
import {useSettingValue} from "../../hooks/useSettings"; import { useSettingValue } from "../../hooks/useSettings";
import UIStore from "../../stores/UIStore"; import UIStore from "../../stores/UIStore";
const MIN_HEIGHT = 100; const MIN_HEIGHT = 100;
@ -62,14 +62,14 @@ const LeftPanelWidget: React.FC = () => {
let content; let content;
if (expanded) { if (expanded) {
content = <Resizable content = <Resizable
size={{height} as any} size={{ height } as any}
minHeight={MIN_HEIGHT} minHeight={MIN_HEIGHT}
maxHeight={Math.min(UIStore.instance.windowHeight / 2, MAX_HEIGHT)} maxHeight={Math.min(UIStore.instance.windowHeight / 2, MAX_HEIGHT)}
onResizeStop={(e, dir, ref, d) => { onResizeStop={(e, dir, ref, d) => {
setHeight(height + d.height); setHeight(height + d.height);
}} }}
handleWrapperClass="mx_LeftPanelWidget_resizerHandles" handleWrapperClass="mx_LeftPanelWidget_resizerHandles"
handleClasses={{top: "mx_LeftPanelWidget_resizerHandle"}} handleClasses={{ top: "mx_LeftPanelWidget_resizerHandle" }}
className="mx_LeftPanelWidget_resizeBox" className="mx_LeftPanelWidget_resizeBox"
enable={{ top: true }} enable={{ top: true }}
> >

View file

@ -20,7 +20,7 @@ import * as React from 'react';
import * as PropTypes from 'prop-types'; import * as PropTypes from 'prop-types';
import { MatrixClient } from 'matrix-js-sdk/src/client'; import { MatrixClient } from 'matrix-js-sdk/src/client';
import {Key} from '../../Keyboard'; 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';
@ -30,7 +30,7 @@ import { IMatrixClientCreds } from '../../MatrixClientPeg';
import SettingsStore from "../../settings/SettingsStore"; import SettingsStore from "../../settings/SettingsStore";
import ResizeHandle from '../views/elements/ResizeHandle'; import ResizeHandle from '../views/elements/ResizeHandle';
import {Resizer, CollapseDistributor} from '../../resizer'; import { Resizer, CollapseDistributor } from '../../resizer';
import MatrixClientContext from "../../contexts/MatrixClientContext"; import MatrixClientContext from "../../contexts/MatrixClientContext";
import * as KeyboardShortcuts from "../../accessibility/KeyboardShortcuts"; import * as KeyboardShortcuts from "../../accessibility/KeyboardShortcuts";
import HomePage from "./HomePage"; import HomePage from "./HomePage";
@ -55,7 +55,7 @@ import HostSignupContainer from '../views/host_signup/HostSignupContainer';
import { getKeyBindingsManager, NavigationAction, RoomAction } from '../../KeyBindingsManager'; import { getKeyBindingsManager, NavigationAction, RoomAction } from '../../KeyBindingsManager';
import { IOpts } from "../../createRoom"; import { IOpts } from "../../createRoom";
import SpacePanel from "../views/spaces/SpacePanel"; import SpacePanel from "../views/spaces/SpacePanel";
import {replaceableComponent} from "../../utils/replaceableComponent"; 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';
@ -232,10 +232,10 @@ class LoggedInView extends React.Component<IProps, IState> {
onCollapsed: (_collapsed) => { onCollapsed: (_collapsed) => {
collapsed = _collapsed; collapsed = _collapsed;
if (_collapsed) { if (_collapsed) {
dis.dispatch({action: "hide_left_panel"}); dis.dispatch({ action: "hide_left_panel" });
window.localStorage.setItem("mx_lhs_size", '0'); window.localStorage.setItem("mx_lhs_size", '0');
} else { } else {
dis.dispatch({action: "show_left_panel"}); dis.dispatch({ action: "show_left_panel" });
} }
}, },
onResized: (_size) => { onResized: (_size) => {
@ -272,7 +272,7 @@ class LoggedInView extends React.Component<IProps, IState> {
onAccountData = (event) => { onAccountData = (event) => {
if (event.getType() === "m.ignored_user_list") { if (event.getType() === "m.ignored_user_list") {
dis.dispatch({action: "ignore_state_changed"}); dis.dispatch({ action: "ignore_state_changed" });
} }
}; };
@ -319,7 +319,7 @@ class LoggedInView extends React.Component<IProps, IState> {
this.setState({ this.setState({
usageLimitDismissed: true, usageLimitDismissed: true,
}); });
} };
_calculateServerLimitToast(syncError: IState["syncErrorData"], usageLimitEventContent?: IUsageLimit) { _calculateServerLimitToast(syncError: IState["syncErrorData"], usageLimitEventContent?: IUsageLimit) {
const error = syncError && syncError.error && syncError.error.errcode === "M_RESOURCE_LIMIT_EXCEEDED"; const error = syncError && syncError.error && syncError.error.errcode === "M_RESOURCE_LIMIT_EXCEEDED";

View file

@ -17,7 +17,7 @@ limitations under the License.
import React from 'react'; import React from 'react';
import { Resizable } from 're-resizable'; import { Resizable } from 're-resizable';
import {replaceableComponent} from "../../utils/replaceableComponent"; import { replaceableComponent } from "../../utils/replaceableComponent";
@replaceableComponent("structures.MainSplit") @replaceableComponent("structures.MainSplit")
export default class MainSplit extends React.Component { export default class MainSplit extends React.Component {
@ -73,7 +73,7 @@ export default class MainSplit extends React.Component {
onResize={this._onResize} onResize={this._onResize}
onResizeStop={this._onResizeStop} onResizeStop={this._onResizeStop}
className="mx_RightPanel_ResizeWrapper" className="mx_RightPanel_ResizeWrapper"
handleClasses={{left: "mx_RightPanel_ResizeHandle"}} handleClasses={{ left: "mx_RightPanel_ResizeHandle" }}
> >
{ panelView } { panelView }
</Resizable>; </Resizable>;

View file

@ -43,8 +43,8 @@ import * as Lifecycle from '../../Lifecycle';
import '../../stores/LifecycleStore'; import '../../stores/LifecycleStore';
import PageTypes from '../../PageTypes'; import PageTypes from '../../PageTypes';
import createRoom, {IOpts} from "../../createRoom"; import createRoom, { IOpts } from "../../createRoom";
import {_t, _td, getCurrentLanguage} from '../../languageHandler'; import { _t, _td, getCurrentLanguage } from '../../languageHandler';
import SettingsStore from "../../settings/SettingsStore"; import SettingsStore from "../../settings/SettingsStore";
import ThemeController from "../../settings/controllers/ThemeController"; import ThemeController from "../../settings/controllers/ThemeController";
import { startAnyRegistrationFlow } from "../../Registration"; import { startAnyRegistrationFlow } from "../../Registration";
@ -65,7 +65,7 @@ import {
showToast as showAnalyticsToast, showToast as showAnalyticsToast,
hideToast as hideAnalyticsToast, hideToast as hideAnalyticsToast,
} from "../../toasts/AnalyticsToast"; } from "../../toasts/AnalyticsToast";
import {showToast as showNotificationsToast} from "../../toasts/DesktopNotificationsToast"; import { showToast as showNotificationsToast } from "../../toasts/DesktopNotificationsToast";
import { OpenToTabPayload } from "../../dispatcher/payloads/OpenToTabPayload"; import { OpenToTabPayload } from "../../dispatcher/payloads/OpenToTabPayload";
import ErrorDialog from "../views/dialogs/ErrorDialog"; import ErrorDialog from "../views/dialogs/ErrorDialog";
import { RoomNotificationStateStore } from "../../stores/notifications/RoomNotificationStateStore"; import { RoomNotificationStateStore } from "../../stores/notifications/RoomNotificationStateStore";
@ -73,15 +73,15 @@ import { SettingLevel } from "../../settings/SettingLevel";
import { leaveRoomBehaviour } from "../../utils/membership"; import { leaveRoomBehaviour } from "../../utils/membership";
import CreateCommunityPrototypeDialog from "../views/dialogs/CreateCommunityPrototypeDialog"; import CreateCommunityPrototypeDialog from "../views/dialogs/CreateCommunityPrototypeDialog";
import ThreepidInviteStore, { IThreepidInvite, IThreepidInviteWireFormat } from "../../stores/ThreepidInviteStore"; import ThreepidInviteStore, { IThreepidInvite, IThreepidInviteWireFormat } from "../../stores/ThreepidInviteStore";
import {UIFeature} from "../../settings/UIFeature"; import { UIFeature } from "../../settings/UIFeature";
import { CommunityPrototypeStore } from "../../stores/CommunityPrototypeStore"; import { CommunityPrototypeStore } from "../../stores/CommunityPrototypeStore";
import DialPadModal from "../views/voip/DialPadModal"; import DialPadModal from "../views/voip/DialPadModal";
import { showToast as showMobileGuideToast } from '../../toasts/MobileGuideToast'; import { showToast as showMobileGuideToast } from '../../toasts/MobileGuideToast';
import { shouldUseLoginForWelcome } from "../../utils/pages"; import { shouldUseLoginForWelcome } from "../../utils/pages";
import SpaceStore from "../../stores/SpaceStore"; import SpaceStore from "../../stores/SpaceStore";
import {replaceableComponent} from "../../utils/replaceableComponent"; import { replaceableComponent } from "../../utils/replaceableComponent";
import RoomListStore from "../../stores/room-list/RoomListStore"; 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";
@ -395,7 +395,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
if (SecurityCustomisations.SHOW_ENCRYPTION_SETUP_UI === false) { if (SecurityCustomisations.SHOW_ENCRYPTION_SETUP_UI === false) {
this.onLoggedIn(); this.onLoggedIn();
} else { } else {
this.setStateForNewView({view: Views.COMPLETE_SECURITY}); this.setStateForNewView({ view: Views.COMPLETE_SECURITY });
} }
} else if (await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")) { } else if (await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")) {
this.setStateForNewView({ view: Views.E2E_SETUP }); this.setStateForNewView({ view: Views.E2E_SETUP });
@ -448,7 +448,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
let props = this.state.serverConfig; let props = this.state.serverConfig;
if (!props) props = this.props.serverConfig; // for unit tests if (!props) props = this.props.serverConfig; // for unit tests
if (!props) props = SdkConfig.get()["validated_server_config"]; if (!props) props = SdkConfig.get()["validated_server_config"];
return {serverConfig: props}; return { serverConfig: props };
} }
private loadSession() { private loadSession() {
@ -466,9 +466,9 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
if (!loadedSession) { if (!loadedSession) {
// fall back to showing the welcome screen... unless we have a 3pid invite pending // fall back to showing the welcome screen... unless we have a 3pid invite pending
if (ThreepidInviteStore.instance.pickBestInvite()) { if (ThreepidInviteStore.instance.pickBestInvite()) {
dis.dispatch({action: 'start_registration'}); dis.dispatch({ action: 'start_registration' });
} else { } else {
dis.dispatch({action: "view_welcome_page"}); dis.dispatch({ action: "view_welcome_page" });
} }
} else if (SettingsStore.getValue("analyticsOptIn")) { } else if (SettingsStore.getValue("analyticsOptIn")) {
CountlyAnalytics.instance.enable(/* anonymous = */ false); CountlyAnalytics.instance.enable(/* anonymous = */ false);
@ -532,7 +532,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
action: 'do_after_sync_prepared', action: 'do_after_sync_prepared',
deferred_action: payload, deferred_action: payload,
}); });
dis.dispatch({action: 'require_registration'}); dis.dispatch({ action: 'require_registration' });
return; return;
} }
@ -557,11 +557,11 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
} }
// redispatch the change with a more specific action // redispatch the change with a more specific action
dis.dispatch({action: 'id_server_changed'}); dis.dispatch({ action: 'id_server_changed' });
} }
break; break;
case 'logout': case 'logout':
dis.dispatch({action: "hangup_all"}); dis.dispatch({ action: "hangup_all" });
Lifecycle.logout(); Lifecycle.logout();
break; break;
case 'require_registration': case 'require_registration':
@ -618,7 +618,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
MatrixClientPeg.get().leave(payload.room_id).then(() => { MatrixClientPeg.get().leave(payload.room_id).then(() => {
modal.close(); modal.close();
if (this.state.currentRoomId === payload.room_id) { if (this.state.currentRoomId === payload.room_id) {
dis.dispatch({action: 'view_home_page'}); dis.dispatch({ action: 'view_home_page' });
} }
}, (err) => { }, (err) => {
modal.close(); modal.close();
@ -651,7 +651,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
const tabPayload = payload as OpenToTabPayload; const tabPayload = payload as OpenToTabPayload;
const UserSettingsDialog = sdk.getComponent("dialogs.UserSettingsDialog"); 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);
// View the welcome or home page if we need something to look at // View the welcome or home page if we need something to look at
@ -662,7 +662,7 @@ 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") let CreateGroupDialog = sdk.getComponent("dialogs.CreateGroupDialog");
if (SettingsStore.getValue("feature_communities_v2_prototypes")) { if (SettingsStore.getValue("feature_communities_v2_prototypes")) {
CreateGroupDialog = CreateCommunityPrototypeDialog; CreateGroupDialog = CreateCommunityPrototypeDialog;
} }
@ -721,9 +721,9 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
// We just dispatch the page change rather than have to worry about // We just dispatch the page change rather than have to worry about
// what the logic is for each of these branches. // what the logic is for each of these branches.
if (this.state.page_type === PageTypes.MyGroups) { if (this.state.page_type === PageTypes.MyGroups) {
dis.dispatch({action: 'view_last_screen'}); dis.dispatch({ action: 'view_last_screen' });
} else { } else {
dis.dispatch({action: 'view_my_groups'}); dis.dispatch({ action: 'view_my_groups' });
} }
break; break;
case 'hide_left_panel': case 'hide_left_panel':
@ -764,7 +764,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
this.onLoggedOut(); this.onLoggedOut();
break; break;
case 'will_start_client': case 'will_start_client':
this.setState({ready: false}, () => { this.setState({ ready: false }, () => {
// if the client is about to start, we are, by definition, not ready. // if the client is about to start, we are, by definition, not ready.
// Set ready to false now, then it'll be set to true when the sync // Set ready to false now, then it'll be set to true when the sync
// listener we set below fires. // listener we set below fires.
@ -1000,7 +1000,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
return; return;
} }
this.notifyNewScreen('user/' + userId); this.notifyNewScreen('user/' + userId);
this.setState({currentUserId: userId}); this.setState({ currentUserId: userId });
this.setPage(PageTypes.UserView); this.setPage(PageTypes.UserView);
}); });
} }
@ -1125,8 +1125,14 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
description: ( description: (
<span> <span>
{ isSpace { isSpace
? _t("Are you sure you want to leave the space '%(spaceName)s'?", {spaceName: roomToLeave.name}) ? _t(
: _t("Are you sure you want to leave the room '%(roomName)s'?", {roomName: roomToLeave.name}) } "Are you sure you want to leave the space '%(spaceName)s'?",
{ spaceName: roomToLeave.name },
)
: _t(
"Are you sure you want to leave the room '%(roomName)s'?",
{ roomName: roomToLeave.name },
)}
{ warnings } { warnings }
</span> </span>
), ),
@ -1164,7 +1170,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
}).catch((err) => { }).catch((err) => {
const errCode = err.errcode || _td("unknown error code"); const errCode = err.errcode || _td("unknown error code");
Modal.createTrackedDialog("Failed to forget room", '', ErrorDialog, { Modal.createTrackedDialog("Failed to forget room", '', ErrorDialog, {
title: _t("Failed to forget room %(errCode)s", {errCode}), title: _t("Failed to forget room %(errCode)s", { errCode }),
description: ((err && err.message) ? err.message : _t("Operation failed")), description: ((err && err.message) ? err.message : _t("Operation failed")),
}); });
}); });
@ -1248,7 +1254,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
if (welcomeUserRoom === null) { if (welcomeUserRoom === null) {
// We didn't redirect to the welcome user room, so show // We didn't redirect to the welcome user room, so show
// the homepage. // the homepage.
dis.dispatch({action: 'view_home_page', justRegistered: true}); dis.dispatch({ action: 'view_home_page', justRegistered: true });
} }
} else if (ThreepidInviteStore.instance.pickBestInvite()) { } else if (ThreepidInviteStore.instance.pickBestInvite()) {
// The user has a 3pid invite pending - show them that // The user has a 3pid invite pending - show them that
@ -1257,11 +1263,11 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
// HACK: This is a pretty brutal way of threading the invite back through // HACK: This is a pretty brutal way of threading the invite back through
// our systems, but it's the safest we have for now. // our systems, but it's the safest we have for now.
const params = ThreepidInviteStore.instance.translateToWireFormat(threepidInvite); const params = ThreepidInviteStore.instance.translateToWireFormat(threepidInvite);
this.showScreen(`room/${threepidInvite.roomId}`, params) this.showScreen(`room/${threepidInvite.roomId}`, params);
} else { } else {
// The user has just logged in after registering, // The user has just logged in after registering,
// so show the homepage. // so show the homepage.
dis.dispatch({action: 'view_home_page', justRegistered: true}); dis.dispatch({ action: 'view_home_page', justRegistered: true });
} }
} else { } else {
this.showScreenAfterLogin(); this.showScreenAfterLogin();
@ -1297,9 +1303,9 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
this.viewLastRoom(); this.viewLastRoom();
} else { } else {
if (MatrixClientPeg.get().isGuest()) { if (MatrixClientPeg.get().isGuest()) {
dis.dispatch({action: 'view_welcome_page'}); dis.dispatch({ action: 'view_welcome_page' });
} else { } else {
dis.dispatch({action: 'view_home_page'}); dis.dispatch({ action: 'view_home_page' });
} }
} }
} }
@ -1379,15 +1385,15 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
// So dispatch directly from here. Ideally we'd use a SyncStateStore that // So dispatch directly from here. Ideally we'd use a SyncStateStore that
// would do this dispatch and expose the sync state itself (by listening to // would do this dispatch and expose the sync state itself (by listening to
// its own dispatch). // its own dispatch).
dis.dispatch({action: 'sync_state', prevState, state}); dis.dispatch({ action: 'sync_state', prevState, state });
if (state === "ERROR" || state === "RECONNECTING") { if (state === "ERROR" || state === "RECONNECTING") {
if (data.error instanceof InvalidStoreError) { if (data.error instanceof InvalidStoreError) {
Lifecycle.handleInvalidStoreError(data.error); Lifecycle.handleInvalidStoreError(data.error);
} }
this.setState({syncError: data.error || true}); this.setState({ syncError: data.error || true });
} else if (this.state.syncError) { } else if (this.state.syncError) {
this.setState({syncError: null}); this.setState({ syncError: null });
} }
this.updateStatusIndicator(state, prevState); this.updateStatusIndicator(state, prevState);
@ -1561,7 +1567,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
key: 'verifreq_' + request.channel.transactionId, key: 'verifreq_' + request.channel.transactionId,
title: _t("Verification requested"), title: _t("Verification requested"),
icon: "verification", icon: "verification",
props: {request}, props: { request },
component: sdk.getComponent("toasts.VerificationRequestToast"), component: sdk.getComponent("toasts.VerificationRequestToast"),
priority: 90, priority: 90,
}); });
@ -1658,7 +1664,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
// TODO if logged in, skip SSO // TODO if logged in, skip SSO
let cli = MatrixClientPeg.get(); let cli = MatrixClientPeg.get();
if (!cli) { if (!cli) {
const {hsUrl, isUrl} = this.props.serverConfig; const { hsUrl, isUrl } = this.props.serverConfig;
cli = createClient({ cli = createClient({
baseUrl: hsUrl, baseUrl: hsUrl,
idBaseUrl: isUrl, idBaseUrl: isUrl,
@ -1782,7 +1788,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
onAliasClick(event: MouseEvent, alias: string) { onAliasClick(event: MouseEvent, alias: string) {
event.preventDefault(); event.preventDefault();
dis.dispatch({action: 'view_room', room_alias: alias}); dis.dispatch({ action: 'view_room', room_alias: alias });
} }
onUserClick(event: MouseEvent, userId: string) { onUserClick(event: MouseEvent, userId: string) {
@ -1798,7 +1804,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
onGroupClick(event: MouseEvent, groupId: string) { onGroupClick(event: MouseEvent, groupId: string) {
event.preventDefault(); event.preventDefault();
dis.dispatch({action: 'view_group', group_id: groupId}); dis.dispatch({ action: 'view_group', group_id: groupId });
} }
onLogoutClick(event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) { onLogoutClick(event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) {
@ -1860,14 +1866,14 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
onSendEvent(roomId: string, event: MatrixEvent) { onSendEvent(roomId: string, event: MatrixEvent) {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
if (!cli) { if (!cli) {
dis.dispatch({action: 'message_send_failed'}); dis.dispatch({ action: 'message_send_failed' });
return; return;
} }
cli.sendEvent(roomId, event.getType(), event.getContent()).then(() => { cli.sendEvent(roomId, event.getType(), event.getContent()).then(() => {
dis.dispatch({action: 'message_sent'}); dis.dispatch({ action: 'message_sent' });
}, (err) => { }, (err) => {
dis.dispatch({action: 'message_send_failed'}); dis.dispatch({ action: 'message_send_failed' });
}); });
} }
@ -1914,7 +1920,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
} }
onServerConfigChange = (serverConfig: ValidatedServerConfig) => { onServerConfigChange = (serverConfig: ValidatedServerConfig) => {
this.setState({serverConfig}); this.setState({ serverConfig });
}; };
private makeRegistrationUrl = (params: {[key: string]: string}) => { private makeRegistrationUrl = (params: {[key: string]: string}) => {

View file

@ -16,24 +16,24 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React, {createRef} from 'react'; import React, { createRef } from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import shouldHideEvent from '../../shouldHideEvent'; import shouldHideEvent from '../../shouldHideEvent';
import {wantsDateSeparator} from '../../DateUtils'; import { wantsDateSeparator } from '../../DateUtils';
import * as sdk from '../../index'; import * as sdk from '../../index';
import {MatrixClientPeg} from '../../MatrixClientPeg'; import { MatrixClientPeg } from '../../MatrixClientPeg';
import SettingsStore from '../../settings/SettingsStore'; import SettingsStore from '../../settings/SettingsStore';
import RoomContext from "../../contexts/RoomContext"; import RoomContext from "../../contexts/RoomContext";
import {Layout, LayoutPropType} from "../../settings/Layout"; import { Layout, LayoutPropType } from "../../settings/Layout";
import {_t} from "../../languageHandler"; import { _t } from "../../languageHandler";
import {haveTileForEvent} from "../views/rooms/EventTile"; import { haveTileForEvent } from "../views/rooms/EventTile";
import {hasText} from "../../TextForEvent"; import { hasText } from "../../TextForEvent";
import IRCTimelineProfileResizer from "../views/elements/IRCTimelineProfileResizer"; import IRCTimelineProfileResizer from "../views/elements/IRCTimelineProfileResizer";
import DMRoomMap from "../../utils/DMRoomMap"; import DMRoomMap from "../../utils/DMRoomMap";
import NewRoomIntro from "../views/rooms/NewRoomIntro"; import NewRoomIntro from "../views/rooms/NewRoomIntro";
import {replaceableComponent} from "../../utils/replaceableComponent"; import { replaceableComponent } from "../../utils/replaceableComponent";
import defaultDispatcher from '../../dispatcher/dispatcher'; import defaultDispatcher from '../../dispatcher/dispatcher';
const CONTINUATION_MAX_INTERVAL = 5 * 60 * 1000; // 5 minutes const CONTINUATION_MAX_INTERVAL = 5 * 60 * 1000; // 5 minutes
@ -349,7 +349,7 @@ export default class MessagePanel extends React.Component {
scrollToEventIfNeeded(eventId) { scrollToEventIfNeeded(eventId) {
const node = this.eventNodes[eventId]; const node = this.eventNodes[eventId];
if (node) { if (node) {
node.scrollIntoView({block: "nearest", behavior: "instant"}); node.scrollIntoView({ block: "nearest", behavior: "instant" });
} }
} }
@ -398,7 +398,7 @@ export default class MessagePanel extends React.Component {
// confused. // confused.
if (visible) { if (visible) {
hr = <hr className="mx_RoomView_myReadMarker" hr = <hr className="mx_RoomView_myReadMarker"
style={{opacity: 1, width: '99%'}} style={{ opacity: 1, width: '99%' }}
/>; />;
} }
@ -473,7 +473,7 @@ export default class MessagePanel extends React.Component {
// not-chat purposes. // not-chat purposes.
const nextTile = arr.slice(i + 1).find(e => this._shouldShowEvent(e)); const nextTile = arr.slice(i + 1).find(e => this._shouldShowEvent(e));
return {nextEvent, nextTile}; return { nextEvent, nextTile };
} }
get _roomHasPendingEdit() { get _roomHasPendingEdit() {
@ -531,7 +531,7 @@ export default class MessagePanel extends React.Component {
const mxEv = this.props.events[i]; const mxEv = this.props.events[i];
const eventId = mxEv.getId(); const eventId = mxEv.getId();
const last = (mxEv === lastShownEvent); const last = (mxEv === lastShownEvent);
const {nextEvent, nextTile} = this._getNextEventInfo(this.props.events, i); const { nextEvent, nextTile } = this._getNextEventInfo(this.props.events, i);
if (grouper) { if (grouper) {
if (grouper.shouldGroup(mxEv)) { if (grouper.shouldGroup(mxEv)) {

View file

@ -24,7 +24,7 @@ import dis from '../../dispatcher/dispatcher';
import AccessibleButton from '../views/elements/AccessibleButton'; import AccessibleButton from '../views/elements/AccessibleButton';
import MatrixClientContext from "../../contexts/MatrixClientContext"; import MatrixClientContext from "../../contexts/MatrixClientContext";
import AutoHideScrollbar from "./AutoHideScrollbar"; import AutoHideScrollbar from "./AutoHideScrollbar";
import {replaceableComponent} from "../../utils/replaceableComponent"; import { replaceableComponent } from "../../utils/replaceableComponent";
import BetaCard from "../views/beta/BetaCard"; import BetaCard from "../views/beta/BetaCard";
@replaceableComponent("structures.MyGroups") @replaceableComponent("structures.MyGroups")
@ -41,19 +41,19 @@ export default class MyGroups extends React.Component {
} }
_onCreateGroupClick = () => { _onCreateGroupClick = () => {
dis.dispatch({action: 'view_create_group'}); dis.dispatch({ action: 'view_create_group' });
}; };
_fetch() { _fetch() {
this.context.getJoinedGroups().then((result) => { this.context.getJoinedGroups().then((result) => {
this.setState({groups: result.groups, error: null}); this.setState({ groups: result.groups, error: null });
}, (err) => { }, (err) => {
if (err.errcode === 'M_GUEST_ACCESS_FORBIDDEN') { if (err.errcode === 'M_GUEST_ACCESS_FORBIDDEN') {
// Indicate that the guest isn't in any groups (which should be true) // Indicate that the guest isn't in any groups (which should be true)
this.setState({groups: [], error: null}); this.setState({ groups: [], error: null });
return; return;
} }
this.setState({groups: null, error: err}); this.setState({ groups: null, error: err });
}); });
} }

View file

@ -18,7 +18,7 @@ import * as React from "react";
import { ComponentClass } from "../../@types/common"; import { ComponentClass } from "../../@types/common";
import NonUrgentToastStore from "../../stores/NonUrgentToastStore"; import NonUrgentToastStore from "../../stores/NonUrgentToastStore";
import { UPDATE_EVENT } from "../../stores/AsyncStore"; import { UPDATE_EVENT } from "../../stores/AsyncStore";
import {replaceableComponent} from "../../utils/replaceableComponent"; import { replaceableComponent } from "../../utils/replaceableComponent";
interface IProps { interface IProps {
} }
@ -44,7 +44,7 @@ export default class NonUrgentToastContainer extends React.PureComponent<IProps,
} }
private onUpdateToasts = () => { private onUpdateToasts = () => {
this.setState({toasts: NonUrgentToastStore.instance.components}); this.setState({ toasts: NonUrgentToastStore.instance.components });
}; };
public render() { public render() {

View file

@ -104,7 +104,7 @@ export default class RightPanel extends React.Component<IProps, IState> {
const userForPanel = this.getUserForPanel(); const userForPanel = this.getUserForPanel();
if (this.props.groupId) { if (this.props.groupId) {
if (!RIGHT_PANEL_PHASES_NO_ARGS.includes(rps.groupPanelPhase)) { if (!RIGHT_PANEL_PHASES_NO_ARGS.includes(rps.groupPanelPhase)) {
dis.dispatch({action: Action.SetRightPanelPhase, phase: RightPanelPhases.GroupMemberList}); dis.dispatch({ action: Action.SetRightPanelPhase, phase: RightPanelPhases.GroupMemberList });
return RightPanelPhases.GroupMemberList; return RightPanelPhases.GroupMemberList;
} }
return rps.groupPanelPhase; return rps.groupPanelPhase;

View file

@ -25,7 +25,7 @@ import { _t } from '../../languageHandler';
import SdkConfig from '../../SdkConfig'; import SdkConfig from '../../SdkConfig';
import { instanceForInstanceId, protocolNameForInstanceId } from '../../utils/DirectoryUtils'; import { instanceForInstanceId, protocolNameForInstanceId } from '../../utils/DirectoryUtils';
import Analytics from '../../Analytics'; import Analytics from '../../Analytics';
import {ALL_ROOMS, IFieldType, IInstance, IProtocol, Protocols} from "../views/directory/NetworkDropdown"; import { ALL_ROOMS, IFieldType, IInstance, IProtocol, Protocols } from "../views/directory/NetworkDropdown";
import SettingsStore from "../../settings/SettingsStore"; import SettingsStore from "../../settings/SettingsStore";
import GroupFilterOrderStore from "../../stores/GroupFilterOrderStore"; import GroupFilterOrderStore from "../../stores/GroupFilterOrderStore";
import GroupStore from "../../stores/GroupStore"; import GroupStore from "../../stores/GroupStore";
@ -34,7 +34,7 @@ import CountlyAnalytics from "../../CountlyAnalytics";
import { replaceableComponent } from "../../utils/replaceableComponent"; import { replaceableComponent } from "../../utils/replaceableComponent";
import { mediaFromMxc } from "../../customisations/Media"; import { mediaFromMxc } from "../../customisations/Media";
import { IDialogProps } from "../views/dialogs/IDialogProps"; import { IDialogProps } from "../views/dialogs/IDialogProps";
import AccessibleButton, {ButtonEvent} from "../views/elements/AccessibleButton"; import AccessibleButton, { ButtonEvent } from "../views/elements/AccessibleButton";
import BaseAvatar from "../views/avatars/BaseAvatar"; import BaseAvatar from "../views/avatars/BaseAvatar";
import ErrorDialog from "../views/dialogs/ErrorDialog"; import ErrorDialog from "../views/dialogs/ErrorDialog";
import QuestionDialog from "../views/dialogs/QuestionDialog"; import QuestionDialog from "../views/dialogs/QuestionDialog";
@ -45,7 +45,6 @@ import ScrollPanel from "./ScrollPanel";
import Spinner from "../views/elements/Spinner"; import Spinner from "../views/elements/Spinner";
import { ActionPayload } from "../../dispatcher/payloads"; import { ActionPayload } from "../../dispatcher/payloads";
const MAX_NAME_LENGTH = 80; const MAX_NAME_LENGTH = 80;
const MAX_TOPIC_LENGTH = 800; const MAX_TOPIC_LENGTH = 800;
@ -95,7 +94,7 @@ interface IPublicRoomsRequest {
@replaceableComponent("structures.RoomDirectory") @replaceableComponent("structures.RoomDirectory")
export default class RoomDirectory extends React.Component<IProps, IState> { export default class RoomDirectory extends React.Component<IProps, IState> {
private readonly startTime: number; private readonly startTime: number;
private unmounted = false private unmounted = false;
private nextBatch: string = null; private nextBatch: string = null;
private filterTimeout: NodeJS.Timeout; private filterTimeout: NodeJS.Timeout;
private protocols: Protocols; private protocols: Protocols;
@ -300,9 +299,9 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
let desc; let desc;
if (alias) { if (alias) {
desc = _t('Delete the room address %(alias)s and remove %(name)s from the directory?', {alias, name}); desc = _t('Delete the room address %(alias)s and remove %(name)s from the directory?', { alias, name });
} else { } else {
desc = _t('Remove %(name)s from the directory?', {name: name}); desc = _t('Remove %(name)s from the directory?', { name: name });
} }
Modal.createTrackedDialog('Remove from Directory', '', QuestionDialog, { Modal.createTrackedDialog('Remove from Directory', '', QuestionDialog, {
@ -312,7 +311,7 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
if (!shouldDelete) return; if (!shouldDelete) return;
const modal = Modal.createDialog(Spinner); const modal = Modal.createDialog(Spinner);
let step = _t('remove %(name)s from the directory.', {name: name}); let step = _t('remove %(name)s from the directory.', { name: name });
MatrixClientPeg.get().setRoomDirectoryVisibility(room.room_id, 'private').then(() => { MatrixClientPeg.get().setRoomDirectoryVisibility(room.room_id, 'private').then(() => {
if (!alias) return; if (!alias) return;
@ -483,7 +482,7 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
// to the directory. // to the directory.
if (MatrixClientPeg.get().isGuest()) { if (MatrixClientPeg.get().isGuest()) {
if (!room.world_readable && !room.guest_can_join) { if (!room.world_readable && !room.guest_can_join) {
dis.dispatch({action: 'require_registration'}); dis.dispatch({ action: 'require_registration' });
return; return;
} }
} }
@ -782,11 +781,11 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
} }
const explanation = const explanation =
_t("If you can't find the room you're looking for, ask for an invite or <a>Create a new room</a>.", null, _t("If you can't find the room you're looking for, ask for an invite or <a>Create a new room</a>.", null,
{a: sub => ( { a: sub => (
<AccessibleButton kind="secondary" onClick={this.onCreateRoomClick}> <AccessibleButton kind="secondary" onClick={this.onCreateRoomClick}>
{ sub } { sub }
</AccessibleButton> </AccessibleButton>
)}, ) },
); );
const title = this.state.selectedCommunityId const title = this.state.selectedCommunityId

View file

@ -108,22 +108,22 @@ export default class RoomSearch extends React.PureComponent<IProps, IState> {
}; };
private openSearch = () => { private openSearch = () => {
defaultDispatcher.dispatch({action: "show_left_panel"}); defaultDispatcher.dispatch({ action: "show_left_panel" });
defaultDispatcher.dispatch({action: "focus_room_filter"}); defaultDispatcher.dispatch({ action: "focus_room_filter" });
}; };
private onChange = () => { private onChange = () => {
if (!this.inputRef.current) return; if (!this.inputRef.current) return;
this.setState({query: this.inputRef.current.value}); this.setState({ query: this.inputRef.current.value });
}; };
private onFocus = (ev: React.FocusEvent<HTMLInputElement>) => { private onFocus = (ev: React.FocusEvent<HTMLInputElement>) => {
this.setState({focused: true}); this.setState({ focused: true });
ev.target.select(); ev.target.select();
}; };
private onBlur = (ev: React.FocusEvent<HTMLInputElement>) => { private onBlur = (ev: React.FocusEvent<HTMLInputElement>) => {
this.setState({focused: false}); this.setState({ focused: false });
}; };
private onKeyDown = (ev: React.KeyboardEvent) => { private onKeyDown = (ev: React.KeyboardEvent) => {

View file

@ -17,15 +17,15 @@ limitations under the License.
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { _t, _td } from '../../languageHandler'; import { _t, _td } from '../../languageHandler';
import {MatrixClientPeg} from '../../MatrixClientPeg'; import { MatrixClientPeg } from '../../MatrixClientPeg';
import Resend from '../../Resend'; import Resend from '../../Resend';
import dis from '../../dispatcher/dispatcher'; import dis from '../../dispatcher/dispatcher';
import {messageForResourceLimitError} from '../../utils/ErrorUtils'; import { messageForResourceLimitError } from '../../utils/ErrorUtils';
import {Action} from "../../dispatcher/actions"; import { Action } from "../../dispatcher/actions";
import {replaceableComponent} from "../../utils/replaceableComponent"; import { replaceableComponent } from "../../utils/replaceableComponent";
import {EventStatus} from "matrix-js-sdk/src/models/event"; import { EventStatus } from "matrix-js-sdk/src/models/event";
import NotificationBadge from "../views/rooms/NotificationBadge"; import NotificationBadge from "../views/rooms/NotificationBadge";
import {StaticNotificationState} from "../../stores/notifications/StaticNotificationState"; import { StaticNotificationState } from "../../stores/notifications/StaticNotificationState";
import AccessibleButton from "../views/elements/AccessibleButton"; import AccessibleButton from "../views/elements/AccessibleButton";
import InlineSpinner from "../views/elements/InlineSpinner"; import InlineSpinner from "../views/elements/InlineSpinner";
@ -115,9 +115,9 @@ export default class RoomStatusBar extends React.PureComponent {
_onResendAllClick = () => { _onResendAllClick = () => {
Resend.resendUnsentEvents(this.props.room).then(() => { Resend.resendUnsentEvents(this.props.room).then(() => {
this.setState({isResending: false}); this.setState({ isResending: false });
}); });
this.setState({isResending: true}); this.setState({ isResending: true });
dis.fire(Action.FocusComposer); dis.fire(Action.FocusComposer);
}; };

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