Merge branch 'develop' of github.com:matrix-org/matrix-react-sdk into t3chguy/ts/8

 Conflicts:
	src/components/structures/MessagePanel.tsx
	src/components/structures/ScrollPanel.tsx
	src/components/structures/TimelinePanel.tsx
	src/components/views/elements/ErrorBoundary.tsx
	src/components/views/elements/EventListSummary.tsx
	src/components/views/messages/TileErrorBoundary.tsx
This commit is contained in:
Michael Telatynski 2021-06-29 22:14:40 +01:00
commit 8f4879ea96
638 changed files with 3442 additions and 4515 deletions

View file

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

View file

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

View file

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

View file

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

View file

@ -134,12 +134,15 @@ limitations under the License.
.mx_Toast_buttons { .mx_Toast_buttons {
float: right; float: right;
display: flex; display: flex;
gap: 5px;
.mx_AccessibleButton { .mx_AccessibleButton {
min-width: 96px; min-width: 96px;
box-sizing: border-box; box-sizing: border-box;
} }
.mx_AccessibleButton + .mx_AccessibleButton {
margin-left: 5px;
}
} }
.mx_Toast_description { .mx_Toast_description {

View file

@ -189,7 +189,6 @@ export default class AddThreepid {
// pop up an interactive auth dialog // pop up an interactive auth dialog
const InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog"); const InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog");
const dialogAesthetics = { const dialogAesthetics = {
[SSOAuthEntry.PHASE_PREAUTH]: { [SSOAuthEntry.PHASE_PREAUTH]: {
title: _t("Use Single Sign On to continue"), title: _t("Use Single Sign On to continue"),

View file

@ -80,7 +80,7 @@ import CountlyAnalytics from "./CountlyAnalytics";
import { UIFeature } from "./settings/UIFeature"; import { UIFeature } from "./settings/UIFeature";
import { CallError } from "matrix-js-sdk/src/webrtc/call"; import { CallError } from "matrix-js-sdk/src/webrtc/call";
import { logger } from 'matrix-js-sdk/src/logger'; import { logger } from 'matrix-js-sdk/src/logger';
import DesktopCapturerSourcePicker from "./components/views/elements/DesktopCapturerSourcePicker" import DesktopCapturerSourcePicker from "./components/views/elements/DesktopCapturerSourcePicker";
import { Action } from './dispatcher/actions'; import { Action } from './dispatcher/actions';
import VoipUserMapper from './VoipUserMapper'; import VoipUserMapper from './VoipUserMapper';
import { addManagedHybridWidget, isManagedHybridWidgetEnabled } from './widgets/ManagedHybrid'; import { addManagedHybridWidget, isManagedHybridWidgetEnabled } from './widgets/ManagedHybrid';
@ -166,7 +166,7 @@ export default class CallHandler extends EventEmitter {
static sharedInstance() { static sharedInstance() {
if (!window.mxCallHandler) { if (!window.mxCallHandler) {
window.mxCallHandler = new CallHandler() window.mxCallHandler = new CallHandler();
} }
return window.mxCallHandler; return window.mxCallHandler;
@ -185,7 +185,7 @@ export default class CallHandler extends EventEmitter {
const nativeUser = this.assertedIdentityNativeUsers[call.callId]; const nativeUser = this.assertedIdentityNativeUsers[call.callId];
if (nativeUser) { if (nativeUser) {
const room = findDMForUser(MatrixClientPeg.get(), nativeUser); const room = findDMForUser(MatrixClientPeg.get(), nativeUser);
if (room) return room.roomId if (room) return room.roomId;
} }
} }
@ -299,7 +299,7 @@ export default class CallHandler extends EventEmitter {
action: 'incoming_call', action: 'incoming_call',
call: call, call: call,
}, true); }, true);
} };
getCallForRoom(roomId: string): MatrixCall { getCallForRoom(roomId: string): MatrixCall {
return this.calls.get(roomId) || null; return this.calls.get(roomId) || null;
@ -816,7 +816,7 @@ export default class CallHandler extends EventEmitter {
Analytics.trackEvent('voip', 'receiveCall', 'type', call.type); Analytics.trackEvent('voip', 'receiveCall', 'type', call.type);
console.log("Adding call for room ", mappedRoomId); console.log("Adding call for room ", mappedRoomId);
this.calls.set(mappedRoomId, call) this.calls.set(mappedRoomId, call);
this.emit(CallHandlerEvent.CallsChanged, this.calls); this.emit(CallHandlerEvent.CallsChanged, this.calls);
this.setCallListeners(call); this.setCallListeners(call);
@ -872,7 +872,7 @@ export default class CallHandler extends EventEmitter {
this.dialNumber(payload.number); this.dialNumber(payload.number);
break; break;
} }
} };
private async dialNumber(number: string) { private async dialNumber(number: string) {
const results = await this.pstnLookup(number); const results = await this.pstnLookup(number);

View file

@ -338,8 +338,8 @@ const getRoomStats = (roomId: string) => {
"is_encrypted": cli?.isRoomEncrypted(roomId), "is_encrypted": cli?.isRoomEncrypted(roomId),
// eslint-disable-next-line camelcase // eslint-disable-next-line camelcase
"is_public": room?.currentState.getStateEvents("m.room.join_rules", "")?.getContent()?.join_rule === "public", "is_public": room?.currentState.getStateEvents("m.room.join_rules", "")?.getContent()?.join_rule === "public",
} };
} };
// async wrapper for regex-powered String.prototype.replace // async wrapper for regex-powered String.prototype.replace
const strReplaceAsync = async (str: string, regex: RegExp, fn: (...args: string[]) => Promise<string>) => { const strReplaceAsync = async (str: string, regex: RegExp, fn: (...args: string[]) => Promise<string>) => {
@ -414,7 +414,7 @@ export default class CountlyAnalytics {
this.anonymous = anonymous; this.anonymous = anonymous;
if (anonymous) { if (anonymous) {
await this.changeUserKey(randomString(64)) await this.changeUserKey(randomString(64));
} else { } else {
await this.changeUserKey(await hashHex(MatrixClientPeg.get().getUserId()), true); await this.changeUserKey(await hashHex(MatrixClientPeg.get().getUserId()), true);
} }
@ -438,7 +438,7 @@ export default class CountlyAnalytics {
await this.track("Opt-Out" ); await this.track("Opt-Out" );
this.endSession(); this.endSession();
window.clearInterval(this.heartbeatIntervalId); window.clearInterval(this.heartbeatIntervalId);
window.clearTimeout(this.activityIntervalId) window.clearTimeout(this.activityIntervalId);
this.baseUrl = null; this.baseUrl = null;
// remove listeners bound in trackSessions() // remove listeners bound in trackSessions()
window.removeEventListener("beforeunload", this.endSession); window.removeEventListener("beforeunload", this.endSession);
@ -669,7 +669,7 @@ export default class CountlyAnalytics {
count, count,
platform: this.appPlatform, platform: this.appPlatform,
app_version: this.appVersion, app_version: this.appVersion,
} };
this.pendingEvents.push(ev); this.pendingEvents.push(ev);
if (this.pendingEvents.length > MAX_PENDING_EVENTS) { if (this.pendingEvents.length > MAX_PENDING_EVENTS) {
@ -680,7 +680,7 @@ export default class CountlyAnalytics {
private getOrientation = (): Orientation => { private getOrientation = (): Orientation => {
return window.matchMedia("(orientation: landscape)").matches return window.matchMedia("(orientation: landscape)").matches
? Orientation.Landscape ? Orientation.Landscape
: Orientation.Portrait : Orientation.Portrait;
}; };
private reportOrientation = () => { private reportOrientation = () => {
@ -749,7 +749,7 @@ export default class CountlyAnalytics {
const request: Parameters<typeof CountlyAnalytics.prototype.request>[0] = { const request: Parameters<typeof CountlyAnalytics.prototype.request>[0] = {
begin_session: 1, begin_session: 1,
user_details: JSON.stringify(userDetails), user_details: JSON.stringify(userDetails),
} };
const metrics = this.getMetrics(); const metrics = this.getMetrics();
if (metrics) { if (metrics) {
@ -773,7 +773,7 @@ export default class CountlyAnalytics {
private endSession = () => { private endSession = () => {
if (this.sessionStarted) { if (this.sessionStarted) {
window.removeEventListener("resize", this.reportOrientation) window.removeEventListener("resize", this.reportOrientation);
this.reportViewDuration(); this.reportViewDuration();
this.request({ this.request({

View file

@ -138,7 +138,7 @@ export function getHtmlText(insaneHtml: string): string {
selfClosing: [], selfClosing: [],
allowedSchemes: [], allowedSchemes: [],
disallowedTagsMode: 'discard', disallowedTagsMode: 'discard',
}) });
} }
/** /**

View file

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

View file

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

View file

@ -190,7 +190,6 @@ export default class Login {
} }
} }
/** /**
* Send a login request to the given server, and format the response * Send a login request to the given server, and format the response
* as a MatrixClientCreds * as a MatrixClientCreds

View file

@ -15,7 +15,6 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import classNames from 'classnames'; import classNames from 'classnames';

View file

@ -78,7 +78,7 @@ class Presence {
this.setState(State.Online); this.setState(State.Online);
this.unavailableTimer.restart(); this.unavailableTimer.restart();
} }
} };
/** /**
* Set the presence state. * Set the presence state.

View file

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

View file

@ -208,7 +208,6 @@ Example:
] ]
} }
membership_state AND bot_options membership_state AND bot_options
-------------------------------- --------------------------------
Get the content of the "m.room.member" or "m.room.bot.options" state event respectively. Get the content of the "m.room.member" or "m.room.bot.options" state event respectively.

View file

@ -135,7 +135,7 @@ async function getSecretStorageKey(
const keyFromCustomisations = SecurityCustomisations.getSecretStorageKey?.(); const keyFromCustomisations = SecurityCustomisations.getSecretStorageKey?.();
if (keyFromCustomisations) { if (keyFromCustomisations) {
console.log("Using key from security customisations (secret storage)") console.log("Using key from security customisations (secret storage)");
cacheSecretStorageKey(keyId, keyInfo, keyFromCustomisations); cacheSecretStorageKey(keyId, keyInfo, keyFromCustomisations);
return [keyId, keyFromCustomisations]; return [keyId, keyFromCustomisations];
} }
@ -185,7 +185,7 @@ export async function getDehydrationKey(
): Promise<Uint8Array> { ): Promise<Uint8Array> {
const keyFromCustomisations = SecurityCustomisations.getSecretStorageKey?.(); const keyFromCustomisations = SecurityCustomisations.getSecretStorageKey?.();
if (keyFromCustomisations) { if (keyFromCustomisations) {
console.log("Using key from security customisations (dehydration)") console.log("Using key from security customisations (dehydration)");
return keyFromCustomisations; return keyFromCustomisations;
} }

View file

@ -1,4 +1,3 @@
//@flow
/* /*
Copyright 2017 Aviral Dasgupta Copyright 2017 Aviral Dasgupta

View file

@ -47,7 +47,7 @@ import { EffectiveMembership, getEffectiveMembership, leaveRoomBehaviour } from
import SdkConfig from "./SdkConfig"; import SdkConfig from "./SdkConfig";
import SettingsStore from "./settings/SettingsStore"; import SettingsStore from "./settings/SettingsStore";
import { UIFeature } from "./settings/UIFeature"; import { UIFeature } from "./settings/UIFeature";
import {CHAT_EFFECTS} from "./effects" import { CHAT_EFFECTS } from "./effects";
import CallHandler from "./CallHandler"; import CallHandler from "./CallHandler";
import { guessAndSetDMRoom } from "./Rooms"; import { guessAndSetDMRoom } from "./Rooms";
@ -1176,7 +1176,7 @@ export const Commands = [
})()); })());
}, },
category: CommandCategories.effects, category: CommandCategories.effects,
}) });
}), }),
]; ];

View file

@ -112,7 +112,7 @@ function textForMemberEvent(ev): () => string | null {
targetName, targetName,
reason, reason,
}) })
: _t('%(senderName)s withdrew %(targetName)s\'s invitation', { senderName, targetName }) : _t('%(senderName)s withdrew %(targetName)s\'s invitation', { senderName, targetName });
} else if (prevContent.membership === "join") { } else if (prevContent.membership === "join") {
return () => reason return () => reason
? _t('%(senderName)s kicked %(targetName)s: %(reason)s', { ? _t('%(senderName)s kicked %(targetName)s: %(reason)s', {
@ -492,7 +492,7 @@ const onPinnedMessagesClick = (): void => {
phase: RightPanelPhases.PinnedMessages, phase: RightPanelPhases.PinnedMessages,
allowClose: false, allowClose: false,
}); });
} };
function textForPinnedEvent(event: MatrixEvent, allowJSX: boolean): () => string | JSX.Element | null { function textForPinnedEvent(event: MatrixEvent, allowJSX: boolean): () => string | JSX.Element | null {
if (!SettingsStore.getValue("feature_pinning")) return null; if (!SettingsStore.getValue("feature_pinning")) return null;

View file

@ -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;

View file

@ -68,7 +68,6 @@ export default class CommandProvider extends AutocompleteProvider {
} }
} }
return matches.filter(cmd => cmd.isEnabled()).map((result) => { return matches.filter(cmd => cmd.isEnabled()).map((result) => {
let completion = result.getCommand() + ' '; let completion = result.getCommand() + ' ';
const usedAlias = result.aliases.find(alias => `/${alias}` === command[1]); const usedAlias = result.aliases.find(alias => `/${alias}` === command[1]);

View file

@ -126,12 +126,11 @@ class CategoryRoomList extends React.Component {
}; };
render() { render() {
const TintableSvg = sdk.getComponent("elements.TintableSvg");
const addButton = this.props.editing ? const addButton = this.props.editing ?
(<AccessibleButton className="mx_GroupView_featuredThings_addButton" (<AccessibleButton className="mx_GroupView_featuredThings_addButton"
onClick={this.onAddRoomsToSummaryClicked} 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"> <div className="mx_GroupView_featuredThings_addButton_label">
{ _t('Add a Room') } { _t('Add a Room') }
</div> </div>
@ -300,10 +299,9 @@ class RoleUserList extends React.Component {
}; };
render() { render() {
const TintableSvg = sdk.getComponent("elements.TintableSvg");
const addButton = this.props.editing ? const addButton = this.props.editing ?
(<AccessibleButton className="mx_GroupView_featuredThings_addButton" onClick={this.onAddUsersClicked}> (<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"> <div className="mx_GroupView_featuredThings_addButton_label">
{ _t('Add a User') } { _t('Add a User') }
</div> </div>
@ -363,7 +361,10 @@ class FeaturedUser extends React.Component {
"Failed to remove a user from the summary of %(groupId)s", "Failed to remove a user from the summary of %(groupId)s",
{ groupId: this.props.groupId }, { groupId: this.props.groupId },
), ),
description: _t("The user '%(displayName)s' could not be removed from the summary.", {displayName}), description: _t(
"The user '%(displayName)s' could not be removed from the summary.",
{ displayName },
),
}, },
); );
}); });
@ -855,7 +856,6 @@ export default class GroupView extends React.Component {
_getRoomsNode() { _getRoomsNode() {
const RoomDetailList = sdk.getComponent('rooms.RoomDetailList'); const RoomDetailList = sdk.getComponent('rooms.RoomDetailList');
const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const TintableSvg = sdk.getComponent('elements.TintableSvg');
const Spinner = sdk.getComponent('elements.Spinner'); const Spinner = sdk.getComponent('elements.Spinner');
const TooltipButton = sdk.getComponent('elements.TooltipButton'); const TooltipButton = sdk.getComponent('elements.TooltipButton');
@ -871,7 +871,7 @@ export default class GroupView extends React.Component {
onClick={this._onAddRoomsClick} onClick={this._onAddRoomsClick}
> >
<div className="mx_GroupView_rooms_header_addRow_button"> <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>
<div className="mx_GroupView_rooms_header_addRow_label"> <div className="mx_GroupView_rooms_header_addRow_label">
{ _t('Add rooms to this community') } { _t('Add rooms to this community') }

View file

@ -117,7 +117,6 @@ const HomePage: React.FC<IProps> = ({ justRegistered = false }) => {
</React.Fragment>; </React.Fragment>;
} }
return <AutoHideScrollbar className="mx_HomePage mx_HomePage_default"> return <AutoHideScrollbar className="mx_HomePage mx_HomePage_default">
<div className="mx_HomePage_default_wrapper"> <div className="mx_HomePage_default_wrapper">
{ introSection } { introSection }

View file

@ -35,7 +35,7 @@ export default class HostSignupAction extends React.PureComponent<IProps, IState
private openDialog = async () => { private openDialog = async () => {
this.props.onClick?.(); this.props.onClick?.();
await HostSignupStore.instance.setHostSignupActive(true); await HostSignupStore.instance.setHostSignupActive(true);
} };
public render(): React.ReactNode { public render(): React.ReactNode {
const hostSignupConfig = SdkConfig.get().hostSignup; const hostSignupConfig = SdkConfig.get().hostSignup;

View file

@ -70,7 +70,6 @@ export default class IndicatorScrollbar extends React.Component {
this._autoHideScrollbar = autoHideScrollbar; this._autoHideScrollbar = autoHideScrollbar;
} }
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
const prevLen = prevProps && prevProps.children && prevProps.children.length || 0; const prevLen = prevProps && prevProps.children && prevProps.children.length || 0;
const curLen = this.props.children && this.props.children.length || 0; const curLen = this.props.children && this.props.children.length || 0;

View file

@ -127,7 +127,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
private onDialPad = () => { private onDialPad = () => {
dis.fire(Action.OpenDialPad); dis.fire(Action.OpenDialPad);
} };
private onExplore = () => { private onExplore = () => {
dis.fire(Action.ViewRoomDirectory); dis.fire(Action.ViewRoomDirectory);
@ -136,7 +136,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
private refreshStickyHeaders = () => { private refreshStickyHeaders = () => {
if (!this.listContainerRef.current) return; // ignore: no headers to sticky if (!this.listContainerRef.current) return; // ignore: no headers to sticky
this.handleStickyHeaders(this.listContainerRef.current); this.handleStickyHeaders(this.listContainerRef.current);
} };
private onBreadcrumbsUpdate = () => { private onBreadcrumbsUpdate = () => {
const newVal = BreadcrumbsStore.instance.visible; const newVal = BreadcrumbsStore.instance.visible;

View file

@ -319,7 +319,7 @@ class LoggedInView extends React.Component<IProps, IState> {
this.setState({ this.setState({
usageLimitDismissed: true, usageLimitDismissed: true,
}); });
} };
_calculateServerLimitToast(syncError: IState["syncErrorData"], usageLimitEventContent?: IUsageLimit) { _calculateServerLimitToast(syncError: IState["syncErrorData"], usageLimitEventContent?: IUsageLimit) {
const error = syncError && syncError.error && syncError.error.errcode === "M_RESOURCE_LIMIT_EXCEEDED"; const error = syncError && syncError.error && syncError.error.errcode === "M_RESOURCE_LIMIT_EXCEEDED";

View file

@ -34,7 +34,6 @@ import dis from "../../dispatcher/dispatcher";
import Notifier from '../../Notifier'; import Notifier from '../../Notifier';
import Modal from "../../Modal"; import Modal from "../../Modal";
import Tinter from "../../Tinter";
import * as sdk from '../../index'; import * as sdk from '../../index';
import { showRoomInviteDialog, showStartChatInviteDialog } from '../../RoomInvite'; import { showRoomInviteDialog, showStartChatInviteDialog } from '../../RoomInvite';
import * as Rooms from '../../Rooms'; import * as Rooms from '../../Rooms';
@ -283,11 +282,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
this.pageChanging = false; 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 // For PersistentElement
this.state.resizeNotifier.on("middlePanelResized", this.dispatchTimelineResize); this.state.resizeNotifier.on("middlePanelResized", this.dispatchTimelineResize);
@ -668,7 +662,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
this.createRoom(payload.public, payload.defaultName); this.createRoom(payload.public, payload.defaultName);
break; break;
case 'view_create_group': { case 'view_create_group': {
let CreateGroupDialog = sdk.getComponent("dialogs.CreateGroupDialog") let CreateGroupDialog = sdk.getComponent("dialogs.CreateGroupDialog");
if (SettingsStore.getValue("feature_communities_v2_prototypes")) { if (SettingsStore.getValue("feature_communities_v2_prototypes")) {
CreateGroupDialog = CreateCommunityPrototypeDialog; CreateGroupDialog = CreateCommunityPrototypeDialog;
} }
@ -1131,8 +1125,14 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
description: ( description: (
<span> <span>
{ isSpace { isSpace
? _t("Are you sure you want to leave the space '%(spaceName)s'?", {spaceName: roomToLeave.name}) ? _t(
: _t("Are you sure you want to leave the room '%(roomName)s'?", {roomName: roomToLeave.name}) } "Are you sure you want to leave the space '%(spaceName)s'?",
{ spaceName: roomToLeave.name },
)
: _t(
"Are you sure you want to leave the room '%(roomName)s'?",
{ roomName: roomToLeave.name },
)}
{ warnings } { warnings }
</span> </span>
), ),
@ -1263,7 +1263,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
// HACK: This is a pretty brutal way of threading the invite back through // HACK: This is a pretty brutal way of threading the invite back through
// our systems, but it's the safest we have for now. // our systems, but it's the safest we have for now.
const params = ThreepidInviteStore.instance.translateToWireFormat(threepidInvite); const params = ThreepidInviteStore.instance.translateToWireFormat(threepidInvite);
this.showScreen(`room/${threepidInvite.roomId}`, params) this.showScreen(`room/${threepidInvite.roomId}`, params);
} else { } else {
// The user has just logged in after registering, // The user has just logged in after registering,
// so show the homepage. // so show the homepage.
@ -1573,10 +1573,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
}); });
} }
}); });
// 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);
} }
/** /**

View file

@ -123,7 +123,7 @@ export default class MyGroups extends React.Component {
</div> </div>
{/*<div className="mx_MyGroups_joinBox mx_MyGroups_headerCard"> {/*<div className="mx_MyGroups_joinBox mx_MyGroups_headerCard">
<AccessibleButton className='mx_MyGroups_headerCard_button' onClick={this._onJoinGroupClick}> <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> </AccessibleButton>
<div className="mx_MyGroups_headerCard_content"> <div className="mx_MyGroups_headerCard_content">
<div className="mx_MyGroups_headerCard_header"> <div className="mx_MyGroups_headerCard_header">

View file

@ -45,7 +45,6 @@ import ScrollPanel from "./ScrollPanel";
import Spinner from "../views/elements/Spinner"; import Spinner from "../views/elements/Spinner";
import { ActionPayload } from "../../dispatcher/payloads"; import { ActionPayload } from "../../dispatcher/payloads";
const MAX_NAME_LENGTH = 80; const MAX_NAME_LENGTH = 80;
const MAX_TOPIC_LENGTH = 800; const MAX_TOPIC_LENGTH = 800;
@ -95,7 +94,7 @@ interface IPublicRoomsRequest {
@replaceableComponent("structures.RoomDirectory") @replaceableComponent("structures.RoomDirectory")
export default class RoomDirectory extends React.Component<IProps, IState> { export default class RoomDirectory extends React.Component<IProps, IState> {
private readonly startTime: number; private readonly startTime: number;
private unmounted = false private unmounted = false;
private nextBatch: string = null; private nextBatch: string = null;
private filterTimeout: NodeJS.Timeout; private filterTimeout: NodeJS.Timeout;
private protocols: Protocols; private protocols: Protocols;

View file

@ -37,7 +37,6 @@ import Modal from '../../Modal';
import * as sdk from '../../index'; import * as sdk from '../../index';
import CallHandler, { PlaceCallType } from '../../CallHandler'; import CallHandler, { PlaceCallType } from '../../CallHandler';
import dis from '../../dispatcher/dispatcher'; import dis from '../../dispatcher/dispatcher';
import Tinter from '../../Tinter';
import rateLimitedFunc from '../../ratelimitedfunc'; import rateLimitedFunc from '../../ratelimitedfunc';
import * as Rooms from '../../Rooms'; import * as Rooms from '../../Rooms';
import eventSearch, { searchPagination } from '../../Searching'; import eventSearch, { searchPagination } from '../../Searching';
@ -287,7 +286,7 @@ export default class RoomView extends React.Component<IProps, IState> {
if (this.state.room) { if (this.state.room) {
this.checkWidgets(this.state.room); this.checkWidgets(this.state.room);
} }
} };
private checkWidgets = (room) => { private checkWidgets = (room) => {
this.setState({ this.setState({
@ -679,10 +678,6 @@ export default class RoomView extends React.Component<IProps, IState> {
// cancel any pending calls to the rate_limited_funcs // cancel any pending calls to the rate_limited_funcs
this.updateRoomMembers.cancelPendingCall(); this.updateRoomMembers.cancelPendingCall();
// no need to do this as Dir & Settings are now overlays. It just burnt CPU.
// console.log("Tinter.tint from RoomView.unmount");
// Tinter.tint(); // reset colourscheme
for (const watcher of this.settingWatchers) { for (const watcher of this.settingWatchers) {
SettingsStore.unwatchSetting(watcher); SettingsStore.unwatchSetting(watcher);
} }
@ -698,7 +693,7 @@ export default class RoomView extends React.Component<IProps, IState> {
replyingToEvent: this.state.replyToEvent, replyingToEvent: this.state.replyToEvent,
}); });
} }
} };
private onRightPanelStoreUpdate = () => { private onRightPanelStoreUpdate = () => {
this.setState({ this.setState({
@ -1062,10 +1057,6 @@ export default class RoomView extends React.Component<IProps, IState> {
private updateTint() { private updateTint() {
const room = this.state.room; const room = this.state.room;
if (!room) return; if (!room) return;
console.log("Tinter.tint from updateTint");
const colorScheme = SettingsStore.getValue("roomColor", room.roomId);
Tinter.tint(colorScheme.primary_color, colorScheme.secondary_color);
} }
private onAccountData = (event: MatrixEvent) => { private onAccountData = (event: MatrixEvent) => {
@ -1079,12 +1070,7 @@ export default class RoomView extends React.Component<IProps, IState> {
private onRoomAccountData = (event: MatrixEvent, room: Room) => { private onRoomAccountData = (event: MatrixEvent, room: Room) => {
if (room.roomId == this.state.roomId) { if (room.roomId == this.state.roomId) {
const type = event.getType(); const type = event.getType();
if (type === "org.matrix.room.color_scheme") { if (type === "org.matrix.room.preview_urls" || type === "im.vector.web.settings") {
const colorScheme = event.getContent();
// XXX: we should validate the event
console.log("Tinter.tint from onRoomAccountData");
Tinter.tint(colorScheme.primary_color, colorScheme.secondary_color);
} else if (type === "org.matrix.room.preview_urls" || type === "im.vector.web.settings") {
// non-e2ee url previews are stored in legacy event type `org.matrix.room.preview_urls` // non-e2ee url previews are stored in legacy event type `org.matrix.room.preview_urls`
this.updatePreviewUrlVisibility(room); this.updatePreviewUrlVisibility(room);
} }

View file

@ -15,7 +15,6 @@ limitations under the License.
*/ */
import React, { createRef, CSSProperties, ReactNode, SyntheticEvent, KeyboardEvent } from "react"; import React, { createRef, CSSProperties, ReactNode, SyntheticEvent, KeyboardEvent } from "react";
import Timer from '../../utils/Timer'; import Timer from '../../utils/Timer';
import AutoHideScrollbar from "./AutoHideScrollbar"; import AutoHideScrollbar from "./AutoHideScrollbar";
import { replaceableComponent } from "../../utils/replaceableComponent"; import { replaceableComponent } from "../../utils/replaceableComponent";

View file

@ -112,12 +112,12 @@ const Tile: React.FC<ITileProps> = ({
ev.preventDefault(); ev.preventDefault();
ev.stopPropagation(); ev.stopPropagation();
onViewRoomClick(false); onViewRoomClick(false);
} };
const onJoinClick = (ev: ButtonEvent) => { const onJoinClick = (ev: ButtonEvent) => {
ev.preventDefault(); ev.preventDefault();
ev.stopPropagation(); ev.stopPropagation();
onViewRoomClick(true); onViewRoomClick(true);
} };
let button; let button;
if (joinedRoom) { if (joinedRoom) {
@ -137,7 +137,7 @@ const Tile: React.FC<ITileProps> = ({
} else { } else {
checkbox = <TextWithTooltip checkbox = <TextWithTooltip
tooltip={_t("You don't have permission")} tooltip={_t("You don't have permission")}
onClick={ev => { ev.stopPropagation() }} onClick={ev => { ev.stopPropagation(); }}
> >
<StyledCheckbox disabled={true} /> <StyledCheckbox disabled={true} />
</TextWithTooltip>; </TextWithTooltip>;
@ -340,7 +340,7 @@ export const HierarchyLevel = ({
</Tile> </Tile>
)) ))
} }
</React.Fragment> </React.Fragment>;
}; };
// mutate argument refreshToken to force a reload // mutate argument refreshToken to force a reload

View file

@ -37,7 +37,7 @@ import * as Email from "../../email";
import defaultDispatcher from "../../dispatcher/dispatcher"; import defaultDispatcher from "../../dispatcher/dispatcher";
import dis from "../../dispatcher/dispatcher"; import dis from "../../dispatcher/dispatcher";
import { Action } from "../../dispatcher/actions"; import { Action } from "../../dispatcher/actions";
import ResizeNotifier from "../../utils/ResizeNotifier" import ResizeNotifier from "../../utils/ResizeNotifier";
import MainSplit from './MainSplit'; import MainSplit from './MainSplit';
import ErrorBoundary from "../views/elements/ErrorBoundary"; import ErrorBoundary from "../views/elements/ErrorBoundary";
import { ActionPayload } from "../../dispatcher/payloads"; import { ActionPayload } from "../../dispatcher/payloads";
@ -162,7 +162,7 @@ const SpaceInfo = ({ space }) => {
</AccessibleButton> </AccessibleButton>
) : null} ) : null}
</RoomMemberCount> } </RoomMemberCount> }
</div> </div>;
}; };
const onBetaClick = () => { const onBetaClick = () => {
@ -592,14 +592,14 @@ const SpaceSetupPrivateScope = ({ space, justCreatedOpts, onFinished }) => {
<AccessibleButton <AccessibleButton
className="mx_SpaceRoomView_privateScope_justMeButton" className="mx_SpaceRoomView_privateScope_justMeButton"
onClick={() => { onFinished(false) }} onClick={() => { onFinished(false); }}
> >
<h3>{ _t("Just me") }</h3> <h3>{ _t("Just me") }</h3>
<div>{ _t("A private space to organise your rooms") }</div> <div>{ _t("A private space to organise your rooms") }</div>
</AccessibleButton> </AccessibleButton>
<AccessibleButton <AccessibleButton
className="mx_SpaceRoomView_privateScope_meAndMyTeammatesButton" className="mx_SpaceRoomView_privateScope_meAndMyTeammatesButton"
onClick={() => { onFinished(true) }} onClick={() => { onFinished(true); }}
> >
<h3>{ _t("Me and my teammates") }</h3> <h3>{ _t("Me and my teammates") }</h3>
<div>{ _t("A private space for you and your teammates") }</div> <div>{ _t("A private space for you and your teammates") }</div>
@ -686,7 +686,7 @@ const SpaceSetupPrivateInvite = ({ space, onFinished }) => {
let buttonLabel = _t("Skip for now"); let buttonLabel = _t("Skip for now");
if (emailAddresses.some(name => name.trim())) { if (emailAddresses.some(name => name.trim())) {
onClick = onNextClick; onClick = onNextClick;
buttonLabel = busy ? _t("Inviting...") : _t("Continue") buttonLabel = busy ? _t("Inviting...") : _t("Continue");
} }
return <div className="mx_SpaceRoomView_inviteTeammates"> return <div className="mx_SpaceRoomView_inviteTeammates">

View file

@ -839,7 +839,6 @@ class TimelinePanel extends React.Component<IProps, IState> {
this.sendReadReceipt(); this.sendReadReceipt();
}; };
// advance the read marker past any events we sent ourselves. // advance the read marker past any events we sent ourselves.
private advanceReadMarkerPastMyEvents(): void { private advanceReadMarkerPastMyEvents(): void {
if (!this.props.manageReadMarkers) return; if (!this.props.manageReadMarkers) return;
@ -955,7 +954,6 @@ class TimelinePanel extends React.Component<IProps, IState> {
&& !this.timelineWindow.canPaginate(EventTimeline.FORWARDS); && !this.timelineWindow.canPaginate(EventTimeline.FORWARDS);
} }
/* get the current scroll state. See ScrollPanel.getScrollState for /* get the current scroll state. See ScrollPanel.getScrollState for
* details. * details.
* *

View file

@ -123,7 +123,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
private onRoom = (room: Room): void => { private onRoom = (room: Room): void => {
this.removePendingJoinRoom(room.roomId); this.removePendingJoinRoom(room.roomId);
} };
private onTagStoreUpdate = () => { private onTagStoreUpdate = () => {
this.forceUpdate(); // we don't have anything useful in state to update this.forceUpdate(); // we don't have anything useful in state to update
@ -185,7 +185,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
if (this.state.pendingRoomJoin.delete(roomId)) { if (this.state.pendingRoomJoin.delete(roomId)) {
this.setState({ this.setState({
pendingRoomJoin: new Set<string>(this.state.pendingRoomJoin), pendingRoomJoin: new Set<string>(this.state.pendingRoomJoin),
}) });
} }
} }
@ -357,7 +357,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
), ),
})} })}
</div> </div>
) );
} else if (hostSignupConfig) { } else if (hostSignupConfig) {
if (hostSignupConfig && hostSignupConfig.url) { if (hostSignupConfig && hostSignupConfig.url) {
// If hostSignup.domains is set to a non-empty array, only show // If hostSignup.domains is set to a non-empty array, only show
@ -509,7 +509,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
/> />
</IconizedContextMenuOptionList> </IconizedContextMenuOptionList>
</React.Fragment> </React.Fragment>
) );
} else if (MatrixClientPeg.get().isGuest()) { } else if (MatrixClientPeg.get().isGuest()) {
primaryOptionList = ( primaryOptionList = (
<React.Fragment> <React.Fragment>

View file

@ -501,9 +501,9 @@ export default class LoginComponent extends React.PureComponent<IProps, IState>
return <React.Fragment> return <React.Fragment>
{ flows.map(flow => { { flows.map(flow => {
const stepRenderer = this.stepRendererMap[flow.type]; const stepRenderer = this.stepRendererMap[flow.type];
return <React.Fragment key={flow.type}>{ stepRenderer() }</React.Fragment> return <React.Fragment key={flow.type}>{ stepRenderer() }</React.Fragment>;
}) } }) }
</React.Fragment> </React.Fragment>;
} }
private renderPasswordStep = () => { private renderPasswordStep = () => {

View file

@ -267,7 +267,7 @@ export default class Registration extends React.Component<IProps, IState> {
session_id: sessionId, session_id: sessionId,
}), }),
); );
} };
private onUIAuthFinished = async (success: boolean, response: any) => { private onUIAuthFinished = async (success: boolean, response: any) => {
if (!success) { if (!success) {
@ -487,7 +487,13 @@ export default class Registration extends React.Component<IProps, IState> {
fragmentAfterLogin={this.props.fragmentAfterLogin} fragmentAfterLogin={this.props.fragmentAfterLogin}
/> />
<h3 className="mx_AuthBody_centered"> <h3 className="mx_AuthBody_centered">
{ _t("%(ssoButtons)s Or %(usernamePassword)s", { ssoButtons: "", usernamePassword: ""}).trim() } {_t(
"%(ssoButtons)s Or %(usernamePassword)s",
{
ssoButtons: "",
usernamePassword: "",
},
).trim()}
</h3> </h3>
</React.Fragment>; </React.Fragment>;
} }

View file

@ -354,7 +354,6 @@ export class TermsAuthEntry extends React.Component<ITermsAuthEntryProps, ITerms
CountlyAnalytics.instance.track("onboarding_terms_begin"); CountlyAnalytics.instance.track("onboarding_terms_begin");
} }
componentDidMount() { componentDidMount() {
this.props.onPhaseChange(DEFAULT_PHASE); this.props.onPhaseChange(DEFAULT_PHASE);
} }

View file

@ -322,7 +322,7 @@ export default class PasswordLogin extends React.PureComponent<IProps, IState> {
const result = await this.validatePasswordRules(fieldState); const result = await this.validatePasswordRules(fieldState);
this.markFieldValid(LoginField.Password, result.valid); this.markFieldValid(LoginField.Password, result.valid);
return result; return result;
} };
private renderLoginField(loginType: IState["loginType"], autoFocus: boolean) { private renderLoginField(loginType: IState["loginType"], autoFocus: boolean) {
const classes = { const classes = {

View file

@ -49,7 +49,7 @@ const WidgetAvatar: React.FC<IProps> = ({ app, className, width = 20, height = 2
width={width} width={width}
height={height} height={height}
/> />
) );
}; };
export default WidgetAvatar; export default WidgetAvatar;

View file

@ -42,13 +42,13 @@ export default class CallContextMenu extends React.Component<IProps> {
onHoldClick = () => { onHoldClick = () => {
this.props.call.setRemoteOnHold(true); this.props.call.setRemoteOnHold(true);
this.props.onFinished(); this.props.onFinished();
} };
onUnholdClick = () => { onUnholdClick = () => {
CallHandler.sharedInstance().setActiveCallRoomId(this.props.call.roomId); CallHandler.sharedInstance().setActiveCallRoomId(this.props.call.roomId);
this.props.onFinished(); this.props.onFinished();
} };
onTransferClick = () => { onTransferClick = () => {
Modal.createTrackedDialog( Modal.createTrackedDialog(
@ -56,7 +56,7 @@ export default class CallContextMenu extends React.Component<IProps> {
/*className=*/null, /*isPriority=*/false, /*isStatic=*/true, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true,
); );
this.props.onFinished(); this.props.onFinished();
} };
render() { render() {
const holdUnholdCaption = this.props.call.isRemoteOnHold() ? _t("Resume") : _t("Hold"); const holdUnholdCaption = this.props.call.isRemoteOnHold() ? _t("Resume") : _t("Hold");

View file

@ -37,18 +37,17 @@ export default class DialpadContextMenu extends React.Component<IProps, IState>
this.state = { this.state = {
value: '', value: '',
} };
} }
onDigitPress = (digit) => { onDigitPress = (digit) => {
this.props.call.sendDtmfDigit(digit); this.props.call.sendDtmfDigit(digit);
this.setState({ value: this.state.value + digit }); this.setState({ value: this.state.value + digit });
} };
onChange = (ev) => { onChange = (ev) => {
this.setState({ value: ev.target.value }); this.setState({ value: ev.target.value });
} };
render() { render() {
return <ContextMenu {...this.props}> return <ContextMenu {...this.props}>

View file

@ -23,7 +23,6 @@ import {replaceableComponent} from "../../../utils/replaceableComponent";
* menu. * menu.
*/ */
@replaceableComponent("views.context_menus.GenericElementContextMenu") @replaceableComponent("views.context_menus.GenericElementContextMenu")
export default class GenericElementContextMenu extends React.Component { export default class GenericElementContextMenu extends React.Component {
static propTypes = { static propTypes = {

View file

@ -207,7 +207,7 @@ export default class MessageContextMenu extends React.Component {
this.closeMenu(); this.closeMenu();
}; };
onPermalinkClick = (e: Event) => { onPermalinkClick = (e) => {
e.preventDefault(); e.preventDefault();
const ShareDialog = sdk.getComponent("dialogs.ShareDialog"); const ShareDialog = sdk.getComponent("dialogs.ShareDialog");
Modal.createTrackedDialog('share room message dialog', '', ShareDialog, { Modal.createTrackedDialog('share room message dialog', '', ShareDialog, {

View file

@ -68,7 +68,7 @@ export default class BugReportDialog extends React.Component<IProps, IState> {
private onCancel = (): void => { private onCancel = (): void => {
this.props.onFinished(false); this.props.onFinished(false);
} };
private onSubmit = (): void => { private onSubmit = (): void => {
if ((!this.state.text || !this.state.text.trim()) && (!this.state.issueUrl || !this.state.issueUrl.trim())) { if ((!this.state.text || !this.state.text.trim()) && (!this.state.issueUrl || !this.state.issueUrl.trim())) {
@ -110,7 +110,7 @@ export default class BugReportDialog extends React.Component<IProps, IState> {
}); });
} }
}); });
} };
private onDownload = async (): Promise<void> => { private onDownload = async (): Promise<void> => {
this.setState({ downloadBusy: true }); this.setState({ downloadBusy: true });
@ -139,25 +139,25 @@ export default class BugReportDialog extends React.Component<IProps, IState> {
private onTextChange = (ev: React.FormEvent<HTMLTextAreaElement>): void => { private onTextChange = (ev: React.FormEvent<HTMLTextAreaElement>): void => {
this.setState({ text: ev.currentTarget.value }); this.setState({ text: ev.currentTarget.value });
} };
private onIssueUrlChange = (ev: React.FormEvent<HTMLInputElement>): void => { private onIssueUrlChange = (ev: React.FormEvent<HTMLInputElement>): void => {
this.setState({ issueUrl: ev.currentTarget.value }); this.setState({ issueUrl: ev.currentTarget.value });
} };
private sendProgressCallback = (progress: string): void => { private sendProgressCallback = (progress: string): void => {
if (this.unmounted) { if (this.unmounted) {
return; return;
} }
this.setState({ progress }); this.setState({ progress });
} };
private downloadProgressCallback = (downloadProgress: string): void => { private downloadProgressCallback = (downloadProgress: string): void => {
if (this.unmounted) { if (this.unmounted) {
return; return;
} }
this.setState({ downloadProgress }); this.setState({ downloadProgress });
} };
public render() { public render() {
const Loader = sdk.getComponent("elements.Spinner"); const Loader = sdk.getComponent("elements.Spinner");

View file

@ -93,7 +93,6 @@ export default class ChangelogDialog extends React.Component<IProps> {
</div> </div>
); );
return ( return (
<QuestionDialog <QuestionDialog
title={_t("Changelog")} title={_t("Changelog")}

View file

@ -175,7 +175,7 @@ export default class CreateCommunityPrototypeDialog extends React.PureComponent<
let preview = <img src={this.state.avatarPreview} className="mx_CreateCommunityPrototypeDialog_avatar" />; let preview = <img src={this.state.avatarPreview} className="mx_CreateCommunityPrototypeDialog_avatar" />;
if (!this.state.avatarPreview) { if (!this.state.avatarPreview) {
preview = <div className="mx_CreateCommunityPrototypeDialog_placeholderAvatar" /> preview = <div className="mx_CreateCommunityPrototypeDialog_placeholderAvatar" />;
} }
return ( return (

View file

@ -62,13 +62,13 @@ abstract class GenericEditor<
} else { } else {
this.props.onBack(); this.props.onBack();
} }
} };
protected onChange = (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => { protected onChange = (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
// @ts-ignore: Unsure how to convince TS this is okay when the state // @ts-ignore: Unsure how to convince TS this is okay when the state
// type can be extended. // type can be extended.
this.setState({ [e.target.id]: e.target.type === 'checkbox' ? e.target.checked : e.target.value }); this.setState({ [e.target.id]: e.target.type === 'checkbox' ? e.target.checked : e.target.value });
} };
protected abstract send(); protected abstract send();
@ -158,7 +158,7 @@ export class SendCustomEvent extends GenericEditor<ISendCustomEventProps, ISendC
message = _t('Failed to send custom event.') + ' (' + e.toString() + ')'; message = _t('Failed to send custom event.') + ' (' + e.toString() + ')';
} }
this.setState({ message }); this.setState({ message });
} };
render() { render() {
if (this.state.message) { if (this.state.message) {
@ -264,7 +264,7 @@ class SendAccountData extends GenericEditor<ISendAccountDataProps, ISendAccountD
message = _t('Failed to send custom event.') + ' (' + e.toString() + ')'; message = _t('Failed to send custom event.') + ' (' + e.toString() + ')';
} }
this.setState({ message }); this.setState({ message });
} };
render() { render() {
if (this.state.message) { if (this.state.message) {
@ -442,19 +442,19 @@ class RoomStateExplorer extends React.PureComponent<IExplorerProps, IRoomStateEx
} else { } else {
this.props.onBack(); this.props.onBack();
} }
} };
private editEv = () => { private editEv = () => {
this.setState({ editing: true }); this.setState({ editing: true });
} };
private onQueryEventType = (filterEventType: string) => { private onQueryEventType = (filterEventType: string) => {
this.setState({ queryEventType: filterEventType }); this.setState({ queryEventType: filterEventType });
} };
private onQueryStateKey = (filterStateKey: string) => { private onQueryStateKey = (filterStateKey: string) => {
this.setState({ queryStateKey: filterStateKey }); this.setState({ queryStateKey: filterStateKey });
} };
render() { render() {
if (this.state.event) { if (this.state.event) {
@ -570,19 +570,19 @@ class AccountDataExplorer extends React.PureComponent<IExplorerProps, IAccountDa
} else { } else {
this.props.onBack(); this.props.onBack();
} }
} };
private onChange = (e: ChangeEvent<HTMLInputElement>) => { private onChange = (e: ChangeEvent<HTMLInputElement>) => {
this.setState({ [e.target.id]: e.target.type === 'checkbox' ? e.target.checked : e.target.value }); this.setState({ [e.target.id]: e.target.type === 'checkbox' ? e.target.checked : e.target.value });
} };
private editEv = () => { private editEv = () => {
this.setState({ editing: true }); this.setState({ editing: true });
} };
private onQueryEventType = (queryEventType: string) => { private onQueryEventType = (queryEventType: string) => {
this.setState({ queryEventType }); this.setState({ queryEventType });
} };
render() { render() {
if (this.state.event) { if (this.state.event) {
@ -676,7 +676,7 @@ class ServersInRoomList extends React.PureComponent<IExplorerProps, IServersInRo
private onQuery = (query: string) => { private onQuery = (query: string) => {
this.setState({ query }); this.setState({ query });
} };
render() { render() {
return <div> return <div>
@ -739,7 +739,7 @@ const VerificationRequestExplorer: React.FC<{
<dd>{JSON.stringify(request.observeOnly)}</dd> <dd>{JSON.stringify(request.observeOnly)}</dd>
</dl> </dl>
</div>); </div>);
} };
class VerificationExplorer extends React.PureComponent<IExplorerProps> { class VerificationExplorer extends React.PureComponent<IExplorerProps> {
static getLabel() { static getLabel() {
@ -751,7 +751,7 @@ class VerificationExplorer extends React.PureComponent<IExplorerProps> {
private onNewRequest = () => { private onNewRequest = () => {
this.forceUpdate(); this.forceUpdate();
} };
componentDidMount() { componentDidMount() {
const cli = this.context; const cli = this.context;
@ -1221,11 +1221,11 @@ export default class DevtoolsDialog extends React.PureComponent<IProps, IState>
private onBack = () => { private onBack = () => {
this.setState({ mode: null }); this.setState({ mode: null });
} };
private onCancel = () => { private onCancel = () => {
this.props.onFinished(false); this.props.onFinished(false);
} };
render() { render() {
let body; let body;

View file

@ -122,7 +122,7 @@ export default class EditCommunityPrototypeDialog extends React.PureComponent<IP
const url = mediaFromMxc(this.state.currentAvatarUrl).srcHttp; const url = mediaFromMxc(this.state.currentAvatarUrl).srcHttp;
preview = <img src={url} className="mx_EditCommunityPrototypeDialog_avatar" />; preview = <img src={url} className="mx_EditCommunityPrototypeDialog_avatar" />;
} else { } else {
preview = <div className="mx_EditCommunityPrototypeDialog_placeholderAvatar" /> preview = <div className="mx_EditCommunityPrototypeDialog_placeholderAvatar" />;
} }
} }

View file

@ -30,7 +30,6 @@ const existingIssuesUrl = "https://github.com/vector-im/element-web/issues" +
"?q=is%3Aopen+is%3Aissue+sort%3Areactions-%2B1-desc"; "?q=is%3Aopen+is%3Aissue+sort%3Areactions-%2B1-desc";
const newIssueUrl = "https://github.com/vector-im/element-web/issues/new"; const newIssueUrl = "https://github.com/vector-im/element-web/issues/new";
export default (props) => { export default (props) => {
const [rating, setRating] = useState(""); const [rating, setRating] = useState("");
const [comment, setComment] = useState(""); const [comment, setComment] = useState("");

View file

@ -86,7 +86,7 @@ export default class HostSignupDialog extends React.PureComponent<IProps, IState
case PostmessageAction.CloseDialog: case PostmessageAction.CloseDialog:
return this.closeDialog(); return this.closeDialog();
} }
} };
private maximizeDialog = () => { private maximizeDialog = () => {
this.setState({ this.setState({
@ -96,7 +96,7 @@ export default class HostSignupDialog extends React.PureComponent<IProps, IState
this.sendMessage({ this.sendMessage({
action: PostmessageAction.Maximize, action: PostmessageAction.Maximize,
}); });
} };
private minimizeDialog = () => { private minimizeDialog = () => {
this.setState({ this.setState({
@ -106,7 +106,7 @@ export default class HostSignupDialog extends React.PureComponent<IProps, IState
this.sendMessage({ this.sendMessage({
action: PostmessageAction.Minimize, action: PostmessageAction.Minimize,
}); });
} };
private closeDialog = async () => { private closeDialog = async () => {
window.removeEventListener("message", this.messageHandler); window.removeEventListener("message", this.messageHandler);
@ -114,7 +114,7 @@ export default class HostSignupDialog extends React.PureComponent<IProps, IState
PersistedElement.destroyElement("host_signup"); PersistedElement.destroyElement("host_signup");
// Finally clear the flag in // Finally clear the flag in
return HostSignupStore.instance.setHostSignupActive(false); return HostSignupStore.instance.setHostSignupActive(false);
} };
private onCloseClick = async () => { private onCloseClick = async () => {
if (this.state.completed) { if (this.state.completed) {
@ -137,16 +137,16 @@ export default class HostSignupDialog extends React.PureComponent<IProps, IState
}, },
); );
} }
} };
private sendMessage = (message: IPostmessageResponseData) => { private sendMessage = (message: IPostmessageResponseData) => {
this.iframeRef.current.contentWindow.postMessage(message, this.config.url); this.iframeRef.current.contentWindow.postMessage(message, this.config.url);
} };
private async sendAccountDetails() { private async sendAccountDetails() {
const openIdToken = await MatrixClientPeg.get().getOpenIdToken(); const openIdToken = await MatrixClientPeg.get().getOpenIdToken();
if (!openIdToken || !openIdToken.access_token) { if (!openIdToken || !openIdToken.access_token) {
console.warn("Failed to connect to homeserver for OpenID token.") console.warn("Failed to connect to homeserver for OpenID token.");
this.setState({ this.setState({
completed: true, completed: true,
error: _t("Failed to connect to your homeserver. Please close this dialog and try again."), error: _t("Failed to connect to your homeserver. Please close this dialog and try again."),
@ -171,7 +171,7 @@ export default class HostSignupDialog extends React.PureComponent<IProps, IState
return this.sendAccountDetails(); return this.sendAccountDetails();
} }
return this.closeDialog(); return this.closeDialog();
} };
private onAccountDetailsRequest = () => { private onAccountDetailsRequest = () => {
const textComponent = ( const textComponent = (
@ -215,7 +215,7 @@ export default class HostSignupDialog extends React.PureComponent<IProps, IState
onFinished: this.onAccountDetailsDialogFinished, onFinished: this.onAccountDetailsDialogFinished,
}, },
); );
} };
public componentDidMount() { public componentDidMount() {
window.addEventListener("message", this.messageHandler); window.addEventListener("message", this.messageHandler);

View file

@ -427,7 +427,7 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
private onConsultFirstChange = (ev) => { private onConsultFirstChange = (ev) => {
this.setState({ consultFirst: ev.target.checked }); this.setState({ consultFirst: ev.target.checked });
} };
public static buildRecents(excludedTargetIds: Set<string>): IRecentUser[] { public static buildRecents(excludedTargetIds: Set<string>): IRecentUser[] {
const rooms = DMRoomMap.shared().getUniqueRoomsWithIndividuals(); // map of userId => js-sdk Room const rooms = DMRoomMap.shared().getUniqueRoomsWithIndividuals(); // map of userId => js-sdk Room
@ -696,7 +696,7 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
return roomOptions; return roomOptions;
}, },
{ invite: [], invite_3pid: [] }, { invite: [], invite_3pid: [] },
) );
} }
await createRoom(createRoomOptions); await createRoom(createRoomOptions);
@ -729,7 +729,7 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
} }
try { try {
const result = await inviteMultipleToRoom(this.props.roomId, targetIds) const result = await inviteMultipleToRoom(this.props.roomId, targetIds);
CountlyAnalytics.instance.trackSendInvite(startTime, this.props.roomId, targetIds.length); CountlyAnalytics.instance.trackSendInvite(startTime, this.props.roomId, targetIds.length);
if (!this.shouldAbortAfterInviteError(result, room)) { // handles setting error message too if (!this.shouldAbortAfterInviteError(result, room)) { // handles setting error message too
this.props.onFinished(); this.props.onFinished();
@ -1365,7 +1365,7 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
<div /> <div />
</AccessibleTooltipButton> </AccessibleTooltipButton>
</div> </div>
</div> </div>;
} else if (this.props.kind === KIND_INVITE) { } else if (this.props.kind === KIND_INVITE) {
const room = MatrixClientPeg.get()?.getRoom(this.props.roomId); const room = MatrixClientPeg.get()?.getRoom(this.props.roomId);
const isSpace = SettingsStore.getValue("feature_spaces") && room?.isSpaceRoom(); const isSpace = SettingsStore.getValue("feature_spaces") && room?.isSpaceRoom();

View file

@ -102,7 +102,7 @@ export default class ModalWidgetDialog extends React.PureComponent<IProps, IStat
private onWidgetClose = (ev: CustomEvent<IModalWidgetCloseRequest>) => { private onWidgetClose = (ev: CustomEvent<IModalWidgetCloseRequest>) => {
this.props.onFinished(true, ev.detail.data); this.props.onFinished(true, ev.detail.data);
} };
private onButtonEnableToggle = (ev: CustomEvent<ISetModalButtonEnabledActionRequest>) => { private onButtonEnableToggle = (ev: CustomEvent<ISetModalButtonEnabledActionRequest>) => {
ev.preventDefault(); ev.preventDefault();
@ -160,7 +160,7 @@ export default class ModalWidgetDialog extends React.PureComponent<IProps, IStat
break; break;
case ModalButtonKind.Secondary: case ModalButtonKind.Secondary:
kind = "primary_outline"; kind = "primary_outline";
break break;
case ModalButtonKind.Danger: case ModalButtonKind.Danger:
kind = "danger"; kind = "danger";
break; break;

View file

@ -40,7 +40,6 @@ interface IState {
nature?: EXTENDED_NATURE; nature?: EXTENDED_NATURE;
} }
const MODERATED_BY_STATE_EVENT_TYPE = [ const MODERATED_BY_STATE_EVENT_TYPE = [
"org.matrix.msc3215.room.moderation.moderated_by", "org.matrix.msc3215.room.moderation.moderated_by",
/** /**
@ -75,7 +74,7 @@ type Moderation = {
moderationRoomId: string; moderationRoomId: string;
// The id of the bot in charge of forwarding abuse reports to the moderation room. // The id of the bot in charge of forwarding abuse reports to the moderation room.
moderationBotUserId: string; moderationBotUserId: string;
} };
/* /*
* A dialog for reporting an event. * A dialog for reporting an event.
* *

View file

@ -85,7 +85,7 @@ export default class ServerOfflineDialog extends React.PureComponent<IProps> {
{entries} {entries}
</div> </div>
</div> </div>
) );
}); });
} }

View file

@ -24,7 +24,6 @@ import { _t } from '../../../languageHandler';
import Modal from '../../../Modal'; import Modal from '../../../Modal';
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
/* /*
* Prompt the user to set an email address. * Prompt the user to set an email address.
* *

View file

@ -63,11 +63,11 @@ export default class TabbedIntegrationManagerDialog extends React.Component {
}; };
} }
componentDidMount(): void { componentDidMount() {
this.openManager(0, true); this.openManager(0, true);
} }
openManager = async (i: number, force = false) => { openManager = async (i, force = false) => {
if (i === this.state.currentIndex && !force) return; if (i === this.state.currentIndex && !force) return;
const manager = this.state.managers[i]; const manager = this.state.managers[i];

View file

@ -31,7 +31,7 @@ interface ITermsCheckboxProps {
class TermsCheckbox extends React.PureComponent<ITermsCheckboxProps> { class TermsCheckbox extends React.PureComponent<ITermsCheckboxProps> {
private onChange = (ev: React.FormEvent<HTMLInputElement>): void => { private onChange = (ev: React.FormEvent<HTMLInputElement>): void => {
this.props.onChange(this.props.url, ev.currentTarget.checked); this.props.onChange(this.props.url, ev.currentTarget.checked);
} };
render() { render() {
return <input type="checkbox" return <input type="checkbox"
@ -80,11 +80,11 @@ export default class TermsDialog extends React.PureComponent<ITermsDialogProps,
private onCancelClick = (): void => { private onCancelClick = (): void => {
this.props.onFinished(false); this.props.onFinished(false);
} };
private onNextClick = (): void => { private onNextClick = (): void => {
this.props.onFinished(true, Object.keys(this.state.agreedUrls).filter((url) => this.state.agreedUrls[url])); this.props.onFinished(true, Object.keys(this.state.agreedUrls).filter((url) => this.state.agreedUrls[url]));
} };
private nameForServiceType(serviceType: SERVICE_TYPES, host: string): JSX.Element { private nameForServiceType(serviceType: SERVICE_TYPES, host: string): JSX.Element {
switch (serviceType) { switch (serviceType) {
@ -114,7 +114,7 @@ export default class TermsDialog extends React.PureComponent<ITermsDialogProps,
this.setState({ this.setState({
agreedUrls: Object.assign({}, this.state.agreedUrls, { [url]: checked }), agreedUrls: Object.assign({}, this.state.agreedUrls, { [url]: checked }),
}); });
} };
public render() { public render() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');

View file

@ -36,7 +36,7 @@ export default class UploadConfirmDialog extends React.Component<IProps> {
static defaultProps = { static defaultProps = {
totalFiles: 1, totalFiles: 1,
} };
constructor(props) { constructor(props) {
super(props); super(props);
@ -56,15 +56,15 @@ export default class UploadConfirmDialog extends React.Component<IProps> {
private onCancelClick = () => { private onCancelClick = () => {
this.props.onFinished(false); this.props.onFinished(false);
} };
private onUploadClick = () => { private onUploadClick = () => {
this.props.onFinished(true); this.props.onFinished(true);
} };
private onUploadAllClick = () => { private onUploadAllClick = () => {
this.props.onFinished(true, true); this.props.onFinished(true, true);
} };
render() { render() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');

View file

@ -79,7 +79,7 @@ export default class UserSettingsDialog extends React.Component<IProps, IState>
private mjolnirChanged: CallbackFn = (settingName, roomId, atLevel, newValue) => { private mjolnirChanged: CallbackFn = (settingName, roomId, atLevel, newValue) => {
// We can cheat because we know what levels a feature is tracked at, and how it is tracked // We can cheat because we know what levels a feature is tracked at, and how it is tracked
this.setState({ mjolnirEnabled: newValue }); this.setState({ mjolnirEnabled: newValue });
} };
_getTabs() { _getTabs() {
const tabs = []; const tabs = [];

View file

@ -169,7 +169,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent<IProp
private onRecoveryKeyFileUploadClick = () => { private onRecoveryKeyFileUploadClick = () => {
this.fileUpload.current.click(); this.fileUpload.current.click();
} };
private onPassPhraseNext = async (ev: FormEvent<HTMLFormElement>) => { private onPassPhraseNext = async (ev: FormEvent<HTMLFormElement>) => {
ev.preventDefault(); ev.preventDefault();

View file

@ -139,7 +139,7 @@ export default class CreateCrossSigningDialog extends React.PureComponent<IProps
throw new Error("Cross-signing key upload auth canceled"); throw new Error("Cross-signing key upload auth canceled");
} }
} }
} };
private bootstrapCrossSigning = async (): Promise<void> => { private bootstrapCrossSigning = async (): Promise<void> => {
this.setState({ this.setState({
@ -163,11 +163,11 @@ export default class CreateCrossSigningDialog extends React.PureComponent<IProps
this.setState({ error: e }); this.setState({ error: e });
console.error("Error bootstrapping cross-signing", e); console.error("Error bootstrapping cross-signing", e);
} }
} };
private onCancel = (): void => { private onCancel = (): void => {
this.props.onFinished(false); this.props.onFinished(false);
} };
render() { render() {
let content; let content;

View file

@ -216,7 +216,9 @@ const NetworkDropdown = ({ onOptionChange, protocols = {}, selectedServerName, s
if (removableServers.has(server)) { if (removableServers.has(server)) {
const onClick = async () => { const onClick = async () => {
closeMenu(); closeMenu();
const {finished} = Modal.createTrackedDialog("Network Dropdown", "Remove server", QuestionDialog, { const { finished } = Modal.createTrackedDialog(
"Network Dropdown", "Remove server", QuestionDialog,
{
title: _t("Are you sure?"), title: _t("Are you sure?"),
description: _t("Are you sure you want to remove <b>%(serverName)s</b>", { description: _t("Are you sure you want to remove <b>%(serverName)s</b>", {
serverName: server, serverName: server,
@ -225,7 +227,9 @@ const NetworkDropdown = ({ onOptionChange, protocols = {}, selectedServerName, s
}), }),
button: _t("Remove"), button: _t("Remove"),
fixedWidth: false, fixedWidth: false,
}, "mx_NetworkDropdown_dialog"); },
"mx_NetworkDropdown_dialog",
);
const [ok] = await finished; const [ok] = await finished;
if (!ok) return; if (!ok) return;

View file

@ -62,8 +62,6 @@ export default class ActionButton extends React.Component {
}; };
render() { render() {
const TintableSvg = sdk.getComponent("elements.TintableSvg");
let tooltip; let tooltip;
if (this.state.showTooltip) { if (this.state.showTooltip) {
const Tooltip = sdk.getComponent("elements.Tooltip"); const Tooltip = sdk.getComponent("elements.Tooltip");
@ -71,7 +69,7 @@ export default class ActionButton extends React.Component {
} }
const icon = this.props.iconPath ? const icon = this.props.iconPath ?
(<TintableSvg src={this.props.iconPath} width={this.props.size} height={this.props.size} />) : (<img src={this.props.iconPath} width={this.props.size} height={this.props.size} />) :
undefined; undefined;
const classNames = ["mx_RoleButton"]; const classNames = ["mx_RoleButton"];

View file

@ -53,7 +53,6 @@ export default class AddressTile extends React.Component {
} }
const BaseAvatar = sdk.getComponent('avatars.BaseAvatar'); const BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
const TintableSvg = sdk.getComponent("elements.TintableSvg");
const nameClasses = classNames({ const nameClasses = classNames({
"mx_AddressTile_name": true, "mx_AddressTile_name": true,
@ -124,7 +123,7 @@ export default class AddressTile extends React.Component {
if (this.props.canDismiss) { if (this.props.canDismiss) {
dismiss = ( dismiss = (
<div className="mx_AddressTile_dismiss" onClick={this.props.onDismissed} > <div className="mx_AddressTile_dismiss" onClick={this.props.onDismissed} >
<TintableSvg src={require("../../../../res/img/icon-address-delete.svg")} width="9" height="9" /> <img src={require("../../../../res/img/icon-address-delete.svg")} width="9" height="9" />
</div> </div>
); );
} }

View file

@ -22,7 +22,6 @@ import dis from "../../../dispatcher/dispatcher";
import { Action } from "../../../dispatcher/actions"; import { Action } from "../../../dispatcher/actions";
import { UserTab } from "../dialogs/UserSettingsDialog"; import { UserTab } from "../dialogs/UserSettingsDialog";
export enum WarningKind { export enum WarningKind {
Files, Files,
Search, Search,

View file

@ -16,7 +16,7 @@ limitations under the License.
import React from 'react'; import React from 'react';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import BaseDialog from "..//dialogs/BaseDialog" import BaseDialog from "..//dialogs/BaseDialog";
import AccessibleButton from './AccessibleButton'; import AccessibleButton from './AccessibleButton';
import { getDesktopCapturerSources } from "matrix-js-sdk/src/webrtc/call"; import { getDesktopCapturerSources } from "matrix-js-sdk/src/webrtc/call";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
@ -44,7 +44,7 @@ export class ExistingSource extends React.Component<DesktopCapturerSourceIProps>
onClick = (ev) => { onClick = (ev) => {
this.props.onSelect(this.props.source); this.props.onSelect(this.props.source);
} };
render() { render() {
return ( return (
@ -108,19 +108,19 @@ export default class DesktopCapturerSourcePicker extends React.Component<
onSelect = (source) => { onSelect = (source) => {
this.props.onFinished(source); this.props.onFinished(source);
} };
onScreensClick = (ev) => { onScreensClick = (ev) => {
this.setState({ selectedTab: Tabs.Screens }); this.setState({ selectedTab: Tabs.Screens });
} };
onWindowsClick = (ev) => { onWindowsClick = (ev) => {
this.setState({ selectedTab: Tabs.Windows }); this.setState({ selectedTab: Tabs.Windows });
} };
onCloseClick = (ev) => { onCloseClick = (ev) => {
this.props.onFinished(null); this.props.onFinished(null);
} };
render() { render() {
let sources; let sources;

View file

@ -144,7 +144,6 @@ EditableTextContainer.propTypes = {
blurToSubmit: PropTypes.bool, blurToSubmit: PropTypes.bool,
}; };
EditableTextContainer.defaultProps = { EditableTextContainer.defaultProps = {
initialValue: "", initialValue: "",
placeholder: "", placeholder: "",

View file

@ -17,7 +17,7 @@
import React, { FunctionComponent, useEffect, useRef } from 'react'; import React, { FunctionComponent, useEffect, useRef } from 'react';
import dis from '../../../dispatcher/dispatcher'; import dis from '../../../dispatcher/dispatcher';
import ICanvasEffect from '../../../effects/ICanvasEffect'; import ICanvasEffect from '../../../effects/ICanvasEffect';
import { CHAT_EFFECTS } from '../../../effects' import { CHAT_EFFECTS } from '../../../effects';
import UIStore, { UI_EVENTS } from "../../../stores/UIStore"; import UIStore, { UI_EVENTS } from "../../../stores/UIStore";
interface IProps { interface IProps {
@ -32,7 +32,7 @@ const EffectsOverlay: FunctionComponent<IProps> = ({ roomWidth }) => {
if (!name) return null; if (!name) return null;
let effect: ICanvasEffect | null = effectsRef.current[name] || null; let effect: ICanvasEffect | null = effectsRef.current[name] || null;
if (effect === null) { if (effect === null) {
const options = CHAT_EFFECTS.find((e) => e.command === name)?.options const options = CHAT_EFFECTS.find((e) => e.command === name)?.options;
try { try {
const { default: Effect } = await import(`../../../effects/${name}`); const { default: Effect } = await import(`../../../effects/${name}`);
effect = new Effect(options); effect = new Effect(options);
@ -56,7 +56,7 @@ const EffectsOverlay: FunctionComponent<IProps> = ({ roomWidth }) => {
const effect = payload.action.substr(actionPrefix.length); const effect = payload.action.substr(actionPrefix.length);
lazyLoadEffectModule(effect).then((module) => module?.start(canvasRef.current)); lazyLoadEffectModule(effect).then((module) => module?.start(canvasRef.current));
} }
} };
const dispatcherRef = dis.register(onAction); const dispatcherRef = dis.register(onAction);
const canvas = canvasRef.current; const canvas = canvasRef.current;
canvas.height = UIStore.instance.windowHeight; canvas.height = UIStore.instance.windowHeight;
@ -89,7 +89,7 @@ const EffectsOverlay: FunctionComponent<IProps> = ({ roomWidth }) => {
right: 0, right: 0,
}} }}
/> />
) );
} };
export default EffectsOverlay; export default EffectsOverlay;

View file

@ -22,7 +22,6 @@ import MatrixClientContext from "../../../contexts/MatrixClientContext";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import { mediaFromMxc } from "../../../customisations/Media"; import { mediaFromMxc } from "../../../customisations/Media";
class FlairAvatar extends React.Component { class FlairAvatar extends React.Component {
constructor() { constructor() {
super(); super();

View file

@ -30,7 +30,7 @@ import SettingsStore from "../../../settings/SettingsStore";
import { formatFullDate } from "../../../DateUtils"; import { formatFullDate } from "../../../DateUtils";
import dis from '../../../dispatcher/dispatcher'; import dis from '../../../dispatcher/dispatcher';
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks" import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks";
import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { normalizeWheelEvent } from "../../../utils/Mouse"; import { normalizeWheelEvent } from "../../../utils/Mouse";
@ -116,7 +116,7 @@ export default class ImageView extends React.Component<IProps, IState> {
private recalculateZoom = () => { private recalculateZoom = () => {
this.setZoomAndRotation(); this.setZoomAndRotation();
} };
private setZoomAndRotation = (inputRotation?: number) => { private setZoomAndRotation = (inputRotation?: number) => {
const image = this.image.current; const image = this.image.current;
@ -158,7 +158,7 @@ export default class ImageView extends React.Component<IProps, IState> {
rotation: rotation, rotation: rotation,
zoom: zoom, zoom: zoom,
}); });
} };
private zoom(delta: number) { private zoom(delta: number) {
const newZoom = this.state.zoom + delta; const newZoom = this.state.zoom + delta;

View file

@ -29,7 +29,7 @@ export default class InlineSpinner extends React.PureComponent<IProps> {
static defaultProps = { static defaultProps = {
w: 16, w: 16,
h: 16, h: 16,
} };
render() { render() {
return ( return (

View file

@ -42,7 +42,7 @@ export default class InviteReason extends React.PureComponent<IProps, IState> {
this.setState({ this.setState({
hidden: false, hidden: false,
}); });
} };
render() { render() {
const classes = classNames({ const classes = classNames({

View file

@ -187,4 +187,4 @@ export default class PersistedElement extends React.Component {
} }
} }
export const getPersistKey = (appId: string) => 'widget_' + appId; export const getPersistKey = (appId) => 'widget_' + appId;

View file

@ -48,7 +48,7 @@ const getIcon = (brand: IdentityProviderBrand | string) => {
default: default:
return null; return null;
} }
} };
const SSOButton: React.FC<ISSOButtonProps> = ({ const SSOButton: React.FC<ISSOButtonProps> = ({
matrixClient, matrixClient,

View file

@ -87,7 +87,7 @@ const ServerPicker = ({ title, dialogTitle, serverConfig, onServerConfigChange }
<span className="mx_ServerPicker_server">{serverName}</span> <span className="mx_ServerPicker_server">{serverName}</span>
{ editBtn } { editBtn }
{ desc } { desc }
</div> </div>;
} };
export default ServerPicker; export default ServerPicker;

View file

@ -16,7 +16,7 @@ limitations under the License.
import React from 'react'; import React from 'react';
import Dropdown from "../../views/elements/Dropdown" import Dropdown from "../../views/elements/Dropdown";
import * as sdk from '../../../index'; import * as sdk from '../../../index';
import PlatformPeg from "../../../PlatformPeg"; import PlatformPeg from "../../../PlatformPeg";
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
@ -67,8 +67,8 @@ export default class SpellCheckLanguagesDropdown extends React.Component<SpellCh
langs.push({ langs.push({
label: language, label: language,
value: language, value: language,
}) });
}) });
this.setState({ languages: langs }); this.setState({ languages: langs });
}).catch((e) => { }).catch((e) => {
this.setState({ languages: ['en'] }); this.setState({ languages: ['en'] });

View file

@ -1,82 +0,0 @@
/*
Copyright 2015 OpenMarket Ltd
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import PropTypes from 'prop-types';
import Tinter from "../../../Tinter";
import {replaceableComponent} from "../../../utils/replaceableComponent";
@replaceableComponent("views.elements.TintableSvg")
class TintableSvg extends React.Component {
static propTypes = {
src: PropTypes.string.isRequired,
width: PropTypes.string.isRequired,
height: PropTypes.string.isRequired,
className: PropTypes.string,
};
// list of currently mounted TintableSvgs
static mounts = {};
static idSequence = 0;
componentDidMount() {
this.fixups = [];
this.id = TintableSvg.idSequence++;
TintableSvg.mounts[this.id] = this;
}
componentWillUnmount() {
delete TintableSvg.mounts[this.id];
}
tint = () => {
// TODO: only bother running this if the global tint settings have changed
// since we loaded!
Tinter.applySvgFixups(this.fixups);
};
onLoad = event => {
// console.log("TintableSvg.onLoad for " + this.props.src);
this.fixups = Tinter.calcSvgFixups([event.target]);
Tinter.applySvgFixups(this.fixups);
};
render() {
return (
<object className={"mx_TintableSvg " + (this.props.className ? this.props.className : "")}
type="image/svg+xml"
data={this.props.src}
width={this.props.width}
height={this.props.height}
onLoad={this.onLoad}
tabIndex="-1"
/>
);
}
}
// Register with the Tinter so that we will be told if the tint changes
Tinter.registerTintable(function() {
if (TintableSvg.mounts) {
Object.keys(TintableSvg.mounts).forEach((id) => {
TintableSvg.mounts[id].tint();
});
}
});
export default TintableSvg;

View file

@ -17,7 +17,6 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React, { Component, CSSProperties } from 'react'; import React, { Component, CSSProperties } from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import classNames from 'classnames'; import classNames from 'classnames';

View file

@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
/* eslint-disable babel/no-invalid-this */ /* eslint-disable @typescript-eslint/no-invalid-this */
import React from "react"; import React from "react";
import classNames from "classnames"; import classNames from "classnames";

View file

@ -234,7 +234,7 @@ class EmojiPicker extends React.Component<IProps, IState> {
className="mx_EmojiPicker_body" className="mx_EmojiPicker_body"
wrappedRef={ref => { wrappedRef={ref => {
// @ts-ignore - AutoHideScrollbar should accept a RefObject or fall back to its own instead // @ts-ignore - AutoHideScrollbar should accept a RefObject or fall back to its own instead
this.bodyRef.current = ref this.bodyRef.current = ref;
}} }}
onScroll={this.onScroll} onScroll={this.onScroll}
> >

View file

@ -32,7 +32,7 @@ import {mediaFromMxc} from "../../../customisations/Media";
// XXX this class copies a lot from RoomTile.js // XXX this class copies a lot from RoomTile.js
@replaceableComponent("views.groups.GroupInviteTile") @replaceableComponent("views.groups.GroupInviteTile")
export default class GroupInviteTile extends React.Component { export default class GroupInviteTile extends React.Component {
static propTypes: { static propTypes = {
group: PropTypes.object.isRequired, group: PropTypes.object.isRequired,
}; };

View file

@ -33,4 +33,4 @@ const HostSignupContainer = () => {
</div>; </div>;
}; };
export default HostSignupContainer export default HostSignupContainer;

View file

@ -51,7 +51,7 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
decryptedThumbnailUrl: null, decryptedThumbnailUrl: null,
decryptedBlob: null, decryptedBlob: null,
error: null, error: null,
} };
} }
thumbScale(fullWidth: number, fullHeight: number, thumbWidth: number, thumbHeight: number) { thumbScale(fullWidth: number, fullHeight: number, thumbWidth: number, thumbHeight: number) {
@ -182,7 +182,7 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
this.videoRef.current.play(); this.videoRef.current.play();
}); });
this.props.onHeightChanged(); this.props.onHeightChanged();
} };
render() { render() {
const content = this.props.mxEvent.getContent(); const content = this.props.mxEvent.getContent();

View file

@ -106,6 +106,6 @@ export default class MVoiceMessageBody extends React.PureComponent<IProps, IStat
<RecordingPlayback playback={this.state.playback} /> <RecordingPlayback playback={this.state.playback} />
<MFileBody {...this.props} decryptedBlob={this.state.decryptedBlob} showGenericPlaceholder={false} /> <MFileBody {...this.props} decryptedBlob={this.state.decryptedBlob} showGenericPlaceholder={false} />
</span> </span>
) );
} }
} }

View file

@ -125,7 +125,7 @@ export default class ReactionsRow extends React.PureComponent<IProps, IState> {
private onDecrypted = () => { private onDecrypted = () => {
// Decryption changes whether the event is actionable // Decryption changes whether the event is actionable
this.forceUpdate(); this.forceUpdate();
} };
private onReactionsChange = () => { private onReactionsChange = () => {
// TODO: Call `onHeightChanged` as needed // TODO: Call `onHeightChanged` as needed
@ -136,7 +136,7 @@ export default class ReactionsRow extends React.PureComponent<IProps, IState> {
// has changed (this is triggered by events for that purpose only) and // has changed (this is triggered by events for that purpose only) and
// `PureComponent`s shallow state / props compare would otherwise filter this out. // `PureComponent`s shallow state / props compare would otherwise filter this out.
this.forceUpdate(); this.forceUpdate();
} };
private getMyReactions() { private getMyReactions() {
const reactions = this.props.reactions; const reactions = this.props.reactions;
@ -155,7 +155,7 @@ export default class ReactionsRow extends React.PureComponent<IProps, IState> {
this.setState({ this.setState({
showAll: true, showAll: true,
}); });
} };
render() { render() {
const { mxEvent, reactions } = this.props; const { mxEvent, reactions } = this.props;

View file

@ -79,13 +79,13 @@ export default class ReactionsRowButton extends React.PureComponent<IProps, ISta
tooltipRendered: true, tooltipRendered: true,
tooltipVisible: true, tooltipVisible: true,
}); });
} };
onMouseLeave = () => { onMouseLeave = () => {
this.setState({ this.setState({
tooltipVisible: false, tooltipVisible: false,
}); });
} };
render() { render() {
const { mxEvent, content, count, reactionEvents, myReactionEvent } = this.props; const { mxEvent, content, count, reactionEvents, myReactionEvent } = this.props;

View file

@ -39,7 +39,7 @@ export default class SenderProfile extends React.Component<IProps, IState> {
private unmounted: boolean; private unmounted: boolean;
constructor(props: IProps) { constructor(props: IProps) {
super(props) super(props);
const senderId = this.props.mxEvent.getSender(); const senderId = this.props.mxEvent.getSender();
this.state = { this.state = {
@ -56,7 +56,6 @@ export default class SenderProfile extends React.Component<IProps, IState> {
this.getPublicisedGroups(); this.getPublicisedGroups();
} }
this.context.on('RoomState.events', this.onRoomStateEvents); this.context.on('RoomState.events', this.onRoomStateEvents);
} }

View file

@ -202,7 +202,6 @@ function DeviceItem({userId, device}: {userId: string, device: IDevice}) {
let trustedLabel = null; let trustedLabel = null;
if (userTrust.isVerified()) trustedLabel = isVerified ? _t("Trusted") : _t("Not trusted"); if (userTrust.isVerified()) trustedLabel = isVerified ? _t("Trusted") : _t("Not trusted");
if (isVerified) { if (isVerified) {
return ( return (
<div className={classes} title={device.deviceId} > <div className={classes} title={device.deviceId} >
@ -1382,7 +1381,7 @@ const BasicUserInfo: React.FC<{
}}> }}>
{ _t("Edit devices") } { _t("Edit devices") }
</AccessibleButton> </AccessibleButton>
</p>) </p>);
} }
const securitySection = ( const securitySection = (
@ -1580,7 +1579,7 @@ const UserInfo: React.FC<IProps> = ({
phase: previousPhase, phase: previousPhase,
refireParams: refireParams, refireParams: refireParams,
}); });
} };
let content; let content;
switch (phase) { switch (phase) {

View file

@ -293,7 +293,7 @@ export default class AliasSettings extends React.Component<IProps, IState> {
private onNewAltAliasChanged = (value: string) => { private onNewAltAliasChanged = (value: string) => {
this.setState({ newAltAlias: value }); this.setState({ newAltAlias: value });
} };
private onAltAliasAdded = (alias: string) => { private onAltAliasAdded = (alias: string) => {
const altAliases = this.state.altAliases.slice(); const altAliases = this.state.altAliases.slice();
@ -302,13 +302,13 @@ export default class AliasSettings extends React.Component<IProps, IState> {
this.changeAltAliases(altAliases); this.changeAltAliases(altAliases);
this.setState({ newAltAlias: "" }); this.setState({ newAltAlias: "" });
} }
} };
private onAltAliasDeleted = (index: number) => { private onAltAliasDeleted = (index: number) => {
const altAliases = this.state.altAliases.slice(); const altAliases = this.state.altAliases.slice();
altAliases.splice(index, 1); altAliases.splice(index, 1);
this.changeAltAliases(altAliases); this.changeAltAliases(altAliases);
} };
private getAliases() { private getAliases() {
return this.state.altAliases.concat(this.getLocalNonAltAliases()); return this.state.altAliases.concat(this.getLocalNonAltAliases());

View file

@ -291,7 +291,6 @@ export default class Autocomplete extends React.PureComponent<IProps, IState> {
}); });
}); });
return completions.length > 0 ? ( return completions.length > 0 ? (
<div key={i} className="mx_Autocomplete_ProviderSection"> <div key={i} className="mx_Autocomplete_ProviderSection">
<div className="mx_Autocomplete_provider_name">{ completionResult.provider.getName() }</div> <div className="mx_Autocomplete_provider_name">{ completionResult.provider.getName() }</div>

View file

@ -17,7 +17,7 @@ limitations under the License.
import React from 'react'; import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { lexicographicCompare } from 'matrix-js-sdk/src/utils'; import { lexicographicCompare } from 'matrix-js-sdk/src/utils';
import { Room } from 'matrix-js-sdk/src/models/room' import { Room } from 'matrix-js-sdk/src/models/room';
import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { MatrixClientPeg } from "../../../MatrixClientPeg";
import AppsDrawer from './AppsDrawer'; import AppsDrawer from './AppsDrawer';
@ -126,7 +126,7 @@ export default class AuxPanel extends React.Component<IProps, IState> {
link, link,
severity, severity,
stateKey, stateKey,
}) });
} }
} }
} }

View file

@ -33,7 +33,7 @@ export enum PowerStatus {
const PowerLabel: Record<PowerStatus, string> = { const PowerLabel: Record<PowerStatus, string> = {
[PowerStatus.Admin]: _td("Admin"), [PowerStatus.Admin]: _td("Admin"),
[PowerStatus.Moderator]: _td("Mod"), [PowerStatus.Moderator]: _td("Mod"),
} };
const PRESENCE_CLASS = { const PRESENCE_CLASS = {
"offline": "mx_EntityTile_offline", "offline": "mx_EntityTile_offline",

View file

@ -729,7 +729,7 @@ export default class EventTile extends React.Component<IProps, IState> {
{ avatars } { avatars }
</span> </span>
</div> </div>
) );
} }
onSenderProfileClick = event => { onSenderProfileClick = event => {
@ -1213,7 +1213,7 @@ export default class EventTile extends React.Component<IProps, IState> {
avatar, avatar,
]) ])
) );
} }
} }
} }

View file

@ -242,7 +242,7 @@ export default class MemberList extends React.Component<IProps, IState> {
}, 500); }, 500);
private updateListNow(): void { private updateListNow(): void {
const members = this.roomMembers() const members = this.roomMembers();
this.setState({ this.setState({
loading: false, loading: false,
@ -471,7 +471,7 @@ export default class MemberList extends React.Component<IProps, IState> {
} }
private getChildrenJoined = (start: number, end: number): Array<JSX.Element> => { private getChildrenJoined = (start: number, end: number): Array<JSX.Element> => {
return this.makeMemberTiles(this.state.filteredJoinedMembers.slice(start, end)) return this.makeMemberTiles(this.state.filteredJoinedMembers.slice(start, end));
}; };
private getChildCountJoined = (): number => this.state.filteredJoinedMembers.length; private getChildCountJoined = (): number => this.state.filteredJoinedMembers.length;
@ -487,7 +487,7 @@ export default class MemberList extends React.Component<IProps, IState> {
private getChildCountInvited = (): number => { private getChildCountInvited = (): number => {
return this.state.filteredInvitedMembers.length + (this.getPending3PidInvites() || []).length; return this.state.filteredInvitedMembers.length + (this.getPending3PidInvites() || []).length;
} };
render() { render() {
if (this.state.loading) { if (this.state.loading) {

View file

@ -136,7 +136,7 @@ class UploadButton extends React.Component<IUploadButtonProps> {
return; return;
} }
this.uploadInput.current.click(); this.uploadInput.current.click();
} };
private onUploadFileInputChange = (ev: React.ChangeEvent<HTMLInputElement>) => { private onUploadFileInputChange = (ev: React.ChangeEvent<HTMLInputElement>) => {
if (ev.target.files.length === 0) return; if (ev.target.files.length === 0) return;
@ -157,7 +157,7 @@ class UploadButton extends React.Component<IUploadButtonProps> {
// to empty. // to empty.
// NB. we need to set 'value': the 'files' property is immutable. // NB. we need to set 'value': the 'files' property is immutable.
ev.target.value = ''; ev.target.value = '';
} };
render() { render() {
const uploadInputStyle = { display: 'none' }; const uploadInputStyle = { display: 'none' };
@ -266,7 +266,7 @@ export default class MessageComposer extends React.Component<IProps, IState> {
if (ev.getType() === 'm.room.power_levels') { if (ev.getType() === 'm.room.power_levels') {
this.setState({ canSendMessages: this.props.room.maySendMessage() }); this.setState({ canSendMessages: this.props.room.maySendMessage() });
} }
} };
private getRoomTombstone() { private getRoomTombstone() {
return this.props.room.currentState.getStateEvents('m.room.tombstone', ''); return this.props.room.currentState.getStateEvents('m.room.tombstone', '');
@ -300,7 +300,7 @@ export default class MessageComposer extends React.Component<IProps, IState> {
viaServers: viaServers, viaServers: viaServers,
}, },
}); });
} };
private renderPlaceholderText = () => { private renderPlaceholderText = () => {
if (this.props.replyToEvent) { if (this.props.replyToEvent) {
@ -316,7 +316,7 @@ export default class MessageComposer extends React.Component<IProps, IState> {
return _t('Send a message…'); return _t('Send a message…');
} }
} }
} };
addEmoji(emoji: string) { addEmoji(emoji: string) {
dis.dispatch<ComposerInsertPayload>({ dis.dispatch<ComposerInsertPayload>({
@ -335,13 +335,13 @@ export default class MessageComposer extends React.Component<IProps, IState> {
// XXX: Private function access // XXX: Private function access
this.messageComposerInput._sendMessage(); this.messageComposerInput._sendMessage();
} };
onChange = (model) => { onChange = (model) => {
this.setState({ this.setState({
isComposerEmpty: model.isEmpty, isComposerEmpty: model.isEmpty,
}); });
} };
private onVoiceStoreUpdate = () => { private onVoiceStoreUpdate = () => {
const recording = VoiceRecordingStore.instance.activeRecording; const recording = VoiceRecordingStore.instance.activeRecording;

View file

@ -74,7 +74,7 @@ export default class RoomHeader extends React.Component {
}; };
_rateLimitedUpdate = new RateLimitedFunc(function() { _rateLimitedUpdate = new RateLimitedFunc(function() {
/* eslint-disable babel/no-invalid-this */ /* eslint-disable @babel/no-invalid-this */
this.forceUpdate(); this.forceUpdate();
}, 500); }, 500);

View file

@ -495,7 +495,7 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
resizeNotifier={this.props.resizeNotifier} resizeNotifier={this.props.resizeNotifier}
alwaysVisible={ALWAYS_VISIBLE_TAGS.includes(orderedTagId)} alwaysVisible={ALWAYS_VISIBLE_TAGS.includes(orderedTagId)}
onListCollapse={this.props.onListCollapse} onListCollapse={this.props.onListCollapse}
/> />;
}); });
} }
@ -542,7 +542,7 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
</AccessibleButton> } </AccessibleButton> }
</div>; </div>;
} else if (Object.values(this.state.sublists).some(list => list.length > 0)) { } else if (Object.values(this.state.sublists).some(list => list.length > 0)) {
const unfilteredLists = RoomListStore.instance.unfilteredLists const unfilteredLists = RoomListStore.instance.unfilteredLists;
const unfilteredRooms = unfilteredLists[DefaultTagID.Untagged] || []; const unfilteredRooms = unfilteredLists[DefaultTagID.Untagged] || [];
const unfilteredHistorical = unfilteredLists[DefaultTagID.Archived] || []; const unfilteredHistorical = unfilteredLists[DefaultTagID.Archived] || [];
const unfilteredFavourite = unfilteredLists[DefaultTagID.Favourite] || []; const unfilteredFavourite = unfilteredLists[DefaultTagID.Favourite] || [];

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