Merge branch 'develop' of github.com:matrix-org/matrix-react-sdk into spaces-jump-to-room
This commit is contained in:
commit
a99b24ef83
666 changed files with 5083 additions and 5561 deletions
38
.eslintrc.js
38
.eslintrc.js
|
@ -1,7 +1,9 @@
|
|||
module.exports = {
|
||||
extends: ["matrix-org", "matrix-org/react-legacy"],
|
||||
parser: "babel-eslint",
|
||||
|
||||
plugins: ["matrix-org"],
|
||||
extends: [
|
||||
"plugin:matrix-org/babel",
|
||||
"plugin:matrix-org/react",
|
||||
],
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
|
@ -15,12 +17,32 @@ module.exports = {
|
|||
"prefer-promise-reject-errors": "off",
|
||||
"no-async-promise-executor": "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: [{
|
||||
"files": ["src/**/*.{ts,tsx}", "test/**/*.{ts,tsx}"],
|
||||
"extends": ["matrix-org/ts"],
|
||||
"rules": {
|
||||
files: [
|
||||
"src/**/*.{ts,tsx}",
|
||||
"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
|
||||
"@typescript-eslint/no-empty-interface": "off",
|
||||
// We disable this while we're transitioning
|
||||
|
@ -28,8 +50,6 @@ module.exports = {
|
|||
// We'd rather not do this but we do
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
|
||||
"quotes": "off",
|
||||
"no-extra-boolean-cast": "off",
|
||||
"no-restricted-properties": [
|
||||
"error",
|
||||
...buildRestrictedPropertiesOptions(
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
[include]
|
||||
src/**/*.js
|
||||
test/**/*.js
|
||||
|
||||
[ignore]
|
||||
node_modules/
|
|
@ -10,7 +10,6 @@ module.exports = {
|
|||
],
|
||||
}],
|
||||
"@babel/preset-typescript",
|
||||
"@babel/preset-flow",
|
||||
"@babel/preset-react",
|
||||
],
|
||||
"plugins": [
|
||||
|
@ -19,7 +18,6 @@ module.exports = {
|
|||
"@babel/plugin-proposal-numeric-separator",
|
||||
"@babel/plugin-proposal-class-properties",
|
||||
"@babel/plugin-proposal-object-rest-spread",
|
||||
"@babel/plugin-transform-flow-comments",
|
||||
"@babel/plugin-syntax-dynamic-import",
|
||||
"@babel/plugin-transform-runtime",
|
||||
],
|
||||
|
|
14
package.json
14
package.json
|
@ -104,16 +104,16 @@
|
|||
"devDependencies": {
|
||||
"@babel/cli": "^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/plugin-proposal-class-properties": "^7.12.1",
|
||||
"@babel/plugin-proposal-decorators": "^7.12.12",
|
||||
"@babel/plugin-proposal-export-default-from": "^7.12.1",
|
||||
"@babel/plugin-proposal-numeric-separator": "^7.12.7",
|
||||
"@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/preset-env": "^7.12.11",
|
||||
"@babel/preset-flow": "^7.12.1",
|
||||
"@babel/preset-react": "^7.12.10",
|
||||
"@babel/preset-typescript": "^7.12.7",
|
||||
"@babel/register": "^7.12.10",
|
||||
|
@ -139,18 +139,16 @@
|
|||
"@types/react-transition-group": "^4.4.0",
|
||||
"@types/sanitize-html": "^2.3.1",
|
||||
"@types/zxcvbn": "^4.4.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.14.0",
|
||||
"@typescript-eslint/parser": "^4.14.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.17.0",
|
||||
"@typescript-eslint/parser": "^4.17.0",
|
||||
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.1",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-jest": "^26.6.3",
|
||||
"chokidar": "^3.5.1",
|
||||
"concurrently": "^5.3.0",
|
||||
"enzyme": "^3.11.0",
|
||||
"eslint": "7.18.0",
|
||||
"eslint-config-matrix-org": "^0.2.0",
|
||||
"eslint-plugin-babel": "^5.3.1",
|
||||
"eslint-plugin-flowtype": "^5.2.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-matrix-org": "github:matrix-org/eslint-plugin-matrix-org#main",
|
||||
"eslint-plugin-react": "^7.22.0",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"glob": "^7.1.6",
|
||||
|
|
|
@ -134,12 +134,15 @@ limitations under the License.
|
|||
.mx_Toast_buttons {
|
||||
float: right;
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
|
||||
.mx_AccessibleButton {
|
||||
min-width: 96px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.mx_AccessibleButton + .mx_AccessibleButton {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_Toast_description {
|
||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||
import { JSXElementConstructor } from "react";
|
||||
|
||||
// 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 Writeable<T> = { -readonly [P in keyof T]: T[P] };
|
||||
|
||||
|
|
32
src/@types/global.d.ts
vendored
32
src/@types/global.d.ts
vendored
|
@ -16,6 +16,7 @@ limitations under the License.
|
|||
|
||||
import "matrix-js-sdk/src/@types/global"; // load matrix-js-sdk's type extensions first
|
||||
import * as ModernizrStatic from "modernizr";
|
||||
|
||||
import ContentMessages from "../ContentMessages";
|
||||
import { IMatrixClientPeg } from "../MatrixClientPeg";
|
||||
import ToastStore from "../stores/ToastStore";
|
||||
|
@ -23,25 +24,25 @@ import DeviceListener from "../DeviceListener";
|
|||
import { RoomListStoreClass } from "../stores/room-list/RoomListStore";
|
||||
import { PlatformPeg } from "../PlatformPeg";
|
||||
import RoomListLayoutStore from "../stores/room-list/RoomListLayoutStore";
|
||||
import {IntegrationManagers} from "../integrations/IntegrationManagers";
|
||||
import {ModalManager} from "../Modal";
|
||||
import { IntegrationManagers } from "../integrations/IntegrationManagers";
|
||||
import { ModalManager } from "../Modal";
|
||||
import SettingsStore from "../settings/SettingsStore";
|
||||
import {ActiveRoomObserver} from "../ActiveRoomObserver";
|
||||
import {Notifier} from "../Notifier";
|
||||
import type {Renderer} from "react-dom";
|
||||
import { ActiveRoomObserver } from "../ActiveRoomObserver";
|
||||
import { Notifier } from "../Notifier";
|
||||
import type { Renderer } from "react-dom";
|
||||
import RightPanelStore from "../stores/RightPanelStore";
|
||||
import WidgetStore from "../stores/WidgetStore";
|
||||
import CallHandler from "../CallHandler";
|
||||
import {Analytics} from "../Analytics";
|
||||
import { Analytics } from "../Analytics";
|
||||
import CountlyAnalytics from "../CountlyAnalytics";
|
||||
import UserActivity from "../UserActivity";
|
||||
import {ModalWidgetStore} from "../stores/ModalWidgetStore";
|
||||
import { ModalWidgetStore } from "../stores/ModalWidgetStore";
|
||||
import { WidgetLayoutStore } from "../stores/widgets/WidgetLayoutStore";
|
||||
import VoipUserMapper from "../VoipUserMapper";
|
||||
import {SpaceStoreClass} from "../stores/SpaceStore";
|
||||
import { SpaceStoreClass } from "../stores/SpaceStore";
|
||||
import TypingStore from "../stores/TypingStore";
|
||||
import { EventIndexPeg } from "../indexing/EventIndexPeg";
|
||||
import {VoiceRecordingStore} from "../stores/VoiceRecordingStore";
|
||||
import { VoiceRecordingStore } from "../stores/VoiceRecordingStore";
|
||||
import PerformanceMonitor from "../performance";
|
||||
import UIStore from "../stores/UIStore";
|
||||
import { SetupEncryptionStore } from "../stores/SetupEncryptionStore";
|
||||
|
@ -127,11 +128,24 @@ declare global {
|
|||
setSinkId(outputId: string);
|
||||
}
|
||||
|
||||
// Add Chrome-specific `instant` ScrollBehaviour
|
||||
type _ScrollBehavior = ScrollBehavior | "instant";
|
||||
|
||||
interface _ScrollOptions {
|
||||
behavior?: _ScrollBehavior;
|
||||
}
|
||||
|
||||
interface _ScrollIntoViewOptions extends _ScrollOptions {
|
||||
block?: ScrollLogicalPosition;
|
||||
inline?: ScrollLogicalPosition;
|
||||
}
|
||||
|
||||
interface Element {
|
||||
// Safari & IE11 only have this prefixed: we used prefixed versions
|
||||
// previously so let's continue to support them for now
|
||||
webkitRequestFullScreen(options?: FullscreenOptions): Promise<void>;
|
||||
msRequestFullscreen(options?: FullscreenOptions): Promise<void>;
|
||||
scrollIntoView(arg?: boolean | _ScrollIntoViewOptions): void;
|
||||
}
|
||||
|
||||
interface Error {
|
||||
|
|
|
@ -16,12 +16,12 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {MatrixClientPeg} from './MatrixClientPeg';
|
||||
import { MatrixClientPeg } from './MatrixClientPeg';
|
||||
import * as sdk from './index';
|
||||
import Modal from './Modal';
|
||||
import { _t } from './languageHandler';
|
||||
import IdentityAuthClient from './IdentityAuthClient';
|
||||
import {SSOAuthEntry} from "./components/views/auth/InteractiveAuthEntryComponents";
|
||||
import { SSOAuthEntry } from "./components/views/auth/InteractiveAuthEntryComponents";
|
||||
|
||||
function getIdServerDomain() {
|
||||
return MatrixClientPeg.get().idBaseUrl.split("://")[1];
|
||||
|
@ -189,7 +189,6 @@ export default class AddThreepid {
|
|||
// pop up an interactive auth dialog
|
||||
const InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog");
|
||||
|
||||
|
||||
const dialogAesthetics = {
|
||||
[SSOAuthEntry.PHASE_PREAUTH]: {
|
||||
title: _t("Use Single Sign On to continue"),
|
||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||
|
||||
import React from 'react';
|
||||
|
||||
import {getCurrentLanguage, _t, _td, IVariables} from './languageHandler';
|
||||
import { getCurrentLanguage, _t, _td, IVariables } from './languageHandler';
|
||||
import PlatformPeg from './PlatformPeg';
|
||||
import SdkConfig from './SdkConfig';
|
||||
import Modal from './Modal';
|
||||
|
|
|
@ -17,16 +17,16 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {MatrixClient} from "matrix-js-sdk/src/client";
|
||||
import {encodeUnpaddedBase64} from "matrix-js-sdk/src/crypto/olmlib";
|
||||
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||
import { encodeUnpaddedBase64 } from "matrix-js-sdk/src/crypto/olmlib";
|
||||
import dis from './dispatcher/dispatcher';
|
||||
import BaseEventIndexManager from './indexing/BaseEventIndexManager';
|
||||
import {ActionPayload} from "./dispatcher/payloads";
|
||||
import {CheckUpdatesPayload} from "./dispatcher/payloads/CheckUpdatesPayload";
|
||||
import {Action} from "./dispatcher/actions";
|
||||
import {hideToast as hideUpdateToast} from "./toasts/UpdateToast";
|
||||
import {MatrixClientPeg} from "./MatrixClientPeg";
|
||||
import {idbLoad, idbSave, idbDelete} from "./utils/StorageManager";
|
||||
import { ActionPayload } from "./dispatcher/payloads";
|
||||
import { CheckUpdatesPayload } from "./dispatcher/payloads/CheckUpdatesPayload";
|
||||
import { Action } from "./dispatcher/actions";
|
||||
import { hideToast as hideUpdateToast } from "./toasts/UpdateToast";
|
||||
import { MatrixClientPeg } from "./MatrixClientPeg";
|
||||
import { idbLoad, idbSave, idbDelete } from "./utils/StorageManager";
|
||||
|
||||
export const SSO_HOMESERVER_URL_KEY = "mx_sso_hs_url";
|
||||
export const SSO_ID_SERVER_URL_KEY = "mx_sso_is_url";
|
||||
|
@ -335,7 +335,7 @@ export default abstract class BasePlatform {
|
|||
|
||||
try {
|
||||
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,
|
||||
);
|
||||
return encodeUnpaddedBase64(key);
|
||||
|
@ -348,7 +348,7 @@ export default abstract class BasePlatform {
|
|||
/**
|
||||
* Create and store a pickle key for encrypting libolm objects.
|
||||
* @param {string} userId the user ID for the user that the pickle key is for.
|
||||
* @param {string} userId the device ID that the pickle key is for.
|
||||
* @param {string} deviceId the device ID that the pickle key is for.
|
||||
* @returns {string|null} the pickle key, or null if the platform does not
|
||||
* support storing pickle keys.
|
||||
*/
|
||||
|
@ -360,7 +360,7 @@ export default abstract class BasePlatform {
|
|||
const randomArray = new Uint8Array(32);
|
||||
crypto.getRandomValues(randomArray);
|
||||
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);
|
||||
crypto.getRandomValues(iv);
|
||||
|
@ -375,11 +375,11 @@ export default abstract class BasePlatform {
|
|||
}
|
||||
|
||||
const encrypted = await crypto.subtle.encrypt(
|
||||
{name: "AES-GCM", iv, additionalData}, cryptoKey, randomArray,
|
||||
{ name: "AES-GCM", iv, additionalData }, cryptoKey, randomArray,
|
||||
);
|
||||
|
||||
try {
|
||||
await idbSave("pickleKey", [userId, deviceId], {encrypted, iv, cryptoKey});
|
||||
await idbSave("pickleKey", [userId, deviceId], { encrypted, iv, cryptoKey });
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ limitations under the License.
|
|||
|
||||
import React from 'react';
|
||||
|
||||
import {MatrixClientPeg} from './MatrixClientPeg';
|
||||
import { MatrixClientPeg } from './MatrixClientPeg';
|
||||
import PlatformPeg from './PlatformPeg';
|
||||
import Modal from './Modal';
|
||||
import { _t } from './languageHandler';
|
||||
|
@ -63,11 +63,11 @@ import dis from './dispatcher/dispatcher';
|
|||
import WidgetUtils from './utils/WidgetUtils';
|
||||
import WidgetEchoStore from './stores/WidgetEchoStore';
|
||||
import SettingsStore from './settings/SettingsStore';
|
||||
import {Jitsi} from "./widgets/Jitsi";
|
||||
import {WidgetType} from "./widgets/WidgetType";
|
||||
import {SettingLevel} from "./settings/SettingLevel";
|
||||
import { Jitsi } from "./widgets/Jitsi";
|
||||
import { WidgetType } from "./widgets/WidgetType";
|
||||
import { SettingLevel } from "./settings/SettingLevel";
|
||||
import { ActionPayload } from "./dispatcher/payloads";
|
||||
import {base32} from "rfc4648";
|
||||
import { base32 } from "rfc4648";
|
||||
|
||||
import QuestionDialog from "./components/views/dialogs/QuestionDialog";
|
||||
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 Analytics from './Analytics';
|
||||
import CountlyAnalytics from "./CountlyAnalytics";
|
||||
import {UIFeature} from "./settings/UIFeature";
|
||||
import { UIFeature } from "./settings/UIFeature";
|
||||
import { CallError } from "matrix-js-sdk/src/webrtc/call";
|
||||
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 VoipUserMapper from './VoipUserMapper';
|
||||
import { addManagedHybridWidget, isManagedHybridWidgetEnabled } from './widgets/ManagedHybrid';
|
||||
|
@ -166,7 +166,7 @@ export default class CallHandler extends EventEmitter {
|
|||
|
||||
static sharedInstance() {
|
||||
if (!window.mxCallHandler) {
|
||||
window.mxCallHandler = new CallHandler()
|
||||
window.mxCallHandler = new CallHandler();
|
||||
}
|
||||
|
||||
return window.mxCallHandler;
|
||||
|
@ -185,7 +185,7 @@ export default class CallHandler extends EventEmitter {
|
|||
const nativeUser = this.assertedIdentityNativeUsers[call.callId];
|
||||
if (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;
|
||||
}
|
||||
|
||||
dis.dispatch({action: Action.PstnSupportUpdated});
|
||||
dis.dispatch({ action: Action.PstnSupportUpdated });
|
||||
|
||||
if (protocols[PROTOCOL_SIP_NATIVE] !== undefined && protocols[PROTOCOL_SIP_VIRTUAL] !== undefined) {
|
||||
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) {
|
||||
if (maxTries === 1) {
|
||||
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',
|
||||
call: call,
|
||||
}, true);
|
||||
}
|
||||
};
|
||||
|
||||
getCallForRoom(roomId: string): MatrixCall {
|
||||
return this.calls.get(roomId) || null;
|
||||
|
@ -711,7 +711,7 @@ export default class CallHandler extends EventEmitter {
|
|||
|
||||
call.placeScreenSharingCall(
|
||||
async (): Promise<DesktopCapturerSource> => {
|
||||
const {finished} = Modal.createDialog(DesktopCapturerSourcePicker);
|
||||
const { finished } = Modal.createDialog(DesktopCapturerSourcePicker);
|
||||
const [source] = await finished;
|
||||
return source;
|
||||
},
|
||||
|
@ -816,7 +816,7 @@ export default class CallHandler extends EventEmitter {
|
|||
|
||||
Analytics.trackEvent('voip', 'receiveCall', 'type', call.type);
|
||||
console.log("Adding call for room ", mappedRoomId);
|
||||
this.calls.set(mappedRoomId, call)
|
||||
this.calls.set(mappedRoomId, call);
|
||||
this.emit(CallHandlerEvent.CallsChanged, this.calls);
|
||||
this.setCallListeners(call);
|
||||
|
||||
|
@ -872,7 +872,7 @@ export default class CallHandler extends EventEmitter {
|
|||
this.dialNumber(payload.number);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private async dialNumber(number: string) {
|
||||
const results = await this.pstnLookup(number);
|
||||
|
@ -966,7 +966,7 @@ export default class CallHandler extends EventEmitter {
|
|||
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
|
||||
const parsedUrl = new URL(widgetUrl);
|
||||
|
|
|
@ -18,8 +18,8 @@ limitations under the License.
|
|||
|
||||
import React from "react";
|
||||
import dis from './dispatcher/dispatcher';
|
||||
import {MatrixClientPeg} from './MatrixClientPeg';
|
||||
import {MatrixClient} from "matrix-js-sdk/src/client";
|
||||
import { MatrixClientPeg } from './MatrixClientPeg';
|
||||
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||
import * as sdk from './index';
|
||||
import { _t } from './languageHandler';
|
||||
import Modal from './Modal';
|
||||
|
@ -37,7 +37,7 @@ import {
|
|||
UploadProgressPayload,
|
||||
UploadStartedPayload,
|
||||
} from "./dispatcher/payloads/UploadPayload";
|
||||
import {IUpload} from "./models/IUpload";
|
||||
import { IUpload } from "./models/IUpload";
|
||||
import { IImageInfo } from "matrix-js-sdk/src/@types/partials";
|
||||
|
||||
const MAX_WIDTH = 800;
|
||||
|
@ -189,7 +189,7 @@ async function loadImageElement(imageFile: File) {
|
|||
const [hidpi] = await Promise.all([parsePromise, imgPromise]);
|
||||
const width = hidpi ? (img.width >> 1) : img.width;
|
||||
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) {
|
||||
encryptInfo.mimetype = file.type;
|
||||
}
|
||||
return {"file": encryptInfo};
|
||||
return { "file": encryptInfo };
|
||||
});
|
||||
(prom as IAbortablePromise<any>).abort = () => {
|
||||
canceled = true;
|
||||
|
@ -357,7 +357,7 @@ export function uploadFile(
|
|||
const promise1 = basePromise.then(function(url) {
|
||||
if (canceled) throw new UploadCanceledError();
|
||||
// If the attachment isn't encrypted then include the URL directly.
|
||||
return {"url": url};
|
||||
return { "url": url };
|
||||
});
|
||||
(promise1 as any).abort = () => {
|
||||
canceled = true;
|
||||
|
@ -377,7 +377,7 @@ export default class ContentMessages {
|
|||
console.warn(`Failed to send content with URL ${url} to room ${roomId}`, 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;
|
||||
}
|
||||
|
||||
|
@ -391,14 +391,14 @@ export default class ContentMessages {
|
|||
|
||||
async sendContentListToRoom(files: File[], roomId: string, matrixClient: MatrixClient) {
|
||||
if (matrixClient.isGuest()) {
|
||||
dis.dispatch({action: 'require_registration'});
|
||||
dis.dispatch({ action: 'require_registration' });
|
||||
return;
|
||||
}
|
||||
|
||||
const isQuoting = Boolean(RoomViewStore.getQuotingEvent());
|
||||
if (isQuoting) {
|
||||
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'),
|
||||
description: (
|
||||
<div>{_t(
|
||||
|
@ -432,7 +432,7 @@ export default class ContentMessages {
|
|||
|
||||
if (tooBigFiles.length > 0) {
|
||||
const UploadFailureDialog = sdk.getComponent("dialogs.UploadFailureDialog");
|
||||
const {finished} = Modal.createTrackedDialog<[boolean]>('Upload Failure', '', UploadFailureDialog, {
|
||||
const { finished } = Modal.createTrackedDialog<[boolean]>('Upload Failure', '', UploadFailureDialog, {
|
||||
badFiles: tooBigFiles,
|
||||
totalFiles: files.length,
|
||||
contentMessages: this,
|
||||
|
@ -449,7 +449,7 @@ export default class ContentMessages {
|
|||
for (let i = 0; i < okFiles.length; ++i) {
|
||||
const file = okFiles[i];
|
||||
if (!uploadAll) {
|
||||
const {finished} = Modal.createTrackedDialog<[boolean, boolean]>('Upload Files confirmation',
|
||||
const { finished } = Modal.createTrackedDialog<[boolean, boolean]>('Upload Files confirmation',
|
||||
'', UploadConfirmDialog, {
|
||||
file,
|
||||
currentIndex: i,
|
||||
|
@ -481,7 +481,7 @@ export default class ContentMessages {
|
|||
if (upload) {
|
||||
upload.canceled = true;
|
||||
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,
|
||||
};
|
||||
this.inprogress.push(upload);
|
||||
dis.dispatch<UploadStartedPayload>({action: Action.UploadStarted, upload});
|
||||
dis.dispatch<UploadStartedPayload>({ action: Action.UploadStarted, upload });
|
||||
|
||||
// Focus the composer view
|
||||
dis.fire(Action.FocusComposer);
|
||||
|
@ -550,7 +550,7 @@ export default class ContentMessages {
|
|||
function onProgress(ev) {
|
||||
upload.total = ev.total;
|
||||
upload.loaded = ev.loaded;
|
||||
dis.dispatch<UploadProgressPayload>({action: Action.UploadProgress, upload});
|
||||
dis.dispatch<UploadProgressPayload>({ action: Action.UploadProgress, upload });
|
||||
}
|
||||
|
||||
let error;
|
||||
|
@ -577,11 +577,11 @@ export default class ContentMessages {
|
|||
}, function(err) {
|
||||
error = err;
|
||||
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) {
|
||||
desc = _t(
|
||||
"The file '%(fileName)s' exceeds this homeserver's size limit for uploads",
|
||||
{fileName: upload.fileName},
|
||||
{ fileName: upload.fileName },
|
||||
);
|
||||
}
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
|
@ -604,10 +604,10 @@ export default class ContentMessages {
|
|||
if (error && error.http_status === 413) {
|
||||
this.mediaConfig = null;
|
||||
}
|
||||
dis.dispatch<UploadErrorPayload>({action: Action.UploadFailed, upload, error});
|
||||
dis.dispatch<UploadErrorPayload>({ action: Action.UploadFailed, upload, error });
|
||||
} else {
|
||||
dis.dispatch<UploadFinishedPayload>({action: Action.UploadFinished, upload});
|
||||
dis.dispatch({action: 'message_sent'});
|
||||
dis.dispatch<UploadFinishedPayload>({ action: Action.UploadFinished, upload });
|
||||
dis.dispatch({ action: 'message_sent' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -14,13 +14,13 @@ See the License for the specific language governing permissions and
|
|||
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 SdkConfig from './SdkConfig';
|
||||
import {MatrixClientPeg} from "./MatrixClientPeg";
|
||||
import {sleep} from "./utils/promise";
|
||||
import { MatrixClientPeg } from "./MatrixClientPeg";
|
||||
import { sleep } from "./utils/promise";
|
||||
import RoomViewStore from "./stores/RoomViewStore";
|
||||
import { Action } from "./dispatcher/actions";
|
||||
|
||||
|
@ -338,8 +338,8 @@ const getRoomStats = (roomId: string) => {
|
|||
"is_encrypted": cli?.isRoomEncrypted(roomId),
|
||||
// eslint-disable-next-line camelcase
|
||||
"is_public": room?.currentState.getStateEvents("m.room.join_rules", "")?.getContent()?.join_rule === "public",
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// async wrapper for regex-powered String.prototype.replace
|
||||
const strReplaceAsync = async (str: string, regex: RegExp, fn: (...args: string[]) => Promise<string>) => {
|
||||
|
@ -414,7 +414,7 @@ export default class CountlyAnalytics {
|
|||
|
||||
this.anonymous = anonymous;
|
||||
if (anonymous) {
|
||||
await this.changeUserKey(randomString(64))
|
||||
await this.changeUserKey(randomString(64));
|
||||
} else {
|
||||
await this.changeUserKey(await hashHex(MatrixClientPeg.get().getUserId()), true);
|
||||
}
|
||||
|
@ -438,7 +438,7 @@ export default class CountlyAnalytics {
|
|||
await this.track("Opt-Out" );
|
||||
this.endSession();
|
||||
window.clearInterval(this.heartbeatIntervalId);
|
||||
window.clearTimeout(this.activityIntervalId)
|
||||
window.clearTimeout(this.activityIntervalId);
|
||||
this.baseUrl = null;
|
||||
// remove listeners bound in trackSessions()
|
||||
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">>) {
|
||||
const {count = 1, ...rest} = args;
|
||||
const { count = 1, ...rest } = args;
|
||||
const ev = {
|
||||
...this.getTimeParams(),
|
||||
...rest,
|
||||
count,
|
||||
platform: this.appPlatform,
|
||||
app_version: this.appVersion,
|
||||
}
|
||||
};
|
||||
|
||||
this.pendingEvents.push(ev);
|
||||
if (this.pendingEvents.length > MAX_PENDING_EVENTS) {
|
||||
|
@ -680,7 +680,7 @@ export default class CountlyAnalytics {
|
|||
private getOrientation = (): Orientation => {
|
||||
return window.matchMedia("(orientation: landscape)").matches
|
||||
? Orientation.Landscape
|
||||
: Orientation.Portrait
|
||||
: Orientation.Portrait;
|
||||
};
|
||||
|
||||
private reportOrientation = () => {
|
||||
|
@ -749,7 +749,7 @@ export default class CountlyAnalytics {
|
|||
const request: Parameters<typeof CountlyAnalytics.prototype.request>[0] = {
|
||||
begin_session: 1,
|
||||
user_details: JSON.stringify(userDetails),
|
||||
}
|
||||
};
|
||||
|
||||
const metrics = this.getMetrics();
|
||||
if (metrics) {
|
||||
|
@ -773,7 +773,7 @@ export default class CountlyAnalytics {
|
|||
|
||||
private endSession = () => {
|
||||
if (this.sessionStarted) {
|
||||
window.removeEventListener("resize", this.reportOrientation)
|
||||
window.removeEventListener("resize", this.reportOrientation);
|
||||
|
||||
this.reportViewDuration();
|
||||
this.request({
|
||||
|
|
|
@ -168,7 +168,7 @@ export class DecryptionFailureTracker {
|
|||
const trackedEventIds = [...dedupedFailuresMap.keys()];
|
||||
|
||||
this.trackedEventHashMap = trackedEventIds.reduce(
|
||||
(result, eventId) => ({...result, [eventId]: true}),
|
||||
(result, eventId) => ({ ...result, [eventId]: true }),
|
||||
this.trackedEventHashMap,
|
||||
);
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {MatrixClientPeg} from './MatrixClientPeg';
|
||||
import { MatrixClientPeg } from './MatrixClientPeg';
|
||||
import dis from "./dispatcher/dispatcher";
|
||||
import {
|
||||
hideToast as hideBulkUnverifiedSessionsToast,
|
||||
|
|
|
@ -19,7 +19,7 @@ import Modal from './Modal';
|
|||
import * as sdk from './';
|
||||
import MultiInviter from './utils/MultiInviter';
|
||||
import { _t } from './languageHandler';
|
||||
import {MatrixClientPeg} from './MatrixClientPeg';
|
||||
import { MatrixClientPeg } from './MatrixClientPeg';
|
||||
import GroupStore from './stores/GroupStore';
|
||||
import StyledCheckbox from './components/views/elements/StyledCheckbox';
|
||||
|
||||
|
@ -103,7 +103,7 @@ function _onGroupInviteFinished(groupId, addrs) {
|
|||
if (errorList.length > 0) {
|
||||
const ErrorDialog = sdk.getComponent("dialogs.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(", "),
|
||||
});
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ function _onGroupInviteFinished(groupId, addrs) {
|
|||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createTrackedDialog('Failed to invite users to group', '', ErrorDialog, {
|
||||
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
|
||||
if (!groups.includes(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(() => {
|
||||
|
@ -152,7 +152,7 @@ function _onGroupAddRoomFinished(groupId, addrs, addRoomsPublicly) {
|
|||
{
|
||||
title: _t(
|
||||
"Failed to add the following rooms to %(groupId)s:",
|
||||
{groupId},
|
||||
{ groupId },
|
||||
),
|
||||
description: errorList.join(", "),
|
||||
},
|
||||
|
|
|
@ -138,7 +138,7 @@ export function getHtmlText(insaneHtml: string): string {
|
|||
selfClosing: [],
|
||||
allowedSchemes: [],
|
||||
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
|
||||
// like standalone image events have.
|
||||
if (!attribs.src || !attribs.src.startsWith('mxc://') || !SettingsStore.getValue("showImages")) {
|
||||
return { tagName, attribs: {}};
|
||||
return { tagName, attribs: {} };
|
||||
}
|
||||
const width = Number(attribs.width) || 800;
|
||||
const height = Number(attribs.height) || 600;
|
||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||
import { SERVICE_TYPES } from 'matrix-js-sdk/src/service-types';
|
||||
import { createClient } from 'matrix-js-sdk/src/matrix';
|
||||
|
||||
import {MatrixClientPeg} from './MatrixClientPeg';
|
||||
import { MatrixClientPeg } from './MatrixClientPeg';
|
||||
import Modal from './Modal';
|
||||
import * as sdk from './index';
|
||||
import { _t } from './languageHandler';
|
||||
|
|
|
@ -156,7 +156,7 @@ const messageComposerBindings = (): KeyBinding<MessageComposerAction>[] => {
|
|||
}
|
||||
}
|
||||
return bindings;
|
||||
}
|
||||
};
|
||||
|
||||
const autocompleteBindings = (): KeyBinding<AutocompleteAction>[] => {
|
||||
return [
|
||||
|
@ -207,7 +207,7 @@ const autocompleteBindings = (): KeyBinding<AutocompleteAction>[] => {
|
|||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
const roomListBindings = (): KeyBinding<RoomListAction>[] => {
|
||||
return [
|
||||
|
@ -248,7 +248,7 @@ const roomListBindings = (): KeyBinding<RoomListAction>[] => {
|
|||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
const roomBindings = (): KeyBinding<RoomAction>[] => {
|
||||
const bindings: KeyBinding<RoomAction>[] = [
|
||||
|
@ -312,7 +312,7 @@ const roomBindings = (): KeyBinding<RoomAction>[] => {
|
|||
}
|
||||
|
||||
return bindings;
|
||||
}
|
||||
};
|
||||
|
||||
const navigationBindings = (): KeyBinding<NavigationAction>[] => {
|
||||
return [
|
||||
|
@ -396,7 +396,7 @@ const navigationBindings = (): KeyBinding<NavigationAction>[] => {
|
|||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
export const defaultBindingsProvider: IKeyBindingsProvider = {
|
||||
getMessageComposerBindings: messageComposerBindings,
|
||||
|
@ -404,4 +404,4 @@ export const defaultBindingsProvider: IKeyBindingsProvider = {
|
|||
getRoomListBindings: roomListBindings,
|
||||
getRoomBindings: roomBindings,
|
||||
getNavigationBindings: navigationBindings,
|
||||
}
|
||||
};
|
||||
|
|
|
@ -140,12 +140,12 @@ export type KeyCombo = {
|
|||
ctrlKey?: boolean;
|
||||
metaKey?: boolean;
|
||||
shiftKey?: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
export type KeyBinding<T extends string> = {
|
||||
action: T;
|
||||
keyCombo: KeyCombo;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper method to check if a KeyboardEvent matches a KeyCombo
|
||||
|
|
|
@ -20,9 +20,9 @@ limitations under the License.
|
|||
import { createClient } from 'matrix-js-sdk/src/matrix';
|
||||
import { InvalidStoreError } from "matrix-js-sdk/src/errors";
|
||||
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||
import {decryptAES, encryptAES} from "matrix-js-sdk/src/crypto/aes";
|
||||
import { decryptAES, encryptAES, IEncryptedPayload } from "matrix-js-sdk/src/crypto/aes";
|
||||
|
||||
import {IMatrixClientCreds, MatrixClientPeg} from './MatrixClientPeg';
|
||||
import { IMatrixClientCreds, MatrixClientPeg } from './MatrixClientPeg';
|
||||
import SecurityCustomisations from "./customisations/Security";
|
||||
import EventIndexPeg from './indexing/EventIndexPeg';
|
||||
import createMatrixClient from './utils/createMatrixClient';
|
||||
|
@ -41,17 +41,17 @@ import * as StorageManager from './utils/StorageManager';
|
|||
import SettingsStore from "./settings/SettingsStore";
|
||||
import TypingStore from "./stores/TypingStore";
|
||||
import ToastStore from "./stores/ToastStore";
|
||||
import {IntegrationManagers} from "./integrations/IntegrationManagers";
|
||||
import {Mjolnir} from "./mjolnir/Mjolnir";
|
||||
import { IntegrationManagers } from "./integrations/IntegrationManagers";
|
||||
import { Mjolnir } from "./mjolnir/Mjolnir";
|
||||
import DeviceListener from "./DeviceListener";
|
||||
import {Jitsi} from "./widgets/Jitsi";
|
||||
import {SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY, SSO_IDP_ID_KEY} from "./BasePlatform";
|
||||
import { Jitsi } from "./widgets/Jitsi";
|
||||
import { SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY, SSO_IDP_ID_KEY } from "./BasePlatform";
|
||||
import ThreepidInviteStore from "./stores/ThreepidInviteStore";
|
||||
import CountlyAnalytics from "./CountlyAnalytics";
|
||||
import CallHandler from './CallHandler';
|
||||
import LifecycleCustomisations from "./customisations/Lifecycle";
|
||||
import ErrorDialog from "./components/views/dialogs/ErrorDialog";
|
||||
import {_t} from "./languageHandler";
|
||||
import { _t } from "./languageHandler";
|
||||
|
||||
const HOMESERVER_URL_KEY = "mx_hs_url";
|
||||
const ID_SERVER_URL_KEY = "mx_is_url";
|
||||
|
@ -154,7 +154,7 @@ export async function loadSession(opts: ILoadSessionOpts = {}): Promise<boolean>
|
|||
* return [null, null].
|
||||
*/
|
||||
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];
|
||||
}
|
||||
|
||||
|
@ -303,7 +303,7 @@ export interface IStoredSession {
|
|||
hsUrl: string;
|
||||
isUrl: string;
|
||||
hasAccessToken: boolean;
|
||||
accessToken: string | object;
|
||||
accessToken: string | IEncryptedPayload;
|
||||
userId: string;
|
||||
deviceId: string;
|
||||
isGuest: boolean;
|
||||
|
@ -346,11 +346,11 @@ export async function getStoredSessionVars(): Promise<IStoredSession> {
|
|||
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
|
||||
// need a 256-bit Uint8Array. So we HKDF the pickle key to generate the AES
|
||||
// need a 256-bit Uint8Array. So we HKDF the pickle key to generate the AES
|
||||
// key. The AES key should be zeroed after it is used.
|
||||
async function pickleKeyToAesKey(pickleKey: string): Promise<Uint8Array> {
|
||||
const pickleKeyBuffer = new Uint8Array(pickleKey.length);
|
||||
|
@ -402,7 +402,7 @@ export async function restoreFromLocalStorage(opts?: { ignoreGuest?: boolean }):
|
|||
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) {
|
||||
abortLogin();
|
||||
|
@ -495,7 +495,7 @@ export async function setLoggedIn(credentials: IMatrixClientCreds): Promise<Matr
|
|||
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.
|
||||
// (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) {
|
||||
await clearStorage();
|
||||
|
@ -745,7 +745,7 @@ export function softLogout(): void {
|
|||
// Ensure that we dispatch a view change **before** stopping the client so
|
||||
// so that React components unmount first. This avoids React soft crashes
|
||||
// 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);
|
||||
|
||||
// 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
|
||||
// a race condition (and we need to dispatch synchronously for this
|
||||
// to work).
|
||||
dis.dispatch({action: 'will_start_client'}, true);
|
||||
dis.dispatch({ action: 'will_start_client' }, true);
|
||||
|
||||
// reset things first just in case
|
||||
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
|
||||
// of the matrix client that cannot be set prior to starting up.
|
||||
dis.dispatch({action: 'client_started'});
|
||||
dis.dispatch({ action: 'client_started' });
|
||||
|
||||
if (isSoftLogout()) {
|
||||
softLogout();
|
||||
|
@ -830,9 +830,9 @@ export async function onLoggedOut(): Promise<void> {
|
|||
// Ensure that we dispatch a view change **before** stopping the client so
|
||||
// so that React components unmount first. This avoids React soft crashes
|
||||
// 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();
|
||||
await clearStorage({deleteEverything: true});
|
||||
await clearStorage({ deleteEverything: true });
|
||||
LifecycleCustomisations.onLoggedOutAndStorageCleared?.();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
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 { IMatrixClientCreds } from "./MatrixClientPeg";
|
||||
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
|
||||
* as a MatrixClientCreds
|
||||
|
|
|
@ -18,22 +18,22 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import { ICreateClientOpts } from 'matrix-js-sdk/src/matrix';
|
||||
import {MatrixClient} from 'matrix-js-sdk/src/client';
|
||||
import {MemoryStore} from 'matrix-js-sdk/src/store/memory';
|
||||
import { MatrixClient } from 'matrix-js-sdk/src/client';
|
||||
import { MemoryStore } from 'matrix-js-sdk/src/store/memory';
|
||||
import * as utils from 'matrix-js-sdk/src/utils';
|
||||
import {EventTimeline} from 'matrix-js-sdk/src/models/event-timeline';
|
||||
import {EventTimelineSet} from 'matrix-js-sdk/src/models/event-timeline-set';
|
||||
import { EventTimeline } from 'matrix-js-sdk/src/models/event-timeline';
|
||||
import { EventTimelineSet } from 'matrix-js-sdk/src/models/event-timeline-set';
|
||||
import * as sdk from './index';
|
||||
import createMatrixClient from './utils/createMatrixClient';
|
||||
import SettingsStore from './settings/SettingsStore';
|
||||
import MatrixActionCreators from './actions/MatrixActionCreators';
|
||||
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 * as StorageManager from './utils/StorageManager';
|
||||
import IdentityAuthClient from './IdentityAuthClient';
|
||||
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";
|
||||
|
||||
export interface IMatrixClientCreds {
|
||||
|
|
|
@ -15,14 +15,13 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import Analytics from './Analytics';
|
||||
import dis from './dispatcher/dispatcher';
|
||||
import {defer} from './utils/promise';
|
||||
import { defer } from './utils/promise';
|
||||
import AsyncWrapper from './AsyncWrapper';
|
||||
|
||||
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.close = closeDialog;
|
||||
|
||||
return {modal, closeDialog, onFinishedProm};
|
||||
return { modal, closeDialog, onFinishedProm };
|
||||
}
|
||||
|
||||
private getCloseFn<T extends any[]>(
|
||||
|
@ -282,7 +281,7 @@ export class ModalManager {
|
|||
isStaticModal = false,
|
||||
options: IOptions<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) {
|
||||
// XXX: This is destructive
|
||||
this.priorityModal = modal;
|
||||
|
@ -305,7 +304,7 @@ export class ModalManager {
|
|||
props?: IProps<T>,
|
||||
className?: string,
|
||||
): 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.reRender();
|
||||
|
|
|
@ -32,11 +32,11 @@ import { _t } from './languageHandler';
|
|||
import Modal from './Modal';
|
||||
import SettingsStore from "./settings/SettingsStore";
|
||||
import { hideToast as hideNotificationsToast } from "./toasts/DesktopNotificationsToast";
|
||||
import {SettingLevel} from "./settings/SettingLevel";
|
||||
import {isPushNotifyDisabled} from "./settings/controllers/NotificationControllers";
|
||||
import { SettingLevel } from "./settings/SettingLevel";
|
||||
import { isPushNotifyDisabled } from "./settings/controllers/NotificationControllers";
|
||||
import RoomViewStore from "./stores/RoomViewStore";
|
||||
import UserActivity from "./UserActivity";
|
||||
import {mediaFromMxc} from "./customisations/Media";
|
||||
import { mediaFromMxc } from "./customisations/Media";
|
||||
|
||||
/*
|
||||
* Dispatches:
|
||||
|
|
|
@ -16,10 +16,10 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {MatrixClientPeg} from "./MatrixClientPeg";
|
||||
import { MatrixClientPeg } from "./MatrixClientPeg";
|
||||
import dis from "./dispatcher/dispatcher";
|
||||
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
|
||||
const UNAVAILABLE_TIME_MS = 3 * 60 * 1000; // 3 mins
|
||||
|
@ -78,7 +78,7 @@ class Presence {
|
|||
this.setState(State.Online);
|
||||
this.unavailableTimer.restart();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the presence state.
|
||||
|
@ -98,7 +98,7 @@ class Presence {
|
|||
}
|
||||
|
||||
try {
|
||||
await MatrixClientPeg.get().setPresence({presence: this.state});
|
||||
await MatrixClientPeg.get().setPresence({ presence: this.state });
|
||||
console.info("Presence:", newState);
|
||||
} catch (err) {
|
||||
console.error("Failed to set presence:", err);
|
||||
|
|
|
@ -53,16 +53,16 @@ export async function startAnyRegistrationFlow(options) {
|
|||
extraButtons: [
|
||||
<button key="start_login" onClick={() => {
|
||||
modal.close();
|
||||
dis.dispatch({action: 'start_login', screenAfterLogin: options.screen_after});
|
||||
dis.dispatch({ action: 'start_login', screenAfterLogin: options.screen_after });
|
||||
}}>{ _t('Sign In') }</button>,
|
||||
],
|
||||
onFinished: (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) {
|
||||
dis.dispatch({action: 'view_home_page'});
|
||||
dis.dispatch({ action: 'view_home_page' });
|
||||
} else if (options.go_welcome_on_cancel) {
|
||||
dis.dispatch({action: 'view_welcome_page'});
|
||||
dis.dispatch({ action: 'view_welcome_page' });
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -31,6 +31,6 @@ export function textualPowerLevel(level: number, usersDefault: number): string {
|
|||
if (LEVEL_ROLE_MAP[level]) {
|
||||
return LEVEL_ROLE_MAP[level];
|
||||
} else {
|
||||
return _t("Custom (%(level)s)", {level});
|
||||
return _t("Custom (%(level)s)", { level });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ export function showStartChatInviteDialog(initialText = ""): void {
|
|||
// This dialog handles the room creation internally - we don't need to worry about it.
|
||||
const InviteDialog = sdk.getComponent("dialogs.InviteDialog");
|
||||
Modal.createTrackedDialog(
|
||||
'Start DM', '', InviteDialog, {kind: KIND_DM, initialText},
|
||||
'Start DM', '', InviteDialog, { kind: KIND_DM, initialText },
|
||||
/*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 {
|
||||
Modal.createTrackedDialog(
|
||||
'Invite Users to Community', '', CommunityPrototypeInviteDialog, {communityName, roomId},
|
||||
'Invite Users to Community', '', CommunityPrototypeInviteDialog, { communityName, roomId },
|
||||
/*className=*/null, /*isPriority=*/false, /*isStatic=*/true,
|
||||
);
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ export function showAnyInviteErrors(
|
|||
// pointless for us to list who failed exactly.
|
||||
const ErrorDialog = sdk.getComponent("dialogs.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]),
|
||||
});
|
||||
return false;
|
||||
|
|
|
@ -15,8 +15,8 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {MatrixClientPeg} from './MatrixClientPeg';
|
||||
import {PushProcessor} from 'matrix-js-sdk/src/pushprocessor';
|
||||
import { MatrixClientPeg } from './MatrixClientPeg';
|
||||
import { PushProcessor } from 'matrix-js-sdk/src/pushprocessor';
|
||||
|
||||
export const ALL_MESSAGES_LOUD = 'all_messages_loud';
|
||||
export const ALL_MESSAGES = 'all_messages';
|
||||
|
@ -52,7 +52,7 @@ export function aggregateNotificationCount(rooms) {
|
|||
}
|
||||
}
|
||||
return result;
|
||||
}, {count: 0, highlight: false});
|
||||
}, { count: 0, highlight: false });
|
||||
}
|
||||
|
||||
export function getRoomHasBadge(room) {
|
||||
|
|
|
@ -104,7 +104,6 @@ export function setDMRoom(roomId: string, userId: string): Promise<void> {
|
|||
dmRoomMap[userId] = roomList;
|
||||
}
|
||||
|
||||
|
||||
return MatrixClientPeg.get().setAccountData('m.direct', dmRoomMap);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,12 +17,12 @@ limitations under the License.
|
|||
import url from 'url';
|
||||
import SettingsStore from "./settings/SettingsStore";
|
||||
import { Service, startTermsFlow, TermsInteractionCallback, TermsNotSignedError } from './Terms';
|
||||
import {MatrixClientPeg} from "./MatrixClientPeg";
|
||||
import { MatrixClientPeg } from "./MatrixClientPeg";
|
||||
import request from "browser-request";
|
||||
|
||||
import SdkConfig from "./SdkConfig";
|
||||
import {WidgetType} from "./widgets/WidgetType";
|
||||
import {SERVICE_TYPES} from "matrix-js-sdk/src/service-types";
|
||||
import { WidgetType } from "./widgets/WidgetType";
|
||||
import { SERVICE_TYPES } from "matrix-js-sdk/src/service-types";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
|
||||
// The version of the integration manager API we're intending to work with
|
||||
|
@ -109,7 +109,7 @@ export default class ScalarAuthClient {
|
|||
request({
|
||||
method: "GET",
|
||||
uri: url,
|
||||
qs: {scalar_token: token, v: imApiVersion},
|
||||
qs: { scalar_token: token, v: imApiVersion },
|
||||
json: true,
|
||||
}, (err, response, body) => {
|
||||
if (err) {
|
||||
|
@ -189,7 +189,7 @@ export default class ScalarAuthClient {
|
|||
request({
|
||||
method: 'POST',
|
||||
uri: scalarRestUrl + '/register',
|
||||
qs: {v: imApiVersion},
|
||||
qs: { v: imApiVersion },
|
||||
body: openidTokenObject,
|
||||
json: true,
|
||||
}, (err, response, body) => {
|
||||
|
|
|
@ -208,7 +208,6 @@ Example:
|
|||
]
|
||||
}
|
||||
|
||||
|
||||
membership_state AND bot_options
|
||||
--------------------------------
|
||||
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 dis from './dispatcher/dispatcher';
|
||||
import WidgetUtils from './utils/WidgetUtils';
|
||||
import RoomViewStore from './stores/RoomViewStore';
|
||||
import { _t } from './languageHandler';
|
||||
import {IntegrationManagers} from "./integrations/IntegrationManagers";
|
||||
import {WidgetType} from "./widgets/WidgetType";
|
||||
import {objectClone} from "./utils/objects";
|
||||
import { IntegrationManagers } from "./integrations/IntegrationManagers";
|
||||
import { WidgetType } from "./widgets/WidgetType";
|
||||
import { objectClone } from "./utils/objects";
|
||||
|
||||
function sendResponse(event, res) {
|
||||
const data = objectClone(event.data);
|
||||
|
@ -608,7 +607,7 @@ const onMessage = function(event) {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import EventIndexPeg from "./indexing/EventIndexPeg";
|
||||
import {MatrixClientPeg} from "./MatrixClientPeg";
|
||||
import { MatrixClientPeg } from "./MatrixClientPeg";
|
||||
|
||||
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 = {
|
||||
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
|
||||
// local indexes turn or the local index has exhausted its results.
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ import { ICryptoCallbacks, ISecretStorageKeyInfo } from 'matrix-js-sdk/src/matri
|
|||
import { MatrixClient } from 'matrix-js-sdk/src/client';
|
||||
import Modal from './Modal';
|
||||
import * as sdk from './index';
|
||||
import {MatrixClientPeg} from './MatrixClientPeg';
|
||||
import { MatrixClientPeg } from './MatrixClientPeg';
|
||||
import { deriveKey } from 'matrix-js-sdk/src/crypto/key_passphrase';
|
||||
import { decodeRecoveryKey } from 'matrix-js-sdk/src/crypto/recoverykey';
|
||||
import { _t } from './languageHandler';
|
||||
|
@ -135,7 +135,7 @@ async function getSecretStorageKey(
|
|||
|
||||
const keyFromCustomisations = SecurityCustomisations.getSecretStorageKey?.();
|
||||
if (keyFromCustomisations) {
|
||||
console.log("Using key from security customisations (secret storage)")
|
||||
console.log("Using key from security customisations (secret storage)");
|
||||
cacheSecretStorageKey(keyId, keyInfo, keyFromCustomisations);
|
||||
return [keyId, keyFromCustomisations];
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ export async function getDehydrationKey(
|
|||
): Promise<Uint8Array> {
|
||||
const keyFromCustomisations = SecurityCustomisations.getSecretStorageKey?.();
|
||||
if (keyFromCustomisations) {
|
||||
console.log("Using key from security customisations (dehydration)")
|
||||
console.log("Using key from security customisations (dehydration)");
|
||||
return keyFromCustomisations;
|
||||
}
|
||||
|
||||
|
@ -224,7 +224,7 @@ export async function getDehydrationKey(
|
|||
const key = await inputToKey(input);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//@flow
|
||||
/*
|
||||
Copyright 2017 Aviral Dasgupta
|
||||
|
||||
|
@ -15,10 +14,10 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {clamp} from "lodash";
|
||||
import {MatrixEvent} from "matrix-js-sdk/src/models/event";
|
||||
import { clamp } from "lodash";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
|
||||
import {SerializedPart} from "./editor/parts";
|
||||
import { SerializedPart } from "./editor/parts";
|
||||
import EditorModel from "./editor/model";
|
||||
|
||||
interface IHistoryItem {
|
||||
|
|
|
@ -21,21 +21,21 @@ import * as React from 'react';
|
|||
import { User } from "matrix-js-sdk/src/models/user";
|
||||
|
||||
import * as ContentHelpers from 'matrix-js-sdk/src/content-helpers';
|
||||
import {MatrixClientPeg} from './MatrixClientPeg';
|
||||
import { MatrixClientPeg } from './MatrixClientPeg';
|
||||
import dis from './dispatcher/dispatcher';
|
||||
import * as sdk from './index';
|
||||
import {_t, _td} from './languageHandler';
|
||||
import { _t, _td } from './languageHandler';
|
||||
import Modal from './Modal';
|
||||
import MultiInviter from './utils/MultiInviter';
|
||||
import { linkifyAndSanitizeHtml } from './HtmlUtils';
|
||||
import QuestionDialog from "./components/views/dialogs/QuestionDialog";
|
||||
import WidgetUtils from "./utils/WidgetUtils";
|
||||
import {textToHtmlRainbow} from "./utils/colour";
|
||||
import { textToHtmlRainbow } from "./utils/colour";
|
||||
import { getAddressType } from './UserAddress';
|
||||
import { abbreviateUrl } from './utils/UrlUtils';
|
||||
import { getDefaultIdentityServerUrl, useDefaultIdentityServer } from './utils/IdentityServerUtils';
|
||||
import {isPermalinkHost, parsePermalink} from "./utils/permalinks/Permalinks";
|
||||
import {inviteUsersToRoom} from "./RoomInvite";
|
||||
import { isPermalinkHost, parsePermalink } from "./utils/permalinks/Permalinks";
|
||||
import { inviteUsersToRoom } from "./RoomInvite";
|
||||
import { WidgetType } from "./widgets/WidgetType";
|
||||
import { Jitsi } from "./widgets/Jitsi";
|
||||
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 SdkConfig from "./SdkConfig";
|
||||
import SettingsStore from "./settings/SettingsStore";
|
||||
import {UIFeature} from "./settings/UIFeature";
|
||||
import {CHAT_EFFECTS} from "./effects"
|
||||
import { UIFeature } from "./settings/UIFeature";
|
||||
import { CHAT_EFFECTS } from "./effects";
|
||||
import CallHandler from "./CallHandler";
|
||||
import {guessAndSetDMRoom} from "./Rooms";
|
||||
import { guessAndSetDMRoom } from "./Rooms";
|
||||
|
||||
// XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816
|
||||
interface HTMLInputEvent extends Event {
|
||||
|
@ -143,11 +143,11 @@ export class Command {
|
|||
}
|
||||
|
||||
function reject(error) {
|
||||
return {error};
|
||||
return { error };
|
||||
}
|
||||
|
||||
function success(promise?: Promise<any>) {
|
||||
return {promise};
|
||||
return { promise };
|
||||
}
|
||||
|
||||
function successSync(value: any) {
|
||||
|
@ -271,8 +271,8 @@ export const Commands = [
|
|||
|
||||
const RoomUpgradeWarningDialog = sdk.getComponent("dialogs.RoomUpgradeWarningDialog");
|
||||
|
||||
const {finished} = Modal.createTrackedDialog('Slash Commands', 'upgrade room confirmation',
|
||||
RoomUpgradeWarningDialog, {roomId: roomId, targetVersion: args}, /*className=*/null,
|
||||
const { finished } = Modal.createTrackedDialog('Slash Commands', 'upgrade room confirmation',
|
||||
RoomUpgradeWarningDialog, { roomId: roomId, targetVersion: args }, /*className=*/null,
|
||||
/*isPriority=*/false, /*isStatic=*/true);
|
||||
|
||||
return success(finished.then(async ([resp]) => {
|
||||
|
@ -288,7 +288,7 @@ export const Commands = [
|
|||
if (resp.invite) {
|
||||
checkForUpgradeFn = async (newRoom) => {
|
||||
// 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;
|
||||
|
||||
const toInvite = [
|
||||
|
@ -370,7 +370,7 @@ export const Commands = [
|
|||
|
||||
return success(promise.then((url) => {
|
||||
if (!url) return;
|
||||
return MatrixClientPeg.get().sendStateEvent(roomId, 'm.room.avatar', {url}, '');
|
||||
return MatrixClientPeg.get().sendStateEvent(roomId, 'm.room.avatar', { url }, '');
|
||||
}));
|
||||
},
|
||||
category: CommandCategories.actions,
|
||||
|
@ -741,7 +741,7 @@ export const Commands = [
|
|||
Modal.createTrackedDialog('Slash Commands', 'User ignored', InfoDialog, {
|
||||
title: _t('Ignored user'),
|
||||
description: <div>
|
||||
<p>{ _t('You are now ignoring %(userId)s', {userId}) }</p>
|
||||
<p>{ _t('You are now ignoring %(userId)s', { userId }) }</p>
|
||||
</div>,
|
||||
});
|
||||
}),
|
||||
|
@ -772,7 +772,7 @@ export const Commands = [
|
|||
Modal.createTrackedDialog('Slash Commands', 'User unignored', InfoDialog, {
|
||||
title: _t('Unignored user'),
|
||||
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>,
|
||||
});
|
||||
}),
|
||||
|
@ -839,7 +839,7 @@ export const Commands = [
|
|||
description: _td('Opens the Developer Tools dialog'),
|
||||
runFn: function(roomId) {
|
||||
const DevtoolsDialog = sdk.getComponent('dialogs.DevtoolsDialog');
|
||||
Modal.createDialog(DevtoolsDialog, {roomId});
|
||||
Modal.createDialog(DevtoolsDialog, { roomId });
|
||||
return success();
|
||||
},
|
||||
category: CommandCategories.advanced,
|
||||
|
@ -951,7 +951,7 @@ export const Commands = [
|
|||
{
|
||||
_t('The signing key you provided matches the signing key you received ' +
|
||||
'from %(userId)s\'s session %(deviceId)s. Session marked as verified.',
|
||||
{userId, deviceId})
|
||||
{ userId, deviceId })
|
||||
}
|
||||
</p>
|
||||
</div>,
|
||||
|
@ -1172,11 +1172,11 @@ export const Commands = [
|
|||
};
|
||||
MatrixClientPeg.get().sendMessage(roomId, content);
|
||||
}
|
||||
dis.dispatch({action: `effects.${effect.command}`});
|
||||
dis.dispatch({ action: `effects.${effect.command}` });
|
||||
})());
|
||||
},
|
||||
category: CommandCategories.effects,
|
||||
})
|
||||
});
|
||||
}),
|
||||
];
|
||||
|
||||
|
@ -1205,7 +1205,7 @@ export function parseCommandString(input: string) {
|
|||
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.
|
||||
*/
|
||||
export function getCommand(input: string) {
|
||||
const {cmd, args} = parseCommandString(input);
|
||||
const { cmd, args } = parseCommandString(input);
|
||||
|
||||
if (CommandMap.has(cmd) && CommandMap.get(cmd).isEnabled()) {
|
||||
return {
|
||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import {MatrixClientPeg} from './MatrixClientPeg';
|
||||
import { MatrixClientPeg } from './MatrixClientPeg';
|
||||
import * as sdk from '.';
|
||||
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
|
||||
// things they've not agreed to yet.
|
||||
const unagreedPoliciesAndServicePairs = [];
|
||||
for (const {service, policies} of policiesAndServicePairs) {
|
||||
for (const { service, policies } of policiesAndServicePairs) {
|
||||
const unagreedPolicies = {};
|
||||
for (const [policyName, policy] of Object.entries(policies)) {
|
||||
let policyAgreed = false;
|
||||
|
@ -131,7 +131,7 @@ export async function startTermsFlow(
|
|||
if (!policyAgreed) unagreedPolicies[policyName] = policy;
|
||||
}
|
||||
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
|
||||
if (agreedUrlSet.size !== numAcceptedBeforeAgreement) {
|
||||
const newAcceptedTerms = {accepted: Array.from(agreedUrlSet)};
|
||||
const newAcceptedTerms = { accepted: Array.from(agreedUrlSet) };
|
||||
await MatrixClientPeg.get().setAccountData('m.accepted_terms', newAcceptedTerms);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,13 +15,13 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {MatrixClientPeg} from './MatrixClientPeg';
|
||||
import { MatrixClientPeg } from './MatrixClientPeg';
|
||||
import { _t } from './languageHandler';
|
||||
import * as Roles from './Roles';
|
||||
import {isValid3pidInvite} from "./RoomInvite";
|
||||
import { isValid3pidInvite } from "./RoomInvite";
|
||||
import SettingsStore from "./settings/SettingsStore";
|
||||
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 { 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 { RightPanelPhases } from './stores/RightPanelStorePhases';
|
||||
import { Action } from './dispatcher/actions';
|
||||
import defaultDispatcher from './dispatcher/dispatcher';
|
||||
|
@ -112,7 +112,7 @@ function textForMemberEvent(ev): () => string | null {
|
|||
targetName,
|
||||
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") {
|
||||
return () => reason
|
||||
? _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();
|
||||
|
||||
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) {
|
||||
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 {
|
||||
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 {
|
||||
|
@ -183,9 +183,9 @@ function textForGuestAccessEvent(ev): () => string | null {
|
|||
const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
|
||||
switch (ev.getContent().guest_access) {
|
||||
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":
|
||||
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:
|
||||
// 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', {
|
||||
|
@ -237,9 +237,9 @@ function textForServerACLEvent(ev): () => string | null {
|
|||
|
||||
let getText = null;
|
||||
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 {
|
||||
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)) {
|
||||
|
@ -262,7 +262,7 @@ function textForMessageEvent(ev): () => string | null {
|
|||
if (ev.getContent().msgtype === "m.emote") {
|
||||
message = "* " + senderDisplayName + " " + message;
|
||||
} 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;
|
||||
};
|
||||
|
@ -323,7 +323,7 @@ function textForCallAnswerEvent(event): () => string | null {
|
|||
return () => {
|
||||
const senderName = event.sender ? event.sender.name : _t('Someone');
|
||||
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)
|
||||
getReason = () => '';
|
||||
} 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 {
|
||||
return () => {
|
||||
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) {
|
||||
case 'invited':
|
||||
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':
|
||||
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':
|
||||
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':
|
||||
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:
|
||||
return () => _t('%(senderName)s made future room history visible to unknown (%(visibility)s).', {
|
||||
senderName,
|
||||
|
@ -492,7 +492,7 @@ const onPinnedMessagesClick = (): void => {
|
|||
phase: RightPanelPhases.PinnedMessages,
|
||||
allowClose: false,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function textForPinnedEvent(event: MatrixEvent, allowJSX: boolean): () => string | JSX.Element | null {
|
||||
if (!SettingsStore.getValue("feature_pinning")) return null;
|
||||
|
@ -517,8 +517,8 @@ function textForPinnedEvent(event: MatrixEvent, allowJSX: boolean): () => string
|
|||
|
||||
function textForWidgetEvent(event): () => string | null {
|
||||
const senderName = event.getSender();
|
||||
const {name: prevName, type: prevType, url: prevUrl} = event.getPrevContent();
|
||||
const {name, type, url} = event.getContent() || {};
|
||||
const { name: prevName, type: prevType, url: prevUrl } = event.getPrevContent();
|
||||
const { name, type, url } = event.getContent() || {};
|
||||
|
||||
let widgetName = name || prevName || type || prevType || '';
|
||||
// Apply sentence case to widget name
|
||||
|
@ -547,68 +547,68 @@ function textForWidgetEvent(event): () => string | null {
|
|||
|
||||
function textForWidgetLayoutEvent(event): () => string | null {
|
||||
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 {
|
||||
const senderName = event.getSender();
|
||||
const {entity: prevEntity} = event.getPrevContent();
|
||||
const {entity, recommendation, reason} = event.getContent();
|
||||
const { entity: prevEntity } = event.getPrevContent();
|
||||
const { entity, recommendation, reason } = event.getContent();
|
||||
|
||||
// Rule removed
|
||||
if (!entity) {
|
||||
if (USER_RULE_TYPES.includes(event.getType())) {
|
||||
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())) {
|
||||
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())) {
|
||||
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.
|
||||
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
|
||||
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
|
||||
if (entity === prevEntity) {
|
||||
if (USER_RULE_TYPES.includes(event.getType())) {
|
||||
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())) {
|
||||
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())) {
|
||||
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.
|
||||
return () => _t("%(senderName)s updated a ban rule matching %(glob)s for %(reason)s",
|
||||
{senderName, glob: entity, reason});
|
||||
{ senderName, glob: entity, reason });
|
||||
}
|
||||
|
||||
// New rule
|
||||
if (!prevEntity) {
|
||||
if (USER_RULE_TYPES.includes(event.getType())) {
|
||||
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())) {
|
||||
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())) {
|
||||
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.
|
||||
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
|
||||
|
@ -616,25 +616,25 @@ function textForMjolnirEvent(event): () => string | null {
|
|||
return () => _t(
|
||||
"%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching " +
|
||||
"%(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())) {
|
||||
return () => _t(
|
||||
"%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching " +
|
||||
"%(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())) {
|
||||
return () => _t(
|
||||
"%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching " +
|
||||
"%(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.
|
||||
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 {
|
||||
|
|
458
src/Tinter.js
458
src/Tinter.js
|
@ -1,458 +0,0 @@
|
|||
/*
|
||||
Copyright 2015 OpenMarket Ltd
|
||||
Copyright 2017 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
const DEBUG = 0;
|
||||
|
||||
// utility to turn #rrggbb or rgb(r,g,b) into [red,green,blue]
|
||||
function colorToRgb(color) {
|
||||
if (!color) {
|
||||
return [0, 0, 0];
|
||||
}
|
||||
|
||||
if (color[0] === '#') {
|
||||
color = color.slice(1);
|
||||
if (color.length === 3) {
|
||||
color = color[0] + color[0] +
|
||||
color[1] + color[1] +
|
||||
color[2] + color[2];
|
||||
}
|
||||
const val = parseInt(color, 16);
|
||||
const r = (val >> 16) & 255;
|
||||
const g = (val >> 8) & 255;
|
||||
const b = val & 255;
|
||||
return [r, g, b];
|
||||
} else {
|
||||
const match = color.match(/rgb\((.*?),(.*?),(.*?)\)/);
|
||||
if (match) {
|
||||
return [
|
||||
parseInt(match[1]),
|
||||
parseInt(match[2]),
|
||||
parseInt(match[3]),
|
||||
];
|
||||
}
|
||||
}
|
||||
return [0, 0, 0];
|
||||
}
|
||||
|
||||
// utility to turn [red,green,blue] into #rrggbb
|
||||
function rgbToColor(rgb) {
|
||||
const val = (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];
|
||||
return '#' + (0x1000000 + val).toString(16).slice(1);
|
||||
}
|
||||
|
||||
class Tinter {
|
||||
constructor() {
|
||||
// The default colour keys to be replaced as referred to in CSS
|
||||
// (should be overridden by .mx_theme_accentColor and .mx_theme_secondaryAccentColor)
|
||||
this.keyRgb = [
|
||||
"rgb(118, 207, 166)", // Vector Green
|
||||
"rgb(234, 245, 240)", // Vector Light Green
|
||||
"rgb(211, 239, 225)", // roomsublist-label-bg-color (20% Green overlaid on Light Green)
|
||||
];
|
||||
|
||||
// Some algebra workings for calculating the tint % of Vector Green & Light Green
|
||||
// x * 118 + (1 - x) * 255 = 234
|
||||
// x * 118 + 255 - 255 * x = 234
|
||||
// x * 118 - x * 255 = 234 - 255
|
||||
// (255 - 118) x = 255 - 234
|
||||
// x = (255 - 234) / (255 - 118) = 0.16
|
||||
|
||||
// The colour keys to be replaced as referred to in SVGs
|
||||
this.keyHex = [
|
||||
"#76CFA6", // Vector Green
|
||||
"#EAF5F0", // Vector Light Green
|
||||
"#D3EFE1", // roomsublist-label-bg-color (20% Green overlaid on Light Green)
|
||||
"#FFFFFF", // white highlights of the SVGs (for switching to dark theme)
|
||||
"#000000", // black lowlights of the SVGs (for switching to dark theme)
|
||||
];
|
||||
|
||||
// track the replacement colours actually being used
|
||||
// defaults to our keys.
|
||||
this.colors = [
|
||||
this.keyHex[0],
|
||||
this.keyHex[1],
|
||||
this.keyHex[2],
|
||||
this.keyHex[3],
|
||||
this.keyHex[4],
|
||||
];
|
||||
|
||||
// track the most current tint request inputs (which may differ from the
|
||||
// end result stored in this.colors
|
||||
this.currentTint = [
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
];
|
||||
|
||||
this.cssFixups = [
|
||||
// { theme: {
|
||||
// style: a style object that should be fixed up taken from a stylesheet
|
||||
// attr: name of the attribute to be clobbered, e.g. 'color'
|
||||
// index: ordinal of primary, secondary or tertiary
|
||||
// },
|
||||
// }
|
||||
];
|
||||
|
||||
// CSS attributes to be fixed up
|
||||
this.cssAttrs = [
|
||||
"color",
|
||||
"backgroundColor",
|
||||
"borderColor",
|
||||
"borderTopColor",
|
||||
"borderBottomColor",
|
||||
"borderLeftColor",
|
||||
];
|
||||
|
||||
this.svgAttrs = [
|
||||
"fill",
|
||||
"stroke",
|
||||
];
|
||||
|
||||
// List of functions to call when the tint changes.
|
||||
this.tintables = [];
|
||||
|
||||
// the currently loaded theme (if any)
|
||||
this.theme = undefined;
|
||||
|
||||
// whether to force a tint (e.g. after changing theme)
|
||||
this.forceTint = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to fire when the tint changes.
|
||||
* This is used to rewrite the tintable SVGs with the new tint.
|
||||
*
|
||||
* It's not possible to unregister a tintable callback. So this can only be
|
||||
* used to register a static callback. If a set of tintables will change
|
||||
* over time then the best bet is to register a single callback for the
|
||||
* entire set.
|
||||
*
|
||||
* To ensure the tintable work happens at least once, it is also called as
|
||||
* part of registration.
|
||||
*
|
||||
* @param {Function} tintable Function to call when the tint changes.
|
||||
*/
|
||||
registerTintable(tintable) {
|
||||
this.tintables.push(tintable);
|
||||
tintable();
|
||||
}
|
||||
|
||||
getKeyRgb() {
|
||||
return this.keyRgb;
|
||||
}
|
||||
|
||||
tint(primaryColor, secondaryColor, tertiaryColor) {
|
||||
return;
|
||||
// eslint-disable-next-line no-unreachable
|
||||
this.currentTint[0] = primaryColor;
|
||||
this.currentTint[1] = secondaryColor;
|
||||
this.currentTint[2] = tertiaryColor;
|
||||
|
||||
this.calcCssFixups();
|
||||
|
||||
if (DEBUG) {
|
||||
console.log("Tinter.tint(" + primaryColor + ", " +
|
||||
secondaryColor + ", " +
|
||||
tertiaryColor + ")");
|
||||
}
|
||||
|
||||
if (!primaryColor) {
|
||||
primaryColor = this.keyRgb[0];
|
||||
secondaryColor = this.keyRgb[1];
|
||||
tertiaryColor = this.keyRgb[2];
|
||||
}
|
||||
|
||||
if (!secondaryColor) {
|
||||
const x = 0.16; // average weighting factor calculated from vector green & light green
|
||||
const rgb = colorToRgb(primaryColor);
|
||||
rgb[0] = x * rgb[0] + (1 - x) * 255;
|
||||
rgb[1] = x * rgb[1] + (1 - x) * 255;
|
||||
rgb[2] = x * rgb[2] + (1 - x) * 255;
|
||||
secondaryColor = rgbToColor(rgb);
|
||||
}
|
||||
|
||||
if (!tertiaryColor) {
|
||||
const x = 0.19;
|
||||
const rgb1 = colorToRgb(primaryColor);
|
||||
const rgb2 = colorToRgb(secondaryColor);
|
||||
rgb1[0] = x * rgb1[0] + (1 - x) * rgb2[0];
|
||||
rgb1[1] = x * rgb1[1] + (1 - x) * rgb2[1];
|
||||
rgb1[2] = x * rgb1[2] + (1 - x) * rgb2[2];
|
||||
tertiaryColor = rgbToColor(rgb1);
|
||||
}
|
||||
|
||||
if (this.forceTint == false &&
|
||||
this.colors[0] === primaryColor &&
|
||||
this.colors[1] === secondaryColor &&
|
||||
this.colors[2] === tertiaryColor) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.forceTint = false;
|
||||
|
||||
this.colors[0] = primaryColor;
|
||||
this.colors[1] = secondaryColor;
|
||||
this.colors[2] = tertiaryColor;
|
||||
|
||||
if (DEBUG) {
|
||||
console.log("Tinter.tint final: (" + primaryColor + ", " +
|
||||
secondaryColor + ", " +
|
||||
tertiaryColor + ")");
|
||||
}
|
||||
|
||||
// go through manually fixing up the stylesheets.
|
||||
this.applyCssFixups();
|
||||
|
||||
// tell all the SVGs to go fix themselves up
|
||||
// we don't do this as a dispatch otherwise it will visually lag
|
||||
this.tintables.forEach(function(tintable) {
|
||||
tintable();
|
||||
});
|
||||
}
|
||||
|
||||
tintSvgWhite(whiteColor) {
|
||||
this.currentTint[3] = whiteColor;
|
||||
|
||||
if (!whiteColor) {
|
||||
whiteColor = this.colors[3];
|
||||
}
|
||||
if (this.colors[3] === whiteColor) {
|
||||
return;
|
||||
}
|
||||
this.colors[3] = whiteColor;
|
||||
this.tintables.forEach(function(tintable) {
|
||||
tintable();
|
||||
});
|
||||
}
|
||||
|
||||
tintSvgBlack(blackColor) {
|
||||
this.currentTint[4] = blackColor;
|
||||
|
||||
if (!blackColor) {
|
||||
blackColor = this.colors[4];
|
||||
}
|
||||
if (this.colors[4] === blackColor) {
|
||||
return;
|
||||
}
|
||||
this.colors[4] = blackColor;
|
||||
this.tintables.forEach(function(tintable) {
|
||||
tintable();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
setTheme(theme) {
|
||||
this.theme = theme;
|
||||
|
||||
// update keyRgb from the current theme CSS itself, if it defines it
|
||||
if (document.getElementById('mx_theme_accentColor')) {
|
||||
this.keyRgb[0] = window.getComputedStyle(
|
||||
document.getElementById('mx_theme_accentColor')).color;
|
||||
}
|
||||
if (document.getElementById('mx_theme_secondaryAccentColor')) {
|
||||
this.keyRgb[1] = window.getComputedStyle(
|
||||
document.getElementById('mx_theme_secondaryAccentColor')).color;
|
||||
}
|
||||
if (document.getElementById('mx_theme_tertiaryAccentColor')) {
|
||||
this.keyRgb[2] = window.getComputedStyle(
|
||||
document.getElementById('mx_theme_tertiaryAccentColor')).color;
|
||||
}
|
||||
|
||||
this.calcCssFixups();
|
||||
this.forceTint = true;
|
||||
|
||||
this.tint(this.currentTint[0], this.currentTint[1], this.currentTint[2]);
|
||||
|
||||
if (theme === 'dark') {
|
||||
// abuse the tinter to change all the SVG's #fff to #2d2d2d
|
||||
// XXX: obviously this shouldn't be hardcoded here.
|
||||
this.tintSvgWhite('#2d2d2d');
|
||||
this.tintSvgBlack('#dddddd');
|
||||
} else {
|
||||
this.tintSvgWhite('#ffffff');
|
||||
this.tintSvgBlack('#000000');
|
||||
}
|
||||
}
|
||||
|
||||
calcCssFixups() {
|
||||
// cache our fixups
|
||||
if (this.cssFixups[this.theme]) return;
|
||||
|
||||
if (DEBUG) {
|
||||
console.debug("calcCssFixups start for " + this.theme + " (checking " +
|
||||
document.styleSheets.length +
|
||||
" stylesheets)");
|
||||
}
|
||||
|
||||
this.cssFixups[this.theme] = [];
|
||||
|
||||
for (let i = 0; i < document.styleSheets.length; i++) {
|
||||
const ss = document.styleSheets[i];
|
||||
try {
|
||||
if (!ss) continue; // well done safari >:(
|
||||
// Chromium apparently sometimes returns null here; unsure why.
|
||||
// see $14534907369972FRXBx:matrix.org in HQ
|
||||
// ...ah, it's because there's a third party extension like
|
||||
// privacybadger inserting its own stylesheet in there with a
|
||||
// resource:// URI or something which results in a XSS error.
|
||||
// See also #vector:matrix.org/$145357669685386ebCfr:matrix.org
|
||||
// ...except some browsers apparently return stylesheets without
|
||||
// hrefs, which we have no choice but ignore right now
|
||||
|
||||
// XXX seriously? we are hardcoding the name of vector's CSS file in
|
||||
// here?
|
||||
//
|
||||
// Why do we need to limit it to vector's CSS file anyway - if there
|
||||
// are other CSS files affecting the doc don't we want to apply the
|
||||
// same transformations to them?
|
||||
//
|
||||
// Iterating through the CSS looking for matches to hack on feels
|
||||
// pretty horrible anyway. And what if the application skin doesn't use
|
||||
// Vector Green as its primary color?
|
||||
// --richvdh
|
||||
|
||||
// Yes, tinting assumes that you are using the Element skin for now.
|
||||
// The right solution will be to move the CSS over to react-sdk.
|
||||
// And yes, the default assets for the base skin might as well use
|
||||
// Vector Green as any other colour.
|
||||
// --matthew
|
||||
|
||||
// stylesheets we don't have permission to access (eg. ones from extensions) have a null
|
||||
// href and will throw exceptions if we try to access their rules.
|
||||
if (!ss.href || !ss.href.match(new RegExp('/theme-' + this.theme + '.css$'))) continue;
|
||||
if (ss.disabled) continue;
|
||||
if (!ss.cssRules) continue;
|
||||
|
||||
if (DEBUG) console.debug("calcCssFixups checking " + ss.cssRules.length + " rules for " + ss.href);
|
||||
|
||||
for (let j = 0; j < ss.cssRules.length; j++) {
|
||||
const rule = ss.cssRules[j];
|
||||
if (!rule.style) continue;
|
||||
if (rule.selectorText && rule.selectorText.match(/#mx_theme/)) continue;
|
||||
for (let k = 0; k < this.cssAttrs.length; k++) {
|
||||
const attr = this.cssAttrs[k];
|
||||
for (let l = 0; l < this.keyRgb.length; l++) {
|
||||
if (rule.style[attr] === this.keyRgb[l]) {
|
||||
this.cssFixups[this.theme].push({
|
||||
style: rule.style,
|
||||
attr: attr,
|
||||
index: l,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Catch any random exceptions that happen here: all sorts of things can go
|
||||
// wrong with this (nulls, SecurityErrors) and mostly it's for other
|
||||
// stylesheets that we don't want to proces anyway. We should not propagate an
|
||||
// exception out since this will cause the app to fail to start.
|
||||
console.log("Failed to calculate CSS fixups for a stylesheet: " + ss.href, e);
|
||||
}
|
||||
}
|
||||
if (DEBUG) {
|
||||
console.log("calcCssFixups end (" +
|
||||
this.cssFixups[this.theme].length +
|
||||
" fixups)");
|
||||
}
|
||||
}
|
||||
|
||||
applyCssFixups() {
|
||||
if (DEBUG) {
|
||||
console.log("applyCssFixups start (" +
|
||||
this.cssFixups[this.theme].length +
|
||||
" fixups)");
|
||||
}
|
||||
for (let i = 0; i < this.cssFixups[this.theme].length; i++) {
|
||||
const cssFixup = this.cssFixups[this.theme][i];
|
||||
try {
|
||||
cssFixup.style[cssFixup.attr] = this.colors[cssFixup.index];
|
||||
} catch (e) {
|
||||
// Firefox Quantum explodes if you manually edit the CSS in the
|
||||
// inspector and then try to do a tint, as apparently all the
|
||||
// fixups are then stale.
|
||||
console.error("Failed to apply cssFixup in Tinter! ", e.name);
|
||||
}
|
||||
}
|
||||
if (DEBUG) console.log("applyCssFixups end");
|
||||
}
|
||||
|
||||
// XXX: we could just move this all into TintableSvg, but as it's so similar
|
||||
// to the CSS fixup stuff in Tinter (just that the fixups are stored in TintableSvg)
|
||||
// keeping it here for now.
|
||||
calcSvgFixups(svgs) {
|
||||
// go through manually fixing up SVG colours.
|
||||
// we could do this by stylesheets, but keeping the stylesheets
|
||||
// updated would be a PITA, so just brute-force search for the
|
||||
// key colour; cache the element and apply.
|
||||
|
||||
if (DEBUG) console.log("calcSvgFixups start for " + svgs);
|
||||
const fixups = [];
|
||||
for (let i = 0; i < svgs.length; i++) {
|
||||
let svgDoc;
|
||||
try {
|
||||
svgDoc = svgs[i].contentDocument;
|
||||
} catch (e) {
|
||||
let msg = 'Failed to get svg.contentDocument of ' + svgs[i].toString();
|
||||
if (e.message) {
|
||||
msg += e.message;
|
||||
}
|
||||
if (e.stack) {
|
||||
msg += ' | stack: ' + e.stack;
|
||||
}
|
||||
console.error(msg);
|
||||
}
|
||||
if (!svgDoc) continue;
|
||||
const tags = svgDoc.getElementsByTagName("*");
|
||||
for (let j = 0; j < tags.length; j++) {
|
||||
const tag = tags[j];
|
||||
for (let k = 0; k < this.svgAttrs.length; k++) {
|
||||
const attr = this.svgAttrs[k];
|
||||
for (let l = 0; l < this.keyHex.length; l++) {
|
||||
if (tag.getAttribute(attr) &&
|
||||
tag.getAttribute(attr).toUpperCase() === this.keyHex[l]) {
|
||||
fixups.push({
|
||||
node: tag,
|
||||
attr: attr,
|
||||
index: l,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (DEBUG) console.log("calcSvgFixups end");
|
||||
|
||||
return fixups;
|
||||
}
|
||||
|
||||
applySvgFixups(fixups) {
|
||||
if (DEBUG) console.log("applySvgFixups start for " + fixups);
|
||||
for (let i = 0; i < fixups.length; i++) {
|
||||
const svgFixup = fixups[i];
|
||||
svgFixup.node.setAttribute(svgFixup.attr, this.colors[svgFixup.index]);
|
||||
}
|
||||
if (DEBUG) console.log("applySvgFixups end");
|
||||
}
|
||||
}
|
||||
|
||||
if (global.singletonTinter === undefined) {
|
||||
global.singletonTinter = new Tinter();
|
||||
}
|
||||
export default global.singletonTinter;
|
|
@ -191,10 +191,10 @@ export default class UserActivity {
|
|||
this.lastScreenY = event.screenY;
|
||||
}
|
||||
|
||||
dis.dispatch({action: 'user_activity'});
|
||||
dis.dispatch({ action: 'user_activity' });
|
||||
if (!this.activeNowTimeout.isRunning()) {
|
||||
this.activeNowTimeout.start();
|
||||
dis.dispatch({action: 'user_activity_start'});
|
||||
dis.dispatch({ action: 'user_activity_start' });
|
||||
|
||||
UserActivity.runTimersUntilTimeout(this.attachedActiveNowTimers, this.activeNowTimeout);
|
||||
} else {
|
||||
|
|
|
@ -14,10 +14,10 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {Room} from "matrix-js-sdk/src/models/room";
|
||||
import {RoomMember} from "matrix-js-sdk/src/models/room-member";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||
|
||||
import {MatrixClientPeg} from "./MatrixClientPeg";
|
||||
import { MatrixClientPeg } from "./MatrixClientPeg";
|
||||
import { _t } from './languageHandler';
|
||||
|
||||
export function usersTypingApartFromMeAndIgnored(room: Room): RoomMember[] {
|
||||
|
@ -61,7 +61,7 @@ export function whoIsTypingString(whoIsTyping: RoomMember[], limit: number): str
|
|||
if (whoIsTyping.length === 0) {
|
||||
return '';
|
||||
} 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);
|
||||
|
@ -73,6 +73,6 @@ export function whoIsTypingString(whoIsTyping: RoomMember[], limit: number): str
|
|||
});
|
||||
} else {
|
||||
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 });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import classNames from "classnames";
|
|||
import * as sdk from "../index";
|
||||
import Modal from "../Modal";
|
||||
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
|
||||
_td("Navigation");
|
||||
|
@ -332,7 +332,7 @@ const keyIcon: Record<string, string> = {
|
|||
|
||||
const Shortcut: React.FC<{
|
||||
shortcut: IShortcut;
|
||||
}> = ({shortcut}) => {
|
||||
}> = ({ shortcut }) => {
|
||||
const classes = classNames({
|
||||
"mx_KeyboardShortcutsDialog_inline": shortcut.keybinds.every(k => !k.modifiers || k.modifiers.length === 0),
|
||||
});
|
||||
|
|
|
@ -26,8 +26,8 @@ import React, {
|
|||
Dispatch,
|
||||
} from "react";
|
||||
|
||||
import {Key} from "../Keyboard";
|
||||
import {FocusHandler, Ref} from "./roving/types";
|
||||
import { Key } from "../Keyboard";
|
||||
import { FocusHandler, Ref } from "./roving/types";
|
||||
|
||||
/**
|
||||
* Module to simplify implementing the Roving TabIndex accessibility technique
|
||||
|
@ -156,13 +156,13 @@ interface IProps {
|
|||
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, {
|
||||
activeRef: null,
|
||||
refs: [],
|
||||
});
|
||||
|
||||
const context = useMemo<IContext>(() => ({state, dispatch}), [state]);
|
||||
const context = useMemo<IContext>(() => ({ state, dispatch }), [state]);
|
||||
|
||||
const onKeyDownHandler = useCallback((ev) => {
|
||||
let handled = false;
|
||||
|
@ -196,7 +196,7 @@ export const RovingTabIndexProvider: React.FC<IProps> = ({children, handleHomeEn
|
|||
}, [context.state, onKeyDown, handleHomeEnd]);
|
||||
|
||||
return <RovingTabIndexContext.Provider value={context}>
|
||||
{ children({onKeyDownHandler}) }
|
||||
{ children({ onKeyDownHandler }) }
|
||||
</RovingTabIndexContext.Provider>;
|
||||
};
|
||||
|
||||
|
@ -218,13 +218,13 @@ export const useRovingTabIndex = (inputRef?: Ref): [FocusHandler, boolean, Ref]
|
|||
useLayoutEffect(() => {
|
||||
context.dispatch({
|
||||
type: Type.Register,
|
||||
payload: {ref},
|
||||
payload: { ref },
|
||||
});
|
||||
// teardown
|
||||
return () => {
|
||||
context.dispatch({
|
||||
type: Type.Unregister,
|
||||
payload: {ref},
|
||||
payload: { ref },
|
||||
});
|
||||
};
|
||||
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
@ -232,7 +232,7 @@ export const useRovingTabIndex = (inputRef?: Ref): [FocusHandler, boolean, Ref]
|
|||
const onFocus = useCallback(() => {
|
||||
context.dispatch({
|
||||
type: Type.SetFocus,
|
||||
payload: {ref},
|
||||
payload: { ref },
|
||||
});
|
||||
}, [ref, context]);
|
||||
|
||||
|
@ -241,6 +241,6 @@ export const useRovingTabIndex = (inputRef?: Ref): [FocusHandler, boolean, Ref]
|
|||
};
|
||||
|
||||
// re-export the semantic helper components for simplicity
|
||||
export {RovingTabIndexWrapper} from "./roving/RovingTabIndexWrapper";
|
||||
export {RovingAccessibleButton} from "./roving/RovingAccessibleButton";
|
||||
export {RovingAccessibleTooltipButton} from "./roving/RovingAccessibleTooltipButton";
|
||||
export { RovingTabIndexWrapper } from "./roving/RovingTabIndexWrapper";
|
||||
export { RovingAccessibleButton } from "./roving/RovingAccessibleButton";
|
||||
export { RovingAccessibleTooltipButton } from "./roving/RovingAccessibleTooltipButton";
|
||||
|
|
|
@ -16,8 +16,8 @@ limitations under the License.
|
|||
|
||||
import React from "react";
|
||||
|
||||
import {IState, RovingTabIndexProvider} from "./RovingTabIndex";
|
||||
import {Key} from "../Keyboard";
|
||||
import { IState, RovingTabIndexProvider } from "./RovingTabIndex";
|
||||
import { Key } from "../Keyboard";
|
||||
|
||||
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.
|
||||
// https://www.w3.org/TR/wai-aria-practices-1.1/#toolbar
|
||||
// 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 target = ev.target as HTMLElement;
|
||||
// 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}>
|
||||
{({onKeyDownHandler}) => <div {...props} onKeyDown={onKeyDownHandler} role="toolbar">
|
||||
{({ onKeyDownHandler }) => <div {...props} onKeyDown={onKeyDownHandler} role="toolbar">
|
||||
{ children }
|
||||
</div>}
|
||||
</RovingTabIndexProvider>;
|
||||
|
|
|
@ -23,7 +23,7 @@ interface IProps extends React.HTMLAttributes<HTMLDivElement> {
|
|||
}
|
||||
|
||||
// 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}>
|
||||
{ children }
|
||||
</div>;
|
||||
|
|
|
@ -27,7 +27,7 @@ interface IProps extends React.ComponentProps<typeof AccessibleButton> {
|
|||
}
|
||||
|
||||
// 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;
|
||||
|
||||
if (tooltip) {
|
||||
|
|
|
@ -26,7 +26,7 @@ interface IProps extends React.ComponentProps<typeof AccessibleButton> {
|
|||
}
|
||||
|
||||
// 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 (
|
||||
<AccessibleButton
|
||||
{...props}
|
||||
|
|
|
@ -26,7 +26,7 @@ interface IProps extends React.ComponentProps<typeof AccessibleButton> {
|
|||
}
|
||||
|
||||
// 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 (
|
||||
<AccessibleButton
|
||||
{...props}
|
||||
|
|
|
@ -18,7 +18,7 @@ limitations under the License.
|
|||
|
||||
import React from "react";
|
||||
|
||||
import {Key} from "../../Keyboard";
|
||||
import { Key } from "../../Keyboard";
|
||||
import StyledCheckbox from "../../components/views/elements/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
|
||||
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) => {
|
||||
if (e.key === Key.ENTER || e.key === Key.SPACE) {
|
||||
e.stopPropagation();
|
||||
|
|
|
@ -18,7 +18,7 @@ limitations under the License.
|
|||
|
||||
import React from "react";
|
||||
|
||||
import {Key} from "../../Keyboard";
|
||||
import { Key } from "../../Keyboard";
|
||||
import StyledRadioButton from "../../components/views/elements/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
|
||||
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) => {
|
||||
if (e.key === Key.ENTER || e.key === Key.SPACE) {
|
||||
e.stopPropagation();
|
||||
|
|
|
@ -17,15 +17,15 @@ limitations under the License.
|
|||
import React from "react";
|
||||
|
||||
import AccessibleButton from "../../components/views/elements/AccessibleButton";
|
||||
import {useRovingTabIndex} from "../RovingTabIndex";
|
||||
import {Ref} from "./types";
|
||||
import { useRovingTabIndex } from "../RovingTabIndex";
|
||||
import { Ref } from "./types";
|
||||
|
||||
interface IProps extends Omit<React.ComponentProps<typeof AccessibleButton>, "onFocus" | "inputRef" | "tabIndex"> {
|
||||
inputRef?: Ref;
|
||||
}
|
||||
|
||||
// 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);
|
||||
return <AccessibleButton {...props} onFocus={onFocus} inputRef={ref} tabIndex={isActive ? 0 : -1} />;
|
||||
};
|
||||
|
|
|
@ -17,8 +17,8 @@ limitations under the License.
|
|||
import React from "react";
|
||||
|
||||
import AccessibleTooltipButton from "../../components/views/elements/AccessibleTooltipButton";
|
||||
import {useRovingTabIndex} from "../RovingTabIndex";
|
||||
import {Ref} from "./types";
|
||||
import { useRovingTabIndex } from "../RovingTabIndex";
|
||||
import { Ref } from "./types";
|
||||
|
||||
type ATBProps = React.ComponentProps<typeof AccessibleTooltipButton>;
|
||||
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.
|
||||
export const RovingAccessibleTooltipButton: React.FC<IProps> = ({inputRef, ...props}) => {
|
||||
export const RovingAccessibleTooltipButton: React.FC<IProps> = ({ inputRef, ...props }) => {
|
||||
const [onFocus, isActive, ref] = useRovingTabIndex(inputRef);
|
||||
return <AccessibleTooltipButton {...props} onFocus={onFocus} inputRef={ref} tabIndex={isActive ? 0 : -1} />;
|
||||
};
|
||||
|
|
|
@ -16,8 +16,8 @@ limitations under the License.
|
|||
|
||||
import React from "react";
|
||||
|
||||
import {useRovingTabIndex} from "../RovingTabIndex";
|
||||
import {FocusHandler, Ref} from "./types";
|
||||
import { useRovingTabIndex } from "../RovingTabIndex";
|
||||
import { FocusHandler, Ref } from "./types";
|
||||
|
||||
interface IProps {
|
||||
inputRef?: Ref;
|
||||
|
@ -29,7 +29,7 @@ interface IProps {
|
|||
}
|
||||
|
||||
// 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);
|
||||
return children({onFocus, isActive, ref});
|
||||
return children({ onFocus, isActive, ref });
|
||||
};
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {RefObject} from "react";
|
||||
import { RefObject } from "react";
|
||||
|
||||
export type Ref = RefObject<HTMLElement>;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ import { Room } from "matrix-js-sdk/src/models/room";
|
|||
import { EventTimeline } from "matrix-js-sdk/src/models/event-timeline";
|
||||
|
||||
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
|
||||
// become dispatches in the same place.
|
||||
|
|
|
@ -112,7 +112,7 @@ export default class RoomListActions {
|
|||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
console.error("Failed to remove tag " + oldTag + " from room: " + err);
|
||||
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')),
|
||||
});
|
||||
});
|
||||
|
@ -132,7 +132,7 @@ export default class RoomListActions {
|
|||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
console.error("Failed to add tag " + newTag + " to room: " + err);
|
||||
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')),
|
||||
});
|
||||
|
||||
|
|
|
@ -53,11 +53,11 @@ export default class TagOrderActions {
|
|||
Analytics.trackEvent('TagOrderActions', 'commitTagOrdering');
|
||||
return matrixClient.setAccountData(
|
||||
'im.vector.web.tag_ordering',
|
||||
{tags, removedTags, _storeId: storeId},
|
||||
{ tags, removedTags, _storeId: storeId },
|
||||
);
|
||||
}, () => {
|
||||
// For an optimistic update
|
||||
return {tags, removedTags};
|
||||
return { tags, removedTags };
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -100,11 +100,11 @@ export default class TagOrderActions {
|
|||
Analytics.trackEvent('TagOrderActions', 'removeTag');
|
||||
return matrixClient.setAccountData(
|
||||
'im.vector.web.tag_ordering',
|
||||
{tags, removedTags, _storeId: storeId},
|
||||
{ tags, removedTags, _storeId: storeId },
|
||||
);
|
||||
}, () => {
|
||||
// For an optimistic update
|
||||
return {removedTags};
|
||||
return { removedTags };
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,9 +51,9 @@ export function asyncAction(id: string, fn: () => Promise<any>, pendingFn: () =>
|
|||
request: typeof pendingFn === 'function' ? pendingFn() : undefined,
|
||||
});
|
||||
fn().then((result) => {
|
||||
dispatch({action: id + '.success', result});
|
||||
dispatch({ action: id + '.success', result });
|
||||
}).catch((err) => {
|
||||
dispatch({action: id + '.failure', err});
|
||||
dispatch({ action: id + '.failure', err });
|
||||
});
|
||||
};
|
||||
return new AsyncActionPayload(helper);
|
||||
|
|
|
@ -22,8 +22,8 @@ import { _t } from '../../../../languageHandler';
|
|||
|
||||
import SettingsStore from "../../../../settings/SettingsStore";
|
||||
import EventIndexPeg from "../../../../indexing/EventIndexPeg";
|
||||
import {Action} from "../../../../dispatcher/actions";
|
||||
import {SettingLevel} from "../../../../settings/SettingLevel";
|
||||
import { Action } from "../../../../dispatcher/actions";
|
||||
import { SettingLevel } from "../../../../settings/SettingLevel";
|
||||
|
||||
/*
|
||||
* Allows the user to disable the Event Index.
|
||||
|
|
|
@ -21,9 +21,9 @@ import SdkConfig from '../../../../SdkConfig';
|
|||
import SettingsStore from "../../../../settings/SettingsStore";
|
||||
|
||||
import Modal from '../../../../Modal';
|
||||
import {formatBytes, formatCountLong} from "../../../../utils/FormattingUtils";
|
||||
import { formatBytes, formatCountLong } from "../../../../utils/FormattingUtils";
|
||||
import EventIndexPeg from "../../../../indexing/EventIndexPeg";
|
||||
import {SettingLevel} from "../../../../settings/SettingLevel";
|
||||
import { SettingLevel } from "../../../../settings/SettingLevel";
|
||||
|
||||
interface IProps {
|
||||
onFinished: (confirmed: boolean) => void;
|
||||
|
@ -139,7 +139,7 @@ export default class ManageEventIndexDialog extends React.Component<IProps, ISta
|
|||
};
|
||||
|
||||
private onCrawlerSleepTimeChange = (e) => {
|
||||
this.setState({crawlerSleepTime: e.target.value});
|
||||
this.setState({ crawlerSleepTime: e.target.value });
|
||||
SettingsStore.setValue("crawlerSleepTime", null, SettingLevel.DEVICE, e.target.value);
|
||||
};
|
||||
|
||||
|
|
|
@ -15,15 +15,15 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React, {createRef} from 'react';
|
||||
import React, { createRef } from 'react';
|
||||
import FileSaver from 'file-saver';
|
||||
import * as sdk from '../../../../index';
|
||||
import {MatrixClientPeg} from '../../../../MatrixClientPeg';
|
||||
import { MatrixClientPeg } from '../../../../MatrixClientPeg';
|
||||
import PropTypes from 'prop-types';
|
||||
import {_t, _td} from '../../../../languageHandler';
|
||||
import { _t, _td } from '../../../../languageHandler';
|
||||
import { accessSecretStorage } from '../../../../SecurityManager';
|
||||
import AccessibleButton from "../../../../components/views/elements/AccessibleButton";
|
||||
import {copyNode} from "../../../../utils/strings";
|
||||
import { copyNode } from "../../../../utils/strings";
|
||||
import PassphraseField from "../../../../components/views/auth/PassphraseField";
|
||||
|
||||
const PHASE_PASSPHRASE = 0;
|
||||
|
@ -152,11 +152,11 @@ export default class CreateKeyBackupDialog extends React.PureComponent {
|
|||
}
|
||||
|
||||
_onOptOutClick = () => {
|
||||
this.setState({phase: PHASE_OPTOUT_CONFIRM});
|
||||
this.setState({ phase: PHASE_OPTOUT_CONFIRM });
|
||||
}
|
||||
|
||||
_onSetUpClick = () => {
|
||||
this.setState({phase: PHASE_PASSPHRASE});
|
||||
this.setState({ phase: PHASE_PASSPHRASE });
|
||||
}
|
||||
|
||||
_onSkipPassPhraseClick = async () => {
|
||||
|
@ -179,7 +179,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent {
|
|||
return;
|
||||
}
|
||||
|
||||
this.setState({phase: PHASE_PASSPHRASE_CONFIRM});
|
||||
this.setState({ phase: PHASE_PASSPHRASE_CONFIRM });
|
||||
};
|
||||
|
||||
_onPassPhraseConfirmNextClick = async (e) => {
|
||||
|
@ -370,21 +370,21 @@ export default class CreateKeyBackupDialog extends React.PureComponent {
|
|||
if (this.state.copied) {
|
||||
introText = _t(
|
||||
"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) {
|
||||
introText = _t(
|
||||
"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');
|
||||
return <div>
|
||||
{introText}
|
||||
<ul>
|
||||
<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>Copy it</b> to your personal cloud storage", {}, {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>Copy it</b> to your personal cloud storage", {}, { b: s => <b>{s}</b> })}</li>
|
||||
</ul>
|
||||
<DialogButtons primaryButton={_t("Continue")}
|
||||
onPrimaryButtonClick={this._createBackup}
|
||||
|
|
|
@ -15,16 +15,16 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React, {createRef} from 'react';
|
||||
import React, { createRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import * as sdk from '../../../../index';
|
||||
import {MatrixClientPeg} from '../../../../MatrixClientPeg';
|
||||
import { MatrixClientPeg } from '../../../../MatrixClientPeg';
|
||||
import FileSaver from 'file-saver';
|
||||
import {_t, _td} from '../../../../languageHandler';
|
||||
import { _t, _td } from '../../../../languageHandler';
|
||||
import Modal from '../../../../Modal';
|
||||
import { promptForBackupPassphrase } from '../../../../SecurityManager';
|
||||
import {copyNode} from "../../../../utils/strings";
|
||||
import {SSOAuthEntry} from "../../../../components/views/auth/InteractiveAuthEntryComponents";
|
||||
import { copyNode } from "../../../../utils/strings";
|
||||
import { SSOAuthEntry } from "../../../../components/views/auth/InteractiveAuthEntryComponents";
|
||||
import PassphraseField from "../../../../components/views/auth/PassphraseField";
|
||||
import StyledRadioButton from '../../../../components/views/elements/StyledRadioButton';
|
||||
import AccessibleButton from "../../../../components/views/elements/AccessibleButton";
|
||||
|
@ -155,7 +155,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
|
|||
backupSigStatus,
|
||||
};
|
||||
} catch (e) {
|
||||
this.setState({phase: PHASE_LOADERROR});
|
||||
this.setState({ phase: PHASE_LOADERROR });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -385,7 +385,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
|
|||
}
|
||||
|
||||
_onLoadRetryClick = () => {
|
||||
this.setState({phase: PHASE_LOADING});
|
||||
this.setState({ phase: PHASE_LOADING });
|
||||
this._fetchBackupInfo();
|
||||
}
|
||||
|
||||
|
@ -394,11 +394,11 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
|
|||
}
|
||||
|
||||
_onCancelClick = () => {
|
||||
this.setState({phase: PHASE_CONFIRM_SKIP});
|
||||
this.setState({ phase: PHASE_CONFIRM_SKIP });
|
||||
}
|
||||
|
||||
_onGoBackClick = () => {
|
||||
this.setState({phase: PHASE_CHOOSE_KEY_PASSPHRASE});
|
||||
this.setState({ phase: PHASE_CHOOSE_KEY_PASSPHRASE });
|
||||
}
|
||||
|
||||
_onPassPhraseNextClick = async (e) => {
|
||||
|
@ -412,7 +412,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
|
|||
return;
|
||||
}
|
||||
|
||||
this.setState({phase: PHASE_PASSPHRASE_CONFIRM});
|
||||
this.setState({ phase: PHASE_PASSPHRASE_CONFIRM });
|
||||
};
|
||||
|
||||
_onPassPhraseConfirmNextClick = async (e) => {
|
||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import FileSaver from 'file-saver';
|
||||
import React, {createRef} from 'react';
|
||||
import React, { createRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { _t } from '../../../../languageHandler';
|
||||
|
||||
|
@ -55,11 +55,11 @@ export default class ExportE2eKeysDialog extends React.Component {
|
|||
|
||||
const passphrase = this._passphrase1.current.value;
|
||||
if (passphrase !== this._passphrase2.current.value) {
|
||||
this.setState({errStr: _t('Passphrases must match')});
|
||||
this.setState({ errStr: _t('Passphrases must match') });
|
||||
return false;
|
||||
}
|
||||
if (!passphrase) {
|
||||
this.setState({errStr: _t('Passphrase must not be empty')});
|
||||
this.setState({ errStr: _t('Passphrase must not be empty') });
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React, {createRef} from 'react';
|
||||
import React, { createRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { MatrixClient } from 'matrix-js-sdk/src/client';
|
||||
|
|
|
@ -18,12 +18,12 @@ limitations under the License.
|
|||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import * as sdk from "../../../../index";
|
||||
import {MatrixClientPeg} from '../../../../MatrixClientPeg';
|
||||
import { MatrixClientPeg } from '../../../../MatrixClientPeg';
|
||||
import dis from "../../../../dispatcher/dispatcher";
|
||||
import { _t } from "../../../../languageHandler";
|
||||
import Modal from "../../../../Modal";
|
||||
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 {
|
||||
static propTypes = {
|
||||
|
|
|
@ -21,7 +21,7 @@ import * as sdk from "../../../../index";
|
|||
import dis from "../../../../dispatcher/dispatcher";
|
||||
import { _t } from "../../../../languageHandler";
|
||||
import Modal from "../../../../Modal";
|
||||
import {Action} from "../../../../dispatcher/actions";
|
||||
import { Action } from "../../../../dispatcher/actions";
|
||||
|
||||
export default class RecoveryMethodRemovedDialog extends React.PureComponent {
|
||||
static propTypes = {
|
||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import type {ICompletion, ISelectionRange} from './Autocompleter';
|
||||
import type { ICompletion, ISelectionRange } from './Autocompleter';
|
||||
|
||||
export interface ICommand {
|
||||
command: string | null;
|
||||
|
|
|
@ -26,7 +26,7 @@ import UserProvider from './UserProvider';
|
|||
import EmojiProvider from './EmojiProvider';
|
||||
import NotifProvider from './NotifProvider';
|
||||
import { timeout } from "../utils/promise";
|
||||
import AutocompleteProvider, {ICommand} from "./AutocompleteProvider";
|
||||
import AutocompleteProvider, { ICommand } from "./AutocompleteProvider";
|
||||
import SettingsStore from "../settings/SettingsStore";
|
||||
import SpaceProvider from "./SpaceProvider";
|
||||
|
||||
|
|
|
@ -18,12 +18,12 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {_t} from '../languageHandler';
|
||||
import { _t } from '../languageHandler';
|
||||
import AutocompleteProvider from './AutocompleteProvider';
|
||||
import QueryMatcher from './QueryMatcher';
|
||||
import {TextualCompletion} from './Components';
|
||||
import {ICompletion, ISelectionRange} from "./Autocompleter";
|
||||
import {Command, Commands, CommandMap} from '../SlashCommands';
|
||||
import { TextualCompletion } from './Components';
|
||||
import { ICompletion, ISelectionRange } from "./Autocompleter";
|
||||
import { Command, Commands, CommandMap } from '../SlashCommands';
|
||||
|
||||
const COMMAND_RE = /(^\/\w*)(?: .*)?/g;
|
||||
|
||||
|
@ -34,7 +34,7 @@ export default class CommandProvider extends AutocompleteProvider {
|
|||
super(COMMAND_RE);
|
||||
this.matcher = new QueryMatcher(Commands, {
|
||||
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,
|
||||
limit = -1,
|
||||
): Promise<ICompletion[]> {
|
||||
const {command, range} = this.getCurrentCommand(query, selection);
|
||||
const { command, range } = this.getCurrentCommand(query, selection);
|
||||
if (!command) return [];
|
||||
|
||||
let matches = [];
|
||||
|
@ -68,7 +68,6 @@ export default class CommandProvider extends AutocompleteProvider {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
return matches.filter(cmd => cmd.isEnabled()).map((result) => {
|
||||
let completion = result.getCommand() + ' ';
|
||||
const usedAlias = result.aliases.find(alias => `/${alias}` === command[1]);
|
||||
|
|
|
@ -19,15 +19,15 @@ import React from 'react';
|
|||
import Group from "matrix-js-sdk/src/models/group";
|
||||
import { _t } from '../languageHandler';
|
||||
import AutocompleteProvider from './AutocompleteProvider';
|
||||
import {MatrixClientPeg} from '../MatrixClientPeg';
|
||||
import { MatrixClientPeg } from '../MatrixClientPeg';
|
||||
import QueryMatcher from './QueryMatcher';
|
||||
import {PillCompletion} from './Components';
|
||||
import { PillCompletion } from './Components';
|
||||
import * as sdk from '../index';
|
||||
import {sortBy} from "lodash";
|
||||
import {makeGroupPermalink} from "../utils/permalinks/Permalinks";
|
||||
import {ICompletion, ISelectionRange} from "./Autocompleter";
|
||||
import { sortBy } from "lodash";
|
||||
import { makeGroupPermalink } from "../utils/permalinks/Permalinks";
|
||||
import { ICompletion, ISelectionRange } from "./Autocompleter";
|
||||
import FlairStore from "../stores/FlairStore";
|
||||
import {mediaFromMxc} from "../customisations/Media";
|
||||
import { mediaFromMxc } from "../customisations/Media";
|
||||
|
||||
const COMMUNITY_REGEX = /\B\+\S*/g;
|
||||
|
||||
|
@ -66,11 +66,11 @@ export default class CommunityProvider extends AutocompleteProvider {
|
|||
|
||||
const cli = MatrixClientPeg.get();
|
||||
let completions = [];
|
||||
const {command, range} = this.getCurrentCommand(query, selection, force);
|
||||
const { command, range } = this.getCurrentCommand(query, selection, force);
|
||||
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 {
|
||||
return FlairStore.getGroupProfileCached(cli, groupId);
|
||||
} catch (e) { // if FlairStore failed, fall back to just groupId
|
||||
|
@ -90,7 +90,7 @@ export default class CommunityProvider extends AutocompleteProvider {
|
|||
completions = sortBy(completions, [
|
||||
(c) => score(matchedString, c.groupId),
|
||||
(c) => c.groupId.length,
|
||||
]).map(({avatarUrl, groupId, name}) => ({
|
||||
]).map(({ avatarUrl, groupId, name }) => ({
|
||||
completion: groupId,
|
||||
suffix: ' ',
|
||||
type: "community",
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React, {forwardRef} from 'react';
|
||||
import React, { forwardRef } from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
/* 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) => {
|
||||
const {title, subtitle, description, className, ...restProps} = props;
|
||||
const { title, subtitle, description, className, ...restProps } = props;
|
||||
return (
|
||||
<div {...restProps}
|
||||
className={classNames('mx_Autocomplete_Completion_block', className)}
|
||||
|
@ -50,7 +50,7 @@ interface IPillCompletionProps extends ITextualCompletionProps {
|
|||
}
|
||||
|
||||
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 (
|
||||
<div {...restProps}
|
||||
className={classNames('mx_Autocomplete_Completion_pill', className)}
|
||||
|
|
|
@ -20,8 +20,8 @@ import React from 'react';
|
|||
import { _t } from '../languageHandler';
|
||||
import AutocompleteProvider from './AutocompleteProvider';
|
||||
|
||||
import {TextualCompletion} from './Components';
|
||||
import {ICompletion, ISelectionRange} from "./Autocompleter";
|
||||
import { TextualCompletion } from './Components';
|
||||
import { ICompletion, ISelectionRange } from "./Autocompleter";
|
||||
|
||||
const DDG_REGEX = /\/ddg\s+(.+)$/g;
|
||||
const REFERRER = 'vector';
|
||||
|
@ -42,7 +42,7 @@ export default class DuckDuckGoProvider extends AutocompleteProvider {
|
|||
force = false,
|
||||
limit = -1,
|
||||
): Promise<ICompletion[]> {
|
||||
const {command, range} = this.getCurrentCommand(query, selection);
|
||||
const { command, range } = this.getCurrentCommand(query, selection);
|
||||
if (!query || !command) {
|
||||
return [];
|
||||
}
|
||||
|
|
|
@ -21,9 +21,9 @@ import React from 'react';
|
|||
import { _t } from '../languageHandler';
|
||||
import AutocompleteProvider from './AutocompleteProvider';
|
||||
import QueryMatcher from './QueryMatcher';
|
||||
import {PillCompletion} from './Components';
|
||||
import {ICompletion, ISelectionRange} from './Autocompleter';
|
||||
import {uniq, sortBy} from 'lodash';
|
||||
import { PillCompletion } from './Components';
|
||||
import { ICompletion, ISelectionRange } from './Autocompleter';
|
||||
import { uniq, sortBy } from 'lodash';
|
||||
import SettingsStore from "../settings/SettingsStore";
|
||||
import { shortcodeToUnicode } from '../HtmlUtils';
|
||||
import { EMOJI, IEmoji } from '../emoji';
|
||||
|
@ -95,7 +95,7 @@ export default class EmojiProvider extends AutocompleteProvider {
|
|||
}
|
||||
|
||||
let completions = [];
|
||||
const {command, range} = this.getCurrentCommand(query, selection);
|
||||
const { command, range } = this.getCurrentCommand(query, selection);
|
||||
if (command) {
|
||||
const matchedString = command[0];
|
||||
completions = this.matcher.match(matchedString, limit);
|
||||
|
@ -121,7 +121,7 @@ export default class EmojiProvider extends AutocompleteProvider {
|
|||
sorters.push((c) => c._orderBy);
|
||||
completions = sortBy(uniq(completions), sorters);
|
||||
|
||||
completions = completions.map(({shortname}) => {
|
||||
completions = completions.map(({ shortname }) => {
|
||||
const unicode = shortcodeToUnicode(shortname);
|
||||
return {
|
||||
completion: unicode,
|
||||
|
|
|
@ -19,10 +19,10 @@ import { Room } from "matrix-js-sdk/src/models/room";
|
|||
|
||||
import AutocompleteProvider from './AutocompleteProvider';
|
||||
import { _t } from '../languageHandler';
|
||||
import {MatrixClientPeg} from '../MatrixClientPeg';
|
||||
import {PillCompletion} from './Components';
|
||||
import { MatrixClientPeg } from '../MatrixClientPeg';
|
||||
import { PillCompletion } from './Components';
|
||||
import * as sdk from '../index';
|
||||
import {ICompletion, ISelectionRange} from "./Autocompleter";
|
||||
import { ICompletion, ISelectionRange } from "./Autocompleter";
|
||||
|
||||
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 [];
|
||||
|
||||
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) {
|
||||
return [{
|
||||
completion: '@room',
|
||||
|
|
|
@ -16,8 +16,8 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {at, uniq} from 'lodash';
|
||||
import {removeHiddenChars} from "matrix-js-sdk/src/utils";
|
||||
import { at, uniq } from 'lodash';
|
||||
import { removeHiddenChars } from "matrix-js-sdk/src/utils";
|
||||
|
||||
interface IOptions<T extends {}> {
|
||||
keys: Array<string | keyof T>;
|
||||
|
@ -112,7 +112,7 @@ export default class QueryMatcher<T extends Object> {
|
|||
const index = resultKey.indexOf(query);
|
||||
if (index !== -1) {
|
||||
matches.push(
|
||||
...candidates.map((candidate) => ({index, ...candidate})),
|
||||
...candidates.map((candidate) => ({ index, ...candidate })),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ export default class RoomProvider extends AutocompleteProvider {
|
|||
limit = -1,
|
||||
): Promise<ICompletion[]> {
|
||||
let completions = [];
|
||||
const {command, range} = this.getCurrentCommand(query, selection, force);
|
||||
const { command, range } = this.getCurrentCommand(query, selection, force);
|
||||
if (command) {
|
||||
// the only reason we need to do this is because Fuse only matches on properties
|
||||
let matcherObjects = this.getRooms().reduce((aliases, room) => {
|
||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||
import React from "react";
|
||||
|
||||
import { _t } from '../languageHandler';
|
||||
import {MatrixClientPeg} from '../MatrixClientPeg';
|
||||
import { MatrixClientPeg } from '../MatrixClientPeg';
|
||||
import RoomProvider from "./RoomProvider";
|
||||
|
||||
export default class SpaceProvider extends RoomProvider {
|
||||
|
|
|
@ -114,7 +114,7 @@ export default class UserProvider extends AutocompleteProvider {
|
|||
if (!this.users) this._makeUsers();
|
||||
|
||||
let completions = [];
|
||||
const {command, range} = this.getCurrentCommand(rawQuery, selection, force);
|
||||
const { command, range } = this.getCurrentCommand(rawQuery, selection, force);
|
||||
|
||||
if (!command) return completions;
|
||||
|
||||
|
@ -158,7 +158,7 @@ export default class UserProvider extends AutocompleteProvider {
|
|||
}
|
||||
|
||||
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 = sortBy(this.users, (member) => 1E20 - lastSpoken[member.userId] || 1E20);
|
||||
|
|
|
@ -15,12 +15,12 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { HTMLAttributes } from "react";
|
||||
import React, { HTMLAttributes, WheelEvent } from "react";
|
||||
|
||||
interface IProps extends HTMLAttributes<HTMLDivElement> {
|
||||
interface IProps extends Omit<HTMLAttributes<HTMLDivElement>, "onScroll"> {
|
||||
className?: string;
|
||||
onScroll?: () => void;
|
||||
onWheel?: () => void;
|
||||
onScroll?: (event: Event) => void;
|
||||
onWheel?: (event: WheelEvent) => void;
|
||||
style?: React.CSSProperties
|
||||
tabIndex?: number,
|
||||
wrappedRef?: (ref: HTMLDivElement) => void;
|
||||
|
|
|
@ -16,13 +16,13 @@ See the License for the specific language governing permissions and
|
|||
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 classNames from "classnames";
|
||||
|
||||
import {Key} from "../../Keyboard";
|
||||
import {Writeable} from "../../@types/common";
|
||||
import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||
import { Key } from "../../Keyboard";
|
||||
import { Writeable } from "../../@types/common";
|
||||
import { replaceableComponent } from "../../utils/replaceableComponent";
|
||||
import UIStore from "../../stores/UIStore";
|
||||
|
||||
// Shamelessly ripped off Modal.js. There's probably a better way
|
||||
|
@ -371,7 +371,7 @@ export class ContextMenu extends React.PureComponent<IProps, IState> {
|
|||
return (
|
||||
<div
|
||||
className={classNames("mx_ContextualMenu_wrapper", this.props.wrapperClassName)}
|
||||
style={{...position, ...wrapperStyle}}
|
||||
style={{ ...position, ...wrapperStyle }}
|
||||
onKeyDown={this.onKeyDown}
|
||||
onContextMenu={this.onContextMenuPreventBubbling}
|
||||
>
|
||||
|
@ -399,7 +399,7 @@ export const toRightOf = (elementRect: Pick<DOMRect, "right" | "top" | "height">
|
|||
const left = elementRect.right + window.pageXOffset + 3;
|
||||
let top = elementRect.top + (elementRect.height / 2) + window.pageYOffset;
|
||||
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,
|
||||
|
@ -498,15 +498,15 @@ export function createMenu(ElementClass, props) {
|
|||
|
||||
ReactDOM.render(menu, getOrCreateContainer());
|
||||
|
||||
return {close: onFinished};
|
||||
return { close: onFinished };
|
||||
}
|
||||
|
||||
// re-export the semantic helper components for simplicity
|
||||
export {ContextMenuButton} from "../../accessibility/context_menu/ContextMenuButton";
|
||||
export {ContextMenuTooltipButton} from "../../accessibility/context_menu/ContextMenuTooltipButton";
|
||||
export {MenuGroup} from "../../accessibility/context_menu/MenuGroup";
|
||||
export {MenuItem} from "../../accessibility/context_menu/MenuItem";
|
||||
export {MenuItemCheckbox} from "../../accessibility/context_menu/MenuItemCheckbox";
|
||||
export {MenuItemRadio} from "../../accessibility/context_menu/MenuItemRadio";
|
||||
export {StyledMenuItemCheckbox} from "../../accessibility/context_menu/StyledMenuItemCheckbox";
|
||||
export {StyledMenuItemRadio} from "../../accessibility/context_menu/StyledMenuItemRadio";
|
||||
export { ContextMenuButton } from "../../accessibility/context_menu/ContextMenuButton";
|
||||
export { ContextMenuTooltipButton } from "../../accessibility/context_menu/ContextMenuTooltipButton";
|
||||
export { MenuGroup } from "../../accessibility/context_menu/MenuGroup";
|
||||
export { MenuItem } from "../../accessibility/context_menu/MenuItem";
|
||||
export { MenuItemCheckbox } from "../../accessibility/context_menu/MenuItemCheckbox";
|
||||
export { MenuItemRadio } from "../../accessibility/context_menu/MenuItemRadio";
|
||||
export { StyledMenuItemCheckbox } from "../../accessibility/context_menu/StyledMenuItemCheckbox";
|
||||
export { StyledMenuItemRadio } from "../../accessibility/context_menu/StyledMenuItemRadio";
|
||||
|
|
|
@ -21,7 +21,7 @@ import * as sdk from '../../index';
|
|||
import dis from '../../dispatcher/dispatcher';
|
||||
import classNames from 'classnames';
|
||||
import * as FormattingUtils from '../../utils/FormattingUtils';
|
||||
import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||
import { replaceableComponent } from "../../utils/replaceableComponent";
|
||||
|
||||
@replaceableComponent("structures.CustomRoomTagPanel")
|
||||
class CustomRoomTagPanel extends React.Component {
|
||||
|
@ -34,7 +34,7 @@ class CustomRoomTagPanel extends React.Component {
|
|||
|
||||
componentDidMount() {
|
||||
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 {
|
||||
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() {
|
||||
|
|
|
@ -22,7 +22,7 @@ import request from 'browser-request';
|
|||
import { _t } from '../../languageHandler';
|
||||
import sanitizeHtml from 'sanitize-html';
|
||||
import dis from '../../dispatcher/dispatcher';
|
||||
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
||||
import { MatrixClientPeg } from '../../MatrixClientPeg';
|
||||
import classnames from 'classnames';
|
||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||
import AutoHideScrollbar from "./AutoHideScrollbar";
|
||||
|
|
|
@ -16,37 +16,49 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {Filter} from 'matrix-js-sdk/src/filter';
|
||||
import { Filter } from 'matrix-js-sdk/src/filter';
|
||||
import { EventTimelineSet } from "matrix-js-sdk/src/models/event-timeline-set";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { Room } from 'matrix-js-sdk/src/models/room';
|
||||
import { TimelineWindow } from 'matrix-js-sdk/src/timeline-window';
|
||||
|
||||
import * as sdk from '../../index';
|
||||
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
||||
import { MatrixClientPeg } from '../../MatrixClientPeg';
|
||||
import EventIndexPeg from "../../indexing/EventIndexPeg";
|
||||
import { _t } from '../../languageHandler';
|
||||
import BaseCard from "../views/right_panel/BaseCard";
|
||||
import {RightPanelPhases} from "../../stores/RightPanelStorePhases";
|
||||
import DesktopBuildsNotice, {WarningKind} from "../views/elements/DesktopBuildsNotice";
|
||||
import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||
import { RightPanelPhases } from "../../stores/RightPanelStorePhases";
|
||||
import DesktopBuildsNotice, { WarningKind } from "../views/elements/DesktopBuildsNotice";
|
||||
import { replaceableComponent } from "../../utils/replaceableComponent";
|
||||
|
||||
import ResizeNotifier from '../../utils/ResizeNotifier';
|
||||
|
||||
interface IProps {
|
||||
roomId: string;
|
||||
onClose: () => void;
|
||||
resizeNotifier: ResizeNotifier
|
||||
}
|
||||
|
||||
interface IState {
|
||||
timelineSet: EventTimelineSet;
|
||||
}
|
||||
|
||||
/*
|
||||
* Component which shows the filtered file using a TimelinePanel
|
||||
*/
|
||||
@replaceableComponent("structures.FilePanel")
|
||||
class FilePanel extends React.Component {
|
||||
static propTypes = {
|
||||
roomId: PropTypes.string.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class FilePanel extends React.Component<IProps, IState> {
|
||||
// This is used to track if a decrypted event was a live event and should be
|
||||
// added to the timeline.
|
||||
decryptingEvents = new Set();
|
||||
private decryptingEvents = new Set<string>();
|
||||
public noRoom: boolean;
|
||||
|
||||
state = {
|
||||
timelineSet: null,
|
||||
};
|
||||
|
||||
onRoomTimeline = (ev, room, toStartOfTimeline, removed, data) => {
|
||||
private onRoomTimeline = (ev: MatrixEvent, room: Room, toStartOfTimeline: true, removed: true, data: any): void => {
|
||||
if (room?.roomId !== this.props?.roomId) return;
|
||||
if (toStartOfTimeline || !data || !data.liveEvent || ev.isRedacted()) return;
|
||||
|
||||
|
@ -60,7 +72,7 @@ class FilePanel extends React.Component {
|
|||
}
|
||||
};
|
||||
|
||||
onEventDecrypted = (ev, err) => {
|
||||
private onEventDecrypted = (ev: MatrixEvent, err?: any): void => {
|
||||
if (ev.getRoomId() !== this.props.roomId) return;
|
||||
const eventId = ev.getId();
|
||||
|
||||
|
@ -70,7 +82,7 @@ class FilePanel extends React.Component {
|
|||
this.addEncryptedLiveEvent(ev);
|
||||
};
|
||||
|
||||
addEncryptedLiveEvent(ev, toStartOfTimeline) {
|
||||
public addEncryptedLiveEvent(ev: MatrixEvent): void {
|
||||
if (!this.state.timelineSet) return;
|
||||
|
||||
const timeline = this.state.timelineSet.getLiveTimeline();
|
||||
|
@ -84,7 +96,7 @@ class FilePanel extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
public async componentDidMount(): Promise<void> {
|
||||
const client = MatrixClientPeg.get();
|
||||
|
||||
await this.updateTimelineSet(this.props.roomId);
|
||||
|
@ -105,7 +117,7 @@ class FilePanel extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
const client = MatrixClientPeg.get();
|
||||
if (client === null) return;
|
||||
|
||||
|
@ -117,7 +129,7 @@ class FilePanel extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
async fetchFileEventsServer(room) {
|
||||
public async fetchFileEventsServer(room: Room): Promise<void> {
|
||||
const client = MatrixClientPeg.get();
|
||||
|
||||
const filter = new Filter(client.credentials.userId);
|
||||
|
@ -141,7 +153,7 @@ class FilePanel extends React.Component {
|
|||
return timelineSet;
|
||||
}
|
||||
|
||||
onPaginationRequest = (timelineWindow, direction, limit) => {
|
||||
private onPaginationRequest = (timelineWindow: TimelineWindow, direction: string, limit: number): void => {
|
||||
const client = MatrixClientPeg.get();
|
||||
const eventIndex = EventIndexPeg.get();
|
||||
const roomId = this.props.roomId;
|
||||
|
@ -159,7 +171,7 @@ class FilePanel extends React.Component {
|
|||
}
|
||||
};
|
||||
|
||||
async updateTimelineSet(roomId: string) {
|
||||
public async updateTimelineSet(roomId: string): Promise<void> {
|
||||
const client = MatrixClientPeg.get();
|
||||
const room = client.getRoom(roomId);
|
||||
const eventIndex = EventIndexPeg.get();
|
||||
|
@ -195,7 +207,7 @@ class FilePanel extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
public render() {
|
||||
if (MatrixClientPeg.get().isGuest()) {
|
||||
return <BaseCard
|
||||
className="mx_FilePanel mx_RoomView_messageListWrapper"
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||
import { replaceableComponent } from "../../utils/replaceableComponent";
|
||||
|
||||
@replaceableComponent("structures.GenericErrorPage")
|
||||
export default class GenericErrorPage extends React.PureComponent {
|
||||
|
|
|
@ -29,7 +29,7 @@ import MatrixClientContext from "../../contexts/MatrixClientContext";
|
|||
import AutoHideScrollbar from "./AutoHideScrollbar";
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
import UserTagTile from "../views/elements/UserTagTile";
|
||||
import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||
import { replaceableComponent } from "../../utils/replaceableComponent";
|
||||
|
||||
@replaceableComponent("structures.GroupFilterPanel")
|
||||
class GroupFilterPanel extends React.Component {
|
||||
|
@ -85,12 +85,12 @@ class GroupFilterPanel extends React.Component {
|
|||
onClick = e => {
|
||||
// only dispatch if its not a no-op
|
||||
if (this.state.selectedTags.length > 0) {
|
||||
dis.dispatch({action: 'deselect_tags'});
|
||||
dis.dispatch({ action: 'deselect_tags' });
|
||||
}
|
||||
};
|
||||
|
||||
onClearFilterClick = ev => {
|
||||
dis.dispatch({action: 'deselect_tags'});
|
||||
dis.dispatch({ action: 'deselect_tags' });
|
||||
};
|
||||
|
||||
renderGlobalIcon() {
|
||||
|
|
|
@ -18,7 +18,7 @@ limitations under the License.
|
|||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
||||
import { MatrixClientPeg } from '../../MatrixClientPeg';
|
||||
import * as sdk from '../../index';
|
||||
import dis from '../../dispatcher/dispatcher';
|
||||
import { getHostingLink } from '../../utils/HostingLink';
|
||||
|
@ -34,13 +34,13 @@ import classnames from 'classnames';
|
|||
import GroupStore from '../../stores/GroupStore';
|
||||
import FlairStore from '../../stores/FlairStore';
|
||||
import { showGroupAddRoomDialog } from '../../GroupAddressPicker';
|
||||
import {makeGroupPermalink, makeUserPermalink} from "../../utils/permalinks/Permalinks";
|
||||
import {Group} from "matrix-js-sdk/src/models/group";
|
||||
import {sleep} from "../../utils/promise";
|
||||
import { makeGroupPermalink, makeUserPermalink } from "../../utils/permalinks/Permalinks";
|
||||
import { Group } from "matrix-js-sdk/src/models/group";
|
||||
import { sleep } from "../../utils/promise";
|
||||
import RightPanelStore from "../../stores/RightPanelStore";
|
||||
import AutoHideScrollbar from "./AutoHideScrollbar";
|
||||
import {mediaFromMxc} from "../../customisations/Media";
|
||||
import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||
import { mediaFromMxc } from "../../customisations/Media";
|
||||
import { replaceableComponent } from "../../utils/replaceableComponent";
|
||||
|
||||
const LONG_DESC_PLACEHOLDER = _td(
|
||||
`<h1>HTML for your community's page</h1>
|
||||
|
@ -115,7 +115,7 @@ class CategoryRoomList extends React.Component {
|
|||
{
|
||||
title: _t(
|
||||
"Failed to add the following rooms to the summary of %(groupId)s:",
|
||||
{groupId: this.props.groupId},
|
||||
{ groupId: this.props.groupId },
|
||||
),
|
||||
description: errorList.join(", "),
|
||||
},
|
||||
|
@ -126,12 +126,11 @@ class CategoryRoomList extends React.Component {
|
|||
};
|
||||
|
||||
render() {
|
||||
const TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||
const addButton = this.props.editing ?
|
||||
(<AccessibleButton className="mx_GroupView_featuredThings_addButton"
|
||||
onClick={this.onAddRoomsToSummaryClicked}
|
||||
>
|
||||
<TintableSvg src={require("../../../res/img/icons-create-room.svg")} width="64" height="64" />
|
||||
<img src={require("../../../res/img/icons-create-room.svg")} width="64" height="64" />
|
||||
<div className="mx_GroupView_featuredThings_addButton_label">
|
||||
{ _t('Add a Room') }
|
||||
</div>
|
||||
|
@ -195,9 +194,9 @@ class FeaturedRoom extends React.Component {
|
|||
{
|
||||
title: _t(
|
||||
"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 }),
|
||||
},
|
||||
);
|
||||
});
|
||||
|
@ -289,7 +288,7 @@ class RoleUserList extends React.Component {
|
|||
{
|
||||
title: _t(
|
||||
"Failed to add the following users to the summary of %(groupId)s:",
|
||||
{groupId: this.props.groupId},
|
||||
{ groupId: this.props.groupId },
|
||||
),
|
||||
description: errorList.join(", "),
|
||||
},
|
||||
|
@ -300,10 +299,9 @@ class RoleUserList extends React.Component {
|
|||
};
|
||||
|
||||
render() {
|
||||
const TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||
const addButton = this.props.editing ?
|
||||
(<AccessibleButton className="mx_GroupView_featuredThings_addButton" onClick={this.onAddUsersClicked}>
|
||||
<TintableSvg src={require("../../../res/img/icons-create-room.svg")} width="64" height="64" />
|
||||
<img src={require("../../../res/img/icons-create-room.svg")} width="64" height="64" />
|
||||
<div className="mx_GroupView_featuredThings_addButton_label">
|
||||
{ _t('Add a User') }
|
||||
</div>
|
||||
|
@ -361,9 +359,12 @@ class FeaturedUser extends React.Component {
|
|||
{
|
||||
title: _t(
|
||||
"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}),
|
||||
},
|
||||
);
|
||||
});
|
||||
|
@ -470,7 +471,7 @@ export default class GroupView extends React.Component {
|
|||
// Leave settings - the user might have clicked the "Leave" button
|
||||
this._closeSettings();
|
||||
}
|
||||
this.setState({membershipBusy: false});
|
||||
this.setState({ membershipBusy: false });
|
||||
};
|
||||
|
||||
_initGroupStore(groupId, firstInit) {
|
||||
|
@ -491,7 +492,7 @@ export default class GroupView extends React.Component {
|
|||
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;
|
||||
}
|
||||
if (stateKey === GroupStore.STATE_KEY.Summary) {
|
||||
|
@ -592,7 +593,7 @@ export default class GroupView extends React.Component {
|
|||
};
|
||||
|
||||
_closeSettings = () => {
|
||||
dis.dispatch({action: 'close_settings'});
|
||||
dis.dispatch({ action: 'close_settings' });
|
||||
};
|
||||
|
||||
_onNameChange = (value) => {
|
||||
|
@ -620,7 +621,7 @@ export default class GroupView extends React.Component {
|
|||
const file = ev.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
this.setState({uploadingAvatar: true});
|
||||
this.setState({ uploadingAvatar: true });
|
||||
this._matrixClient.uploadContent(file).then((url) => {
|
||||
const newProfileForm = Object.assign(this.state.profileForm, { avatar_url: url });
|
||||
this.setState({
|
||||
|
@ -632,7 +633,7 @@ export default class GroupView extends React.Component {
|
|||
avatarChanged: true,
|
||||
});
|
||||
}).catch((e) => {
|
||||
this.setState({uploadingAvatar: false});
|
||||
this.setState({ uploadingAvatar: false });
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
console.error("Failed to upload avatar image", e);
|
||||
Modal.createTrackedDialog('Failed to upload image', '', ErrorDialog, {
|
||||
|
@ -649,7 +650,7 @@ export default class GroupView extends React.Component {
|
|||
};
|
||||
|
||||
_onSaveClick = () => {
|
||||
this.setState({saving: true});
|
||||
this.setState({ saving: true });
|
||||
const savePromise = this.state.isUserPrivileged ? this._saveGroup() : Promise.resolve();
|
||||
savePromise.then((result) => {
|
||||
this.setState({
|
||||
|
@ -688,7 +689,7 @@ export default class GroupView extends React.Component {
|
|||
}
|
||||
|
||||
_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
|
||||
// spinner disappearing after we have fetched new group data.
|
||||
|
@ -697,7 +698,7 @@ export default class GroupView extends React.Component {
|
|||
GroupStore.acceptGroupInvite(this.props.groupId).then(() => {
|
||||
// don't reset membershipBusy here: wait for the membership change to come down the sync
|
||||
}).catch((e) => {
|
||||
this.setState({membershipBusy: false});
|
||||
this.setState({ membershipBusy: false });
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createTrackedDialog('Error accepting invite', '', ErrorDialog, {
|
||||
title: _t("Error"),
|
||||
|
@ -707,7 +708,7 @@ export default class GroupView extends React.Component {
|
|||
};
|
||||
|
||||
_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
|
||||
// spinner disappearing after we have fetched new group data.
|
||||
|
@ -716,7 +717,7 @@ export default class GroupView extends React.Component {
|
|||
GroupStore.leaveGroup(this.props.groupId).then(() => {
|
||||
// don't reset membershipBusy here: wait for the membership change to come down the sync
|
||||
}).catch((e) => {
|
||||
this.setState({membershipBusy: false});
|
||||
this.setState({ membershipBusy: false });
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createTrackedDialog('Error rejecting invite', '', ErrorDialog, {
|
||||
title: _t("Error"),
|
||||
|
@ -727,11 +728,11 @@ export default class GroupView extends React.Component {
|
|||
|
||||
_onJoinClick = async () => {
|
||||
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;
|
||||
}
|
||||
|
||||
this.setState({membershipBusy: true});
|
||||
this.setState({ membershipBusy: true });
|
||||
|
||||
// Wait 500ms to prevent flashing. Do this before sending a request otherwise we risk the
|
||||
// spinner disappearing after we have fetched new group data.
|
||||
|
@ -740,7 +741,7 @@ export default class GroupView extends React.Component {
|
|||
GroupStore.joinGroup(this.props.groupId).then(() => {
|
||||
// don't reset membershipBusy here: wait for the membership change to come down the sync
|
||||
}).catch((e) => {
|
||||
this.setState({membershipBusy: false});
|
||||
this.setState({ membershipBusy: false });
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createTrackedDialog('Error joining room', '', ErrorDialog, {
|
||||
title: _t("Error"),
|
||||
|
@ -773,7 +774,7 @@ export default class GroupView extends React.Component {
|
|||
title: _t("Leave Community"),
|
||||
description: (
|
||||
<span>
|
||||
{ _t("Leave %(groupName)s?", {groupName: this.props.groupId}) }
|
||||
{ _t("Leave %(groupName)s?", { groupName: this.props.groupId }) }
|
||||
{ warnings }
|
||||
</span>
|
||||
),
|
||||
|
@ -782,7 +783,7 @@ export default class GroupView extends React.Component {
|
|||
onFinished: async (confirmed) => {
|
||||
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
|
||||
// spinner disappearing after we have fetched new group data.
|
||||
|
@ -791,7 +792,7 @@ export default class GroupView extends React.Component {
|
|||
GroupStore.leaveGroup(this.props.groupId).then(() => {
|
||||
// don't reset membershipBusy here: wait for the membership change to come down the sync
|
||||
}).catch((e) => {
|
||||
this.setState({membershipBusy: false});
|
||||
this.setState({ membershipBusy: false });
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createTrackedDialog('Error leaving community', '', ErrorDialog, {
|
||||
title: _t("Error"),
|
||||
|
@ -855,7 +856,6 @@ export default class GroupView extends React.Component {
|
|||
_getRoomsNode() {
|
||||
const RoomDetailList = sdk.getComponent('rooms.RoomDetailList');
|
||||
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
||||
const TintableSvg = sdk.getComponent('elements.TintableSvg');
|
||||
const Spinner = sdk.getComponent('elements.Spinner');
|
||||
const TooltipButton = sdk.getComponent('elements.TooltipButton');
|
||||
|
||||
|
@ -871,7 +871,7 @@ export default class GroupView extends React.Component {
|
|||
onClick={this._onAddRoomsClick}
|
||||
>
|
||||
<div className="mx_GroupView_rooms_header_addRow_button">
|
||||
<TintableSvg src={require("../../../res/img/icons-room-add.svg")} width="24" height="24" />
|
||||
<img src={require("../../../res/img/icons-room-add.svg")} width="24" height="24" />
|
||||
</div>
|
||||
<div className="mx_GroupView_rooms_header_addRow_label">
|
||||
{ _t('Add rooms to this community') }
|
||||
|
@ -1336,7 +1336,7 @@ export default class GroupView extends React.Component {
|
|||
if (this.state.error.httpStatus === 404) {
|
||||
return (
|
||||
<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>
|
||||
);
|
||||
} else {
|
||||
|
@ -1346,7 +1346,7 @@ export default class GroupView extends React.Component {
|
|||
}
|
||||
return (
|
||||
<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 }
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -15,29 +15,29 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import * as React from "react";
|
||||
import {useContext, useState} from "react";
|
||||
import { useContext, useState } from "react";
|
||||
|
||||
import AutoHideScrollbar from './AutoHideScrollbar';
|
||||
import {getHomePageUrl} from "../../utils/pages";
|
||||
import {_t} from "../../languageHandler";
|
||||
import { getHomePageUrl } from "../../utils/pages";
|
||||
import { _t } from "../../languageHandler";
|
||||
import SdkConfig from "../../SdkConfig";
|
||||
import * as sdk from "../../index";
|
||||
import dis from "../../dispatcher/dispatcher";
|
||||
import {Action} from "../../dispatcher/actions";
|
||||
import { Action } from "../../dispatcher/actions";
|
||||
import BaseAvatar from "../views/avatars/BaseAvatar";
|
||||
import {OwnProfileStore} from "../../stores/OwnProfileStore";
|
||||
import { OwnProfileStore } from "../../stores/OwnProfileStore";
|
||||
import AccessibleButton from "../views/elements/AccessibleButton";
|
||||
import {UPDATE_EVENT} from "../../stores/AsyncStore";
|
||||
import {useEventEmitter} from "../../hooks/useEventEmitter";
|
||||
import { UPDATE_EVENT } from "../../stores/AsyncStore";
|
||||
import { useEventEmitter } from "../../hooks/useEventEmitter";
|
||||
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 CountlyAnalytics from "../../CountlyAnalytics";
|
||||
|
||||
const onClickSendDm = () => {
|
||||
Analytics.trackEvent('home_page', 'button', 'dm');
|
||||
CountlyAnalytics.instance.track("home_page_button", { button: "dm" });
|
||||
dis.dispatch({action: 'view_create_chat'});
|
||||
dis.dispatch({ action: 'view_create_chat' });
|
||||
};
|
||||
|
||||
const onClickExplore = () => {
|
||||
|
@ -49,7 +49,7 @@ const onClickExplore = () => {
|
|||
const onClickNewRoom = () => {
|
||||
Analytics.trackEvent('home_page', '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 {
|
||||
|
@ -117,7 +117,6 @@ const HomePage: React.FC<IProps> = ({ justRegistered = false }) => {
|
|||
</React.Fragment>;
|
||||
}
|
||||
|
||||
|
||||
return <AutoHideScrollbar className="mx_HomePage mx_HomePage_default">
|
||||
<div className="mx_HomePage_default_wrapper">
|
||||
{ introSection }
|
||||
|
|
|
@ -22,7 +22,7 @@ import {
|
|||
import { _t } from "../../languageHandler";
|
||||
import { HostSignupStore } from "../../stores/HostSignupStore";
|
||||
import SdkConfig from "../../SdkConfig";
|
||||
import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||
import { replaceableComponent } from "../../utils/replaceableComponent";
|
||||
|
||||
interface IProps {
|
||||
onClick?(): void;
|
||||
|
@ -35,7 +35,7 @@ export default class HostSignupAction extends React.PureComponent<IProps, IState
|
|||
private openDialog = async () => {
|
||||
this.props.onClick?.();
|
||||
await HostSignupStore.instance.setHostSignupActive(true);
|
||||
}
|
||||
};
|
||||
|
||||
public render(): React.ReactNode {
|
||||
const hostSignupConfig = SdkConfig.get().hostSignup;
|
||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import AutoHideScrollbar from "./AutoHideScrollbar";
|
||||
import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||
import { replaceableComponent } from "../../utils/replaceableComponent";
|
||||
|
||||
@replaceableComponent("structures.IndicatorScrollbar")
|
||||
export default class IndicatorScrollbar extends React.Component {
|
||||
|
@ -70,7 +70,6 @@ export default class IndicatorScrollbar extends React.Component {
|
|||
this._autoHideScrollbar = autoHideScrollbar;
|
||||
}
|
||||
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const prevLen = prevProps && prevProps.children && prevProps.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
|
||||
const { children, trackHorizontalOverflow, verticalScrollsHorizontally, ...otherProps } = this.props;
|
||||
|
||||
const leftIndicatorStyle = {left: this.state.leftIndicatorOffset};
|
||||
const rightIndicatorStyle = {right: this.state.rightIndicatorOffset};
|
||||
const leftIndicatorStyle = { left: this.state.leftIndicatorOffset };
|
||||
const rightIndicatorStyle = { right: this.state.rightIndicatorOffset };
|
||||
const leftOverflowIndicator = trackHorizontalOverflow
|
||||
? <div className="mx_IndicatorScrollbar_leftOverflowIndicator" style={leftIndicatorStyle} /> : null;
|
||||
const rightOverflowIndicator = trackHorizontalOverflow
|
||||
|
|
|
@ -15,14 +15,14 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {InteractiveAuth} from "matrix-js-sdk/src/interactive-auth";
|
||||
import React, {createRef} from 'react';
|
||||
import { InteractiveAuth } from "matrix-js-sdk/src/interactive-auth";
|
||||
import React, { createRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import getEntryComponentForLoginType from '../views/auth/InteractiveAuthEntryComponents';
|
||||
|
||||
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");
|
||||
|
||||
|
|
|
@ -40,9 +40,9 @@ import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton";
|
|||
import { OwnProfileStore } from "../../stores/OwnProfileStore";
|
||||
import RoomListNumResults from "../views/rooms/RoomListNumResults";
|
||||
import LeftPanelWidget from "./LeftPanelWidget";
|
||||
import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||
import {mediaFromMxc} from "../../customisations/Media";
|
||||
import SpaceStore, {UPDATE_SELECTED_SPACE} from "../../stores/SpaceStore";
|
||||
import { replaceableComponent } from "../../utils/replaceableComponent";
|
||||
import { mediaFromMxc } from "../../customisations/Media";
|
||||
import SpaceStore, { UPDATE_SELECTED_SPACE } from "../../stores/SpaceStore";
|
||||
import { getKeyBindingsManager, RoomListAction } from "../../KeyBindingsManager";
|
||||
import UIStore from "../../stores/UIStore";
|
||||
|
||||
|
@ -91,7 +91,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
|||
this.bgImageWatcherRef = SettingsStore.watchSetting(
|
||||
"RoomList.backgroundImage", null, this.onBackgroundImageUpdate);
|
||||
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 = () => {
|
||||
dis.fire(Action.OpenDialPad);
|
||||
}
|
||||
};
|
||||
|
||||
private onExplore = () => {
|
||||
dis.fire(Action.ViewRoomDirectory);
|
||||
|
@ -136,12 +136,12 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
|||
private refreshStickyHeaders = () => {
|
||||
if (!this.listContainerRef.current) return; // ignore: no headers to sticky
|
||||
this.handleStickyHeaders(this.listContainerRef.current);
|
||||
}
|
||||
};
|
||||
|
||||
private onBreadcrumbsUpdate = () => {
|
||||
const newVal = BreadcrumbsStore.instance.visible;
|
||||
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.
|
||||
if (!this.listContainerRef.current) return; // ignore: no headers to sticky
|
||||
|
|
|
@ -14,19 +14,19 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React, {useContext, useMemo} from "react";
|
||||
import {Resizable} from "re-resizable";
|
||||
import React, { useContext, useMemo } from "react";
|
||||
import { Resizable } from "re-resizable";
|
||||
import classNames from "classnames";
|
||||
|
||||
import AccessibleButton from "../views/elements/AccessibleButton";
|
||||
import {useRovingTabIndex} from "../../accessibility/RovingTabIndex";
|
||||
import {Key} from "../../Keyboard";
|
||||
import {useLocalStorageState} from "../../hooks/useLocalStorageState";
|
||||
import { useRovingTabIndex } from "../../accessibility/RovingTabIndex";
|
||||
import { Key } from "../../Keyboard";
|
||||
import { useLocalStorageState } from "../../hooks/useLocalStorageState";
|
||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||
import WidgetUtils, {IWidgetEvent} from "../../utils/WidgetUtils";
|
||||
import {useAccountData} from "../../hooks/useAccountData";
|
||||
import WidgetUtils, { IWidgetEvent } from "../../utils/WidgetUtils";
|
||||
import { useAccountData } from "../../hooks/useAccountData";
|
||||
import AppTile from "../views/elements/AppTile";
|
||||
import {useSettingValue} from "../../hooks/useSettings";
|
||||
import { useSettingValue } from "../../hooks/useSettings";
|
||||
import UIStore from "../../stores/UIStore";
|
||||
|
||||
const MIN_HEIGHT = 100;
|
||||
|
@ -62,14 +62,14 @@ const LeftPanelWidget: React.FC = () => {
|
|||
let content;
|
||||
if (expanded) {
|
||||
content = <Resizable
|
||||
size={{height} as any}
|
||||
size={{ height } as any}
|
||||
minHeight={MIN_HEIGHT}
|
||||
maxHeight={Math.min(UIStore.instance.windowHeight / 2, MAX_HEIGHT)}
|
||||
onResizeStop={(e, dir, ref, d) => {
|
||||
setHeight(height + d.height);
|
||||
}}
|
||||
handleWrapperClass="mx_LeftPanelWidget_resizerHandles"
|
||||
handleClasses={{top: "mx_LeftPanelWidget_resizerHandle"}}
|
||||
handleClasses={{ top: "mx_LeftPanelWidget_resizerHandle" }}
|
||||
className="mx_LeftPanelWidget_resizeBox"
|
||||
enable={{ top: true }}
|
||||
>
|
||||
|
|
|
@ -20,7 +20,7 @@ import * as React from 'react';
|
|||
import * as PropTypes from 'prop-types';
|
||||
import { MatrixClient } from 'matrix-js-sdk/src/client';
|
||||
|
||||
import {Key} from '../../Keyboard';
|
||||
import { Key } from '../../Keyboard';
|
||||
import PageTypes from '../../PageTypes';
|
||||
import MediaDeviceHandler from '../../MediaDeviceHandler';
|
||||
import { fixupColorFonts } from '../../utils/FontManager';
|
||||
|
@ -30,7 +30,7 @@ import { IMatrixClientCreds } from '../../MatrixClientPeg';
|
|||
import SettingsStore from "../../settings/SettingsStore";
|
||||
|
||||
import ResizeHandle from '../views/elements/ResizeHandle';
|
||||
import {Resizer, CollapseDistributor} from '../../resizer';
|
||||
import { Resizer, CollapseDistributor } from '../../resizer';
|
||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||
import * as KeyboardShortcuts from "../../accessibility/KeyboardShortcuts";
|
||||
import HomePage from "./HomePage";
|
||||
|
@ -55,7 +55,7 @@ import HostSignupContainer from '../views/host_signup/HostSignupContainer';
|
|||
import { getKeyBindingsManager, NavigationAction, RoomAction } from '../../KeyBindingsManager';
|
||||
import { IOpts } from "../../createRoom";
|
||||
import SpacePanel from "../views/spaces/SpacePanel";
|
||||
import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||
import { replaceableComponent } from "../../utils/replaceableComponent";
|
||||
import CallHandler, { CallHandlerEvent } from '../../CallHandler';
|
||||
import { MatrixCall } from 'matrix-js-sdk/src/webrtc/call';
|
||||
import AudioFeedArrayForCall from '../views/voip/AudioFeedArrayForCall';
|
||||
|
@ -232,10 +232,10 @@ class LoggedInView extends React.Component<IProps, IState> {
|
|||
onCollapsed: (_collapsed) => {
|
||||
collapsed = _collapsed;
|
||||
if (_collapsed) {
|
||||
dis.dispatch({action: "hide_left_panel"});
|
||||
dis.dispatch({ action: "hide_left_panel" });
|
||||
window.localStorage.setItem("mx_lhs_size", '0');
|
||||
} else {
|
||||
dis.dispatch({action: "show_left_panel"});
|
||||
dis.dispatch({ action: "show_left_panel" });
|
||||
}
|
||||
},
|
||||
onResized: (_size) => {
|
||||
|
@ -272,7 +272,7 @@ class LoggedInView extends React.Component<IProps, IState> {
|
|||
|
||||
onAccountData = (event) => {
|
||||
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({
|
||||
usageLimitDismissed: true,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
_calculateServerLimitToast(syncError: IState["syncErrorData"], usageLimitEventContent?: IUsageLimit) {
|
||||
const error = syncError && syncError.error && syncError.error.errcode === "M_RESOURCE_LIMIT_EXCEEDED";
|
||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||
|
||||
import React from 'react';
|
||||
import { Resizable } from 're-resizable';
|
||||
import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||
import { replaceableComponent } from "../../utils/replaceableComponent";
|
||||
|
||||
@replaceableComponent("structures.MainSplit")
|
||||
export default class MainSplit extends React.Component {
|
||||
|
@ -73,7 +73,7 @@ export default class MainSplit extends React.Component {
|
|||
onResize={this._onResize}
|
||||
onResizeStop={this._onResizeStop}
|
||||
className="mx_RightPanel_ResizeWrapper"
|
||||
handleClasses={{left: "mx_RightPanel_ResizeHandle"}}
|
||||
handleClasses={{ left: "mx_RightPanel_ResizeHandle" }}
|
||||
>
|
||||
{ panelView }
|
||||
</Resizable>;
|
||||
|
|
|
@ -34,7 +34,6 @@ import dis from "../../dispatcher/dispatcher";
|
|||
import Notifier from '../../Notifier';
|
||||
|
||||
import Modal from "../../Modal";
|
||||
import Tinter from "../../Tinter";
|
||||
import * as sdk from '../../index';
|
||||
import { showRoomInviteDialog, showStartChatInviteDialog } from '../../RoomInvite';
|
||||
import * as Rooms from '../../Rooms';
|
||||
|
@ -44,8 +43,8 @@ import * as Lifecycle from '../../Lifecycle';
|
|||
import '../../stores/LifecycleStore';
|
||||
import PageTypes from '../../PageTypes';
|
||||
|
||||
import createRoom, {IOpts} from "../../createRoom";
|
||||
import {_t, _td, getCurrentLanguage} from '../../languageHandler';
|
||||
import createRoom, { IOpts } from "../../createRoom";
|
||||
import { _t, _td, getCurrentLanguage } from '../../languageHandler';
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
import ThemeController from "../../settings/controllers/ThemeController";
|
||||
import { startAnyRegistrationFlow } from "../../Registration";
|
||||
|
@ -66,7 +65,7 @@ import {
|
|||
showToast as showAnalyticsToast,
|
||||
hideToast as hideAnalyticsToast,
|
||||
} from "../../toasts/AnalyticsToast";
|
||||
import {showToast as showNotificationsToast} from "../../toasts/DesktopNotificationsToast";
|
||||
import { showToast as showNotificationsToast } from "../../toasts/DesktopNotificationsToast";
|
||||
import { OpenToTabPayload } from "../../dispatcher/payloads/OpenToTabPayload";
|
||||
import ErrorDialog from "../views/dialogs/ErrorDialog";
|
||||
import { RoomNotificationStateStore } from "../../stores/notifications/RoomNotificationStateStore";
|
||||
|
@ -74,15 +73,15 @@ import { SettingLevel } from "../../settings/SettingLevel";
|
|||
import { leaveRoomBehaviour } from "../../utils/membership";
|
||||
import CreateCommunityPrototypeDialog from "../views/dialogs/CreateCommunityPrototypeDialog";
|
||||
import ThreepidInviteStore, { IThreepidInvite, IThreepidInviteWireFormat } from "../../stores/ThreepidInviteStore";
|
||||
import {UIFeature} from "../../settings/UIFeature";
|
||||
import { UIFeature } from "../../settings/UIFeature";
|
||||
import { CommunityPrototypeStore } from "../../stores/CommunityPrototypeStore";
|
||||
import DialPadModal from "../views/voip/DialPadModal";
|
||||
import { showToast as showMobileGuideToast } from '../../toasts/MobileGuideToast';
|
||||
import { shouldUseLoginForWelcome } from "../../utils/pages";
|
||||
import SpaceStore from "../../stores/SpaceStore";
|
||||
import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||
import { replaceableComponent } from "../../utils/replaceableComponent";
|
||||
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 SecurityCustomisations from "../../customisations/Security";
|
||||
|
||||
|
@ -283,11 +282,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
|
||||
this.pageChanging = false;
|
||||
|
||||
// check we have the right tint applied for this theme.
|
||||
// N.B. we don't call the whole of setTheme() here as we may be
|
||||
// racing with the theme CSS download finishing from index.js
|
||||
Tinter.tint();
|
||||
|
||||
// For PersistentElement
|
||||
this.state.resizeNotifier.on("middlePanelResized", this.dispatchTimelineResize);
|
||||
|
||||
|
@ -401,7 +395,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
if (SecurityCustomisations.SHOW_ENCRYPTION_SETUP_UI === false) {
|
||||
this.onLoggedIn();
|
||||
} else {
|
||||
this.setStateForNewView({view: Views.COMPLETE_SECURITY});
|
||||
this.setStateForNewView({ view: Views.COMPLETE_SECURITY });
|
||||
}
|
||||
} else if (await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")) {
|
||||
this.setStateForNewView({ view: Views.E2E_SETUP });
|
||||
|
@ -454,7 +448,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
let props = this.state.serverConfig;
|
||||
if (!props) props = this.props.serverConfig; // for unit tests
|
||||
if (!props) props = SdkConfig.get()["validated_server_config"];
|
||||
return {serverConfig: props};
|
||||
return { serverConfig: props };
|
||||
}
|
||||
|
||||
private loadSession() {
|
||||
|
@ -472,9 +466,9 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
if (!loadedSession) {
|
||||
// fall back to showing the welcome screen... unless we have a 3pid invite pending
|
||||
if (ThreepidInviteStore.instance.pickBestInvite()) {
|
||||
dis.dispatch({action: 'start_registration'});
|
||||
dis.dispatch({ action: 'start_registration' });
|
||||
} else {
|
||||
dis.dispatch({action: "view_welcome_page"});
|
||||
dis.dispatch({ action: "view_welcome_page" });
|
||||
}
|
||||
} else if (SettingsStore.getValue("analyticsOptIn")) {
|
||||
CountlyAnalytics.instance.enable(/* anonymous = */ false);
|
||||
|
@ -538,7 +532,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
action: 'do_after_sync_prepared',
|
||||
deferred_action: payload,
|
||||
});
|
||||
dis.dispatch({action: 'require_registration'});
|
||||
dis.dispatch({ action: 'require_registration' });
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -563,11 +557,11 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
|
||||
// redispatch the change with a more specific action
|
||||
dis.dispatch({action: 'id_server_changed'});
|
||||
dis.dispatch({ action: 'id_server_changed' });
|
||||
}
|
||||
break;
|
||||
case 'logout':
|
||||
dis.dispatch({action: "hangup_all"});
|
||||
dis.dispatch({ action: "hangup_all" });
|
||||
Lifecycle.logout();
|
||||
break;
|
||||
case 'require_registration':
|
||||
|
@ -624,7 +618,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
MatrixClientPeg.get().leave(payload.room_id).then(() => {
|
||||
modal.close();
|
||||
if (this.state.currentRoomId === payload.room_id) {
|
||||
dis.dispatch({action: 'view_home_page'});
|
||||
dis.dispatch({ action: 'view_home_page' });
|
||||
}
|
||||
}, (err) => {
|
||||
modal.close();
|
||||
|
@ -657,7 +651,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
const tabPayload = payload as OpenToTabPayload;
|
||||
const UserSettingsDialog = sdk.getComponent("dialogs.UserSettingsDialog");
|
||||
Modal.createTrackedDialog('User settings', '', UserSettingsDialog,
|
||||
{initialTabId: tabPayload.initialTabId},
|
||||
{ initialTabId: tabPayload.initialTabId },
|
||||
/*className=*/null, /*isPriority=*/false, /*isStatic=*/true);
|
||||
|
||||
// View the welcome or home page if we need something to look at
|
||||
|
@ -668,7 +662,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
this.createRoom(payload.public, payload.defaultName);
|
||||
break;
|
||||
case 'view_create_group': {
|
||||
let CreateGroupDialog = sdk.getComponent("dialogs.CreateGroupDialog")
|
||||
let CreateGroupDialog = sdk.getComponent("dialogs.CreateGroupDialog");
|
||||
if (SettingsStore.getValue("feature_communities_v2_prototypes")) {
|
||||
CreateGroupDialog = CreateCommunityPrototypeDialog;
|
||||
}
|
||||
|
@ -727,9 +721,9 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
// We just dispatch the page change rather than have to worry about
|
||||
// what the logic is for each of these branches.
|
||||
if (this.state.page_type === PageTypes.MyGroups) {
|
||||
dis.dispatch({action: 'view_last_screen'});
|
||||
dis.dispatch({ action: 'view_last_screen' });
|
||||
} else {
|
||||
dis.dispatch({action: 'view_my_groups'});
|
||||
dis.dispatch({ action: 'view_my_groups' });
|
||||
}
|
||||
break;
|
||||
case 'hide_left_panel':
|
||||
|
@ -770,7 +764,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
this.onLoggedOut();
|
||||
break;
|
||||
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.
|
||||
// Set ready to false now, then it'll be set to true when the sync
|
||||
// listener we set below fires.
|
||||
|
@ -1006,7 +1000,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
return;
|
||||
}
|
||||
this.notifyNewScreen('user/' + userId);
|
||||
this.setState({currentUserId: userId});
|
||||
this.setState({ currentUserId: userId });
|
||||
this.setPage(PageTypes.UserView);
|
||||
});
|
||||
}
|
||||
|
@ -1131,8 +1125,14 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
description: (
|
||||
<span>
|
||||
{ isSpace
|
||||
? _t("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}) }
|
||||
? _t(
|
||||
"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 }
|
||||
</span>
|
||||
),
|
||||
|
@ -1170,7 +1170,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}).catch((err) => {
|
||||
const errCode = err.errcode || _td("unknown error code");
|
||||
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")),
|
||||
});
|
||||
});
|
||||
|
@ -1254,7 +1254,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
if (welcomeUserRoom === null) {
|
||||
// We didn't redirect to the welcome user room, so show
|
||||
// the homepage.
|
||||
dis.dispatch({action: 'view_home_page', justRegistered: true});
|
||||
dis.dispatch({ action: 'view_home_page', justRegistered: true });
|
||||
}
|
||||
} else if (ThreepidInviteStore.instance.pickBestInvite()) {
|
||||
// The user has a 3pid invite pending - show them that
|
||||
|
@ -1263,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
|
||||
// our systems, but it's the safest we have for now.
|
||||
const params = ThreepidInviteStore.instance.translateToWireFormat(threepidInvite);
|
||||
this.showScreen(`room/${threepidInvite.roomId}`, params)
|
||||
this.showScreen(`room/${threepidInvite.roomId}`, params);
|
||||
} else {
|
||||
// The user has just logged in after registering,
|
||||
// so show the homepage.
|
||||
dis.dispatch({action: 'view_home_page', justRegistered: true});
|
||||
dis.dispatch({ action: 'view_home_page', justRegistered: true });
|
||||
}
|
||||
} else {
|
||||
this.showScreenAfterLogin();
|
||||
|
@ -1303,9 +1303,9 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
this.viewLastRoom();
|
||||
} else {
|
||||
if (MatrixClientPeg.get().isGuest()) {
|
||||
dis.dispatch({action: 'view_welcome_page'});
|
||||
dis.dispatch({ action: 'view_welcome_page' });
|
||||
} else {
|
||||
dis.dispatch({action: 'view_home_page'});
|
||||
dis.dispatch({ action: 'view_home_page' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1385,15 +1385,15 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
// 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
|
||||
// its own dispatch).
|
||||
dis.dispatch({action: 'sync_state', prevState, state});
|
||||
dis.dispatch({ action: 'sync_state', prevState, state });
|
||||
|
||||
if (state === "ERROR" || state === "RECONNECTING") {
|
||||
if (data.error instanceof InvalidStoreError) {
|
||||
Lifecycle.handleInvalidStoreError(data.error);
|
||||
}
|
||||
this.setState({syncError: data.error || true});
|
||||
this.setState({ syncError: data.error || true });
|
||||
} else if (this.state.syncError) {
|
||||
this.setState({syncError: null});
|
||||
this.setState({ syncError: null });
|
||||
}
|
||||
|
||||
this.updateStatusIndicator(state, prevState);
|
||||
|
@ -1567,16 +1567,12 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
key: 'verifreq_' + request.channel.transactionId,
|
||||
title: _t("Verification requested"),
|
||||
icon: "verification",
|
||||
props: {request},
|
||||
props: { request },
|
||||
component: sdk.getComponent("toasts.VerificationRequestToast"),
|
||||
priority: 90,
|
||||
});
|
||||
}
|
||||
});
|
||||
// Fire the tinter right on startup to ensure the default theme is applied
|
||||
// A later sync can/will correct the tint to be the right value for the user
|
||||
const colorScheme = SettingsStore.getValue("roomColor");
|
||||
Tinter.tint(colorScheme.primary_color, colorScheme.secondary_color);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1668,7 +1664,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
// TODO if logged in, skip SSO
|
||||
let cli = MatrixClientPeg.get();
|
||||
if (!cli) {
|
||||
const {hsUrl, isUrl} = this.props.serverConfig;
|
||||
const { hsUrl, isUrl } = this.props.serverConfig;
|
||||
cli = createClient({
|
||||
baseUrl: hsUrl,
|
||||
idBaseUrl: isUrl,
|
||||
|
@ -1792,7 +1788,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
|
||||
onAliasClick(event: MouseEvent, alias: string) {
|
||||
event.preventDefault();
|
||||
dis.dispatch({action: 'view_room', room_alias: alias});
|
||||
dis.dispatch({ action: 'view_room', room_alias: alias });
|
||||
}
|
||||
|
||||
onUserClick(event: MouseEvent, userId: string) {
|
||||
|
@ -1808,7 +1804,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
|
||||
onGroupClick(event: MouseEvent, groupId: string) {
|
||||
event.preventDefault();
|
||||
dis.dispatch({action: 'view_group', group_id: groupId});
|
||||
dis.dispatch({ action: 'view_group', group_id: groupId });
|
||||
}
|
||||
|
||||
onLogoutClick(event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) {
|
||||
|
@ -1870,14 +1866,14 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
onSendEvent(roomId: string, event: MatrixEvent) {
|
||||
const cli = MatrixClientPeg.get();
|
||||
if (!cli) {
|
||||
dis.dispatch({action: 'message_send_failed'});
|
||||
dis.dispatch({ action: 'message_send_failed' });
|
||||
return;
|
||||
}
|
||||
|
||||
cli.sendEvent(roomId, event.getType(), event.getContent()).then(() => {
|
||||
dis.dispatch({action: 'message_sent'});
|
||||
dis.dispatch({ action: 'message_sent' });
|
||||
}, (err) => {
|
||||
dis.dispatch({action: 'message_send_failed'});
|
||||
dis.dispatch({ action: 'message_send_failed' });
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1924,7 +1920,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
|
||||
onServerConfigChange = (serverConfig: ValidatedServerConfig) => {
|
||||
this.setState({serverConfig});
|
||||
this.setState({ serverConfig });
|
||||
};
|
||||
|
||||
private makeRegistrationUrl = (params: {[key: string]: string}) => {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -24,7 +24,7 @@ import dis from '../../dispatcher/dispatcher';
|
|||
import AccessibleButton from '../views/elements/AccessibleButton';
|
||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||
import AutoHideScrollbar from "./AutoHideScrollbar";
|
||||
import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||
import { replaceableComponent } from "../../utils/replaceableComponent";
|
||||
import BetaCard from "../views/beta/BetaCard";
|
||||
|
||||
@replaceableComponent("structures.MyGroups")
|
||||
|
@ -41,19 +41,19 @@ export default class MyGroups extends React.Component {
|
|||
}
|
||||
|
||||
_onCreateGroupClick = () => {
|
||||
dis.dispatch({action: 'view_create_group'});
|
||||
dis.dispatch({ action: 'view_create_group' });
|
||||
};
|
||||
|
||||
_fetch() {
|
||||
this.context.getJoinedGroups().then((result) => {
|
||||
this.setState({groups: result.groups, error: null});
|
||||
this.setState({ groups: result.groups, error: null });
|
||||
}, (err) => {
|
||||
if (err.errcode === 'M_GUEST_ACCESS_FORBIDDEN') {
|
||||
// Indicate that the guest isn't in any groups (which should be true)
|
||||
this.setState({groups: [], error: null});
|
||||
this.setState({ groups: [], error: null });
|
||||
return;
|
||||
}
|
||||
this.setState({groups: null, error: err});
|
||||
this.setState({ groups: null, error: err });
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,7 @@ export default class MyGroups extends React.Component {
|
|||
</div>
|
||||
{/*<div className="mx_MyGroups_joinBox mx_MyGroups_headerCard">
|
||||
<AccessibleButton className='mx_MyGroups_headerCard_button' onClick={this._onJoinGroupClick}>
|
||||
<TintableSvg src={require("../../../res/img/icons-create-room.svg")} width="50" height="50" />
|
||||
<img src={require("../../../res/img/icons-create-room.svg")} width="50" height="50" />
|
||||
</AccessibleButton>
|
||||
<div className="mx_MyGroups_headerCard_content">
|
||||
<div className="mx_MyGroups_headerCard_header">
|
||||
|
|
|
@ -18,7 +18,7 @@ import * as React from "react";
|
|||
import { ComponentClass } from "../../@types/common";
|
||||
import NonUrgentToastStore from "../../stores/NonUrgentToastStore";
|
||||
import { UPDATE_EVENT } from "../../stores/AsyncStore";
|
||||
import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||
import { replaceableComponent } from "../../utils/replaceableComponent";
|
||||
|
||||
interface IProps {
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ export default class NonUrgentToastContainer extends React.PureComponent<IProps,
|
|||
}
|
||||
|
||||
private onUpdateToasts = () => {
|
||||
this.setState({toasts: NonUrgentToastStore.instance.components});
|
||||
this.setState({ toasts: NonUrgentToastStore.instance.components });
|
||||
};
|
||||
|
||||
public render() {
|
||||
|
|
|
@ -22,6 +22,7 @@ import BaseCard from "../views/right_panel/BaseCard";
|
|||
import { replaceableComponent } from "../../utils/replaceableComponent";
|
||||
import TimelinePanel from "./TimelinePanel";
|
||||
import Spinner from "../views/elements/Spinner";
|
||||
import { TileShape } from "../views/rooms/EventTile";
|
||||
|
||||
interface IProps {
|
||||
onClose(): void;
|
||||
|
@ -48,7 +49,7 @@ export default class NotificationPanel extends React.PureComponent<IProps> {
|
|||
manageReadMarkers={false}
|
||||
timelineSet={timelineSet}
|
||||
showUrlPreview={false}
|
||||
tileShape="notif"
|
||||
tileShape={TileShape.Notif}
|
||||
empty={emptyState}
|
||||
alwaysShowTimestamps={true}
|
||||
/>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue