More typescript conversion
This commit is contained in:
parent
6d92953311
commit
a839d0f396
13 changed files with 166 additions and 93 deletions
|
@ -123,6 +123,7 @@
|
||||||
"@sinonjs/fake-timers": "^7.0.2",
|
"@sinonjs/fake-timers": "^7.0.2",
|
||||||
"@types/classnames": "^2.2.11",
|
"@types/classnames": "^2.2.11",
|
||||||
"@types/counterpart": "^0.18.1",
|
"@types/counterpart": "^0.18.1",
|
||||||
|
"@types/diff-match-patch": "^1.0.5",
|
||||||
"@types/flux": "^3.1.9",
|
"@types/flux": "^3.1.9",
|
||||||
"@types/jest": "^26.0.20",
|
"@types/jest": "^26.0.20",
|
||||||
"@types/linkifyjs": "^2.1.3",
|
"@types/linkifyjs": "^2.1.3",
|
||||||
|
|
50
src/@types/diff-dom.ts
Normal file
50
src/@types/diff-dom.ts
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare module "diff-dom" {
|
||||||
|
enum Action {
|
||||||
|
AddElement = "addElement",
|
||||||
|
AddTextElement = "addTextElement",
|
||||||
|
RemoveTextElement = "removeTextElement",
|
||||||
|
RemoveElement = "removeElement",
|
||||||
|
ReplaceElement = "replaceElement",
|
||||||
|
ModifyTextElement = "modifyTextElement",
|
||||||
|
AddAttribute = "addAttribute",
|
||||||
|
RemoveAttribute = "removeAttribute",
|
||||||
|
ModifyAttribute = "modifyAttribute",
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDiff {
|
||||||
|
action: Action;
|
||||||
|
name: string;
|
||||||
|
text?: string;
|
||||||
|
route: number[];
|
||||||
|
value: string;
|
||||||
|
element: unknown;
|
||||||
|
oldValue: string;
|
||||||
|
newValue: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IOpts {
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DiffDOM {
|
||||||
|
public constructor(opts?: IOpts);
|
||||||
|
public apply(tree: unknown, diffs: IDiff[]): unknown;
|
||||||
|
public undo(tree: unknown, diffs: IDiff[]): unknown;
|
||||||
|
public diff(a: HTMLElement | string, b: HTMLElement | string): IDiff[];
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2018 New Vector Ltd
|
Copyright 2018 - 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,34 +14,40 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { MatrixError } from "matrix-js-sdk/src/http-api";
|
||||||
|
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
|
|
||||||
export class DecryptionFailure {
|
export class DecryptionFailure {
|
||||||
constructor(failedEventId, errorCode) {
|
public readonly ts: number;
|
||||||
this.failedEventId = failedEventId;
|
|
||||||
this.errorCode = errorCode;
|
constructor(public readonly failedEventId: string, public readonly errorCode: string) {
|
||||||
this.ts = Date.now();
|
this.ts = Date.now();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Fn = (count: number, trackedErrCode: string) => void;
|
||||||
|
type ErrCodeMapFn = (errcode: string) => string;
|
||||||
|
|
||||||
export class DecryptionFailureTracker {
|
export class DecryptionFailureTracker {
|
||||||
// Array of items of type DecryptionFailure. Every `CHECK_INTERVAL_MS`, this list
|
// Array of items of type DecryptionFailure. Every `CHECK_INTERVAL_MS`, this list
|
||||||
// is checked for failures that happened > `GRACE_PERIOD_MS` ago. Those that did
|
// is checked for failures that happened > `GRACE_PERIOD_MS` ago. Those that did
|
||||||
// are accumulated in `failureCounts`.
|
// are accumulated in `failureCounts`.
|
||||||
failures = [];
|
public failures: DecryptionFailure[] = [];
|
||||||
|
|
||||||
// A histogram of the number of failures that will be tracked at the next tracking
|
// A histogram of the number of failures that will be tracked at the next tracking
|
||||||
// interval, split by failure error code.
|
// interval, split by failure error code.
|
||||||
failureCounts = {
|
public failureCounts: Record<string, number> = {
|
||||||
// [errorCode]: 42
|
// [errorCode]: 42
|
||||||
};
|
};
|
||||||
|
|
||||||
// Event IDs of failures that were tracked previously
|
// Event IDs of failures that were tracked previously
|
||||||
trackedEventHashMap = {
|
public trackedEventHashMap: Record<string, boolean> = {
|
||||||
// [eventId]: true
|
// [eventId]: true
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set to an interval ID when `start` is called
|
// Set to an interval ID when `start` is called
|
||||||
checkInterval = null;
|
public checkInterval: NodeJS.Timeout = null;
|
||||||
trackInterval = null;
|
public trackInterval: NodeJS.Timeout = null;
|
||||||
|
|
||||||
// Spread the load on `Analytics` by tracking at a low frequency, `TRACK_INTERVAL_MS`.
|
// Spread the load on `Analytics` by tracking at a low frequency, `TRACK_INTERVAL_MS`.
|
||||||
static TRACK_INTERVAL_MS = 60000;
|
static TRACK_INTERVAL_MS = 60000;
|
||||||
|
@ -67,7 +73,7 @@ export class DecryptionFailureTracker {
|
||||||
* @param {function?} errorCodeMapFn The function used to map error codes to the
|
* @param {function?} errorCodeMapFn The function used to map error codes to the
|
||||||
* trackedErrorCode. If not provided, the `.code` of errors will be used.
|
* trackedErrorCode. If not provided, the `.code` of errors will be used.
|
||||||
*/
|
*/
|
||||||
constructor(fn, errorCodeMapFn) {
|
constructor(private readonly fn: Fn, private readonly errorCodeMapFn?: ErrCodeMapFn) {
|
||||||
if (!fn || typeof fn !== 'function') {
|
if (!fn || typeof fn !== 'function') {
|
||||||
throw new Error('DecryptionFailureTracker requires tracking function');
|
throw new Error('DecryptionFailureTracker requires tracking function');
|
||||||
}
|
}
|
||||||
|
@ -75,9 +81,6 @@ export class DecryptionFailureTracker {
|
||||||
if (errorCodeMapFn && typeof errorCodeMapFn !== 'function') {
|
if (errorCodeMapFn && typeof errorCodeMapFn !== 'function') {
|
||||||
throw new Error('DecryptionFailureTracker second constructor argument should be a function');
|
throw new Error('DecryptionFailureTracker second constructor argument should be a function');
|
||||||
}
|
}
|
||||||
|
|
||||||
this._trackDecryptionFailure = fn;
|
|
||||||
this._mapErrorCode = errorCodeMapFn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadTrackedEventHashMap() {
|
// loadTrackedEventHashMap() {
|
||||||
|
@ -88,7 +91,7 @@ export class DecryptionFailureTracker {
|
||||||
// localStorage.setItem('mx-decryption-failure-event-id-hashes', JSON.stringify(this.trackedEventHashMap));
|
// localStorage.setItem('mx-decryption-failure-event-id-hashes', JSON.stringify(this.trackedEventHashMap));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
eventDecrypted(e, err) {
|
public eventDecrypted(e: MatrixEvent, err: MatrixError | Error): void {
|
||||||
if (err) {
|
if (err) {
|
||||||
this.addDecryptionFailure(new DecryptionFailure(e.getId(), err.code));
|
this.addDecryptionFailure(new DecryptionFailure(e.getId(), err.code));
|
||||||
} else {
|
} else {
|
||||||
|
@ -97,18 +100,18 @@ export class DecryptionFailureTracker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addDecryptionFailure(failure) {
|
public addDecryptionFailure(failure: DecryptionFailure): void {
|
||||||
this.failures.push(failure);
|
this.failures.push(failure);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeDecryptionFailuresForEvent(e) {
|
public removeDecryptionFailuresForEvent(e: MatrixEvent): void {
|
||||||
this.failures = this.failures.filter((f) => f.failedEventId !== e.getId());
|
this.failures = this.failures.filter((f) => f.failedEventId !== e.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start checking for and tracking failures.
|
* Start checking for and tracking failures.
|
||||||
*/
|
*/
|
||||||
start() {
|
public start(): void {
|
||||||
this.checkInterval = setInterval(
|
this.checkInterval = setInterval(
|
||||||
() => this.checkFailures(Date.now()),
|
() => this.checkFailures(Date.now()),
|
||||||
DecryptionFailureTracker.CHECK_INTERVAL_MS,
|
DecryptionFailureTracker.CHECK_INTERVAL_MS,
|
||||||
|
@ -123,7 +126,7 @@ export class DecryptionFailureTracker {
|
||||||
/**
|
/**
|
||||||
* Clear state and stop checking for and tracking failures.
|
* Clear state and stop checking for and tracking failures.
|
||||||
*/
|
*/
|
||||||
stop() {
|
public stop(): void {
|
||||||
clearInterval(this.checkInterval);
|
clearInterval(this.checkInterval);
|
||||||
clearInterval(this.trackInterval);
|
clearInterval(this.trackInterval);
|
||||||
|
|
||||||
|
@ -132,11 +135,11 @@ export class DecryptionFailureTracker {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark failures that occured before nowTs - GRACE_PERIOD_MS as failures that should be
|
* Mark failures that occurred before nowTs - GRACE_PERIOD_MS as failures that should be
|
||||||
* tracked. Only mark one failure per event ID.
|
* tracked. Only mark one failure per event ID.
|
||||||
* @param {number} nowTs the timestamp that represents the time now.
|
* @param {number} nowTs the timestamp that represents the time now.
|
||||||
*/
|
*/
|
||||||
checkFailures(nowTs) {
|
public checkFailures(nowTs: number): void {
|
||||||
const failuresGivenGrace = [];
|
const failuresGivenGrace = [];
|
||||||
const failuresNotReady = [];
|
const failuresNotReady = [];
|
||||||
while (this.failures.length > 0) {
|
while (this.failures.length > 0) {
|
||||||
|
@ -175,10 +178,10 @@ export class DecryptionFailureTracker {
|
||||||
|
|
||||||
const dedupedFailures = dedupedFailuresMap.values();
|
const dedupedFailures = dedupedFailuresMap.values();
|
||||||
|
|
||||||
this._aggregateFailures(dedupedFailures);
|
this.aggregateFailures(dedupedFailures);
|
||||||
}
|
}
|
||||||
|
|
||||||
_aggregateFailures(failures) {
|
private aggregateFailures(failures: DecryptionFailure[]): void {
|
||||||
for (const failure of failures) {
|
for (const failure of failures) {
|
||||||
const errorCode = failure.errorCode;
|
const errorCode = failure.errorCode;
|
||||||
this.failureCounts[errorCode] = (this.failureCounts[errorCode] || 0) + 1;
|
this.failureCounts[errorCode] = (this.failureCounts[errorCode] || 0) + 1;
|
||||||
|
@ -189,12 +192,12 @@ export class DecryptionFailureTracker {
|
||||||
* If there are failures that should be tracked, call the given trackDecryptionFailure
|
* If there are failures that should be tracked, call the given trackDecryptionFailure
|
||||||
* function with the number of failures that should be tracked.
|
* function with the number of failures that should be tracked.
|
||||||
*/
|
*/
|
||||||
trackFailures() {
|
public trackFailures(): void {
|
||||||
for (const errorCode of Object.keys(this.failureCounts)) {
|
for (const errorCode of Object.keys(this.failureCounts)) {
|
||||||
if (this.failureCounts[errorCode] > 0) {
|
if (this.failureCounts[errorCode] > 0) {
|
||||||
const trackedErrorCode = this._mapErrorCode ? this._mapErrorCode(errorCode) : errorCode;
|
const trackedErrorCode = this.errorCodeMapFn ? this.errorCodeMapFn(errorCode) : errorCode;
|
||||||
|
|
||||||
this._trackDecryptionFailure(this.failureCounts[errorCode], trackedErrorCode);
|
this.fn(this.failureCounts[errorCode], trackedErrorCode);
|
||||||
this.failureCounts[errorCode] = 0;
|
this.failureCounts[errorCode] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,11 +17,10 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, { ReactNode } from 'react';
|
||||||
import sanitizeHtml from 'sanitize-html';
|
import sanitizeHtml from 'sanitize-html';
|
||||||
import { IExtendedSanitizeOptions } from './@types/sanitize-html';
|
import cheerio from 'cheerio';
|
||||||
import * as linkify from 'linkifyjs';
|
import * as linkify from 'linkifyjs';
|
||||||
import linkifyMatrix from './linkify-matrix';
|
|
||||||
import _linkifyElement from 'linkifyjs/element';
|
import _linkifyElement from 'linkifyjs/element';
|
||||||
import _linkifyString from 'linkifyjs/string';
|
import _linkifyString from 'linkifyjs/string';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
@ -29,13 +28,15 @@ import EMOJIBASE_REGEX from 'emojibase-regex';
|
||||||
import url from 'url';
|
import url from 'url';
|
||||||
import katex from 'katex';
|
import katex from 'katex';
|
||||||
import { AllHtmlEntities } from 'html-entities';
|
import { AllHtmlEntities } from 'html-entities';
|
||||||
import SettingsStore from './settings/SettingsStore';
|
import { IContent } from 'matrix-js-sdk/src/models/event';
|
||||||
import cheerio from 'cheerio';
|
|
||||||
|
|
||||||
import {tryTransformPermalinkToLocalHref} from "./utils/permalinks/Permalinks";
|
import { IExtendedSanitizeOptions } from './@types/sanitize-html';
|
||||||
import {SHORTCODE_TO_EMOJI, getEmojiFromUnicode} from "./emoji";
|
import linkifyMatrix from './linkify-matrix';
|
||||||
|
import SettingsStore from './settings/SettingsStore';
|
||||||
|
import { tryTransformPermalinkToLocalHref } from "./utils/permalinks/Permalinks";
|
||||||
|
import { SHORTCODE_TO_EMOJI, getEmojiFromUnicode } from "./emoji";
|
||||||
import ReplyThread from "./components/views/elements/ReplyThread";
|
import ReplyThread from "./components/views/elements/ReplyThread";
|
||||||
import {mediaFromMxc} from "./customisations/Media";
|
import { mediaFromMxc } from "./customisations/Media";
|
||||||
|
|
||||||
linkifyMatrix(linkify);
|
linkifyMatrix(linkify);
|
||||||
|
|
||||||
|
@ -66,7 +67,7 @@ export const PERMITTED_URL_SCHEMES = ['http', 'https', 'ftp', 'mailto', 'magnet'
|
||||||
* need emojification.
|
* need emojification.
|
||||||
* unicodeToImage uses this function.
|
* unicodeToImage uses this function.
|
||||||
*/
|
*/
|
||||||
function mightContainEmoji(str: string) {
|
function mightContainEmoji(str: string): boolean {
|
||||||
return SURROGATE_PAIR_PATTERN.test(str) || SYMBOL_PATTERN.test(str);
|
return SURROGATE_PAIR_PATTERN.test(str) || SYMBOL_PATTERN.test(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +77,7 @@ function mightContainEmoji(str: string) {
|
||||||
* @param {String} char The emoji character
|
* @param {String} char The emoji character
|
||||||
* @return {String} The shortcode (such as :thumbup:)
|
* @return {String} The shortcode (such as :thumbup:)
|
||||||
*/
|
*/
|
||||||
export function unicodeToShortcode(char: string) {
|
export function unicodeToShortcode(char: string): string {
|
||||||
const data = getEmojiFromUnicode(char);
|
const data = getEmojiFromUnicode(char);
|
||||||
return (data && data.shortcodes ? `:${data.shortcodes[0]}:` : '');
|
return (data && data.shortcodes ? `:${data.shortcodes[0]}:` : '');
|
||||||
}
|
}
|
||||||
|
@ -87,7 +88,7 @@ export function unicodeToShortcode(char: string) {
|
||||||
* @param {String} shortcode The shortcode (such as :thumbup:)
|
* @param {String} shortcode The shortcode (such as :thumbup:)
|
||||||
* @return {String} The emoji character; null if none exists
|
* @return {String} The emoji character; null if none exists
|
||||||
*/
|
*/
|
||||||
export function shortcodeToUnicode(shortcode: string) {
|
export function shortcodeToUnicode(shortcode: string): string {
|
||||||
shortcode = shortcode.slice(1, shortcode.length - 1);
|
shortcode = shortcode.slice(1, shortcode.length - 1);
|
||||||
const data = SHORTCODE_TO_EMOJI.get(shortcode);
|
const data = SHORTCODE_TO_EMOJI.get(shortcode);
|
||||||
return data ? data.unicode : null;
|
return data ? data.unicode : null;
|
||||||
|
@ -124,13 +125,13 @@ export function processHtmlForSending(html: string): string {
|
||||||
* Given an untrusted HTML string, return a React node with an sanitized version
|
* Given an untrusted HTML string, return a React node with an sanitized version
|
||||||
* of that HTML.
|
* of that HTML.
|
||||||
*/
|
*/
|
||||||
export function sanitizedHtmlNode(insaneHtml: string) {
|
export function sanitizedHtmlNode(insaneHtml: string): ReactNode {
|
||||||
const saneHtml = sanitizeHtml(insaneHtml, sanitizeHtmlParams);
|
const saneHtml = sanitizeHtml(insaneHtml, sanitizeHtmlParams);
|
||||||
|
|
||||||
return <div dangerouslySetInnerHTML={{ __html: saneHtml }} dir="auto" />;
|
return <div dangerouslySetInnerHTML={{ __html: saneHtml }} dir="auto" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getHtmlText(insaneHtml: string) {
|
export function getHtmlText(insaneHtml: string): string {
|
||||||
return sanitizeHtml(insaneHtml, {
|
return sanitizeHtml(insaneHtml, {
|
||||||
allowedTags: [],
|
allowedTags: [],
|
||||||
allowedAttributes: {},
|
allowedAttributes: {},
|
||||||
|
@ -148,7 +149,7 @@ export function getHtmlText(insaneHtml: string) {
|
||||||
* other places we need to sanitise URLs.
|
* other places we need to sanitise URLs.
|
||||||
* @return true if permitted, otherwise false
|
* @return true if permitted, otherwise false
|
||||||
*/
|
*/
|
||||||
export function isUrlPermitted(inputUrl: string) {
|
export function isUrlPermitted(inputUrl: string): boolean {
|
||||||
try {
|
try {
|
||||||
const parsed = url.parse(inputUrl);
|
const parsed = url.parse(inputUrl);
|
||||||
if (!parsed.protocol) return false;
|
if (!parsed.protocol) return false;
|
||||||
|
@ -351,13 +352,6 @@ class HtmlHighlighter extends BaseHighlighter<string> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IContent {
|
|
||||||
format?: string;
|
|
||||||
// eslint-disable-next-line camelcase
|
|
||||||
formatted_body?: string;
|
|
||||||
body: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IOpts {
|
interface IOpts {
|
||||||
highlightLink?: string;
|
highlightLink?: string;
|
||||||
disableBigEmoji?: boolean;
|
disableBigEmoji?: boolean;
|
||||||
|
@ -367,6 +361,14 @@ interface IOpts {
|
||||||
ref?: React.Ref<any>;
|
ref?: React.Ref<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IOptsReturnNode extends IOpts {
|
||||||
|
returnString: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IOptsReturnString extends IOpts {
|
||||||
|
returnString: true;
|
||||||
|
}
|
||||||
|
|
||||||
/* turn a matrix event body into html
|
/* turn a matrix event body into html
|
||||||
*
|
*
|
||||||
* content: 'content' of the MatrixEvent
|
* content: 'content' of the MatrixEvent
|
||||||
|
@ -380,6 +382,8 @@ interface IOpts {
|
||||||
* opts.forComposerQuote: optional param to lessen the url rewriting done by sanitization, for quoting into composer
|
* opts.forComposerQuote: optional param to lessen the url rewriting done by sanitization, for quoting into composer
|
||||||
* opts.ref: React ref to attach to any React components returned (not compatible with opts.returnString)
|
* opts.ref: React ref to attach to any React components returned (not compatible with opts.returnString)
|
||||||
*/
|
*/
|
||||||
|
export function bodyToHtml(content: IContent, highlights: string[], opts: IOptsReturnString): string;
|
||||||
|
export function bodyToHtml(content: IContent, highlights: string[], opts: IOptsReturnNode): ReactNode;
|
||||||
export function bodyToHtml(content: IContent, highlights: string[], opts: IOpts = {}) {
|
export function bodyToHtml(content: IContent, highlights: string[], opts: IOpts = {}) {
|
||||||
const isHtmlMessage = content.format === "org.matrix.custom.html" && content.formatted_body;
|
const isHtmlMessage = content.format === "org.matrix.custom.html" && content.formatted_body;
|
||||||
let bodyHasEmoji = false;
|
let bodyHasEmoji = false;
|
||||||
|
@ -523,7 +527,7 @@ export function linkifyElement(element: HTMLElement, options = linkifyMatrix.opt
|
||||||
* @param {object} [options] Options for linkifyString. Default: linkifyMatrix.options
|
* @param {object} [options] Options for linkifyString. Default: linkifyMatrix.options
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function linkifyAndSanitizeHtml(dirtyHtml: string, options = linkifyMatrix.options) {
|
export function linkifyAndSanitizeHtml(dirtyHtml: string, options = linkifyMatrix.options): string {
|
||||||
return sanitizeHtml(linkifyString(dirtyHtml, options), sanitizeHtmlParams);
|
return sanitizeHtml(linkifyString(dirtyHtml, options), sanitizeHtmlParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,7 +538,7 @@ export function linkifyAndSanitizeHtml(dirtyHtml: string, options = linkifyMatri
|
||||||
* @param {Node} node
|
* @param {Node} node
|
||||||
* @returns {bool}
|
* @returns {bool}
|
||||||
*/
|
*/
|
||||||
export function checkBlockNode(node: Node) {
|
export function checkBlockNode(node: Node): boolean {
|
||||||
switch (node.nodeName) {
|
switch (node.nodeName) {
|
||||||
case "H1":
|
case "H1":
|
||||||
case "H2":
|
case "H2":
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2015, 2016 OpenMarket Ltd
|
Copyright 2015 - 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,7 +14,9 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {MatrixClientPeg} from './MatrixClientPeg';
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
|
|
||||||
|
import { MatrixClientPeg } from './MatrixClientPeg';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a room object, return the alias we should use for it,
|
* Given a room object, return the alias we should use for it,
|
||||||
|
@ -25,11 +27,11 @@ import {MatrixClientPeg} from './MatrixClientPeg';
|
||||||
* @param {Object} room The room object
|
* @param {Object} room The room object
|
||||||
* @returns {string} A display alias for the given room
|
* @returns {string} A display alias for the given room
|
||||||
*/
|
*/
|
||||||
export function getDisplayAliasForRoom(room) {
|
export function getDisplayAliasForRoom(room: Room): string {
|
||||||
return room.getCanonicalAlias() || room.getAltAliases()[0];
|
return room.getCanonicalAlias() || room.getAltAliases()[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function looksLikeDirectMessageRoom(room, myUserId) {
|
export function looksLikeDirectMessageRoom(room: Room, myUserId: string): boolean {
|
||||||
const myMembership = room.getMyMembership();
|
const myMembership = room.getMyMembership();
|
||||||
const me = room.getMember(myUserId);
|
const me = room.getMember(myUserId);
|
||||||
|
|
||||||
|
@ -48,7 +50,7 @@ export function looksLikeDirectMessageRoom(room, myUserId) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function guessAndSetDMRoom(room, isDirect) {
|
export function guessAndSetDMRoom(room: Room, isDirect: boolean): Promise<void> {
|
||||||
let newTarget;
|
let newTarget;
|
||||||
if (isDirect) {
|
if (isDirect) {
|
||||||
const guessedUserId = guessDMRoomTargetId(
|
const guessedUserId = guessDMRoomTargetId(
|
||||||
|
@ -70,7 +72,7 @@ export function guessAndSetDMRoom(room, isDirect) {
|
||||||
this room as a DM room
|
this room as a DM room
|
||||||
* @returns {object} A promise
|
* @returns {object} A promise
|
||||||
*/
|
*/
|
||||||
export function setDMRoom(roomId, userId) {
|
export function setDMRoom(roomId: string, userId: string): Promise<void> {
|
||||||
if (MatrixClientPeg.get().isGuest()) {
|
if (MatrixClientPeg.get().isGuest()) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
@ -114,7 +116,7 @@ export function setDMRoom(roomId, userId) {
|
||||||
* @param {string} myUserId User ID of the current user
|
* @param {string} myUserId User ID of the current user
|
||||||
* @returns {string} User ID of the user that the room is probably a DM with
|
* @returns {string} User ID of the user that the room is probably a DM with
|
||||||
*/
|
*/
|
||||||
function guessDMRoomTargetId(room, myUserId) {
|
function guessDMRoomTargetId(room: Room, myUserId: string): string {
|
||||||
let oldestTs;
|
let oldestTs;
|
||||||
let oldestUser;
|
let oldestUser;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2015, 2016 OpenMarket Ltd
|
Copyright 2015 - 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,9 +14,13 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {MatrixClientPeg} from "./MatrixClientPeg";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
|
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
|
import { EventType, MsgType } from "matrix-js-sdk/src/@types/event";
|
||||||
|
|
||||||
|
import { MatrixClientPeg } from "./MatrixClientPeg";
|
||||||
import shouldHideEvent from './shouldHideEvent';
|
import shouldHideEvent from './shouldHideEvent';
|
||||||
import {haveTileForEvent} from "./components/views/rooms/EventTile";
|
import { haveTileForEvent } from "./components/views/rooms/EventTile";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true iff this event arriving in a room should affect the room's
|
* Returns true iff this event arriving in a room should affect the room's
|
||||||
|
@ -25,28 +29,33 @@ import {haveTileForEvent} from "./components/views/rooms/EventTile";
|
||||||
* @param {Object} ev The event
|
* @param {Object} ev The event
|
||||||
* @returns {boolean} True if the given event should affect the unread message count
|
* @returns {boolean} True if the given event should affect the unread message count
|
||||||
*/
|
*/
|
||||||
export function eventTriggersUnreadCount(ev) {
|
export function eventTriggersUnreadCount(ev: MatrixEvent): boolean {
|
||||||
if (ev.sender && ev.sender.userId == MatrixClientPeg.get().credentials.userId) {
|
if (ev.sender && ev.sender.userId == MatrixClientPeg.get().credentials.userId) {
|
||||||
return false;
|
return false;
|
||||||
} else if (ev.getType() == 'm.room.member') {
|
}
|
||||||
|
|
||||||
|
switch (ev.getType()) {
|
||||||
|
case EventType.RoomMember:
|
||||||
|
case EventType.RoomThirdPartyInvite:
|
||||||
|
case EventType.CallAnswer:
|
||||||
|
case EventType.CallHangup:
|
||||||
|
case EventType.RoomAliases:
|
||||||
|
case EventType.RoomCanonicalAlias:
|
||||||
|
case EventType.RoomServerAcl:
|
||||||
return false;
|
return false;
|
||||||
} else if (ev.getType() == 'm.room.third_party_invite') {
|
|
||||||
return false;
|
case EventType.RoomMessage:
|
||||||
} else if (ev.getType() == 'm.call.answer' || ev.getType() == 'm.call.hangup') {
|
if (ev.getContent().msgtype === MsgType.Notice) {
|
||||||
return false;
|
|
||||||
} else if (ev.getType() == 'm.room.message' && ev.getContent().msgtype == 'm.notify') {
|
|
||||||
return false;
|
|
||||||
} else if (ev.getType() == 'm.room.aliases' || ev.getType() == 'm.room.canonical_alias') {
|
|
||||||
return false;
|
|
||||||
} else if (ev.getType() == 'm.room.server_acl') {
|
|
||||||
return false;
|
|
||||||
} else if (ev.isRedacted()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev.isRedacted()) return false;
|
||||||
return haveTileForEvent(ev);
|
return haveTileForEvent(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doesRoomHaveUnreadMessages(room) {
|
export function doesRoomHaveUnreadMessages(room: Room): boolean {
|
||||||
const myUserId = MatrixClientPeg.get().getUserId();
|
const myUserId = MatrixClientPeg.get().getUserId();
|
||||||
|
|
||||||
// get the most recent read receipt sent by our account.
|
// get the most recent read receipt sent by our account.
|
|
@ -1461,7 +1461,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
});
|
});
|
||||||
|
|
||||||
const dft = new DecryptionFailureTracker((total, errorCode) => {
|
const dft = new DecryptionFailureTracker((total, errorCode) => {
|
||||||
Analytics.trackEvent('E2E', 'Decryption failure', errorCode, total);
|
Analytics.trackEvent('E2E', 'Decryption failure', errorCode, String(total));
|
||||||
CountlyAnalytics.instance.track("decryption_failure", { errorCode }, null, { sum: total });
|
CountlyAnalytics.instance.track("decryption_failure", { errorCode }, null, { sum: total });
|
||||||
}, (errorCode) => {
|
}, (errorCode) => {
|
||||||
// Map JS-SDK error codes to tracker codes for aggregation
|
// Map JS-SDK error codes to tracker codes for aggregation
|
||||||
|
|
|
@ -23,7 +23,7 @@ import RateLimitedFunc from '../../../ratelimitedfunc';
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
|
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
|
||||||
import { UIFeature } from "../../../settings/UIFeature";
|
import { UIFeature } from "../../../settings/UIFeature";
|
||||||
import { ResizeNotifier } from "../../../utils/ResizeNotifier";
|
import ResizeNotifier from "../../../utils/ResizeNotifier";
|
||||||
import CallViewForRoom from '../voip/CallViewForRoom';
|
import CallViewForRoom from '../voip/CallViewForRoom';
|
||||||
import { objectHasDiff } from "../../../utils/objects";
|
import { objectHasDiff } from "../../../utils/objects";
|
||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
|
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
|
||||||
import { EventType } from "matrix-js-sdk/src/@types/event";
|
import { EventType } from "matrix-js-sdk/src/@types/event";
|
||||||
import { EventStatus, MatrixEvent } from "matrix-js-sdk/src/models/event";
|
import { EventStatus, MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
import { Relations } from "matrix-js-sdk/src/models/relations";
|
import { Relations } from "matrix-js-sdk/src/models/relations";
|
||||||
|
@ -29,24 +28,24 @@ import { hasText } from "../../../TextForEvent";
|
||||||
import * as sdk from "../../../index";
|
import * as sdk from "../../../index";
|
||||||
import dis from '../../../dispatcher/dispatcher';
|
import dis from '../../../dispatcher/dispatcher';
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
import {Layout} from "../../../settings/Layout";
|
import { Layout } from "../../../settings/Layout";
|
||||||
import {formatTime} from "../../../DateUtils";
|
import { formatTime } from "../../../DateUtils";
|
||||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
import { MatrixClientPeg } from '../../../MatrixClientPeg';
|
||||||
import {ALL_RULE_TYPES} from "../../../mjolnir/BanList";
|
import { ALL_RULE_TYPES } from "../../../mjolnir/BanList";
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||||
import {E2E_STATE} from "./E2EIcon";
|
import { E2E_STATE } from "./E2EIcon";
|
||||||
import {toRem} from "../../../utils/units";
|
import { toRem } from "../../../utils/units";
|
||||||
import {WidgetType} from "../../../widgets/WidgetType";
|
import { WidgetType } from "../../../widgets/WidgetType";
|
||||||
import RoomAvatar from "../avatars/RoomAvatar";
|
import RoomAvatar from "../avatars/RoomAvatar";
|
||||||
import {WIDGET_LAYOUT_EVENT_TYPE} from "../../../stores/widgets/WidgetLayoutStore";
|
import { WIDGET_LAYOUT_EVENT_TYPE } from "../../../stores/widgets/WidgetLayoutStore";
|
||||||
import {objectHasDiff} from "../../../utils/objects";
|
import { objectHasDiff } from "../../../utils/objects";
|
||||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
import Tooltip from "../elements/Tooltip";
|
import Tooltip from "../elements/Tooltip";
|
||||||
import { EditorStateTransfer } from "../../../utils/EditorStateTransfer";
|
import EditorStateTransfer from "../../../utils/EditorStateTransfer";
|
||||||
import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks';
|
import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks';
|
||||||
import {StaticNotificationState} from "../../../stores/notifications/StaticNotificationState";
|
import { StaticNotificationState } from "../../../stores/notifications/StaticNotificationState";
|
||||||
import NotificationBadge from "./NotificationBadge";
|
import NotificationBadge from "./NotificationBadge";
|
||||||
import {ComposerInsertPayload} from "../../../dispatcher/payloads/ComposerInsertPayload";
|
import { ComposerInsertPayload } from "../../../dispatcher/payloads/ComposerInsertPayload";
|
||||||
import { Action } from '../../../dispatcher/actions';
|
import { Action } from '../../../dispatcher/actions';
|
||||||
|
|
||||||
const eventTileTypes = {
|
const eventTileTypes = {
|
||||||
|
|
|
@ -22,7 +22,7 @@ import { EventType } from "matrix-js-sdk/src/@types/event";
|
||||||
|
|
||||||
import { _t, _td } from "../../../languageHandler";
|
import { _t, _td } from "../../../languageHandler";
|
||||||
import { RovingTabIndexProvider } from "../../../accessibility/RovingTabIndex";
|
import { RovingTabIndexProvider } from "../../../accessibility/RovingTabIndex";
|
||||||
import { ResizeNotifier } from "../../../utils/ResizeNotifier";
|
import ResizeNotifier from "../../../utils/ResizeNotifier";
|
||||||
import RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore";
|
import RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore";
|
||||||
import RoomViewStore from "../../../stores/RoomViewStore";
|
import RoomViewStore from "../../../stores/RoomViewStore";
|
||||||
import { ITagMap } from "../../../stores/room-list/algorithms/models";
|
import { ITagMap } from "../../../stores/room-list/algorithms/models";
|
||||||
|
|
|
@ -45,7 +45,7 @@ import { ActionPayload } from "../../../dispatcher/payloads";
|
||||||
import { Enable, Resizable } from "re-resizable";
|
import { Enable, Resizable } from "re-resizable";
|
||||||
import { Direction } from "re-resizable/lib/resizer";
|
import { Direction } from "re-resizable/lib/resizer";
|
||||||
import { polyfillTouchEvent } from "../../../@types/polyfill";
|
import { polyfillTouchEvent } from "../../../@types/polyfill";
|
||||||
import { ResizeNotifier } from "../../../utils/ResizeNotifier";
|
import ResizeNotifier from "../../../utils/ResizeNotifier";
|
||||||
import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore";
|
import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore";
|
||||||
import RoomListLayoutStore from "../../../stores/room-list/RoomListLayoutStore";
|
import RoomListLayoutStore from "../../../stores/room-list/RoomListLayoutStore";
|
||||||
import { arrayFastClone, arrayHasOrderChange } from "../../../utils/arrays";
|
import { arrayFastClone, arrayHasOrderChange } from "../../../utils/arrays";
|
||||||
|
|
|
@ -112,7 +112,7 @@ export interface IVariables {
|
||||||
[key: string]: SubstitutionValue;
|
[key: string]: SubstitutionValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Tags = Record<string, SubstitutionValue>;
|
export type Tags = Record<string, SubstitutionValue>;
|
||||||
|
|
||||||
export type TranslatedString = string | React.ReactNode;
|
export type TranslatedString = string | React.ReactNode;
|
||||||
|
|
||||||
|
|
|
@ -1479,6 +1479,11 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/counterpart/-/counterpart-0.18.1.tgz#b1b784d9e54d9879f0a8cb12f2caedab65430fe8"
|
resolved "https://registry.yarnpkg.com/@types/counterpart/-/counterpart-0.18.1.tgz#b1b784d9e54d9879f0a8cb12f2caedab65430fe8"
|
||||||
integrity sha512-PRuFlBBkvdDOtxlIASzTmkEFar+S66Ek48NVVTWMUjtJAdn5vyMSN8y6IZIoIymGpR36q2nZbIYazBWyFxL+IQ==
|
integrity sha512-PRuFlBBkvdDOtxlIASzTmkEFar+S66Ek48NVVTWMUjtJAdn5vyMSN8y6IZIoIymGpR36q2nZbIYazBWyFxL+IQ==
|
||||||
|
|
||||||
|
"@types/diff-match-patch@^1.0.32":
|
||||||
|
version "1.0.32"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/diff-match-patch/-/diff-match-patch-1.0.32.tgz#d9c3b8c914aa8229485351db4865328337a3d09f"
|
||||||
|
integrity sha512-bPYT5ECFiblzsVzyURaNhljBH2Gh1t9LowgUwciMrNAhFewLkHT2H0Mto07Y4/3KCOGZHRQll3CTtQZ0X11D/A==
|
||||||
|
|
||||||
"@types/events@^3.0.0":
|
"@types/events@^3.0.0":
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
|
resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
|
||||||
|
|
Loading…
Reference in a new issue